#include "c-family/c-ada-spec.h"
#include "cilk.h"
#include "builtins.h"
+#include "spellcheck-tree.h"
+#include "gcc-rich-location.h"
/* In grokdeclarator, distinguish syntactic contexts of declarators. */
enum decl_context
{
/* If warn_cxx_compat, a list of types defined within this
struct. */
- vec<tree> struct_types;
+ auto_vec<tree> struct_types;
/* If warn_cxx_compat, a list of field names which have bindings,
and which are defined in this struct, but which are not defined
in any enclosing struct. This is used to clear the in_struct
field of the c_bindings structure. */
- vec<c_binding_ptr> fields;
+ auto_vec<c_binding_ptr> fields;
/* If warn_cxx_compat, a list of typedef names used when defining
fields in this struct. */
- vec<tree> typedefs_seen;
+ auto_vec<tree> typedefs_seen;
};
/* Information for the struct or union currently being parsed, or
set_type_context (TREE_TYPE (p), context);
}
- /* Fall through. */
+ gcc_fallthrough ();
/* Parameters go in DECL_ARGUMENTS, not BLOCK_VARS, and have
already been put there by store_parm_decls. Unused-
parameter warnings are handled by function.c.
}
if (TREE_CODE (newdecl) == FUNCTION_DECL)
- {
- /* Diagnose inline __attribute__ ((noinline)) which is silly. */
- if (DECL_DECLARED_INLINE_P (newdecl)
- && lookup_attribute ("noinline", DECL_ATTRIBUTES (olddecl)))
- warned |= warning (OPT_Wattributes,
- "inline declaration of %qD follows "
- "declaration with attribute noinline", newdecl);
- else if (DECL_DECLARED_INLINE_P (olddecl)
- && lookup_attribute ("noinline", DECL_ATTRIBUTES (newdecl)))
- warned |= warning (OPT_Wattributes,
- "declaration of %q+D with attribute "
- "noinline follows inline declaration ", newdecl);
- else if (lookup_attribute ("noinline", DECL_ATTRIBUTES (newdecl))
- && lookup_attribute ("always_inline", DECL_ATTRIBUTES (olddecl)))
- warned |= warning (OPT_Wattributes,
- "declaration of %q+D with attribute "
- "%qs follows declaration with attribute %qs",
- newdecl, "noinline", "always_inline");
- else if (lookup_attribute ("always_inline", DECL_ATTRIBUTES (newdecl))
- && lookup_attribute ("noinline", DECL_ATTRIBUTES (olddecl)))
- warned |= warning (OPT_Wattributes,
- "declaration of %q+D with attribute "
- "%qs follows declaration with attribute %qs",
- newdecl, "always_inline", "noinline");
- else if (lookup_attribute ("cold", DECL_ATTRIBUTES (newdecl))
- && lookup_attribute ("hot", DECL_ATTRIBUTES (olddecl)))
- warned |= warning (OPT_Wattributes,
- "declaration of %q+D with attribute %qs follows "
- "declaration with attribute %qs", newdecl, "cold",
- "hot");
- else if (lookup_attribute ("hot", DECL_ATTRIBUTES (newdecl))
- && lookup_attribute ("cold", DECL_ATTRIBUTES (olddecl)))
- warned |= warning (OPT_Wattributes,
- "declaration of %q+D with attribute %qs follows "
- "declaration with attribute %qs", newdecl, "hot",
- "cold");
- }
+ warned |= diagnose_mismatched_attributes (olddecl, newdecl);
else /* PARM_DECL, VAR_DECL */
{
/* Redeclaration of a parameter is a constraint violation (this is
if (warn_implicit_function_declaration)
{
bool warned;
+ const char *hint = NULL;
+ if (!olddecl)
+ hint = lookup_name_fuzzy (id, FUZZY_LOOKUP_FUNCTION_NAME);
if (flag_isoc99)
- warned = pedwarn (loc, OPT_Wimplicit_function_declaration,
- "implicit declaration of function %qE", id);
+ if (hint)
+ {
+ gcc_rich_location richloc (loc);
+ richloc.add_fixit_replace (hint);
+ warned = pedwarn_at_rich_loc
+ (&richloc, OPT_Wimplicit_function_declaration,
+ "implicit declaration of function %qE; did you mean %qs?",
+ id, hint);
+ }
+ else
+ warned = pedwarn (loc, OPT_Wimplicit_function_declaration,
+ "implicit declaration of function %qE", id);
else
- warned = warning_at (loc, OPT_Wimplicit_function_declaration,
- G_("implicit declaration of function %qE"), id);
+ if (hint)
+ {
+ gcc_rich_location richloc (loc);
+ richloc.add_fixit_replace (hint);
+ warned = warning_at_rich_loc
+ (&richloc, OPT_Wimplicit_function_declaration,
+ G_("implicit declaration of function %qE;did you mean %qs?"),
+ id, hint);
+ }
+ else
+ warned = warning_at (loc, OPT_Wimplicit_function_declaration,
+ G_("implicit declaration of function %qE"), id);
if (olddecl && warned)
locate_old_decl (olddecl);
}
if (decl)
{
- if (decl == error_mark_node)
+ if (TREE_CODE (decl) != FUNCTION_DECL)
return decl;
/* FIXME: Objective-C has weird not-really-builtin functions
if (current_function_decl == 0)
{
- error_at (loc, "%qE undeclared here (not in a function)", id);
+ const char *guessed_id = lookup_name_fuzzy (id, FUZZY_LOOKUP_NAME);
+ if (guessed_id)
+ {
+ gcc_rich_location richloc (loc);
+ richloc.add_fixit_replace (guessed_id);
+ error_at_rich_loc (&richloc,
+ "%qE undeclared here (not in a function);"
+ " did you mean %qs?",
+ id, guessed_id);
+ }
+ else
+ error_at (loc, "%qE undeclared here (not in a function)", id);
scope = current_scope;
}
else
{
if (!objc_diagnose_private_ivar (id))
- error_at (loc, "%qE undeclared (first use in this function)", id);
+ {
+ const char *guessed_id = lookup_name_fuzzy (id, FUZZY_LOOKUP_NAME);
+ if (guessed_id)
+ {
+ gcc_rich_location richloc (loc);
+ richloc.add_fixit_replace (guessed_id);
+ error_at_rich_loc
+ (&richloc,
+ "%qE undeclared (first use in this function);"
+ " did you mean %qs?",
+ id, guessed_id);
+ }
+ else
+ error_at (loc, "%qE undeclared (first use in this function)", id);
+ }
if (!already)
{
inform (loc, "each undeclared identifier is reported only"
return b->decl;
return NULL_TREE;
}
+
+/* Look for the closest match for NAME within the currently valid
+ scopes.
+
+ This finds the identifier with the lowest Levenshtein distance to
+ NAME. If there are multiple candidates with equal minimal distance,
+ the first one found is returned. Scopes are searched from innermost
+ outwards, and within a scope in reverse order of declaration, thus
+ benefiting candidates "near" to the current scope.
+
+ The function also looks for similar macro names to NAME, since a
+ misspelled macro name will not be expanded, and hence looks like an
+ identifier to the C frontend.
+
+ It also looks for start_typename keywords, to detect "singed" vs "signed"
+ typos. */
+
+const char *
+lookup_name_fuzzy (tree name, enum lookup_name_fuzzy_kind kind)
+{
+ gcc_assert (TREE_CODE (name) == IDENTIFIER_NODE);
+
+ best_match<tree, tree> bm (name);
+
+ /* Look within currently valid scopes. */
+ for (c_scope *scope = current_scope; scope; scope = scope->outer)
+ for (c_binding *binding = scope->bindings; binding; binding = binding->prev)
+ {
+ if (!binding->id || binding->invisible)
+ continue;
+ /* Don't use bindings from implicitly declared functions,
+ as they were likely misspellings themselves. */
+ if (TREE_CODE (binding->decl) == FUNCTION_DECL)
+ if (C_DECL_IMPLICIT (binding->decl))
+ continue;
+ switch (kind)
+ {
+ case FUZZY_LOOKUP_TYPENAME:
+ if (TREE_CODE (binding->decl) != TYPE_DECL)
+ continue;
+ break;
+
+ case FUZZY_LOOKUP_FUNCTION_NAME:
+ if (TREE_CODE (binding->decl) != FUNCTION_DECL)
+ {
+ /* Allow function pointers. */
+ if ((VAR_P (binding->decl)
+ || TREE_CODE (binding->decl) == PARM_DECL)
+ && TREE_CODE (TREE_TYPE (binding->decl)) == POINTER_TYPE
+ && (TREE_CODE (TREE_TYPE (TREE_TYPE (binding->decl)))
+ == FUNCTION_TYPE))
+ break;
+ continue;
+ }
+ break;
+
+ default:
+ break;
+ }
+ bm.consider (binding->id);
+ }
+
+ /* Consider macros: if the user misspelled a macro name e.g. "SOME_MACRO"
+ as:
+ x = SOME_OTHER_MACRO (y);
+ then "SOME_OTHER_MACRO" will survive to the frontend and show up
+ as a misspelled identifier.
+
+ Use the best distance so far so that a candidate is only set if
+ a macro is better than anything so far. This allows early rejection
+ (without calculating the edit distance) of macro names that must have
+ distance >= bm.get_best_distance (), and means that we only get a
+ non-NULL result for best_macro_match if it's better than any of
+ the identifiers already checked, which avoids needless creation
+ of identifiers for macro hashnodes. */
+ best_macro_match bmm (name, bm.get_best_distance (), parse_in);
+ cpp_hashnode *best_macro = bmm.get_best_meaningful_candidate ();
+ /* If a macro is the closest so far to NAME, use it, creating an
+ identifier tree node for it. */
+ if (best_macro)
+ {
+ const char *id = (const char *)best_macro->ident.str;
+ tree macro_as_identifier
+ = get_identifier_with_length (id, best_macro->ident.len);
+ bm.set_best_so_far (macro_as_identifier,
+ bmm.get_best_distance (),
+ bmm.get_best_candidate_length ());
+ }
+
+ /* Try the "start_typename" keywords to detect
+ "singed" vs "signed" typos. */
+ if (kind == FUZZY_LOOKUP_TYPENAME)
+ {
+ for (unsigned i = 0; i < num_c_common_reswords; i++)
+ {
+ const c_common_resword *resword = &c_common_reswords[i];
+ if (!c_keyword_starts_typename (resword->rid))
+ continue;
+ tree resword_identifier = ridpointers [resword->rid];
+ if (!resword_identifier)
+ continue;
+ gcc_assert (TREE_CODE (resword_identifier) == IDENTIFIER_NODE);
+ bm.consider (resword_identifier);
+ }
+ }
+
+ tree best = bm.get_best_meaningful_candidate ();
+ if (best)
+ return IDENTIFIER_POINTER (best);
+ else
+ return NULL;
+}
+
\f
/* Create the predefined scalar types of C,
and some nodes representing standard constants (0, 1, (void *) 0).
the __FUNCTION__ is believed to appear in K&R style function
parameter declarator. In that case we still don't have
function_scope. */
- && (!seen_error () || current_function_scope))
+ && current_function_scope)
{
DECL_CONTEXT (decl) = current_function_decl;
bind (id, decl, current_function_scope,
vec<tree, va_gc> *v;
/* Build "cleanup(&decl)" for the destructor. */
- cleanup = build_unary_op (input_location, ADDR_EXPR, decl, 0);
+ cleanup = build_unary_op (input_location, ADDR_EXPR, decl, false);
vec_alloc (v, 1);
v->quick_push (cleanup);
cleanup = c_build_function_call_vec (DECL_SOURCE_LOCATION (decl),
if (type == error_mark_node || !COMPLETE_TYPE_P (type))
{
- c_incomplete_type_error (NULL_TREE, type);
+ c_incomplete_type_error (loc, NULL_TREE, type);
return error_mark_node;
}
struct c_arg_info *arg_info = 0;
addr_space_t as1, as2, address_space;
location_t loc = UNKNOWN_LOCATION;
- const char *errmsg;
tree expr_dummy;
bool expr_const_operands_dummy;
enum c_declarator_kind first_non_attr_kind;
"an array");
type = integer_type_node;
}
- errmsg = targetm.invalid_return_type (type);
- if (errmsg)
- {
- error (errmsg);
- type = integer_type_node;
- }
/* Construct the function type and go to the next
inner layer of declarator. */
qualify the return type, not the function type. */
if (type_quals)
{
+ int quals_used = type_quals;
/* Type qualifiers on a function return type are
normally permitted by the standard but have no
effect, so give a warning at -Wreturn-type.
Qualifiers on a void return type are banned on
function definitions in ISO C; GCC used to used
- them for noreturn functions. */
- if (VOID_TYPE_P (type) && really_funcdef)
+ them for noreturn functions. The resolution of C11
+ DR#423 means qualifiers (other than _Atomic) are
+ actually removed from the return type when
+ determining the function type. */
+ if (flag_isoc11)
+ quals_used &= TYPE_QUAL_ATOMIC;
+ if (quals_used && VOID_TYPE_P (type) && really_funcdef)
pedwarn (loc, 0,
"function definition has qualified void return type");
else
warning_at (loc, OPT_Wignored_qualifiers,
"type qualifiers ignored on function return type");
- type = c_build_qualified_type (type, type_quals);
+ /* Ensure an error for restrict on invalid types; the
+ DR#423 resolution is not entirely clear about
+ this. */
+ if (flag_isoc11
+ && (type_quals & TYPE_QUAL_RESTRICT)
+ && (!POINTER_TYPE_P (type)
+ || !C_TYPE_OBJECT_OR_INCOMPLETE_P (TREE_TYPE (type))))
+ error_at (loc, "invalid use of %<restrict%>");
+ if (quals_used)
+ type = c_build_qualified_type (type, quals_used);
}
type_quals = TYPE_UNQUALIFIED;
}
else if (TREE_CODE (type) == FUNCTION_TYPE)
error_at (loc, "alignment specified for function %qE", name);
- else if (declspecs->align_log != -1)
+ else if (declspecs->align_log != -1 && TYPE_P (type))
{
alignas_align = 1U << declspecs->align_log;
if (alignas_align < min_align_of_type (type))
type = build_distinct_type_copy (TYPE_MAIN_VARIANT (type));
TYPE_DOMAIN (type) = build_range_type (sizetype, size_zero_node,
NULL_TREE);
+ if (orig_qual_indirect == 0)
+ orig_qual_type = NULL_TREE;
}
type = c_build_qualified_type (type, type_quals, orig_qual_type,
orig_qual_indirect);
{
tree parm, type, typelt;
unsigned int parmno;
- const char *errmsg;
/* If there is a parameter of incomplete type in a definition,
this is an error. In a declaration this is valid, and a
}
}
- errmsg = targetm.invalid_parameter_type (type);
- if (errmsg)
- {
- error (errmsg);
- TREE_VALUE (typelt) = error_mark_node;
- TREE_TYPE (parm) = error_mark_node;
- arg_types = NULL_TREE;
- }
-
if (DECL_NAME (parm) && TREE_USED (parm))
warn_if_shadowing (parm);
}
break;
case FUNCTION_DECL:
- /* FUNCTION_DECLs appear when there is an implicit function
- declaration in the parameter list. */
- gcc_assert (b->nested);
+ /* FUNCTION_DECLs appear when there is an implicit function
+ declaration in the parameter list. */
+ gcc_assert (b->nested || seen_error ());
goto set_shadowed;
case CONST_DECL:
TYPE_PACKED (v) = flag_pack_struct;
*enclosing_struct_parse_info = struct_parse_info;
- struct_parse_info = XNEW (struct c_struct_parse_info);
- struct_parse_info->struct_types.create (0);
- struct_parse_info->fields.create (0);
- struct_parse_info->typedefs_seen.create (0);
+ struct_parse_info = new c_struct_parse_info ();
/* FIXME: This will issue a warning for a use of a type defined
within a statement expr used within sizeof, et. al. This is not
else if (!saw_named_field)
{
error_at (DECL_SOURCE_LOCATION (x),
- "flexible array member in otherwise empty struct");
+ "flexible array member in a struct with no named "
+ "members");
TREE_TYPE (x) = error_mark_node;
}
}
if (warn_cxx_compat)
warn_cxx_compat_finish_struct (fieldlist, TREE_CODE (t), loc);
- struct_parse_info->struct_types.release ();
- struct_parse_info->fields.release ();
- struct_parse_info->typedefs_seen.release ();
- XDELETE (struct_parse_info);
+ delete struct_parse_info;
struct_parse_info = enclosing_struct_parse_info;
continue;
/* If we got something other than a PARM_DECL it is an error. */
if (TREE_CODE (decl) != PARM_DECL)
- error_at (DECL_SOURCE_LOCATION (decl),
- "%qD declared as a non-parameter", decl);
+ {
+ error_at (DECL_SOURCE_LOCATION (decl),
+ "%qD declared as a non-parameter", decl);
+ continue;
+ }
/* If the declaration is already marked, we have a duplicate
name. Complain and ignore the duplicate. */
else if (seen_args.contains (decl))
/* For GNU C extern inline functions disregard inline limits. */
if (DECL_EXTERNAL (fndecl)
- && DECL_DECLARED_INLINE_P (fndecl))
+ && DECL_DECLARED_INLINE_P (fndecl)
+ && (flag_gnu89_inline
+ || lookup_attribute ("gnu_inline", DECL_ATTRIBUTES (fndecl))))
DECL_DISREGARD_INLINE_LIMITS (fndecl) = 1;
/* Genericize before inlining. Delay genericizing nested functions
gcc_assert (TREE_CODE (qual) == IDENTIFIER_NODE
&& C_IS_RESERVED_WORD (qual));
i = C_RID_CODE (qual);
+ location_t prev_loc = 0;
switch (i)
{
case RID_CONST:
dupe = specs->const_p;
specs->const_p = true;
+ prev_loc = specs->locations[cdw_const];
specs->locations[cdw_const] = loc;
break;
case RID_VOLATILE:
dupe = specs->volatile_p;
specs->volatile_p = true;
+ prev_loc = specs->locations[cdw_volatile];
specs->locations[cdw_volatile] = loc;
break;
case RID_RESTRICT:
dupe = specs->restrict_p;
specs->restrict_p = true;
+ prev_loc = specs->locations[cdw_restrict];
specs->locations[cdw_restrict] = loc;
break;
case RID_ATOMIC:
dupe = specs->atomic_p;
specs->atomic_p = true;
+ prev_loc = specs->locations[cdw_atomic];
+ specs->locations[cdw_atomic] = loc;
break;
default:
gcc_unreachable ();
}
if (dupe)
- pedwarn_c90 (loc, OPT_Wpedantic, "duplicate %qE", qual);
+ {
+ bool warned = pedwarn_c90 (loc, OPT_Wpedantic,
+ "duplicate %qE declaration specifier", qual);
+ if (!warned
+ && warn_duplicate_decl_specifier
+ && prev_loc >= RESERVED_LOCATION_COUNT
+ && !from_macro_expansion_at (prev_loc)
+ && !from_macro_expansion_at (loc))
+ warning_at (loc, OPT_Wduplicate_decl_specifier,
+ "duplicate %qE declaration specifier", qual);
+ }
return specs;
}
error_at (loc,
("both %<long%> and %<float%> in "
"declaration specifiers"));
+ else if (specs->typespec_word == cts_floatn_nx)
+ error_at (loc,
+ ("both %<long%> and %<_Float%d%s%> in "
+ "declaration specifiers"),
+ floatn_nx_types[specs->floatn_nx_idx].n,
+ (floatn_nx_types[specs->floatn_nx_idx].extended
+ ? "x"
+ : ""));
else if (specs->typespec_word == cts_dfloat32)
error_at (loc,
("both %<long%> and %<_Decimal32%> in "
error_at (loc,
("both %<short%> and %<double%> in "
"declaration specifiers"));
+ else if (specs->typespec_word == cts_floatn_nx)
+ error_at (loc,
+ ("both %<short%> and %<_Float%d%s%> in "
+ "declaration specifiers"),
+ floatn_nx_types[specs->floatn_nx_idx].n,
+ (floatn_nx_types[specs->floatn_nx_idx].extended
+ ? "x"
+ : ""));
else if (specs->typespec_word == cts_dfloat32)
error_at (loc,
("both %<short%> and %<_Decimal32%> in "
error_at (loc,
("both %<signed%> and %<double%> in "
"declaration specifiers"));
+ else if (specs->typespec_word == cts_floatn_nx)
+ error_at (loc,
+ ("both %<signed%> and %<_Float%d%s%> in "
+ "declaration specifiers"),
+ floatn_nx_types[specs->floatn_nx_idx].n,
+ (floatn_nx_types[specs->floatn_nx_idx].extended
+ ? "x"
+ : ""));
else if (specs->typespec_word == cts_dfloat32)
error_at (loc,
("both %<signed%> and %<_Decimal32%> in "
error_at (loc,
("both %<unsigned%> and %<double%> in "
"declaration specifiers"));
+ else if (specs->typespec_word == cts_floatn_nx)
+ error_at (loc,
+ ("both %<unsigned%> and %<_Float%d%s%> in "
+ "declaration specifiers"),
+ floatn_nx_types[specs->floatn_nx_idx].n,
+ (floatn_nx_types[specs->floatn_nx_idx].extended
+ ? "x"
+ : ""));
else if (specs->typespec_word == cts_dfloat32)
error_at (loc,
("both %<unsigned%> and %<_Decimal32%> in "
error_at (loc,
("both %<_Sat%> and %<double%> in "
"declaration specifiers"));
+ else if (specs->typespec_word == cts_floatn_nx)
+ error_at (loc,
+ ("both %<_Sat%> and %<_Float%d%s%> in "
+ "declaration specifiers"),
+ floatn_nx_types[specs->floatn_nx_idx].n,
+ (floatn_nx_types[specs->floatn_nx_idx].extended
+ ? "x"
+ : ""));
else if (specs->typespec_word == cts_dfloat32)
error_at (loc,
("both %<_Sat%> and %<_Decimal32%> in "
}
else
{
- /* "void", "_Bool", "char", "int", "float", "double", "_Decimal32",
- "__intN", "_Decimal64", "_Decimal128", "_Fract", "_Accum" or
+ /* "void", "_Bool", "char", "int", "float", "double",
+ "_FloatN", "_FloatNx", "_Decimal32", "__intN",
+ "_Decimal64", "_Decimal128", "_Fract", "_Accum" or
"__auto_type". */
if (specs->typespec_word != cts_none)
{
("both %<__int%d%> and %<short%> in "
"declaration specifiers"),
int_n_data[specs->int_n_idx].bitsize);
- else if (! int_n_enabled_p [specs->int_n_idx])
- error_at (loc,
- "%<__int%d%> is not supported on this target",
- int_n_data[specs->int_n_idx].bitsize);
+ else if (! int_n_enabled_p[specs->int_n_idx])
+ {
+ specs->typespec_word = cts_int_n;
+ error_at (loc,
+ "%<__int%d%> is not supported on this target",
+ int_n_data[specs->int_n_idx].bitsize);
+ }
else
{
specs->typespec_word = cts_int_n;
specs->locations[cdw_typespec] = loc;
}
return specs;
+ CASE_RID_FLOATN_NX:
+ specs->floatn_nx_idx = i - RID_FLOATN_NX_FIRST;
+ if (!in_system_header_at (input_location))
+ pedwarn (loc, OPT_Wpedantic,
+ "ISO C does not support the %<_Float%d%s%> type",
+ floatn_nx_types[specs->floatn_nx_idx].n,
+ (floatn_nx_types[specs->floatn_nx_idx].extended
+ ? "x"
+ : ""));
+
+ if (specs->long_p)
+ error_at (loc,
+ ("both %<long%> and %<_Float%d%s%> in "
+ "declaration specifiers"),
+ floatn_nx_types[specs->floatn_nx_idx].n,
+ (floatn_nx_types[specs->floatn_nx_idx].extended
+ ? "x"
+ : ""));
+ else if (specs->short_p)
+ error_at (loc,
+ ("both %<short%> and %<_Float%d%s%> in "
+ "declaration specifiers"),
+ floatn_nx_types[specs->floatn_nx_idx].n,
+ (floatn_nx_types[specs->floatn_nx_idx].extended
+ ? "x"
+ : ""));
+ else if (specs->signed_p)
+ error_at (loc,
+ ("both %<signed%> and %<_Float%d%s%> in "
+ "declaration specifiers"),
+ floatn_nx_types[specs->floatn_nx_idx].n,
+ (floatn_nx_types[specs->floatn_nx_idx].extended
+ ? "x"
+ : ""));
+ else if (specs->unsigned_p)
+ error_at (loc,
+ ("both %<unsigned%> and %<_Float%d%s%> in "
+ "declaration specifiers"),
+ floatn_nx_types[specs->floatn_nx_idx].n,
+ (floatn_nx_types[specs->floatn_nx_idx].extended
+ ? "x"
+ : ""));
+ else if (specs->saturating_p)
+ error_at (loc,
+ ("both %<_Sat%> and %<_Float%d%s%> in "
+ "declaration specifiers"),
+ floatn_nx_types[specs->floatn_nx_idx].n,
+ (floatn_nx_types[specs->floatn_nx_idx].extended
+ ? "x"
+ : ""));
+ else if (FLOATN_NX_TYPE_NODE (specs->floatn_nx_idx) == NULL_TREE)
+ {
+ specs->typespec_word = cts_floatn_nx;
+ error_at (loc,
+ "%<_Float%d%s%> is not supported on this target",
+ floatn_nx_types[specs->floatn_nx_idx].n,
+ (floatn_nx_types[specs->floatn_nx_idx].extended
+ ? "x"
+ : ""));
+ }
+ else
+ {
+ specs->typespec_word = cts_floatn_nx;
+ specs->locations[cdw_typespec] = loc;
+ }
+ return specs;
case RID_DFLOAT32:
case RID_DFLOAT64:
case RID_DFLOAT128:
: double_type_node);
}
break;
+ case cts_floatn_nx:
+ gcc_assert (!specs->long_p && !specs->short_p
+ && !specs->signed_p && !specs->unsigned_p);
+ if (FLOATN_NX_TYPE_NODE (specs->floatn_nx_idx) == NULL_TREE)
+ specs->type = integer_type_node;
+ else if (specs->complex_p)
+ specs->type = COMPLEX_FLOATN_NX_TYPE_NODE (specs->floatn_nx_idx);
+ else
+ specs->type = FLOATN_NX_TYPE_NODE (specs->floatn_nx_idx);
+ break;
case cts_dfloat32:
case cts_dfloat64:
case cts_dfloat128: