aboutsummaryrefslogtreecommitdiff
path: root/gcc/cp
diff options
context:
space:
mode:
authorJakub Jelinek <jakub@redhat.com>2019-10-10 09:07:30 +0200
committerJakub Jelinek <jakub@gcc.gnu.org>2019-10-10 09:07:30 +0200
commit94e7f906ca5c73fb79d21ec54733e9e75a96c2b4 (patch)
tree5f686002d13f0905df1681a9408a9d96b23ee258 /gcc/cp
parent6ea20bd0218fd6386cef3701befa653cee6f1101 (diff)
downloadgcc-94e7f906ca5c73fb79d21ec54733e9e75a96c2b4.zip
gcc-94e7f906ca5c73fb79d21ec54733e9e75a96c2b4.tar.gz
gcc-94e7f906ca5c73fb79d21ec54733e9e75a96c2b4.tar.bz2
c-common.h (c_omp_check_context_selector, [...]): Declare.
c-family/ * c-common.h (c_omp_check_context_selector, c_omp_get_context_selector): Declare. * c-omp.c (c_omp_declare_simd_clauses_to_numbers): Fix spelling in diagnostic message. (c_omp_check_context_selector, c_omp_get_context_selector): New functions. * c-attribs.c (c_common_attribute_table): Add "omp declare variant" attribute. (handle_omp_declare_variant_attribute): New function. c/ * c-parser.c (c_parser_omp_all_clauses): Add NESTED_P argument, if true, terminate processing on closing paren and don't skip to end of pragma line. (c_parser_omp_declare_simd): Handle also declare variant. (omp_construct_selectors, omp_device_selectors, omp_implementation_selectors, omp_user_selectors): New variables. (c_parser_omp_context_selector, c_parser_omp_context_selector_specification, c_finish_omp_declare_variant): New functions. (c_finish_omp_declare_simd): Handle both declare simd and declare variant. (c_parser_omp_declare): Handle declare variant. cp/ * parser.h (struct cp_omp_declare_simd_data): Add variant_p member. * parser.c (cp_ensure_no_omp_declare_simd): Handle both declare simd and declare variant. (cp_parser_oacc_all_clauses): Formatting fix. (cp_parser_omp_all_clauses): Add NESTED_P argument, if true, terminate processing on closing paren and don't skip to end of pragma line. (cp_parser_omp_declare_simd): Add VARIANT_P argument. Handle also declare variant. (omp_construct_selectors, omp_device_selectors, omp_implementation_selectors, omp_user_selectors): New variables. (cp_parser_omp_context_selector, cp_parser_omp_context_selector_specification, cp_finish_omp_declare_variant): New functions. (cp_parser_late_parsing_omp_declare_simd): Handle also declare variant. (cp_parser_omp_declare): Handle declare variant. testsuite/ * c-c++-common/gomp/declare-variant-1.c: New test. * c-c++-common/gomp/declare-variant-2.c: New test. * c-c++-common/gomp/declare-variant-3.c: New test. * g++.dg/gomp/this-1.C: Adjust for diagnostic message spelling fix. * gcc.dg/gomp/declare-variant-1.c: New test. * gcc.dg/gomp/declare-variant-2.c: New test. From-SVN: r276789
Diffstat (limited to 'gcc/cp')
-rw-r--r--gcc/cp/ChangeLog18
-rw-r--r--gcc/cp/parser.c506
-rw-r--r--gcc/cp/parser.h3
3 files changed, 500 insertions, 27 deletions
diff --git a/gcc/cp/ChangeLog b/gcc/cp/ChangeLog
index 2a35bf2..9ed7311 100644
--- a/gcc/cp/ChangeLog
+++ b/gcc/cp/ChangeLog
@@ -1,3 +1,21 @@
+2019-10-10 Jakub Jelinek <jakub@redhat.com>
+
+ * parser.h (struct cp_omp_declare_simd_data): Add variant_p member.
+ * parser.c (cp_ensure_no_omp_declare_simd): Handle both declare simd
+ and declare variant.
+ (cp_parser_oacc_all_clauses): Formatting fix.
+ (cp_parser_omp_all_clauses): Add NESTED_P argument, if true, terminate
+ processing on closing paren and don't skip to end of pragma line.
+ (cp_parser_omp_declare_simd): Add VARIANT_P argument. Handle also
+ declare variant.
+ (omp_construct_selectors, omp_device_selectors,
+ omp_implementation_selectors, omp_user_selectors): New variables.
+ (cp_parser_omp_context_selector,
+ cp_parser_omp_context_selector_specification,
+ cp_finish_omp_declare_variant): New functions.
+ (cp_parser_late_parsing_omp_declare_simd): Handle also declare variant.
+ (cp_parser_omp_declare): Handle declare variant.
+
2019-10-09 Jason Merrill <jason@redhat.com>
* cp-tree.h (template_info_decl_check): Check ENABLE_TREE_CHECKING.
diff --git a/gcc/cp/parser.c b/gcc/cp/parser.c
index b6e738c..3ee8da7 100644
--- a/gcc/cp/parser.c
+++ b/gcc/cp/parser.c
@@ -1376,8 +1376,9 @@ cp_ensure_no_omp_declare_simd (cp_parser *parser)
{
if (parser->omp_declare_simd && !parser->omp_declare_simd->error_seen)
{
- error ("%<#pragma omp declare simd%> not immediately followed by "
- "function declaration or definition");
+ error ("%<#pragma omp declare %s%> not immediately followed by "
+ "function declaration or definition",
+ parser->omp_declare_simd->variant_p ? "variant" : "simd");
parser->omp_declare_simd = NULL;
}
}
@@ -35878,8 +35879,8 @@ cp_parser_oacc_clause_async (cp_parser *parser, tree list)
static tree
cp_parser_oacc_all_clauses (cp_parser *parser, omp_clause_mask mask,
- const char *where, cp_token *pragma_tok,
- bool finish_p = true)
+ const char *where, cp_token *pragma_tok,
+ bool finish_p = true)
{
tree clauses = NULL;
bool first = true;
@@ -36075,13 +36076,15 @@ cp_parser_oacc_all_clauses (cp_parser *parser, omp_clause_mask mask,
}
/* Parse all OpenMP clauses. The set clauses allowed by the directive
- is a bitmask in MASK. Return the list of clauses found; the result
- of clause default goes in *pdefault. */
+ is a bitmask in MASK. Return the list of clauses found.
+ FINISH_P set if finish_omp_clauses should be called.
+ NESTED_P set if clauses should be terminated by closing paren instead
+ of end of pragma. */
static tree
cp_parser_omp_all_clauses (cp_parser *parser, omp_clause_mask mask,
const char *where, cp_token *pragma_tok,
- bool finish_p = true)
+ bool finish_p = true, bool nested_p = false)
{
tree clauses = NULL;
bool first = true;
@@ -36096,6 +36099,9 @@ cp_parser_omp_all_clauses (cp_parser *parser, omp_clause_mask mask,
const char *c_name;
tree prev = clauses;
+ if (nested_p && cp_lexer_next_token_is (parser->lexer, CPP_CLOSE_PAREN))
+ break;
+
if (!first && cp_lexer_next_token_is (parser->lexer, CPP_COMMA))
cp_lexer_consume_token (parser->lexer);
@@ -36415,7 +36421,8 @@ cp_parser_omp_all_clauses (cp_parser *parser, omp_clause_mask mask,
}
}
saw_error:
- cp_parser_skip_to_pragma_eol (parser, pragma_tok);
+ if (!nested_p)
+ cp_parser_skip_to_pragma_eol (parser, pragma_tok);
if (finish_p)
{
if ((mask & (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_UNIFORM)) != 0)
@@ -40241,7 +40248,8 @@ cp_parser_oacc_wait (cp_parser *parser, cp_token *pragma_tok)
static void
cp_parser_omp_declare_simd (cp_parser *parser, cp_token *pragma_tok,
- enum pragma_context context)
+ enum pragma_context context,
+ bool variant_p)
{
bool first_p = parser->omp_declare_simd == NULL;
cp_omp_declare_simd_data data;
@@ -40249,12 +40257,22 @@ cp_parser_omp_declare_simd (cp_parser *parser, cp_token *pragma_tok,
{
data.error_seen = false;
data.fndecl_seen = false;
+ data.variant_p = variant_p;
data.tokens = vNULL;
data.clauses = NULL_TREE;
/* It is safe to take the address of a local variable; it will only be
used while this scope is live. */
parser->omp_declare_simd = &data;
}
+ else if (parser->omp_declare_simd->variant_p != variant_p)
+ {
+ error_at (pragma_tok->location,
+ "%<#pragma omp declare %s%> followed by "
+ "%<#pragma omp declare %s%>",
+ parser->omp_declare_simd->variant_p ? "variant" : "simd",
+ parser->omp_declare_simd->variant_p ? "simd" : "variant");
+ parser->omp_declare_simd->error_seen = true;
+ }
/* Store away all pragma tokens. */
while (cp_lexer_next_token_is_not (parser->lexer, CPP_PRAGMA_EOL)
@@ -40290,13 +40308,427 @@ cp_parser_omp_declare_simd (cp_parser *parser, cp_token *pragma_tok,
&& !parser->omp_declare_simd->error_seen
&& !parser->omp_declare_simd->fndecl_seen)
error_at (pragma_tok->location,
- "%<#pragma omp declare simd%> not immediately followed by "
- "function declaration or definition");
+ "%<#pragma omp declare %s%> not immediately followed by "
+ "function declaration or definition",
+ parser->omp_declare_simd->variant_p ? "variant" : "simd");
data.tokens.release ();
parser->omp_declare_simd = NULL;
}
}
+static const char *const omp_construct_selectors[] = {
+ "simd", "target", "teams", "parallel", "for", NULL };
+static const char *const omp_device_selectors[] = {
+ "kind", "isa", "arch", NULL };
+static const char *const omp_implementation_selectors[] = {
+ "vendor", "extension", "atomic_default_mem_order", "unified_address",
+ "unified_shared_memory", "dynamic_allocators", "reverse_offload", NULL };
+static const char *const omp_user_selectors[] = {
+ "condition", NULL };
+
+/* OpenMP 5.0:
+
+ trait-selector:
+ trait-selector-name[([trait-score:]trait-property[,trait-property[,...]])]
+
+ trait-score:
+ score(score-expression) */
+
+static tree
+cp_parser_omp_context_selector (cp_parser *parser, tree set, bool has_parms_p)
+{
+ tree ret = NULL_TREE;
+ do
+ {
+ tree selector;
+ if (cp_lexer_next_token_is (parser->lexer, CPP_KEYWORD)
+ || cp_lexer_next_token_is (parser->lexer, CPP_NAME))
+ selector = cp_lexer_peek_token (parser->lexer)->u.value;
+ else
+ {
+ cp_parser_error (parser, "expected trait selector name");
+ return error_mark_node;
+ }
+
+ tree properties = NULL_TREE;
+ const char *const *selectors = NULL;
+ bool allow_score = true;
+ bool allow_user = false;
+ int property_limit = 0;
+ enum { CTX_PROPERTY_NONE, CTX_PROPERTY_USER, CTX_PROPERTY_IDLIST,
+ CTX_PROPERTY_EXPR, CTX_PROPERTY_SIMD } property_kind
+ = CTX_PROPERTY_NONE;
+ switch (IDENTIFIER_POINTER (set)[0])
+ {
+ case 'c': /* construct */
+ selectors = omp_construct_selectors;
+ allow_score = false;
+ property_limit = 1;
+ property_kind = CTX_PROPERTY_SIMD;
+ break;
+ case 'd': /* device */
+ selectors = omp_device_selectors;
+ allow_score = false;
+ allow_user = true;
+ property_limit = 3;
+ property_kind = CTX_PROPERTY_IDLIST;
+ break;
+ case 'i': /* implementation */
+ selectors = omp_implementation_selectors;
+ allow_user = true;
+ property_limit = 3;
+ property_kind = CTX_PROPERTY_IDLIST;
+ break;
+ case 'u': /* user */
+ selectors = omp_user_selectors;
+ property_limit = 1;
+ property_kind = CTX_PROPERTY_EXPR;
+ break;
+ default:
+ gcc_unreachable ();
+ }
+ for (int i = 0; ; i++)
+ {
+ if (selectors[i] == NULL)
+ {
+ if (allow_user)
+ {
+ property_kind = CTX_PROPERTY_USER;
+ break;
+ }
+ else
+ {
+ error ("selector %qs not allowed for context selector "
+ "set %qs", IDENTIFIER_POINTER (selector),
+ IDENTIFIER_POINTER (set));
+ cp_lexer_consume_token (parser->lexer);
+ return error_mark_node;
+ }
+ }
+ if (i == property_limit)
+ property_kind = CTX_PROPERTY_NONE;
+ if (strcmp (selectors[i], IDENTIFIER_POINTER (selector)) == 0)
+ break;
+ }
+
+ cp_lexer_consume_token (parser->lexer);
+
+ if (cp_lexer_next_token_is (parser->lexer, CPP_OPEN_PAREN))
+ {
+ if (property_kind == CTX_PROPERTY_NONE)
+ {
+ error ("selector %qs does not accept any properties",
+ IDENTIFIER_POINTER (selector));
+ return error_mark_node;
+ }
+
+ matching_parens parens;
+ parens.consume_open (parser);
+
+ cp_token *token = cp_lexer_peek_token (parser->lexer);
+ if (allow_score
+ && cp_lexer_next_token_is (parser->lexer, CPP_NAME)
+ && strcmp (IDENTIFIER_POINTER (token->u.value), "score") == 0
+ && cp_lexer_nth_token_is (parser->lexer, 2, CPP_OPEN_PAREN))
+ {
+ cp_lexer_save_tokens (parser->lexer);
+ cp_lexer_consume_token (parser->lexer);
+ cp_lexer_consume_token (parser->lexer);
+ if (cp_parser_skip_to_closing_parenthesis (parser, false, false,
+ true)
+ && cp_lexer_next_token_is (parser->lexer, CPP_COLON))
+ {
+ cp_lexer_rollback_tokens (parser->lexer);
+ cp_lexer_consume_token (parser->lexer);
+
+ matching_parens parens2;
+ parens2.require_open (parser);
+ tree score = cp_parser_constant_expression (parser);
+ if (!parens2.require_close (parser))
+ cp_parser_skip_to_closing_parenthesis (parser, true,
+ false, true);
+ cp_parser_require (parser, CPP_COLON, RT_COLON);
+ if (score != error_mark_node)
+ {
+ score = fold_non_dependent_expr (score);
+ if (!value_dependent_expression_p (score)
+ && (!INTEGRAL_TYPE_P (TREE_TYPE (score))
+ || !tree_fits_shwi_p (score)))
+ error_at (token->location, "score argument must be "
+ "constant integer expression");
+ else
+ properties = tree_cons (get_identifier (" score"),
+ score, properties);
+ }
+ }
+ else
+ cp_lexer_rollback_tokens (parser->lexer);
+
+ token = cp_lexer_peek_token (parser->lexer);
+ }
+
+ switch (property_kind)
+ {
+ tree t;
+ case CTX_PROPERTY_USER:
+ do
+ {
+ t = cp_parser_constant_expression (parser);
+ if (t != error_mark_node)
+ {
+ t = fold_non_dependent_expr (t);
+ if (TREE_CODE (t) == STRING_CST)
+ properties = tree_cons (NULL_TREE, t, properties);
+ else if (!value_dependent_expression_p (t)
+ && (!INTEGRAL_TYPE_P (TREE_TYPE (t))
+ || !tree_fits_shwi_p (t)))
+ error_at (token->location, "property must be "
+ "constant integer expression or string "
+ "literal");
+ else
+ properties = tree_cons (NULL_TREE, t, properties);
+ }
+
+ if (cp_lexer_next_token_is (parser->lexer, CPP_COMMA))
+ cp_lexer_consume_token (parser->lexer);
+ else
+ break;
+ }
+ while (1);
+ break;
+ case CTX_PROPERTY_IDLIST:
+ do
+ {
+ tree prop;
+ if (cp_lexer_next_token_is (parser->lexer, CPP_KEYWORD)
+ || cp_lexer_next_token_is (parser->lexer, CPP_NAME))
+ prop = cp_lexer_peek_token (parser->lexer)->u.value;
+ else
+ {
+ cp_parser_error (parser, "expected identifier");
+ return error_mark_node;
+ }
+ cp_lexer_consume_token (parser->lexer);
+
+ properties = tree_cons (prop, NULL_TREE, properties);
+
+ if (cp_lexer_next_token_is (parser->lexer, CPP_COMMA))
+ cp_lexer_consume_token (parser->lexer);
+ else
+ break;
+ }
+ while (1);
+ break;
+ case CTX_PROPERTY_EXPR:
+ t = cp_parser_constant_expression (parser);
+ if (t != error_mark_node)
+ {
+ t = fold_non_dependent_expr (t);
+ if (!value_dependent_expression_p (t)
+ && (!INTEGRAL_TYPE_P (TREE_TYPE (t))
+ || !tree_fits_shwi_p (t)))
+ error_at (token->location, "property must be "
+ "constant integer expression");
+ else
+ properties = tree_cons (NULL_TREE, t, properties);
+ }
+ break;
+ case CTX_PROPERTY_SIMD:
+ if (!has_parms_p)
+ {
+ error_at (token->location, "properties for %<simd%> "
+ "selector may not be specified in "
+ "%<metadirective%>");
+ return error_mark_node;
+ }
+ tree c;
+ c = cp_parser_omp_all_clauses (parser,
+ OMP_DECLARE_SIMD_CLAUSE_MASK,
+ "simd", NULL, true, true);
+ properties = tree_cons (NULL_TREE, c, properties);
+ break;
+ default:
+ gcc_unreachable ();
+ }
+
+ if (!parens.require_close (parser))
+ cp_parser_skip_to_closing_parenthesis (parser, true, false, true);
+
+ properties = nreverse (properties);
+ }
+ else if (property_kind == CTX_PROPERTY_IDLIST
+ || property_kind == CTX_PROPERTY_EXPR)
+ {
+ cp_parser_require (parser, CPP_OPEN_PAREN, RT_OPEN_PAREN);
+ return error_mark_node;
+ }
+
+ ret = tree_cons (selector, properties, ret);
+
+ if (cp_lexer_next_token_is (parser->lexer, CPP_COMMA))
+ cp_lexer_consume_token (parser->lexer);
+ else
+ break;
+ }
+ while (1);
+
+ return nreverse (ret);
+}
+
+/* OpenMP 5.0:
+
+ trait-set-selector[,trait-set-selector[,...]]
+
+ trait-set-selector:
+ trait-set-selector-name = { trait-selector[, trait-selector[, ...]] }
+
+ trait-set-selector-name:
+ constructor
+ device
+ implementation
+ user */
+
+static tree
+cp_parser_omp_context_selector_specification (cp_parser *parser,
+ bool has_parms_p)
+{
+ tree ret = NULL_TREE;
+ do
+ {
+ const char *setp = "";
+ if (cp_lexer_next_token_is (parser->lexer, CPP_NAME))
+ setp
+ = IDENTIFIER_POINTER (cp_lexer_peek_token (parser->lexer)->u.value);
+ switch (setp[0])
+ {
+ case 'c':
+ if (strcmp (setp, "construct") == 0)
+ setp = NULL;
+ break;
+ case 'd':
+ if (strcmp (setp, "device") == 0)
+ setp = NULL;
+ break;
+ case 'i':
+ if (strcmp (setp, "implementation") == 0)
+ setp = NULL;
+ break;
+ case 'u':
+ if (strcmp (setp, "user") == 0)
+ setp = NULL;
+ break;
+ default:
+ break;
+ }
+ if (setp)
+ {
+ cp_parser_error (parser, "expected %<construct%>, %<device%>, "
+ "%<implementation%> or %<user%>");
+ return error_mark_node;
+ }
+
+ tree set = cp_lexer_peek_token (parser->lexer)->u.value;
+ cp_lexer_consume_token (parser->lexer);
+
+ if (!cp_parser_require (parser, CPP_EQ, RT_EQ))
+ return error_mark_node;
+
+ matching_braces braces;
+ if (!braces.require_open (parser))
+ return error_mark_node;
+
+ tree selectors
+ = cp_parser_omp_context_selector (parser, set, has_parms_p);
+ if (selectors == error_mark_node)
+ {
+ cp_parser_skip_to_closing_brace (parser);
+ ret = error_mark_node;
+ }
+ else if (ret != error_mark_node)
+ ret = tree_cons (set, selectors, ret);
+
+ braces.require_close (parser);
+
+ if (cp_lexer_next_token_is (parser->lexer, CPP_COMMA))
+ cp_lexer_consume_token (parser->lexer);
+ else
+ break;
+ }
+ while (1);
+
+ if (ret == error_mark_node)
+ return ret;
+ return nreverse (ret);
+}
+
+/* Finalize #pragma omp declare variant after a fndecl has been parsed, and put
+ that into "omp declare variant" attribute. */
+
+static tree
+cp_finish_omp_declare_variant (cp_parser *parser, cp_token *pragma_tok,
+ tree attrs)
+{
+ matching_parens parens;
+ if (!parens.require_open (parser))
+ {
+ fail:
+ cp_parser_skip_to_pragma_eol (parser, pragma_tok);
+ return attrs;
+ }
+
+ cp_token *token = cp_lexer_peek_token (parser->lexer);
+ tree variant;
+ tree name = cp_parser_id_expression (parser, /*template_p=*/false,
+ /*check_dependency_p=*/true,
+ /*template_p=*/NULL,
+ /*declarator_p=*/false,
+ /*optional_p=*/false);
+ if (identifier_p (name))
+ variant = cp_parser_lookup_name_simple (parser, name, token->location);
+ else
+ variant = name;
+ if (variant == error_mark_node)
+ {
+ cp_parser_name_lookup_error (parser, name, variant, NLE_NULL,
+ token->location);
+ variant = error_mark_node;
+ }
+
+ parens.require_close (parser);
+
+ const char *clause = "";
+ location_t match_loc = cp_lexer_peek_token (parser->lexer)->location;
+ if (cp_lexer_next_token_is (parser->lexer, CPP_NAME))
+ clause = IDENTIFIER_POINTER (cp_lexer_peek_token (parser->lexer)->u.value);
+ if (strcmp (clause, "match"))
+ {
+ cp_parser_error (parser, "expected %<match%>");
+ goto fail;
+ }
+
+ cp_lexer_consume_token (parser->lexer);
+
+ if (!parens.require_open (parser))
+ goto fail;
+
+ tree ctx = cp_parser_omp_context_selector_specification (parser, true);
+ if (ctx == error_mark_node)
+ goto fail;
+ ctx = c_omp_check_context_selector (match_loc, ctx);
+ if (ctx != error_mark_node && variant != error_mark_node)
+ {
+ attrs = tree_cons (get_identifier ("omp declare variant"),
+ build_tree_list (variant, ctx), attrs);
+ if (processing_template_decl)
+ ATTR_IS_DEPENDENT (attrs) = 1;
+ }
+
+ parens.require_close (parser);
+ cp_parser_skip_to_pragma_eol (parser, pragma_tok);
+ return attrs;
+}
+
+
/* Finalize #pragma omp declare simd clauses after direct declarator has
been parsed, and put that into "omp declare simd" attribute. */
@@ -40309,8 +40741,9 @@ cp_parser_late_parsing_omp_declare_simd (cp_parser *parser, tree attrs)
if (!data->error_seen && data->fndecl_seen)
{
- error ("%<#pragma omp declare simd%> not immediately followed by "
- "a single function declaration or definition");
+ error ("%<#pragma omp declare %s%> not immediately followed by "
+ "a single function declaration or definition",
+ data->variant_p ? "variant" : "simd");
data->error_seen = true;
}
if (data->error_seen)
@@ -40324,17 +40757,28 @@ cp_parser_late_parsing_omp_declare_simd (cp_parser *parser, tree attrs)
parser->lexer->in_pragma = true;
gcc_assert (cp_lexer_peek_token (parser->lexer)->type == CPP_PRAGMA);
cp_token *pragma_tok = cp_lexer_consume_token (parser->lexer);
+ tree id = cp_lexer_peek_token (parser->lexer)->u.value;
+ const char *kind = IDENTIFIER_POINTER (id);
cp_lexer_consume_token (parser->lexer);
- cl = cp_parser_omp_all_clauses (parser, OMP_DECLARE_SIMD_CLAUSE_MASK,
- "#pragma omp declare simd", pragma_tok);
+ if (strcmp (kind, "simd") == 0)
+ {
+ cl = cp_parser_omp_all_clauses (parser, OMP_DECLARE_SIMD_CLAUSE_MASK,
+ "#pragma omp declare simd",
+ pragma_tok);
+ if (cl)
+ cl = tree_cons (NULL_TREE, cl, NULL_TREE);
+ c = build_tree_list (get_identifier ("omp declare simd"), cl);
+ TREE_CHAIN (c) = attrs;
+ if (processing_template_decl)
+ ATTR_IS_DEPENDENT (c) = 1;
+ attrs = c;
+ }
+ else
+ {
+ gcc_assert (strcmp (kind, "variant") == 0);
+ attrs = cp_finish_omp_declare_variant (parser, pragma_tok, attrs);
+ }
cp_parser_pop_lexer (parser);
- if (cl)
- cl = tree_cons (NULL_TREE, cl, NULL_TREE);
- c = build_tree_list (get_identifier ("omp declare simd"), cl);
- TREE_CHAIN (c) = attrs;
- if (processing_template_decl)
- ATTR_IS_DEPENDENT (c) = 1;
- attrs = c;
}
data->fndecl_seen = true;
@@ -40898,7 +41342,10 @@ cp_parser_omp_declare_reduction (cp_parser *parser, cp_token *pragma_tok,
#pragma omp declare simd declare-simd-clauses[optseq] new-line
#pragma omp declare reduction (reduction-id : typename-list : expression) \
initializer-clause[opt] new-line
- #pragma omp declare target new-line */
+ #pragma omp declare target new-line
+
+ OpenMP 5.0
+ #pragma omp declare variant (identifier) match (context-selector) */
static bool
cp_parser_omp_declare (cp_parser *parser, cp_token *pragma_tok,
@@ -40913,7 +41360,14 @@ cp_parser_omp_declare (cp_parser *parser, cp_token *pragma_tok,
{
cp_lexer_consume_token (parser->lexer);
cp_parser_omp_declare_simd (parser, pragma_tok,
- context);
+ context, false);
+ return true;
+ }
+ if (flag_openmp && strcmp (p, "variant") == 0)
+ {
+ cp_lexer_consume_token (parser->lexer);
+ cp_parser_omp_declare_simd (parser, pragma_tok,
+ context, true);
return true;
}
cp_ensure_no_omp_declare_simd (parser);
@@ -40936,8 +41390,8 @@ cp_parser_omp_declare (cp_parser *parser, cp_token *pragma_tok,
return false;
}
}
- cp_parser_error (parser, "expected %<simd%> or %<reduction%> "
- "or %<target%>");
+ cp_parser_error (parser, "expected %<simd%>, %<reduction%>, "
+ "%<target%> or %<variant%>");
cp_parser_require_pragma_eol (parser, pragma_tok);
return false;
}
diff --git a/gcc/cp/parser.h b/gcc/cp/parser.h
index 2890788..91b5916 100644
--- a/gcc/cp/parser.h
+++ b/gcc/cp/parser.h
@@ -202,10 +202,11 @@ struct GTY (()) cp_parser_context {
};
-/* Helper data structure for parsing #pragma omp declare simd. */
+/* Helper data structure for parsing #pragma omp declare {simd,variant}. */
struct cp_omp_declare_simd_data {
bool error_seen; /* Set if error has been reported. */
bool fndecl_seen; /* Set if one fn decl/definition has been seen already. */
+ bool variant_p; /* Set for #pragma omp declare variant. */
vec<cp_token_cache_ptr> tokens;
tree clauses;
};