From b3f44388f3bb9b42553ea516984db4c4d4baa5bc Mon Sep 17 00:00:00 2001 From: Jakub Jelinek Date: Fri, 29 Nov 2019 10:08:46 +0100 Subject: [PATCH] re PR c++/60228 (ICE using lambda in #pragma omp declare reduction) 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 | 17 ++++ gcc/cp/decl.c | 14 ++- gcc/cp/mangle.c | 11 ++- gcc/cp/parser.c | 4 + gcc/cp/semantics.c | 8 +- gcc/testsuite/ChangeLog | 6 ++ gcc/testsuite/g++.dg/gomp/openmp-simd-2.C | 2 - libgomp/ChangeLog | 6 ++ libgomp/testsuite/libgomp.c++/udr-20.C | 108 ++++++++++++++++++++++ libgomp/testsuite/libgomp.c++/udr-21.C | 108 ++++++++++++++++++++++ 10 files changed, 276 insertions(+), 8 deletions(-) create mode 100644 libgomp/testsuite/libgomp.c++/udr-20.C create mode 100644 libgomp/testsuite/libgomp.c++/udr-21.C diff --git a/gcc/cp/ChangeLog b/gcc/cp/ChangeLog index 8b71f02cf10..3a6bf059a2d 100644 --- a/gcc/cp/ChangeLog +++ b/gcc/cp/ChangeLog @@ -1,3 +1,20 @@ +2019-11-29 Jakub Jelinek + + 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 PR c++/92695 diff --git a/gcc/cp/decl.c b/gcc/cp/decl.c index 7d5bc914d2d..81d73433547 100644 --- a/gcc/cp/decl.c +++ b/gcc/cp/decl.c @@ -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: diff --git a/gcc/cp/mangle.c b/gcc/cp/mangle.c index 0ac04514e8e..88c5fa2c622 100644 --- a/gcc/cp/mangle.c +++ b/gcc/cp/mangle.c @@ -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; } /* ::= diff --git a/gcc/cp/parser.c b/gcc/cp/parser.c index ed2441644f1..fb030022627 100644 --- a/gcc/cp/parser.c +++ b/gcc/cp/parser.c @@ -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) diff --git a/gcc/cp/semantics.c b/gcc/cp/semantics.c index 4a5479cb4b4..17de39eea54 100644 --- a/gcc/cp/semantics.c +++ b/gcc/cp/semantics.c @@ -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; } diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog index e0c37ddba90..45c9de34b61 100644 --- a/gcc/testsuite/ChangeLog +++ b/gcc/testsuite/ChangeLog @@ -1,3 +1,9 @@ +2019-11-29 Jakub Jelinek + + 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 PR lto/91574 diff --git a/gcc/testsuite/g++.dg/gomp/openmp-simd-2.C b/gcc/testsuite/g++.dg/gomp/openmp-simd-2.C index e31c1ebecf9..e66806845b7 100644 --- a/gcc/testsuite/g++.dg/gomp/openmp-simd-2.C +++ b/gcc/testsuite/g++.dg/gomp/openmp-simd-2.C @@ -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" } } */ diff --git a/libgomp/ChangeLog b/libgomp/ChangeLog index d8d76ba3ce8..abbd47eb517 100644 --- a/libgomp/ChangeLog +++ b/libgomp/ChangeLog @@ -1,3 +1,9 @@ +2019-11-29 Jakub Jelinek + + PR c++/60228 + * testsuite/libgomp.c++/udr-20.C: New test. + * testsuite/libgomp.c++/udr-21.C: New test. + 2019-11-27 Thomas Schwinge * 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 index 00000000000..48d4feab7e5 --- /dev/null +++ b/libgomp/testsuite/libgomp.c++/udr-20.C @@ -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 +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 +void +B::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::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 +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 +void +B::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::foo (); +} diff --git a/libgomp/testsuite/libgomp.c++/udr-21.C b/libgomp/testsuite/libgomp.c++/udr-21.C new file mode 100644 index 00000000000..1ecaf473d1d --- /dev/null +++ b/libgomp/testsuite/libgomp.c++/udr-21.C @@ -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 +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 +void +B::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::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 +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 +void +B::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::foo (); +} -- 2.30.2