From 749476b4be1f8ddf482910f907a5b56eb5f3e138 Mon Sep 17 00:00:00 2001 From: Nathan Sidwell Date: Wed, 9 Sep 2020 12:29:05 -0700 Subject: [PATCH] c++: omp reduction cleanups omp reductions are modeled as nested functions, which is a thing C++ doesn't have. Leading to much confusion until I figured out what was happening. Not helped by some duplicate code and inconsistencies in the dependent and non-dependent paths. This patch removes the parser duplication and fixes up some bookkeeping. Added some asserts and comments too. gcc/cp/ * parser.c (cp_parser_omp_declare_reduction): Refactor to avoid code duplication. Update DECL_TI_TEMPLATE's context. * pt.c (tsubst_expr): For OMP reduction function, set context to global_namespace before pushing. (tsubst_omp_udr): Assert current_function_decl, add comment about decl context. --- gcc/cp/parser.c | 22 ++++++++++++---------- gcc/cp/pt.c | 9 +++++++-- 2 files changed, 19 insertions(+), 12 deletions(-) diff --git a/gcc/cp/parser.c b/gcc/cp/parser.c index 9849e59d5aa..0da383937c2 100644 --- a/gcc/cp/parser.c +++ b/gcc/cp/parser.c @@ -42616,16 +42616,9 @@ cp_parser_omp_declare_reduction (cp_parser *parser, cp_token *pragma_tok, cp_parser_push_lexer_for_tokens (parser, cp); parser->lexer->in_pragma = true; } - if (!cp_parser_omp_declare_reduction_exprs (fndecl, parser)) - { - if (!block_scope) - finish_function (/*inline_p=*/false); - else - DECL_CONTEXT (fndecl) = current_function_decl; - if (cp) - cp_parser_pop_lexer (parser); - goto fail; - } + + bool ok = cp_parser_omp_declare_reduction_exprs (fndecl, parser); + if (cp) cp_parser_pop_lexer (parser); if (!block_scope) @@ -42633,6 +42626,14 @@ cp_parser_omp_declare_reduction (cp_parser *parser, cp_token *pragma_tok, else { DECL_CONTEXT (fndecl) = current_function_decl; + if (DECL_TEMPLATE_INFO (fndecl)) + DECL_CONTEXT (DECL_TI_TEMPLATE (fndecl)) = current_function_decl; + } + if (!ok) + goto fail; + + if (block_scope) + { block = finish_omp_structured_block (block); if (TREE_CODE (block) == BIND_EXPR) DECL_SAVED_TREE (fndecl) = BIND_EXPR_BODY (block); @@ -42641,6 +42642,7 @@ cp_parser_omp_declare_reduction (cp_parser *parser, cp_token *pragma_tok, if (processing_template_decl) add_decl_expr (fndecl); } + cp_check_omp_declare_reduction (fndecl); if (cp == NULL && types.length () > 1) cp = cp_token_cache_new (first_token, diff --git a/gcc/cp/pt.c b/gcc/cp/pt.c index a7b7a12b59f..4e212620eaf 100644 --- a/gcc/cp/pt.c +++ b/gcc/cp/pt.c @@ -18077,7 +18077,10 @@ tsubst_expr (tree t, tree args, tsubst_flags_t complain, tree in_decl, && DECL_OMP_DECLARE_REDUCTION_P (decl) && DECL_FUNCTION_SCOPE_P (pattern_decl)) { - DECL_CONTEXT (decl) = NULL_TREE; + /* We pretend this is regular local extern decl of + a namespace-scope fn. Then we make it really + local, it is a nested function. */ + DECL_CONTEXT (decl) = global_namespace; pushdecl (decl); DECL_CONTEXT (decl) = current_function_decl; cp_check_omp_declare_reduction (decl); @@ -18899,7 +18902,7 @@ tsubst_omp_udr (tree t, tree args, tsubst_flags_t complain, tree in_decl) if (t == NULL_TREE || t == error_mark_node) return; - gcc_assert (TREE_CODE (t) == STATEMENT_LIST); + gcc_assert (TREE_CODE (t) == STATEMENT_LIST && current_function_decl); tree_stmt_iterator tsi; int i; @@ -18919,6 +18922,8 @@ tsubst_omp_udr (tree t, tree args, tsubst_flags_t complain, tree in_decl) args, complain, in_decl); tree omp_in = tsubst (DECL_EXPR_DECL (stmts[1]), args, complain, in_decl); + /* tsubsting a local var_decl leaves DECL_CONTEXT null, as we + expect to be pushing it. */ DECL_CONTEXT (omp_out) = current_function_decl; DECL_CONTEXT (omp_in) = current_function_decl; keep_next_level (true); -- 2.30.2