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>
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)
{
fndecl = push_template_decl (fndecl);
if (block_scope)
- {
- if (!processing_template_decl)
- pushdecl (fndecl);
- }
+ pushdecl (fndecl);
else if (current_class_type)
{
if (cp == NULL)
--- /dev/null
+// 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;
+}
--- /dev/null
+// PR c++/119864
+// { dg-additional-options "-fmodules -fopenmp" }
+
+import p1;
+
+int main()
+{
+ T<1u> v[3u] = {};
+
+ T s = sum(v, 3u);
+}