@@ -204,5 +204,6 @@ extern void c_parser_declspecs (c_parser
bool, bool, bool, bool, bool,
enum c_lookahead_kind);
extern struct c_type_name *c_parser_type_name (c_parser *, bool = false);
+extern bool c_maybe_parse_omp_decl (tree, tree);
#endif
@@ -262,6 +262,10 @@ struct GTY(()) c_parser {
attributes turned into pragma, vector of tokens created from that,
otherwise NULL. */
vec<c_token, va_gc> *in_omp_attribute_pragma;
+
+ /* Set for omp::decl attribute parsing to the decl to which it
+ appertains. */
+ tree in_omp_decl_attribute;
};
/* Return a pointer to the Nth token in PARSERs tokens_buf. */
@@ -5797,14 +5801,14 @@ c_parser_std_attribute (c_parser *parser
parens.skip_until_found_close (parser);
return attribute;
}
-/* else if (is_attribute_p ("decl", name))
+ else if (is_attribute_p ("decl", name))
{
TREE_VALUE (TREE_PURPOSE (attribute))
= get_identifier ("directive");
c_parser_omp_directive_args (parser, attribute, true);
parens.skip_until_found_close (parser);
return attribute;
- } */
+ }
else if (is_attribute_p ("sequence", name))
{
TREE_VALUE (TREE_PURPOSE (attribute))
@@ -15147,6 +15151,19 @@ c_parser_omp_var_list_parens (c_parser *
/* The clauses location. */
location_t loc = c_parser_peek_token (parser)->location;
+ if (parser->in_omp_decl_attribute)
+ {
+ if (kind)
+ {
+ tree u = build_omp_clause (loc, kind);
+ OMP_CLAUSE_DECL (u) = parser->in_omp_decl_attribute;
+ OMP_CLAUSE_CHAIN (u) = list;
+ return u;
+ }
+ else
+ return tree_cons (parser->in_omp_decl_attribute, NULL_TREE, list);
+ }
+
matching_parens parens;
if (parens.require_open (parser))
{
@@ -24498,6 +24515,84 @@ c_finish_omp_declare_simd (c_parser *par
clauses[0].type = CPP_PRAGMA;
}
+/* D should be C_TOKEN_VEC from omp::decl attribute. If it contains
+ a threadprivate, groupprivate, allocate or declare target directive,
+ return true and parse it for DECL. */
+
+bool
+c_maybe_parse_omp_decl (tree decl, tree d)
+{
+ gcc_assert (TREE_CODE (d) == C_TOKEN_VEC);
+ vec<c_token, va_gc> *toks = C_TOKEN_VEC_TOKENS (d);
+ c_token *first = toks->address ();
+ c_token *last = first + toks->length ();
+ const char *directive[3] = {};
+ for (int j = 0; j < 3; j++)
+ {
+ tree id = NULL_TREE;
+ if (first + j == last)
+ break;
+ if (first[j].type == CPP_NAME)
+ id = first[j].value;
+ else if (first[j].type == CPP_KEYWORD)
+ id = ridpointers[(int) first[j].keyword];
+ else
+ break;
+ directive[j] = IDENTIFIER_POINTER (id);
+ }
+ const c_omp_directive *dir = NULL;
+ if (directive[0])
+ dir = c_omp_categorize_directive (directive[0], directive[1],
+ directive[2]);
+ if (dir == NULL)
+ {
+ error_at (first->location,
+ "unknown OpenMP directive name in "
+ "%qs attribute argument", "omp::decl");
+ return false;
+ }
+ if (dir->id != PRAGMA_OMP_THREADPRIVATE
+ /* && dir->id != PRAGMA_OMP_GROUPPRIVATE */
+ && dir->id != PRAGMA_OMP_ALLOCATE
+ && (dir->id != PRAGMA_OMP_DECLARE
+ || strcmp (directive[1], "target") != 0))
+ return false;
+
+ if (!flag_openmp && !dir->simd)
+ return true;
+
+ c_parser *parser = the_parser;
+ unsigned int tokens_avail = parser->tokens_avail;
+ gcc_assert (parser->tokens == &parser->tokens_buf[0]);
+ toks = NULL;
+ vec_safe_reserve (toks, last - first + 2, true);
+ c_token tok = {};
+ tok.type = CPP_PRAGMA;
+ tok.keyword = RID_MAX;
+ tok.pragma_kind = pragma_kind (dir->id);
+ tok.location = first->location;
+ toks->quick_push (tok);
+ while (++first < last)
+ toks->quick_push (*first);
+ tok = {};
+ tok.type = CPP_PRAGMA_EOL;
+ tok.keyword = RID_MAX;
+ tok.location = last[-1].location;
+ toks->quick_push (tok);
+ tok = {};
+ tok.type = CPP_EOF;
+ tok.keyword = RID_MAX;
+ tok.location = last[-1].location;
+ tok.flags = tokens_avail;
+ toks->quick_push (tok);
+ parser->in_omp_decl_attribute = decl;
+ parser->tokens = toks->address ();
+ parser->tokens_avail = toks->length ();
+ parser->in_omp_attribute_pragma = toks;
+ c_parser_pragma (parser, pragma_external, NULL);
+ parser->in_omp_decl_attribute = NULL_TREE;
+ return true;
+}
/* OpenMP 4.0:
# pragma omp declare target new-line
@@ -24526,7 +24621,8 @@ c_parser_omp_declare_target (c_parser *p
&& c_parser_peek_2nd_token (parser)->type == CPP_NAME))
clauses = c_parser_omp_all_clauses (parser, OMP_DECLARE_TARGET_CLAUSE_MASK,
"#pragma omp declare target");
- else if (c_parser_next_token_is (parser, CPP_OPEN_PAREN))
+ else if (parser->in_omp_decl_attribute
+ || c_parser_next_token_is (parser, CPP_OPEN_PAREN))
{
clauses = c_parser_omp_var_list_parens (parser, OMP_CLAUSE_ENTER,
clauses);
@@ -5385,11 +5385,11 @@ c_decl_attributes (tree *node, tree attr
{
tree d = TREE_VALUE (a);
gcc_assert (TREE_CODE (d) == C_TOKEN_VEC);
-/* if (TREE_PUBLIC (d)
- && (VAR_P (*decl)
- || TREE_CODE (*decl) == FUNCTION_DECL)
- && c_maybe_parse_omp_decl (*decl, d))
- continue; */
+ if (TREE_PUBLIC (d)
+ && (VAR_P (*node)
+ || TREE_CODE (*node) == FUNCTION_DECL)
+ && c_maybe_parse_omp_decl (*node, d))
+ continue;
p = TREE_PUBLIC (d) ? "decl" : "directive";
}
if (p && !diagnosed)
@@ -0,0 +1,69 @@
+/* { dg-do compile } */
+/* { dg-options "-fopenmp -std=c2x" } */
+
+void foo1 ();
+
+void
+foo ()
+{
+ [[omp::decl (declare variant (foo1) match (construct={parallel,for}))]]
+ extern void foo2 ();
+ [[omp::sequence (directive (parallel), directive (for))]]
+ for (int i = 0; i < 5; i++)
+ foo2 ();
+ [[omp::decl (declare simd simdlen(4) linear(l) aligned(p:4) uniform(p) inbranch),
+ omp::directive (declare simd simdlen(8) notinbranch)]]
+ extern int foo3 (int l, int *p);
+ [[omp::directive (declare simd simdlen(4) linear(l) aligned(p:4) uniform(p) inbranch),
+ omp::decl (declare simd simdlen(8) notinbranch)]]
+ extern int foo4 (int l, int *p);
+ [[omp::decl (declare simd simdlen(4) linear(l) aligned(p:4) uniform(p) inbranch),
+ omp::decl (declare simd simdlen(8) notinbranch)]]
+ extern int foo5 (int l, int *p);
+}
+
+void bar1 ();
+
+void
+bar ()
+{
+ [[omp :: decl (declare variant (bar1), match (construct={parallel,for}))]]
+ extern void bar2 ();
+ [[omp::sequence (directive (parallel), directive (for))]]
+ for (int i = 0; i < 5; i++)
+ bar2 ();
+ [[omp::decl (declare simd, simdlen(4), linear(l), aligned(p:4),uniform(p),inbranch),
+ omp::directive (declare simd simdlen(8) notinbranch)]]
+ extern int bar3 (int l, int *p);
+ [[omp::directive (declare simd,simdlen(4),linear(l),aligned(p:4),uniform(p),inbranch),
+ omp::decl (declare simd, simdlen(8), notinbranch)]]
+ extern int bar4 (int l, int *p);
+ [[omp::decl (declare simd, simdlen(4), linear(l), aligned(p:4), uniform(p), inbranch),
+ omp::decl (declare simd, simdlen(8), notinbranch)]]
+ extern int bar5 (int l, int *p);
+}
+
+struct S { int s; };
+
+[[omp::decl (threadprivate)]] int t1, t2;
+int x1, t3 [[omp::decl (threadprivate)]], x2, t4 [[omp::decl (threadprivate)]] [5];
+[[maybe_unused, omp::decl (threadprivate)]] int t5, t6;
+[[omp::decl (threadprivate)]] struct S t7, t8;
+[[omp::decl (declare target enter device_type (host))]] int d1, d2, d3 (int, int), d4;
+int x3, d5 [[omp::decl (declare target, enter, device_type (any))]], d6 [[omp::decl (declare target link)]], x4;
+int d7 [[omp::decl (declare target)]];
+[[omp::decl (declare target), omp::decl (declare target)]] int d8, d9;
+
+void
+baz ()
+{
+ [[omp::decl (threadprivate)]] static int t1, t2;
+ static int x1, t3 [[omp::decl (threadprivate)]], x2, t4 [[omp::decl (threadprivate)]] [5];
+ [[maybe_unused, omp::decl (threadprivate)]] extern int t5, t6;
+ [[omp::decl (declare target enter)]] extern int d1, d2, d3 (int, int), d4;
+ static int x3, d5 [[omp::decl (declare target, enter, device_type (any))]], d6 [[omp::decl (declare target link)]], x4;
+ ++t1; ++t2;
+ ++t3; ++t4[2];
+ ++t5; ++t6;
+ ++d1;
+}
@@ -0,0 +1,192 @@
+/* { dg-do compile } */
+/* { dg-options "-fopenmp -std=c2x -ffat-lto-objects -fdump-tree-gimple" } */
+
+extern void abort ();
+
+[[omp::decl (declare simd, linear (l))]] extern int f1 (int l);
+extern int f2 (int), f3 [[omp::decl (declare simd, uniform (m))]] (int m), f4 (int), z;
+[[omp::decl (declare simd, linear (l), simdlen(4))]] extern int f5 [[omp::decl (declare simd uniform (l) simdlen (8) notinbranch)]] (int l);
+
+int
+f1 (int l)
+{
+ return l;
+}
+
+/* { dg-final { scan-assembler-times "_ZGVbM4l_f1:" 1 { target { i?86-*-* x86_64-*-* } } } } */
+/* { dg-final { scan-assembler-times "_ZGVbN4l_f1:" 1 { target { i?86-*-* x86_64-*-* } } } } */
+/* { dg-final { scan-assembler-times "_ZGVcM4l_f1:" 1 { target { i?86-*-* x86_64-*-* } } } } */
+/* { dg-final { scan-assembler-times "_ZGVcN4l_f1:" 1 { target { i?86-*-* x86_64-*-* } } } } */
+/* { dg-final { scan-assembler-times "_ZGVdM8l_f1:" 1 { target { i?86-*-* x86_64-*-* } } } } */
+/* { dg-final { scan-assembler-times "_ZGVdN8l_f1:" 1 { target { i?86-*-* x86_64-*-* } } } } */
+/* { dg-final { scan-assembler-times "_ZGVeM16l_f1:" 1 { target { i?86-*-* x86_64-*-* } } } } */
+/* { dg-final { scan-assembler-times "_ZGVeN16l_f1:" 1 { target { i?86-*-* x86_64-*-* } } } } */
+
+int
+f2 (int l)
+{
+ return l + 1;
+}
+
+/* { dg-final { scan-assembler-not "_ZGV\[a-zA-Z0-9]_f2:" { target { i?86-*-* x86_64-*-* } } } } */
+
+int
+f3 (int l)
+{
+ return l + 2;
+}
+
+/* { dg-final { scan-assembler-times "_ZGVbM4u_f3:" 1 { target { i?86-*-* x86_64-*-* } } } } */
+/* { dg-final { scan-assembler-times "_ZGVbN4u_f3:" 1 { target { i?86-*-* x86_64-*-* } } } } */
+/* { dg-final { scan-assembler-times "_ZGVcM4u_f3:" 1 { target { i?86-*-* x86_64-*-* } } } } */
+/* { dg-final { scan-assembler-times "_ZGVcN4u_f3:" 1 { target { i?86-*-* x86_64-*-* } } } } */
+/* { dg-final { scan-assembler-times "_ZGVdM8u_f3:" 1 { target { i?86-*-* x86_64-*-* } } } } */
+/* { dg-final { scan-assembler-times "_ZGVdN8u_f3:" 1 { target { i?86-*-* x86_64-*-* } } } } */
+/* { dg-final { scan-assembler-times "_ZGVeM16u_f3:" 1 { target { i?86-*-* x86_64-*-* } } } } */
+/* { dg-final { scan-assembler-times "_ZGVeN16u_f3:" 1 { target { i?86-*-* x86_64-*-* } } } } */
+
+int
+f4 (int l)
+{
+ return l + 3;
+}
+
+/* { dg-final { scan-assembler-not "_ZGV\[a-zA-Z0-9]_f4:" { target { i?86-*-* x86_64-*-* } } } } */
+
+int
+f5 (int l)
+{ /* { dg-warning "GCC does not currently support simdlen 8 for type 'int'" "" { target aarch64*-*-* } .-1 } */
+ return l + 4;
+}
+
+/* { dg-final { scan-assembler-times "_ZGVbM4l_f5:" 1 { target { i?86-*-* x86_64-*-* } } } } */
+/* { dg-final { scan-assembler-times "_ZGVbN4l_f5:" 1 { target { i?86-*-* x86_64-*-* } } } } */
+/* { dg-final { scan-assembler-times "_ZGVcM4l_f5:" 1 { target { i?86-*-* x86_64-*-* } } } } */
+/* { dg-final { scan-assembler-times "_ZGVcN4l_f5:" 1 { target { i?86-*-* x86_64-*-* } } } } */
+/* { dg-final { scan-assembler-times "_ZGVdM4l_f5:" 1 { target { i?86-*-* x86_64-*-* } } } } */
+/* { dg-final { scan-assembler-times "_ZGVdN4l_f5:" 1 { target { i?86-*-* x86_64-*-* } } } } */
+/* { dg-final { scan-assembler-times "_ZGVeM4l_f5:" 1 { target { i?86-*-* x86_64-*-* } } } } */
+/* { dg-final { scan-assembler-times "_ZGVeN4l_f5:" 1 { target { i?86-*-* x86_64-*-* } } } } */
+/* { dg-final { scan-assembler-times "_ZGVbN8u_f5:" 1 { target { i?86-*-* x86_64-*-* } } } } */
+/* { dg-final { scan-assembler-times "_ZGVcN8u_f5:" 1 { target { i?86-*-* x86_64-*-* } } } } */
+/* { dg-final { scan-assembler-times "_ZGVdN8u_f5:" 1 { target { i?86-*-* x86_64-*-* } } } } */
+/* { dg-final { scan-assembler-times "_ZGVeN8u_f5:" 1 { target { i?86-*-* x86_64-*-* } } } } */
+/* { dg-final { scan-assembler-not "_ZGV\[bcde]M8u_f5:" { target { i?86-*-* x86_64-*-* } } } } */
+
+[[omp::decl (declare simd, linear (l), simdlen(4), notinbranch),
+ omp::decl (declare simd, uniform (l), simdlen(4), inbranch)]]
+int
+f6 [[omp::decl (declare simd uniform (l) simdlen (8), notinbranch),
+ omp::decl (declare simd linear (l) simdlen (8) inbranch)]] (int l)
+{ /* { dg-warning "GCC does not currently support simdlen 8 for type 'int'" "" { target aarch64*-*-* } .-2 } */
+ return l + 5;
+}
+
+/* { dg-final { scan-assembler-times "_ZGVbM4u_f6:" 1 { target { i?86-*-* x86_64-*-* } } } } */
+/* { dg-final { scan-assembler-times "_ZGVbN4l_f6:" 1 { target { i?86-*-* x86_64-*-* } } } } */
+/* { dg-final { scan-assembler-times "_ZGVbM8l_f6:" 1 { target { i?86-*-* x86_64-*-* } } } } */
+/* { dg-final { scan-assembler-times "_ZGVbN8u_f6:" 1 { target { i?86-*-* x86_64-*-* } } } } */
+/* { dg-final { scan-assembler-times "_ZGVcM4u_f6:" 1 { target { i?86-*-* x86_64-*-* } } } } */
+/* { dg-final { scan-assembler-times "_ZGVcN4l_f6:" 1 { target { i?86-*-* x86_64-*-* } } } } */
+/* { dg-final { scan-assembler-times "_ZGVcM8l_f6:" 1 { target { i?86-*-* x86_64-*-* } } } } */
+/* { dg-final { scan-assembler-times "_ZGVcN8u_f6:" 1 { target { i?86-*-* x86_64-*-* } } } } */
+/* { dg-final { scan-assembler-times "_ZGVdM4u_f6:" 1 { target { i?86-*-* x86_64-*-* } } } } */
+/* { dg-final { scan-assembler-times "_ZGVdN4l_f6:" 1 { target { i?86-*-* x86_64-*-* } } } } */
+/* { dg-final { scan-assembler-times "_ZGVdM8l_f6:" 1 { target { i?86-*-* x86_64-*-* } } } } */
+/* { dg-final { scan-assembler-times "_ZGVdN8u_f6:" 1 { target { i?86-*-* x86_64-*-* } } } } */
+/* { dg-final { scan-assembler-times "_ZGVeM4u_f6:" 1 { target { i?86-*-* x86_64-*-* } } } } */
+/* { dg-final { scan-assembler-times "_ZGVeN4l_f6:" 1 { target { i?86-*-* x86_64-*-* } } } } */
+/* { dg-final { scan-assembler-times "_ZGVeM8l_f6:" 1 { target { i?86-*-* x86_64-*-* } } } } */
+/* { dg-final { scan-assembler-times "_ZGVeN8u_f6:" 1 { target { i?86-*-* x86_64-*-* } } } } */
+/* { dg-final { scan-assembler-not "_ZGV\[bcde]M4l_f6:" { target { i?86-*-* x86_64-*-* } } } } */
+/* { dg-final { scan-assembler-not "_ZGV\[bcde]N4u_f6:" { target { i?86-*-* x86_64-*-* } } } } */
+/* { dg-final { scan-assembler-not "_ZGV\[bcde]M8u_f6:" { target { i?86-*-* x86_64-*-* } } } } */
+/* { dg-final { scan-assembler-not "_ZGV\[bcde]N8l_f6:" { target { i?86-*-* x86_64-*-* } } } } */
+
+int
+f7 (int l)
+{
+ return l + 6;
+}
+
+/* { dg-final { scan-assembler-not "_ZGV\[a-zA-Z0-9]_f7:" { target { i?86-*-* x86_64-*-* } } } } */
+
+int
+f8 (int l)
+{
+ return l + 7;
+}
+
+/* { dg-final { scan-assembler-not "_ZGV\[a-zA-Z0-9]_f8:" { target { i?86-*-* x86_64-*-* } } } } */
+
+[[omp::decl (declare variant (f7), match (construct={parallel})),
+ omp::decl (declare simd uniform (l), simdlen(4))]]
+int
+f9 [[omp::decl (declare simd uniform (l) simdlen (8)),
+ omp::decl (declare variant (f8) match (construct={parallel,for}))]] (int l)
+{ /* { dg-warning "GCC does not currently support simdlen 8 for type 'int'" "" { target aarch64*-*-* } .-2 } */
+ return l + 8;
+}
+
+/* { dg-final { scan-assembler-times "_ZGVbM4u_f9:" 1 { target { i?86-*-* x86_64-*-* } } } } */
+/* { dg-final { scan-assembler-times "_ZGVbN4u_f9:" 1 { target { i?86-*-* x86_64-*-* } } } } */
+/* { dg-final { scan-assembler-times "_ZGVcM4u_f9:" 1 { target { i?86-*-* x86_64-*-* } } } } */
+/* { dg-final { scan-assembler-times "_ZGVcN4u_f9:" 1 { target { i?86-*-* x86_64-*-* } } } } */
+/* { dg-final { scan-assembler-times "_ZGVdM4u_f9:" 1 { target { i?86-*-* x86_64-*-* } } } } */
+/* { dg-final { scan-assembler-times "_ZGVdN4u_f9:" 1 { target { i?86-*-* x86_64-*-* } } } } */
+/* { dg-final { scan-assembler-times "_ZGVeM4u_f9:" 1 { target { i?86-*-* x86_64-*-* } } } } */
+/* { dg-final { scan-assembler-times "_ZGVeN4u_f9:" 1 { target { i?86-*-* x86_64-*-* } } } } */
+/* { dg-final { scan-assembler-times "_ZGVbM8u_f9:" 1 { target { i?86-*-* x86_64-*-* } } } } */
+/* { dg-final { scan-assembler-times "_ZGVbN8u_f9:" 1 { target { i?86-*-* x86_64-*-* } } } } */
+/* { dg-final { scan-assembler-times "_ZGVcM8u_f9:" 1 { target { i?86-*-* x86_64-*-* } } } } */
+/* { dg-final { scan-assembler-times "_ZGVcN8u_f9:" 1 { target { i?86-*-* x86_64-*-* } } } } */
+/* { dg-final { scan-assembler-times "_ZGVdM8u_f9:" 1 { target { i?86-*-* x86_64-*-* } } } } */
+/* { dg-final { scan-assembler-times "_ZGVdN8u_f9:" 1 { target { i?86-*-* x86_64-*-* } } } } */
+/* { dg-final { scan-assembler-times "_ZGVeM8u_f9:" 1 { target { i?86-*-* x86_64-*-* } } } } */
+/* { dg-final { scan-assembler-times "_ZGVeN8u_f9:" 1 { target { i?86-*-* x86_64-*-* } } } } */
+
+int z;
+
+void
+test ()
+{
+ [[omp::directive (parallel)]]
+ if (f9 (3) != 9)
+ abort ();
+ [[omp::directive (parallel for)]]
+ for (int i = 0; i < 1; i++)
+ if (f9 (4) != 11)
+ abort ();
+ if (f9 (5) != 13)
+ abort ();
+}
+
+/* { dg-final { scan-tree-dump-times " = f7 \\\(3\\\);" 1 "gimple" } } */
+/* { dg-final { scan-tree-dump-times " = f8 \\\(4\\\);" 1 "gimple" } } */
+/* { dg-final { scan-tree-dump-times " = f9 \\\(5\\\);" 1 "gimple" } } */
+
+int
+f10 (int x)
+{
+ return x;
+}
+
+[[omp::decl (declare simd, notinbranch)]] int f10 (int);
+
+/* { dg-final { scan-assembler-times "_ZGVbN4v_f10:" 1 { target { i?86-*-* x86_64-*-* } } } } */
+/* { dg-final { scan-assembler-times "_ZGVcN4v_f10:" 1 { target { i?86-*-* x86_64-*-* } } } } */
+/* { dg-final { scan-assembler-times "_ZGVdN8v_f10:" 1 { target { i?86-*-* x86_64-*-* } } } } */
+/* { dg-final { scan-assembler-times "_ZGVeN16v_f10:" 1 { target { i?86-*-* x86_64-*-* } } } } */
+
+int
+f11 (int x)
+{
+ return x + 1;
+}
+
+int f11 [[omp::decl (declare simd inbranch linear(x))]] (int x);
+
+/* { dg-final { scan-assembler-times "_ZGVbM4l_f11:" 1 { target { i?86-*-* x86_64-*-* } } } } */
+/* { dg-final { scan-assembler-times "_ZGVcM4l_f11:" 1 { target { i?86-*-* x86_64-*-* } } } } */
+/* { dg-final { scan-assembler-times "_ZGVdM8l_f11:" 1 { target { i?86-*-* x86_64-*-* } } } } */
+/* { dg-final { scan-assembler-times "_ZGVeM16l_f11:" 1 { target { i?86-*-* x86_64-*-* } } } } */
@@ -0,0 +1,28 @@
+/* { dg-do compile } */
+/* { dg-options "-fopenmp -std=c2x" */
+
+void
+foo ()
+{
+ [[omp::decl]] int v1; /* { dg-error "'omp::decl' attribute requires argument" } */
+ [[omp::decl ()]] int v2; /* { dg-error "expected OpenMP directive name" } */
+ /* { dg-error "'omp::directive' not allowed to be specified in this context" "" { target *-*-* } .-1 } */
+ [[omp::decl (nonexistent foobar)]] int v3; /* { dg-error "unknown OpenMP directive name in 'omp::decl' attribute argument" } */
+ /* { dg-error "'omp::directive' not allowed to be specified in this context" "" { target *-*-* } .-1 } */
+ [[omp::sequence(decl(threadprivate))]] int v4; /* { dg-error "expected 'directive' or 'sequence'" } */
+ /* { dg-error "'omp::directive' not allowed to be specified in this context" "" { target *-*-* } .-1 } */
+ [[omp::sequence(omp::decl(threadprivate))]] int v5; /* { dg-error "expected 'directive' or 'sequence'" } */
+ /* { dg-error "'omp::directive' not allowed to be specified in this context" "" { target *-*-* } .-1 } */
+ [[omp::decl (barrier)]]; /* { dg-error "OpenMP 'omp::decl' attribute on a statement" } */
+ [[omp::decl (parallel)]] {}; /* { dg-error "OpenMP 'omp::decl' attribute on a statement" } */
+ extern int [[omp::decl (threadprivate)]] *v6; /* { dg-warning "'omp::directive' scoped attribute directive ignored" } */
+ [[omp::decl (threadprivate (v5))]] static int v7; /* { dg-error "expected end of line before '\\\(' token" } */
+ extern int v8;
+ [[omp::decl (declare target (v8))]] static int v9; /* { dg-error "expected end of line before '\\\(' token" } */
+ [[omp::decl (declare target enter (v8))]] static int v10; /* { dg-error "expected an OpenMP clause before '\\\(' token" } */
+ [[omp::decl (declare target, link (v9))]] static int v11; /* { dg-error "expected an OpenMP clause before '\\\(' token" } */
+ [[omp::decl (declare target device_type (any))]] static int v12; /* { dg-error "directive with only 'device_type' clause" } */
+}
+
+int i;
+[[omp::decl (assume (i < 42))]]; /* { dg-error "OpenMP 'omp::decl' attribute on a statement" } */