error ("nested function %q+D declared but never defined", p);
undef_nested_function = true;
}
- /* C99 6.7.4p6: "a function with external linkage... declared
- with an inline function specifier ... shall also be defined in the
- same translation unit." */
else if (DECL_DECLARED_INLINE_P (p)
&& TREE_PUBLIC (p)
- && !DECL_INITIAL (p)
- && !flag_gnu89_inline)
- pedwarn (input_location, 0, "inline function %q+D declared but never defined", p);
+ && !DECL_INITIAL (p))
+ {
+ /* C99 6.7.4p6: "a function with external linkage... declared
+ with an inline function specifier ... shall also be defined
+ in the same translation unit." */
+ if (!flag_gnu89_inline)
+ pedwarn (input_location, 0,
+ "inline function %q+D declared but never defined", p);
+ DECL_EXTERNAL (p) = 1;
+ }
goto common_symbol;
throw it away, in case it was inlined into a function that
hasn't been written out yet. */
if (new_is_definition && DECL_INITIAL (olddecl))
- {
- if (TREE_USED (olddecl)
- /* We never inline re-defined extern inline functions.
- FIXME: This would be better handled by keeping both functions
- as separate declarations. */
- && cgraph_function_possibly_inlined_p (olddecl))
- (*debug_hooks->outlining_inline_function) (olddecl);
-
- /* The new defn must not be inline. */
- DECL_UNINLINABLE (newdecl) = 1;
- }
+ /* The new defn must not be inline. */
+ DECL_UNINLINABLE (newdecl) = 1;
else
{
/* If either decl says `inline', this fn is inline, unless
tree cleanup;
/* Build "cleanup(&decl)" for the destructor. */
- cleanup = build_unary_op (ADDR_EXPR, decl, 0);
+ cleanup = build_unary_op (input_location, ADDR_EXPR, decl, 0);
cleanup = build_tree_list (NULL_TREE, cleanup);
cleanup = build_function_call (cleanup_decl, cleanup);
{
struct lang_type *lt = TYPE_LANG_SPECIFIC (*type);
if (!lt
- || w < min_precision (lt->enum_min, TYPE_UNSIGNED (*type))
- || w < min_precision (lt->enum_max, TYPE_UNSIGNED (*type)))
+ || w < tree_int_cst_min_precision (lt->enum_min, TYPE_UNSIGNED (*type))
+ || w < tree_int_cst_min_precision (lt->enum_max, TYPE_UNSIGNED (*type)))
warning (0, "%qs is narrower than values of its type", name);
}
}
}
else if (decl_context == FIELD)
{
- if (pedantic && !flag_isoc99 && !in_system_header)
+ bool flexible_array_member = false;
+ if (array_parm_vla_unspec_p)
+ /* Field names can in fact have function prototype
+ scope so [*] is disallowed here through making
+ the field variably modified, not through being
+ something other than a declaration with function
+ prototype scope. */
+ size_varies = 1;
+ else
+ {
+ const struct c_declarator *t = declarator;
+ while (t->kind == cdk_attrs)
+ t = t->declarator;
+ flexible_array_member = (t->kind == cdk_id);
+ }
+ if (flexible_array_member
+ && pedantic && !flag_isoc99 && !in_system_header)
pedwarn (input_location, OPT_pedantic,
"ISO C90 does not support flexible array members");
/* ISO C99 Flexible array members are effectively
identical to GCC's zero-length array extension. */
- itype = build_range_type (sizetype, size_zero_node, NULL_TREE);
+ if (flexible_array_member || array_parm_vla_unspec_p)
+ itype = build_range_type (sizetype, size_zero_node,
+ NULL_TREE);
}
else if (decl_context == PARM)
{
if (array_parm_vla_unspec_p)
{
- if (! orig_name)
- {
- /* C99 6.7.5.2p4 */
- error ("%<[*]%> not allowed in other than a declaration");
- }
-
itype = build_range_type (sizetype, size_zero_node, NULL_TREE);
size_varies = 1;
}
{
if (array_parm_vla_unspec_p)
{
- /* The error is printed elsewhere. We use this to
- avoid messing up with incomplete array types of
- the same type, that would otherwise be modified
- below. */
+ /* C99 6.7.5.2p4 */
+ warning (0, "%<[*]%> not in a declaration");
+ /* We use this to avoid messing up with incomplete
+ array types of the same type, that would
+ otherwise be modified below. */
itype = build_range_type (sizetype, size_zero_node,
NULL_TREE);
+ size_varies = 1;
}
}
{
/* Give the type a default layout like unsigned int
to avoid crashing if it does not get defined. */
- TYPE_MODE (ref) = TYPE_MODE (unsigned_type_node);
+ SET_TYPE_MODE (ref, TYPE_MODE (unsigned_type_node));
TYPE_ALIGN (ref) = TYPE_ALIGN (unsigned_type_node);
TYPE_USER_ALIGN (ref) = 0;
TYPE_UNSIGNED (ref) = 1;
error ("redefinition of %<union %E%>", name);
else
error ("redefinition of %<struct %E%>", name);
+ /* Don't create structures using a name already in use. */
+ ref = NULL_TREE;
}
else if (C_TYPE_BEING_DEFINED (ref))
{
DECL_CONTEXT (x) = t;
- if (TYPE_PACKED (t) && TYPE_ALIGN (TREE_TYPE (x)) > BITS_PER_UNIT)
- DECL_PACKED (x) = 1;
-
/* If any field is const, the structure type is pseudo-const. */
if (TREE_READONLY (x))
C_TYPE_FIELDS_READONLY (t) = 1;
SET_DECL_C_BIT_FIELD (x);
}
+ if (TYPE_PACKED (t)
+ && (DECL_BIT_FIELD (x)
+ || TYPE_ALIGN (TREE_TYPE (x)) > BITS_PER_UNIT))
+ DECL_PACKED (x) = 1;
+
/* Detect flexible array member in an invalid context. */
if (TREE_CODE (TREE_TYPE (x)) == ARRAY_TYPE
&& TYPE_SIZE (TREE_TYPE (x)) == NULL_TREE
that normally we only go as narrow as int - and signed iff any of
the values are negative. */
unsign = (tree_int_cst_sgn (minnode) >= 0);
- precision = MAX (min_precision (minnode, unsign),
- min_precision (maxnode, unsign));
+ precision = MAX (tree_int_cst_min_precision (minnode, unsign),
+ tree_int_cst_min_precision (maxnode, unsign));
if (TYPE_PACKED (enumtype) || precision > TYPE_PRECISION (integer_type_node))
{
/* The ISO C Standard mandates enumerators to have type int,
even though the underlying type of an enum type is
unspecified. However, GCC allows enumerators of any
- integer type as an extensions. Here we convert any
- enumerators that fit in an int to type int, to avoid
- promotions to unsigned types when comparing integers with
- enumerators that fit in the int range. When -pedantic is
- given, build_enumerator() would have already warned about
- those that don't fit. */
- if (int_fits_type_p (ini, integer_type_node))
- tem = integer_type_node;
- else
- tem = enumtype;
- ini = convert (tem, ini);
+ integer type as an extensions. build_enumerator()
+ converts any enumerators that fit in an int to type int,
+ to avoid promotions to unsigned types when comparing
+ integers with enumerators that fit in the int range.
+ When -pedantic is given, build_enumerator() would have
+ already warned about those that don't fit. Here we
+ convert the rest to the enumerator type. */
+ if (TREE_TYPE (ini) != integer_type_node)
+ ini = convert (enumtype, ini);
DECL_INITIAL (enu) = ini;
TREE_PURPOSE (pair) = DECL_NAME (enu);
TYPE_MAX_VALUE (tem) = TYPE_MAX_VALUE (enumtype);
TYPE_SIZE (tem) = TYPE_SIZE (enumtype);
TYPE_SIZE_UNIT (tem) = TYPE_SIZE_UNIT (enumtype);
- TYPE_MODE (tem) = TYPE_MODE (enumtype);
+ SET_TYPE_MODE (tem, TYPE_MODE (enumtype));
TYPE_PRECISION (tem) = TYPE_PRECISION (enumtype);
TYPE_ALIGN (tem) = TYPE_ALIGN (enumtype);
TYPE_USER_ALIGN (tem) = TYPE_USER_ALIGN (enumtype);
pedwarn (value_loc, OPT_pedantic,
"ISO C restricts enumerator values to range of %<int%>");
+ /* The ISO C Standard mandates enumerators to have type int, even
+ though the underlying type of an enum type is unspecified.
+ However, GCC allows enumerators of any integer type as an
+ extensions. Here we convert any enumerators that fit in an int
+ to type int, to avoid promotions to unsigned types when comparing
+ integers with enumerators that fit in the int range. When
+ -pedantic is given, we would have already warned about those that
+ don't fit. We have to do this here rather than in finish_enum
+ because this value may be used to define more enumerators. */
+ if (int_fits_type_p (value, integer_type_node))
+ value = convert (integer_type_node, value);
+
/* Set basis for default for next value. */
the_enum->enum_next_value
= build_binary_op
if (specs->saturating_p)
{
error ("%<_Sat%> is used without %<_Fract%> or %<_Accum%>");
+ if (!targetm.fixed_point_supported_p ())
+ error ("fixed-point types not supported for this target");
specs->typespec_word = cts_fract;
}
else if (specs->long_p || specs->short_p
specs->type = dfloat128_type_node;
break;
case cts_fract:
- gcc_assert (!specs->complex_p);
- if (specs->saturating_p)
+ gcc_assert (!specs->complex_p);
+ if (!targetm.fixed_point_supported_p ())
+ specs->type = integer_type_node;
+ else if (specs->saturating_p)
{
if (specs->long_long_p)
specs->type = specs->unsigned_p
specs->type = specs->unsigned_p
? sat_unsigned_fract_type_node
: sat_fract_type_node;
- }
+ }
else
{
if (specs->long_long_p)
specs->type = specs->unsigned_p
? unsigned_fract_type_node
: fract_type_node;
- }
+ }
break;
case cts_accum:
- gcc_assert (!specs->complex_p);
- if (specs->saturating_p)
+ gcc_assert (!specs->complex_p);
+ if (!targetm.fixed_point_supported_p ())
+ specs->type = integer_type_node;
+ else if (specs->saturating_p)
{
if (specs->long_long_p)
specs->type = specs->unsigned_p
specs->type = specs->unsigned_p
? sat_unsigned_accum_type_node
: sat_accum_type_node;
- }
+ }
else
{
if (specs->long_long_p)
specs->type = specs->unsigned_p
? unsigned_accum_type_node
: accum_type_node;
- }
+ }
break;
default:
gcc_unreachable ();