From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: by sourceware.org (Postfix, from userid 1729) id 88DDC384D1AE; Wed, 29 Jun 2022 14:44:24 +0000 (GMT) DKIM-Filter: OpenDKIM Filter v2.11.0 sourceware.org 88DDC384D1AE Content-Type: text/plain; charset="us-ascii" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit From: Kwok Yeung To: gcc-cvs@gcc.gnu.org Subject: [gcc/devel/omp/gcc-12] openmp: Improve handling of nested OpenMP metadirectives in C and C++ X-Act-Checkin: gcc X-Git-Author: Kwok Cheung Yeung X-Git-Refname: refs/heads/devel/omp/gcc-12 X-Git-Oldrev: 484384f0b284e771c1828b07590ee3353cff16b7 X-Git-Newrev: 44810a4970934905059ea137972764241c90957b Message-Id: <20220629144424.88DDC384D1AE@sourceware.org> Date: Wed, 29 Jun 2022 14:44:24 +0000 (GMT) X-BeenThere: gcc-cvs@gcc.gnu.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: Gcc-cvs mailing list List-Unsubscribe: , List-Archive: List-Help: List-Subscribe: , X-List-Received-Date: Wed, 29 Jun 2022 14:44:24 -0000 https://gcc.gnu.org/g:44810a4970934905059ea137972764241c90957b commit 44810a4970934905059ea137972764241c90957b Author: Kwok Cheung Yeung Date: Fri Feb 18 19:00:57 2022 +0000 openmp: Improve handling of nested OpenMP metadirectives in C and C++ This patch fixes a misparsing issue when encountering code like: #pragma omp metadirective when {={...}: A) #pragma omp metadirective when (={...}: B) When called for the first metadirective, analyze_metadirective_body would stop just before the colon in the second metadirective because it naively assumes that the '}' marks the end of a code block. The assertion for clauses to end parsing at the same point is now disabled if a parse error has occurred during the parsing of the clause, since some tokens may not be consumed if a parse error cuts parsing short. 2022-02-18 Kwok Cheung Yeung gcc/c/ * c-parser.cc (c_parser_omp_construct): Move handling of PRAGMA_OMP_METADIRECTIVE from here... (c_parser_pragma): ...to here. (analyze_metadirective_body): Check that the bracket nesting level is also zero before stopping the adding of tokens on encountering a close brace. (c_parser_omp_metadirective): Modify function signature and update. Do not assert on remaining tokens if there has been a parse error. gcc/cp/ * parser.cc (cp_parser_omp_construct): Move handling of PRAGMA_OMP_METADIRECTIVE from here... (cp_parser_pragma): ...to here. (analyze_metadirective_body): Check that the bracket nesting level is also zero before stopping the adding of tokens on encountering a close brace. (cp_parser_omp_metadirective): Modify function signature and update. Do not assert on remaining tokens if there has been a parse error. gcc/testsuite/ * c-c++-common/gomp/metadirective-1.c (f): Add test for improperly nested metadirectives. Diff: --- gcc/c/ChangeLog.omp | 11 ++++++ gcc/c/c-parser.cc | 47 +++++++++++------------ gcc/cp/ChangeLog.omp | 11 ++++++ gcc/cp/parser.cc | 33 ++++++++-------- gcc/testsuite/ChangeLog.omp | 5 +++ gcc/testsuite/c-c++-common/gomp/metadirective-1.c | 13 +++++++ 6 files changed, 78 insertions(+), 42 deletions(-) diff --git a/gcc/c/ChangeLog.omp b/gcc/c/ChangeLog.omp index 487c385fb6c..3e5fe5fd85e 100644 --- a/gcc/c/ChangeLog.omp +++ b/gcc/c/ChangeLog.omp @@ -1,3 +1,14 @@ +2022-02-18 Kwok Cheung Yeung + + * c-parser.cc (c_parser_omp_construct): Move handling of + PRAGMA_OMP_METADIRECTIVE from here... + (c_parser_pragma): ...to here. + (analyze_metadirective_body): Check that the bracket nesting level + is also zero before stopping the adding of tokens on encountering a + close brace. + (c_parser_omp_metadirective): Modify function signature and update. + Do not assert on remaining tokens if there has been a parse error. + 2022-01-25 Kwok Cheung Yeung * c-parser.cc (omp_target_device_selectors): New. diff --git a/gcc/c/c-parser.cc b/gcc/c/c-parser.cc index fea78ddbb57..60734268f7e 100644 --- a/gcc/c/c-parser.cc +++ b/gcc/c/c-parser.cc @@ -1592,6 +1592,7 @@ static void c_parser_omp_taskwait (c_parser *); static void c_parser_omp_taskyield (c_parser *); static void c_parser_omp_cancel (c_parser *); static void c_parser_omp_nothing (c_parser *); +static void c_parser_omp_metadirective (c_parser *, bool *); enum pragma_context { pragma_external, pragma_struct, pragma_param, pragma_stmt, pragma_compound }; @@ -1600,8 +1601,6 @@ static bool c_parser_omp_cancellation_point (c_parser *, enum pragma_context); static bool c_parser_omp_target (c_parser *, enum pragma_context, bool *); static void c_parser_omp_end_declare_target (c_parser *); static bool c_parser_omp_declare (c_parser *, enum pragma_context); -static tree c_parser_omp_metadirective (location_t, c_parser *, char *, - omp_clause_mask, tree *, bool *); static void c_parser_omp_requires (c_parser *); static bool c_parser_omp_error (c_parser *, enum pragma_context); static bool c_parser_omp_ordered (c_parser *, enum pragma_context, bool *); @@ -12556,6 +12555,10 @@ c_parser_pragma (c_parser *parser, enum pragma_context context, bool *if_p) c_parser_omp_nothing (parser); return false; + case PRAGMA_OMP_METADIRECTIVE: + c_parser_omp_metadirective (parser, if_p); + return true; + case PRAGMA_OMP_ERROR: return c_parser_omp_error (parser, context); @@ -23075,7 +23078,7 @@ analyze_metadirective_body (c_parser *parser, ++nesting_depth; goto add; case CPP_CLOSE_BRACE: - if (--nesting_depth == 0) + if (--nesting_depth == 0 && bracket_depth == 0) stop = true; goto add; case CPP_OPEN_PAREN: @@ -23113,10 +23116,8 @@ analyze_metadirective_body (c_parser *parser, # pragma omp metadirective [clause[, clause]] */ -static tree -c_parser_omp_metadirective (location_t loc, c_parser *parser, - char *p_name, omp_clause_mask, tree *, - bool *if_p) +static void +c_parser_omp_metadirective (c_parser *parser, bool *if_p) { tree ret; auto_vec directive_tokens; @@ -23128,13 +23129,14 @@ c_parser_omp_metadirective (location_t loc, c_parser *parser, bool default_seen = false; int directive_token_idx = 0; tree standalone_body = NULL_TREE; + location_t pragma_loc = c_parser_peek_token (parser)->location; ret = make_node (OMP_METADIRECTIVE); - SET_EXPR_LOCATION (ret, loc); + SET_EXPR_LOCATION (ret, pragma_loc); TREE_TYPE (ret) = void_type_node; OMP_METADIRECTIVE_CLAUSES (ret) = NULL_TREE; - strcat (p_name, " metadirective"); + c_parser_consume_pragma (parser); while (c_parser_next_token_is_not (parser, CPP_PRAGMA_EOL)) { if (c_parser_next_token_is_not (parser, CPP_NAME) @@ -23342,6 +23344,7 @@ c_parser_omp_metadirective (location_t loc, c_parser *parser, parser->tokens = tokens.address (); parser->tokens_avail = tokens.length (); + int prev_errorcount = errorcount; tree directive = c_begin_compound_stmt (true); /* Declare all non-local labels that occur within the directive body @@ -23351,11 +23354,11 @@ c_parser_omp_metadirective (location_t loc, c_parser *parser, tree label = declare_label (body_labels[j]); C_DECLARED_LABEL_FLAG (label) = 1; - add_stmt (build_stmt (loc, DECL_EXPR, label)); + add_stmt (build_stmt (pragma_loc, DECL_EXPR, label)); } c_parser_pragma (parser, pragma_compound, if_p); - directive = c_end_compound_stmt (loc, directive, true); + directive = c_end_compound_stmt (pragma_loc, directive, true); bool standalone_p = directives[i]->kind == C_OMP_DIR_STANDALONE || directives[i]->kind == C_OMP_DIR_UTILITY; @@ -23378,10 +23381,14 @@ c_parser_omp_metadirective (location_t loc, c_parser *parser, OMP_METADIRECTIVE_CLAUSES (ret) = chainon (OMP_METADIRECTIVE_CLAUSES (ret), variant); - /* Check that all valid tokens have been consumed. */ - gcc_assert (parser->tokens_avail == 2); - gcc_assert (c_parser_next_token_is (parser, CPP_EOF)); - gcc_assert (c_parser_peek_2nd_token (parser)->type == CPP_EOF); + /* Check that all valid tokens have been consumed if no parse errors + encountered. */ + if (errorcount == prev_errorcount) + { + gcc_assert (parser->tokens_avail == 2); + gcc_assert (c_parser_next_token_is (parser, CPP_EOF)); + gcc_assert (c_parser_peek_2nd_token (parser)->type == CPP_EOF); + } parser->tokens = old_tokens; parser->tokens_avail = old_tokens_avail; @@ -23393,15 +23400,12 @@ c_parser_omp_metadirective (location_t loc, c_parser *parser, ret = c_omp_expand_metadirective (candidates); add_stmt (ret); - - return ret; + return; error: if (parser->in_pragma) c_parser_skip_to_pragma_eol (parser); c_parser_skip_to_end_of_block_or_statement (parser); - - return NULL_TREE; } /* Main entry point to parsing most OpenMP pragmas. */ @@ -23477,11 +23481,6 @@ c_parser_omp_construct (c_parser *parser, bool *if_p) strcpy (p_name, "#pragma omp"); stmt = c_parser_omp_master (loc, parser, p_name, mask, NULL, if_p); break; - case PRAGMA_OMP_METADIRECTIVE: - strcpy (p_name, "#pragma omp"); - stmt = c_parser_omp_metadirective (loc, parser, p_name, mask, NULL, - if_p); - break; case PRAGMA_OMP_PARALLEL: strcpy (p_name, "#pragma omp"); stmt = c_parser_omp_parallel (loc, parser, p_name, mask, NULL, if_p); diff --git a/gcc/cp/ChangeLog.omp b/gcc/cp/ChangeLog.omp index c2a317e29fa..251fc73f190 100644 --- a/gcc/cp/ChangeLog.omp +++ b/gcc/cp/ChangeLog.omp @@ -1,3 +1,14 @@ +2022-02-18 Kwok Cheung Yeung + + * parser.cc (cp_parser_omp_construct): Move handling of + PRAGMA_OMP_METADIRECTIVE from here... + (cp_parser_pragma): ...to here. + (analyze_metadirective_body): Check that the bracket + nesting level is also zero before stopping the adding of tokens on + encountering a close brace. + (cp_parser_omp_metadirective): Modify function signature and update. + Do not assert on remaining tokens if there has been a parse error. + 2022-01-25 Kwok Cheung Yeung * parser.cc (omp_target_device_selectors): New. diff --git a/gcc/cp/parser.cc b/gcc/cp/parser.cc index 90af3f89a5c..7377849105d 100644 --- a/gcc/cp/parser.cc +++ b/gcc/cp/parser.cc @@ -46047,7 +46047,7 @@ cp_parser_omp_end_declare_target (cp_parser *parser, cp_token *pragma_tok) } -/* Helper function for c_parser_omp_metadirective. */ +/* Helper function for cp_parser_omp_metadirective. */ static void analyze_metadirective_body (cp_parser *parser, @@ -46083,7 +46083,7 @@ analyze_metadirective_body (cp_parser *parser, ++nesting_depth; goto add; case CPP_CLOSE_BRACE: - if (--nesting_depth == 0) + if (--nesting_depth == 0 && bracket_depth == 0) stop = true; goto add; case CPP_OPEN_PAREN: @@ -46118,9 +46118,8 @@ analyze_metadirective_body (cp_parser *parser, # pragma omp metadirective [clause[, clause]] */ -static tree +static void cp_parser_omp_metadirective (cp_parser *parser, cp_token *pragma_tok, - char *p_name, omp_clause_mask, tree *, bool *if_p) { tree ret; @@ -46131,15 +46130,14 @@ cp_parser_omp_metadirective (cp_parser *parser, cp_token *pragma_tok, auto_vec ctxs; bool default_seen = false; int directive_token_idx = 0; - location_t loc = cp_lexer_peek_token (parser->lexer)->location; + location_t pragma_loc = pragma_tok->location; tree standalone_body = NULL_TREE; vec candidates; ret = make_node (OMP_METADIRECTIVE); - SET_EXPR_LOCATION (ret, loc); + SET_EXPR_LOCATION (ret, pragma_loc); TREE_TYPE (ret) = void_type_node; OMP_METADIRECTIVE_CLAUSES (ret) = NULL_TREE; - strcat (p_name, " metadirective"); while (cp_lexer_next_token_is_not (parser->lexer, CPP_PRAGMA_EOL)) { @@ -46358,6 +46356,7 @@ cp_parser_omp_metadirective (cp_parser *parser, cp_token *pragma_tok, parser->lexer = lexer; cp_lexer_set_source_position_from_token (lexer->next_token); + int prev_errorcount = errorcount; tree directive = push_stmt_list (); tree directive_stmt = begin_compound_stmt (0); @@ -46392,8 +46391,10 @@ cp_parser_omp_metadirective (cp_parser *parser, cp_token *pragma_tok, OMP_METADIRECTIVE_CLAUSES (ret) = chainon (OMP_METADIRECTIVE_CLAUSES (ret), variant); - /* Check that all valid tokens have been consumed. */ - gcc_assert (cp_lexer_next_token_is (parser->lexer, CPP_EOF)); + /* Check that all valid tokens have been consumed if no parse errors + encountered. */ + gcc_assert (errorcount != prev_errorcount + || cp_lexer_next_token_is (parser->lexer, CPP_EOF)); parser->lexer = old_lexer; cp_lexer_set_source_position_from_token (old_lexer->next_token); @@ -46405,8 +46406,7 @@ cp_parser_omp_metadirective (cp_parser *parser, cp_token *pragma_tok, ret = c_omp_expand_metadirective (candidates); add_stmt (ret); - - return ret; + return; fail: /* Skip the metadirective pragma. */ @@ -46414,7 +46414,6 @@ fail: /* Skip the metadirective body. */ cp_parser_skip_to_end_of_block_or_statement (parser); - return error_mark_node; } @@ -47661,11 +47660,6 @@ cp_parser_omp_construct (cp_parser *parser, cp_token *pragma_tok, bool *if_p) stmt = cp_parser_omp_master (parser, pragma_tok, p_name, mask, NULL, if_p); break; - case PRAGMA_OMP_METADIRECTIVE: - strcpy (p_name, "#pragma omp"); - stmt = cp_parser_omp_metadirective (parser, pragma_tok, p_name, mask, - NULL, if_p); - break; case PRAGMA_OMP_PARALLEL: strcpy (p_name, "#pragma omp"); stmt = cp_parser_omp_parallel (parser, pragma_tok, p_name, mask, NULL, @@ -48316,7 +48310,6 @@ cp_parser_pragma (cp_parser *parser, enum pragma_context context, bool *if_p) case PRAGMA_OMP_LOOP: case PRAGMA_OMP_MASKED: case PRAGMA_OMP_MASTER: - case PRAGMA_OMP_METADIRECTIVE: case PRAGMA_OMP_PARALLEL: case PRAGMA_OMP_SCOPE: case PRAGMA_OMP_SECTIONS: @@ -48348,6 +48341,10 @@ cp_parser_pragma (cp_parser *parser, enum pragma_context context, bool *if_p) cp_parser_omp_nothing (parser, pragma_tok); return false; + case PRAGMA_OMP_METADIRECTIVE: + cp_parser_omp_metadirective (parser, pragma_tok, if_p); + return true; + case PRAGMA_OMP_ERROR: return cp_parser_omp_error (parser, pragma_tok, context); diff --git a/gcc/testsuite/ChangeLog.omp b/gcc/testsuite/ChangeLog.omp index 2ca7567c25c..72c03338b02 100644 --- a/gcc/testsuite/ChangeLog.omp +++ b/gcc/testsuite/ChangeLog.omp @@ -1,3 +1,8 @@ +2022-02-18 Kwok Cheung Yeung + + * c-c++-common/gomp/metadirective-1.c (f): Add test for + improperly nested metadirectives. + 2022-02-11 Kwok Cheung Yeung * gfortran.dg/gomp/metadirective-2.f90 (main): Test empty diff --git a/gcc/testsuite/c-c++-common/gomp/metadirective-1.c b/gcc/testsuite/c-c++-common/gomp/metadirective-1.c index 72cf0abbbd7..543063a3324 100644 --- a/gcc/testsuite/c-c++-common/gomp/metadirective-1.c +++ b/gcc/testsuite/c-c++-common/gomp/metadirective-1.c @@ -4,6 +4,8 @@ void f (int a[], int b[], int c[]) { + int i; + #pragma omp metadirective \ default (teams loop) \ default (parallel loop) /* { dg-error "there can only be one default clause in a metadirective before '\\(' token" } */ @@ -26,4 +28,15 @@ void f (int a[], int b[], int c[]) #pragma omp metadirective \ default (metadirective default (flush)) /* { dg-error "metadirectives cannot be used as directive variants before 'default'" } */ for (i = 0; i < N; i++) c[i] = a[i] * b[i]; + + /* Test improperly nested metadirectives - even though the second + metadirective resolves to 'omp nothing', that is not the same as there + being literally nothing there. */ + #pragma omp metadirective \ + when (implementation={vendor("gnu")}: parallel for) + #pragma omp metadirective \ + when (implementation={vendor("cray")}: parallel for) + /* { dg-error "for statement expected before '#pragma'" "" { target c } .-2 } */ + /* { dg-error "'#pragma' is not allowed here" "" { target c++ } .-3 } */ + for (i = 0; i < N; i++) c[i] = a[i] * b[i]; }