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. */
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:
cp_parser_label_for_labeled_statement (parser, std_attrs);
in_compound = false;
+ in_omp_attribute_pragma = parser->lexer->in_omp_attribute_pragma;
goto restart;
}
}
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)
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:
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)
{
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;
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);
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);
--- /dev/null
+// { 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;
+}