aboutsummaryrefslogtreecommitdiff
path: root/gcc
diff options
context:
space:
mode:
Diffstat (limited to 'gcc')
-rw-r--r--gcc/cp/parser.c105
-rw-r--r--gcc/cp/parser.h4
-rw-r--r--gcc/testsuite/g++.dg/gomp/attrs-1.C12
-rw-r--r--gcc/testsuite/g++.dg/gomp/attrs-2.C12
-rw-r--r--gcc/testsuite/g++.dg/gomp/attrs-6.C50
-rw-r--r--gcc/testsuite/g++.dg/gomp/attrs-7.C64
-rw-r--r--gcc/testsuite/g++.dg/gomp/attrs-8.C10
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))]];
+}