diff options
Diffstat (limited to 'gcc')
-rw-r--r-- | gcc/cp/parser.c | 105 | ||||
-rw-r--r-- | gcc/cp/parser.h | 4 | ||||
-rw-r--r-- | gcc/testsuite/g++.dg/gomp/attrs-1.C | 12 | ||||
-rw-r--r-- | gcc/testsuite/g++.dg/gomp/attrs-2.C | 12 | ||||
-rw-r--r-- | gcc/testsuite/g++.dg/gomp/attrs-6.C | 50 | ||||
-rw-r--r-- | gcc/testsuite/g++.dg/gomp/attrs-7.C | 64 | ||||
-rw-r--r-- | gcc/testsuite/g++.dg/gomp/attrs-8.C | 10 |
7 files changed, 240 insertions, 17 deletions
diff --git a/gcc/cp/parser.c b/gcc/cp/parser.c index 18905cf..976e2e7 100644 --- a/gcc/cp/parser.c +++ b/gcc/cp/parser.c @@ -11901,10 +11901,9 @@ cp_parser_statement (cp_parser* parser, tree in_statement_expr, tree statement, std_attrs = NULL_TREE; cp_token *token; location_t statement_location, attrs_loc; - bool in_omp_attribute_pragma; + bool in_omp_attribute_pragma = parser->lexer->in_omp_attribute_pragma; restart: - in_omp_attribute_pragma = parser->lexer->in_omp_attribute_pragma; if (if_p != NULL) *if_p = false; /* There is no statement yet. */ @@ -11951,6 +11950,7 @@ cp_parser_statement (cp_parser* parser, tree in_statement_expr, the statement. */ cp_parser_label_for_labeled_statement (parser, std_attrs); in_compound = false; + in_omp_attribute_pragma = parser->lexer->in_omp_attribute_pragma; goto restart; case RID_IF: @@ -12034,6 +12034,7 @@ cp_parser_statement (cp_parser* parser, tree in_statement_expr, cp_parser_label_for_labeled_statement (parser, std_attrs); in_compound = false; + in_omp_attribute_pragma = parser->lexer->in_omp_attribute_pragma; goto restart; } } @@ -12058,13 +12059,28 @@ cp_parser_statement (cp_parser* parser, tree in_statement_expr, cp_parser_pragma (parser, pragma_compound, if_p); else if (!cp_parser_pragma (parser, pragma_stmt, if_p)) do_restart = true; - if (lexer->in_omp_attribute_pragma && !in_omp_attribute_pragma) + if (parser->lexer != lexer + && lexer->in_omp_attribute_pragma + && (!in_omp_attribute_pragma || lexer->orphan_p)) { - gcc_assert (parser->lexer != lexer); + if (saved_tokens.lexer == lexer) + { + if (saved_tokens.commit) + cp_lexer_commit_tokens (lexer); + gcc_assert (lexer->saved_tokens.length () == saved_tokens.len); + saved_tokens.lexer = parser->lexer; + saved_tokens.commit = false; + saved_tokens.len = parser->lexer->saved_tokens.length (); + } cp_lexer_destroy (lexer); + lexer = parser->lexer; } if (do_restart) goto restart; + if (parser->lexer == lexer + && lexer->in_omp_attribute_pragma + && !in_omp_attribute_pragma) + parser->lexer->orphan_p = true; return; } else if (token->type == CPP_EOF) @@ -40775,6 +40791,77 @@ cp_finish_omp_range_for (tree orig, tree begin) cp_finish_decomp (decl, decomp_first_name, decomp_cnt); } +/* Return true if next tokens contain a standard attribute that contains + omp::directive (DIRECTIVE). */ + +static bool +cp_parser_omp_section_scan (cp_parser *parser, const char *directive, + bool tentative) +{ + size_t n = cp_parser_skip_attributes_opt (parser, 1), i; + if (n < 10) + return false; + for (i = 5; i < n - 4; i++) + if (cp_lexer_nth_token_is (parser->lexer, i, CPP_NAME) + && cp_lexer_nth_token_is (parser->lexer, i + 1, CPP_OPEN_PAREN) + && cp_lexer_nth_token_is (parser->lexer, i + 2, CPP_NAME)) + { + tree first = cp_lexer_peek_nth_token (parser->lexer, i)->u.value; + tree second = cp_lexer_peek_nth_token (parser->lexer, i + 2)->u.value; + if (strcmp (IDENTIFIER_POINTER (first), "directive")) + continue; + if (strcmp (IDENTIFIER_POINTER (second), directive) == 0) + break; + } + if (i == n - 4) + return false; + cp_parser_parse_tentatively (parser); + location_t first_loc = cp_lexer_peek_token (parser->lexer)->location; + location_t last_loc + = cp_lexer_peek_nth_token (parser->lexer, n - 1)->location; + location_t middle_loc = UNKNOWN_LOCATION; + tree std_attrs = cp_parser_std_attribute_spec_seq (parser); + int cnt = 0; + bool seen = false; + for (tree attr = std_attrs; attr; attr = TREE_CHAIN (attr)) + if (get_attribute_namespace (attr) == omp_identifier + && is_attribute_p ("directive", get_attribute_name (attr))) + { + for (tree a = TREE_VALUE (attr); a; a = TREE_CHAIN (a)) + { + tree d = TREE_VALUE (a); + gcc_assert (TREE_CODE (d) == DEFERRED_PARSE); + cp_token *first = DEFPARSE_TOKENS (d)->first; + cnt++; + if (first->type == CPP_NAME + && strcmp (IDENTIFIER_POINTER (first->u.value), + directive) == 0) + { + seen = true; + if (middle_loc == UNKNOWN_LOCATION) + middle_loc = first->location; + } + } + } + if (!seen || tentative) + { + cp_parser_abort_tentative_parse (parser); + return seen; + } + if (cnt != 1 || TREE_CHAIN (std_attrs)) + { + error_at (make_location (first_loc, last_loc, middle_loc), + "%<[[omp::directive(%s)]]%> must be the only specified " + "attribute on a statement", directive); + cp_parser_abort_tentative_parse (parser); + return false; + } + if (!cp_parser_parse_definitely (parser)) + return false; + cp_parser_handle_statement_omp_attributes (parser, std_attrs); + return true; +} + /* OpenMP 5.0: scan-loop-body: @@ -40793,6 +40880,7 @@ cp_parser_omp_scan_loop_body (cp_parser *parser) substmt = build2 (OMP_SCAN, void_type_node, substmt, NULL_TREE); add_stmt (substmt); + cp_parser_omp_section_scan (parser, "scan", false); cp_token *tok = cp_lexer_peek_token (parser->lexer); if (cp_parser_pragma_kind (tok) == PRAGMA_OMP_SCAN) { @@ -40800,6 +40888,10 @@ cp_parser_omp_scan_loop_body (cp_parser *parser) cp_lexer_consume_token (parser->lexer); + if (parser->lexer->in_omp_attribute_pragma + && cp_lexer_next_token_is (parser->lexer, CPP_COMMA)) + cp_lexer_consume_token (parser->lexer); + if (cp_lexer_next_token_is (parser->lexer, CPP_NAME)) { tree id = cp_lexer_peek_token (parser->lexer)->u.value; @@ -41623,7 +41715,8 @@ cp_parser_omp_sections_scope (cp_parser *parser) stmt = push_stmt_list (); if (cp_parser_pragma_kind (cp_lexer_peek_token (parser->lexer)) - != PRAGMA_OMP_SECTION) + != PRAGMA_OMP_SECTION + && !cp_parser_omp_section_scan (parser, "section", true)) { substmt = cp_parser_omp_structured_block (parser, NULL, false); substmt = build1 (OMP_SECTION, void_type_node, substmt); @@ -41638,6 +41731,8 @@ cp_parser_omp_sections_scope (cp_parser *parser) if (tok->type == CPP_EOF) break; + if (cp_parser_omp_section_scan (parser, "section", false)) + tok = cp_lexer_peek_token (parser->lexer); if (cp_parser_pragma_kind (tok) == PRAGMA_OMP_SECTION) { cp_lexer_consume_token (parser->lexer); diff --git a/gcc/cp/parser.h b/gcc/cp/parser.h index 6fdd214..e62742d 100644 --- a/gcc/cp/parser.h +++ b/gcc/cp/parser.h @@ -117,6 +117,10 @@ struct GTY (()) cp_lexer { /* True if we're in the context of OpenMP directives written as C++11 attributes turned into pragma. */ bool in_omp_attribute_pragma; + + /* True for in_omp_attribute_pragma lexer that should be destroyed + when it is no longer in use. */ + bool orphan_p; }; diff --git a/gcc/testsuite/g++.dg/gomp/attrs-1.C b/gcc/testsuite/g++.dg/gomp/attrs-1.C index c2734a1..6bbdcac 100644 --- a/gcc/testsuite/g++.dg/gomp/attrs-1.C +++ b/gcc/testsuite/g++.dg/gomp/attrs-1.C @@ -146,17 +146,17 @@ bar (int d, int m, int i1, int i2, int i3, int p, int *idp, int s, private (p) firstprivate (f) if (parallel: i2) default(shared) shared(s) copyin(t) reduction(+:r) num_threads (nth) proc_bind(spread) lastprivate (l) allocate (f))]] { - #pragma omp section + [[omp::directive (section)]] {} - #pragma omp section + [[omp::sequence (omp::directive (section))]] {} } [[omp::directive (sections private (p) firstprivate (f) reduction(+:r) lastprivate (l) allocate (f) nowait)]] { ; - #pragma omp section + [[omp::sequence (sequence (directive (section)))]] ; - #pragma omp section + [[omp::directive (section)]] {} } [[omp::directive (barrier)]]; @@ -539,14 +539,14 @@ garply (int a, int *c, int *d, int *e, int *f) for (i = 0; i < 64; i++) { d[i] = a; - #pragma omp scan exclusive (a) + [[omp::directive (scan exclusive (a))]] a += c[i]; } [[omp::directive (simd reduction (inscan, +: a))]] for (i = 0; i < 64; i++) { a += c[i]; - #pragma omp scan inclusive (a) + [[omp::sequence (omp::sequence (omp::directive (scan inclusive (a))))]] d[i] = a; } return a; diff --git a/gcc/testsuite/g++.dg/gomp/attrs-2.C b/gcc/testsuite/g++.dg/gomp/attrs-2.C index 1eb6263..189dc6b 100644 --- a/gcc/testsuite/g++.dg/gomp/attrs-2.C +++ b/gcc/testsuite/g++.dg/gomp/attrs-2.C @@ -146,17 +146,17 @@ bar (int d, int m, int i1, int i2, int i3, int p, int *idp, int s, private (p),firstprivate (f),if (parallel: i2),default(shared),shared(s),copyin(t),reduction(+:r),num_threads (nth),proc_bind(spread), lastprivate (l),allocate (f))]] { - #pragma omp section + [[using omp:directive (section)]] {} - #pragma omp section + [[omp::sequence (omp::directive (section))]] {} } [[omp::directive (sections, private (p),firstprivate (f),reduction(+:r),lastprivate (l),allocate (f),nowait)]] { ; - #pragma omp section + [[omp::sequence (sequence (directive (section)))]] ; - #pragma omp section + [[omp::directive (section)]] {} } [[omp::directive (barrier)]]; @@ -539,14 +539,14 @@ garply (int a, int *c, int *d, int *e, int *f) for (i = 0; i < 64; i++) { d[i] = a; - #pragma omp scan exclusive (a) + [[omp::directive (scan, exclusive (a))]] a += c[i]; } [[omp::directive (simd, reduction (inscan, +: a))]] for (i = 0; i < 64; i++) { a += c[i]; - #pragma omp scan inclusive (a) + [[using omp : sequence (sequence (directive (scan inclusive (a))))]] d[i] = a; } return a; diff --git a/gcc/testsuite/g++.dg/gomp/attrs-6.C b/gcc/testsuite/g++.dg/gomp/attrs-6.C new file mode 100644 index 0000000..30b47e1 --- /dev/null +++ b/gcc/testsuite/g++.dg/gomp/attrs-6.C @@ -0,0 +1,50 @@ +// { dg-do compile { target c++11 } } + +void +foo () +{ + int a[10] = {}; + #pragma omp parallel sections + { + #pragma omp section + a[0]++; + [[omp::directive (section)]] { + a[1]++; + } [[omp::directive (section)]] + a[2]++; + #pragma omp section + { a[3]++; } + } + [[omp::directive (parallel sections)]] + { + #pragma omp section + a[0]++; + [[omp::directive (section)]] { + a[1]++; + } [[omp::directive (section)]] + a[2]++; + #pragma omp section + { a[3]++; } + } +} + +int +bar (int a, int *c, int *d, int *e, int *f) +{ + int i; + #pragma omp simd reduction (inscan, +: a) + for (i = 0; i < 64; i++) + { + d[i] = a; + [[omp::directive (scan, exclusive (a))]] + a += c[i]; + } + [[omp::directive (simd reduction (inscan, +: a))]] + for (i = 0; i < 64; i++) + { + a += c[i]; + #pragma omp scan inclusive (a) + d[i] = a; + } + return a; +} diff --git a/gcc/testsuite/g++.dg/gomp/attrs-7.C b/gcc/testsuite/g++.dg/gomp/attrs-7.C new file mode 100644 index 0000000..598c32a --- /dev/null +++ b/gcc/testsuite/g++.dg/gomp/attrs-7.C @@ -0,0 +1,64 @@ +// { dg-do compile { target c++11 } } + +void +foo () +{ + + [[omp::directive (parallel sections)]] + { + [[omp::directive (parallel)]]; + [[omp::sequence (directive (section), directive (flush))]]; // { dg-error "must be the only specified attribute on a statement" } + // { dg-error "#pragma omp section" "" { target *-*-* } .-1 } + // { dg-error "#pragma omp flush" "" { target *-*-* } .-2 } + [[omp::sequence (directive (flush), omp::directive (section))]]; // { dg-error "must be the only specified attribute on a statement" } + // { dg-error "#pragma omp section" "" { target *-*-* } .-1 } + // { dg-error "#pragma omp flush" "" { target *-*-* } .-2 } + [[gnu::cold, omp::directive (section)]]; // { dg-error "must be the only specified attribute on a statement" } + // { dg-error "#pragma omp section" "" { target *-*-* } .-1 } + [[omp::directive (section)]] [[gnu::cold]]; // { dg-error "must be the only specified attribute on a statement" } + // { dg-error "#pragma omp section" "" { target *-*-* } .-1 } + [[omp::directive (section foo)]]; // { dg-error "expected end of line before 'foo'" } + } +} + +int +bar (int a, int *c, int *d, int *e, int *f) +{ + int i; + [[omp::directive (parallel for reduction (inscan, +: a))]] // { dg-error "'a' specified in 'inscan' 'reduction' clause but not in 'scan' directive clause" } + for (i = 0; i < 64; i++) + { + d[i] = a; + [[omp::sequence (omp::directive (parallel), omp::directive (scan, exclusive (a)))]] // { dg-error "must be the only specified attribute on a statement" } + a += c[i]; // { dg-error "#pragma omp scan" "" { target *-*-* } .-1 } + } + [[omp::directive (parallel for reduction (inscan, +: a))]] // { dg-error "'a' specified in 'inscan' 'reduction' clause but not in 'scan' directive clause" } + for (i = 0; i < 64; i++) + { + a += c[i]; + [[omp::sequence (directive (scan inclusive (a)), directive (critical))]] // { dg-error "must be the only specified attribute on a statement" } + d[i] = a; // { dg-error "#pragma omp scan" "" { target *-*-* } .-1 } + } + [[omp::directive (parallel for reduction (inscan, +: a))]] // { dg-error "'a' specified in 'inscan' 'reduction' clause but not in 'scan' directive clause" } + for (i = 0; i < 64; i++) + { + d[i] = a; + [[gnu::cold]] [[omp::directive (scan, exclusive (a))]] // { dg-error "must be the only specified attribute on a statement" } + a += c[i]; // { dg-error "#pragma omp scan" "" { target *-*-* } .-1 } + } + [[omp::directive (parallel for reduction (inscan, +: a))]] // { dg-error "'a' specified in 'inscan' 'reduction' clause but not in 'scan' directive clause" } + for (i = 0; i < 64; i++) + { + d[i] = a; + [[omp::directive (scan, exclusive (a)), gnu::cold]] // { dg-error "must be the only specified attribute on a statement" } + a += c[i]; // { dg-error "#pragma omp scan" "" { target *-*-* } .-1 } + } + [[omp::directive (parallel for reduction (inscan, +: a))]] // { dg-error "'a' specified in 'inscan' 'reduction' clause but not in 'scan' directive clause" } + for (i = 0; i < 64; i++) + { + d[i] = a; + [[omp::directive (scan)]] // { dg-error "expected 'inclusive' or 'exclusive' clause before end of line" } + a += c[i]; + } + return a; +} diff --git a/gcc/testsuite/g++.dg/gomp/attrs-8.C b/gcc/testsuite/g++.dg/gomp/attrs-8.C new file mode 100644 index 0000000..30cfe99 --- /dev/null +++ b/gcc/testsuite/g++.dg/gomp/attrs-8.C @@ -0,0 +1,10 @@ +// { dg-do compile { target c++11 } } + +void +foo () +{ + // Unsure if this shouldn't be invalid, whether we shouldn't require + // that each standalone directive sits on its own empty statement. + [[omp::sequence (omp::directive (barrier), omp::directive (barrier))]]; + [[omp::sequence (omp::directive (taskyield), omp::directive (taskwait))]]; +} |