diff --git a/gcc/c/c-parser.cc b/gcc/c/c-parser.cc index b5bed5ee276..4f1e0662c72 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]) + if (sel == OMP_TRAIT_INVALID) { - 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 (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, + "% 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, "% 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, "% 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) { - error_at (token->location, "properties for % " - "selector may not be specified in " - "%"); + if (parms == NULL_TREE) + { + error_at (token->location, "properties for % " + "selector may not be specified in " + "%"); + 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) + { + /* 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, + "% 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]) + enum omp_tss_code set = omp_lookup_tss_code (setp); + + if (set == OMP_TRAIT_SET_INVALID) { - 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) - { - c_parser_error (parser, "expected %, %, " - "% or %"); + 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 1ffe4c82748..27f17808934 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 3250b0bda6d..cb1dcd8e402 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]) + enum omp_ts_code sel + = omp_lookup_ts_code (set, IDENTIFIER_POINTER (selector)); + + if (sel == OMP_TRAIT_INVALID) { - 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 (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, + "% 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, "% 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, "% 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) { - error_at (token->location, "properties for % " - "selector may not be specified in " - "%"); + if (!has_parms_p) + { + error_at (token->location, "properties for % " + "selector may not be specified in " + "%"); + 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) + { + /* 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, + "% 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]) + enum omp_tss_code set = omp_lookup_tss_code (setp); + + if (set == OMP_TRAIT_SET_INVALID) { - case 'c': - if (strcmp (setp, "construct") == 0) - setp = NULL; - break; - case 'd': - if (strcmp (setp, "device") == 0) - setp = NULL; - break; - case 'i': - if (strcmp (setp, "implementation") == 0) - setp = NULL; - break; - case 'u': - if (strcmp (setp, "user") == 0) - setp = NULL; - break; - default: - break; - } - if (setp) - { - cp_parser_error (parser, "expected %, %, " - "% or %"); + 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 ef280e417d4..f7063e09581 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 b5e1b4c9d4b..1cb48f82979 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 8c0e5445ddb..f0d39e15263 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]) + if (os->code == OMP_TRAIT_INVALID) { - case 'c': /* construct */ - selectors = omp_construct_selectors; - allow_score = false; - property_limit = 1; - property_kind = CTX_PROPERTY_SIMD; + 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; - 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 (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; - } - 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 ("% 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 ("% 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 ("% 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) { - gfc_error ("expected simd clause at %C"); + 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) + { + /* FIXME: The "requires" selector was added in OpenMP 5.1. + Currently only the now-deprecated syntax + from OpenMP 5.0 is supported. */ + sorry ("% 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 %, %, % " - "or % 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 93f75162a2a..a757b84c1c5 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 f61c8ae7a30..12c06b219b7 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 285bc788836..d7a5d475f4a 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, "% 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 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 % " "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, const char *set, const char *sel) +omp_get_context_selector (tree ctx, enum omp_tss_code set, + enum omp_ts_code sel) { - 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) + 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_list (tree ctx, enum omp_tss_code set) +{ + for (tree tss = ctx; tss; tss = TREE_CHAIN (tss)) + 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 > score_wide_int; @@ -2019,14 +2188,18 @@ typedef generic_wide_int > 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 40ede66568b..66ed4903513 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 00000000000..825a082c939 --- /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 +. */ + + +#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 8b3cd7fed9f..75fcb7bf0e7 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 3c2c12c9e03..83e61403b5e 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 00000000000..dbe12a7348b --- /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 de09dbfe806..50d7e41613f 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 63d77780196..cbb29f87302 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 00000000000..616a34bc8f5 --- /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 +