re PR c++/60228 (ICE using lambda in #pragma omp declare reduction)
authorJakub Jelinek <jakub@redhat.com>
Fri, 29 Nov 2019 09:08:46 +0000 (10:08 +0100)
committerJakub Jelinek <jakub@gcc.gnu.org>
Fri, 29 Nov 2019 09:08:46 +0000 (10:08 +0100)
PR c++/60228
* parser.c (cp_parser_omp_declare_reduction_exprs): If
processing_template_decl, wrap the combiner or initializer
into EXPR_STMT.
* decl.c (start_preparsed_function): Don't start a lambda scope
for DECL_OMP_DECLARE_REDUCTION_P functions.
(finish_function): Don't finish a lambda scope for
DECL_OMP_DECLARE_REDUCTION_P functions, nor cp_fold_function
them nor cp_genericize them.
* mangle.c (decl_mangling_context): Look through
DECL_OMP_DECLARE_REDUCTION_P functions.
* semantics.c (expand_or_defer_fn_1): For DECL_OMP_DECLARE_REDUCTION_P
functions, use tentative linkage, don't keep their bodies with
-fkeep-inline-functions and return false at the end.

* g++.dg/gomp/openmp-simd-2.C: Don't expect bodies for
DECL_OMP_DECLARE_REDUCTION_P functions.

* testsuite/libgomp.c++/udr-20.C: New test.
* testsuite/libgomp.c++/udr-21.C: New test.

From-SVN: r278831

gcc/cp/ChangeLog
gcc/cp/decl.c
gcc/cp/mangle.c
gcc/cp/parser.c
gcc/cp/semantics.c
gcc/testsuite/ChangeLog
gcc/testsuite/g++.dg/gomp/openmp-simd-2.C
libgomp/ChangeLog
libgomp/testsuite/libgomp.c++/udr-20.C [new file with mode: 0644]
libgomp/testsuite/libgomp.c++/udr-21.C [new file with mode: 0644]

index 8b71f02cf10c89830e366f47656007cc50e62661..3a6bf059a2df992d700409ba686d68d459e372d0 100644 (file)
@@ -1,3 +1,20 @@
+2019-11-29  Jakub Jelinek  <jakub@redhat.com>
+
+       PR c++/60228
+       * parser.c (cp_parser_omp_declare_reduction_exprs): If
+       processing_template_decl, wrap the combiner or initializer
+       into EXPR_STMT.
+       * decl.c (start_preparsed_function): Don't start a lambda scope
+       for DECL_OMP_DECLARE_REDUCTION_P functions.
+       (finish_function): Don't finish a lambda scope for
+       DECL_OMP_DECLARE_REDUCTION_P functions, nor cp_fold_function
+       them nor cp_genericize them.
+       * mangle.c (decl_mangling_context): Look through
+       DECL_OMP_DECLARE_REDUCTION_P functions.
+       * semantics.c (expand_or_defer_fn_1): For DECL_OMP_DECLARE_REDUCTION_P
+       functions, use tentative linkage, don't keep their bodies with
+       -fkeep-inline-functions and return false at the end.
+
 2019-11-28  Jakub Jelinek  <jakub@redhat.com>
 
        PR c++/92695
index 7d5bc914d2d407e4409714906bf57da12ff35efc..81d73433547e3edb6d74838fc046dc9267a6515e 100644 (file)
@@ -16318,7 +16318,8 @@ start_preparsed_function (tree decl1, tree attrs, int flags)
       && !implicit_default_ctor_p (decl1))
     cp_ubsan_maybe_initialize_vtbl_ptrs (current_class_ptr);
 
-  start_lambda_scope (decl1);
+  if (!DECL_OMP_DECLARE_REDUCTION_P (decl1))
+    start_lambda_scope (decl1);
 
   return true;
 }
@@ -16703,7 +16704,8 @@ finish_function (bool inline_p)
   if (fndecl == NULL_TREE)
     return error_mark_node;
 
-  finish_lambda_scope ();
+  if (!DECL_OMP_DECLARE_REDUCTION_P (fndecl))
+    finish_lambda_scope ();
 
   if (c_dialect_objc ())
     objc_finish_function ();
@@ -16845,7 +16847,9 @@ finish_function (bool inline_p)
     invoke_plugin_callbacks (PLUGIN_PRE_GENERICIZE, fndecl);
 
   /* Perform delayed folding before NRV transformation.  */
-  if (!processing_template_decl && !DECL_IMMEDIATE_FUNCTION_P (fndecl))
+  if (!processing_template_decl
+      && !DECL_IMMEDIATE_FUNCTION_P (fndecl)
+      && !DECL_OMP_DECLARE_REDUCTION_P (fndecl))
     cp_fold_function (fndecl);
 
   /* Set up the named return value optimization, if we can.  Candidate
@@ -16958,7 +16962,9 @@ finish_function (bool inline_p)
     do_warn_unused_parameter (fndecl);
 
   /* Genericize before inlining.  */
-  if (!processing_template_decl && !DECL_IMMEDIATE_FUNCTION_P (fndecl))
+  if (!processing_template_decl
+      && !DECL_IMMEDIATE_FUNCTION_P (fndecl)
+      && !DECL_OMP_DECLARE_REDUCTION_P (fndecl))
     cp_genericize (fndecl);
 
  cleanup:
index 0ac04514e8e8a38b6d02f7947a571810afd645cf..88c5fa2c622e419b91fe086b88215fed171840e1 100644 (file)
@@ -873,7 +873,16 @@ decl_mangling_context (tree decl)
   else if (template_type_parameter_p (decl))
      /* template type parms have no mangling context.  */
       return NULL_TREE;
-  return CP_DECL_CONTEXT (decl);
+
+  tcontext = CP_DECL_CONTEXT (decl);
+
+  /* Ignore the artificial declare reduction functions.  */
+  if (tcontext
+      && TREE_CODE (tcontext) == FUNCTION_DECL
+      && DECL_OMP_DECLARE_REDUCTION_P (tcontext))
+    return decl_mangling_context (tcontext);
+
+  return tcontext;
 }
 
 /* <name> ::= <unscoped-name>
index ed2441644f1a314c1969928325e17340f91be06b..fb03002262754caaa5ccd750ce231006a8a6f037 100644 (file)
@@ -41244,6 +41244,8 @@ cp_parser_omp_declare_reduction_exprs (tree fndecl, cp_parser *parser)
   combiner = cp_parser_expression (parser);
   finish_expr_stmt (combiner);
   block = finish_omp_structured_block (block);
+  if (processing_template_decl)
+    block = build_stmt (input_location, EXPR_STMT, block);
   add_stmt (block);
 
   if (!cp_parser_require (parser, CPP_CLOSE_PAREN, RT_CLOSE_PAREN))
@@ -41348,6 +41350,8 @@ cp_parser_omp_declare_reduction_exprs (tree fndecl, cp_parser *parser)
 
       block = finish_omp_structured_block (block);
       cp_walk_tree (&block, cp_remove_omp_priv_cleanup_stmt, omp_priv, NULL);
+      if (processing_template_decl)
+       block = build_stmt (input_location, EXPR_STMT, block);
       add_stmt (block);
 
       if (ctor)
index 4a5479cb4b4eba13330a844d0b848c672d672808..17de39eea5489af212e46fb30dfe047e19dd0498 100644 (file)
@@ -4417,7 +4417,9 @@ expand_or_defer_fn_1 (tree fn)
       if (DECL_INTERFACE_KNOWN (fn))
        /* We've already made a decision as to how this function will
           be handled.  */;
-      else if (!at_eof || DECL_IMMEDIATE_FUNCTION_P (fn))
+      else if (!at_eof
+              || DECL_IMMEDIATE_FUNCTION_P (fn)
+              || DECL_OMP_DECLARE_REDUCTION_P (fn))
        tentative_decl_linkage (fn);
       else
        import_export_decl (fn);
@@ -4429,6 +4431,7 @@ expand_or_defer_fn_1 (tree fn)
       if (DECL_DECLARED_INLINE_P (fn)
          && !DECL_REALLY_EXTERN (fn)
          && !DECL_IMMEDIATE_FUNCTION_P (fn)
+         && !DECL_OMP_DECLARE_REDUCTION_P (fn)
          && (flag_keep_inline_functions
              || (flag_keep_inline_dllexport
                  && lookup_attribute ("dllexport", DECL_ATTRIBUTES (fn)))))
@@ -4461,6 +4464,9 @@ expand_or_defer_fn_1 (tree fn)
       return false;
     }
 
+  if (DECL_OMP_DECLARE_REDUCTION_P (fn))
+    return false;
+
   return true;
 }
 
index e0c37ddba900a2cad43bf4abc2a11c4a98b6d9a1..45c9de34b61120a01100501da99873a5b86b5af9 100644 (file)
@@ -1,3 +1,9 @@
+2019-11-29  Jakub Jelinek  <jakub@redhat.com>
+
+       PR c++/60228
+       * g++.dg/gomp/openmp-simd-2.C: Don't expect bodies for
+       DECL_OMP_DECLARE_REDUCTION_P functions.
+
 2019-11-29  Martin Liska  <mliska@suse.cz>
 
        PR lto/91574
index e31c1ebecf9f02fb66da83ac4c39eea49a6bf110..e66806845b7d245e4fdb995cba355aa5725575fc 100644 (file)
@@ -36,8 +36,6 @@ void bar(int n, float *a, float *b)
     a[i] = b[i];
 }
 
-/* { dg-final { scan-tree-dump-times "Function void omp declare reduction operator\\+" 1 "original" } } */
-/* { dg-final { scan-tree-dump-times "Function void omp declare reduction foo" 2 "original" } } */
 /* { dg-final { scan-tree-dump-times "pragma omp simd reduction\\(u\\) reduction\\(t\\) reduction\\(\\+:s\\) aligned\\(a:32\\)" 1 "original" } } */
 /* { dg-final { scan-tree-dump-times "pragma omp simd safelen\\(64\\)" 1 "original" } } */
 /* { dg-final { scan-tree-dump-not "omp parallel" "original" } } */
index d8d76ba3ce801c19dd39b3dc1203ebb609f32e67..abbd47eb517f597533074787ebe0f3e4d9a2f8b2 100644 (file)
@@ -1,3 +1,9 @@
+2019-11-29  Jakub Jelinek  <jakub@redhat.com>
+
+       PR c++/60228
+       * testsuite/libgomp.c++/udr-20.C: New test.
+       * testsuite/libgomp.c++/udr-21.C: New test.
+
 2019-11-27  Thomas Schwinge  <thomas@codesourcery.com>
 
        * testsuite/lib/libgomp.exp
diff --git a/libgomp/testsuite/libgomp.c++/udr-20.C b/libgomp/testsuite/libgomp.c++/udr-20.C
new file mode 100644 (file)
index 0000000..48d4fea
--- /dev/null
@@ -0,0 +1,108 @@
+// PR c++/60228
+// { dg-additional-options "-std=c++11" }
+
+extern "C" void abort ();
+
+struct A
+{
+  typedef int T;
+  #pragma omp declare reduction (x : T : omp_out += omp_in + [](){ return 0; }()) initializer (omp_priv = [](){ return 0; }())
+  static void foo ();
+};
+
+template <typename T>
+struct B
+{
+  #pragma omp declare reduction (x : T : omp_out += omp_in + [](){ return T (0); }()) initializer (omp_priv = [](){ return T (0); }())
+  static void foo ();
+};
+
+void
+A::foo ()
+{
+  int r = 0, s = 0;
+  #pragma omp parallel for reduction (x : r, s)
+  for (int i = 0; i < 64; i++)
+    {
+      r++;
+      s += i;
+    }
+  if (r != 64 || s != (64 * 63) / 2)
+    abort ();
+}
+
+template <typename T>
+void
+B<T>::foo ()
+{
+  T r = 0, s = 0;
+  #pragma omp parallel for reduction (x : r, s)
+  for (int i = 0; i < 64; i++)
+    {
+      r++;
+      s += i;
+    }
+  if (r != 64 || s != (64 * 63) / 2)
+    abort ();
+}
+
+int
+main ()
+{
+  A::foo ();
+  B<long>::foo ();
+}
+// PR c++/60228
+// { dg-additional-options "-std=c++11" }
+
+extern "C" void abort ();
+
+struct A
+{
+  typedef int T;
+  #pragma omp declare reduction (x : T : omp_out += omp_in + [](){ return 0; }()) initializer (omp_priv = [](){ return 0; }())
+  static void foo ();
+};
+
+template <typename T>
+struct B
+{
+  #pragma omp declare reduction (x : T : omp_out += omp_in + [](){ return T (0); }()) initializer (omp_priv = [](){ return T (0); }())
+  static void foo ();
+};
+
+void
+A::foo ()
+{
+  int r = 0, s = 0;
+  #pragma omp parallel for reduction (x : r, s)
+  for (int i = 0; i < 64; i++)
+    {
+      r++;
+      s += i;
+    }
+  if (r != 64 || s != (64 * 63) / 2)
+    abort ();
+}
+
+template <typename T>
+void
+B<T>::foo ()
+{
+  T r = 0, s = 0;
+  #pragma omp parallel for reduction (x : r, s)
+  for (int i = 0; i < 64; i++)
+    {
+      r++;
+      s += i;
+    }
+  if (r != 64 || s != (64 * 63) / 2)
+    abort ();
+}
+
+int
+main ()
+{
+  A::foo ();
+  B<long>::foo ();
+}
diff --git a/libgomp/testsuite/libgomp.c++/udr-21.C b/libgomp/testsuite/libgomp.c++/udr-21.C
new file mode 100644 (file)
index 0000000..1ecaf47
--- /dev/null
@@ -0,0 +1,108 @@
+// PR c++/60228
+// { dg-additional-options "-std=c++11" }
+
+extern "C" void abort ();
+
+struct A
+{
+  typedef int T;
+  #pragma omp declare reduction (y : T : [&omp_out, &omp_in]() { omp_out += omp_in; return 0; }()) initializer (omp_priv = [omp_orig]() { return omp_orig; }())
+  static void foo ();
+};
+
+template <typename T>
+struct B
+{
+  #pragma omp declare reduction (y : T : [&omp_out, &omp_in]() { omp_out += omp_in; return 0; }()) initializer (omp_priv = [omp_orig]() { return omp_orig; }())
+  static void foo ();
+};
+
+void
+A::foo ()
+{
+  int r = 0, s = 0;
+  #pragma omp parallel for reduction (y : r, s)
+  for (int i = 0; i < 64; i++)
+    {
+      r++;
+      s += i;
+    }
+  if (r != 64 || s != (64 * 63) / 2)
+    abort ();
+}
+
+template <typename T>
+void
+B<T>::foo ()
+{
+  T r = 0, s = 0;
+  #pragma omp parallel for reduction (y : r, s)
+  for (int i = 0; i < 64; i++)
+    {
+      r++;
+      s += i;
+    }
+  if (r != 64 || s != (64 * 63) / 2)
+    abort ();
+}
+
+int
+main ()
+{
+  A::foo ();
+  B<short>::foo ();
+}
+// PR c++/60228
+// { dg-additional-options "-std=c++11" }
+
+extern "C" void abort ();
+
+struct A
+{
+  typedef int T;
+  #pragma omp declare reduction (y : T : [&omp_out, &omp_in]() { omp_out += omp_in; return 0; }()) initializer (omp_priv = [omp_orig]() { return omp_orig; }())
+  static void foo ();
+};
+
+template <typename T>
+struct B
+{
+  #pragma omp declare reduction (y : T : [&omp_out, &omp_in]() { omp_out += omp_in; return 0; }()) initializer (omp_priv = [omp_orig]() { return omp_orig; }())
+  static void foo ();
+};
+
+void
+A::foo ()
+{
+  int r = 0, s = 0;
+  #pragma omp parallel for reduction (y : r, s)
+  for (int i = 0; i < 64; i++)
+    {
+      r++;
+      s += i;
+    }
+  if (r != 64 || s != (64 * 63) / 2)
+    abort ();
+}
+
+template <typename T>
+void
+B<T>::foo ()
+{
+  T r = 0, s = 0;
+  #pragma omp parallel for reduction (y : r, s)
+  for (int i = 0; i < 64; i++)
+    {
+      r++;
+      s += i;
+    }
+  if (r != 64 || s != (64 * 63) / 2)
+    abort ();
+}
+
+int
+main ()
+{
+  A::foo ();
+  B<short>::foo ();
+}