c++: Fix up handling of captured vars in lambdas in OpenMP clauses [PR93931]
authorJakub Jelinek <jakub@redhat.com>
Thu, 19 Mar 2020 11:22:47 +0000 (12:22 +0100)
committerJakub Jelinek <jakub@redhat.com>
Thu, 19 Mar 2020 11:22:47 +0000 (12:22 +0100)
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.

gcc/cp/ChangeLog
gcc/cp/cp-gimplify.c
gcc/cp/parser.c
libgomp/ChangeLog
libgomp/testsuite/libgomp.c++/pr93931.C [new file with mode: 0644]

index bb5f77f4db16e43603a5830f8e9ed1cac7b2d914..b5d429b5c3572a580ba8c0540e9f4ab8aa6b3465 100644 (file)
@@ -1,3 +1,11 @@
+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-18  Nathan Sidwell  <nathan@acm.org>
 
        PR c++/94147 - mangling of lambdas assigned to globals
index 23a25e5797531db57d2f2b4a5f0bce3dc3a80692..87c7e394b014126b4e1ff70488a0e9df31ab21fa 100644 (file)
@@ -2260,12 +2260,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.  */
index 198ab975e562fa1a36e72dd84cec648d6189c94c..cbd5510a8fb3e4fe67b565a3751bdfd2d5846d02 100644 (file)
@@ -34059,6 +34059,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)
index 4d3a4f32ecee1970267fed03b8e46e28bf62b2fa..f7cd873f498cf44c06e72c3a868d6b73f633779a 100644 (file)
@@ -1,3 +1,8 @@
+2020-03-19  Jakub Jelinek  <jakub@redhat.com>
+
+       PR c++/93931
+       * testsuite/libgomp.c++/pr93931.C: New test.
+
 2020-03-19  Tobias Burnus  <tobias@codesourcery.com>
 
        * testsuite/libgomp.c-c++-common/function-not-offloaded.c: Add
diff --git a/libgomp/testsuite/libgomp.c++/pr93931.C b/libgomp/testsuite/libgomp.c++/pr93931.C
new file mode 100644 (file)
index 0000000..4d4232e
--- /dev/null
@@ -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 ();
+}