aboutsummaryrefslogtreecommitdiff
path: root/gcc/c/c-parser.cc
diff options
context:
space:
mode:
authorJerry DeLisle <jvdelisle@gcc.gnu.org>2025-09-02 15:58:26 -0700
committerJerry DeLisle <jvdelisle@gcc.gnu.org>2025-09-02 15:58:26 -0700
commit071b4126c613881f4cb25b4e5c39032964827f88 (patch)
tree7ed805786566918630d1d617b1ed8f7310f5fd8e /gcc/c/c-parser.cc
parent845d23f3ea08ba873197c275a8857eee7edad996 (diff)
parentcaa1c2f42691d68af4d894a5c3e700ecd2dba080 (diff)
downloadgcc-devel/gfortran-test.zip
gcc-devel/gfortran-test.tar.gz
gcc-devel/gfortran-test.tar.bz2
Merge branch 'master' into gfortran-testdevel/gfortran-test
Diffstat (limited to 'gcc/c/c-parser.cc')
-rw-r--r--gcc/c/c-parser.cc487
1 files changed, 317 insertions, 170 deletions
diff --git a/gcc/c/c-parser.cc b/gcc/c/c-parser.cc
index 4a13fc0..566ab1b 100644
--- a/gcc/c/c-parser.cc
+++ b/gcc/c/c-parser.cc
@@ -2822,7 +2822,7 @@ c_parser_declaration_or_fndef (c_parser *parser, bool fndef_ok,
specs->constexpr_p, &richloc);
/* A parameter is initialized, which is invalid. Don't
attempt to instrument the initializer. */
- int flag_sanitize_save = flag_sanitize;
+ sanitize_code_type flag_sanitize_save = flag_sanitize;
if (nested && !empty_ok)
flag_sanitize = 0;
init = c_parser_expr_no_commas (parser, NULL);
@@ -2911,7 +2911,7 @@ c_parser_declaration_or_fndef (c_parser *parser, bool fndef_ok,
specs->constexpr_p, &richloc);
/* A parameter is initialized, which is invalid. Don't
attempt to instrument the initializer. */
- int flag_sanitize_save = flag_sanitize;
+ sanitize_code_type flag_sanitize_save = flag_sanitize;
if (TREE_CODE (d) == PARM_DECL)
flag_sanitize = 0;
init = c_parser_initializer (parser, d);
@@ -11876,12 +11876,9 @@ c_parser_postfix_expression (c_parser *parser)
if (c_parser_next_token_is (parser, CPP_NAME))
{
c_token *comp_tok = c_parser_peek_token (parser);
- /* Ignore the counted_by attribute for reference inside
- offsetof since the information is not useful at all. */
offsetof_ref
= build_component_ref (loc, offsetof_ref, comp_tok->value,
- comp_tok->location, UNKNOWN_LOCATION,
- false);
+ comp_tok->location, UNKNOWN_LOCATION);
c_parser_consume_token (parser);
while (c_parser_next_token_is (parser, CPP_DOT)
|| c_parser_next_token_is (parser,
@@ -11908,14 +11905,11 @@ c_parser_postfix_expression (c_parser *parser)
break;
}
c_token *comp_tok = c_parser_peek_token (parser);
- /* Ignore the counted_by attribute for reference inside
- offsetof since the information is not useful. */
offsetof_ref
= build_component_ref (loc, offsetof_ref,
comp_tok->value,
comp_tok->location,
- UNKNOWN_LOCATION,
- false);
+ UNKNOWN_LOCATION);
c_parser_consume_token (parser);
}
else
@@ -12701,7 +12695,7 @@ c_parser_postfix_expression (c_parser *parser)
/* If the array ref is inside TYPEOF or ALIGNOF, the call to
.ACCESS_WITH_SIZE was not generated by the routine
build_component_ref by default, we should generate it here. */
- if ((in_typeof || in_alignof) && TREE_CODE (ref) == COMPONENT_REF)
+ if (TREE_CODE (ref) == COMPONENT_REF)
ref = handle_counted_by_for_component_ref (loc, ref);
if (has_counted_by_object (ref))
@@ -16659,7 +16653,7 @@ c_parser_omp_variable_list (c_parser *parser,
|| CONVERT_EXPR_P (decl))
decl = TREE_OPERAND (decl, 0);
- tree u = build_omp_clause (clause_loc, kind);
+ tree u = build_omp_clause (loc, kind);
OMP_CLAUSE_DECL (u) = decl;
OMP_CLAUSE_CHAIN (u) = list;
list = u;
@@ -20072,7 +20066,7 @@ c_parser_omp_clause_doacross (c_parser *parser, tree list)
map ( [map-type-modifier[,] ...] map-kind: variable-list )
map-type-modifier:
- always | close */
+ always | close | present | iterator (iterators-definition) */
static tree
c_parser_omp_clause_map (c_parser *parser, tree list, bool declare_mapper_p)
@@ -20087,15 +20081,35 @@ c_parser_omp_clause_map (c_parser *parser, tree list, bool declare_mapper_p)
int pos = 1;
int map_kind_pos = 0;
- while (c_parser_peek_nth_token_raw (parser, pos)->type == CPP_NAME)
+ int iterator_length = 0;
+ for (;;)
{
- if (c_parser_peek_nth_token_raw (parser, pos + 1)->type == CPP_COLON)
+ c_token *tok = c_parser_peek_nth_token_raw (parser, pos);
+ if (tok->type != CPP_NAME)
+ break;
+
+ const char *p = IDENTIFIER_POINTER (tok->value);
+ c_token *next_tok = c_parser_peek_nth_token_raw (parser, pos + 1);
+ if (strcmp (p, "iterator") == 0 && next_tok->type == CPP_OPEN_PAREN)
+ {
+ unsigned n = pos + 2;
+ if (c_parser_check_balanced_raw_token_sequence (parser, &n)
+ && c_parser_peek_nth_token_raw (parser, n)->type
+ == CPP_CLOSE_PAREN)
+ {
+ iterator_length = n - pos + 1;
+ pos = n;
+ next_tok = c_parser_peek_nth_token_raw (parser, pos + 1);
+ }
+ }
+
+ if (next_tok->type == CPP_COLON)
{
map_kind_pos = pos;
break;
}
- if (c_parser_peek_nth_token_raw (parser, pos + 1)->type == CPP_COMMA)
+ if (next_tok->type == CPP_COMMA)
pos++;
else if (c_parser_peek_nth_token_raw (parser, pos + 1)->type
== CPP_OPEN_PAREN)
@@ -20117,6 +20131,7 @@ c_parser_omp_clause_map (c_parser *parser, tree list, bool declare_mapper_p)
int present_modifier = 0;
int mapper_modifier = 0;
tree mapper_name = NULL_TREE;
+ tree iterators = NULL_TREE;
for (int pos = 1; pos < map_kind_pos; ++pos)
{
c_token *tok = c_parser_peek_token (parser);
@@ -20150,6 +20165,17 @@ c_parser_omp_clause_map (c_parser *parser, tree list, bool declare_mapper_p)
close_modifier++;
c_parser_consume_token (parser);
}
+ else if (strcmp ("iterator", p) == 0)
+ {
+ if (iterators)
+ {
+ c_parser_error (parser, "too many %<iterator%> modifiers");
+ parens.skip_until_found_close (parser);
+ return list;
+ }
+ iterators = c_parser_omp_iterators (parser);
+ pos += iterator_length - 1;
+ }
else if (strcmp ("mapper", p) == 0)
{
c_parser_consume_token (parser);
@@ -20223,8 +20249,8 @@ c_parser_omp_clause_map (c_parser *parser, tree list, bool declare_mapper_p)
else
{
c_parser_error (parser, "%<map%> clause with map-type modifier other "
- "than %<always%>, %<close%>, %<mapper%> or "
- "%<present%>");
+ "than %<always%>, %<close%>, %<iterator%>, "
+ "%<mapper%> or %<present%>");
parens.skip_until_found_close (parser);
return list;
}
@@ -20273,9 +20299,19 @@ c_parser_omp_clause_map (c_parser *parser, tree list, bool declare_mapper_p)
tree last_new = NULL_TREE;
+ if (iterators)
+ {
+ tree block = pop_scope ();
+ if (iterators == error_mark_node)
+ iterators = NULL_TREE;
+ else
+ TREE_VEC_ELT (iterators, 5) = block;
+ }
+
for (c = nl; c != list; c = OMP_CLAUSE_CHAIN (c))
{
OMP_CLAUSE_SET_MAP_KIND (c, kind);
+ OMP_CLAUSE_ITERATORS (c) = iterators;
last_new = c;
}
@@ -20534,8 +20570,11 @@ c_parser_omp_clause_device_type (c_parser *parser, tree list)
to ( variable-list )
OpenMP 5.1:
- from ( [present :] variable-list )
- to ( [present :] variable-list ) */
+ from ( [motion-modifier[,] [motion-modifier[,]...]:] variable-list )
+ to ( [motion-modifier[,] [motion-modifier[,]...]:] variable-list )
+
+ motion-modifier:
+ present | iterator (iterators-definition) */
static tree
c_parser_omp_clause_from_to (c_parser *parser, enum omp_clause_code kind,
@@ -20546,18 +20585,85 @@ c_parser_omp_clause_from_to (c_parser *parser, enum omp_clause_code kind,
if (!parens.require_open (parser))
return list;
+ int pos = 1, colon_pos = 0;
+ int iterator_length = 0;
+
+ while (c_parser_peek_nth_token_raw (parser, pos)->type == CPP_NAME)
+ {
+ const char *identifier =
+ IDENTIFIER_POINTER (c_parser_peek_nth_token_raw (parser, pos)->value);
+ if (c_parser_peek_nth_token_raw (parser, pos + 1)->type
+ == CPP_OPEN_PAREN)
+ {
+ unsigned int npos = pos + 2;
+ if (c_parser_check_balanced_raw_token_sequence (parser, &npos)
+ && (c_parser_peek_nth_token_raw (parser, npos)->type
+ == CPP_CLOSE_PAREN))
+ {
+ if (strcmp (identifier, "iterator") == 0)
+ iterator_length = npos - pos + 1;
+ pos = npos;
+ }
+ }
+ if (c_parser_peek_nth_token_raw (parser, pos + 1)->type == CPP_COMMA)
+ pos += 2;
+ else
+ pos++;
+ if (c_parser_peek_nth_token_raw (parser, pos)->type == CPP_COLON)
+ {
+ colon_pos = pos;
+ break;
+ }
+ }
+
bool present = false;
- c_token *token = c_parser_peek_token (parser);
+ tree iterators = NULL_TREE;
- if (token->type == CPP_NAME
- && strcmp (IDENTIFIER_POINTER (token->value), "present") == 0
- && c_parser_peek_2nd_token (parser)->type == CPP_COLON)
+ for (int pos = 1; pos < colon_pos; ++pos)
{
- present = true;
- c_parser_consume_token (parser);
- c_parser_consume_token (parser);
+ c_token *token = c_parser_peek_token (parser);
+ if (token->type == CPP_COMMA)
+ {
+ c_parser_consume_token (parser);
+ continue;
+ }
+ const char *p = IDENTIFIER_POINTER (token->value);
+ if (strcmp ("present", p) == 0)
+ {
+ if (present)
+ {
+ c_parser_error (parser, "too many %<present%> modifiers");
+ parens.skip_until_found_close (parser);
+ return list;
+ }
+ present = true;
+ c_parser_consume_token (parser);
+ }
+ else if (strcmp ("iterator", p) == 0)
+ {
+ if (iterators)
+ {
+ c_parser_error (parser, "too many %<iterator%> modifiers");
+ parens.skip_until_found_close (parser);
+ return list;
+ }
+ iterators = c_parser_omp_iterators (parser);
+ pos += iterator_length - 1;
+ }
+ else
+ {
+ error_at (token->location,
+ "%qs clause with modifier other than %<iterator%> or "
+ "%<present%>",
+ kind == OMP_CLAUSE_TO ? "to" : "from");
+ parens.skip_until_found_close (parser);
+ return list;
+ }
}
+ if (colon_pos)
+ c_parser_require (parser, CPP_COLON, "expected %<:%>");
+
tree nl = c_parser_omp_variable_list (parser, loc, kind, list);
parens.skip_until_found_close (parser);
@@ -20565,6 +20671,19 @@ c_parser_omp_clause_from_to (c_parser *parser, enum omp_clause_code kind,
for (tree c = nl; c != list; c = OMP_CLAUSE_CHAIN (c))
OMP_CLAUSE_MOTION_PRESENT (c) = 1;
+ if (iterators)
+ {
+ tree block = pop_scope ();
+ if (iterators == error_mark_node)
+ iterators = NULL_TREE;
+ else
+ TREE_VEC_ELT (iterators, 5) = block;
+ }
+
+ if (iterators)
+ for (tree c = nl; c != list; c = OMP_CLAUSE_CHAIN (c))
+ OMP_CLAUSE_ITERATORS (c) = iterators;
+
return nl;
}
@@ -27185,6 +27304,30 @@ c_finish_omp_declare_variant (c_parser *parser, tree fndecl, tree parms)
undeclared_variable (token->location, token->value);
variant = error_mark_node;
}
+ else if (TREE_CODE (variant) != FUNCTION_DECL)
+ {
+ error_at (token->location, "variant %qD is not a function",
+ variant);
+ variant = error_mark_node;
+ }
+ else if (fndecl_built_in_p (variant)
+ && (strncmp (IDENTIFIER_POINTER (DECL_NAME (variant)),
+ "__builtin_", strlen ("__builtin_")) == 0
+ || strncmp (IDENTIFIER_POINTER (DECL_NAME (variant)),
+ "__sync_", strlen ("__sync_")) == 0
+ || strncmp (IDENTIFIER_POINTER (DECL_NAME (variant)),
+ "__atomic_", strlen ("__atomic_")) == 0))
+ {
+ error_at (token->location, "variant %qD is a built-in",
+ variant);
+ variant = error_mark_node;
+ }
+ else if (variant == fndecl)
+ {
+ error_at (token->location, "variant %qD is the same as base function",
+ variant);
+ variant = error_mark_node;
+ }
c_parser_consume_token (parser);
@@ -27258,30 +27401,6 @@ c_finish_omp_declare_variant (c_parser *parser, tree fndecl, tree parms)
goto fail;
ctx = omp_check_context_selector (match_loc, ctx,
OMP_CTX_DECLARE_VARIANT);
- if (ctx != error_mark_node && variant != error_mark_node)
- {
- if (TREE_CODE (variant) != FUNCTION_DECL)
- {
- error_at (token->location, "variant %qD is not a function",
- variant);
- variant = error_mark_node;
- }
- else if (fndecl_built_in_p (variant)
- && (strncmp (IDENTIFIER_POINTER (DECL_NAME (variant)),
- "__builtin_", strlen ("__builtin_"))
- == 0
- || strncmp (IDENTIFIER_POINTER (DECL_NAME (variant)),
- "__sync_", strlen ("__sync_"))
- == 0
- || strncmp (IDENTIFIER_POINTER (DECL_NAME (variant)),
- "__atomic_", strlen ("__atomic_"))
- == 0))
- {
- error_at (token->location, "variant %qD is a built-in",
- variant);
- variant = error_mark_node;
- }
- }
}
else if (ccode == adjust_args)
{
@@ -27423,18 +27542,64 @@ c_finish_omp_declare_variant (c_parser *parser, tree fndecl, tree parms)
parens.require_close (parser);
} while (c_parser_next_token_is_not (parser, CPP_PRAGMA_EOL));
+ if (variant != error_mark_node && !has_match)
+ {
+ c_parser_error (parser, "expected %<match%> clause");
+ variant = error_mark_node;
+ }
c_parser_skip_to_pragma_eol (parser);
- if ((ctx != error_mark_node && variant != error_mark_node)
+ /* At this point, we have completed parsing of the pragma, now it's
+ on to error checking. */
+ if (variant == error_mark_node || ctx == error_mark_node)
+ /* Previously diagnosed error. */
+ return;
+
+ if ((has_adjust_args || append_args_tree)
&& !omp_get_context_selector (ctx, OMP_TRAIT_SET_CONSTRUCT,
- OMP_TRAIT_CONSTRUCT_SIMD))
+ OMP_TRAIT_CONSTRUCT_DISPATCH))
{
- bool fail = false;
- if (append_args_tree)
+ error_at (has_adjust_args ? adjust_args_loc : append_args_loc,
+ "an %qs clause can only be specified if the "
+ "%<dispatch%> selector of the %<construct%> selector "
+ "set appears in the %<match%> clause",
+ has_adjust_args ? "adjust_args" : "append_args");
+ return;
+ }
+
+ if (!omp_get_context_selector (ctx, OMP_TRAIT_SET_CONSTRUCT,
+ OMP_TRAIT_CONSTRUCT_SIMD))
+ /* Check that the base and variant have compatible types. */
+ {
+ tree base_type = TREE_TYPE (fndecl);
+ tree variant_type = TREE_TYPE (variant);
+ bool unprototyped_variant
+ = (TYPE_ARG_TYPES (variant_type) == NULL_TREE
+ && !TYPE_NO_NAMED_ARGS_STDARG_P (variant_type));
+
+ if (append_args_tree
+ && TYPE_ARG_TYPES (base_type) == NULL_TREE
+ && !TYPE_NO_NAMED_ARGS_STDARG_P (base_type))
+ {
+ /* The base function is a pre-C23 unprototyped function. Without
+ a prototype, we don't know the offset where the append_args go.
+ That offset needs to be stored with the append_args in the
+ variant function attributes, so we cannot presently handle
+ this case. */
+ sorry_at (append_args_loc,
+ "%<append_args%> with unprototyped base function "
+ "is not supported yet");
+ inform (DECL_SOURCE_LOCATION (fndecl),
+ "base function %qD declared here", fndecl);
+ return;
+ }
+ else if (append_args_tree)
{
+ /* Find nbase_args, the number of fixed arguments in the base
+ function. */
int nappend_args = 0;
int nbase_args = 0;
- for (tree t = TYPE_ARG_TYPES (TREE_TYPE (fndecl));
+ for (tree t = TYPE_ARG_TYPES (base_type);
t && TREE_VALUE (t) != void_type_node; t = TREE_CHAIN (t))
nbase_args++;
for (tree t = append_args_tree; t; t = TREE_CHAIN (t))
@@ -27445,135 +27610,117 @@ c_finish_omp_declare_variant (c_parser *parser, tree fndecl, tree parms)
append_args_tree = build_tree_list (build_int_cst (integer_type_node,
nbase_args),
append_args_tree);
- tree args, arg;
- args = arg = TYPE_ARG_TYPES (TREE_TYPE (variant));
- for (int j = 0; j < nbase_args && arg; j++, arg = TREE_CHAIN (arg))
- args = arg;
- for (int i = 0; i < nappend_args && arg; i++)
- arg = TREE_CHAIN (arg);
- tree saved_args;
- if (nbase_args && args)
- {
- saved_args = TREE_CHAIN (args);
- TREE_CHAIN (args) = arg;
+
+ /* Give a specific diagnostic if the append_args parameters
+ of the variant are of the wrong type, or missing. The
+ compatible types test below could fail to detect this if
+ the variant is a varargs function. */
+ if (!unprototyped_variant)
+ {
+ tree args = TYPE_ARG_TYPES (variant_type);
+ for (int i = 0; args && i < nbase_args;
+ i++, args = TREE_CHAIN (args))
+ ;
+ for (int i = 0; i < nappend_args; i++, args = TREE_CHAIN (args))
+ if (!args || !c_omp_interop_t_p (TREE_VALUE (args)))
+ {
+ error_at (DECL_SOURCE_LOCATION (variant),
+ "argument %d of %qD must be of "
+ "%<omp_interop_t%>",
+ nbase_args + i + 1, variant);
+ inform (append_args_loc,
+ "%<append_args%> specified here");
+ return;
+ }
}
- else
+
+ /* Perform the "implementation defined transformation" on the type
+ of the base function to add the append_args before checking it
+ for compatibility with the function variant's type. */
+ tree args = TYPE_ARG_TYPES (base_type);
+ tree newargs = NULL_TREE;
+ tree lastarg = NULL_TREE;
+ for (int j = 0; j < nbase_args; j++, args = TREE_CHAIN (args))
{
- saved_args = args;
- TYPE_ARG_TYPES (TREE_TYPE (variant)) = arg;
- TYPE_NO_NAMED_ARGS_STDARG_P (TREE_TYPE (variant)) = 1;
+ tree t = tree_cons (TREE_PURPOSE (args),
+ TREE_VALUE (args), NULL_TREE);
+ if (lastarg)
+ TREE_CHAIN (lastarg) = t;
+ else
+ newargs = t;
+ lastarg = t;
}
- if (!comptypes (TREE_TYPE (fndecl), TREE_TYPE (variant)))
- fail = true;
- if (nbase_args && args)
- TREE_CHAIN (args) = saved_args;
- else
+ tree type = lookup_name (get_identifier ("omp_interop_t"));
+ type = type ? TREE_TYPE (type) : pointer_sized_int_node;
+ for (int j = 0; j < nappend_args; j++)
{
- TYPE_ARG_TYPES (TREE_TYPE (variant)) = saved_args;
- TYPE_NO_NAMED_ARGS_STDARG_P (TREE_TYPE (variant)) = 0;
+ tree t = tree_cons (NULL_TREE, type, NULL_TREE);
+ if (lastarg)
+ TREE_CHAIN (lastarg) = t;
+ else
+ newargs = t;
+ lastarg = t;
}
- arg = saved_args;
- if (!fail)
- for (int i = 0; i < nappend_args; i++, arg = TREE_CHAIN (arg))
- if (!arg || !c_omp_interop_t_p (TREE_VALUE (arg)))
- {
- error_at (DECL_SOURCE_LOCATION (variant),
- "argument %d of %qD must be of %<omp_interop_t%>",
- nbase_args + i + 1, variant);
- inform (append_args_loc, "%<append_args%> specified here");
- break;
- }
- }
- else
- {
- if (comptypes (TREE_TYPE (fndecl), TREE_TYPE (variant)))
+ TREE_CHAIN (lastarg) = args;
+
+ /* Temporarily stuff newargs into the original base_type. */
+ tree saveargs = TYPE_ARG_TYPES (base_type);
+ TYPE_ARG_TYPES (base_type) = newargs;
+ bool fail = !comptypes (base_type, variant_type);
+ TYPE_ARG_TYPES (base_type) = saveargs;
+
+ if (fail)
{
- if (TYPE_ARG_TYPES (TREE_TYPE (variant)) == NULL_TREE
- && TYPE_ARG_TYPES (TREE_TYPE (fndecl)) != NULL_TREE)
- {
- if (!append_args_tree)
- TYPE_ARG_TYPES (TREE_TYPE (variant))
- = TYPE_ARG_TYPES (TREE_TYPE (fndecl));
- else
- {
- tree new_args = NULL_TREE;
- tree arg, last_arg = NULL_TREE;
- for (arg = TYPE_ARG_TYPES (TREE_TYPE (fndecl));
- arg && arg != void_type_node; arg = TREE_CHAIN (arg))
- {
- if (new_args == NULL_TREE)
- new_args = last_arg = copy_node (arg);
- else
- {
- TREE_CHAIN (last_arg) = copy_node (arg);
- last_arg = TREE_CHAIN (last_arg);
- }
- }
- for (tree t3 = append_args_tree; t3; t3 = TREE_CHAIN (t3))
- {
- tree type = lookup_name (get_identifier ("omp_interop_t"));
- type = type ? TREE_TYPE (type) : ptr_type_node;
- last_arg = tree_cons (NULL_TREE, type, last_arg);
- }
- TREE_CHAIN (last_arg) = arg;
- TYPE_ARG_TYPES (TREE_TYPE (variant)) = new_args;
- }
- }
+ error_at (token->location,
+ "variant %qD and base %qD have incompatible types "
+ "after %<append_args%> adjustment",
+ variant, fndecl);
+ inform (DECL_SOURCE_LOCATION (variant),
+ "%<declare variant%> candidate %qD declared here",
+ variant);
+ return;
}
- else
- fail = true;
+ else if (unprototyped_variant)
+ /* If we've got an unprototyped variant, copy the transformed
+ base arg types to the variant. This is needed later by
+ modify_call_for_omp_dispatch. */
+ TYPE_ARG_TYPES (variant_type) = newargs;
}
- if (fail)
- {
- error_at (token->location,
- "variant %qD and base %qD have incompatible types",
- variant, fndecl);
- variant = error_mark_node;
- }
- }
- if (ctx != error_mark_node && variant != error_mark_node)
- {
- C_DECL_USED (variant) = 1;
- 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, NULL_TREE, false))
+ else /* No append_args present. */
{
- tree attr = tree_cons (get_identifier ("omp declare variant base"),
- build_tree_list (variant, ctx),
- DECL_ATTRIBUTES (fndecl));
- DECL_ATTRIBUTES (fndecl) = attr;
+ if (!comptypes (base_type, variant_type))
+ {
+ error_at (token->location,
+ "variant %qD and base %qD have incompatible types",
+ variant, fndecl);
+ inform (DECL_SOURCE_LOCATION (variant),
+ "%<declare variant%> candidate %qD declared here",
+ variant);
+ return;
+ }
+ else if (TYPE_ARG_TYPES (variant_type) == NULL_TREE
+ && !TYPE_NO_NAMED_ARGS_STDARG_P (variant_type)
+ && TYPE_ARG_TYPES (base_type) != NULL_TREE)
+ /* If we've got an unprototyped variant but the base has
+ a prototype, copy the base arg types to the variant. */
+ TYPE_ARG_TYPES (variant_type) = TYPE_ARG_TYPES (base_type);
}
}
- if (has_adjust_args || append_args_tree)
+ /* If we made it here, store the parsed information. */
+ C_DECL_USED (variant) = 1;
+ 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, NULL_TREE, false))
{
- if (!has_match)
- {
- error_at (has_adjust_args ? adjust_args_loc : append_args_loc,
- "an %qs clause requires a %<match%> clause",
- has_adjust_args ? "adjust_args" : "append_args");
- }
- else if (ctx != error_mark_node && variant != error_mark_node)
- {
- tree attr = lookup_attribute ("omp declare variant base",
- DECL_ATTRIBUTES (fndecl));
- if (attr != NULL_TREE)
- {
- tree ctx = TREE_VALUE (TREE_VALUE (attr));
- if (!omp_get_context_selector (ctx, OMP_TRAIT_SET_CONSTRUCT,
- OMP_TRAIT_CONSTRUCT_DISPATCH))
- error_at (has_adjust_args ? adjust_args_loc : append_args_loc,
- "an %qs clause can only be specified if the "
- "%<dispatch%> selector of the %<construct%> selector "
- "set appears in the %<match%> clause",
- has_adjust_args ? "adjust_args" : "append_args");
- }
- }
+ tree attr = tree_cons (get_identifier ("omp declare variant base"),
+ build_tree_list (variant, ctx),
+ DECL_ATTRIBUTES (fndecl));
+ DECL_ATTRIBUTES (fndecl) = attr;
}
- if ((ctx != error_mark_node && variant != error_mark_node)
- && (need_device_ptr_list || append_args_tree))
+ if (need_device_ptr_list || append_args_tree)
{
tree variant_decl = tree_strip_nop_conversions (variant);
tree t = build_tree_list (need_device_ptr_list,