/* Process declarations and variables for C compiler.
- Copyright (C) 1988, 1992, 1993 Free Software Foundation, Inc.
+ Copyright (C) 1988, 1992, 1993, 1994 Free Software Foundation, Inc.
This file is part of GNU CC.
int pending_invalid_xref_line;
/* While defining an enum type, this is 1 plus the last enumerator
- constant value. */
+ constant value. Note that will do not have to save this or `enum_overflow'
+ around nested function definition since such a definition could only
+ occur in an enum value expression and we don't use these variables in
+ that case. */
static tree enum_next_value;
int flag_traditional;
+/* Nonzero means to allow single precision math even if we're generally
+ being traditional. */
+int flag_allow_single_precision = 0;
+
/* Nonzero means to treat bitfields as signed unless they say `unsigned'. */
int flag_signed_bitfields = 1;
int warn_missing_prototypes;
+/* Nonzero means warn for any global function def
+ without separate previous decl. */
+
+int warn_missing_declarations;
+
/* Nonzero means warn about multiple (redundant) decls for the same single
variable or function. */
dollars_in_ident = 1;
#endif
}
+ else if (!strcmp (p, "-fallow-single-precision"))
+ flag_allow_single_precision = 1;
else if (!strcmp (p, "-fnotraditional") || !strcmp (p, "-fno-traditional"))
{
flag_traditional = 0;
warn_missing_prototypes = 1;
else if (!strcmp (p, "-Wno-missing-prototypes"))
warn_missing_prototypes = 0;
+ else if (!strcmp (p, "-Wmissing-declarations"))
+ warn_missing_declarations = 1;
+ else if (!strcmp (p, "-Wno-missing-declarations"))
+ warn_missing_declarations = 0;
else if (!strcmp (p, "-Wredundant-decls"))
warn_redundant_decls = 1;
else if (!strcmp (p, "-Wno-redundant-decls"))
if (TREE_CODE (olddecl) != TREE_CODE (newdecl))
{
if (TREE_CODE (olddecl) == FUNCTION_DECL
- && DECL_BUILT_IN (olddecl))
+ && (DECL_BUILT_IN (olddecl)
+ || DECL_BUILT_IN_NONANSI (olddecl)))
{
- /* If you declare a built-in function name as static, the
- built-in definition is overridden,
+ /* If you declare a built-in or predefined function name as static,
+ the old definition is overridden,
but optionally warn this was a bad choice of name. */
if (!TREE_PUBLIC (newdecl))
{
- if (warn_shadow)
+ if (!warn_shadow)
+ ;
+ else if (DECL_BUILT_IN (olddecl))
warning_with_decl (newdecl, "shadowing built-in function `%s'");
+ else
+ warning_with_decl (newdecl, "shadowing library function `%s'");
}
/* Likewise, if the built-in is not ansi, then programs can
override it even globally without an error. */
+ else if (! DECL_BUILT_IN (olddecl))
+ warning_with_decl (newdecl,
+ "library function `%s' declared as non-function");
+
else if (DECL_BUILT_IN_NONANSI (olddecl))
warning_with_decl (newdecl,
"built-in function `%s' declared as non-function");
else
- error_with_decl (newdecl,
- "built-in function `%s' declared as non-function");
- }
- else if (TREE_CODE (olddecl) == FUNCTION_DECL
- && DECL_BUILT_IN_NONANSI (olddecl))
- {
- /* If overriding decl is static,
- optionally warn this was a bad choice of name. */
- if (!TREE_PUBLIC (newdecl))
- {
- if (warn_shadow)
- warning_with_decl (newdecl, "shadowing library function `%s'");
- }
- /* Otherwise, always warn. */
- else
warning_with_decl (newdecl,
- "library function `%s' declared as non-function");
+ "built-in function `%s' declared as non-function");
}
else
{
&& DECL_INITIAL (olddecl) != 0)
warning_with_decl (newdecl,
"`%s' declared inline after its definition");
- /* It is nice to warn when a function is declared
- global first and then static. */
- if (TREE_CODE (olddecl) == FUNCTION_DECL
+
+ /* If pedantic, warn when static declaration follows a non-static
+ declaration. Otherwise, do so only for functions. */
+ if ((pedantic || TREE_CODE (olddecl) == FUNCTION_DECL)
&& TREE_PUBLIC (olddecl)
&& !TREE_PUBLIC (newdecl))
warning_with_decl (newdecl, "static declaration for `%s' follows non-static");
if (types_match)
{
+ /* Make sure we put the new type in the same obstack as the old ones.
+ If the old types are not both in the same obstack, use the permanent
+ one. */
+ if (TYPE_OBSTACK (oldtype) == TYPE_OBSTACK (newtype))
+ push_obstacks (TYPE_OBSTACK (oldtype), TYPE_OBSTACK (oldtype));
+ else
+ {
+ push_obstacks_nochange ();
+ end_temporary_allocation ();
+ }
+
/* Merge the data types specified in the two decls. */
if (TREE_CODE (newdecl) != FUNCTION_DECL || !DECL_BUILT_IN (olddecl))
TREE_TYPE (newdecl)
/* Merge the initialization information. */
if (DECL_INITIAL (newdecl) == 0)
DECL_INITIAL (newdecl) = DECL_INITIAL (olddecl);
+
+ /* Merge the section attribute.
+ We want to issue an error if the sections conflict but that must be
+ done later in decl_attributes since we are called before attributes
+ are assigned. */
+ if (DECL_SECTION_NAME (newdecl) == NULL_TREE)
+ DECL_SECTION_NAME (newdecl) = DECL_SECTION_NAME (olddecl);
+
+ pop_obstacks ();
}
/* If cannot merge, then use the new type and qualifiers,
and don't preserve the old rtl. */
if (DECL_BUILT_IN (olddecl))
{
DECL_BUILT_IN (newdecl) = 1;
- DECL_SET_FUNCTION_CODE (newdecl, DECL_FUNCTION_CODE (olddecl));
+ DECL_FUNCTION_CODE (newdecl) = DECL_FUNCTION_CODE (olddecl);
}
else
DECL_FRAME_SIZE (newdecl) = DECL_FRAME_SIZE (olddecl);
DECL_CONTEXT (x) = 0;
if (warn_nested_externs && DECL_EXTERNAL (x) && b != global_binding_level
- && x != IDENTIFIER_IMPLICIT_DECL (name))
+ && x != IDENTIFIER_IMPLICIT_DECL (name)
+ /* Don't print error messages for __FUNCTION__ and __PRETTY_FUNCTION__ */
+ && !DECL_IN_SYSTEM_HEADER (x))
warning ("nested extern declaration of `%s'", IDENTIFIER_POINTER (name));
if (name)
char *file;
int line;
- t = lookup_name_current_level (name);
+ if (DECL_EXTERNAL (x) && TREE_PUBLIC (x))
+ t = lookup_name (name);
+ else
+ t = lookup_name_current_level (name);
if (t != 0 && t == error_mark_node)
/* error_mark_node is 0 for a while during initialization! */
{
}
/* Multiple external decls of the same identifier ought to match.
- Check against both global declarations and out of scope (limbo) block
- level declarations.
+ Check against out of scope (limbo) block level declarations.
+
+ If this is a block level declaration, then DECL_EXTERNAL must also
+ be set, so we have already checked against global declarations above
+ via the lookup_name call.
We get warnings about inline functions where they are defined.
Avoid duplicate warnings where they are used. */
- if (TREE_PUBLIC (x) && ! DECL_INLINE (x))
+ if (TREE_PUBLIC (x) && ! DECL_INLINE (x)
+ && IDENTIFIER_LIMBO_VALUE (name))
{
- tree decl;
-
- if (IDENTIFIER_GLOBAL_VALUE (name) != 0
- && (DECL_EXTERNAL (IDENTIFIER_GLOBAL_VALUE (name))
- || TREE_PUBLIC (IDENTIFIER_GLOBAL_VALUE (name))))
- decl = IDENTIFIER_GLOBAL_VALUE (name);
- else if (IDENTIFIER_LIMBO_VALUE (name) != 0)
- /* Decls in limbo are always extern, so no need to check that. */
- decl = IDENTIFIER_LIMBO_VALUE (name);
- else
- decl = 0;
+ tree decl = IDENTIFIER_LIMBO_VALUE (name);
- if (decl && ! comptypes (TREE_TYPE (x), TREE_TYPE (decl))
+ if (! comptypes (TREE_TYPE (x), TREE_TYPE (decl))
/* If old decl is built-in, we already warned if we should. */
&& !DECL_BUILT_IN (decl))
{
if (DECL_BUILT_IN (oldglobal))
{
DECL_BUILT_IN (x) = DECL_BUILT_IN (oldglobal);
- DECL_SET_FUNCTION_CODE (x, DECL_FUNCTION_CODE (oldglobal));
+ DECL_FUNCTION_CODE (x) = DECL_FUNCTION_CODE (oldglobal);
}
/* Keep the arg types from a file-scope fcn defn. */
if (TYPE_ARG_TYPES (TREE_TYPE (oldglobal)) != 0
return 0;
else
{
- /* Objects declared with block scope: */
- /* Reject two definitions, and reject a definition
- together with an external reference. */
- if (!(DECL_EXTERNAL (newdecl) && DECL_EXTERNAL (olddecl)))
+ /* Newdecl has block scope. If olddecl has block scope also, then
+ reject two definitions, and reject a definition together with an
+ external reference. Otherwise, it is OK, because newdecl must
+ be an extern reference to olddecl. */
+ if (!(DECL_EXTERNAL (newdecl) && DECL_EXTERNAL (olddecl))
+ && DECL_CONTEXT (newdecl) == DECL_CONTEXT (olddecl))
return "redeclaration of `%s'";
return 0;
}
pushdecl (build_decl (TYPE_DECL, get_identifier ("long unsigned int"),
long_unsigned_type_node));
+ long_long_integer_type_node = make_signed_type (LONG_LONG_TYPE_SIZE);
+ pushdecl (build_decl (TYPE_DECL, get_identifier ("long long int"),
+ long_long_integer_type_node));
+
+ long_long_unsigned_type_node = make_unsigned_type (LONG_LONG_TYPE_SIZE);
+ pushdecl (build_decl (TYPE_DECL, get_identifier ("long long unsigned int"),
+ long_long_unsigned_type_node));
+
/* `unsigned long' is the standard type for sizeof.
Traditionally, use a signed type.
Note that stddef.h uses `unsigned long',
TREE_TYPE (TYPE_SIZE (unsigned_type_node)) = sizetype;
TREE_TYPE (TYPE_SIZE (long_unsigned_type_node)) = sizetype;
TREE_TYPE (TYPE_SIZE (long_integer_type_node)) = sizetype;
+ TREE_TYPE (TYPE_SIZE (long_long_integer_type_node)) = sizetype;
+ TREE_TYPE (TYPE_SIZE (long_long_unsigned_type_node)) = sizetype;
error_mark_node = make_node (ERROR_MARK);
TREE_TYPE (error_mark_node) = error_mark_node;
pushdecl (build_decl (TYPE_DECL, get_identifier ("short int"),
short_integer_type_node));
- long_long_integer_type_node = make_signed_type (LONG_LONG_TYPE_SIZE);
- pushdecl (build_decl (TYPE_DECL, get_identifier ("long long int"),
- long_long_integer_type_node));
-
short_unsigned_type_node = make_unsigned_type (SHORT_TYPE_SIZE);
pushdecl (build_decl (TYPE_DECL, get_identifier ("short unsigned int"),
short_unsigned_type_node));
- long_long_unsigned_type_node = make_unsigned_type (LONG_LONG_TYPE_SIZE);
- pushdecl (build_decl (TYPE_DECL, get_identifier ("long long unsigned int"),
- long_long_unsigned_type_node));
-
/* Define both `signed char' and `unsigned char'. */
signed_char_type_node = make_signed_type (CHAR_TYPE_SIZE);
pushdecl (build_decl (TYPE_DECL, get_identifier ("signed char"),
wchar_type_node
= TREE_TYPE (IDENTIFIER_GLOBAL_VALUE (get_identifier (WCHAR_TYPE)));
wchar_type_size = TYPE_PRECISION (wchar_type_node);
- signed_wchar_type_node = type_for_size (wchar_type_size, 0);
- unsigned_wchar_type_node = type_for_size (wchar_type_size, 1);
+ signed_wchar_type_node = signed_type (wchar_type_node);
+ unsigned_wchar_type_node = unsigned_type (wchar_type_node);
integer_zero_node = build_int_2 (0, 0);
TREE_TYPE (integer_zero_node) = integer_type_node;
builtin_function ("__builtin_classify_type", default_function_type,
BUILT_IN_CLASSIFY_TYPE, NULL_PTR);
builtin_function ("__builtin_next_arg",
- build_function_type (ptr_type_node, endlink),
+ build_function_type (ptr_type_node, NULL_TREE),
BUILT_IN_NEXT_ARG, NULL_PTR);
builtin_function ("__builtin_args_info",
build_function_type (integer_type_node,
start_identifier_warnings ();
- init_format_info_table ();
+ /* Prepare to check format strings against argument lists. */
+ init_function_format_info ();
init_iterators ();
if (function_code != NOT_BUILT_IN)
{
DECL_BUILT_IN (decl) = 1;
- DECL_SET_FUNCTION_CODE (decl, function_code);
+ DECL_FUNCTION_CODE (decl) = function_code;
}
/* Warn if a function in the namespace for users
is used without an occasion to consider it declared. */
TEM may equal DECL or it may be a previous decl of the same name. */
tem = pushdecl (decl);
+ /* For C and Obective-C, we by default put things in .common when
+ possible. */
+ DECL_COMMON (tem) = 1;
+
/* For a local variable, define the RTL now. */
if (current_binding_level != global_binding_level
/* But not if this is a duplicate decl
int temporary = allocation_temporary_p ();
char *asmspec = 0;
+ /* If a name was specified, get the string. Then reset DECL_RTL
+ so that we will remake it with the new name. */
if (asmspec_tree)
- asmspec = TREE_STRING_POINTER (asmspec_tree);
+ {
+ asmspec = TREE_STRING_POINTER (asmspec_tree);
+ DECL_RTL (decl) = 0;
+ }
/* If `start_decl' didn't like having an initialization, ignore it now. */
DECL_EXTERNAL (decl) = 1;
}
+ /* TYPE_MAX_VALUE is always one less than the number of elements
+ in the array, because we start counting at zero. Therefore,
+ warn only if the value is less than zero. */
if (pedantic && TYPE_DOMAIN (type) != 0
- && tree_int_cst_lt (TYPE_MAX_VALUE (TYPE_DOMAIN (type)),
- integer_zero_node))
- error_with_decl (decl, "zero-size array `%s'");
+ && tree_int_cst_sgn (TYPE_MAX_VALUE (TYPE_DOMAIN (type))) < 0)
+ error_with_decl (decl, "zero or negative size array `%s'");
layout_decl (decl, 0);
}
?
/* A static variable with an incomplete type
is an error if it is initialized.
+ Also if it is not file scope.
Otherwise, let it through, but if it is not `extern'
then it may cause an error message later. */
- DECL_INITIAL (decl) != 0
+ (DECL_INITIAL (decl) != 0
+ || current_binding_level != global_binding_level)
:
/* An automatic variable with an incomplete type
is an error. */
}
}
+ /* If this is a function and an assembler name is specified, it isn't
+ builtin any more. */
+ if (TREE_CODE (decl) == FUNCTION_DECL && asmspec)
+ DECL_BUILT_IN (decl) = 0;
+
/* Output the assembler code and/or RTL code for variables and functions,
unless the type is an undefined structure or union.
If not, it will get done when the type is completed. */
}
/* ??? After 2.3, test (init != 0) instead of TREE_CODE. */
+ /* This test used to include TREE_PERMANENT, however, we have the same
+ problem with initializers at the function level. Such initializers get
+ saved until the end of the function on the momentary_obstack. */
if (!(TREE_CODE (decl) == FUNCTION_DECL && DECL_INLINE (decl))
- && temporary && TREE_PERMANENT (decl)
+ && temporary
/* DECL_INITIAL is not defined in PARM_DECLs, since it shares
space with DECL_ARG_TYPE. */
&& TREE_CODE (decl) != PARM_DECL)
/* We make an exception for inline functions, since it's
normal for a local extern redeclaration of an inline function
to have a copy of the top-level decl's DECL_INLINE. */
- if (DECL_INITIAL (decl) != 0)
- DECL_INITIAL (decl) = error_mark_node;
+ if (DECL_INITIAL (decl) != 0 && DECL_INITIAL (decl) != error_mark_node)
+ {
+ /* If this is a const variable, then preserve the
+ initializer instead of discarding it so that we can optimize
+ references to it. */
+ /* This test used to include TREE_STATIC, but this won't be set
+ for function level initializers. */
+ if (TREE_READONLY (decl))
+ {
+ preserve_initializer ();
+ /* Hack? Set the permanent bit for something that is permanent,
+ but not on the permenent obstack, so as to convince
+ output_constant_def to make its rtl on the permanent
+ obstack. */
+ TREE_PERMANENT (DECL_INITIAL (decl)) = 1;
+
+ /* The initializer and DECL must have the same (or equivalent
+ types), but if the initializer is a STRING_CST, its type
+ might not be on the right obstack, so copy the type
+ of DECL. */
+ TREE_TYPE (DECL_INITIAL (decl)) = type;
+ }
+ else
+ DECL_INITIAL (decl) = error_mark_node;
+ }
+ }
+
+ /* If requested, warn about definitions of large data objects. */
+
+ if (warn_larger_than
+ && (TREE_CODE (decl) == VAR_DECL || TREE_CODE (decl) == PARM_DECL)
+ && !DECL_EXTERNAL (decl))
+ {
+ register tree decl_size = DECL_SIZE (decl);
+
+ if (decl_size && TREE_CODE (decl_size) == INTEGER_CST)
+ {
+ unsigned units = TREE_INT_CST_LOW(decl_size) / BITS_PER_UNIT;
+
+ if (units > larger_than_size)
+ warning_with_decl (decl, "size of `%s' is %u bytes", units);
+ }
}
#if 0
/* If we have gone back from temporary to permanent allocation,
actually free the temporary space that we no longer need. */
if (temporary && !allocation_temporary_p ())
- permanent_allocation ();
+ permanent_allocation (0);
/* At the end of a declaration, throw away any variable type sizes
of types defined inside that declaration. There is no use
push_parm_decl (parm)
tree parm;
{
- tree decl, olddecl;
+ tree decl;
int old_immediate_size_expand = immediate_size_expand;
/* Don't try computing parm sizes now -- wait till fn is called. */
immediate_size_expand = 0;
#if 0
if (DECL_NAME (decl))
{
+ tree olddecl;
olddecl = lookup_name (DECL_NAME (decl));
if (pedantic && olddecl != 0 && TREE_CODE (olddecl) == TYPE_DECL)
pedwarn_with_decl (decl, "ANSI C forbids parameter `%s' shadowing typedef");
{
int eltsize
= int_size_in_bytes (TREE_TYPE (TREE_TYPE (initial_value)));
- maxindex = build_int_2 (TREE_STRING_LENGTH (initial_value) / eltsize - 1, 0);
+ maxindex = build_int_2 ((TREE_STRING_LENGTH (initial_value)
+ / eltsize) - 1, 0);
}
else if (TREE_CODE (initial_value) == CONSTRUCTOR)
{
- register int nelts
- = list_length (CONSTRUCTOR_ELTS (initial_value));
- maxindex = build_int_2 (nelts - 1, - (nelts == 0));
+ tree elts = CONSTRUCTOR_ELTS (initial_value);
+ maxindex = size_binop (MINUS_EXPR, integer_zero_node, size_one_node);
+ for (; elts; elts = TREE_CHAIN (elts))
+ {
+ if (TREE_PURPOSE (elts))
+ maxindex = TREE_PURPOSE (elts);
+ else
+ maxindex = size_binop (PLUS_EXPR, maxindex, size_one_node);
+ }
+ maxindex = copy_node (maxindex);
}
else
{
}
}
+ if ((specbits & (1 << (int) RID_COMPLEX))
+ && TREE_CODE (type) != INTEGER_TYPE && TREE_CODE (type) != REAL_TYPE)
+ {
+ error ("complex invalid for `%s'", name);
+ specbits &= ~ (1 << (int) RID_COMPLEX);
+ }
+
/* Decide whether an integer type is signed or not.
Optionally treat bitfields as signed by default. */
if (specbits & 1 << (int) RID_UNSIGNED
type = long_integer_type_node;
else if (specbits & 1 << (int) RID_SHORT)
type = short_integer_type_node;
- else if (specbits & 1 << (int) RID_COMPLEX)
+
+ if (specbits & 1 << (int) RID_COMPLEX)
{
- if (defaulted_int)
+ /* If we just have "complex", it is equivalent to
+ "complex double", but if any modifiers at all are specified it is
+ the complex form of TYPE. E.g, "complex short" is
+ "complex short int". */
+
+ if (defaulted_int && ! longlong
+ && ! (specbits & ((1 << (int) RID_LONG) | (1 << (int) RID_SHORT)
+ | (1 << (int) RID_SIGNED)
+ | (1 << (int) RID_UNSIGNED))))
type = complex_double_type_node;
else if (type == integer_type_node)
type = complex_integer_type_node;
else if (type == long_double_type_node)
type = complex_long_double_type_node;
else
- error ("invalid complex type");
+ type = build_complex_type (type);
}
/* Set CONSTP if this declaration is `const', whether by
register tree size = TREE_OPERAND (declarator, 1);
/* An uninitialized decl with `extern' is a reference. */
int extern_ref = !initialized && (specbits & (1 << (int) RID_EXTERN));
+ /* The index is a signed object `sizetype' bits wide. */
+ tree index_type = signed_type (sizetype);
declarator = TREE_OPERAND (declarator, 0);
error ("size of array `%s' has non-integer type", name);
size = integer_one_node;
}
+
if (pedantic && integer_zerop (size))
pedwarn ("ANSI C forbids zero-size array `%s'", name);
+
if (TREE_CODE (size) == INTEGER_CST)
{
constant_expression_warning (size);
- if (INT_CST_LT (size, integer_zero_node))
+ if (tree_int_cst_sgn (size) < 0)
{
error ("size of array `%s' is negative", name);
size = integer_one_node;
}
- itype = build_index_type (size_binop (MINUS_EXPR, size,
- size_one_node));
}
else
{
+ /* Make sure the array size remains visibly nonconstant
+ even if it is (eg) a const variable with known value. */
+ size_varies = 1;
+
if (pedantic)
{
if (TREE_CONSTANT (size))
else
pedwarn ("ANSI C forbids variable-size array `%s'", name);
}
- itype = build_binary_op (MINUS_EXPR, size, integer_one_node,
- 1);
- /* Make sure the array size remains visibly nonconstant
- even if it is (eg) a const variable with known value. */
- size_varies = 1;
- itype = variable_size (itype);
- itype = build_index_type (itype);
}
+
+ /* Convert size to index_type, so that if it is a variable
+ the computations will be done in the proper mode. */
+ itype = fold (build (MINUS_EXPR, index_type,
+ convert (index_type, size),
+ convert (index_type, size_one_node)));
+
+ if (size_varies)
+ itype = variable_size (itype);
+ itype = build_index_type (itype);
}
#if 0 /* This had bad results for pointers to arrays, as in
if (TREE_CODE (type) == ARRAY_TYPE)
{
/* Transfer const-ness of array into that of type pointed to. */
- type = build_pointer_type
- (c_build_type_variant (TREE_TYPE (type), constp, volatilep));
+ type = TREE_TYPE (type);
+ if (constp || volatilep)
+ type = c_build_type_variant (type, constp, volatilep);
+ type = build_pointer_type (type);
volatilep = constp = 0;
size_varies = 0;
}
{
if (pedantic && (constp || volatilep))
pedwarn ("ANSI C forbids const or volatile function types");
- type = build_pointer_type (c_build_type_variant (type, constp, volatilep));
+ if (constp || volatilep)
+ type = c_build_type_variant (type, constp, volatilep);
+ type = build_pointer_type (type);
volatilep = constp = 0;
}
if (volatilep
&& TREE_TYPE (TREE_TYPE (decl)) != void_type_node)
- warning ("volatile function returns non-void value");
+ warning ("`noreturn' function returns non-void value");
if (extern_ref)
DECL_EXTERNAL (decl) = 1;
tree type = TREE_TYPE (decl);
DECL_ARG_TYPE (decl) = type;
#ifdef PROMOTE_PROTOTYPES
- if (TREE_CODE (type) == INTEGER_TYPE
+ if ((TREE_CODE (type) == INTEGER_TYPE
+ || TREE_CODE (type) == ENUMERAL_TYPE)
&& TYPE_PRECISION (type) < TYPE_PRECISION (integer_type_node))
DECL_ARG_TYPE (decl) = integer_type_node;
#endif
{
unsigned HOST_WIDE_INT width = TREE_INT_CST_LOW (DECL_INITIAL (x));
- if (tree_int_cst_lt (DECL_INITIAL (x), integer_zero_node))
+ if (tree_int_cst_sgn (DECL_INITIAL (x)) < 0)
{
DECL_INITIAL (x) = NULL;
error_with_decl (x, "negative width in bit-field `%s'");
tree minnode = 0, maxnode = 0;
register HOST_WIDE_INT maxvalue = 0;
register HOST_WIDE_INT minvalue = 0;
- register int i;
unsigned precision = 0;
int toplevel = global_binding_level == current_binding_level;
- int temporary = allocation_temporary_p ();
if (in_parm_level_p ())
warning ("enum defined inside parms");
layout_type (enumtype);
/* An enum can have some negative values; then it is signed. */
- TREE_UNSIGNED (enumtype) = ! tree_int_cst_lt (minnode, integer_zero_node);
+ TREE_UNSIGNED (enumtype) = tree_int_cst_sgn (minnode) >= 0;
- /* If the enumerators might not fit in an int, change their type now. */
- /* It seems more useful in the debugger to leave these as int
- unless the enumerator is wider than int. */
- if (TYPE_PRECISION (enumtype) <= TYPE_PRECISION (integer_type_node))
- for (pair = values; pair; pair = TREE_CHAIN (pair))
- {
- TREE_TYPE (TREE_PURPOSE (pair)) = enumtype;
- DECL_SIZE (TREE_PURPOSE (pair)) = TYPE_SIZE (enumtype);
- if (TREE_CODE (TREE_PURPOSE (pair)) != FUNCTION_DECL)
- DECL_ALIGN (TREE_PURPOSE (pair)) = TYPE_ALIGN (enumtype);
- }
+ /* Change the type of the enumerators to be the enum type.
+ Formerly this was done only for enums that fit in an int,
+ but the comment said it was done only for enums wider than int.
+ It seems necessary to do this for wide enums,
+ and best not to change what's done for ordinary narrower ones. */
+ for (pair = values; pair; pair = TREE_CHAIN (pair))
+ {
+ TREE_TYPE (TREE_PURPOSE (pair)) = enumtype;
+ DECL_SIZE (TREE_PURPOSE (pair)) = TYPE_SIZE (enumtype);
+ if (TREE_CODE (TREE_PURPOSE (pair)) != FUNCTION_DECL)
+ DECL_ALIGN (TREE_PURPOSE (pair)) = TYPE_ALIGN (enumtype);
+ }
/* Replace the decl nodes in VALUES with their names. */
for (pair = values; pair; pair = TREE_CHAIN (pair))
build_enumerator (name, value)
tree name, value;
{
- register tree decl;
+ register tree decl, type;
/* Validate and default VALUE. */
if (value != 0)
{
if (TREE_CODE (value) == INTEGER_CST)
- constant_expression_warning (value);
+ {
+ value = default_conversion (value);
+ constant_expression_warning (value);
+ }
else
{
error ("enumerator value for `%s' not integer constant",
/* Now create a declaration for the enum value name. */
- decl = build_decl (CONST_DECL, name, integer_type_node);
+ type = TREE_TYPE (value);
+ type = type_for_size (MAX (TYPE_PRECISION (type),
+ TYPE_PRECISION (integer_type_node)),
+ ((flag_traditional
+ || TYPE_PRECISION (type) >= TYPE_PRECISION (integer_type_node))
+ && TREE_UNSIGNED (type)));
+
+ decl = build_decl (CONST_DECL, name, type);
DECL_INITIAL (decl) = value;
- TREE_TYPE (value) = integer_type_node;
+ TREE_TYPE (value) = type;
pushdecl (decl);
return saveable_tree_cons (decl, value, NULL_TREE);
else if (warn_missing_prototypes
&& old_decl != 0 && TREE_USED (old_decl)
&& !(old_decl != 0 && TYPE_ARG_TYPES (TREE_TYPE (old_decl)) != 0))
- warning_with_decl (decl1, "`%s' was used with no prototype before its definition");
+ warning_with_decl (decl1,
+ "`%s' was used with no prototype before its definition");
+ /* Optionally warn of any global def with no previous declaration. */
+ else if (warn_missing_declarations
+ && TREE_PUBLIC (decl1)
+ && old_decl == 0
+ && strcmp ("main", IDENTIFIER_POINTER (DECL_NAME (decl1))))
+ warning_with_decl (decl1, "no previous declaration for `%s'");
+ /* Optionally warn of any def with no previous declaration
+ if the function has already been used. */
+ else if (warn_missing_declarations
+ && old_decl != 0 && TREE_USED (old_decl))
+ warning_with_decl (decl1,
+ "`%s' was used with no declaration before its definition");
/* This is a definition, not a reference.
So normally clear DECL_EXTERNAL.
useful for argument types like uid_t. */
DECL_ARG_TYPE (parm) = TREE_TYPE (parm);
#ifdef PROMOTE_PROTOTYPES
- if (TREE_CODE (TREE_TYPE (parm)) == INTEGER_TYPE
+ if ((TREE_CODE (TREE_TYPE (parm)) == INTEGER_TYPE
+ || TREE_CODE (TREE_TYPE (parm)) == ENUMERAL_TYPE)
&& TYPE_PRECISION (TREE_TYPE (parm))
< TYPE_PRECISION (integer_type_node))
DECL_ARG_TYPE (parm) = integer_type_node;
else
{
- register tree actual, type;
- register tree last = 0;
+ tree actual = 0, last = 0, type;
for (parm = DECL_ARGUMENTS (fndecl); parm; parm = TREE_CHAIN (parm))
{
#endif
/* Generate rtl for function exit. */
- expand_function_end (input_filename, lineno);
+ expand_function_end (input_filename, lineno, 0);
/* So we can tell if jump_optimize sets it to 1. */
can_reach_end = 0;
current_function_returns_null |= can_reach_end;
if (TREE_THIS_VOLATILE (fndecl) && current_function_returns_null)
- warning ("`volatile' function does return");
+ warning ("`noreturn' function does return");
else if (warn_return_type && can_reach_end
&& TYPE_MAIN_VARIANT (TREE_TYPE (TREE_TYPE (fndecl))) != void_type_node)
/* If this function returns non-void and control can drop through,
&& current_function_returns_value && current_function_returns_null)
warning ("this function may return with or without a value");
+ /* If requested, warn about function definitions where the function will
+ return a value (usually of some struct or union type) which itself will
+ take up a lot of stack space. */
+
+ if (warn_larger_than && !DECL_EXTERNAL (fndecl) && TREE_TYPE (fndecl))
+ {
+ register tree ret_type = TREE_TYPE (TREE_TYPE (fndecl));
+
+ if (ret_type)
+ {
+ register tree ret_type_size = TYPE_SIZE (ret_type);
+
+ if (TREE_CODE (ret_type_size) == INTEGER_CST)
+ {
+ unsigned units
+ = TREE_INT_CST_LOW (ret_type_size) / BITS_PER_UNIT;
+
+ if (units > larger_than_size)
+ warning_with_decl (fndecl,
+ "size of return value of `%s' is %u bytes",
+ units);
+ }
+ }
+ }
+
/* Free all the tree nodes making up this function. */
/* Switch back to allocating nodes permanently
until we start another function. */
if (! nested)
- permanent_allocation ();
+ permanent_allocation (1);
if (DECL_SAVED_INSNS (fndecl) == 0 && ! nested)
{
/* But DECL_INITIAL must remain nonzero so we know this
was an actual function definition. */
/* For a nested function, this is done in pop_c_function_context. */
- DECL_INITIAL (fndecl) = error_mark_node;
+ /* If rest_of_compilation set this to 0, leave it 0. */
+ if (DECL_INITIAL (fndecl) != 0)
+ DECL_INITIAL (fndecl) = error_mark_node;
DECL_ARGUMENTS (fndecl) = 0;
}
struct c_function
{
struct c_function *next;
- tree enum_next_value;
tree named_labels;
tree shadowed_labels;
int returns_value;
p->next = c_function_chain;
c_function_chain = p;
- p->enum_next_value = enum_next_value;
p->named_labels = named_labels;
p->shadowed_labels = shadowed_labels;
p->returns_value = current_function_returns_value;
c_function_chain = p->next;
- enum_next_value = p->enum_next_value;
named_labels = p->named_labels;
shadowed_labels = p->shadowed_labels;
current_function_returns_value = p->returns_value;