auto_vec<cp_omp_attribute_data, 16> vec;
int cnt = 0;
int tokens = 0;
+ bool bad = false;
for (tree *pa = &attrs; *pa; )
if (get_attribute_namespace (*pa) == omp_identifier
&& is_attribute_p ("directive", get_attribute_name (*pa)))
gcc_assert (TREE_CODE (d) == DEFERRED_PARSE);
cp_token *first = DEFPARSE_TOKENS (d)->first;
cp_token *last = DEFPARSE_TOKENS (d)->last;
+ if (parser->omp_attrs_forbidden_p)
+ {
+ error_at (first->location,
+ "mixing OpenMP directives with attribute and pragma "
+ "syntax on the same statement");
+ parser->omp_attrs_forbidden_p = false;
+ bad = true;
+ }
const char *directive[3] = {};
for (int i = 0; i < 3; i++)
{
else
pa = &TREE_CHAIN (*pa);
+ if (bad)
+ return attrs;
+
unsigned int i;
cp_omp_attribute_data *v;
cp_omp_attribute_data *construct_seen = nullptr;
" can only appear on an empty statement");
return attrs;
}
+ if (cnt && cp_lexer_next_token_is (parser->lexer, CPP_PRAGMA))
+ {
+ cp_token *token = cp_lexer_peek_token (parser->lexer);
+ enum pragma_kind kind = cp_parser_pragma_kind (token);
+ if (kind >= PRAGMA_OMP__START_ && kind <= PRAGMA_OMP__LAST_)
+ {
+ error_at (token->location,
+ "mixing OpenMP directives with attribute and pragma "
+ "syntax on the same statement");
+ return attrs;
+ }
+ }
if (!tokens)
return attrs;
if (std_attrs && (flag_openmp || flag_openmp_simd))
std_attrs = cp_parser_handle_statement_omp_attributes (parser, std_attrs);
+ parser->omp_attrs_forbidden_p = false;
/* Peek at the next token. */
token = cp_lexer_peek_token (parser->lexer);
}
static tree
-cp_parser_omp_structured_block (cp_parser *parser, bool *if_p)
+cp_parser_omp_structured_block (cp_parser *parser, bool *if_p,
+ bool disallow_omp_attrs = true)
{
tree stmt = begin_omp_structured_block ();
unsigned int save = cp_parser_begin_omp_structured_block (parser);
+ if (disallow_omp_attrs)
+ parser->omp_attrs_forbidden_p = true;
cp_parser_statement (parser, NULL_TREE, false, if_p);
cp_parser_end_omp_structured_block (parser, save);
if (!braces.require_open (parser))
return;
- substmt = cp_parser_omp_structured_block (parser, NULL);
+ substmt = cp_parser_omp_structured_block (parser, NULL, false);
substmt = build2 (OMP_SCAN, void_type_node, substmt, NULL_TREE);
add_stmt (substmt);
error ("expected %<#pragma omp scan%>");
clauses = finish_omp_clauses (clauses, C_ORT_OMP);
- substmt = cp_parser_omp_structured_block (parser, NULL);
+ substmt = cp_parser_omp_structured_block (parser, NULL, false);
substmt = build2_loc (tok->location, OMP_SCAN, void_type_node, substmt,
clauses);
add_stmt (substmt);
if (cp_parser_pragma_kind (cp_lexer_peek_token (parser->lexer))
!= PRAGMA_OMP_SECTION)
{
- substmt = cp_parser_omp_structured_block (parser, NULL);
+ substmt = cp_parser_omp_structured_block (parser, NULL, false);
substmt = build1 (OMP_SECTION, void_type_node, substmt);
add_stmt (substmt);
}
error_suppress = true;
}
- substmt = cp_parser_omp_structured_block (parser, NULL);
+ substmt = cp_parser_omp_structured_block (parser, NULL, false);
substmt = build1 (OMP_SECTION, void_type_node, substmt);
add_stmt (substmt);
}
block = begin_omp_parallel ();
save = cp_parser_begin_omp_structured_block (parser);
+ parser->omp_attrs_forbidden_p = true;
cp_parser_statement (parser, NULL_TREE, false, if_p);
cp_parser_end_omp_structured_block (parser, save);
stmt = finish_omp_parallel (clauses, block);
"#pragma omp task", pragma_tok);
block = begin_omp_task ();
save = cp_parser_begin_omp_structured_block (parser);
+ parser->omp_attrs_forbidden_p = true;
cp_parser_statement (parser, NULL_TREE, false, if_p);
cp_parser_end_omp_structured_block (parser, save);
return finish_omp_task (clauses, block);
--- /dev/null
+// { dg-do compile { target c++11 } }
+
+void
+foo (int x)
+{
+ [[omp::directive (parallel)]]
+ #pragma omp for // { dg-error "mixing OpenMP directives with attribute and pragma syntax on the same statement" }
+ for (int i = 0; i < 16; i++)
+ ;
+ [[omp::directive (barrier)]] // { dg-error "standalone OpenMP directives in 'omp::directive' attribute can only appear on an empty statement" }
+ #pragma omp flush
+ ;
+ #pragma omp parallel
+ [[omp::directive (master)]] // { dg-error "mixing OpenMP directives with attribute and pragma syntax on the same statement" }
+ ;
+ #pragma omp teams
+ [[omp::sequence (directive (parallel), directive (master))]] // { dg-error "mixing OpenMP directives with attribute and pragma syntax on the same statement" }
+ ;
+ #pragma omp task
+ [[omp::directive (flush)]] // { dg-error "mixing OpenMP directives with attribute and pragma syntax on the same statement" }
+ ;
+ #pragma omp master
+ [[omp::directive (flush)]] // { dg-error "mixing OpenMP directives with attribute and pragma syntax on the same statement" }
+ ;
+ #pragma omp for ordered
+ for (int i = 0; i < 16; i++)
+ #pragma omp ordered
+ [[omp::directive (flush)]] // { dg-error "mixing OpenMP directives with attribute and pragma syntax on the same statement" }
+ ;
+ #pragma omp single
+ [[omp::directive (flush)]] // { dg-error "mixing OpenMP directives with attribute and pragma syntax on the same statement" }
+ ;
+ #pragma omp taskgroup
+ [[omp::directive (taskyield)]] // { dg-error "mixing OpenMP directives with attribute and pragma syntax on the same statement" }
+ ;
+ #pragma omp target data map (tofrom: x)
+ [[omp::directive (flush)]] // { dg-error "mixing OpenMP directives with attribute and pragma syntax on the same statement" }
+ ;
+ #pragma omp target
+ [[omp::directive (teams)]] // { dg-error "mixing OpenMP directives with attribute and pragma syntax on the same statement" }
+ ;
+ [[omp::directive (parallel)]]
+ #pragma omp master // { dg-error "mixing OpenMP directives with attribute and pragma syntax on the same statement" }
+ [[omp::sequence (omp::directive (taskloop))]] // { dg-error "mixing OpenMP directives with attribute and pragma syntax on the same statement" }
+ for (int i = 0; i < 16; i++)
+ ;
+ #pragma omp parallel
+ [[omp::directive (for)]] // { dg-error "mixing OpenMP directives with attribute and pragma syntax on the same statement" }
+ for (int i = 0; i < 16; i++)
+ ;
+ #pragma omp for
+ [[omp::directive (master)]] // { dg-error "for statement expected before '\\\[' token" }
+ ;
+ #pragma omp target teams
+ [[omp::directive (parallel)]] // { dg-error "mixing OpenMP directives with attribute and pragma syntax on the same statement" }
+ ;
+ #pragma omp parallel master
+ [[omp::directive (taskloop)]] // { dg-error "mixing OpenMP directives with attribute and pragma syntax on the same statement" }
+ for (int i = 0; i < 16; i++)
+ ;
+}
--- /dev/null
+// { dg-do compile { target c++11 } }
+
+typedef struct __attribute__((__aligned__ (sizeof (void *)))) omp_depend_t {
+ char __omp_depend_t__[2 * sizeof (void *)];
+} omp_depend_t;
+
+void
+foo (int x)
+{
+ #pragma omp barrier
+ [[omp::directive (barrier)]];
+ #pragma omp parallel
+ {
+ #pragma omp cancel parallel
+ [[omp::directive (cancellation point, parallel)]];
+ }
+ #pragma omp parallel
+ {
+ #pragma omp cancellation point parallel
+ [[omp::directive (cancel parallel)]];
+ }
+ #pragma omp parallel
+ {
+ [[omp::directive (cancel, parallel)]];
+ #pragma omp cancellation point parallel
+ }
+ omp_depend_t depobj;
+ #pragma omp depobj(depobj) update(inout)
+ [[omp::directive (depobj(depobj), destroy)]];
+ #pragma omp flush
+ [[omp::directive (flush)]];
+ #pragma omp target enter data map (to: x)
+ [[omp::directive (target exit data, map (from: x))]];
+ [[omp::directive (target enter data, map (to: x))]];
+ #pragma omp target exit data map (from: x)
+ [[omp::directive (flush)]];
+ #pragma omp target update to (x)
+ [[omp::directive (flush)]];
+ #pragma omp taskwait
+ [[omp::directive (flush)]];
+ #pragma omp taskyield
+ [[omp::directive (flush)]];
+ extern int t;
+ #pragma omp threadprivate (t)
+ [[omp::directive (flush)]];
+}