Bootstrapped and regtested on x86_64-pc-linux-gnu, OK for trunk?
-- >8 --
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 <[email protected]>
---
gcc/cp/module.cc | 8 ++++++-
gcc/cp/parser.cc | 5 +----
gcc/testsuite/g++.dg/modules/omp-4_a.C | 30 ++++++++++++++++++++++++++
gcc/testsuite/g++.dg/modules/omp-4_b.C | 11 ++++++++++
4 files changed, 49 insertions(+), 5 deletions(-)
create mode 100644 gcc/testsuite/g++.dg/modules/omp-4_a.C
create mode 100644 gcc/testsuite/g++.dg/modules/omp-4_b.C
diff --git a/gcc/cp/module.cc b/gcc/cp/module.cc
index ccabd640757..66c7322a6e6 100644
--- a/gcc/cp/module.cc
+++ b/gcc/cp/module.cc
@@ -12985,7 +12985,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)
{
diff --git a/gcc/cp/parser.cc b/gcc/cp/parser.cc
index 06cba31ada6..2f8d7712dc6 100644
--- a/gcc/cp/parser.cc
+++ b/gcc/cp/parser.cc
@@ -53170,10 +53170,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
index 00000000000..948966e657f
--- /dev/null
+++ b/gcc/testsuite/g++.dg/modules/omp-4_a.C
@@ -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
index 00000000000..c1ca279a97e
--- /dev/null
+++ b/gcc/testsuite/g++.dg/modules/omp-4_b.C
@@ -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);
+}
--
2.51.0