* [committed] openmp: Diagnose invalid mixing of the attribute and pragma syntax directives
@ 2021-07-23 8:09 Jakub Jelinek
0 siblings, 0 replies; only message in thread
From: Jakub Jelinek @ 2021-07-23 8:09 UTC (permalink / raw)
To: gcc-patches
Hi!
The OpenMP 5.1 spec says that the attribute and pragma syntax directives
should not be mixed on the same statement. The following patch adds diagnostic
for that,
[[omp::directive (...)]]
#pragma omp ...
is always an error and for the other order
#pragma omp ...
[[omp::directive (...)]]
it depends on whether the pragma directive is an OpenMP construct
(then it is an error because it needs a structured block or loop
or statement as body) or e.g. a standalone directive (then it is fine).
Only block scope is handled for now though, namespace scope and class scope
still needs implementing even the basic support.
Bootstrapped/regtested on x86_64-linux and i686-linux, committed to trunk.
2021-07-23 Jakub Jelinek <jakub@redhat.com>
gcc/c-family/
* c-pragma.h (enum pragma_kind): Add PRAGMA_OMP__START_ and
PRAGMA_OMP__LAST_ enumerators.
gcc/cp/
* parser.h (struct cp_parser): Add omp_attrs_forbidden_p member.
* parser.c (cp_parser_handle_statement_omp_attributes): Diagnose
mixing of attribute and pragma syntax directives when seeing
omp::directive if parser->omp_attrs_forbidden_p or if attribute syntax
directives are followed by OpenMP pragma.
(cp_parser_statement): Clear parser->omp_attrs_forbidden_p after
the cp_parser_handle_statement_omp_attributes call.
(cp_parser_omp_structured_block): Add disallow_omp_attrs argument,
if true, set parser->omp_attrs_forbidden_p.
(cp_parser_omp_scan_loop_body, cp_parser_omp_sections_scope): Pass
false as disallow_omp_attrs to cp_parser_omp_structured_block.
(cp_parser_omp_parallel, cp_parser_omp_task): Set
parser->omp_attrs_forbidden_p.
gcc/testsuite/
* g++.dg/gomp/attrs-4.C: New test.
* g++.dg/gomp/attrs-5.C: New test.
--- gcc/c-family/c-pragma.h.jj 2021-07-22 12:37:20.409533286 +0200
+++ gcc/c-family/c-pragma.h 2021-07-22 12:44:57.903028283 +0200
@@ -42,7 +42,9 @@ enum pragma_kind {
PRAGMA_OACC_UPDATE,
PRAGMA_OACC_WAIT,
+ /* PRAGMA_OMP__START_ should be equal to the first PRAGMA_OMP_* code. */
PRAGMA_OMP_ALLOCATE,
+ PRAGMA_OMP__START_ = PRAGMA_OMP_ALLOCATE,
PRAGMA_OMP_ATOMIC,
PRAGMA_OMP_BARRIER,
PRAGMA_OMP_CANCEL,
@@ -72,6 +74,8 @@ enum pragma_kind {
PRAGMA_OMP_TASKYIELD,
PRAGMA_OMP_THREADPRIVATE,
PRAGMA_OMP_TEAMS,
+ /* PRAGMA_OMP__LAST_ should be equal to the last PRAGMA_OMP_* code. */
+ PRAGMA_OMP__LAST_ = PRAGMA_OMP_TEAMS,
PRAGMA_GCC_PCH_PREPROCESS,
PRAGMA_IVDEP,
--- gcc/cp/parser.h.jj 2021-07-02 21:59:12.350171752 +0200
+++ gcc/cp/parser.h 2021-07-22 15:26:41.905013091 +0200
@@ -398,6 +398,9 @@ struct GTY(()) cp_parser {
identifiers) rather than an explicit template parameter list. */
bool fully_implicit_function_template_p;
+ /* TRUE if omp::directive or omp::sequence attributes may not appear. */
+ bool omp_attrs_forbidden_p;
+
/* Tracks the function's template parameter list when declaring a function
using generic type parameters. This is either a new chain in the case of a
fully implicit function template or an extension of the function's existing
--- gcc/cp/parser.c.jj 2021-07-22 12:37:20.445532774 +0200
+++ gcc/cp/parser.c 2021-07-22 17:47:26.025761491 +0200
@@ -11665,6 +11665,7 @@ cp_parser_handle_statement_omp_attribute
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)))
@@ -11676,6 +11677,14 @@ cp_parser_handle_statement_omp_attribute
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++)
{
@@ -11731,6 +11740,9 @@ cp_parser_handle_statement_omp_attribute
else
pa = &TREE_CHAIN (*pa);
+ if (bad)
+ return attrs;
+
unsigned int i;
cp_omp_attribute_data *v;
cp_omp_attribute_data *construct_seen = nullptr;
@@ -11780,6 +11792,18 @@ cp_parser_handle_statement_omp_attribute
" 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;
@@ -11904,6 +11928,7 @@ cp_parser_statement (cp_parser* parser,
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);
@@ -39391,11 +39416,14 @@ cp_parser_end_omp_structured_block (cp_p
}
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);
@@ -40761,7 +40789,7 @@ cp_parser_omp_scan_loop_body (cp_parser
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);
@@ -40796,7 +40824,7 @@ cp_parser_omp_scan_loop_body (cp_parser
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);
@@ -41597,7 +41625,7 @@ cp_parser_omp_sections_scope (cp_parser
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);
}
@@ -41622,7 +41650,7 @@ cp_parser_omp_sections_scope (cp_parser
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);
}
@@ -41842,6 +41870,7 @@ cp_parser_omp_parallel (cp_parser *parse
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);
@@ -41904,6 +41933,7 @@ cp_parser_omp_task (cp_parser *parser, c
"#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);
--- gcc/testsuite/g++.dg/gomp/attrs-4.C.jj 2021-07-22 16:32:23.295177963 +0200
+++ gcc/testsuite/g++.dg/gomp/attrs-4.C 2021-07-22 18:34:59.823183344 +0200
@@ -0,0 +1,61 @@
+// { 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++)
+ ;
+}
--- gcc/testsuite/g++.dg/gomp/attrs-5.C.jj 2021-07-22 18:30:03.934285592 +0200
+++ gcc/testsuite/g++.dg/gomp/attrs-5.C 2021-07-22 18:31:39.517960417 +0200
@@ -0,0 +1,46 @@
+// { 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)]];
+}
Jakub
^ permalink raw reply [flat|nested] only message in thread
only message in thread, other threads:[~2021-07-23 8:09 UTC | newest]
Thread overview: (only message) (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2021-07-23 8:09 [committed] openmp: Diagnose invalid mixing of the attribute and pragma syntax directives Jakub Jelinek
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).