c++: Fix up handling of captured vars in lambdas in OpenMP clauses [PR93931]

Without the parser.c change we were ICEing on the testcase, because while the
uses of the captured vars inside of the constructs were replaced with capture
proxy decls, we didn't do that for decls in OpenMP clauses.

With that fixed, we don't ICE anymore, but the testcase is miscompiled and FAILs
at runtime.  This is because the capture proxy decls have DECL_VALUE_EXPR and
during gimplification we were gimplifying those to their DECL_VALUE_EXPRs.
That is fine for shared vars, but for privatized ones we must not do that.
So that is what the cp-gimplify.c changes do.  Had to add a DECL_CONTEXT check
before calling is_capture_proxy because some VAR_DECLs don't have DECL_CONTEXT
set (yet) and is_capture_proxy relies on that being non-NULL always.

2020-03-19  Jakub Jelinek  <jakub@redhat.com>

	PR c++/93931
	* parser.c (cp_parser_omp_var_list_no_open): Call process_outer_var_ref
	on outer_automatic_var_p decls.
	* cp-gimplify.c (cxx_omp_disregard_value_expr): Return true also for
	capture proxy decls.

	* testsuite/libgomp.c++/pr93931.C: New test.
This commit is contained in:
Jakub Jelinek 2020-03-19 12:22:47 +01:00
parent 8db876e9c0
commit 484206967f
5 changed files with 149 additions and 6 deletions

View File

@ -1,6 +1,14 @@
2020-04-07 Jakub Jelinek <jakub@redhat.com>
Backported from mainline
2020-03-19 Jakub Jelinek <jakub@redhat.com>
PR c++/93931
* parser.c (cp_parser_omp_var_list_no_open): Call process_outer_var_ref
on outer_automatic_var_p decls.
* cp-gimplify.c (cxx_omp_disregard_value_expr): Return true also for
capture proxy decls.
2020-03-17 Jakub Jelinek <jakub@redhat.com>
PR c++/90995

View File

@ -2192,12 +2192,17 @@ cxx_omp_finish_clause (tree c, gimple_seq *)
bool
cxx_omp_disregard_value_expr (tree decl, bool shared)
{
return !shared
&& VAR_P (decl)
&& DECL_HAS_VALUE_EXPR_P (decl)
&& DECL_ARTIFICIAL (decl)
&& DECL_LANG_SPECIFIC (decl)
&& DECL_OMP_PRIVATIZED_MEMBER (decl);
if (shared)
return false;
if (VAR_P (decl)
&& DECL_HAS_VALUE_EXPR_P (decl)
&& DECL_ARTIFICIAL (decl)
&& DECL_LANG_SPECIFIC (decl)
&& DECL_OMP_PRIVATIZED_MEMBER (decl))
return true;
if (VAR_P (decl) && DECL_CONTEXT (decl) && is_capture_proxy (decl))
return true;
return false;
}
/* Fold expression X which is used as an rvalue if RVAL is true. */

View File

@ -32563,6 +32563,8 @@ cp_parser_omp_var_list_no_open (cp_parser *parser, enum omp_clause_code kind,
token->location);
}
}
if (outer_automatic_var_p (decl))
decl = process_outer_var_ref (decl, tf_warning_or_error);
if (decl == error_mark_node)
;
else if (kind != 0)

View File

@ -1,3 +1,11 @@
2020-04-07 Jakub Jelinek <jakub@redhat.com>
Backported from mainline
2020-03-19 Jakub Jelinek <jakub@redhat.com>
PR c++/93931
* testsuite/libgomp.c++/pr93931.C: New test.
2020-03-17 Jakub Jelinek <jakub@redhat.com>
Backported from mainline

View File

@ -0,0 +1,120 @@
// PR c++/93931
// { dg-do run }
// { dg-options "-O2 -std=c++14" }
extern "C" void abort ();
void
sink (int &x)
{
int *volatile p;
p = &x;
(*p)++;
}
int
foo ()
{
int r = 0;
[&r] () {
#pragma omp parallel for reduction(+ : r)
for (int i = 0; i < 1024; ++i)
r += i;
} ();
return r;
}
int
bar ()
{
int l = 0;
[&l] () {
#pragma omp parallel for lastprivate (l)
for (int i = 0; i < 1024; ++i)
l = i;
} ();
return l;
}
void
baz ()
{
int f = 18;
[&f] () {
#pragma omp parallel for firstprivate (f)
for (int i = 0; i < 1024; ++i)
{
sink (f);
f += 3;
sink (f);
if (f != 23)
abort ();
sink (f);
f -= 7;
sink (f);
}
} ();
if (f != 18)
abort ();
}
int
qux ()
{
int r = 0;
[&] () {
#pragma omp parallel for reduction(+ : r)
for (int i = 0; i < 1024; ++i)
r += i;
} ();
return r;
}
int
corge ()
{
int l = 0;
[&] () {
#pragma omp parallel for lastprivate (l)
for (int i = 0; i < 1024; ++i)
l = i;
} ();
return l;
}
void
garply ()
{
int f = 18;
[&] () {
#pragma omp parallel for firstprivate (f)
for (int i = 0; i < 1024; ++i)
{
sink (f);
f += 3;
sink (f);
if (f != 23)
abort ();
sink (f);
f -= 7;
sink (f);
}
} ();
if (f != 18)
abort ();
}
int
main ()
{
if (foo () != 1024 * 1023 / 2)
abort ();
if (bar () != 1023)
abort ();
baz ();
if (qux () != 1024 * 1023 / 2)
abort ();
if (corge () != 1023)
abort ();
garply ();
}