aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--gcc/c/c-parser.cc242
-rw-r--r--gcc/cp/decl.cc8
-rw-r--r--gcc/cp/parser.cc229
-rw-r--r--gcc/cp/pt.cc15
-rw-r--r--gcc/fortran/gfortran.h20
-rw-r--r--gcc/fortran/openmp.cc227
-rw-r--r--gcc/fortran/trans-openmp.cc42
-rw-r--r--gcc/gimplify.cc17
-rw-r--r--gcc/omp-general.cc565
-rw-r--r--gcc/omp-general.h23
-rw-r--r--gcc/omp-selectors.h93
-rw-r--r--gcc/testsuite/c-c++-common/gomp/declare-variant-1.c1
-rw-r--r--gcc/testsuite/c-c++-common/gomp/declare-variant-2.c54
-rw-r--r--gcc/testsuite/c-c++-common/gomp/declare-variant-no-score.c24
-rw-r--r--gcc/testsuite/gfortran.dg/gomp/declare-variant-1.f901
-rw-r--r--gcc/testsuite/gfortran.dg/gomp/declare-variant-2.f9048
-rw-r--r--gcc/testsuite/gfortran.dg/gomp/declare-variant-no-score.f9030
17 files changed, 920 insertions, 719 deletions
diff --git a/gcc/c/c-parser.cc b/gcc/c/c-parser.cc
index b5bed5e..4f1e066 100644
--- a/gcc/c/c-parser.cc
+++ b/gcc/c/c-parser.cc
@@ -24370,16 +24370,6 @@ c_parser_omp_declare_simd (c_parser *parser, enum pragma_context context)
}
}
-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:
@@ -24392,7 +24382,8 @@ static const char *const omp_user_selectors[] = {
trait-selector-set SET. */
static tree
-c_parser_omp_context_selector (c_parser *parser, tree set, tree parms)
+c_parser_omp_context_selector (c_parser *parser, enum omp_tss_code set,
+ tree parms)
{
tree ret = NULL_TREE;
do
@@ -24406,80 +24397,41 @@ c_parser_omp_context_selector (c_parser *parser, tree set, tree parms)
c_parser_error (parser, "expected trait selector name");
return error_mark_node;
}
+ enum omp_ts_code sel
+ = omp_lookup_ts_code (set, IDENTIFIER_POINTER (selector));
- tree properties = NULL_TREE;
- tree scoreval = 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_NAME_LIST,
- CTX_PROPERTY_ID, 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_NAME_LIST;
- break;
- case 'i': /* implementation */
- selectors = omp_implementation_selectors;
- allow_user = true;
- property_limit = 3;
- property_kind = CTX_PROPERTY_NAME_LIST;
- 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 (sel == OMP_TRAIT_INVALID)
{
- if (selectors[i] == NULL)
+ /* Per the spec, "Implementations can ignore specified selectors
+ that are not those described in this section"; however, we
+ must record such selectors because they cause match failures. */
+ warning_at (c_parser_peek_token (parser)->location, OPT_Wopenmp,
+ "unknown selector %qs for context selector set %qs",
+ IDENTIFIER_POINTER (selector), omp_tss_map[set]);
+ c_parser_consume_token (parser);
+ ret = make_trait_selector (sel, NULL_TREE, NULL_TREE, ret);
+ if (c_parser_next_token_is (parser, CPP_OPEN_PAREN))
+ c_parser_balanced_token_sequence (parser);
+ if (c_parser_next_token_is (parser, CPP_COMMA))
{
- if (allow_user)
- {
- property_kind = CTX_PROPERTY_USER;
- break;
- }
- else
- {
- error_at (c_parser_peek_token (parser)->location,
- "selector %qs not allowed for context selector "
- "set %qs", IDENTIFIER_POINTER (selector),
- IDENTIFIER_POINTER (set));
- c_parser_consume_token (parser);
- return error_mark_node;
- }
+ c_parser_consume_token (parser);
+ continue;
}
- if (i == property_limit)
- property_kind = CTX_PROPERTY_NONE;
- if (strcmp (selectors[i], IDENTIFIER_POINTER (selector)) == 0)
+ else
break;
}
- if (property_kind == CTX_PROPERTY_NAME_LIST
- && IDENTIFIER_POINTER (set)[0] == 'i'
- && strcmp (IDENTIFIER_POINTER (selector),
- "atomic_default_mem_order") == 0)
- property_kind = CTX_PROPERTY_ID;
c_parser_consume_token (parser);
+ tree properties = NULL_TREE;
+ tree scoreval = NULL_TREE;
+ enum omp_tp_type property_kind = omp_ts_map[sel].tp_type;
+ bool allow_score = omp_ts_map[sel].allow_score;
+ tree t;
+
if (c_parser_next_token_is (parser, CPP_OPEN_PAREN))
{
- if (property_kind == CTX_PROPERTY_NONE)
+ if (property_kind == OMP_TRAIT_PROPERTY_NONE)
{
error_at (c_parser_peek_token (parser)->location,
"selector %qs does not accept any properties",
@@ -24491,8 +24443,7 @@ c_parser_omp_context_selector (c_parser *parser, tree set, tree parms)
parens.require_open (parser);
c_token *token = c_parser_peek_token (parser);
- if (allow_score
- && c_parser_next_token_is (parser, CPP_NAME)
+ if (c_parser_next_token_is (parser, CPP_NAME)
&& strcmp (IDENTIFIER_POINTER (token->value), "score") == 0
&& c_parser_peek_2nd_token (parser)->type == CPP_OPEN_PAREN)
{
@@ -24503,17 +24454,22 @@ c_parser_omp_context_selector (c_parser *parser, tree set, tree parms)
tree score = c_parser_expr_no_commas (parser, NULL).value;
parens2.skip_until_found_close (parser);
c_parser_require (parser, CPP_COLON, "expected %<:%>");
- if (score != error_mark_node)
+ if (!allow_score)
+ error_at (token->location,
+ "%<score%> cannot be specified in traits "
+ "in the %qs trait-selector-set",
+ omp_tss_map[set]);
+ else if (score != error_mark_node)
{
mark_exp_read (score);
score = c_fully_fold (score, false, NULL);
if (!INTEGRAL_TYPE_P (TREE_TYPE (score))
|| TREE_CODE (score) != INTEGER_CST)
- error_at (token->location, "score argument must be "
- "constant integer expression");
+ error_at (token->location, "%<score%> argument must "
+ "be constant integer expression");
else if (tree_int_cst_sgn (score) < 0)
- error_at (token->location, "score argument must be "
- "non-negative");
+ error_at (token->location, "%<score%> argument must "
+ "be non-negative");
else
scoreval = score;
}
@@ -24522,38 +24478,7 @@ c_parser_omp_context_selector (c_parser *parser, tree set, tree parms)
switch (property_kind)
{
- tree t;
- case CTX_PROPERTY_USER:
- do
- {
- t = c_parser_expr_no_commas (parser, NULL).value;
- if (TREE_CODE (t) == STRING_CST)
- properties = make_trait_property (NULL_TREE, t,
- properties);
- else if (t != error_mark_node)
- {
- mark_exp_read (t);
- t = c_fully_fold (t, false, NULL);
- if (!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 = make_trait_property (NULL_TREE, t,
- properties);
- }
- else
- return error_mark_node;
-
- if (c_parser_next_token_is (parser, CPP_COMMA))
- c_parser_consume_token (parser);
- else
- break;
- }
- while (1);
- break;
- case CTX_PROPERTY_ID:
+ case OMP_TRAIT_PROPERTY_ID:
if (c_parser_next_token_is (parser, CPP_KEYWORD)
|| c_parser_next_token_is (parser, CPP_NAME))
{
@@ -24568,7 +24493,7 @@ c_parser_omp_context_selector (c_parser *parser, tree set, tree parms)
return error_mark_node;
}
break;
- case CTX_PROPERTY_NAME_LIST:
+ case OMP_TRAIT_PROPERTY_NAME_LIST:
do
{
tree prop = OMP_TP_NAMELIST_NODE;
@@ -24598,12 +24523,14 @@ c_parser_omp_context_selector (c_parser *parser, tree set, tree parms)
}
while (1);
break;
- case CTX_PROPERTY_EXPR:
+ case OMP_TRAIT_PROPERTY_EXPR:
t = c_parser_expr_no_commas (parser, NULL).value;
if (t != error_mark_node)
{
mark_exp_read (t);
t = c_fully_fold (t, false, NULL);
+ /* FIXME: this is bogus, both device_num and
+ condition selectors allow arbitrary expressions. */
if (!INTEGRAL_TYPE_P (TREE_TYPE (t))
|| !tree_fits_shwi_p (t))
error_at (token->location, "property must be "
@@ -24615,23 +24542,37 @@ c_parser_omp_context_selector (c_parser *parser, tree set, tree parms)
else
return error_mark_node;
break;
- case CTX_PROPERTY_SIMD:
- if (parms == NULL_TREE)
+ case OMP_TRAIT_PROPERTY_CLAUSE_LIST:
+ if (sel == OMP_TRAIT_CONSTRUCT_SIMD)
+ {
+ if (parms == NULL_TREE)
+ {
+ error_at (token->location, "properties for %<simd%> "
+ "selector may not be specified in "
+ "%<metadirective%>");
+ return error_mark_node;
+ }
+ tree c;
+ c = c_parser_omp_all_clauses (parser,
+ OMP_DECLARE_SIMD_CLAUSE_MASK,
+ "simd", true, 2);
+ c = c_omp_declare_simd_clauses_to_numbers (parms
+ == error_mark_node
+ ? NULL_TREE : parms,
+ c);
+ properties = c;
+ }
+ else if (sel == OMP_TRAIT_IMPLEMENTATION_REQUIRES)
{
- error_at (token->location, "properties for %<simd%> "
- "selector may not be specified in "
- "%<metadirective%>");
+ /* FIXME: The "requires" selector was added in OpenMP 5.1.
+ Currently only the now-deprecated syntax
+ from OpenMP 5.0 is supported. */
+ sorry_at (token->location,
+ "%<requires%> selector is not supported yet");
return error_mark_node;
}
- tree c;
- c = c_parser_omp_all_clauses (parser,
- OMP_DECLARE_SIMD_CLAUSE_MASK,
- "simd", true, 2);
- c = c_omp_declare_simd_clauses_to_numbers (parms
- == error_mark_node
- ? NULL_TREE : parms,
- c);
- properties = c;
+ else
+ gcc_unreachable ();
break;
default:
gcc_unreachable ();
@@ -24640,15 +24581,15 @@ c_parser_omp_context_selector (c_parser *parser, tree set, tree parms)
parens.skip_until_found_close (parser);
properties = nreverse (properties);
}
- else if (property_kind == CTX_PROPERTY_NAME_LIST
- || property_kind == CTX_PROPERTY_ID
- || property_kind == CTX_PROPERTY_EXPR)
+ else if (property_kind != OMP_TRAIT_PROPERTY_NONE
+ && property_kind != OMP_TRAIT_PROPERTY_CLAUSE_LIST
+ && property_kind != OMP_TRAIT_PROPERTY_EXTENSION)
{
c_parser_require (parser, CPP_OPEN_PAREN, "expected %<(%>");
return error_mark_node;
}
- ret = make_trait_selector (selector, scoreval, properties, ret);
+ ret = make_trait_selector (sel, scoreval, properties, ret);
if (c_parser_next_token_is (parser, CPP_COMMA))
c_parser_consume_token (parser);
@@ -24682,35 +24623,14 @@ c_parser_omp_context_selector_specification (c_parser *parser, tree parms)
const char *setp = "";
if (c_parser_next_token_is (parser, CPP_NAME))
setp = IDENTIFIER_POINTER (c_parser_peek_token (parser)->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)
+ enum omp_tss_code set = omp_lookup_tss_code (setp);
+
+ if (set == OMP_TRAIT_SET_INVALID)
{
- c_parser_error (parser, "expected %<construct%>, %<device%>, "
- "%<implementation%> or %<user%>");
+ c_parser_error (parser, "expected context selector set name");
return error_mark_node;
}
- tree set = c_parser_peek_token (parser)->value;
c_parser_consume_token (parser);
if (!c_parser_require (parser, CPP_EQ, "expected %<=%>"))
@@ -24807,7 +24727,8 @@ c_finish_omp_declare_variant (c_parser *parser, tree fndecl, tree parms)
error_at (token->location, "variant %qD is not a function", variant);
variant = error_mark_node;
}
- else if (omp_get_context_selector (ctx, "construct", "simd") == NULL_TREE
+ else if (!omp_get_context_selector (ctx, OMP_TRAIT_SET_CONSTRUCT,
+ OMP_TRAIT_CONSTRUCT_SIMD)
&& !comptypes (TREE_TYPE (fndecl), TREE_TYPE (variant)))
{
error_at (token->location, "variant %qD and base %qD have "
@@ -24828,7 +24749,8 @@ c_finish_omp_declare_variant (c_parser *parser, tree fndecl, tree parms)
if (variant != error_mark_node)
{
C_DECL_USED (variant) = 1;
- tree construct = omp_get_context_selector (ctx, "construct", NULL);
+ tree construct
+ = omp_get_context_selector_list (ctx, OMP_TRAIT_SET_CONSTRUCT);
omp_mark_declare_variant (match_loc, variant, construct);
if (omp_context_selector_matches (ctx))
{
diff --git a/gcc/cp/decl.cc b/gcc/cp/decl.cc
index 1ffe4c8..27f1780 100644
--- a/gcc/cp/decl.cc
+++ b/gcc/cp/decl.cc
@@ -8097,12 +8097,13 @@ omp_declare_variant_finalize_one (tree decl, tree attr)
}
tree ctx = TREE_VALUE (TREE_VALUE (attr));
- tree simd = omp_get_context_selector (ctx, "construct", "simd");
+ tree simd = omp_get_context_selector (ctx, OMP_TRAIT_SET_CONSTRUCT,
+ OMP_TRAIT_CONSTRUCT_SIMD);
if (simd)
{
TREE_VALUE (simd)
= c_omp_declare_simd_clauses_to_numbers (DECL_ARGUMENTS (decl),
- TREE_VALUE (simd));
+ OMP_TS_PROPERTIES (simd));
/* FIXME, adjusting simd args unimplemented. */
return true;
}
@@ -8195,7 +8196,8 @@ omp_declare_variant_finalize_one (tree decl, tree attr)
}
else
{
- tree construct = omp_get_context_selector (ctx, "construct", NULL);
+ tree construct
+ = omp_get_context_selector_list (ctx, OMP_TRAIT_SET_CONSTRUCT);
omp_mark_declare_variant (match_loc, variant, construct);
if (!omp_context_selector_matches (ctx))
return true;
diff --git a/gcc/cp/parser.cc b/gcc/cp/parser.cc
index 3250b0b..cb1dcd8 100644
--- a/gcc/cp/parser.cc
+++ b/gcc/cp/parser.cc
@@ -47416,16 +47416,6 @@ cp_parser_omp_declare_simd (cp_parser *parser, cp_token *pragma_tok,
}
}
-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:
@@ -47438,7 +47428,8 @@ static const char *const omp_user_selectors[] = {
trait-selector-set SET. */
static tree
-cp_parser_omp_context_selector (cp_parser *parser, tree set, bool has_parms_p)
+cp_parser_omp_context_selector (cp_parser *parser, enum omp_tss_code set,
+ bool has_parms_p)
{
tree ret = NULL_TREE;
do
@@ -47453,78 +47444,44 @@ cp_parser_omp_context_selector (cp_parser *parser, tree set, bool has_parms_p)
return error_mark_node;
}
- tree properties = NULL_TREE;
- tree scoreval = 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_NAME_LIST,
- CTX_PROPERTY_ID, 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_NAME_LIST;
- break;
- case 'i': /* implementation */
- selectors = omp_implementation_selectors;
- allow_user = true;
- property_limit = 3;
- property_kind = CTX_PROPERTY_NAME_LIST;
- 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++)
+ enum omp_ts_code sel
+ = omp_lookup_ts_code (set, IDENTIFIER_POINTER (selector));
+
+ if (sel == OMP_TRAIT_INVALID)
{
- if (selectors[i] == NULL)
+ /* Per the spec, "Implementations can ignore specified selectors
+ that are not those described in this section"; however, we
+ must record such selectors because they cause match failures. */
+ warning_at (cp_lexer_peek_token (parser->lexer)->location,
+ OPT_Wopenmp,
+ "unknown selector %qs for context selector set %qs",
+ IDENTIFIER_POINTER (selector), omp_tss_map[set]);
+ cp_lexer_consume_token (parser->lexer);
+ ret = make_trait_selector (sel, NULL_TREE, NULL_TREE, ret);
+ if (cp_lexer_next_token_is (parser->lexer, CPP_OPEN_PAREN))
+ for (size_t n = cp_parser_skip_balanced_tokens (parser, 1) - 1;
+ n; --n)
+ cp_lexer_consume_token (parser->lexer);
+ if (cp_lexer_next_token_is (parser->lexer, CPP_COMMA))
{
- 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;
- }
+ cp_lexer_consume_token (parser->lexer);
+ continue;
}
- if (i == property_limit)
- property_kind = CTX_PROPERTY_NONE;
- if (strcmp (selectors[i], IDENTIFIER_POINTER (selector)) == 0)
+ else
break;
}
- if (property_kind == CTX_PROPERTY_NAME_LIST
- && IDENTIFIER_POINTER (set)[0] == 'i'
- && strcmp (IDENTIFIER_POINTER (selector),
- "atomic_default_mem_order") == 0)
- property_kind = CTX_PROPERTY_ID;
cp_lexer_consume_token (parser->lexer);
+ tree properties = NULL_TREE;
+ tree scoreval = NULL_TREE;
+ enum omp_tp_type property_kind = omp_ts_map[sel].tp_type;
+ bool allow_score = omp_ts_map[sel].allow_score;
+ tree t;
+
if (cp_lexer_next_token_is (parser->lexer, CPP_OPEN_PAREN))
{
- if (property_kind == CTX_PROPERTY_NONE)
+ if (property_kind == OMP_TRAIT_PROPERTY_NONE)
{
error ("selector %qs does not accept any properties",
IDENTIFIER_POINTER (selector));
@@ -47535,8 +47492,7 @@ cp_parser_omp_context_selector (cp_parser *parser, tree set, bool has_parms_p)
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)
+ if (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))
{
@@ -47557,18 +47513,23 @@ cp_parser_omp_context_selector (cp_parser *parser, tree set, bool has_parms_p)
cp_parser_skip_to_closing_parenthesis (parser, true,
false, true);
cp_parser_require (parser, CPP_COLON, RT_COLON);
- if (score != error_mark_node)
+ if (!allow_score)
+ error_at (token->location,
+ "%<score%> cannot be specified in traits "
+ "in the %qs trait-selector-set",
+ omp_tss_map[set]);
+ else if (score != error_mark_node)
{
score = fold_non_dependent_expr (score);
if (value_dependent_expression_p (score))
scoreval = score;
else if (!INTEGRAL_TYPE_P (TREE_TYPE (score))
|| TREE_CODE (score) != INTEGER_CST)
- error_at (token->location, "score argument must be "
- "constant integer expression");
+ error_at (token->location, "%<score%> argument must "
+ "be constant integer expression");
else if (tree_int_cst_sgn (score) < 0)
- error_at (token->location, "score argument must be "
- "non-negative");
+ error_at (token->location, "%<score%> argument must "
+ "be non-negative");
else
scoreval = score;
}
@@ -47581,38 +47542,7 @@ cp_parser_omp_context_selector (cp_parser *parser, tree set, bool has_parms_p)
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 = make_trait_property (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 = make_trait_property (NULL_TREE, t,
- properties);
- }
- else
- return error_mark_node;
-
- if (cp_lexer_next_token_is (parser->lexer, CPP_COMMA))
- cp_lexer_consume_token (parser->lexer);
- else
- break;
- }
- while (1);
- break;
- case CTX_PROPERTY_ID:
+ case OMP_TRAIT_PROPERTY_ID:
if (cp_lexer_next_token_is (parser->lexer, CPP_KEYWORD)
|| cp_lexer_next_token_is (parser->lexer, CPP_NAME))
{
@@ -47627,7 +47557,7 @@ cp_parser_omp_context_selector (cp_parser *parser, tree set, bool has_parms_p)
return error_mark_node;
}
break;
- case CTX_PROPERTY_NAME_LIST:
+ case OMP_TRAIT_PROPERTY_NAME_LIST:
do
{
tree prop = OMP_TP_NAMELIST_NODE;
@@ -47658,7 +47588,9 @@ cp_parser_omp_context_selector (cp_parser *parser, tree set, bool has_parms_p)
}
while (1);
break;
- case CTX_PROPERTY_EXPR:
+ case OMP_TRAIT_PROPERTY_EXPR:
+ /* FIXME: this is bogus, the expression need
+ not be constant. */
t = cp_parser_constant_expression (parser);
if (t != error_mark_node)
{
@@ -47675,18 +47607,32 @@ cp_parser_omp_context_selector (cp_parser *parser, tree set, bool has_parms_p)
else
return error_mark_node;
break;
- case CTX_PROPERTY_SIMD:
- if (!has_parms_p)
+ case OMP_TRAIT_PROPERTY_CLAUSE_LIST:
+ if (sel == OMP_TRAIT_CONSTRUCT_SIMD)
+ {
+ if (!has_parms_p)
+ {
+ error_at (token->location, "properties for %<simd%> "
+ "selector may not be specified in "
+ "%<metadirective%>");
+ return error_mark_node;
+ }
+ properties
+ = cp_parser_omp_all_clauses (parser,
+ OMP_DECLARE_SIMD_CLAUSE_MASK,
+ "simd", NULL, true, 2);
+ }
+ else if (sel == OMP_TRAIT_IMPLEMENTATION_REQUIRES)
{
- error_at (token->location, "properties for %<simd%> "
- "selector may not be specified in "
- "%<metadirective%>");
+ /* FIXME: The "requires" selector was added in OpenMP 5.1.
+ Currently only the now-deprecated syntax
+ from OpenMP 5.0 is supported. */
+ sorry_at (token->location,
+ "%<requires%> selector is not supported yet");
return error_mark_node;
}
- properties
- = cp_parser_omp_all_clauses (parser,
- OMP_DECLARE_SIMD_CLAUSE_MASK,
- "simd", NULL, true, 2);
+ else
+ gcc_unreachable ();
break;
default:
gcc_unreachable ();
@@ -47697,15 +47643,15 @@ cp_parser_omp_context_selector (cp_parser *parser, tree set, bool has_parms_p)
properties = nreverse (properties);
}
- else if (property_kind == CTX_PROPERTY_NAME_LIST
- || property_kind == CTX_PROPERTY_ID
- || property_kind == CTX_PROPERTY_EXPR)
+ else if (property_kind != OMP_TRAIT_PROPERTY_NONE
+ && property_kind != OMP_TRAIT_PROPERTY_CLAUSE_LIST
+ && property_kind != OMP_TRAIT_PROPERTY_EXTENSION)
{
cp_parser_require (parser, CPP_OPEN_PAREN, RT_OPEN_PAREN);
return error_mark_node;
}
- ret = make_trait_selector (selector, scoreval, properties, ret);
+ ret = make_trait_selector (sel, scoreval, properties, ret);
if (cp_lexer_next_token_is (parser->lexer, CPP_COMMA))
cp_lexer_consume_token (parser->lexer);
@@ -47741,35 +47687,14 @@ cp_parser_omp_context_selector_specification (cp_parser *parser,
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)
+ enum omp_tss_code set = omp_lookup_tss_code (setp);
+
+ if (set == OMP_TRAIT_SET_INVALID)
{
- cp_parser_error (parser, "expected %<construct%>, %<device%>, "
- "%<implementation%> or %<user%>");
+ cp_parser_error (parser, "expected context selector set name");
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))
diff --git a/gcc/cp/pt.cc b/gcc/cp/pt.cc
index ef280e4..f7063e0 100644
--- a/gcc/cp/pt.cc
+++ b/gcc/cp/pt.cc
@@ -11888,18 +11888,20 @@ tsubst_attribute (tree t, tree *decl_p, tree args,
tree chain = TREE_CHAIN (val);
location_t match_loc = cp_expr_loc_or_input_loc (TREE_PURPOSE (chain));
tree ctx = copy_list (TREE_VALUE (val));
- tree simd = get_identifier ("simd");
- tree condition = get_identifier ("condition");
for (tree tss = ctx; tss; tss = TREE_CHAIN (tss))
{
- const char *set = IDENTIFIER_POINTER (OMP_TSS_ID (tss));
+ enum omp_tss_code set = OMP_TSS_CODE (tss);
tree selectors = NULL_TREE;
for (tree ts = OMP_TSS_TRAIT_SELECTORS (tss); ts;
ts = TREE_CHAIN (ts))
{
tree properties = NULL_TREE;
tree scoreval = NULL_TREE;
- if (OMP_TS_ID (ts) == simd && set[0] == 'c')
+ /* FIXME: The body of this loop should really be dispatching
+ according to omp_ts_map[OMP_TS_CODE (TS)].tp_type instead
+ of having hard-wired knowledge of specific selectors. */
+ if (OMP_TS_CODE (ts) == OMP_TRAIT_CONSTRUCT_SIMD
+ && set == OMP_TRAIT_SET_CONSTRUCT)
{
tree clauses = OMP_TS_PROPERTIES (ts);
clauses = tsubst_omp_clauses (clauses,
@@ -11944,7 +11946,8 @@ tsubst_attribute (tree t, tree *decl_p, tree args,
else if (OMP_TP_VALUE (p))
{
bool allow_string
- = (OMP_TS_ID (ts) != condition || set[0] != 'u');
+ = (OMP_TS_CODE (ts) != OMP_TRAIT_USER_CONDITION
+ || set != OMP_TRAIT_SET_USER);
tree v = OMP_TP_VALUE (p);
if (TREE_CODE (v) == STRING_CST && allow_string)
continue;
@@ -11968,7 +11971,7 @@ tsubst_attribute (tree t, tree *decl_p, tree args,
OMP_TP_VALUE (p) = v;
}
}
- selectors = make_trait_selector (OMP_TS_ID (ts), scoreval,
+ selectors = make_trait_selector (OMP_TS_CODE (ts), scoreval,
properties, selectors);
}
OMP_TSS_TRAIT_SELECTORS (tss) = nreverse (selectors);
diff --git a/gcc/fortran/gfortran.h b/gcc/fortran/gfortran.h
index b5e1b4c..1cb48f8 100644
--- a/gcc/fortran/gfortran.h
+++ b/gcc/fortran/gfortran.h
@@ -1647,21 +1647,13 @@ typedef struct gfc_omp_declare_simd
gfc_omp_declare_simd;
#define gfc_get_omp_declare_simd() XCNEW (gfc_omp_declare_simd)
-
-enum gfc_omp_trait_property_kind
-{
- CTX_PROPERTY_NONE,
- CTX_PROPERTY_USER,
- CTX_PROPERTY_NAME_LIST,
- CTX_PROPERTY_ID,
- CTX_PROPERTY_EXPR,
- CTX_PROPERTY_SIMD
-};
+/* For OpenMP trait selector enum types and tables. */
+#include "omp-selectors.h"
typedef struct gfc_omp_trait_property
{
struct gfc_omp_trait_property *next;
- enum gfc_omp_trait_property_kind property_kind;
+ enum omp_tp_type property_kind;
bool is_name : 1;
union
@@ -1677,8 +1669,7 @@ typedef struct gfc_omp_trait_property
typedef struct gfc_omp_selector
{
struct gfc_omp_selector *next;
-
- char *trait_selector_name;
+ enum omp_ts_code code;
gfc_expr *score;
struct gfc_omp_trait_property *properties;
} gfc_omp_selector;
@@ -1687,8 +1678,7 @@ typedef struct gfc_omp_selector
typedef struct gfc_omp_set_selector
{
struct gfc_omp_set_selector *next;
-
- const char *trait_set_selector_name;
+ enum omp_tss_code code;
struct gfc_omp_selector *trait_selectors;
} gfc_omp_set_selector;
#define gfc_get_omp_set_selector() XCNEW (gfc_omp_set_selector)
diff --git a/gcc/fortran/openmp.cc b/gcc/fortran/openmp.cc
index 8c0e544..f0d39e1 100644
--- a/gcc/fortran/openmp.cc
+++ b/gcc/fortran/openmp.cc
@@ -269,14 +269,14 @@ gfc_free_omp_trait_property_list (gfc_omp_trait_property *list)
list = list->next;
switch (current->property_kind)
{
- case CTX_PROPERTY_ID:
+ case OMP_TRAIT_PROPERTY_ID:
free (current->name);
break;
- case CTX_PROPERTY_NAME_LIST:
+ case OMP_TRAIT_PROPERTY_NAME_LIST:
if (current->is_name)
free (current->name);
break;
- case CTX_PROPERTY_SIMD:
+ case OMP_TRAIT_PROPERTY_CLAUSE_LIST:
gfc_free_omp_clauses (current->clauses);
break;
default:
@@ -5584,17 +5584,55 @@ cleanup:
return MATCH_ERROR;
}
+/* Skip over and ignore trait-property-extensions.
-static const char *const omp_construct_selectors[] = {
- "simd", "target", "teams", "parallel", "do", 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 };
+ trait-property-extension :
+ trait-property-name
+ identifier (trait-property-extension[, trait-property-extension[, ...]])
+ constant integer expression
+ */
+static match gfc_ignore_trait_property_extension_list (void);
+
+static match
+gfc_ignore_trait_property_extension (void)
+{
+ char buf[GFC_MAX_SYMBOL_LEN + 1];
+ gfc_expr *expr;
+
+ /* Identifier form of trait-property name, possibly followed by
+ a list of (recursive) trait-property-extensions. */
+ if (gfc_match_name (buf) == MATCH_YES)
+ {
+ if (gfc_match (" (") == MATCH_YES)
+ return gfc_ignore_trait_property_extension_list ();
+ return MATCH_YES;
+ }
+
+ /* Literal constant. */
+ if (gfc_match_literal_constant (&expr, 0) == MATCH_YES)
+ return MATCH_YES;
+
+ /* FIXME: constant integer expressions. */
+ gfc_error ("Expected trait-property-extension at %C");
+ return MATCH_ERROR;
+}
+
+static match
+gfc_ignore_trait_property_extension_list (void)
+{
+ while (1)
+ {
+ if (gfc_ignore_trait_property_extension () != MATCH_YES)
+ return MATCH_ERROR;
+ if (gfc_match (" ,") == MATCH_YES)
+ continue;
+ if (gfc_match (" )") == MATCH_YES)
+ return MATCH_YES;
+ gfc_error ("expected %<)%> at %C");
+ return MATCH_ERROR;
+ }
+}
/* OpenMP 5.0:
@@ -5618,83 +5656,52 @@ gfc_match_omp_context_selector (gfc_omp_set_selector *oss)
}
gfc_omp_selector *os = gfc_get_omp_selector ();
- os->trait_selector_name = XNEWVEC (char, strlen (selector) + 1);
- strcpy (os->trait_selector_name, selector);
+ if (oss->code == OMP_TRAIT_SET_CONSTRUCT
+ && !strcmp (selector, "do"))
+ os->code = OMP_TRAIT_CONSTRUCT_FOR;
+ else if (oss->code == OMP_TRAIT_SET_CONSTRUCT
+ && !strcmp (selector, "for"))
+ os->code = OMP_TRAIT_INVALID;
+ else
+ os->code = omp_lookup_ts_code (oss->code, selector);
os->next = oss->trait_selectors;
oss->trait_selectors = os;
- const char *const *selectors = NULL;
- bool allow_score = true;
- bool allow_user = false;
- int property_limit = 0;
- enum gfc_omp_trait_property_kind property_kind = CTX_PROPERTY_NONE;
- switch (oss->trait_set_selector_name[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_NAME_LIST;
- break;
- case 'i': /* implementation */
- selectors = omp_implementation_selectors;
- allow_user = true;
- property_limit = 3;
- property_kind = CTX_PROPERTY_NAME_LIST;
- 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 (os->code == OMP_TRAIT_INVALID)
{
- if (selectors[i] == NULL)
- {
- if (allow_user)
- {
- property_kind = CTX_PROPERTY_USER;
- break;
- }
- else
- {
- gfc_error ("selector %qs not allowed for context selector "
- "set %qs at %C",
- selector, oss->trait_set_selector_name);
- return MATCH_ERROR;
- }
- }
- if (i == property_limit)
- property_kind = CTX_PROPERTY_NONE;
- if (strcmp (selectors[i], selector) == 0)
- break;
+ gfc_warning (OPT_Wopenmp,
+ "unknown selector %qs for context selector set %qs "
+ "at %C",
+ selector, omp_tss_map[oss->code]);
+ if (gfc_match (" (") == MATCH_YES
+ && gfc_ignore_trait_property_extension_list () != MATCH_YES)
+ return MATCH_ERROR;
+ if (gfc_match (" ,") == MATCH_YES)
+ continue;
+ break;
}
- if (property_kind == CTX_PROPERTY_NAME_LIST
- && oss->trait_set_selector_name[0] == 'i'
- && strcmp (selector, "atomic_default_mem_order") == 0)
- property_kind = CTX_PROPERTY_ID;
+
+ enum omp_tp_type property_kind = omp_ts_map[os->code].tp_type;
+ bool allow_score = omp_ts_map[os->code].allow_score;
if (gfc_match (" (") == MATCH_YES)
{
- if (property_kind == CTX_PROPERTY_NONE)
+ if (property_kind == OMP_TRAIT_PROPERTY_NONE)
{
gfc_error ("selector %qs does not accept any properties at %C",
selector);
return MATCH_ERROR;
}
- if (allow_score && gfc_match (" score") == MATCH_YES)
+ if (gfc_match (" score") == MATCH_YES)
{
+ if (!allow_score)
+ {
+ gfc_error ("%<score%> cannot be specified in traits "
+ "in the %qs trait-selector-set at %C",
+ omp_tss_map[oss->code]);
+ return MATCH_ERROR;
+ }
if (gfc_match (" (") != MATCH_YES)
{
gfc_error ("expected %<(%> at %C");
@@ -5705,7 +5712,7 @@ gfc_match_omp_context_selector (gfc_omp_set_selector *oss)
|| os->score->ts.type != BT_INTEGER
|| os->score->rank != 0)
{
- gfc_error ("score argument must be constant integer "
+ gfc_error ("%<score%> argument must be constant integer "
"expression at %C");
return MATCH_ERROR;
}
@@ -5713,7 +5720,7 @@ gfc_match_omp_context_selector (gfc_omp_set_selector *oss)
if (os->score->expr_type == EXPR_CONSTANT
&& mpz_sgn (os->score->value.integer) < 0)
{
- gfc_error ("score argument must be non-negative at %C");
+ gfc_error ("%<score%> argument must be non-negative at %C");
return MATCH_ERROR;
}
@@ -5737,22 +5744,7 @@ gfc_match_omp_context_selector (gfc_omp_set_selector *oss)
switch (property_kind)
{
- case CTX_PROPERTY_USER:
- do
- {
- if (gfc_match_expr (&otp->expr) != MATCH_YES)
- {
- gfc_error ("property must be constant integer "
- "expression or string literal at %C");
- return MATCH_ERROR;
- }
-
- if (gfc_match (" ,") != MATCH_YES)
- break;
- }
- while (1);
- break;
- case CTX_PROPERTY_ID:
+ case OMP_TRAIT_PROPERTY_ID:
{
char buf[GFC_MAX_SYMBOL_LEN + 1];
if (gfc_match_name (buf) == MATCH_YES)
@@ -5767,7 +5759,7 @@ gfc_match_omp_context_selector (gfc_omp_set_selector *oss)
}
}
break;
- case CTX_PROPERTY_NAME_LIST:
+ case OMP_TRAIT_PROPERTY_NAME_LIST:
do
{
char buf[GFC_MAX_SYMBOL_LEN + 1];
@@ -5798,7 +5790,7 @@ gfc_match_omp_context_selector (gfc_omp_set_selector *oss)
}
while (1);
break;
- case CTX_PROPERTY_EXPR:
+ case OMP_TRAIT_PROPERTY_EXPR:
if (gfc_match_expr (&otp->expr) != MATCH_YES)
{
gfc_error ("expected expression at %C");
@@ -5814,16 +5806,29 @@ gfc_match_omp_context_selector (gfc_omp_set_selector *oss)
return MATCH_ERROR;
}
break;
- case CTX_PROPERTY_SIMD:
+ case OMP_TRAIT_PROPERTY_CLAUSE_LIST:
{
- if (gfc_match_omp_clauses (&otp->clauses,
- OMP_DECLARE_SIMD_CLAUSES,
- true, false, false, true)
- != MATCH_YES)
+ if (os->code == OMP_TRAIT_CONSTRUCT_SIMD)
+ {
+ if (gfc_match_omp_clauses (&otp->clauses,
+ OMP_DECLARE_SIMD_CLAUSES,
+ true, false, false, true)
+ != MATCH_YES)
+ {
+ gfc_error ("expected simd clause at %C");
+ return MATCH_ERROR;
+ }
+ }
+ else if (os->code == OMP_TRAIT_IMPLEMENTATION_REQUIRES)
{
- gfc_error ("expected simd clause at %C");
+ /* FIXME: The "requires" selector was added in OpenMP 5.1.
+ Currently only the now-deprecated syntax
+ from OpenMP 5.0 is supported. */
+ sorry ("%<requires%> selector is not supported yet");
return MATCH_ERROR;
}
+ else
+ gcc_unreachable ();
break;
}
default:
@@ -5836,9 +5841,9 @@ gfc_match_omp_context_selector (gfc_omp_set_selector *oss)
return MATCH_ERROR;
}
}
- else if (property_kind == CTX_PROPERTY_NAME_LIST
- || property_kind == CTX_PROPERTY_ID
- || property_kind == CTX_PROPERTY_EXPR)
+ else if (property_kind != OMP_TRAIT_PROPERTY_NONE
+ && property_kind != OMP_TRAIT_PROPERTY_CLAUSE_LIST
+ && property_kind != OMP_TRAIT_PROPERTY_EXTENSION)
{
if (gfc_match (" (") != MATCH_YES)
{
@@ -5874,22 +5879,16 @@ gfc_match_omp_context_selector_specification (gfc_omp_declare_variant *odv)
do
{
match m;
- const char *selector_sets[] = { "construct", "device",
- "implementation", "user" };
- const int selector_set_count = ARRAY_SIZE (selector_sets);
- int i;
char buf[GFC_MAX_SYMBOL_LEN + 1];
+ enum omp_tss_code set = OMP_TRAIT_SET_INVALID;
m = gfc_match_name (buf);
if (m == MATCH_YES)
- for (i = 0; i < selector_set_count; i++)
- if (strcmp (buf, selector_sets[i]) == 0)
- break;
+ set = omp_lookup_tss_code (buf);
- if (m != MATCH_YES || i == selector_set_count)
+ if (set == OMP_TRAIT_SET_INVALID)
{
- gfc_error ("expected %<construct%>, %<device%>, %<implementation%> "
- "or %<user%> at %C");
+ gfc_error ("expected context selector set name at %C");
return MATCH_ERROR;
}
@@ -5909,7 +5908,7 @@ gfc_match_omp_context_selector_specification (gfc_omp_declare_variant *odv)
gfc_omp_set_selector *oss = gfc_get_omp_set_selector ();
oss->next = odv->set_selectors;
- oss->trait_set_selector_name = selector_sets[i];
+ oss->code = set;
odv->set_selectors = oss;
if (gfc_match_omp_context_selector (oss) != MATCH_YES)
diff --git a/gcc/fortran/trans-openmp.cc b/gcc/fortran/trans-openmp.cc
index 93f7516..a757b84 100644
--- a/gcc/fortran/trans-openmp.cc
+++ b/gcc/fortran/trans-openmp.cc
@@ -8401,18 +8401,32 @@ gfc_trans_omp_declare_variant (gfc_namespace *ns)
{
tree selectors = NULL_TREE;
gfc_omp_selector *os;
+ enum omp_tss_code set = oss->code;
+ gcc_assert (set != OMP_TRAIT_SET_INVALID);
+
for (os = oss->trait_selectors; os; os = os->next)
{
tree scoreval = NULL_TREE;
tree properties = NULL_TREE;
gfc_omp_trait_property *otp;
+ enum omp_ts_code sel = os->code;
+
+ /* Per the spec, "Implementations can ignore specified
+ selectors that are not those described in this section";
+ however, we must record such selectors because they
+ cause match failures. */
+ if (sel == OMP_TRAIT_INVALID)
+ {
+ selectors = make_trait_selector (sel, NULL_TREE, NULL_TREE,
+ selectors);
+ continue;
+ }
for (otp = os->properties; otp; otp = otp->next)
{
switch (otp->property_kind)
{
- case CTX_PROPERTY_USER:
- case CTX_PROPERTY_EXPR:
+ case OMP_TRAIT_PROPERTY_EXPR:
{
gfc_se se;
gfc_init_se (&se, NULL);
@@ -8421,12 +8435,12 @@ gfc_trans_omp_declare_variant (gfc_namespace *ns)
properties);
}
break;
- case CTX_PROPERTY_ID:
+ case OMP_TRAIT_PROPERTY_ID:
properties
= make_trait_property (get_identifier (otp->name),
NULL_TREE, properties);
break;
- case CTX_PROPERTY_NAME_LIST:
+ case OMP_TRAIT_PROPERTY_NAME_LIST:
{
tree prop = OMP_TP_NAMELIST_NODE;
tree value = NULL_TREE;
@@ -8439,7 +8453,7 @@ gfc_trans_omp_declare_variant (gfc_namespace *ns)
properties);
}
break;
- case CTX_PROPERTY_SIMD:
+ case OMP_TRAIT_PROPERTY_CLAUSE_LIST:
properties = gfc_trans_omp_clauses (NULL, otp->clauses,
odv->where, true);
break;
@@ -8456,13 +8470,10 @@ gfc_trans_omp_declare_variant (gfc_namespace *ns)
scoreval = se.expr;
}
- tree ts_name = get_identifier (os->trait_selector_name);
- selectors = make_trait_selector (ts_name, scoreval,
+ selectors = make_trait_selector (sel, scoreval,
properties, selectors);
}
-
- tree tss_name = get_identifier (oss->trait_set_selector_name);
- set_selectors = make_trait_set_selector (tss_name, selectors,
+ set_selectors = make_trait_set_selector (set, selectors,
set_selectors);
}
@@ -8491,8 +8502,10 @@ gfc_trans_omp_declare_variant (gfc_namespace *ns)
variant_proc_name, &odv->where);
variant_proc_sym = NULL;
}
- else if (omp_get_context_selector (set_selectors, "construct",
- "simd") == NULL_TREE)
+ else if (omp_get_context_selector (set_selectors,
+ OMP_TRAIT_SET_CONSTRUCT,
+ OMP_TRAIT_CONSTRUCT_SIMD)
+ == NULL_TREE)
{
char err[256];
if (!gfc_compare_interfaces (ns->proc_name, variant_proc_sym,
@@ -8509,8 +8522,9 @@ gfc_trans_omp_declare_variant (gfc_namespace *ns)
if (variant_proc_sym != NULL)
{
gfc_set_sym_referenced (variant_proc_sym);
- tree construct = omp_get_context_selector (set_selectors,
- "construct", NULL);
+ tree construct
+ = omp_get_context_selector_list (set_selectors,
+ OMP_TRAIT_SET_CONSTRUCT);
omp_mark_declare_variant (gfc_get_location (&odv->where),
gfc_get_symbol_decl (variant_proc_sym),
construct);
diff --git a/gcc/gimplify.cc b/gcc/gimplify.cc
index f61c8ae..12c06b2 100644
--- a/gcc/gimplify.cc
+++ b/gcc/gimplify.cc
@@ -14480,12 +14480,17 @@ omp_construct_selector_matches (enum tree_code *constructs, int nconstructs,
if (tree attr = lookup_attribute ("omp declare variant variant",
DECL_ATTRIBUTES (current_function_decl)))
{
- enum tree_code variant_constructs[5];
- int variant_nconstructs = 0;
- if (!target_seen)
- variant_nconstructs
- = omp_construct_traits_to_codes (TREE_VALUE (attr),
- variant_constructs);
+ tree selectors = TREE_VALUE (attr);
+ int variant_nconstructs = list_length (selectors);
+ enum tree_code *variant_constructs = NULL;
+ if (!target_seen && variant_nconstructs)
+ {
+ variant_constructs
+ = (enum tree_code *) alloca (variant_nconstructs
+ * sizeof (enum tree_code));
+ omp_construct_traits_to_codes (selectors, variant_nconstructs,
+ variant_constructs);
+ }
for (int i = 0; i < variant_nconstructs; i++)
{
++cnt;
diff --git a/gcc/omp-general.cc b/gcc/omp-general.cc
index 285bc78..d7a5d47 100644
--- a/gcc/omp-general.cc
+++ b/gcc/omp-general.cc
@@ -1015,32 +1015,29 @@ omp_max_simt_vf (void)
return 0;
}
-/* Store the construct selectors as tree codes from last to first,
- return their number. */
+/* Store the construct selectors as tree codes from last to first.
+ CTX is a list of trait selectors, nconstructs must be equal to its
+ length, and the array CONSTRUCTS holds the output. */
-int
-omp_construct_traits_to_codes (tree ctx, enum tree_code *constructs)
+void
+omp_construct_traits_to_codes (tree ctx, int nconstructs,
+ enum tree_code *constructs)
{
- int nconstructs = list_length (ctx);
int i = nconstructs - 1;
+
+ /* Order must match the OMP_TRAIT_CONSTRUCT_* enumerators in
+ enum omp_ts_code. */
+ static enum tree_code code_map[]
+ = { OMP_TARGET, OMP_TEAMS, OMP_PARALLEL, OMP_FOR, OMP_SIMD };
+
for (tree ts = ctx; ts; ts = TREE_CHAIN (ts), i--)
{
- const char *sel = IDENTIFIER_POINTER (OMP_TS_ID (ts));
- if (!strcmp (sel, "target"))
- constructs[i] = OMP_TARGET;
- else if (!strcmp (sel, "teams"))
- constructs[i] = OMP_TEAMS;
- else if (!strcmp (sel, "parallel"))
- constructs[i] = OMP_PARALLEL;
- else if (!strcmp (sel, "for") || !strcmp (sel, "do"))
- constructs[i] = OMP_FOR;
- else if (!strcmp (sel, "simd"))
- constructs[i] = OMP_SIMD;
- else
- gcc_unreachable ();
+ enum omp_ts_code sel = OMP_TS_CODE (ts);
+ int j = (int)sel - (int)OMP_TRAIT_CONSTRUCT_TARGET;
+ gcc_assert (j >= 0 && (unsigned int) j < ARRAY_SIZE (code_map));
+ constructs[i] = code_map[j];
}
gcc_assert (i == -1);
- return nconstructs;
}
/* Return true if PROP is possibly present in one of the offloading target's
@@ -1116,6 +1113,124 @@ omp_maybe_offloaded (void)
return false;
}
+/* Lookup tables for context selectors. */
+const char *omp_tss_map[] =
+ {
+ "construct",
+ "device",
+ "target_device",
+ "implementation",
+ "user",
+ NULL
+};
+
+/* Arrays of property candidates must be null-terminated. */
+static const char *const kind_properties[] =
+ { "host", "nohost", "cpu", "gpu", "fpga", "any", NULL };
+static const char *const vendor_properties[] =
+ { "amd", "arm", "bsc", "cray", "fujitsu", "gnu", "ibm", "intel",
+ "llvm", "nvidia", "pgi", "ti", "unknown", NULL };
+static const char *const extension_properties[] =
+ { NULL };
+static const char *const atomic_default_mem_order_properties[] =
+ { "seq_cst", "relaxed", "acq_rel", NULL };
+
+struct omp_ts_info omp_ts_map[] =
+ {
+ { "kind",
+ (1 << OMP_TRAIT_SET_DEVICE) | (1 << OMP_TRAIT_SET_TARGET_DEVICE),
+ OMP_TRAIT_PROPERTY_NAME_LIST, false,
+ kind_properties
+ },
+ { "isa",
+ (1 << OMP_TRAIT_SET_DEVICE) | (1 << OMP_TRAIT_SET_TARGET_DEVICE),
+ OMP_TRAIT_PROPERTY_NAME_LIST, false,
+ NULL
+ },
+ { "arch",
+ (1 << OMP_TRAIT_SET_DEVICE) | (1 << OMP_TRAIT_SET_TARGET_DEVICE),
+ OMP_TRAIT_PROPERTY_NAME_LIST, false,
+ NULL
+ },
+ { "device_num",
+ (1 << OMP_TRAIT_SET_TARGET_DEVICE),
+ OMP_TRAIT_PROPERTY_EXPR, false,
+ NULL
+ },
+ { "vendor",
+ (1 << OMP_TRAIT_SET_IMPLEMENTATION),
+ OMP_TRAIT_PROPERTY_NAME_LIST, true,
+ vendor_properties,
+ },
+ { "extension",
+ (1 << OMP_TRAIT_SET_IMPLEMENTATION),
+ OMP_TRAIT_PROPERTY_NAME_LIST, true,
+ extension_properties,
+ },
+ { "atomic_default_mem_order",
+ (1 << OMP_TRAIT_SET_IMPLEMENTATION),
+ OMP_TRAIT_PROPERTY_ID, true,
+ atomic_default_mem_order_properties,
+ },
+ { "requires",
+ (1 << OMP_TRAIT_SET_IMPLEMENTATION),
+ OMP_TRAIT_PROPERTY_CLAUSE_LIST, true,
+ NULL
+ },
+ { "unified_address",
+ (1 << OMP_TRAIT_SET_IMPLEMENTATION),
+ OMP_TRAIT_PROPERTY_NONE, true,
+ NULL
+ },
+ { "unified_shared_memory",
+ (1 << OMP_TRAIT_SET_IMPLEMENTATION),
+ OMP_TRAIT_PROPERTY_NONE, true,
+ NULL
+ },
+ { "dynamic_allocators",
+ (1 << OMP_TRAIT_SET_IMPLEMENTATION),
+ OMP_TRAIT_PROPERTY_NONE, true,
+ NULL
+ },
+ { "reverse_offload",
+ (1 << OMP_TRAIT_SET_IMPLEMENTATION),
+ OMP_TRAIT_PROPERTY_NONE, true,
+ NULL
+ },
+ { "condition",
+ (1 << OMP_TRAIT_SET_USER),
+ OMP_TRAIT_PROPERTY_EXPR, true,
+ NULL
+ },
+ { "target",
+ (1 << OMP_TRAIT_SET_CONSTRUCT),
+ OMP_TRAIT_PROPERTY_NONE, false,
+ NULL
+ },
+ { "teams",
+ (1 << OMP_TRAIT_SET_CONSTRUCT),
+ OMP_TRAIT_PROPERTY_NONE, false,
+ NULL
+ },
+ { "parallel",
+ (1 << OMP_TRAIT_SET_CONSTRUCT),
+ OMP_TRAIT_PROPERTY_NONE, false,
+ NULL
+ },
+ { "for",
+ (1 << OMP_TRAIT_SET_CONSTRUCT),
+ OMP_TRAIT_PROPERTY_NONE, false,
+ NULL
+ },
+ { "simd",
+ (1 << OMP_TRAIT_SET_CONSTRUCT),
+ OMP_TRAIT_PROPERTY_CLAUSE_LIST, false,
+ NULL
+ },
+ { NULL, 0, OMP_TRAIT_PROPERTY_NONE, false, NULL } /* OMP_TRAIT_LAST */
+ };
+
+
/* Return a name from PROP, a property in selectors accepting
name lists. */
@@ -1147,124 +1262,119 @@ omp_context_name_list_prop (tree prop)
tree
omp_check_context_selector (location_t loc, tree ctx)
{
- /* Each trait-set-selector-name can only be specified once.
- There are just 4 set names. */
- for (tree t1 = ctx; t1; t1 = TREE_CHAIN (t1))
- for (tree t2 = TREE_CHAIN (t1); t2; t2 = TREE_CHAIN (t2))
- if (OMP_TSS_ID (t1) == OMP_TSS_ID (t2))
- {
- error_at (loc, "selector set %qs specified more than once",
- IDENTIFIER_POINTER (OMP_TSS_ID (t1)));
- return error_mark_node;
- }
+ bool tss_seen[OMP_TRAIT_SET_LAST], ts_seen[OMP_TRAIT_LAST];
+
+ memset (tss_seen, 0, sizeof (tss_seen));
for (tree tss = ctx; tss; tss = TREE_CHAIN (tss))
{
- /* Each trait-selector-name can only be specified once. */
- if (list_length (OMP_TSS_TRAIT_SELECTORS (tss)) < 5)
+ enum omp_tss_code tss_code = OMP_TSS_CODE (tss);
+
+ /* We can parse this, but not handle it yet. */
+ if (tss_code == OMP_TRAIT_SET_TARGET_DEVICE)
+ sorry_at (loc, "%<target_device%> selector set is not supported yet");
+
+ /* Each trait-set-selector-name can only be specified once. */
+ if (tss_seen[tss_code])
{
- for (tree ts1 = OMP_TSS_TRAIT_SELECTORS (tss); ts1;
- ts1 = TREE_CHAIN (ts1))
- for (tree ts2 = TREE_CHAIN (ts1); ts2; ts2 = TREE_CHAIN (ts2))
- if (OMP_TS_ID (ts1) == OMP_TS_ID (ts2))
- {
- error_at (loc,
- "selector %qs specified more than once in set %qs",
- IDENTIFIER_POINTER (OMP_TS_ID (ts1)),
- IDENTIFIER_POINTER (OMP_TSS_ID (tss)));
- return error_mark_node;
- }
+ error_at (loc, "selector set %qs specified more than once",
+ OMP_TSS_NAME (tss));
+ return error_mark_node;
}
else
+ tss_seen[tss_code] = true;
+
+ memset (ts_seen, 0, sizeof (ts_seen));
+ for (tree ts = OMP_TSS_TRAIT_SELECTORS (tss); ts; ts = TREE_CHAIN (ts))
{
- hash_set<tree> pset;
- for (tree ts = OMP_TSS_TRAIT_SELECTORS (tss); ts;
- ts = TREE_CHAIN (ts))
- if (pset.add (OMP_TS_ID (ts)))
+ enum omp_ts_code ts_code = OMP_TS_CODE (ts);
+
+ /* Ignore unknown traits. */
+ if (ts_code == OMP_TRAIT_INVALID)
+ continue;
+
+ /* Each trait-selector-name can only be specified once. */
+ if (ts_seen[ts_code])
+ {
+ error_at (loc,
+ "selector %qs specified more than once in set %qs",
+ OMP_TS_NAME (ts),
+ OMP_TSS_NAME (tss));
+ return error_mark_node;
+ }
+ else
+ ts_seen[ts_code] = true;
+
+ if (omp_ts_map[ts_code].valid_properties == NULL)
+ continue;
+
+ for (tree p = OMP_TS_PROPERTIES (ts); p; p = TREE_CHAIN (p))
+ for (unsigned j = 0; ; j++)
{
- error_at (loc,
- "selector %qs specified more than once in set %qs",
- IDENTIFIER_POINTER (OMP_TS_ID (ts)),
- IDENTIFIER_POINTER (OMP_TSS_ID (tss)));
- return error_mark_node;
+ const char *candidate
+ = omp_ts_map[ts_code].valid_properties[j];
+ if (candidate == NULL)
+ {
+ /* We've reached the end of the candidate array. */
+ if (ts_code == OMP_TRAIT_IMPLEMENTATION_ADMO)
+ /* FIXME: not sure why this is an error vs warnings
+ for the others, + incorrect/unknown wording? */
+ {
+ error_at (loc,
+ "incorrect property %qs of %qs selector",
+ IDENTIFIER_POINTER (OMP_TP_NAME (p)),
+ "atomic_default_mem_order");
+ return error_mark_node;
+ }
+ if (OMP_TP_NAME (p) == OMP_TP_NAMELIST_NODE
+ && (TREE_CODE (OMP_TP_VALUE (p)) == STRING_CST))
+ warning_at (loc, OPT_Wopenmp,
+ "unknown property %qE of %qs selector",
+ OMP_TP_VALUE (p),
+ OMP_TS_NAME (ts));
+ else if (OMP_TP_NAME (p) == OMP_TP_NAMELIST_NODE)
+ warning_at (loc, OPT_Wopenmp,
+ "unknown property %qs of %qs selector",
+ omp_context_name_list_prop (p),
+ OMP_TS_NAME (ts));
+ else if (OMP_TP_NAME (p))
+ warning_at (loc, OPT_Wopenmp,
+ "unknown property %qs of %qs selector",
+ IDENTIFIER_POINTER (OMP_TP_NAME (p)),
+ OMP_TS_NAME (ts));
+ break;
+ }
+ else if (OMP_TP_NAME (p) == OMP_TP_NAMELIST_NODE)
+ /* Property-list traits. */
+ {
+ const char *str = omp_context_name_list_prop (p);
+ if (str && !strcmp (str, candidate))
+ break;
+ }
+ else if (!strcmp (IDENTIFIER_POINTER (OMP_TP_NAME (p)),
+ candidate))
+ /* Identifier traits. */
+ break;
}
}
-
- static const char *const kind[] = {
- "host", "nohost", "cpu", "gpu", "fpga", "any", NULL };
- static const char *const vendor[] = {
- "amd", "arm", "bsc", "cray", "fujitsu", "gnu", "ibm", "intel",
- "llvm", "nvidia", "pgi", "ti", "unknown", NULL };
- static const char *const extension[] = { NULL };
- static const char *const atomic_default_mem_order[] = {
- "seq_cst", "relaxed", "acq_rel", NULL };
- struct known_properties { const char *set; const char *selector;
- const char *const *props; };
- known_properties props[] = {
- { "device", "kind", kind },
- { "implementation", "vendor", vendor },
- { "implementation", "extension", extension },
- { "implementation", "atomic_default_mem_order",
- atomic_default_mem_order } };
- for (tree ts = OMP_TSS_TRAIT_SELECTORS (tss); ts; ts = TREE_CHAIN (ts))
- for (unsigned i = 0; i < ARRAY_SIZE (props); i++)
- if (!strcmp (IDENTIFIER_POINTER (OMP_TS_ID (ts)),
- props[i].selector)
- && !strcmp (IDENTIFIER_POINTER (OMP_TSS_ID (tss)),
- props[i].set))
- for (tree p = OMP_TS_PROPERTIES (ts); p; p = TREE_CHAIN (p))
- for (unsigned j = 0; ; j++)
- {
- if (props[i].props[j] == NULL)
- {
- if (props[i].props == atomic_default_mem_order)
- {
- error_at (loc,
- "incorrect property %qs of %qs selector",
- IDENTIFIER_POINTER (TREE_PURPOSE (p)),
- "atomic_default_mem_order");
- return error_mark_node;
- }
- else if (OMP_TP_NAME (p) == OMP_TP_NAMELIST_NODE
- && (TREE_CODE (OMP_TP_VALUE (p)) == STRING_CST))
- warning_at (loc, 0,
- "unknown property %qE of %qs selector",
- OMP_TP_VALUE (p),
- props[i].selector);
- else if (OMP_TP_NAME (p) == OMP_TP_NAMELIST_NODE)
- warning_at (loc, 0,
- "unknown property %qs of %qs selector",
- omp_context_name_list_prop (p),
- props[i].selector);
- else if (OMP_TP_NAME (p))
- warning_at (loc, OPT_Wopenmp,
- "unknown property %qs of %qs selector",
- IDENTIFIER_POINTER (OMP_TP_NAME (p)),
- props[i].selector);
- break;
- }
- else if (OMP_TP_NAME (p) == OMP_TP_NAMELIST_NODE)
- /* Property-list traits. */
- {
- const char *str = omp_context_name_list_prop (p);
- if (str && !strcmp (str, props[i].props[j]))
- break;
- }
- else if (!strcmp (IDENTIFIER_POINTER (OMP_TP_NAME (p)),
- props[i].props[j]))
- break;
- }
}
return ctx;
}
/* Register VARIANT as variant of some base function marked with
- #pragma omp declare variant. CONSTRUCT is corresponding construct
- selector set. */
-
+ #pragma omp declare variant. CONSTRUCT is corresponding list of
+ trait-selectors for the construct selector set. This is stashed as the
+ value of the "omp declare variant variant" attribute on VARIANT. */
void
omp_mark_declare_variant (location_t loc, tree variant, tree construct)
{
+ /* Ignore this variant if it contains unknown construct selectors.
+ It will never match, and the front ends have already issued a warning
+ about it. */
+ for (tree c = construct; c; c = TREE_CHAIN (c))
+ if (OMP_TS_CODE (c) == OMP_TRAIT_INVALID)
+ return;
+
tree attr = lookup_attribute ("omp declare variant variant",
DECL_ATTRIBUTES (variant));
if (attr == NULL_TREE)
@@ -1277,7 +1387,8 @@ omp_mark_declare_variant (location_t loc, tree variant, tree construct)
}
if ((TREE_VALUE (attr) != NULL_TREE) != (construct != NULL_TREE)
|| (construct != NULL_TREE
- && omp_context_selector_set_compare ("construct", TREE_VALUE (attr),
+ && omp_context_selector_set_compare (OMP_TRAIT_SET_CONSTRUCT,
+ TREE_VALUE (attr),
construct)))
error_at (loc, "%qD used as a variant with incompatible %<construct%> "
"selector sets", variant);
@@ -1287,18 +1398,21 @@ omp_mark_declare_variant (location_t loc, tree variant, tree construct)
/* Constructors for context selectors. */
tree
-make_trait_set_selector (tree name, tree selectors, tree chain)
+make_trait_set_selector (enum omp_tss_code code, tree selectors, tree chain)
{
- return tree_cons (name, selectors, chain);
+ return tree_cons (build_int_cst (integer_type_node, code),
+ selectors, chain);
}
tree
-make_trait_selector (tree name, tree score, tree properties, tree chain)
+make_trait_selector (enum omp_ts_code code, tree score, tree properties,
+ tree chain)
{
if (score == NULL_TREE)
- return tree_cons (name, properties, chain);
+ return tree_cons (build_int_cst (integer_type_node, code),
+ properties, chain);
else
- return tree_cons (name,
+ return tree_cons (build_int_cst (integer_type_node, code),
tree_cons (OMP_TS_SCORE_NODE, score, properties),
chain);
}
@@ -1321,8 +1435,16 @@ omp_context_selector_matches (tree ctx)
int ret = 1;
for (tree tss = ctx; tss; tss = TREE_CHAIN (tss))
{
- char set = IDENTIFIER_POINTER (OMP_TSS_ID (tss))[0];
- if (set == 'c')
+ enum omp_tss_code set = OMP_TSS_CODE (tss);
+ tree selectors = OMP_TSS_TRAIT_SELECTORS (tss);
+
+ /* Immediately reject the match if there are any ignored
+ selectors present. */
+ for (tree ts = selectors; ts; ts = TREE_CHAIN (ts))
+ if (OMP_TS_CODE (ts) == OMP_TRAIT_INVALID)
+ return 0;
+
+ if (set == OMP_TRAIT_SET_CONSTRUCT)
{
/* For now, ignore the construct set. While something can be
determined already during parsing, we don't know until end of TU
@@ -1337,10 +1459,20 @@ omp_context_selector_matches (tree ctx)
continue;
}
- enum tree_code constructs[5];
- int nconstructs
- = omp_construct_traits_to_codes (OMP_TSS_TRAIT_SELECTORS (tss),
+ int nconstructs = list_length (selectors);
+ enum tree_code *constructs = NULL;
+ if (nconstructs)
+ {
+ /* Even though this alloca appears in a loop over selector
+ sets, it does not repeatedly grow the stack, because
+ there can be only one construct selector set specified.
+ This is enforced by omp_check_context_selector. */
+ constructs
+ = (enum tree_code *) alloca (nconstructs
+ * sizeof (enum tree_code));
+ omp_construct_traits_to_codes (selectors, nconstructs,
constructs);
+ }
if (cfun && (cfun->curr_properties & PROP_gimple_any) != 0)
{
@@ -1371,13 +1503,13 @@ omp_context_selector_matches (tree ctx)
ret = -1;
continue;
}
- for (tree ts = OMP_TSS_TRAIT_SELECTORS (tss); ts; ts = TREE_CHAIN (ts))
+ for (tree ts = selectors; ts; ts = TREE_CHAIN (ts))
{
- const char *sel = IDENTIFIER_POINTER (OMP_TS_ID (ts));
- switch (*sel)
+ enum omp_ts_code sel = OMP_TS_CODE (ts);
+ switch (sel)
{
- case 'v':
- if (set == 'i' && !strcmp (sel, "vendor"))
+ case OMP_TRAIT_IMPLEMENTATION_VENDOR:
+ if (set == OMP_TRAIT_SET_IMPLEMENTATION)
for (tree p = OMP_TS_PROPERTIES (ts); p; p = TREE_CHAIN (p))
{
const char *prop = omp_context_name_list_prop (p);
@@ -1388,13 +1520,13 @@ omp_context_selector_matches (tree ctx)
return 0;
}
break;
- case 'e':
- if (set == 'i' && !strcmp (sel, "extension"))
+ case OMP_TRAIT_IMPLEMENTATION_EXTENSION:
+ if (set == OMP_TRAIT_SET_IMPLEMENTATION)
/* We don't support any extensions right now. */
return 0;
break;
- case 'a':
- if (set == 'i' && !strcmp (sel, "atomic_default_mem_order"))
+ case OMP_TRAIT_IMPLEMENTATION_ADMO:
+ if (set == OMP_TRAIT_SET_IMPLEMENTATION)
{
if (cfun && (cfun->curr_properties & PROP_gimple_any) != 0)
break;
@@ -1426,7 +1558,9 @@ omp_context_selector_matches (tree ctx)
&& omo != OMP_MEMORY_ORDER_ACQ_REL)
return 0;
}
- if (set == 'd' && !strcmp (sel, "arch"))
+ break;
+ case OMP_TRAIT_DEVICE_ARCH:
+ if (set == OMP_TRAIT_SET_DEVICE)
for (tree p = OMP_TS_PROPERTIES (ts); p; p = TREE_CHAIN (p))
{
const char *arch = omp_context_name_list_prop (p);
@@ -1463,8 +1597,8 @@ omp_context_selector_matches (tree ctx)
ret = -1;
}
break;
- case 'u':
- if (set == 'i' && !strcmp (sel, "unified_address"))
+ case OMP_TRAIT_IMPLEMENTATION_UNIFIED_ADDRESS:
+ if (set == OMP_TRAIT_SET_IMPLEMENTATION)
{
if (cfun && (cfun->curr_properties & PROP_gimple_any) != 0)
break;
@@ -1476,9 +1610,10 @@ omp_context_selector_matches (tree ctx)
else
return 0;
}
- break;
}
- if (set == 'i' && !strcmp (sel, "unified_shared_memory"))
+ break;
+ case OMP_TRAIT_IMPLEMENTATION_UNIFIED_SHARED_MEMORY:
+ if (set == OMP_TRAIT_SET_IMPLEMENTATION)
{
if (cfun && (cfun->curr_properties & PROP_gimple_any) != 0)
break;
@@ -1491,11 +1626,10 @@ omp_context_selector_matches (tree ctx)
else
return 0;
}
- break;
}
break;
- case 'd':
- if (set == 'i' && !strcmp (sel, "dynamic_allocators"))
+ case OMP_TRAIT_IMPLEMENTATION_DYNAMIC_ALLOCATORS:
+ if (set == OMP_TRAIT_SET_IMPLEMENTATION)
{
if (cfun && (cfun->curr_properties & PROP_gimple_any) != 0)
break;
@@ -1508,11 +1642,10 @@ omp_context_selector_matches (tree ctx)
else
return 0;
}
- break;
}
break;
- case 'r':
- if (set == 'i' && !strcmp (sel, "reverse_offload"))
+ case OMP_TRAIT_IMPLEMENTATION_REVERSE_OFFLOAD:
+ if (set == OMP_TRAIT_SET_IMPLEMENTATION)
{
if (cfun && (cfun->curr_properties & PROP_gimple_any) != 0)
break;
@@ -1524,11 +1657,10 @@ omp_context_selector_matches (tree ctx)
else
return 0;
}
- break;
}
break;
- case 'k':
- if (set == 'd' && !strcmp (sel, "kind"))
+ case OMP_TRAIT_DEVICE_KIND:
+ if (set == OMP_TRAIT_SET_DEVICE)
for (tree p = OMP_TS_PROPERTIES (ts); p; p = TREE_CHAIN (p))
{
const char *prop = omp_context_name_list_prop (p);
@@ -1588,8 +1720,8 @@ omp_context_selector_matches (tree ctx)
ret = -1;
}
break;
- case 'i':
- if (set == 'd' && !strcmp (sel, "isa"))
+ case OMP_TRAIT_DEVICE_ISA:
+ if (set == OMP_TRAIT_SET_DEVICE)
for (tree p = OMP_TS_PROPERTIES (ts); p; p = TREE_CHAIN (p))
{
const char *isa = omp_context_name_list_prop (p);
@@ -1641,8 +1773,8 @@ omp_context_selector_matches (tree ctx)
ret = -1;
}
break;
- case 'c':
- if (set == 'u' && !strcmp (sel, "condition"))
+ case OMP_TRAIT_USER_CONDITION:
+ if (set == OMP_TRAIT_SET_USER)
for (tree p = OMP_TS_PROPERTIES (ts); p; p = TREE_CHAIN (p))
if (OMP_TP_NAME (p) == NULL_TREE)
{
@@ -1784,7 +1916,8 @@ omp_construct_simd_compare (tree clauses1, tree clauses2)
Unlike set names or selector names, properties can have duplicates. */
static int
-omp_context_selector_props_compare (const char *set, const char *sel,
+omp_context_selector_props_compare (enum omp_tss_code set,
+ enum omp_ts_code sel,
tree ctx1, tree ctx2)
{
int ret = 0;
@@ -1797,7 +1930,8 @@ omp_context_selector_props_compare (const char *set, const char *sel,
{
if (OMP_TP_NAME (p1) == NULL_TREE)
{
- if (set[0] == 'u' && strcmp (sel, "condition") == 0)
+ if (set == OMP_TRAIT_SET_USER
+ && sel == OMP_TRAIT_USER_CONDITION)
{
if (integer_zerop (OMP_TP_VALUE (p1))
!= integer_zerop (OMP_TP_VALUE (p2)))
@@ -1844,8 +1978,18 @@ omp_context_selector_props_compare (const char *set, const char *sel,
2 if neither context is a subset of another one. */
int
-omp_context_selector_set_compare (const char *set, tree ctx1, tree ctx2)
+omp_context_selector_set_compare (enum omp_tss_code set, tree ctx1, tree ctx2)
{
+
+ /* If either list includes an ignored selector trait, neither can
+ be a subset of the other. */
+ for (tree ts = ctx1; ts; ts = TREE_CHAIN (ts))
+ if (OMP_TS_CODE (ts) == OMP_TRAIT_INVALID)
+ return 2;
+ for (tree ts = ctx2; ts; ts = TREE_CHAIN (ts))
+ if (OMP_TS_CODE (ts) == OMP_TRAIT_INVALID)
+ return 2;
+
bool swapped = false;
int ret = 0;
int len1 = list_length (ctx1);
@@ -1857,18 +2001,18 @@ omp_context_selector_set_compare (const char *set, tree ctx1, tree ctx2)
std::swap (ctx1, ctx2);
std::swap (len1, len2);
}
- if (set[0] == 'c')
+
+ if (set == OMP_TRAIT_SET_CONSTRUCT)
{
tree ts1;
tree ts2 = ctx2;
- tree simd = get_identifier ("simd");
/* Handle construct set specially. In this case the order
of the selector matters too. */
for (ts1 = ctx1; ts1; ts1 = TREE_CHAIN (ts1))
- if (OMP_TS_ID (ts1) == OMP_TS_ID (ts2))
+ if (OMP_TS_CODE (ts1) == OMP_TS_CODE (ts2))
{
int r = 0;
- if (OMP_TS_ID (ts1) == simd)
+ if (OMP_TS_CODE (ts1) == OMP_TRAIT_CONSTRUCT_SIMD)
r = omp_construct_simd_compare (OMP_TS_PROPERTIES (ts1),
OMP_TS_PROPERTIES (ts2));
if (r == 2 || (ret && r && (ret < 0) != (r < 0)))
@@ -1900,17 +2044,17 @@ omp_context_selector_set_compare (const char *set, tree ctx1, tree ctx2)
}
for (tree ts1 = ctx1; ts1; ts1 = TREE_CHAIN (ts1))
{
+ enum omp_ts_code sel = OMP_TS_CODE (ts1);
tree ts2;
for (ts2 = ctx2; ts2; ts2 = TREE_CHAIN (ts2))
- if (OMP_TS_ID (ts1) == OMP_TS_ID (ts2))
+ if (sel == OMP_TS_CODE (ts2))
{
tree score1 = OMP_TS_SCORE (ts1);
tree score2 = OMP_TS_SCORE (ts2);
if (score1 && score2 && !simple_cst_equal (score1, score2))
return 2;
- const char *sel = IDENTIFIER_POINTER (OMP_TS_ID (ts1));
- int r = omp_context_selector_props_compare (set, sel,
+ int r = omp_context_selector_props_compare (set, OMP_TS_CODE (ts1),
OMP_TS_PROPERTIES (ts1),
OMP_TS_PROPERTIES (ts2));
if (r == 2 || (ret && r && (ret < 0) != (r < 0)))
@@ -1956,11 +2100,11 @@ omp_context_selector_compare (tree ctx1, tree ctx2)
}
for (tree tss1 = ctx1; tss1; tss1 = TREE_CHAIN (tss1))
{
+ enum omp_tss_code set = OMP_TSS_CODE (tss1);
tree tss2;
for (tss2 = ctx2; tss2; tss2 = TREE_CHAIN (tss2))
- if (OMP_TSS_ID (tss1) == OMP_TSS_ID (tss2))
+ if (set == OMP_TSS_CODE (tss2))
{
- const char *set = IDENTIFIER_POINTER (OMP_TSS_ID (tss1));
int r
= omp_context_selector_set_compare
(set, OMP_TSS_TRAIT_SELECTORS (tss1),
@@ -1987,26 +2131,51 @@ omp_context_selector_compare (tree ctx1, tree ctx2)
}
/* From context selector CTX, return trait-selector with name SEL in
- trait-selector-set with name SET if any, or NULL_TREE if not found.
- If SEL is NULL, return the list of trait-selectors in SET. */
+ trait-selector-set with name SET if any, or NULL_TREE if not found. */
+tree
+omp_get_context_selector (tree ctx, enum omp_tss_code set,
+ enum omp_ts_code sel)
+{
+ for (tree tss = ctx; tss; tss = TREE_CHAIN (tss))
+ if (OMP_TSS_CODE (tss) == set)
+ for (tree ts = OMP_TSS_TRAIT_SELECTORS (tss); ts; ts = TREE_CHAIN (ts))
+ if (OMP_TS_CODE (ts) == sel)
+ return ts;
+ return NULL_TREE;
+}
+/* Similar, but returns the whole trait-selector list for SET in CTX. */
tree
-omp_get_context_selector (tree ctx, const char *set, const char *sel)
+omp_get_context_selector_list (tree ctx, enum omp_tss_code set)
{
- tree setid = get_identifier (set);
- tree selid = sel ? get_identifier (sel) : NULL_TREE;
for (tree tss = ctx; tss; tss = TREE_CHAIN (tss))
- if (OMP_TSS_ID (tss) == setid)
- {
- if (sel == NULL)
- return OMP_TSS_TRAIT_SELECTORS (tss);
- for (tree ts = OMP_TSS_TRAIT_SELECTORS (tss); ts; ts = TREE_CHAIN (ts))
- if (OMP_TS_ID (ts) == selid)
- return ts;
- }
+ if (OMP_TSS_CODE (tss) == set)
+ return OMP_TSS_TRAIT_SELECTORS (tss);
return NULL_TREE;
}
+/* Map string S onto a trait selector set code. */
+enum omp_tss_code
+omp_lookup_tss_code (const char * s)
+{
+ for (int i = 0; i < OMP_TRAIT_SET_LAST; i++)
+ if (strcmp (s, omp_tss_map[i]) == 0)
+ return (enum omp_tss_code) i;
+ return OMP_TRAIT_SET_INVALID;
+}
+
+/* Map string S onto a trait selector code for set SET. */
+enum omp_ts_code
+omp_lookup_ts_code (enum omp_tss_code set, const char *s)
+{
+ unsigned int mask = 1 << set;
+ for (int i = 0; i < OMP_TRAIT_LAST; i++)
+ if ((mask & omp_ts_map[i].tss_mask) != 0
+ && strcmp (s, omp_ts_map[i].name) == 0)
+ return (enum omp_ts_code) i;
+ return OMP_TRAIT_INVALID;
+}
+
/* Needs to be a GC-friendly widest_int variant, but precision is
desirable to be the same on all targets. */
typedef generic_wide_int <fixed_wide_int_storage <1024> > score_wide_int;
@@ -2019,14 +2188,18 @@ typedef generic_wide_int <fixed_wide_int_storage <1024> > score_wide_int;
static bool
omp_context_compute_score (tree ctx, score_wide_int *score, bool declare_simd)
{
- tree construct = omp_get_context_selector (ctx, "construct", NULL);
- bool has_kind = omp_get_context_selector (ctx, "device", "kind");
- bool has_arch = omp_get_context_selector (ctx, "device", "arch");
- bool has_isa = omp_get_context_selector (ctx, "device", "isa");
+ tree selectors
+ = omp_get_context_selector_list (ctx, OMP_TRAIT_SET_CONSTRUCT);
+ bool has_kind = omp_get_context_selector (ctx, OMP_TRAIT_SET_DEVICE,
+ OMP_TRAIT_DEVICE_KIND);
+ bool has_arch = omp_get_context_selector (ctx, OMP_TRAIT_SET_DEVICE,
+ OMP_TRAIT_DEVICE_ARCH);
+ bool has_isa = omp_get_context_selector (ctx, OMP_TRAIT_SET_DEVICE,
+ OMP_TRAIT_DEVICE_ISA);
bool ret = false;
*score = 1;
for (tree tss = ctx; tss; tss = TREE_CHAIN (tss))
- if (OMP_TSS_TRAIT_SELECTORS (tss) != construct)
+ if (OMP_TSS_TRAIT_SELECTORS (tss) != selectors)
for (tree ts = OMP_TSS_TRAIT_SELECTORS (tss); ts; ts = TREE_CHAIN (ts))
{
tree s = OMP_TS_SCORE (ts);
@@ -2035,13 +2208,19 @@ omp_context_compute_score (tree ctx, score_wide_int *score, bool declare_simd)
TYPE_SIGN (TREE_TYPE (s)));
}
- if (construct || has_kind || has_arch || has_isa)
+ if (selectors || has_kind || has_arch || has_isa)
{
- int scores[12];
- enum tree_code constructs[5];
- int nconstructs = 0;
- if (construct)
- nconstructs = omp_construct_traits_to_codes (construct, constructs);
+ int nconstructs = list_length (selectors);
+ enum tree_code *constructs = NULL;
+ if (nconstructs)
+ {
+ constructs
+ = (enum tree_code *) alloca (nconstructs
+ * sizeof (enum tree_code));
+ omp_construct_traits_to_codes (selectors, nconstructs, constructs);
+ }
+ int *scores
+ = (int *) alloca ((2 * nconstructs + 2) * sizeof (int));
if (omp_construct_selector_matches (constructs, nconstructs, scores)
== 2)
ret = true;
diff --git a/gcc/omp-general.h b/gcc/omp-general.h
index 40ede66..66ed490 100644
--- a/gcc/omp-general.h
+++ b/gcc/omp-general.h
@@ -24,6 +24,7 @@ along with GCC; see the file COPYING3. If not see
#include "gomp-constants.h"
#include "omp-api.h"
+#include "omp-selectors.h"
/* Flags for an OpenACC loop. */
@@ -135,8 +136,18 @@ struct omp_for_data
#define OMP_TP_VALUE(NODE) \
TREE_VALUE (NODE)
-extern tree make_trait_set_selector (tree, tree, tree);
-extern tree make_trait_selector (tree, tree, tree, tree);
+#define OMP_TSS_CODE(t) \
+ ((enum omp_tss_code) TREE_INT_CST_LOW (OMP_TSS_ID (t)))
+#define OMP_TSS_NAME(t) \
+ (omp_tss_map[OMP_TSS_CODE (t)])
+
+#define OMP_TS_CODE(t) \
+ ((enum omp_ts_code) TREE_INT_CST_LOW (OMP_TS_ID (t)))
+#define OMP_TS_NAME(t) \
+ (omp_ts_map[OMP_TS_CODE (t)].name)
+
+extern tree make_trait_set_selector (enum omp_tss_code, tree, tree);
+extern tree make_trait_selector (enum omp_ts_code, tree, tree, tree);
extern tree make_trait_property (tree, tree, tree);
extern tree omp_find_clause (tree clauses, enum omp_clause_code kind);
@@ -153,13 +164,15 @@ extern gimple *omp_build_barrier (tree lhs);
extern tree find_combined_omp_for (tree *, int *, void *);
extern poly_uint64 omp_max_vf (void);
extern int omp_max_simt_vf (void);
-extern int omp_construct_traits_to_codes (tree, enum tree_code *);
+extern void omp_construct_traits_to_codes (tree, int, enum tree_code *);
extern tree omp_check_context_selector (location_t loc, tree ctx);
extern void omp_mark_declare_variant (location_t loc, tree variant,
tree construct);
extern int omp_context_selector_matches (tree);
-extern int omp_context_selector_set_compare (const char *, tree, tree);
-extern tree omp_get_context_selector (tree, const char *, const char *);
+extern int omp_context_selector_set_compare (enum omp_tss_code, tree, tree);
+extern tree omp_get_context_selector (tree, enum omp_tss_code,
+ enum omp_ts_code);
+extern tree omp_get_context_selector_list (tree, enum omp_tss_code);
extern tree omp_resolve_declare_variant (tree);
extern tree oacc_launch_pack (unsigned code, tree device, unsigned op);
extern tree oacc_replace_fn_attrib_attr (tree attribs, tree dims);
diff --git a/gcc/omp-selectors.h b/gcc/omp-selectors.h
new file mode 100644
index 0000000..825a082
--- /dev/null
+++ b/gcc/omp-selectors.h
@@ -0,0 +1,93 @@
+/* Data structures for OpenMP context selectors. This is in a separate file
+ from omp-general.h so that it may also be used in the Fortran parser
+ without reference to tree data structures.
+
+ Copyright (C) 2023 Free Software Foundation, Inc.
+
+This file is part of GCC.
+
+GCC is free software; you can redistribute it and/or modify it under
+the terms of the GNU General Public License as published by the Free
+Software Foundation; either version 3, or (at your option) any later
+version.
+
+GCC is distributed in the hope that it will be useful, but WITHOUT ANY
+WARRANTY; without even the implied warranty of MERCHANTABILITY or
+FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+for more details.
+
+You should have received a copy of the GNU General Public License
+along with GCC; see the file COPYING3. If not see
+<http://www.gnu.org/licenses/>. */
+
+
+#ifndef GCC_OMP_SELECTORS_H
+#define GCC_OMP_SELECTORS_H
+
+/* Trait set selector keywords. */
+enum omp_tss_code {
+ OMP_TRAIT_SET_CONSTRUCT,
+ OMP_TRAIT_SET_DEVICE,
+ OMP_TRAIT_SET_TARGET_DEVICE,
+ OMP_TRAIT_SET_IMPLEMENTATION,
+ OMP_TRAIT_SET_USER,
+ OMP_TRAIT_SET_LAST,
+ OMP_TRAIT_SET_INVALID = -1
+};
+
+/* Trait selector keywords. */
+enum omp_ts_code {
+ OMP_TRAIT_DEVICE_KIND,
+ OMP_TRAIT_DEVICE_ISA,
+ OMP_TRAIT_DEVICE_ARCH,
+ OMP_TRAIT_DEVICE_NUM,
+ OMP_TRAIT_IMPLEMENTATION_VENDOR,
+ OMP_TRAIT_IMPLEMENTATION_EXTENSION,
+ OMP_TRAIT_IMPLEMENTATION_ADMO,
+ OMP_TRAIT_IMPLEMENTATION_REQUIRES,
+ OMP_TRAIT_IMPLEMENTATION_UNIFIED_ADDRESS,
+ OMP_TRAIT_IMPLEMENTATION_UNIFIED_SHARED_MEMORY,
+ OMP_TRAIT_IMPLEMENTATION_DYNAMIC_ALLOCATORS,
+ OMP_TRAIT_IMPLEMENTATION_REVERSE_OFFLOAD,
+ OMP_TRAIT_USER_CONDITION,
+ OMP_TRAIT_CONSTRUCT_TARGET,
+ OMP_TRAIT_CONSTRUCT_TEAMS,
+ OMP_TRAIT_CONSTRUCT_PARALLEL,
+ OMP_TRAIT_CONSTRUCT_FOR,
+ OMP_TRAIT_CONSTRUCT_SIMD,
+ OMP_TRAIT_LAST,
+ OMP_TRAIT_INVALID = -1
+};
+
+/* All trait property forms. */
+enum omp_tp_type {
+ OMP_TRAIT_PROPERTY_NONE,
+ OMP_TRAIT_PROPERTY_ID,
+ OMP_TRAIT_PROPERTY_NAME_LIST,
+ OMP_TRAIT_PROPERTY_EXPR,
+ OMP_TRAIT_PROPERTY_CLAUSE_LIST,
+ OMP_TRAIT_PROPERTY_EXTENSION
+};
+
+/* Map trait set selector name keywords onto strings. */
+extern const char *omp_tss_map [];
+
+/* Map trait selector keywords onto strings, allowed contexts, and
+ allowed property names for OMP_TRAIT_PROPERTY_NAME_LIST and
+ OMP_TRAIT_PROPERTY_ID properties. If valid_properties is null,
+ it means that any required checking has to be done explicitly
+ somewhere instead of being driven by the table. Otherwise it's a
+ null-terminated array of strings. */
+struct omp_ts_info {
+ const char *name;
+ unsigned int tss_mask;
+ enum omp_tp_type tp_type;
+ bool allow_score;
+ const char * const *valid_properties;
+};
+extern struct omp_ts_info omp_ts_map[];
+
+extern enum omp_tss_code omp_lookup_tss_code (const char *);
+extern enum omp_ts_code omp_lookup_ts_code (enum omp_tss_code, const char *);
+
+#endif /* GCC_OMP_SELECTORS_H */
diff --git a/gcc/testsuite/c-c++-common/gomp/declare-variant-1.c b/gcc/testsuite/c-c++-common/gomp/declare-variant-1.c
index 8b3cd7f..75fcb7b 100644
--- a/gcc/testsuite/c-c++-common/gomp/declare-variant-1.c
+++ b/gcc/testsuite/c-c++-common/gomp/declare-variant-1.c
@@ -9,6 +9,7 @@ int bar (int, int, int *);
match (device={arch(x86_64,powerpc64),isa(avx512f,popcntb)}, \
implementation={atomic_default_mem_order(seq_cst),made_up_selector("foo", 13, "bar")}, \
user={condition(3-3)})
+/* { dg-warning "unknown selector 'made_up_selector'" "" { target *-*-* } .-2 } */
int baz (int, int, int *);
int
diff --git a/gcc/testsuite/c-c++-common/gomp/declare-variant-2.c b/gcc/testsuite/c-c++-common/gomp/declare-variant-2.c
index 3c2c12c..83e6140 100644
--- a/gcc/testsuite/c-c++-common/gomp/declare-variant-2.c
+++ b/gcc/testsuite/c-c++-common/gomp/declare-variant-2.c
@@ -14,13 +14,13 @@ void f6 (void);
void f7 (void);
#pragma omp declare variant (f1) match /* { dg-error "expected '\\(' before end of line" } */
void f8 (void);
-#pragma omp declare variant (f1) match( /* { dg-error "expected 'construct', 'device', 'implementation' or 'user' before end of line" } */
+#pragma omp declare variant (f1) match( /* { dg-error "expected context selector set name before end of line" } */
void f9 (void);
-#pragma omp declare variant (f1) match() /* { dg-error "expected 'construct', 'device', 'implementation' or 'user' before '\\)' token" } */
+#pragma omp declare variant (f1) match() /* { dg-error "expected context selector set name before '\\)' token" } */
void f10 (void);
-#pragma omp declare variant (f1) match(foo) /* { dg-error "expected 'construct', 'device', 'implementation' or 'user' before 'foo'" } */
+#pragma omp declare variant (f1) match(foo) /* { dg-error "expected context selector set name before 'foo'" } */
void f11 (void);
-#pragma omp declare variant (f1) match(something={something}) /* { dg-error "expected 'construct', 'device', 'implementation' or 'user' before 'something'" } */
+#pragma omp declare variant (f1) match(something={something}) /* { dg-error "expected context selector set name before 'something'" } */
void f12 (void);
#pragma omp declare variant (f1) match(user) /* { dg-error "expected '=' before '\\)' token" } */
void f13 (void);
@@ -42,10 +42,10 @@ void f20 (void);
void f21 (void); /* { dg-error "cannot appear in a constant-expression" "" { target c++98_only } .-1 } */
#pragma omp declare variant (f1) match(user={condition(1, 2, 3)}) /* { dg-error "expected '\\)' before ',' token" } */
void f22 (void);
-#pragma omp declare variant (f1) match(construct={master}) /* { dg-error "selector 'master' not allowed for context selector set 'construct'" } */
+#pragma omp declare variant (f1) match(construct={master}) /* { dg-warning "unknown selector 'master' for context selector set 'construct'" } */
void f23 (void);
-#pragma omp declare variant (f1) match(construct={teams,parallel,master,for}) /* { dg-error "selector 'master' not allowed for context selector set 'construct'" } */
-void f24 (void); /* { dg-error "expected '\\\}' before ',' token" "" { target c } .-1 } */
+#pragma omp declare variant (f1) match(construct={teams,parallel,master,for}) /* { dg-warning "unknown selector 'master' for context selector set 'construct'" } */
+void f24 (void);
#pragma omp declare variant (f1) match(construct={parallel(1 /* { dg-error "selector 'parallel' does not accept any properties" } */
void f25 (void); /* { dg-error "expected '\\\}' before end of line" "" { target c++ } .-1 } */
/* { dg-error "expected '\\\}' before '\\(' token" "" { target c } .-2 } */
@@ -79,11 +79,11 @@ void f38 (void); /* { dg-warning "unknown property 'foobar' of 'kind' sele
void f39 (void);
#pragma omp declare variant (f1) match(device={arch(17)}) /* { dg-error "expected identifier or string literal before numeric constant" } */
void f40 (void);
-#pragma omp declare variant (f1) match(device={foobar(3)})
+#pragma omp declare variant (f1) match(device={foobar(3)}) /* { dg-warning "unknown selector 'foobar' for context selector set 'device'" } */
void f41 (void);
#pragma omp declare variant (f1) match(device={arch(x86_64)},device={isa(avx512vl)}) /* { dg-error "selector set 'device' specified more than once" } */
void f42 (void);
-#pragma omp declare variant (f1) match(implementation={foobar(3)})
+#pragma omp declare variant (f1) match(implementation={foobar(3)}) /* { dg-warning "unknown selector 'foobar' for context selector set 'implementation'" } */
void f43 (void);
#pragma omp declare variant (f1) match(implementation={vendor}) /* { dg-error "expected '\\(' before '\\\}' token" } */
void f44 (void);
@@ -115,11 +115,11 @@ void f55 (void);
void f56 (void);
#pragma omp declare variant (f1) match(implementation={atomic_default_mem_order(relaxed)},implementation={atomic_default_mem_order(relaxed)}) /* { dg-error "selector set 'implementation' specified more than once" } */
void f57 (void);
-#pragma omp declare variant (f1) match(user={foobar(3)}) /* { dg-error "selector 'foobar' not allowed for context selector set 'user'" } */
-void f58 (void); /* { dg-error "expected '\\\}' before '\\(' token" "" { target c } .-1 } */
-#pragma omp declare variant (f1) match(construct={foobar(3)}) /* { dg-error "selector 'foobar' not allowed for context selector set 'construct'" } */
-void f59 (void); /* { dg-error "expected '\\\}' before '\\(' token" "" { target c } .-1 } */
-#pragma omp declare variant (f1) match(construct={parallel},foobar={bar}) /* { dg-error "expected 'construct', 'device', 'implementation' or 'user' before 'foobar'" } */
+#pragma omp declare variant (f1) match(user={foobar(3)}) /* { dg-warning "unknown selector 'foobar' for context selector set 'user'" } */
+void f58 (void);
+#pragma omp declare variant (f1) match(construct={foobar(3)}) /* { dg-warning "unknown selector 'foobar' for context selector set 'construct'" } */
+void f59 (void);
+#pragma omp declare variant (f1) match(construct={parallel},foobar={bar}) /* { dg-error "expected context selector set name before 'foobar'" } */
void f60 (void);
#pragma omp declare variant (f1) match(construct={parallel,parallel}) /* { dg-error "selector 'parallel' specified more than once in set 'construct'" } */
void f61 (void);
@@ -127,34 +127,34 @@ void f61 (void);
void f62 (void);
#pragma omp declare variant (f1) match(construct={target,teams,teams}) /* { dg-error "selector 'teams' specified more than once in set 'construct'" } */
void f63 (void);
-#pragma omp declare variant (f1) match(construct={single}) /* { dg-error "selector 'single' not allowed for context selector set 'construct'" } */
+#pragma omp declare variant (f1) match(construct={single}) /* { dg-warning "unknown selector 'single' for context selector set 'construct'" } */
void f64 (void);
-#pragma omp declare variant (f1) match(construct={taskgroup}) /* { dg-error "selector 'taskgroup' not allowed for context selector set 'construct'" } */
+#pragma omp declare variant (f1) match(construct={taskgroup}) /* { dg-warning "unknown selector 'taskgroup' for context selector set 'construct'" } */
void f65 (void);
-#pragma omp declare variant (f1) match(construct={do}) /* { dg-error "selector 'do' not allowed for context selector set 'construct'" } */
+#pragma omp declare variant (f1) match(construct={do}) /* { dg-warning "unknown selector 'do' for context selector set 'construct'" } */
void f66 (void);
-#pragma omp declare variant (f1) match(construct={threadprivate}) /* { dg-error "selector 'threadprivate' not allowed for context selector set 'construct'" } */
+#pragma omp declare variant (f1) match(construct={threadprivate}) /* { dg-warning "unknown selector 'threadprivate' for context selector set 'construct'" } */
void f67 (void);
-#pragma omp declare variant (f1) match(construct={critical}) /* { dg-error "selector 'critical' not allowed for context selector set 'construct'" } */
+#pragma omp declare variant (f1) match(construct={critical}) /* { dg-warning "unknown selector 'critical' for context selector set 'construct'" } */
void f68 (void);
-#pragma omp declare variant (f1) match(construct={task}) /* { dg-error "selector 'task' not allowed for context selector set 'construct'" } */
+#pragma omp declare variant (f1) match(construct={task}) /* { dg-warning "unknown selector 'task' for context selector set 'construct'" } */
void f69 (void);
-#pragma omp declare variant (f1) match(construct={taskloop}) /* { dg-error "selector 'taskloop' not allowed for context selector set 'construct'" } */
+#pragma omp declare variant (f1) match(construct={taskloop}) /* { dg-warning "unknown selector 'taskloop' for context selector set 'construct'" } */
void f70 (void);
-#pragma omp declare variant (f1) match(construct={sections}) /* { dg-error "selector 'sections' not allowed for context selector set 'construct'" } */
+#pragma omp declare variant (f1) match(construct={sections}) /* { dg-warning "unknown selector 'sections' for context selector set 'construct'" } */
void f71 (void);
-#pragma omp declare variant (f1) match(construct={section}) /* { dg-error "selector 'section' not allowed for context selector set 'construct'" } */
+#pragma omp declare variant (f1) match(construct={section}) /* { dg-warning "unknown selector 'section' for context selector set 'construct'" } */
void f72 (void);
-#pragma omp declare variant (f1) match(construct={workshare}) /* { dg-error "selector 'workshare' not allowed for context selector set 'construct'" } */
+#pragma omp declare variant (f1) match(construct={workshare}) /* { dg-warning "unknown selector 'workshare' for context selector set 'construct'" } */
void f73 (void);
-#pragma omp declare variant (f1) match(construct={requires}) /* { dg-error "selector 'requires' not allowed for context selector set 'construct'" } */
+#pragma omp declare variant (f1) match(construct={requires}) /* { dg-warning "unknown selector 'requires' for context selector set 'construct'" } */
void f74 (void);
void f75a (void);
#pragma omp declare variant (f75a),match(construct={parallel})
void f75 (void);
#pragma omp declare variant (f1) match(implementation={atomic_default_mem_order("relaxed")}) /* { dg-error "expected identifier before string constant" } */
void f76 (void);
-#pragma omp declare variant (f1) match(user={condition(score(&f76):1)}) /* { dg-error "score argument must be constant integer expression" "" { target { ! c++98_only } } } */
+#pragma omp declare variant (f1) match(user={condition(score(&f76):1)}) /* { dg-error ".score. argument must be constant integer expression" "" { target { ! c++98_only } } } */
void f77 (void); /* { dg-error "cannot appear in a constant-expression" "" { target c++98_only } .-1 } */
-#pragma omp declare variant (f1) match(user={condition(score(-130):1)}) /* { dg-error "score argument must be non-negative" } */
+#pragma omp declare variant (f1) match(user={condition(score(-130):1)}) /* { dg-error ".score. argument must be non-negative" } */
void f78 (void);
diff --git a/gcc/testsuite/c-c++-common/gomp/declare-variant-no-score.c b/gcc/testsuite/c-c++-common/gomp/declare-variant-no-score.c
new file mode 100644
index 0000000..dbe12a7
--- /dev/null
+++ b/gcc/testsuite/c-c++-common/gomp/declare-variant-no-score.c
@@ -0,0 +1,24 @@
+/* { dg-do compile { target x86_64-*-* } } */
+/* { dg-additional-options "-foffload=disable" } */
+
+void f01 (void);
+#pragma omp declare variant (f01) \
+ match (device={kind (score(5) : host)})
+ /* { dg-error ".score. cannot be specified in traits in the .device. trait-selector-set" "" { target *-*-*} .-1 } */
+void f02 (void);
+void f03 (void);
+#pragma omp declare variant (f03) \
+ match (device={kind (host), arch (score(6) : x86_64), isa (avx512f)})
+ /* { dg-error ".score. cannot be specified in traits in the .device. trait-selector-set" "" { target *-*-*} .-1 } */
+void f04 (void);
+void f05 (void);
+#pragma omp declare variant (f05) \
+ match (device={kind (host), arch (score(6) : x86_64), \
+ isa (score(7): avx512f)})
+ /* { dg-error ".score. cannot be specified in traits in the .device. trait-selector-set" "" { target *-*-*} .-2 } */
+ /* { dg-error ".score. cannot be specified in traits in the .device. trait-selector-set" "" { target *-*-*} .-2 } */
+void f06 (void);
+
+
+
+
diff --git a/gcc/testsuite/gfortran.dg/gomp/declare-variant-1.f90 b/gcc/testsuite/gfortran.dg/gomp/declare-variant-1.f90
index de09dbf..50d7e41 100644
--- a/gcc/testsuite/gfortran.dg/gomp/declare-variant-1.f90
+++ b/gcc/testsuite/gfortran.dg/gomp/declare-variant-1.f90
@@ -25,6 +25,7 @@ module main
!$omp & match (device={arch(x86_64,powerpc64),isa(avx512f,popcntb)}, &
!$omp & implementation={atomic_default_mem_order(seq_cst),made_up_selector("foo", 13, "bar")}, &
!$omp & user={condition(3-3)})
+! { dg-warning "unknown selector 'made_up_selector'" "" { target *-*-* } .-2 }
end function
subroutine quux
diff --git a/gcc/testsuite/gfortran.dg/gomp/declare-variant-2.f90 b/gcc/testsuite/gfortran.dg/gomp/declare-variant-2.f90
index 63d7778..cbb29f8 100644
--- a/gcc/testsuite/gfortran.dg/gomp/declare-variant-2.f90
+++ b/gcc/testsuite/gfortran.dg/gomp/declare-variant-2.f90
@@ -27,16 +27,16 @@ contains
!$omp declare variant (f1) match ! { dg-error "expected '\\(' at .1." }
end subroutine
subroutine f9 ()
- !$omp declare variant (f1) match( ! { dg-error "expected 'construct', 'device', 'implementation' or 'user' at .1." }
+ !$omp declare variant (f1) match( ! { dg-error "expected context selector set name at .1." }
end subroutine
subroutine f10 ()
- !$omp declare variant (f1) match() ! { dg-error "expected 'construct', 'device', 'implementation' or 'user' at .1." }
+ !$omp declare variant (f1) match() ! { dg-error "expected context selector set name at .1." }
end subroutine
subroutine f11 ()
- !$omp declare variant (f1) match(foo) ! { dg-error "expected 'construct', 'device', 'implementation' or 'user' at .1." }
+ !$omp declare variant (f1) match(foo) ! { dg-error "expected context selector set name at .1." }
end subroutine
subroutine f12 ()
- !$omp declare variant (f1) match(something={something}) ! { dg-error "expected 'construct', 'device', 'implementation' or 'user' at .1." }
+ !$omp declare variant (f1) match(something={something}) ! { dg-error "expected context selector set name at .1." }
end subroutine
subroutine f13 ()
!$omp declare variant (f1) match(user) ! { dg-error "expected '=' at .1." }
@@ -69,10 +69,10 @@ contains
!$omp declare variant (f1) match(user={condition(1, 2, 3)}) ! { dg-error "expected '\\)' at .1." }
end subroutine
subroutine f23 ()
- !$omp declare variant (f1) match(construct={master}) ! { dg-error "selector 'master' not allowed for context selector set 'construct' at .1." }
+ !$omp declare variant (f1) match(construct={master}) ! { dg-warning "unknown selector 'master' for context selector set 'construct'" }
end subroutine
subroutine f24 ()
- !$omp declare variant (f1) match(construct={teams,parallel,master,do}) ! { dg-error "selector 'master' not allowed for context selector set 'construct' at .1." }
+ !$omp declare variant (f1) match(construct={teams,parallel,master,do}) ! { dg-warning "unknown selector 'master' for context selector set 'construct'" }
end subroutine
subroutine f25 ()
!$omp declare variant (f1) match(construct={parallel(1 ! { dg-error "selector 'parallel' does not accept any properties at .1." }
@@ -105,10 +105,10 @@ contains
!$omp declare variant (f1) match(device={arch(17)}) ! { dg-error "expected identifier or string literal at .1." }
end subroutine
subroutine f41 ()
- !$omp declare variant (f1) match(device={foobar(3)})
+ !$omp declare variant (f1) match(device={foobar(3)}) ! { dg-warning "unknown selector 'foobar' for context selector set 'device' at .1." }
end subroutine
subroutine f43 ()
- !$omp declare variant (f1) match(implementation={foobar(3)})
+ !$omp declare variant (f1) match(implementation={foobar(3)}) ! { dg-warning "unknown selector 'foobar' for context selector set 'implementation' at .1." }
end subroutine
subroutine f44 ()
!$omp declare variant (f1) match(implementation={vendor}) ! { dg-error "expected '\\(' at .1." }
@@ -141,46 +141,46 @@ contains
!$omp declare variant (f1) match(implementation={atomic_default_mem_order(relaxed,seq_cst)}) ! { dg-error "expected '\\)' at .1." }
end subroutine
subroutine f58 ()
- !$omp declare variant (f1) match(user={foobar(3)}) ! { dg-error "selector 'foobar' not allowed for context selector set 'user' at .1." }
+ !$omp declare variant (f1) match(user={foobar(3)}) ! { dg-warning "unknown selector 'foobar' for context selector set 'user' at .1." }
end subroutine
subroutine f59 ()
- !$omp declare variant (f1) match(construct={foobar(3)}) ! { dg-error "selector 'foobar' not allowed for context selector set 'construct' at .1." }
+ !$omp declare variant (f1) match(construct={foobar(3)}) ! { dg-warning "unknown selector 'foobar' for context selector set 'construct' at .1." }
end subroutine
subroutine f60 ()
- !$omp declare variant (f1) match(construct={parallel},foobar={bar}) ! { dg-error "expected 'construct', 'device', 'implementation' or 'user' at .1." }
+ !$omp declare variant (f1) match(construct={parallel},foobar={bar}) ! { dg-error "expected context selector set name at .1." }
end subroutine
subroutine f64 ()
- !$omp declare variant (f1) match(construct={single}) ! { dg-error "selector 'single' not allowed for context selector set 'construct' at .1." }
+ !$omp declare variant (f1) match(construct={single}) ! { dg-warning "unknown selector 'single' for context selector set 'construct' at .1." }
end subroutine
subroutine f65 ()
- !$omp declare variant (f1) match(construct={taskgroup}) ! { dg-error "selector 'taskgroup' not allowed for context selector set 'construct' at .1." }
+ !$omp declare variant (f1) match(construct={taskgroup}) ! { dg-warning "unknown selector 'taskgroup' for context selector set 'construct' at .1." }
end subroutine
subroutine f66 ()
- !$omp declare variant (f1) match(construct={for}) ! { dg-error "selector 'for' not allowed for context selector set 'construct' at .1." }
+ !$omp declare variant (f1) match(construct={for}) ! { dg-warning "unknown selector 'for' for context selector set 'construct' at .1." }
end subroutine
subroutine f67 ()
- !$omp declare variant (f1) match(construct={threadprivate}) ! { dg-error "selector 'threadprivate' not allowed for context selector set 'construct' at .1." }
+ !$omp declare variant (f1) match(construct={threadprivate}) ! { dg-warning "unknown selector 'threadprivate' for context selector set 'construct' at .1." }
end subroutine
subroutine f68 ()
- !$omp declare variant (f1) match(construct={critical}) ! { dg-error "selector 'critical' not allowed for context selector set 'construct' at .1." }
+ !$omp declare variant (f1) match(construct={critical}) ! { dg-warning "unknown selector 'critical' for context selector set 'construct' at .1." }
end subroutine
subroutine f69 ()
- !$omp declare variant (f1) match(construct={task}) ! { dg-error "selector 'task' not allowed for context selector set 'construct' at .1." }
+ !$omp declare variant (f1) match(construct={task}) ! { dg-warning "unknown selector 'task' for context selector set 'construct' at .1." }
end subroutine
subroutine f70 ()
- !$omp declare variant (f1) match(construct={taskloop}) ! { dg-error "selector 'taskloop' not allowed for context selector set 'construct' at .1." }
+ !$omp declare variant (f1) match(construct={taskloop}) ! { dg-warning "unknown selector 'taskloop' for context selector set 'construct' at .1." }
end subroutine
subroutine f71 ()
- !$omp declare variant (f1) match(construct={sections}) ! { dg-error "selector 'sections' not allowed for context selector set 'construct' at .1." }
+ !$omp declare variant (f1) match(construct={sections}) ! { dg-warning "unknown selector 'sections' for context selector set 'construct' at .1." }
end subroutine
subroutine f72 ()
- !$omp declare variant (f1) match(construct={section}) ! { dg-error "selector 'section' not allowed for context selector set 'construct' at .1." }
+ !$omp declare variant (f1) match(construct={section}) ! { dg-warning "unknown selector 'section' for context selector set 'construct' at .1." }
end subroutine
subroutine f73 ()
- !$omp declare variant (f1) match(construct={workshare}) ! { dg-error "selector 'workshare' not allowed for context selector set 'construct' at .1." }
+ !$omp declare variant (f1) match(construct={workshare}) ! { dg-warning "unknown selector 'workshare' for context selector set 'construct' at .1." }
end subroutine
subroutine f74 ()
- !$omp declare variant (f1) match(construct={requires}) ! { dg-error "selector 'requires' not allowed for context selector set 'construct' at .1." }
+ !$omp declare variant (f1) match(construct={requires}) ! { dg-warning "unknown selector 'requires' for context selector set 'construct' at .1." }
end subroutine
subroutine f75 ()
!$omp declare variant (f1),match(construct={parallel}) ! { dg-error "expected 'match' at .1." }
@@ -189,9 +189,9 @@ contains
!$omp declare variant (f1) match(implementation={atomic_default_mem_order("relaxed")}) ! { dg-error "expected identifier at .1." }
end subroutine
subroutine f77 ()
- !$omp declare variant (f1) match(user={condition(score(f76):1)}) ! { dg-error "score argument must be constant integer expression at .1." }
+ !$omp declare variant (f1) match(user={condition(score(f76):1)}) ! { dg-error ".score. argument must be constant integer expression at .1." }
end subroutine
subroutine f78 ()
- !$omp declare variant (f1) match(user={condition(score(-130):1)}) ! { dg-error "score argument must be non-negative" }
+ !$omp declare variant (f1) match(user={condition(score(-130):1)}) ! { dg-error ".score. argument must be non-negative" }
end subroutine
end module
diff --git a/gcc/testsuite/gfortran.dg/gomp/declare-variant-no-score.f90 b/gcc/testsuite/gfortran.dg/gomp/declare-variant-no-score.f90
new file mode 100644
index 0000000..616a34b
--- /dev/null
+++ b/gcc/testsuite/gfortran.dg/gomp/declare-variant-no-score.f90
@@ -0,0 +1,30 @@
+! { dg-do compile { target x86_64-*-* } }
+! { dg-additional-options "-foffload=disable" }
+
+program main
+contains
+ subroutine f01 ()
+ end subroutine
+ subroutine f02 ()
+ !$omp declare variant (f01) &
+ !$omp& match (device={kind (score(5) : host)})
+ ! { dg-error ".score. cannot be specified in traits in the .device. trait-selector-set" "" { target *-*-*} .-1 }
+ end subroutine
+ subroutine f03 ()
+ end subroutine
+ subroutine f04 ()
+ !$omp declare variant (f03) &
+ !$omp& match (device={kind (host), arch (score(6) : x86_64), isa (avx512f)})
+ ! { dg-error ".score. cannot be specified in traits in the .device. trait-selector-set" "" { target *-*-*} .-1 }
+ end subroutine
+ subroutine f05 ()
+ end subroutine
+ subroutine f06 ()
+ !$omp declare variant (f05) &
+ !$omp& match (device={kind (host), arch (score(6) : x86_64), &
+ !$omp& isa (score(7): avx512f)})
+ ! { dg-error ".score. cannot be specified in traits in the .device. trait-selector-set" "" { target *-*-*} .-2 }
+ end subroutine
+
+end program
+