]> git.ipfire.org Git - thirdparty/gcc.git/commitdiff
c++: Support template block-scope OpenMP user-defined reductions in modules [PR119864]
authorNathaniel Shead <nathanieloshead@gmail.com>
Sat, 15 Nov 2025 04:27:13 +0000 (15:27 +1100)
committerNathaniel Shead <nathanieloshead@gmail.com>
Sun, 30 Nov 2025 00:01:09 +0000 (11:01 +1100)
There were two issues preventing OpenMP reductions of UDTs from working
in modules.

Firstly, we were failing a number of checking asserts in the streaming
logic because the declaration is a DECL_LOCAL_DECL_P but was not
correctly added to the BLOCK of the function template.  This is because
cp_parser_omp_declare_reduction only called pushdecl when
!processing_template_decl; correcting this fixed this issue.

The second issue is that modules saw this as a function definition and
so attempted to call allocate_struct_function on it, which crashes.
Given that these reduction functions don't really behave like real
function definitions in any other way, I think the cleanest solution is
to just skip all the function definition post-processing in modules;
this seems to work to get the test functioning correctly, from what I
can see.

PR c++/119864

gcc/cp/ChangeLog:

* module.cc (trees_in::read_function_def): Don't call
post_process on OpenMP UDT reductions.
* parser.cc (cp_parser_omp_declare_reduction): Call push_decl
for block_scope, even when processing_template_decl.

gcc/testsuite/ChangeLog:

* g++.dg/modules/omp-4_a.C: New test.
* g++.dg/modules/omp-4_b.C: New test.

Signed-off-by: Nathaniel Shead <nathanieloshead@gmail.com>
Reviewed-by: Jakub Jelinek <jakub@redhat.com>
Reviewed-by: Jason Merrill <jason@redhat.com>
gcc/cp/module.cc
gcc/cp/parser.cc
gcc/testsuite/g++.dg/modules/omp-4_a.C [new file with mode: 0644]
gcc/testsuite/g++.dg/modules/omp-4_b.C [new file with mode: 0644]

index 92449286a84262e5907eabff7ee39b079ac64daa..ea22cef24a5b944efd008904c2a4f2cdfcc33e7a 100644 (file)
@@ -13015,7 +13015,13 @@ trees_in::read_function_def (tree decl, tree maybe_template)
        SET_DECL_FRIEND_CONTEXT (decl, context);
       if (cexpr.decl)
        register_constexpr_fundef (cexpr);
-      post_process (pdata);
+
+      if (DECL_LOCAL_DECL_P (decl))
+       /* Block-scope OMP UDRs aren't real functions, and don't need a
+          function structure to be allocated or to be expanded.  */
+       gcc_checking_assert (DECL_OMP_DECLARE_REDUCTION_P (decl));
+      else
+       post_process (pdata);
     }
   else if (maybe_dup)
     {
index de11798b8bdc1d2309753f51ed932ee468b821f0..786212713dbc61722c369f9032a791dddf4a45bd 100644 (file)
@@ -53737,10 +53737,7 @@ cp_parser_omp_declare_reduction (cp_parser *parser, cp_token *pragma_tok,
        fndecl = push_template_decl (fndecl);
 
       if (block_scope)
-       {
-         if (!processing_template_decl)
-           pushdecl (fndecl);
-       }
+       pushdecl (fndecl);
       else if (current_class_type)
        {
          if (cp == NULL)
diff --git a/gcc/testsuite/g++.dg/modules/omp-4_a.C b/gcc/testsuite/g++.dg/modules/omp-4_a.C
new file mode 100644 (file)
index 0000000..948966e
--- /dev/null
@@ -0,0 +1,30 @@
+// PR c++/119864
+// { dg-additional-options "-fmodules -fopenmp" }
+// { dg-module-cmi p1 }
+
+export module p1;
+
+export
+template<unsigned>
+struct T
+{
+  double d;
+
+  T &operator +=(T const &x) { d += x.d; return *this; }
+};
+
+export
+template<unsigned d>
+T<d> sum(T<d> const *p, unsigned N)
+{
+T<d> Sum = {};
+
+#pragma omp declare reduction(Op: T<d>: omp_out += omp_in) initializer(omp_priv = {})
+#pragma omp parallel for reduction(Op: Sum)
+for (unsigned i = 0u; i < N; ++i)
+  {
+  Sum += *p;
+  ++p;
+  }
+return Sum;
+}
diff --git a/gcc/testsuite/g++.dg/modules/omp-4_b.C b/gcc/testsuite/g++.dg/modules/omp-4_b.C
new file mode 100644 (file)
index 0000000..c1ca279
--- /dev/null
@@ -0,0 +1,11 @@
+// PR c++/119864
+// { dg-additional-options "-fmodules -fopenmp" }
+
+import p1;
+
+int main()
+{
+  T<1u> v[3u] = {};
+
+  T s = sum(v, 3u);
+}