/* Process declarations and variables for C compiler.
- Copyright (C) 1988, 92-97, 1998 Free Software Foundation, Inc.
+ Copyright (C) 1988, 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999, 2000
+ Free Software Foundation, Inc.
This file is part of GNU CC.
#include "system.h"
#include "tree.h"
#include "flags.h"
+#include "function.h"
#include "output.h"
#include "c-tree.h"
#include "c-lex.h"
#include "toplev.h"
+#include "defaults.h"
+#include "ggc.h"
#if USE_CPPLIB
#include "cpplib.h"
-extern cpp_reader parse_in;
-extern cpp_options parse_options;
-static int cpp_initialized;
+extern cpp_reader parse_in;
#endif
/* In grokdeclarator, distinguish syntactic contexts of declarators. */
BITFIELD, /* Likewise but with specified width */
TYPENAME}; /* Typename (inside cast or sizeof) */
-#ifndef CHAR_TYPE_SIZE
-#define CHAR_TYPE_SIZE BITS_PER_UNIT
-#endif
-
-#ifndef SHORT_TYPE_SIZE
-#define SHORT_TYPE_SIZE (BITS_PER_UNIT * MIN ((UNITS_PER_WORD + 1) / 2, 2))
-#endif
-
-#ifndef INT_TYPE_SIZE
-#define INT_TYPE_SIZE BITS_PER_WORD
-#endif
-
-#ifndef LONG_TYPE_SIZE
-#define LONG_TYPE_SIZE BITS_PER_WORD
-#endif
-
-#ifndef LONG_LONG_TYPE_SIZE
-#define LONG_LONG_TYPE_SIZE (BITS_PER_WORD * 2)
-#endif
-
-#ifndef WCHAR_UNSIGNED
-#define WCHAR_UNSIGNED 0
-#endif
-
-#ifndef FLOAT_TYPE_SIZE
-#define FLOAT_TYPE_SIZE BITS_PER_WORD
-#endif
-
-#ifndef DOUBLE_TYPE_SIZE
-#define DOUBLE_TYPE_SIZE (BITS_PER_WORD * 2)
-#endif
-
-#ifndef LONG_DOUBLE_TYPE_SIZE
-#define LONG_DOUBLE_TYPE_SIZE (BITS_PER_WORD * 2)
-#endif
-
/* We let tm.h override the types used here, to handle trivial differences
such as the choice of unsigned int or long unsigned int for size_t.
When machines start needing nontrivial differences in the size type,
#define WCHAR_TYPE "int"
#endif
\f
-/* a node which has tree code ERROR_MARK, and whose type is itself.
- All erroneous expressions are replaced with this node. All functions
- that accept nodes as arguments should avoid generating error messages
- if this node is one of the arguments, since it is undesirable to get
- multiple error messages from one error in the input. */
-
-tree error_mark_node;
-
-/* INTEGER_TYPE and REAL_TYPE nodes for the standard data types */
-
-tree short_integer_type_node;
-tree integer_type_node;
-tree long_integer_type_node;
-tree long_long_integer_type_node;
-
-tree short_unsigned_type_node;
-tree unsigned_type_node;
-tree long_unsigned_type_node;
-tree long_long_unsigned_type_node;
-
-tree boolean_type_node;
-tree boolean_false_node;
-tree boolean_true_node;
-
-tree ptrdiff_type_node;
-
-tree unsigned_char_type_node;
-tree signed_char_type_node;
-tree char_type_node;
-tree wchar_type_node;
-tree signed_wchar_type_node;
-tree unsigned_wchar_type_node;
-
-tree float_type_node;
-tree double_type_node;
-tree long_double_type_node;
-
-tree complex_integer_type_node;
-tree complex_float_type_node;
-tree complex_double_type_node;
-tree complex_long_double_type_node;
-
-tree intQI_type_node;
-tree intHI_type_node;
-tree intSI_type_node;
-tree intDI_type_node;
-tree intTI_type_node;
-
-tree unsigned_intQI_type_node;
-tree unsigned_intHI_type_node;
-tree unsigned_intSI_type_node;
-tree unsigned_intDI_type_node;
-tree unsigned_intTI_type_node;
-
-/* a VOID_TYPE node. */
-
-tree void_type_node;
-
-/* Nodes for types `void *' and `const void *'. */
-
-tree ptr_type_node, const_ptr_type_node;
-
-/* Nodes for types `char *' and `const char *'. */
-
-tree string_type_node, const_string_type_node;
-
-/* Type `char[SOMENUMBER]'.
- Used when an array of char is needed and the size is irrelevant. */
-
-tree char_array_type_node;
-
-/* Type `int[SOMENUMBER]' or something like it.
- Used when an array of int needed and the size is irrelevant. */
-
-tree int_array_type_node;
-
-/* Type `wchar_t[SOMENUMBER]' or something like it.
- Used when a wide string literal is created. */
-
-tree wchar_array_type_node;
-
-/* type `int ()' -- used for implicit declaration of functions. */
-
-tree default_function_type;
-
-/* function types `double (double)' and `double (double, double)', etc. */
-
-tree double_ftype_double, double_ftype_double_double;
-tree int_ftype_int, long_ftype_long;
-tree float_ftype_float;
-tree ldouble_ftype_ldouble;
-
-/* Function type `void (void *, void *, int)' and similar ones */
-
-tree void_ftype_ptr_ptr_int, int_ftype_ptr_ptr_int, void_ftype_ptr_int_int;
-
-/* Function type `char *(char *, char *)' and similar ones */
-tree string_ftype_ptr_ptr, int_ftype_string_string;
-
-/* Function type `int (const void *, const void *, size_t)' */
-tree int_ftype_cptr_cptr_sizet;
-
-/* Two expressions that are constants with value zero.
- The first is of type `int', the second of type `void *'. */
-
-tree integer_zero_node;
-tree null_pointer_node;
-
-/* A node for the integer constant 1. */
-
-tree integer_one_node;
+/* Do GC. */
+int ggc_p = 1;
/* Nonzero if we have seen an invalid cross reference
to a struct, union, or enum, but not yet printed the message. */
static int c_function_varargs;
-/* The FUNCTION_DECL for the function currently being compiled,
- or 0 if between functions. */
-tree current_function_decl;
-
/* Set to 0 at beginning of a function definition, set to 1 if
a return statement that specifies a return value is seen. */
/* Forward declarations. */
-static struct binding_level * make_binding_level PROTO((void));
-static void clear_limbo_values PROTO((tree));
-static int duplicate_decls PROTO((tree, tree, int));
-static char *redeclaration_error_message PROTO((tree, tree));
-static void storedecls PROTO((tree));
-static void storetags PROTO((tree));
-static tree lookup_tag PROTO((enum tree_code, tree,
- struct binding_level *, int));
-static tree lookup_tag_reverse PROTO((tree));
-static tree grokdeclarator PROTO((tree, tree, enum decl_context,
- int));
-static tree grokparms PROTO((tree, int));
-static int field_decl_cmp PROTO((const GENERIC_PTR, const GENERIC_PTR));
-static void layout_array_type PROTO((tree));
+static struct binding_level * make_binding_level PARAMS ((void));
+static void mark_binding_level PARAMS ((void *));
+static void clear_limbo_values PARAMS ((tree));
+static int duplicate_decls PARAMS ((tree, tree, int));
+static int redeclaration_error_message PARAMS ((tree, tree));
+static void storedecls PARAMS ((tree));
+static void storetags PARAMS ((tree));
+static tree lookup_tag PARAMS ((enum tree_code, tree,
+ struct binding_level *, int));
+static tree lookup_tag_reverse PARAMS ((tree));
+static tree grokdeclarator PARAMS ((tree, tree, enum decl_context,
+ int));
+static tree grokparms PARAMS ((tree, int));
+static void layout_array_type PARAMS ((tree));
+static tree c_make_fname_decl PARAMS ((tree, const char *, int));
\f
/* C-specific option variables. */
int flag_short_double;
+/* Nonzero means give `wchar_t' the same size as `short'. */
+
+int flag_short_wchar;
+
/* Nonzero means don't recognize the keyword `asm'. */
int flag_no_asm;
int flag_traditional;
+/* Nonzero means use the ISO C99 dialect of C. */
+
+int flag_isoc99 = 0;
+
/* Nonzero means that we have builtin functions, and main is an int */
int flag_hosted = 1;
int flag_signed_bitfields = 1;
int explicit_flag_signed_bitfields = 0;
-/* Nonzero means handle `#ident' directives. 0 means ignore them. */
-
-int flag_no_ident = 0;
-
/* Nonzero means warn about use of implicit int. */
int warn_implicit_int;
int warn_bad_function_cast;
+/* Warn about functions which might be candidates for attribute noreturn. */
+
+int warn_missing_noreturn;
+
/* Warn about traditional constructs whose meanings changed in ANSI C. */
int warn_traditional;
int warn_sign_compare = -1;
+/* Warn about testing equality of floating point numbers. */
+
+int warn_float_equal = 0;
+
/* Nonzero means warn about use of multicharacter literals. */
int warn_multichar = 1;
int dollars_in_ident = DOLLARS_IN_IDENTIFIERS;
/* Decode the string P as a language-specific option for C.
- Return the number of strings consumed. */
+ Return the number of strings consumed. Should not complain
+ if it does not recognise the option. */
int
c_decode_option (argc, argv)
- int argc;
+ int argc ATTRIBUTE_UNUSED;
char **argv;
{
int strings_processed;
char *p = argv[0];
#if USE_CPPLIB
- if (! cpp_initialized)
- {
- cpp_reader_init (&parse_in);
- parse_in.data = &parse_options;
- cpp_options_init (&parse_options);
- cpp_initialized = 1;
- }
strings_processed = cpp_handle_option (&parse_in, argc, argv);
#else
strings_processed = 0;
flag_traditional = 0;
flag_writable_strings = 0;
}
+ else if (!strncmp (p, "-std=", 5))
+ {
+ /* Select the appropriate language standard. We currently
+ recognize:
+ -std=iso9899:1990 same as -ansi
+ -std=iso9899:199409 ISO C as modified in amend. 1
+ -std=iso9899:1999 ISO C 99
+ -std=c89 same as -std=iso9899:1990
+ -std=c99 same as -std=iso9899:1999
+ -std=gnu89 default, iso9899:1990 + gnu extensions
+ -std=gnu99 iso9899:1999 + gnu extensions
+ */
+ const char *argstart = &p[5];
+
+ if (!strcmp (argstart, "iso9899:1990")
+ || !strcmp (argstart, "c89"))
+ {
+ iso_1990:
+ flag_traditional = 0;
+ flag_writable_strings = 0;
+ flag_no_asm = 1;
+ flag_no_nonansi_builtin = 1;
+ flag_isoc99 = 0;
+ }
+ else if (!strcmp (argstart, "iso9899:199409"))
+ {
+ /* ??? The changes since ISO C 1990 are not supported. */
+ goto iso_1990;
+ }
+ else if (!strcmp (argstart, "iso9899:199x")
+ || !strcmp (argstart, "iso9899:1999")
+ || !strcmp (argstart, "c9x")
+ || !strcmp (argstart, "c99"))
+ {
+ flag_traditional = 0;
+ flag_writable_strings = 0;
+ flag_no_asm = 1;
+ flag_no_nonansi_builtin = 1;
+ flag_isoc99 = 1;
+ }
+ else if (!strcmp (argstart, "gnu89"))
+ {
+ flag_traditional = 0;
+ flag_writable_strings = 0;
+ flag_no_asm = 0;
+ flag_no_nonansi_builtin = 0;
+ flag_isoc99 = 0;
+ }
+ else if (!strcmp (argstart, "gnu9x") || !strcmp (argstart, "gnu99"))
+ {
+ flag_traditional = 0;
+ flag_writable_strings = 0;
+ flag_no_asm = 0;
+ flag_no_nonansi_builtin = 0;
+ flag_isoc99 = 1;
+ }
+ else
+ error ("unknown C standard `%s'", argstart);
+ }
else if (!strcmp (p, "-fdollars-in-identifiers"))
dollars_in_ident = 1;
else if (!strcmp (p, "-fno-dollars-in-identifiers"))
flag_short_enums = 1;
else if (!strcmp (p, "-fno-short-enums"))
flag_short_enums = 0;
+ else if (!strcmp (p, "-fshort-wchar"))
+ flag_short_wchar = 1;
+ else if (!strcmp (p, "-fno-short-wchar"))
+ flag_short_wchar = 0;
else if (!strcmp (p, "-fcond-mismatch"))
flag_cond_mismatch = 1;
else if (!strcmp (p, "-fno-cond-mismatch"))
flag_no_builtin = 0;
else if (!strcmp (p, "-fno-builtin"))
flag_no_builtin = 1;
- else if (!strcmp (p, "-fno-ident"))
- flag_no_ident = 1;
- else if (!strcmp (p, "-fident"))
- flag_no_ident = 0;
else if (!strcmp (p, "-ansi"))
- flag_no_asm = 1, flag_no_nonansi_builtin = 1;
+ goto iso_1990;
else if (!strcmp (p, "-Werror-implicit-function-declaration"))
mesg_implicit_function_declaration = 2;
else if (!strcmp (p, "-Wimplicit-function-declaration"))
warn_bad_function_cast = 1;
else if (!strcmp (p, "-Wno-bad-function-cast"))
warn_bad_function_cast = 0;
+ else if (!strcmp (p, "-Wmissing-noreturn"))
+ warn_missing_noreturn = 1;
+ else if (!strcmp (p, "-Wno-missing-noreturn"))
+ warn_missing_noreturn = 0;
else if (!strcmp (p, "-Wpointer-arith"))
warn_pointer_arith = 1;
else if (!strcmp (p, "-Wno-pointer-arith"))
warn_traditional = 1;
else if (!strcmp (p, "-Wno-traditional"))
warn_traditional = 0;
+ else if (!strncmp (p, "-Wformat=", 9))
+ warn_format = atol (p + 9);
else if (!strcmp (p, "-Wformat"))
warn_format = 1;
else if (!strcmp (p, "-Wno-format"))
else if (!strcmp (p, "-Wmain"))
warn_main = 1;
else if (!strcmp (p, "-Wno-main"))
- warn_main = 0;
+ warn_main = -1;
else if (!strcmp (p, "-Wsign-compare"))
warn_sign_compare = 1;
else if (!strcmp (p, "-Wno-sign-compare"))
warn_sign_compare = 0;
+ else if (!strcmp (p, "-Wfloat-equal"))
+ warn_float_equal = 1;
+ else if (!strcmp (p, "-Wno-float-equal"))
+ warn_float_equal = 0;
else if (!strcmp (p, "-Wmultichar"))
warn_multichar = 1;
else if (!strcmp (p, "-Wno-multichar"))
void
declare_parm_level (definition_flag)
- int definition_flag;
+ int definition_flag ATTRIBUTE_UNUSED;
{
current_binding_level->parm_flag = 1;
}
#if 0
/* Warn about incomplete structure types in this level. */
for (link = tags; link; link = TREE_CHAIN (link))
- if (TYPE_SIZE (TREE_VALUE (link)) == 0)
+ if (!COMPLETE_TYPE_P (TREE_VALUE (link)))
{
tree type = TREE_VALUE (link);
- char *errmsg;
+ tree type_name = TYPE_NAME (type);
+ char *id = IDENTIFIER_POINTER (TREE_CODE (type_name) == IDENTIFIER_NODE
+ ? type_name
+ : DECL_NAME (type_name));
switch (TREE_CODE (type))
{
case RECORD_TYPE:
- errmsg = "`struct %s' incomplete in scope ending here";
+ error ("`struct %s' incomplete in scope ending here", id);
break;
case UNION_TYPE:
- errmsg = "`union %s' incomplete in scope ending here";
+ error ("`union %s' incomplete in scope ending here", id);
break;
case ENUMERAL_TYPE:
- errmsg = "`enum %s' incomplete in scope ending here";
+ error ("`enum %s' incomplete in scope ending here", id);
break;
}
- if (TREE_CODE (TYPE_NAME (type)) == IDENTIFIER_NODE)
- error (errmsg, IDENTIFIER_POINTER (TYPE_NAME (type)));
- else
- /* If this type has a typedef-name, the TYPE_NAME is a TYPE_DECL. */
- error (errmsg, IDENTIFIER_POINTER (DECL_NAME (TYPE_NAME (type))));
}
#endif /* 0 */
if (block != 0)
{
BLOCK_VARS (block) = decls;
- BLOCK_TYPE_TAGS (block) = tags;
BLOCK_SUBBLOCKS (block) = subblocks;
- remember_end_note (block);
}
/* In each subblock, record that this is its superior. */
TYPE_NAME (type) = name;
}
- if (b == global_binding_level)
- b->tags = perm_tree_cons (name, type, b->tags);
- else
- b->tags = saveable_tree_cons (name, type, b->tags);
+ b->tags = tree_cons (name, type, b->tags);
/* Create a fake NULL-named TYPE_DECL node whose TREE_TYPE will be the
tagged type we just added to the current binding level. This fake
&& DECL_INITIAL (newdecl) != 0);
tree oldtype = TREE_TYPE (olddecl);
tree newtype = TREE_TYPE (newdecl);
- char *errmsg = 0;
+ int errmsg = 0;
- if (TREE_CODE_CLASS (TREE_CODE (olddecl)) == 'd')
+ if (DECL_P (olddecl))
DECL_MACHINE_ATTRIBUTES (newdecl)
= merge_machine_decl_attributes (olddecl, newdecl);
tree oldreturntype = TREE_TYPE (oldtype);
tree newreturntype = TREE_TYPE (newtype);
- /* 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 ();
- }
-
if (TYPE_MODE (oldreturntype) == TYPE_MODE (newreturntype))
{
/* Function types may be shared, so we can't just modify
}
if (! different_binding_level)
TREE_TYPE (olddecl) = oldtype;
-
- pop_obstacks ();
}
if (!types_match)
{
if (TREE_CHAIN (t) == 0
&& TYPE_MAIN_VARIANT (type) != void_type_node)
{
- error ("A parameter list with an ellipsis can't match");
- error ("an empty parameter name list declaration.");
+ error ("A parameter list with an ellipsis can't match an empty parameter name list declaration.");
break;
}
- if (TYPE_MAIN_VARIANT (type) == float_type_node
- || C_PROMOTING_INTEGER_TYPE_P (type))
+ if (simple_type_promotes_to (type) != NULL_TREE)
{
- error ("An argument type that has a default promotion");
- error ("can't match an empty parameter name list declaration.");
+ error ("An argument type that has a default promotion can't match an empty parameter name list declaration.");
break;
}
}
errmsg = redeclaration_error_message (newdecl, olddecl);
if (errmsg)
{
- error_with_decl (newdecl, errmsg);
+ switch (errmsg)
+ {
+ case 1:
+ error_with_decl (newdecl, "redefinition of `%s'");
+ break;
+ case 2:
+ error_with_decl (newdecl, "redeclaration of `%s'");
+ break;
+ case 3:
+ error_with_decl (newdecl, "conflicting declarations of `%s'");
+ break;
+ default:
+ abort ();
+ }
+
error_with_decl (olddecl,
((DECL_INITIAL (olddecl)
&& current_binding_level == global_binding_level)
for (parm = TYPE_ACTUAL_ARG_TYPES (oldtype),
type = TYPE_ARG_TYPES (newtype),
nargs = 1;
- (TYPE_MAIN_VARIANT (TREE_VALUE (parm)) != void_type_node
- || TYPE_MAIN_VARIANT (TREE_VALUE (type)) != void_type_node);
+ ;
parm = TREE_CHAIN (parm), type = TREE_CHAIN (type), nargs++)
{
if (TYPE_MAIN_VARIANT (TREE_VALUE (parm)) == void_type_node
+ && TYPE_MAIN_VARIANT (TREE_VALUE (type)) == void_type_node)
+ {
+ warning_with_decl (newdecl, "prototype for `%s' follows");
+ warning_with_decl (olddecl, "non-prototype definition here");
+ break;
+ }
+ if (TYPE_MAIN_VARIANT (TREE_VALUE (parm)) == void_type_node
|| TYPE_MAIN_VARIANT (TREE_VALUE (type)) == void_type_node)
{
- errmsg = "prototype for `%s' follows and number of arguments";
+ error_with_decl (newdecl, "prototype for `%s' follows and number of arguments doesn't match");
+ error_with_decl (olddecl, "non-prototype definition here");
+ errmsg = 1;
break;
}
/* Type for passing arg must be consistent
&& TYPE_MAIN_VARIANT (TREE_VALUE (parm)) == integer_type_node
&& TYPE_MAIN_VARIANT (TREE_VALUE (type)) == unsigned_type_node)))
{
- errmsg = "prototype for `%s' follows and argument %d";
+ error_with_decl (newdecl,
+ "prototype for `%s' follows and argument %d doesn't match",
+ nargs);
+ error_with_decl (olddecl, "non-prototype definition here");
+ errmsg = 1;
break;
}
}
- if (errmsg)
- {
- error_with_decl (newdecl, errmsg, nargs);
- error_with_decl (olddecl,
- "doesn't match non-prototype definition here");
- }
- else
- {
- warning_with_decl (newdecl, "prototype for `%s' follows");
- warning_with_decl (olddecl, "non-prototype definition here");
- }
}
/* Warn about mismatches in various flags. */
else
&& !TREE_PUBLIC (newdecl))
warning_with_decl (newdecl, "static declaration for `%s' follows non-static");
+ /* If warn_traditional, warn when a non-static function
+ declaration follows a static one. */
+ if (warn_traditional
+ && TREE_CODE (olddecl) == FUNCTION_DECL
+ && !TREE_PUBLIC (olddecl)
+ && TREE_PUBLIC (newdecl))
+ warning_with_decl (newdecl, "non-static declaration for `%s' follows static");
+
/* Warn when const declaration follows a non-const
declaration, but not for functions. */
if (TREE_CODE (olddecl) != FUNCTION_DECL
different_binding_level is true. */
tree write_olddecl = different_binding_level ? newdecl : olddecl;
- /* 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))
{
{
/* Since the type is OLDDECL's, make OLDDECL's size go with. */
DECL_SIZE (newdecl) = DECL_SIZE (olddecl);
+ DECL_SIZE_UNIT (newdecl) = DECL_SIZE_UNIT (olddecl);
+ DECL_MODE (newdecl) = DECL_MODE (olddecl);
if (TREE_CODE (olddecl) != FUNCTION_DECL)
if (DECL_ALIGN (olddecl) > DECL_ALIGN (newdecl))
DECL_ALIGN (newdecl) = DECL_ALIGN (olddecl);
DECL_RTL (newdecl) = DECL_RTL (olddecl);
/* Merge the type qualifiers. */
- if (DECL_BUILT_IN_NONANSI (olddecl) && TREE_THIS_VOLATILE (olddecl)
- && !TREE_THIS_VOLATILE (newdecl))
+ if (TREE_CODE (olddecl) == FUNCTION_DECL
+ && DECL_BUILT_IN_NONANSI (olddecl) && TREE_THIS_VOLATILE (olddecl)
+ && ! TREE_THIS_VOLATILE (newdecl))
TREE_THIS_VOLATILE (write_olddecl) = 0;
+
if (TREE_READONLY (newdecl))
TREE_READONLY (write_olddecl) = 1;
+
if (TREE_THIS_VOLATILE (newdecl))
{
TREE_THIS_VOLATILE (write_olddecl) = 1;
if (DECL_SECTION_NAME (newdecl) == NULL_TREE)
DECL_SECTION_NAME (newdecl) = DECL_SECTION_NAME (olddecl);
+ /* Copy the assembler name.
+ Currently, it can only be defined in the prototype. */
+ DECL_ASSEMBLER_NAME (newdecl) = DECL_ASSEMBLER_NAME (olddecl);
+
if (TREE_CODE (newdecl) == FUNCTION_DECL)
{
DECL_STATIC_CONSTRUCTOR(newdecl) |= DECL_STATIC_CONSTRUCTOR(olddecl);
DECL_NO_INSTRUMENT_FUNCTION_ENTRY_EXIT (newdecl)
|= DECL_NO_INSTRUMENT_FUNCTION_ENTRY_EXIT (olddecl);
+ DECL_NO_CHECK_MEMORY_USAGE (newdecl)
+ |= DECL_NO_CHECK_MEMORY_USAGE (olddecl);
+ DECL_NO_LIMIT_STACK (newdecl)
+ |= DECL_NO_LIMIT_STACK (olddecl);
}
-
- pop_obstacks ();
}
/* If cannot merge, then use the new type and qualifiers,
and don't preserve the old rtl. */
TREE_PUBLIC (olddecl) = TREE_PUBLIC (newdecl);
}
- /* If either decl says `inline', this fn is inline,
- unless its definition was passed already. */
- if (DECL_INLINE (newdecl) && DECL_INITIAL (olddecl) == 0)
- DECL_INLINE (olddecl) = 1;
- DECL_INLINE (newdecl) = DECL_INLINE (olddecl);
-
if (TREE_CODE (newdecl) == FUNCTION_DECL)
{
+ /* If either decl says `inline', this fn is inline,
+ unless its definition was passed already. */
+ if (DECL_INLINE (newdecl) && DECL_INITIAL (olddecl) == 0)
+ DECL_INLINE (olddecl) = 1;
+
+ DECL_INLINE (newdecl) = DECL_INLINE (olddecl);
+
if (DECL_BUILT_IN (olddecl))
{
/* Get rid of any built-in function if new arg types don't match it
if (! different_binding_level)
{
TREE_TYPE (olddecl) = TREE_TYPE (newdecl);
- DECL_BUILT_IN (olddecl) = 0;
+ DECL_BUILT_IN_CLASS (olddecl) = NOT_BUILT_IN;
}
}
else
{
/* If redeclaring a builtin function, and not a definition,
it stays built in. */
- DECL_BUILT_IN (newdecl) = 1;
+ DECL_BUILT_IN_CLASS (newdecl) = DECL_BUILT_IN_CLASS (olddecl);
DECL_FUNCTION_CODE (newdecl) = DECL_FUNCTION_CODE (olddecl);
}
}
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)
+ && ! (TREE_CODE (x) == FUNCTION_DECL && DECL_INLINE (x)))
{
tree decl;
{
if (type == error_mark_node)
break;
- if (! TREE_PERMANENT (type))
+ if (! TYPE_CONTEXT (type))
{
warning_with_decl (x, "type of external `%s' is not global");
/* By exiting the loop early, we leave TYPE nonzero,
/* Here to install a non-global value. */
tree oldlocal = IDENTIFIER_LOCAL_VALUE (name);
tree oldglobal = IDENTIFIER_GLOBAL_VALUE (name);
+
IDENTIFIER_LOCAL_VALUE (name) = x;
/* If this is an extern function declaration, see if we
have a global definition or declaration for the function. */
if (oldlocal == 0
- && DECL_EXTERNAL (x) && !DECL_INLINE (x)
&& oldglobal != 0
&& TREE_CODE (x) == FUNCTION_DECL
- && TREE_CODE (oldglobal) == FUNCTION_DECL)
+ && TREE_CODE (oldglobal) == FUNCTION_DECL
+ && DECL_EXTERNAL (x) && ! DECL_INLINE (x))
{
/* We have one. Their types must agree. */
if (! comptypes (TREE_TYPE (x),
/* Inner extern decl is built-in if global one is. */
if (DECL_BUILT_IN (oldglobal))
{
- DECL_BUILT_IN (x) = DECL_BUILT_IN (oldglobal);
+ DECL_BUILT_IN_CLASS (x) = DECL_BUILT_IN_CLASS (oldglobal);
DECL_FUNCTION_CODE (x) = DECL_FUNCTION_CODE (oldglobal);
}
/* Keep the arg types from a file-scope fcn defn. */
/* No shadow warnings for vars made for inlining. */
&& ! DECL_FROM_INLINE (x))
{
- char *warnstring = 0;
+ char *id = IDENTIFIER_POINTER (name);
if (TREE_CODE (x) == PARM_DECL
&& current_binding_level->level_chain->parm_flag)
but there is no way to tell it's not a definition. */
;
else if (oldlocal != 0 && TREE_CODE (oldlocal) == PARM_DECL)
- warnstring = "declaration of `%s' shadows a parameter";
+ warning ("declaration of `%s' shadows a parameter", id);
else if (oldlocal != 0)
- warnstring = "declaration of `%s' shadows previous local";
+ warning ("declaration of `%s' shadows previous local", id);
else if (IDENTIFIER_GLOBAL_VALUE (name) != 0
&& IDENTIFIER_GLOBAL_VALUE (name) != error_mark_node)
- warnstring = "declaration of `%s' shadows global declaration";
-
- if (warnstring)
- warning (warnstring, IDENTIFIER_POINTER (name));
+ warning ("declaration of `%s' shadows global declaration", id);
}
/* If storing a local value, there may already be one (inherited).
}
/* Keep count of variables in this level with incomplete type. */
- if (TYPE_SIZE (TREE_TYPE (x)) == 0)
+ if (!COMPLETE_TYPE_P (TREE_TYPE (x)))
++b->n_incomplete;
}
/* Only one "implicit declaration" warning per identifier. */
int implicit_warning;
- /* Save the decl permanently so we can warn if definition follows. */
- push_obstacks_nochange ();
- end_temporary_allocation ();
-
/* We used to reuse an old implicit decl here,
but this loses with inline functions because it can clobber
the saved decl chains. */
gen_aux_info_record (decl, 0, 1, 0);
- pop_obstacks ();
-
return decl;
}
/* Return zero if the declaration NEWDECL is valid
when the declaration OLDDECL (assumed to be for the same name)
has already been seen.
- Otherwise return an error message format string with a %s
- where the identifier should go. */
+ Otherwise return 1 if NEWDECL is a redefinition, 2 if it is a redeclaration,
+ and 3 if it is a conflicting declaration. */
-static char *
+static int
redeclaration_error_message (newdecl, olddecl)
tree newdecl, olddecl;
{
return 0;
if (DECL_IN_SYSTEM_HEADER (olddecl) || DECL_IN_SYSTEM_HEADER (newdecl))
return 0;
- return "redefinition of `%s'";
+ return 1;
}
else if (TREE_CODE (newdecl) == FUNCTION_DECL)
{
if (DECL_INITIAL (olddecl) != 0 && DECL_INITIAL (newdecl) != 0
/* However, defining once as extern inline and a second
time in another way is ok. */
- && !(DECL_INLINE (olddecl) && DECL_EXTERNAL (olddecl)
- && !(DECL_INLINE (newdecl) && DECL_EXTERNAL (newdecl))))
- return "redefinition of `%s'";
+ && ! (DECL_INLINE (olddecl) && DECL_EXTERNAL (olddecl)
+ && ! (DECL_INLINE (newdecl) && DECL_EXTERNAL (newdecl))))
+ return 1;
return 0;
}
else if (current_binding_level == global_binding_level)
return 0;
/* Reject two definitions. */
if (DECL_INITIAL (olddecl) != 0 && DECL_INITIAL (newdecl) != 0)
- return "redefinition of `%s'";
+ return 1;
/* Now we have two tentative defs, or one tentative and one real def. */
/* Insist that the linkage match. */
if (TREE_PUBLIC (olddecl) != TREE_PUBLIC (newdecl))
- return "conflicting declarations of `%s'";
+ return 3;
return 0;
}
else if (current_binding_level->parm_flag
be an extern reference to olddecl. */
if (!(DECL_EXTERNAL (newdecl) && DECL_EXTERNAL (olddecl))
&& DECL_CONTEXT (newdecl) == DECL_CONTEXT (olddecl))
- return "redeclaration of `%s'";
+ return 2;
return 0;
}
}
return t;
}
\f
+/* Mark ARG for GC. */
+static void
+mark_binding_level (arg)
+ void *arg;
+{
+ struct binding_level *level = *(struct binding_level **) arg;
+
+ while (level)
+ {
+ ggc_mark_tree (level->names);
+ ggc_mark_tree (level->tags);
+ ggc_mark_tree (level->shadowed);
+ ggc_mark_tree (level->blocks);
+ ggc_mark_tree (level->this_block);
+ ggc_mark_tree (level->parm_order);
+ level = level->level_chain;
+ }
+}
+
/* Create the predefined scalar types of C,
and some nodes representing standard constants (0, 1, (void *) 0).
Initialize the global binding level.
init_decl_processing ()
{
register tree endlink;
- /* Either char* or void*. */
- tree traditional_ptr_type_node;
- /* Data types of memcpy and strlen. */
- tree memcpy_ftype, memset_ftype, strlen_ftype;
- tree void_ftype_any, ptr_ftype_void, ptr_ftype_ptr;
+ tree ptr_ftype_void, ptr_ftype_ptr;
int wchar_type_size;
- tree temp;
tree array_domain_type;
+ tree t;
current_function_decl = NULL;
named_labels = NULL;
pushlevel (0); /* make the binding_level structure for global names */
global_binding_level = current_binding_level;
- /* Define `int' and `char' first so that dbx will output them first. */
+ build_common_tree_nodes (flag_signed_char);
- integer_type_node = make_signed_type (INT_TYPE_SIZE);
+ /* Define `int' and `char' first so that dbx will output them first. */
pushdecl (build_decl (TYPE_DECL, ridpointers[(int) RID_INT],
integer_type_node));
-
- /* Define `char', which is like either `signed char' or `unsigned char'
- but not the same as either. */
-
- char_type_node
- = (flag_signed_char
- ? make_signed_type (CHAR_TYPE_SIZE)
- : make_unsigned_type (CHAR_TYPE_SIZE));
pushdecl (build_decl (TYPE_DECL, get_identifier ("char"),
char_type_node));
-
- long_integer_type_node = make_signed_type (LONG_TYPE_SIZE);
pushdecl (build_decl (TYPE_DECL, get_identifier ("long int"),
long_integer_type_node));
-
- unsigned_type_node = make_unsigned_type (INT_TYPE_SIZE);
pushdecl (build_decl (TYPE_DECL, get_identifier ("unsigned int"),
unsigned_type_node));
-
- long_unsigned_type_node = make_unsigned_type (LONG_TYPE_SIZE);
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));
-
- short_integer_type_node = make_signed_type (SHORT_TYPE_SIZE);
pushdecl (build_decl (TYPE_DECL, get_identifier ("short int"),
short_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));
-
- /* `unsigned long' is the standard type for sizeof.
- Traditionally, use a signed type.
- Note that stddef.h uses `unsigned long',
- and this must agree, even if long and int are the same size. */
- set_sizetype
- (TREE_TYPE (IDENTIFIER_GLOBAL_VALUE (get_identifier (SIZE_TYPE))));
- if (flag_traditional && TREE_UNSIGNED (sizetype))
- set_sizetype (signed_type (sizetype));
-
- ptrdiff_type_node
- = TREE_TYPE (IDENTIFIER_GLOBAL_VALUE (get_identifier (PTRDIFF_TYPE)));
-
- error_mark_node = make_node (ERROR_MARK);
- TREE_TYPE (error_mark_node) = error_mark_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"),
signed_char_type_node));
-
- unsigned_char_type_node = make_unsigned_type (CHAR_TYPE_SIZE);
pushdecl (build_decl (TYPE_DECL, get_identifier ("unsigned char"),
unsigned_char_type_node));
-
- intQI_type_node = make_signed_type (GET_MODE_BITSIZE (QImode));
pushdecl (build_decl (TYPE_DECL, NULL_TREE, intQI_type_node));
-
- intHI_type_node = make_signed_type (GET_MODE_BITSIZE (HImode));
pushdecl (build_decl (TYPE_DECL, NULL_TREE, intHI_type_node));
-
- intSI_type_node = make_signed_type (GET_MODE_BITSIZE (SImode));
pushdecl (build_decl (TYPE_DECL, NULL_TREE, intSI_type_node));
-
- intDI_type_node = make_signed_type (GET_MODE_BITSIZE (DImode));
pushdecl (build_decl (TYPE_DECL, NULL_TREE, intDI_type_node));
-
- intTI_type_node = make_signed_type (GET_MODE_BITSIZE (TImode));
+#if HOST_BITS_PER_WIDE_INT >= 64
pushdecl (build_decl (TYPE_DECL, NULL_TREE, intTI_type_node));
-
- unsigned_intQI_type_node = make_unsigned_type (GET_MODE_BITSIZE (QImode));
+#endif
pushdecl (build_decl (TYPE_DECL, NULL_TREE, unsigned_intQI_type_node));
-
- unsigned_intHI_type_node = make_unsigned_type (GET_MODE_BITSIZE (HImode));
pushdecl (build_decl (TYPE_DECL, NULL_TREE, unsigned_intHI_type_node));
-
- unsigned_intSI_type_node = make_unsigned_type (GET_MODE_BITSIZE (SImode));
pushdecl (build_decl (TYPE_DECL, NULL_TREE, unsigned_intSI_type_node));
-
- unsigned_intDI_type_node = make_unsigned_type (GET_MODE_BITSIZE (DImode));
pushdecl (build_decl (TYPE_DECL, NULL_TREE, unsigned_intDI_type_node));
-
- unsigned_intTI_type_node = make_unsigned_type (GET_MODE_BITSIZE (TImode));
+#if HOST_BITS_PER_WIDE_INT >= 64
pushdecl (build_decl (TYPE_DECL, NULL_TREE, unsigned_intTI_type_node));
+#endif
+
+ /* `unsigned long' is the standard type for sizeof.
+ Traditionally, use a signed type.
+ Note that stddef.h uses `unsigned long',
+ and this must agree, even if long and int are the same size. */
+ t = TREE_TYPE (IDENTIFIER_GLOBAL_VALUE (get_identifier (SIZE_TYPE)));
+ if (flag_traditional && TREE_UNSIGNED (t))
+ t = signed_type (t);
+
+ set_sizetype (t);
+
+ /* Create the widest literal types. */
+ widest_integer_literal_type_node
+ = make_signed_type (HOST_BITS_PER_WIDE_INT * 2);
+ widest_unsigned_literal_type_node
+ = make_unsigned_type (HOST_BITS_PER_WIDE_INT * 2);
+ pushdecl (build_decl (TYPE_DECL, NULL_TREE,
+ widest_integer_literal_type_node));
+ pushdecl (build_decl (TYPE_DECL, NULL_TREE,
+ widest_unsigned_literal_type_node));
+
+ build_common_tree_nodes_2 (flag_short_double);
- float_type_node = make_node (REAL_TYPE);
- TYPE_PRECISION (float_type_node) = FLOAT_TYPE_SIZE;
pushdecl (build_decl (TYPE_DECL, ridpointers[(int) RID_FLOAT],
float_type_node));
- layout_type (float_type_node);
-
- double_type_node = make_node (REAL_TYPE);
- if (flag_short_double)
- TYPE_PRECISION (double_type_node) = FLOAT_TYPE_SIZE;
- else
- TYPE_PRECISION (double_type_node) = DOUBLE_TYPE_SIZE;
pushdecl (build_decl (TYPE_DECL, ridpointers[(int) RID_DOUBLE],
double_type_node));
- layout_type (double_type_node);
-
- long_double_type_node = make_node (REAL_TYPE);
- TYPE_PRECISION (long_double_type_node) = LONG_DOUBLE_TYPE_SIZE;
pushdecl (build_decl (TYPE_DECL, get_identifier ("long double"),
long_double_type_node));
- layout_type (long_double_type_node);
-
- complex_integer_type_node = make_node (COMPLEX_TYPE);
pushdecl (build_decl (TYPE_DECL, get_identifier ("complex int"),
complex_integer_type_node));
- TREE_TYPE (complex_integer_type_node) = integer_type_node;
- layout_type (complex_integer_type_node);
-
- complex_float_type_node = make_node (COMPLEX_TYPE);
pushdecl (build_decl (TYPE_DECL, get_identifier ("complex float"),
complex_float_type_node));
- TREE_TYPE (complex_float_type_node) = float_type_node;
- layout_type (complex_float_type_node);
-
- complex_double_type_node = make_node (COMPLEX_TYPE);
pushdecl (build_decl (TYPE_DECL, get_identifier ("complex double"),
complex_double_type_node));
- TREE_TYPE (complex_double_type_node) = double_type_node;
- layout_type (complex_double_type_node);
-
- complex_long_double_type_node = make_node (COMPLEX_TYPE);
pushdecl (build_decl (TYPE_DECL, get_identifier ("complex long double"),
complex_long_double_type_node));
- TREE_TYPE (complex_long_double_type_node) = long_double_type_node;
- layout_type (complex_long_double_type_node);
+ pushdecl (build_decl (TYPE_DECL,
+ ridpointers[(int) RID_VOID], void_type_node));
- wchar_type_node
- = TREE_TYPE (IDENTIFIER_GLOBAL_VALUE (get_identifier (WCHAR_TYPE)));
+#ifdef MD_INIT_BUILTINS
+ MD_INIT_BUILTINS;
+#endif
+
+ wchar_type_node = get_identifier (flag_short_wchar
+ ? "short unsigned int"
+ : WCHAR_TYPE);
+ wchar_type_node = TREE_TYPE (IDENTIFIER_GLOBAL_VALUE (wchar_type_node));
wchar_type_size = TYPE_PRECISION (wchar_type_node);
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;
- integer_one_node = build_int_2 (1, 0);
- TREE_TYPE (integer_one_node) = integer_type_node;
-
boolean_type_node = integer_type_node;
boolean_true_node = integer_one_node;
boolean_false_node = integer_zero_node;
- size_zero_node = build_int_2 (0, 0);
- TREE_TYPE (size_zero_node) = sizetype;
- size_one_node = build_int_2 (1, 0);
- TREE_TYPE (size_one_node) = sizetype;
-
- void_type_node = make_node (VOID_TYPE);
- pushdecl (build_decl (TYPE_DECL,
- ridpointers[(int) RID_VOID], void_type_node));
- layout_type (void_type_node); /* Uses integer_zero_node */
- /* We are not going to have real types in C with less than byte alignment,
- so we might as well not have any types that claim to have it. */
- TYPE_ALIGN (void_type_node) = BITS_PER_UNIT;
-
- null_pointer_node = build_int_2 (0, 0);
- TREE_TYPE (null_pointer_node) = build_pointer_type (void_type_node);
- layout_type (TREE_TYPE (null_pointer_node));
-
string_type_node = build_pointer_type (char_type_node);
const_string_type_node
= build_pointer_type (build_type_variant (char_type_node, 1, 0));
wchar_array_type_node
= build_array_type (wchar_type_node, array_domain_type);
+ void_list_node = tree_cons (NULL_TREE, void_type_node, NULL_TREE);
+
default_function_type
= build_function_type (integer_type_node, NULL_TREE);
+ ptrdiff_type_node
+ = TREE_TYPE (IDENTIFIER_GLOBAL_VALUE (get_identifier (PTRDIFF_TYPE)));
- ptr_type_node = build_pointer_type (void_type_node);
- const_ptr_type_node
- = build_pointer_type (build_type_variant (void_type_node, 1, 0));
-
- endlink = tree_cons (NULL_TREE, void_type_node, NULL_TREE);
-
- void_ftype_any
- = build_function_type (void_type_node, NULL_TREE);
-
- float_ftype_float
- = build_function_type (float_type_node,
- tree_cons (NULL_TREE, float_type_node, endlink));
-
- double_ftype_double
- = build_function_type (double_type_node,
- tree_cons (NULL_TREE, double_type_node, endlink));
-
- ldouble_ftype_ldouble
- = build_function_type (long_double_type_node,
- tree_cons (NULL_TREE, long_double_type_node,
- endlink));
-
- double_ftype_double_double
- = build_function_type (double_type_node,
- tree_cons (NULL_TREE, double_type_node,
- tree_cons (NULL_TREE,
- double_type_node, endlink)));
-
- int_ftype_int
- = build_function_type (integer_type_node,
- tree_cons (NULL_TREE, integer_type_node, endlink));
-
- long_ftype_long
- = build_function_type (long_integer_type_node,
- tree_cons (NULL_TREE,
- long_integer_type_node, endlink));
-
- void_ftype_ptr_ptr_int
- = build_function_type (void_type_node,
- tree_cons (NULL_TREE, ptr_type_node,
- tree_cons (NULL_TREE, ptr_type_node,
- tree_cons (NULL_TREE,
- integer_type_node,
- endlink))));
-
- int_ftype_cptr_cptr_sizet
- = build_function_type (integer_type_node,
- tree_cons (NULL_TREE, const_ptr_type_node,
- tree_cons (NULL_TREE, const_ptr_type_node,
- tree_cons (NULL_TREE,
- sizetype,
- endlink))));
-
- void_ftype_ptr_int_int
- = build_function_type (void_type_node,
- tree_cons (NULL_TREE, ptr_type_node,
- tree_cons (NULL_TREE, integer_type_node,
- tree_cons (NULL_TREE,
- integer_type_node,
- endlink))));
-
- string_ftype_ptr_ptr /* strcpy prototype */
- = build_function_type (string_type_node,
- tree_cons (NULL_TREE, string_type_node,
- tree_cons (NULL_TREE,
- const_string_type_node,
- endlink)));
-
- int_ftype_string_string /* strcmp prototype */
- = build_function_type (integer_type_node,
- tree_cons (NULL_TREE, const_string_type_node,
- tree_cons (NULL_TREE,
- const_string_type_node,
- endlink)));
-
- strlen_ftype /* strlen prototype */
- = build_function_type (flag_traditional ? integer_type_node : sizetype,
- tree_cons (NULL_TREE, const_string_type_node,
- endlink));
-
- traditional_ptr_type_node
- = (flag_traditional ? string_type_node : ptr_type_node);
-
- memcpy_ftype /* memcpy prototype */
- = build_function_type (traditional_ptr_type_node,
- tree_cons (NULL_TREE, ptr_type_node,
- tree_cons (NULL_TREE, const_ptr_type_node,
- tree_cons (NULL_TREE,
- sizetype,
- endlink))));
-
- memset_ftype /* memset prototype */
- = build_function_type (traditional_ptr_type_node,
- tree_cons (NULL_TREE, ptr_type_node,
- tree_cons (NULL_TREE, integer_type_node,
- tree_cons (NULL_TREE,
- sizetype,
- endlink))));
+ c_common_nodes_and_builtins (0, flag_no_builtin, flag_no_nonansi_builtin);
+ endlink = void_list_node;
ptr_ftype_void = build_function_type (ptr_type_node, endlink);
ptr_ftype_ptr
= build_function_type (ptr_type_node,
tree_cons (NULL_TREE, ptr_type_node, endlink));
- builtin_function ("__builtin_constant_p", default_function_type,
- BUILT_IN_CONSTANT_P, NULL_PTR);
-
- builtin_function ("__builtin_return_address",
- build_function_type (ptr_type_node,
- tree_cons (NULL_TREE,
- unsigned_type_node,
- endlink)),
- BUILT_IN_RETURN_ADDRESS, NULL_PTR);
-
- builtin_function ("__builtin_frame_address",
- build_function_type (ptr_type_node,
- tree_cons (NULL_TREE,
- unsigned_type_node,
- endlink)),
- BUILT_IN_FRAME_ADDRESS, NULL_PTR);
-
builtin_function ("__builtin_aggregate_incoming_address",
build_function_type (ptr_type_node, NULL_TREE),
- BUILT_IN_AGGREGATE_INCOMING_ADDRESS, NULL_PTR);
+ BUILT_IN_AGGREGATE_INCOMING_ADDRESS,
+ BUILT_IN_NORMAL, NULL_PTR);
/* Hooks for the DWARF 2 __throw routine. */
builtin_function ("__builtin_unwind_init",
build_function_type (void_type_node, endlink),
- BUILT_IN_UNWIND_INIT, NULL_PTR);
- builtin_function ("__builtin_fp", ptr_ftype_void, BUILT_IN_FP, NULL_PTR);
- builtin_function ("__builtin_sp", ptr_ftype_void, BUILT_IN_SP, NULL_PTR);
+ BUILT_IN_UNWIND_INIT, BUILT_IN_NORMAL, NULL_PTR);
+ builtin_function ("__builtin_dwarf_cfa", ptr_ftype_void,
+ BUILT_IN_DWARF_CFA, BUILT_IN_NORMAL, NULL_PTR);
builtin_function ("__builtin_dwarf_fp_regnum",
build_function_type (unsigned_type_node, endlink),
- BUILT_IN_DWARF_FP_REGNUM, NULL_PTR);
- builtin_function ("__builtin_dwarf_reg_size", int_ftype_int,
- BUILT_IN_DWARF_REG_SIZE, NULL_PTR);
+ BUILT_IN_DWARF_FP_REGNUM, BUILT_IN_NORMAL, NULL_PTR);
+ builtin_function ("__builtin_init_dwarf_reg_size_table", void_ftype_ptr,
+ BUILT_IN_INIT_DWARF_REG_SIZES, BUILT_IN_NORMAL, NULL_PTR);
builtin_function ("__builtin_frob_return_addr", ptr_ftype_ptr,
- BUILT_IN_FROB_RETURN_ADDR, NULL_PTR);
+ BUILT_IN_FROB_RETURN_ADDR, BUILT_IN_NORMAL, NULL_PTR);
builtin_function ("__builtin_extract_return_addr", ptr_ftype_ptr,
- BUILT_IN_EXTRACT_RETURN_ADDR, NULL_PTR);
- builtin_function ("__builtin_set_return_addr_reg",
- build_function_type (void_type_node,
- tree_cons (NULL_TREE,
- ptr_type_node,
- endlink)),
- BUILT_IN_SET_RETURN_ADDR_REG, NULL_PTR);
- builtin_function ("__builtin_eh_stub_old", ptr_ftype_void,
- BUILT_IN_EH_STUB_OLD, NULL_PTR);
- builtin_function ("__builtin_eh_stub", ptr_ftype_void,
- BUILT_IN_EH_STUB, NULL_PTR);
+ BUILT_IN_EXTRACT_RETURN_ADDR, BUILT_IN_NORMAL, NULL_PTR);
builtin_function
- ("__builtin_set_eh_regs",
+ ("__builtin_eh_return",
build_function_type (void_type_node,
tree_cons (NULL_TREE, ptr_type_node,
tree_cons (NULL_TREE,
type_for_mode (ptr_mode, 0),
- endlink))),
- BUILT_IN_SET_EH_REGS, NULL_PTR);
-
- builtin_function ("__builtin_alloca",
- build_function_type (ptr_type_node,
- tree_cons (NULL_TREE,
- sizetype,
- endlink)),
- BUILT_IN_ALLOCA, "alloca");
- builtin_function ("__builtin_ffs", int_ftype_int, BUILT_IN_FFS, NULL_PTR);
- /* Define alloca, ffs as builtins.
- Declare _exit just to mark it as volatile. */
- if (! flag_no_builtin && !flag_no_nonansi_builtin)
- {
- temp = builtin_function ("alloca",
- build_function_type (ptr_type_node,
- tree_cons (NULL_TREE,
- sizetype,
- endlink)),
- BUILT_IN_ALLOCA, NULL_PTR);
- /* Suppress error if redefined as a non-function. */
- DECL_BUILT_IN_NONANSI (temp) = 1;
- temp = builtin_function ("ffs", int_ftype_int, BUILT_IN_FFS, NULL_PTR);
- /* Suppress error if redefined as a non-function. */
- DECL_BUILT_IN_NONANSI (temp) = 1;
- temp = builtin_function ("_exit", void_ftype_any, NOT_BUILT_IN,
- NULL_PTR);
- TREE_THIS_VOLATILE (temp) = 1;
- TREE_SIDE_EFFECTS (temp) = 1;
- /* Suppress error if redefined as a non-function. */
- DECL_BUILT_IN_NONANSI (temp) = 1;
- }
-
- builtin_function ("__builtin_abs", int_ftype_int, BUILT_IN_ABS, NULL_PTR);
- builtin_function ("__builtin_fabsf", float_ftype_float, BUILT_IN_FABS,
- NULL_PTR);
- builtin_function ("__builtin_fabs", double_ftype_double, BUILT_IN_FABS,
- NULL_PTR);
- builtin_function ("__builtin_fabsl", ldouble_ftype_ldouble, BUILT_IN_FABS,
- NULL_PTR);
- builtin_function ("__builtin_labs", long_ftype_long, BUILT_IN_LABS,
- NULL_PTR);
- builtin_function ("__builtin_saveregs",
- build_function_type (ptr_type_node, NULL_TREE),
- BUILT_IN_SAVEREGS, NULL_PTR);
-/* EXPAND_BUILTIN_VARARGS is obsolete. */
-#if 0
- builtin_function ("__builtin_varargs",
- build_function_type (ptr_type_node,
- tree_cons (NULL_TREE,
- integer_type_node,
- endlink)),
- BUILT_IN_VARARGS, NULL_PTR);
-#endif
- 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, NULL_TREE),
- BUILT_IN_NEXT_ARG, NULL_PTR);
- builtin_function ("__builtin_args_info",
- build_function_type (integer_type_node,
- tree_cons (NULL_TREE,
- integer_type_node,
- endlink)),
- BUILT_IN_ARGS_INFO, NULL_PTR);
-
- /* Untyped call and return. */
- builtin_function ("__builtin_apply_args",
- build_function_type (ptr_type_node, NULL_TREE),
- BUILT_IN_APPLY_ARGS, NULL_PTR);
-
- temp = tree_cons (NULL_TREE,
- build_pointer_type (build_function_type (void_type_node,
- NULL_TREE)),
- tree_cons (NULL_TREE,
- ptr_type_node,
- tree_cons (NULL_TREE,
- sizetype,
- endlink)));
- builtin_function ("__builtin_apply",
- build_function_type (ptr_type_node, temp),
- BUILT_IN_APPLY, NULL_PTR);
- builtin_function ("__builtin_return",
- build_function_type (void_type_node,
- tree_cons (NULL_TREE,
- ptr_type_node,
- endlink)),
- BUILT_IN_RETURN, NULL_PTR);
-
- /* Currently under experimentation. */
- builtin_function ("__builtin_memcpy", memcpy_ftype,
- BUILT_IN_MEMCPY, "memcpy");
- builtin_function ("__builtin_memcmp", int_ftype_cptr_cptr_sizet,
- BUILT_IN_MEMCMP, "memcmp");
- builtin_function ("__builtin_memset", memset_ftype,
- BUILT_IN_MEMSET, "memset");
- builtin_function ("__builtin_strcmp", int_ftype_string_string,
- BUILT_IN_STRCMP, "strcmp");
- builtin_function ("__builtin_strcpy", string_ftype_ptr_ptr,
- BUILT_IN_STRCPY, "strcpy");
- builtin_function ("__builtin_strlen", strlen_ftype,
- BUILT_IN_STRLEN, "strlen");
- builtin_function ("__builtin_sqrtf", float_ftype_float,
- BUILT_IN_FSQRT, "sqrtf");
- builtin_function ("__builtin_fsqrt", double_ftype_double,
- BUILT_IN_FSQRT, "sqrt");
- builtin_function ("__builtin_sqrtl", ldouble_ftype_ldouble,
- BUILT_IN_FSQRT, "sqrtl");
- builtin_function ("__builtin_sinf", float_ftype_float,
- BUILT_IN_SIN, "sinf");
- builtin_function ("__builtin_sin", double_ftype_double,
- BUILT_IN_SIN, "sin");
- builtin_function ("__builtin_sinl", ldouble_ftype_ldouble,
- BUILT_IN_SIN, "sinl");
- builtin_function ("__builtin_cosf", float_ftype_float,
- BUILT_IN_COS, "cosf");
- builtin_function ("__builtin_cos", double_ftype_double,
- BUILT_IN_COS, "cos");
- builtin_function ("__builtin_cosl", ldouble_ftype_ldouble,
- BUILT_IN_COS, "cosl");
- builtin_function ("__builtin_setjmp",
- build_function_type (integer_type_node,
- tree_cons (NULL_TREE,
- ptr_type_node, endlink)),
- BUILT_IN_SETJMP, NULL_PTR);
- builtin_function ("__builtin_longjmp",
- build_function_type
- (void_type_node,
- tree_cons (NULL, ptr_type_node,
- tree_cons (NULL_TREE,
- integer_type_node,
- endlink))),
- BUILT_IN_LONGJMP, NULL_PTR);
- builtin_function ("__builtin_trap",
- build_function_type (void_type_node, endlink),
- BUILT_IN_TRAP, NULL_PTR);
-
- /* In an ANSI C program, it is okay to supply built-in meanings
- for these functions, since applications cannot validly use them
- with any other meaning.
- However, honor the -fno-builtin option. */
- if (!flag_no_builtin)
- {
- builtin_function ("abs", int_ftype_int, BUILT_IN_ABS, NULL_PTR);
- builtin_function ("fabsf", float_ftype_float, BUILT_IN_FABS, NULL_PTR);
- builtin_function ("fabs", double_ftype_double, BUILT_IN_FABS, NULL_PTR);
- builtin_function ("fabsl", ldouble_ftype_ldouble, BUILT_IN_FABS,
- NULL_PTR);
- builtin_function ("labs", long_ftype_long, BUILT_IN_LABS, NULL_PTR);
- builtin_function ("memcpy", memcpy_ftype, BUILT_IN_MEMCPY, NULL_PTR);
- builtin_function ("memcmp", int_ftype_cptr_cptr_sizet, BUILT_IN_MEMCMP,
- NULL_PTR);
- builtin_function ("memset", memset_ftype, BUILT_IN_MEMSET, NULL_PTR);
- builtin_function ("strcmp", int_ftype_string_string, BUILT_IN_STRCMP,
- NULL_PTR);
- builtin_function ("strcpy", string_ftype_ptr_ptr, BUILT_IN_STRCPY,
- NULL_PTR);
- builtin_function ("strlen", strlen_ftype, BUILT_IN_STRLEN, NULL_PTR);
- builtin_function ("sqrtf", float_ftype_float, BUILT_IN_FSQRT, NULL_PTR);
- builtin_function ("sqrt", double_ftype_double, BUILT_IN_FSQRT, NULL_PTR);
- builtin_function ("sqrtl", ldouble_ftype_ldouble, BUILT_IN_FSQRT,
- NULL_PTR);
- builtin_function ("sinf", float_ftype_float, BUILT_IN_SIN, NULL_PTR);
- builtin_function ("sin", double_ftype_double, BUILT_IN_SIN, NULL_PTR);
- builtin_function ("sinl", ldouble_ftype_ldouble, BUILT_IN_SIN, NULL_PTR);
- builtin_function ("cosf", float_ftype_float, BUILT_IN_COS, NULL_PTR);
- builtin_function ("cos", double_ftype_double, BUILT_IN_COS, NULL_PTR);
- builtin_function ("cosl", ldouble_ftype_ldouble, BUILT_IN_COS, NULL_PTR);
-
- /* Declare these functions volatile
- to avoid spurious "control drops through" warnings. */
- /* Don't specify the argument types, to avoid errors
- from certain code which isn't valid in ANSI but which exists. */
- temp = builtin_function ("abort", void_ftype_any, NOT_BUILT_IN,
- NULL_PTR);
- TREE_THIS_VOLATILE (temp) = 1;
- TREE_SIDE_EFFECTS (temp) = 1;
- temp = builtin_function ("exit", void_ftype_any, NOT_BUILT_IN, NULL_PTR);
- TREE_THIS_VOLATILE (temp) = 1;
- TREE_SIDE_EFFECTS (temp) = 1;
- }
-
-#if 0
- /* Support for these has not been written in either expand_builtin
- or build_function_call. */
- builtin_function ("__builtin_div", default_ftype, BUILT_IN_DIV, NULL_PTR);
- builtin_function ("__builtin_ldiv", default_ftype, BUILT_IN_LDIV, NULL_PTR);
- builtin_function ("__builtin_ffloor", double_ftype_double, BUILT_IN_FFLOOR,
- NULL_PTR);
- builtin_function ("__builtin_fceil", double_ftype_double, BUILT_IN_FCEIL,
- NULL_PTR);
- builtin_function ("__builtin_fmod", double_ftype_double_double,
- BUILT_IN_FMOD, NULL_PTR);
- builtin_function ("__builtin_frem", double_ftype_double_double,
- BUILT_IN_FREM, NULL_PTR);
- builtin_function ("__builtin_getexp", double_ftype_double, BUILT_IN_GETEXP,
- NULL_PTR);
- builtin_function ("__builtin_getman", double_ftype_double, BUILT_IN_GETMAN,
- NULL_PTR);
-#endif
+ tree_cons (NULL_TREE,
+ ptr_type_node,
+ endlink)))),
+ BUILT_IN_EH_RETURN, BUILT_IN_NORMAL, NULL_PTR);
pedantic_lvalues = pedantic;
/* Create the global bindings for __FUNCTION__ and __PRETTY_FUNCTION__. */
+ make_fname_decl = c_make_fname_decl;
declare_function_name ();
start_identifier_warnings ();
incomplete_decl_finalize_hook = finish_incomplete_decl;
lang_get_alias_set = c_get_alias_set;
+
+ /* Record our roots. */
+
+ ggc_add_tree_root (c_global_trees, CTI_MAX);
+ ggc_add_tree_root (&named_labels, 1);
+ ggc_add_tree_root (&shadowed_labels, 1);
+ ggc_add_root (¤t_binding_level, 1, sizeof current_binding_level,
+ mark_binding_level);
+ ggc_add_root (&label_level_chain, 1, sizeof label_level_chain,
+ mark_binding_level);
+ ggc_add_tree_root (&static_ctors, 1);
+ ggc_add_tree_root (&static_dtors, 1);
+}
+
+/* Create the VAR_DECL for __FUNCTION__ etc. ID is the name to give the
+ decl, NAME is the initialization string and TYPE_DEP indicates whether
+ NAME depended on the type of the function. As we don't yet implement
+ delayed emission of static data, we mark the decl as emitted
+ so it is not placed in the output. Anything using it must therefore pull
+ out the STRING_CST initializer directly. This does mean that these names
+ are string merging candidates, which C99 does not permit. */
+
+static tree
+c_make_fname_decl (id, name, type_dep)
+ tree id;
+ const char *name;
+ int type_dep ATTRIBUTE_UNUSED;
+{
+ tree decl, type, init;
+ size_t length = strlen (name);
+
+ type = build_array_type
+ (build_qualified_type (char_type_node, TYPE_QUAL_CONST),
+ build_index_type (build_int_2 (length, 0)));
+
+ decl = build_decl (VAR_DECL, id, type);
+ TREE_STATIC (decl) = 1;
+ TREE_READONLY (decl) = 1;
+ TREE_ASM_WRITTEN (decl) = 1;
+ DECL_SOURCE_LINE (decl) = 0;
+ DECL_ARTIFICIAL (decl) = 1;
+ DECL_IN_SYSTEM_HEADER (decl) = 1;
+ DECL_IGNORED_P (decl) = 1;
+ init = build_string (length + 1, name);
+ TREE_TYPE (init) = type;
+ DECL_INITIAL (decl) = init;
+ finish_decl (pushdecl (decl), init, NULL_TREE);
+
+ return decl;
}
/* Return a definition for a builtin function named NAME and whose data type
the name to be called if we can't opencode the function. */
tree
-builtin_function (name, type, function_code, library_name)
- char *name;
+builtin_function (name, type, function_code, class, library_name)
+ const char *name;
tree type;
- enum built_in_function function_code;
- char *library_name;
+ int function_code;
+ enum built_in_class class;
+ const char *library_name;
{
tree decl = build_decl (FUNCTION_DECL, get_identifier (name), type);
DECL_EXTERNAL (decl) = 1;
DECL_ASSEMBLER_NAME (decl) = get_identifier (library_name);
make_decl_rtl (decl, NULL_PTR, 1);
pushdecl (decl);
- if (function_code != NOT_BUILT_IN)
- {
- DECL_BUILT_IN (decl) = 1;
- DECL_FUNCTION_CODE (decl) = function_code;
- }
+ DECL_BUILT_IN_CLASS (decl) = class;
+ DECL_FUNCTION_CODE (decl) = function_code;
+
/* Warn if a function in the namespace for users
is used without an occasion to consider it declared. */
if (name[0] != '_' || name[1] != '_')
do go through here. Structure field declarations are done by
grokfield and not through here. */
-/* Set this to zero to debug not using the temporary obstack
- to parse initializers. */
-int debug_temp_inits = 1;
-
tree
start_decl (declarator, declspecs, initialized, attributes, prefix_attributes)
tree declarator, declspecs;
register tree decl = grokdeclarator (declarator, declspecs,
NORMAL, initialized);
register tree tem;
- int init_written = initialized;
- /* The corresponding pop_obstacks is in finish_decl. */
- push_obstacks_nochange ();
-
- if (warn_main && TREE_CODE (decl) != FUNCTION_DECL
+ if (warn_main > 0 && TREE_CODE (decl) != FUNCTION_DECL
&& !strcmp (IDENTIFIER_POINTER (DECL_NAME (decl)), "main"))
warning_with_decl (decl, "`%s' is usually a function");
default:
/* Don't allow initializations for incomplete types
except for arrays which might be completed by the initialization. */
- if (TYPE_SIZE (TREE_TYPE (decl)) != 0)
+ if (COMPLETE_TYPE_P (TREE_TYPE (decl)))
{
/* A complete type is ok if size is fixed. */
IDENTIFIER_POINTER (DECL_NAME (decl)));
initialized = 0;
}
- else if (TYPE_SIZE (TREE_TYPE (TREE_TYPE (decl))) == 0)
+ else if (!COMPLETE_TYPE_P (TREE_TYPE (TREE_TYPE (decl))))
{
error ("elements of array `%s' have incomplete type",
IDENTIFIER_POINTER (DECL_NAME (decl)));
(which may or may not happen). */
&& DECL_RTL (tem) == 0)
{
- if (TYPE_SIZE (TREE_TYPE (tem)) != 0)
+ if (COMPLETE_TYPE_P (TREE_TYPE (tem)))
expand_decl (tem);
else if (TREE_CODE (TREE_TYPE (tem)) == ARRAY_TYPE
&& DECL_INITIAL (tem) != 0)
expand_decl (tem);
}
- if (init_written)
- {
- /* When parsing and digesting the initializer,
- use temporary storage. Do this even if we will ignore the value. */
- if (current_binding_level == global_binding_level && debug_temp_inits)
- temporary_allocation ();
- }
-
return tem;
}
{
register tree type = TREE_TYPE (decl);
int was_incomplete = (DECL_SIZE (decl) == 0);
- int temporary = allocation_temporary_p ();
char *asmspec = 0;
/* If a name was specified, get the string. */
}
}
- /* Pop back to the obstack that is current for this binding level.
- This is because MAXINDEX, rtl, etc. to be made below
- must go in the permanent obstack. But don't discard the
- temporary data yet. */
- pop_obstacks ();
-#if 0 /* pop_obstacks was near the end; this is what was here. */
- if (current_binding_level == global_binding_level && temporary)
- end_temporary_allocation ();
-#endif
-
/* Deduce size of array from initialization, if not already known */
if (TREE_CODE (type) == ARRAY_TYPE
if (TREE_CODE (decl) == VAR_DECL)
{
- if (DECL_SIZE (decl) == 0
- && TYPE_SIZE (TREE_TYPE (decl)) != 0)
+ if (DECL_SIZE (decl) == 0 && COMPLETE_TYPE_P (TREE_TYPE (decl)))
layout_decl (decl, 0);
if (DECL_SIZE (decl) == 0
name. */
if (TREE_CODE (decl) == FUNCTION_DECL && asmspec)
{
- DECL_BUILT_IN (decl) = 0;
+ DECL_BUILT_IN_CLASS (decl) = NOT_BUILT_IN;
DECL_RTL (decl) = 0;
+ DECL_ASSEMBLER_NAME (decl) = get_identifier (asmspec);
}
/* Output the assembler code and/or RTL code for variables and functions,
if (TREE_CODE (decl) == VAR_DECL || TREE_CODE (decl) == FUNCTION_DECL)
{
- if ((flag_traditional || TREE_PERMANENT (decl))
- && allocation_temporary_p ())
- {
- push_obstacks_nochange ();
- end_temporary_allocation ();
- /* This is a no-op in c-lang.c or something real in objc-actions.c. */
- maybe_objc_check_decl (decl);
- rest_of_decl_compilation (decl, asmspec,
- (DECL_CONTEXT (decl) == 0
- || TREE_ASM_WRITTEN (decl)),
- 0);
- pop_obstacks ();
- }
- else
- {
- /* This is a no-op in c-lang.c or something real in objc-actions.c. */
- maybe_objc_check_decl (decl);
- rest_of_decl_compilation (decl, asmspec, DECL_CONTEXT (decl) == 0,
- 0);
- }
+ /* This is a no-op in c-lang.c or something real in objc-actions.c. */
+ maybe_objc_check_decl (decl);
+ rest_of_decl_compilation (decl, asmspec,
+ (DECL_CONTEXT (decl) == 0
+ || TREE_ASM_WRITTEN (decl)), 0);
+
if (DECL_CONTEXT (decl) != 0)
{
/* Recompute the RTL of a local array now
{
/* This is a no-op in c-lang.c or something real in objc-actions.c. */
maybe_objc_check_decl (decl);
- rest_of_decl_compilation (decl, NULL_PTR, DECL_CONTEXT (decl) == 0,
- 0);
- }
-
- /* ??? 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
- /* DECL_INITIAL is not defined in PARM_DECLs, since it shares
- space with DECL_ARG_TYPE. */
- && TREE_CODE (decl) != PARM_DECL)
- {
- /* We need to remember that this array HAD an initialization,
- but discard the actual temporary nodes,
- since we can't have a permanent node keep pointing to them. */
- /* 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 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) || ITERATOR_P (decl))
- {
- preserve_initializer ();
- /* Hack? Set the permanent bit for something that is permanent,
- but not on the permanent 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);
- }
+ rest_of_decl_compilation (decl, NULL_PTR, DECL_CONTEXT (decl) == 0, 0);
}
-#if 0
- /* Resume permanent allocation, if not within a function. */
- /* The corresponding push_obstacks_nochange is in start_decl,
- and in push_parm_decl and in grokfield. */
- pop_obstacks ();
-#endif
-
- /* 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 (0);
-
/* At the end of a declaration, throw away any variable type sizes
of types defined inside that declaration. There is no use
computing them in the following function definition. */
/* Don't try computing parm sizes now -- wait till fn is called. */
immediate_size_expand = 0;
- /* The corresponding pop_obstacks is in finish_decl. */
- push_obstacks_nochange ();
-
decl = grokdeclarator (TREE_VALUE (TREE_PURPOSE (parm)),
TREE_PURPOSE (TREE_PURPOSE (parm)), PARM, 0);
decl_attributes (decl, TREE_VALUE (TREE_VALUE (parm)),
else if (TREE_CODE (initial_value) == CONSTRUCTOR)
{
tree elts = CONSTRUCTOR_ELTS (initial_value);
- maxindex = size_binop (MINUS_EXPR, integer_zero_node, size_one_node);
+ maxindex = build_int_2 (-1, -1);
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 = fold (build (PLUS_EXPR, integer_type_node,
+ maxindex, integer_one_node));
}
maxindex = copy_node (maxindex);
}
tree type = NULL_TREE;
int longlong = 0;
int constp;
+ int restrictp;
int volatilep;
+ int type_quals = TYPE_UNQUALIFIED;
int inlinep;
int explicit_int = 0;
int explicit_char = 0;
int defaulted_int = 0;
tree typedef_decl = 0;
- char *name;
+ const char *name;
tree typedef_type = 0;
int funcdef_flag = 0;
enum tree_code innermost_code = ERROR_MARK;
if (decl_context == FUNCDEF)
funcdef_flag = 1, decl_context = NORMAL;
- push_obstacks_nochange ();
-
- if (flag_traditional && allocation_temporary_p ())
- end_temporary_allocation ();
-
/* Look inside a declarator for the name being declared
and get it as a string, for an error message. */
{
| (1 << (int) RID_UNSIGNED))))
/* Don't warn about typedef foo = bar. */
&& ! (specbits & (1 << (int) RID_TYPEDEF) && initialized)
- && ! (in_system_header && ! allocation_temporary_p ()))
+ && ! in_system_header)
{
- /* C9x will probably require a diagnostic here.
- For now, issue a warning if -Wreturn-type and this is a function,
- or if -Wimplicit; prefer the former warning since it is more
- explicit. */
+ /* Issue a warning if this is an ISO C 99 program or if -Wreturn-type
+ and this is a function, or if -Wimplicit; prefer the former
+ warning since it is more explicit. */
if ((warn_implicit_int || warn_return_type) && funcdef_flag)
warn_about_return_type = 1;
- else if (warn_implicit_int)
+ else if (warn_implicit_int || flag_isoc99)
warning ("type defaults to `int' in declaration of `%s'", name);
}
type = build_complex_type (type);
}
- /* Set CONSTP if this declaration is `const', whether by
- explicit specification or via a typedef.
- Likewise for VOLATILEP. */
-
+ /* Figure out the type qualifiers for the declaration. There are
+ two ways a declaration can become qualified. One is something
+ like `const int i' where the `const' is explicit. Another is
+ something like `typedef const int CI; CI i' where the type of the
+ declaration contains the `const'. */
constp = !! (specbits & 1 << (int) RID_CONST) + TYPE_READONLY (type);
+ restrictp = !! (specbits & 1 << (int) RID_RESTRICT) + TYPE_RESTRICT (type);
volatilep = !! (specbits & 1 << (int) RID_VOLATILE) + TYPE_VOLATILE (type);
inlinep = !! (specbits & (1 << (int) RID_INLINE));
if (constp > 1)
pedwarn ("duplicate `const'");
+ if (restrictp > 1)
+ pedwarn ("duplicate `restrict'");
if (volatilep > 1)
pedwarn ("duplicate `volatile'");
- if (! flag_gen_aux_info && (TYPE_READONLY (type) || TYPE_VOLATILE (type)))
+ if (! flag_gen_aux_info && (TYPE_QUALS (type)))
type = TYPE_MAIN_VARIANT (type);
+ type_quals = ((constp ? TYPE_QUAL_CONST : 0)
+ | (restrictp ? TYPE_QUAL_RESTRICT : 0)
+ | (volatilep ? TYPE_QUAL_VOLATILE : 0));
/* Warn if two storage classes are given. Default to `auto'. */
;
else
{
- error ((decl_context == FIELD
- ? "storage class specified for structure field `%s'"
- : (decl_context == PARM
- ? "storage class specified for parameter `%s'"
- : "storage class specified for typename")),
- name);
+ switch (decl_context)
+ {
+ case FIELD:
+ error ("storage class specified for structure field `%s'", name);
+ break;
+ case PARM:
+ error ("storage class specified for parameter `%s'", name);
+ break;
+ default:
+ error ("storage class specified for typename");
+ break;
+ }
specbits &= ~ ((1 << (int) RID_TYPEDEF) | (1 << (int) RID_REGISTER)
| (1 << (int) RID_AUTO) | (1 << (int) RID_STATIC)
| (1 << (int) RID_EXTERN));
{
register tree itype = NULL_TREE;
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);
if (type == error_mark_node)
continue;
- /* If this is a block level extern, it must live past the end
- of the function so that we can check it against other extern
- declarations (IDENTIFIER_LIMBO_VALUE). */
- if (extern_ref && allocation_temporary_p ())
- end_temporary_allocation ();
-
/* If size was specified, set ITYPE to a range-type for that size.
Otherwise, ITYPE remains null. finish_decl may figure it out
from an initial value. */
union incomplete (*foo)[4]; */
/* Complain about arrays of incomplete types, except in typedefs. */
- if (TYPE_SIZE (type) == 0
+ if (!COMPLETE_TYPE_P (type)
/* Avoid multiple warnings for nested array types. */
&& TREE_CODE (type) != ARRAY_TYPE
&& !(specbits & (1 << (int) RID_TYPEDEF))
is set correctly. */
type = build_array_type (type, itype);
- if (constp || volatilep)
- type = c_build_type_variant (type, constp, volatilep);
+ if (type_quals)
+ type = c_build_qualified_type (type, type_quals);
#if 0 /* don't clear these; leave them set so that the array type
or the variable is itself const or volatile. */
- constp = 0;
- volatilep = 0;
+ type_quals = TYPE_UNQUALIFIED;
#endif
if (size_varies)
}
else if (TREE_CODE (declarator) == CALL_EXPR)
{
- int extern_ref = (!(specbits & (1 << (int) RID_AUTO))
- || current_binding_level == global_binding_level);
tree arg_types;
/* Declaring a function type.
type = double_type_node;
#endif /* TRADITIONAL_RETURN_FLOAT */
- /* If this is a block level extern, it must live past the end
- of the function so that we can check it against other extern
- declarations (IDENTIFIER_LIMBO_VALUE). */
- if (extern_ref && allocation_temporary_p ())
- end_temporary_allocation ();
-
/* Construct the function type and go to the next
inner layer of declarator. */
only for the CALL_EXPR
closest to the identifier. */
&& TREE_CODE (TREE_OPERAND (declarator, 0)) == IDENTIFIER_NODE);
-#if 0 /* This seems to be false. We turn off temporary allocation
- above in this function if -traditional.
- And this code caused inconsistent results with prototypes:
- callers would ignore them, and pass arguments wrong. */
-
- /* Omit the arg types if -traditional, since the arg types
- and the list links might not be permanent. */
- type = build_function_type (type,
- flag_traditional
- ? NULL_TREE : arg_types);
-#endif
- /* ANSI seems to say that `const int foo ();'
- does not make the function foo const. */
- if (constp || volatilep)
- type = c_build_type_variant (type, constp, volatilep);
- constp = 0;
- volatilep = 0;
+ /* Type qualifiers before the return type of the function
+ qualify the return type, not the function type. */
+ if (type_quals)
+ type = c_build_qualified_type (type, type_quals);
+ type_quals = TYPE_UNQUALIFIED;
type = build_function_type (type, arg_types);
declarator = TREE_OPERAND (declarator, 0);
for the pointer. */
if (pedantic && TREE_CODE (type) == FUNCTION_TYPE
- && (constp || volatilep))
- pedwarn ("ANSI C forbids const or volatile function types");
- if (constp || volatilep)
- type = c_build_type_variant (type, constp, volatilep);
- constp = 0;
- volatilep = 0;
+ && type_quals)
+ pedwarn ("ANSI C forbids qualified function types");
+ if (type_quals)
+ type = c_build_qualified_type (type, type_quals);
+ type_quals = TYPE_UNQUALIFIED;
size_varies = 0;
type = build_pointer_type (type);
{
register tree typemodlist;
int erred = 0;
+
+ constp = 0;
+ volatilep = 0;
+ restrictp = 0;
for (typemodlist = TREE_TYPE (declarator); typemodlist;
typemodlist = TREE_CHAIN (typemodlist))
{
- if (TREE_VALUE (typemodlist) == ridpointers[(int) RID_CONST])
+ tree qualifier = TREE_VALUE (typemodlist);
+
+ if (qualifier == ridpointers[(int) RID_CONST])
constp++;
- else if (TREE_VALUE (typemodlist) == ridpointers[(int) RID_VOLATILE])
+ else if (qualifier == ridpointers[(int) RID_VOLATILE])
volatilep++;
+ else if (qualifier == ridpointers[(int) RID_RESTRICT])
+ restrictp++;
else if (!erred)
{
erred = 1;
pedwarn ("duplicate `const'");
if (volatilep > 1)
pedwarn ("duplicate `volatile'");
+ if (restrictp > 1)
+ pedwarn ("duplicate `restrict'");
+
+ type_quals = ((constp ? TYPE_QUAL_CONST : 0)
+ | (restrictp ? TYPE_QUAL_RESTRICT : 0)
+ | (volatilep ? TYPE_QUAL_VOLATILE : 0));
}
declarator = TREE_OPERAND (declarator, 0);
/* Did array size calculations overflow? */
if (TREE_CODE (type) == ARRAY_TYPE
- && TYPE_SIZE (type)
+ && COMPLETE_TYPE_P (type)
&& TREE_OVERFLOW (TYPE_SIZE (type)))
error ("size of array `%s' is too large", name);
/* Note that the grammar rejects storage classes
in typenames, fields or parameters */
if (pedantic && TREE_CODE (type) == FUNCTION_TYPE
- && (constp || volatilep))
- pedwarn ("ANSI C forbids const or volatile function types");
- if (constp || volatilep)
- type = c_build_type_variant (type, constp, volatilep);
+ && type_quals)
+ pedwarn ("ANSI C forbids qualified function types");
+ if (type_quals)
+ type = c_build_qualified_type (type, type_quals);
decl = build_decl (TYPE_DECL, declarator, type);
if ((specbits & (1 << (int) RID_SIGNED))
|| (typedef_decl && C_TYPEDEF_EXPLICITLY_SIGNED (typedef_decl)))
C_TYPEDEF_EXPLICITLY_SIGNED (decl) = 1;
- pop_obstacks ();
return decl;
}
/* Note that the grammar rejects storage classes
in typenames, fields or parameters */
if (pedantic && TREE_CODE (type) == FUNCTION_TYPE
- && (constp || volatilep))
+ && type_quals)
pedwarn ("ANSI C forbids const or volatile function types");
- if (constp || volatilep)
- type = c_build_type_variant (type, constp, volatilep);
- pop_obstacks ();
+ if (type_quals)
+ type = c_build_qualified_type (type, type_quals);
return type;
}
if (decl_context == PARM)
{
tree type_as_written = type;
- tree main_type;
+ tree promoted_type;
/* A parameter declared as an array of T is really a pointer to T.
One declared as a function is really a pointer to a function. */
{
/* Transfer const-ness of array into that of type pointed to. */
type = TREE_TYPE (type);
- if (constp || volatilep)
- type = c_build_type_variant (type, constp, volatilep);
+ if (type_quals)
+ type = c_build_qualified_type (type, type_quals);
type = build_pointer_type (type);
- volatilep = constp = 0;
+ type_quals = TYPE_UNQUALIFIED;
size_varies = 0;
}
else if (TREE_CODE (type) == FUNCTION_TYPE)
{
- if (pedantic && (constp || volatilep))
- pedwarn ("ANSI C forbids const or volatile function types");
- if (constp || volatilep)
- type = c_build_type_variant (type, constp, volatilep);
+ if (pedantic && type_quals)
+ pedwarn ("ANSI C forbids qualified function types");
+ if (type_quals)
+ type = c_build_qualified_type (type, type_quals);
type = build_pointer_type (type);
- volatilep = constp = 0;
+ type_quals = TYPE_UNQUALIFIED;
}
decl = build_decl (PARM_DECL, declarator, type);
(For example, shorts and chars are passed as ints.)
When there is a prototype, this is overridden later. */
- DECL_ARG_TYPE (decl) = type;
- main_type = (type == error_mark_node
- ? error_mark_node
- : TYPE_MAIN_VARIANT (type));
- if (main_type == float_type_node)
- DECL_ARG_TYPE (decl) = double_type_node;
- /* Don't use TYPE_PRECISION to decide whether to promote,
- because we should convert short if it's the same size as int,
- but we should not convert long if it's the same size as int. */
- else if (TREE_CODE (main_type) != ERROR_MARK
- && C_PROMOTING_INTEGER_TYPE_P (main_type))
+ if (type == error_mark_node)
+ promoted_type = type;
+ else
{
- if (TYPE_PRECISION (type) == TYPE_PRECISION (integer_type_node)
- && TREE_UNSIGNED (type))
- DECL_ARG_TYPE (decl) = unsigned_type_node;
- else
- DECL_ARG_TYPE (decl) = integer_type_node;
+ promoted_type = simple_type_promotes_to (type);
+ if (! promoted_type)
+ promoted_type = type;
}
+ DECL_ARG_TYPE (decl) = promoted_type;
DECL_ARG_TYPE_AS_WRITTEN (decl) = type_as_written;
}
else if (decl_context == FIELD)
error ("field `%s' declared as a function", name);
type = build_pointer_type (type);
}
- else if (TREE_CODE (type) != ERROR_MARK && TYPE_SIZE (type) == 0)
+ else if (TREE_CODE (type) != ERROR_MARK
+ && !COMPLETE_OR_UNBOUND_ARRAY_TYPE_P (type))
{
error ("field `%s' has incomplete type", name);
type = error_mark_node;
}
/* Move type qualifiers down to element of an array. */
- if (TREE_CODE (type) == ARRAY_TYPE && (constp || volatilep))
+ if (TREE_CODE (type) == ARRAY_TYPE && type_quals)
{
- type = build_array_type (c_build_type_variant (TREE_TYPE (type),
- constp, volatilep),
+ type = build_array_type (c_build_qualified_type (TREE_TYPE (type),
+ type_quals),
TYPE_DOMAIN (type));
#if 0 /* Leave the field const or volatile as well. */
- constp = volatilep = 0;
+ type_quals = TYPE_UNQUALIFIED;
#endif
}
decl = build_decl (FIELD_DECL, declarator, type);
&& pedantic)
pedwarn ("invalid storage class for function `%s'", name);
- /* If this is a block level extern, it must live past the end
- of the function so that we can check it against other
- extern declarations (IDENTIFIER_LIMBO_VALUE). */
- if (extern_ref && allocation_temporary_p ())
- end_temporary_allocation ();
-
decl = build_decl (FUNCTION_DECL, declarator, type);
decl = build_decl_attribute_variant (decl, decl_machine_attr);
- if (pedantic && (constp || volatilep)
- && ! DECL_IN_SYSTEM_HEADER (decl))
- pedwarn ("ANSI C forbids const or volatile functions");
+ if (pedantic && type_quals && ! DECL_IN_SYSTEM_HEADER (decl))
+ pedwarn ("ANSI C forbids qualified function types");
if (pedantic
&& TYPE_MAIN_VARIANT (TREE_TYPE (TREE_TYPE (decl))) == void_type_node
- && (TYPE_READONLY (TREE_TYPE (TREE_TYPE (decl)))
- || TYPE_VOLATILE (TREE_TYPE (TREE_TYPE (decl))))
+ && TYPE_QUALS (TREE_TYPE (TREE_TYPE (decl)))
&& ! DECL_IN_SYSTEM_HEADER (decl))
- pedwarn ("ANSI C forbids const or volatile void function return type");
+ pedwarn ("ANSI C forbids qualified void function return type");
- if (volatilep
+ /* GNU C interprets a `volatile void' return type to indicate
+ that the function does not return. */
+ if ((type_quals & TYPE_QUAL_VOLATILE)
&& TREE_TYPE (TREE_TYPE (decl)) != void_type_node)
warning ("`noreturn' function returns non-void value");
int extern_ref = !initialized && (specbits & (1 << (int) RID_EXTERN));
/* Move type qualifiers down to element of an array. */
- if (TREE_CODE (type) == ARRAY_TYPE && (constp || volatilep))
+ if (TREE_CODE (type) == ARRAY_TYPE && type_quals)
{
- type = build_array_type (c_build_type_variant (TREE_TYPE (type),
- constp, volatilep),
+ type = build_array_type (c_build_qualified_type (TREE_TYPE (type),
+ type_quals),
TYPE_DOMAIN (type));
#if 0 /* Leave the variable const or volatile as well. */
- constp = volatilep = 0;
+ type_quals = TYPE_UNQUALIFIED;
#endif
}
- /* If this is a block level extern, it must live past the end
- of the function so that we can check it against other
- extern declarations (IDENTIFIER_LIMBO_VALUE). */
- if (extern_ref && allocation_temporary_p ())
- end_temporary_allocation ();
-
decl = build_decl (VAR_DECL, declarator, type);
if (size_varies)
C_DECL_VARIABLE_SIZE (decl) = 1;
DECL_REGISTER (decl) = 1;
/* Record constancy and volatility. */
+ c_apply_type_quals_to_decl (type_quals, decl);
- if (constp)
- TREE_READONLY (decl) = 1;
- if (volatilep)
- {
- TREE_SIDE_EFFECTS (decl) = 1;
- TREE_THIS_VOLATILE (decl) = 1;
- }
/* If a type has volatile components, it should be stored in memory.
Otherwise, the fact that those components are volatile
will be ignored, and would even crash the compiler. */
if (C_TYPE_FIELDS_VOLATILE (TREE_TYPE (decl)))
mark_addressable (decl);
- pop_obstacks ();
-
return decl;
}
}
{
/* Barf if the parameter itself has an incomplete type. */
tree type = TREE_VALUE (typelt);
- if (TYPE_SIZE (type) == 0)
+ if (!COMPLETE_TYPE_P (type))
{
if (funcdef_flag && DECL_NAME (parm) != 0)
error ("parameter `%s' has incomplete type",
|| TREE_CODE (type) == REFERENCE_TYPE)
type = TREE_TYPE (type);
type = TYPE_MAIN_VARIANT (type);
- if (TYPE_SIZE (type) == 0)
+ if (!COMPLETE_TYPE_P (type))
{
if (DECL_NAME (parm) != 0)
warning ("parameter `%s' points to incomplete type",
typelt = TREE_CHAIN (typelt);
}
- /* Allocate the list of types the way we allocate a type. */
- if (first_parm && ! TREE_PERMANENT (first_parm))
- {
- /* Construct a copy of the list of types
- on the saveable obstack. */
- tree result = NULL;
- for (typelt = first_parm; typelt; typelt = TREE_CHAIN (typelt))
- result = saveable_tree_cons (NULL_TREE, TREE_VALUE (typelt),
- result);
- return nreverse (result);
- }
- else
- /* The list we have is permanent already. */
return first_parm;
}
}
{
parms = NULL_TREE;
storedecls (NULL_TREE);
- return saveable_tree_cons (NULL_TREE, NULL_TREE,
- saveable_tree_cons (NULL_TREE, void_type_node, NULL_TREE));
+ return tree_cons (NULL_TREE, NULL_TREE,
+ tree_cons (NULL_TREE, void_type_node, NULL_TREE));
}
/* Extract enumerator values and other non-parms declared with the parms.
args are passed in their declared types. */
tree type = TREE_TYPE (decl);
DECL_ARG_TYPE (decl) = type;
-#ifdef PROMOTE_PROTOTYPES
- if ((TREE_CODE (type) == INTEGER_TYPE
- || TREE_CODE (type) == ENUMERAL_TYPE)
+ if (PROMOTE_PROTOTYPES
+ && (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
- types = saveable_tree_cons (NULL_TREE, TREE_TYPE (decl), types);
+ types = tree_cons (NULL_TREE, TREE_TYPE (decl), types);
if (TYPE_MAIN_VARIANT (TREE_VALUE (types)) == void_type_node && ! erred
&& DECL_NAME (decl) == 0)
{
}
if (void_at_end)
- return saveable_tree_cons (new_parms, tags,
- nreverse (saveable_tree_cons (NULL_TREE, void_type_node, types)));
+ return tree_cons (new_parms, tags,
+ nreverse (tree_cons (NULL_TREE, void_type_node, types)));
- return saveable_tree_cons (new_parms, tags, nreverse (types));
+ return tree_cons (new_parms, tags, nreverse (types));
}
/* At end of parameter list, warn about any struct, union or enum tags
if (! already)
{
- warning ("its scope is only this definition or declaration,");
- warning ("which is probably not what you want.");
+ warning ("its scope is only this definition or declaration, which is probably not what you want.");
already = 1;
}
}
enum tree_code code;
tree name;
{
- int temporary = allocation_temporary_p ();
-
/* If a cross reference is requested, look up the type
already defined for this tag and return it. */
if (ref)
return ref;
- push_obstacks_nochange ();
-
- if (current_binding_level == global_binding_level && temporary)
- end_temporary_allocation ();
-
/* If no such tag is yet defined, create a forward-reference node
and record it as the "definition".
When a real declaration of this type is found,
pushtag (name, ref);
- pop_obstacks ();
-
return ref;
}
\f
/* Make sure that the tag NAME is defined *in the current binding level*
at least as a forward reference.
- CODE says which kind of tag NAME ought to be.
-
- We also do a push_obstacks_nochange
- whose matching pop is in finish_struct. */
+ CODE says which kind of tag NAME ought to be. */
tree
start_struct (code, name)
register tree ref = 0;
- push_obstacks_nochange ();
- if (current_binding_level == global_binding_level)
- end_temporary_allocation ();
-
if (name != 0)
ref = lookup_tag (code, name, current_binding_level, 1);
if (ref && TREE_CODE (ref) == code)
C_TYPE_BEING_DEFINED (ref) = 1;
TYPE_PACKED (ref) = flag_pack_struct;
if (TYPE_FIELDS (ref))
- error ((code == UNION_TYPE ? "redefinition of `union %s'"
- : "redefinition of `struct %s'"),
+ error ("redefinition of `%s %s'",
+ code == UNION_TYPE ? "union" : "struct",
IDENTIFIER_POINTER (name));
return ref;
tree
grokfield (filename, line, declarator, declspecs, width)
- char *filename;
- int line;
+ const char *filename ATTRIBUTE_UNUSED;
+ int line ATTRIBUTE_UNUSED;
tree declarator, declspecs, width;
{
tree value;
- /* The corresponding pop_obstacks is in finish_decl. */
- push_obstacks_nochange ();
-
value = grokdeclarator (declarator, declspecs, width ? BITFIELD : FIELD, 0);
finish_decl (value, NULL_TREE, NULL_TREE);
return value;
}
\f
-/* Function to help qsort sort FIELD_DECLs by name order. */
-
-static int
-field_decl_cmp (xp, yp)
- const GENERIC_PTR xp;
- const GENERIC_PTR yp;
-{
- tree *x = (tree *)xp, *y = (tree *)yp;
-
- if (DECL_NAME (*x) == DECL_NAME (*y))
- return 0;
- if (DECL_NAME (*x) == NULL)
- return -1;
- if (DECL_NAME (*y) == NULL)
- return 1;
- if (DECL_NAME (*x) < DECL_NAME (*y))
- return -1;
- return 1;
-}
-
/* Fill in the fields of a RECORD_TYPE or UNION_TYPE node, T.
FIELDLIST is a chain of FIELD_DECL nodes for the fields.
- ATTRIBUTES are attributes to be applied to the structure.
-
- We also do a pop_obstacks to match the push in start_struct. */
+ ATTRIBUTES are attributes to be applied to the structure. */
tree
finish_struct (t, fieldlist, attributes)
tree attributes;
{
register tree x;
- int old_momentary;
int toplevel = global_binding_level == current_binding_level;
/* If this type was previously laid out as a forward reference,
if (in_parm_level_p ())
{
if (pedantic)
- pedwarn ((TREE_CODE (t) == UNION_TYPE ? "union defined inside parms"
- : "structure defined inside parms"));
+ pedwarn ("%s defined inside parms",
+ TREE_CODE (t) == UNION_TYPE ? "union" : "structure");
else if (! flag_traditional)
- warning ((TREE_CODE (t) == UNION_TYPE ? "union defined inside parms"
- : "structure defined inside parms"));
+ warning ("%s defined inside parms",
+ TREE_CODE (t) == UNION_TYPE ? "union" : "structure");
}
- old_momentary = suspend_momentary ();
-
if (pedantic)
{
for (x = fieldlist; x; x = TREE_CHAIN (x))
if (x == 0)
pedwarn ("%s has no %smembers",
- (TREE_CODE (t) == UNION_TYPE ? "union" : "structure"),
- (fieldlist ? "named " : ""));
+ TREE_CODE (t) == UNION_TYPE ? "union" : "struct",
+ fieldlist ? "named " : "");
}
/* Install struct as DECL_CONTEXT of each field decl.
- Also process specified field sizes.
- Set DECL_FIELD_SIZE to the specified size, or 0 if none specified.
- The specified size is found in the DECL_INITIAL.
+ Also process specified field sizes,m which is found in the DECL_INITIAL.
Store 0 there, except for ": 0" fields (so we can find them
and delete them, below). */
{
DECL_CONTEXT (x) = t;
DECL_PACKED (x) |= TYPE_PACKED (t);
- DECL_FIELD_SIZE (x) = 0;
/* If any field is const, the structure type is pseudo-const. */
if (TREE_READONLY (x))
constant_expression_warning (DECL_INITIAL (x));
else
{
- error_with_decl (x, "bit-field `%s' width not an integer constant");
+ error_with_decl (x,
+ "bit-field `%s' width not an integer constant");
DECL_INITIAL (x) = NULL;
}
}
error_with_decl (x, "bit-field `%s' has invalid type");
DECL_INITIAL (x) = NULL;
}
+
if (DECL_INITIAL (x) && pedantic
&& TYPE_MAIN_VARIANT (TREE_TYPE (x)) != integer_type_node
&& TYPE_MAIN_VARIANT (TREE_TYPE (x)) != unsigned_type_node
== TYPE_PRECISION (integer_type_node))))
pedwarn_with_decl (x, "bit-field `%s' type invalid in ANSI C");
- /* Detect and ignore out of range field width. */
+ /* Detect and ignore out of range field width and process valid
+ field widths. */
if (DECL_INITIAL (x))
{
- unsigned HOST_WIDE_INT width = TREE_INT_CST_LOW (DECL_INITIAL (x));
-
if (tree_int_cst_sgn (DECL_INITIAL (x)) < 0)
+ error_with_decl (x, "negative width in bit-field `%s'");
+ else if (0 < compare_tree_int (DECL_INITIAL (x),
+ TYPE_PRECISION (TREE_TYPE (x))))
+ pedwarn_with_decl (x, "width of `%s' exceeds its type");
+ else if (integer_zerop (DECL_INITIAL (x)) && DECL_NAME (x) != 0)
+ error_with_decl (x, "zero width for bit-field `%s'");
+ else
{
- DECL_INITIAL (x) = NULL;
- error_with_decl (x, "negative width in bit-field `%s'");
- }
- else if (TREE_INT_CST_HIGH (DECL_INITIAL (x)) != 0
- || width > TYPE_PRECISION (TREE_TYPE (x)))
- {
- DECL_INITIAL (x) = NULL;
- pedwarn_with_decl (x, "width of `%s' exceeds its type");
- }
- else if (width == 0 && DECL_NAME (x) != 0)
- {
- error_with_decl (x, "zero width for bit-field `%s'");
- DECL_INITIAL (x) = NULL;
- }
- }
-
- /* Process valid field width. */
- if (DECL_INITIAL (x))
- {
- register int width = TREE_INT_CST_LOW (DECL_INITIAL (x));
-
- if (TREE_CODE (TREE_TYPE (x)) == ENUMERAL_TYPE
- && (width < min_precision (TYPE_MIN_VALUE (TREE_TYPE (x)),
- TREE_UNSIGNED (TREE_TYPE (x)))
- || width < min_precision (TYPE_MAX_VALUE (TREE_TYPE (x)),
- TREE_UNSIGNED (TREE_TYPE (x)))))
- warning_with_decl (x, "`%s' is narrower than values of its type");
-
- DECL_FIELD_SIZE (x) = width;
- DECL_BIT_FIELD (x) = DECL_C_BIT_FIELD (x) = 1;
- DECL_INITIAL (x) = NULL;
-
- if (width == 0)
- {
- /* field size 0 => force desired amount of alignment. */
+ /* The test above has assured us that TREE_INT_CST_HIGH is 0. */
+ unsigned HOST_WIDE_INT width
+ = TREE_INT_CST_LOW (DECL_INITIAL (x));
+
+ if (TREE_CODE (TREE_TYPE (x)) == ENUMERAL_TYPE
+ && (width < min_precision (TYPE_MIN_VALUE (TREE_TYPE (x)),
+ TREE_UNSIGNED (TREE_TYPE (x)))
+ || (width
+ < min_precision (TYPE_MAX_VALUE (TREE_TYPE (x)),
+ TREE_UNSIGNED (TREE_TYPE (x))))))
+ warning_with_decl (x,
+ "`%s' is narrower than values of its type");
+
+ DECL_SIZE (x) = bitsize_int (width);
+ DECL_BIT_FIELD (x) = DECL_C_BIT_FIELD (x) = 1;
+
+ if (width == 0)
+ {
+ /* field size 0 => force desired amount of alignment. */
#ifdef EMPTY_FIELD_BOUNDARY
- DECL_ALIGN (x) = MAX (DECL_ALIGN (x), EMPTY_FIELD_BOUNDARY);
+ DECL_ALIGN (x) = MAX (DECL_ALIGN (x), EMPTY_FIELD_BOUNDARY);
#endif
#ifdef PCC_BITFIELD_TYPE_MATTERS
- if (PCC_BITFIELD_TYPE_MATTERS)
- DECL_ALIGN (x) = MAX (DECL_ALIGN (x),
- TYPE_ALIGN (TREE_TYPE (x)));
+ if (PCC_BITFIELD_TYPE_MATTERS)
+ DECL_ALIGN (x) = MAX (DECL_ALIGN (x),
+ TYPE_ALIGN (TREE_TYPE (x)));
#endif
+ }
}
}
+
else if (TREE_TYPE (x) != error_mark_node)
{
unsigned int min_align = (DECL_PACKED (x) ? BITS_PER_UNIT
- : TYPE_ALIGN (TREE_TYPE (x)));
+ : TYPE_ALIGN (TREE_TYPE (x)));
+
/* Non-bit-fields are aligned for their type, except packed
fields which require only BITS_PER_UNIT alignment. */
DECL_ALIGN (x) = MAX (DECL_ALIGN (x), min_align);
}
- }
- /* Now DECL_INITIAL is null on all members. */
+ DECL_INITIAL (x) = 0;
+ }
/* Delete all duplicate fields from the fieldlist */
for (x = fieldlist; x && TREE_CHAIN (x);)
layout_type (t);
- /* Delete all zero-width bit-fields from the front of the fieldlist */
- while (fieldlist
- && DECL_INITIAL (fieldlist))
- fieldlist = TREE_CHAIN (fieldlist);
- /* Delete all such members from the rest of the fieldlist */
- for (x = fieldlist; x;)
- {
- if (TREE_CHAIN (x) && DECL_INITIAL (TREE_CHAIN (x)))
- TREE_CHAIN (x) = TREE_CHAIN (TREE_CHAIN (x));
- else x = TREE_CHAIN (x);
- }
+ /* Delete all zero-width bit-fields from the fieldlist */
+ {
+ tree *fieldlistp = &fieldlist;
+ while (*fieldlistp)
+ if (TREE_CODE (*fieldlistp) == FIELD_DECL && DECL_INITIAL (*fieldlistp))
+ *fieldlistp = TREE_CHAIN (*fieldlistp);
+ else
+ fieldlistp = &TREE_CHAIN (*fieldlistp);
+ }
/* Now we have the truly final field list.
Store it in this type and in the variants. */
TYPE_FIELDS (t) = fieldlist;
- /* If there are lots of fields, sort so we can look through them fast.
- We arbitrarily consider 16 or more elts to be "a lot". */
- {
- int len = 0;
-
- for (x = fieldlist; x; x = TREE_CHAIN (x))
- {
- if (len > 15)
- break;
- len += 1;
- }
- if (len > 15)
- {
- tree *field_array;
- char *space;
-
- len += list_length (x);
- /* Use the same allocation policy here that make_node uses, to
- ensure that this lives as long as the rest of the struct decl.
- All decls in an inline function need to be saved. */
- if (allocation_temporary_p ())
- space = savealloc (sizeof (struct lang_type) + len * sizeof (tree));
- else
- space = oballoc (sizeof (struct lang_type) + len * sizeof (tree));
-
- TYPE_LANG_SPECIFIC (t) = (struct lang_type *) space;
- TYPE_LANG_SPECIFIC (t)->len = len;
-
- field_array = &TYPE_LANG_SPECIFIC (t)->elts[0];
- len = 0;
- for (x = fieldlist; x; x = TREE_CHAIN (x))
- field_array[len++] = x;
-
- qsort (field_array, len, sizeof (tree), field_decl_cmp);
- }
- }
-
for (x = TYPE_MAIN_VARIANT (t); x; x = TYPE_NEXT_VARIANT (x))
{
TYPE_FIELDS (x) = TYPE_FIELDS (t);
expand_decl (decl);
--current_binding_level->n_incomplete;
}
- else if (TYPE_SIZE (TREE_TYPE (decl)) == 0
+ else if (!COMPLETE_TYPE_P (TREE_TYPE (decl))
&& TREE_CODE (TREE_TYPE (decl)) == ARRAY_TYPE)
{
tree element = TREE_TYPE (decl);
}
}
- resume_momentary (old_momentary);
-
/* Finish debugging output for this type. */
rest_of_type_compilation (t, toplevel);
- /* The matching push is in start_struct. */
- pop_obstacks ();
-
return t;
}
if (name != 0)
enumtype = lookup_tag (ENUMERAL_TYPE, name, current_binding_level, 1);
- /* The corresponding pop_obstacks is in finish_enum. */
- push_obstacks_nochange ();
- /* If these symbols and types are global, make them permanent. */
- if (current_binding_level == global_binding_level)
- end_temporary_allocation ();
-
if (enumtype == 0 || TREE_CODE (enumtype) != ENUMERAL_TYPE)
{
enumtype = make_node (ENUMERAL_TYPE);
{
register tree pair, tem;
tree minnode = 0, maxnode = 0;
- int lowprec, highprec, precision;
- int toplevel = global_binding_level == current_binding_level;
+ int precision, unsign;
+ int toplevel = (global_binding_level == current_binding_level);
if (in_parm_level_p ())
warning ("enum defined inside parms");
if (values == error_mark_node)
minnode = maxnode = integer_zero_node;
else
- for (pair = values; pair; pair = TREE_CHAIN (pair))
- {
- tree value = TREE_VALUE (pair);
- if (pair == values)
- minnode = maxnode = TREE_VALUE (pair);
- else
- {
- if (tree_int_cst_lt (maxnode, value))
- maxnode = value;
- if (tree_int_cst_lt (value, minnode))
- minnode = value;
- }
- }
-
- TYPE_MIN_VALUE (enumtype) = minnode;
- TYPE_MAX_VALUE (enumtype) = maxnode;
-
- /* An enum can have some negative values; then it is signed. */
- TREE_UNSIGNED (enumtype) = tree_int_cst_sgn (minnode) >= 0;
-
- /* Determine the precision this type needs. */
-
- lowprec = min_precision (minnode, TREE_UNSIGNED (enumtype));
- highprec = min_precision (maxnode, TREE_UNSIGNED (enumtype));
- precision = MAX (lowprec, highprec);
-
- if (TYPE_PACKED (enumtype) || precision > TYPE_PRECISION (integer_type_node))
{
- tree narrowest = type_for_size (precision, 1);
- if (narrowest == 0)
+ minnode = maxnode = TREE_VALUE (values);
+ for (pair = TREE_CHAIN (values); pair; pair = TREE_CHAIN (pair))
{
- warning ("enumeration values exceed range of largest integer");
- narrowest = long_long_integer_type_node;
+ tree value = TREE_VALUE (pair);
+ if (tree_int_cst_lt (maxnode, value))
+ maxnode = value;
+ if (tree_int_cst_lt (value, minnode))
+ minnode = value;
}
+ }
- TYPE_PRECISION (enumtype) = TYPE_PRECISION (narrowest);
+ /* Construct the final type of this enumeration. It is the same
+ as one of the integral types - the narrowest one that fits, except
+ 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));
+ if (!TYPE_PACKED (enumtype))
+ precision = MAX (precision, TYPE_PRECISION (integer_type_node));
+ if (type_for_size (precision, unsign) == 0)
+ {
+ warning ("enumeration values exceed range of largest integer");
+ precision = TYPE_PRECISION (long_long_integer_type_node);
}
- else
- TYPE_PRECISION (enumtype) = TYPE_PRECISION (integer_type_node);
+ TYPE_MIN_VALUE (enumtype) = minnode;
+ TYPE_MAX_VALUE (enumtype) = maxnode;
+ TYPE_PRECISION (enumtype) = precision;
+ TREE_UNSIGNED (enumtype) = unsign;
TYPE_SIZE (enumtype) = 0;
layout_type (enumtype);
if (values != error_mark_node)
{
- /* 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. */
+ /* Change the type of the enumerators to be the enum type. We
+ need to do this irrespective of the size of the enum, for
+ proper type checking. Replace the DECL_INITIALs of the
+ enumerators, and the value slots of the list, with copies
+ that have the enum type; they cannot be modified in place
+ because they may be shared (e.g. integer_zero_node) Finally,
+ change the purpose slots to point to the names of the decls. */
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);
- }
+ tree enu = TREE_PURPOSE (pair);
- /* Replace the decl nodes in VALUES with their names. */
- for (pair = values; pair; pair = TREE_CHAIN (pair))
- TREE_PURPOSE (pair) = DECL_NAME (TREE_PURPOSE (pair));
+ TREE_TYPE (enu) = enumtype;
+ DECL_SIZE (enu) = TYPE_SIZE (enumtype);
+ DECL_SIZE_UNIT (enu) = TYPE_SIZE_UNIT (enumtype);
+ DECL_ALIGN (enu) = TYPE_ALIGN (enumtype);
+ DECL_MODE (enu) = TYPE_MODE (enumtype);
+ DECL_INITIAL (enu) = convert (enumtype, DECL_INITIAL (enu));
+
+ TREE_PURPOSE (pair) = DECL_NAME (enu);
+ TREE_VALUE (pair) = DECL_INITIAL (enu);
+ }
TYPE_VALUES (enumtype) = values;
}
/* Fix up all variant types of this enum type. */
for (tem = TYPE_MAIN_VARIANT (enumtype); tem; tem = TYPE_NEXT_VARIANT (tem))
{
+ if (tem == enumtype)
+ continue;
TYPE_VALUES (tem) = TYPE_VALUES (enumtype);
TYPE_MIN_VALUE (tem) = TYPE_MIN_VALUE (enumtype);
TYPE_MAX_VALUE (tem) = TYPE_MAX_VALUE (enumtype);
/* Finish debugging output for this type. */
rest_of_type_compilation (enumtype, toplevel);
- /* This matches a push in start_enum. */
- pop_obstacks ();
-
return enumtype;
}
TREE_TYPE (value) = type;
pushdecl (decl);
- return saveable_tree_cons (decl, value, NULL_TREE);
+ return tree_cons (decl, value, NULL_TREE);
}
\f
/* Create the FUNCTION_DECL for a function definition.
Returns 1 on success. If the DECLARATOR is not suitable for a function
(it defines a datum instead), we return 0, which tells
- yyparse to report a parse error.
-
- NESTED is nonzero for a function nested within another function. */
+ yyparse to report a parse error. */
int
-start_function (declspecs, declarator, prefix_attributes, attributes, nested)
+start_function (declspecs, declarator, prefix_attributes, attributes)
tree declarator, declspecs, prefix_attributes, attributes;
- int nested;
{
tree decl1, old_decl;
tree restype;
announce_function (decl1);
- if (TYPE_SIZE (TREE_TYPE (TREE_TYPE (decl1))) == 0)
+ if (!COMPLETE_OR_VOID_TYPE_P (TREE_TYPE (TREE_TYPE (decl1))))
{
error ("return-type is an incomplete type");
/* Make it return void instead. */
except for defining how to inline. So set DECL_EXTERNAL in that case. */
DECL_EXTERNAL (decl1) = current_extern_inline;
+#ifdef SET_DEFAULT_DECL_ATTRIBUTES
+ SET_DEFAULT_DECL_ATTRIBUTES (decl1, attributes);
+#endif
+
/* This function exists in static storage.
(This does not mean `static' in the C sense!) */
TREE_STATIC (decl1) = 1;
TREE_PUBLIC (decl1) = 0;
/* Warn for unlikely, improbable, or stupid declarations of `main'. */
- if (warn_main
+ if (warn_main > 0
&& strcmp ("main", IDENTIFIER_POINTER (DECL_NAME (decl1))) == 0)
{
tree args;
DECL_RESULT (current_function_decl)
= build_decl (RESULT_DECL, NULL_TREE, restype);
- if (!nested)
- /* Allocate further tree nodes temporarily during compilation
- of this function only. */
- temporary_allocation ();
-
/* If this fcn was already referenced via a block-scope `extern' decl
(or an implicit decl), propagate certain information about the usage. */
if (TREE_ADDRESSABLE (DECL_ASSEMBLER_NAME (current_function_decl)))
{
if (DECL_NAME (parm) == 0)
error_with_decl (parm, "parameter name omitted");
- else if (TYPE_MAIN_VARIANT (TREE_TYPE (parm)) == void_type_node)
+ else if (TREE_CODE (TREE_TYPE (parm)) != ERROR_MARK
+ && (TYPE_MAIN_VARIANT (TREE_TYPE (parm))
+ == void_type_node))
{
error_with_decl (parm, "parameter `%s' declared void");
/* Change the type to error_mark_node so this parameter
Associate decls with the names and store the decls
into the TREE_PURPOSE slots. */
+ /* We use DECL_WEAK as a flag to show which parameters have been
+ seen already since it is not used on PARM_DECL or CONST_DECL. */
for (parm = parmdecls; parm; parm = TREE_CHAIN (parm))
- DECL_RESULT (parm) = 0;
+ DECL_WEAK (parm) = 0;
for (parm = specparms; parm; parm = TREE_CHAIN (parm))
{
if (TREE_VALUE (parm) == 0)
{
- error_with_decl (fndecl, "parameter name missing from parameter list");
+ error_with_decl (fndecl,
+ "parameter name missing from parameter list");
TREE_PURPOSE (parm) = 0;
continue;
}
/* If declaration already marked, we have a duplicate name.
Complain, and don't use this decl twice. */
- if (found && DECL_RESULT (found) != 0)
+ if (found && DECL_WEAK (found))
{
error_with_decl (found, "multiple parameters named `%s'");
found = 0;
TREE_PURPOSE (parm) = found;
- /* Mark this decl as "already found" -- see test, above.
- It is safe to use DECL_RESULT for this
- since it is not used in PARM_DECLs or CONST_DECLs. */
- DECL_RESULT (found) = error_mark_node;
+ /* Mark this decl as "already found" */
+ DECL_WEAK (found) = 1;
}
/* Put anything which is on the parmdecls chain and which is
else
{
/* Complain about args with incomplete types. */
- if (TYPE_SIZE (TREE_TYPE (parm)) == 0)
+ if (!COMPLETE_TYPE_P (TREE_TYPE (parm)))
{
error_with_decl (parm, "parameter `%s' has incomplete type");
TREE_TYPE (parm) = error_mark_node;
}
- if (DECL_RESULT (parm) == 0)
+ if (! DECL_WEAK (parm))
{
error_with_decl (parm,
"declaration for parameter `%s' but no such parameter");
`int foo(float x) {...}'. This is particularly
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
- || TREE_CODE (TREE_TYPE (parm)) == ENUMERAL_TYPE)
+
+ if (PROMOTE_PROTOTYPES
+ && (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;
-#endif
+
if (pedantic)
{
pedwarn ("promoted argument `%s' doesn't match prototype",
for (parm = DECL_ARGUMENTS (fndecl); parm; parm = TREE_CHAIN (parm))
{
- type = perm_tree_cons (NULL_TREE, DECL_ARG_TYPE (parm),
- NULL_TREE);
+ type = tree_cons (NULL_TREE, DECL_ARG_TYPE (parm), NULL_TREE);
if (last)
TREE_CHAIN (last) = type;
else
actual = type;
last = type;
}
- type = perm_tree_cons (NULL_TREE, void_type_node, NULL_TREE);
+ type = tree_cons (NULL_TREE, void_type_node, NULL_TREE);
if (last)
TREE_CHAIN (last) = type;
else
tree types = 0;
for (parm = parmdecls; parm; parm = TREE_CHAIN (parm))
- DECL_RESULT (parm) = 0;
+ DECL_WEAK (parm) = 0;
for (parm = specparms; parm; parm = TREE_CHAIN (parm))
{
/* If declaration already marked, we have a duplicate name.
Complain, and don't use this decl twice. */
- if (found && DECL_RESULT (found) != 0)
+ if (found && DECL_WEAK (found))
{
error_with_decl (found, "multiple parameters named `%s'");
found = 0;
TREE_PURPOSE (parm) = found;
- /* Mark this decl as "already found" -- see test, above.
- It is safe to use DECL_RESULT for this
- since it is not used in PARM_DECLs or CONST_DECLs. */
- DECL_RESULT (found) = error_mark_node;
+ /* Mark this decl as "already found". */
+ DECL_WEAK (found) = 1;
}
/* Complain about any actual PARM_DECLs not matched with any names. */
TREE_CHAIN (parm) = 0;
/* Complain about args with incomplete types. */
- if (TYPE_SIZE (TREE_TYPE (parm)) == 0)
+ if (!COMPLETE_TYPE_P (TREE_TYPE (parm)))
{
error_with_decl (parm, "parameter `%s' has incomplete type");
TREE_TYPE (parm) = error_mark_node;
}
- if (DECL_RESULT (parm) == 0)
+ if (! DECL_WEAK (parm))
{
error_with_decl (parm,
"declaration for parameter `%s' but no such parameter");
last = TREE_PURPOSE (parm);
TREE_CHAIN (last) = 0;
- types = saveable_tree_cons (NULL_TREE, TREE_TYPE (parm), types);
+ types = tree_cons (NULL_TREE, TREE_TYPE (parm), types);
}
}
if (void_at_end)
- return saveable_tree_cons (parmdecls, nonparms,
- nreverse (saveable_tree_cons (NULL_TREE,
- void_type_node,
- types)));
+ return tree_cons (parmdecls, nonparms,
+ nreverse (tree_cons (NULL_TREE, void_type_node, types)));
- return saveable_tree_cons (parmdecls, nonparms, nreverse (types));
+ return tree_cons (parmdecls, nonparms, nreverse (types));
}
\f
/* Finish up a function declaration and compile that function
if (TYPE_MAIN_VARIANT (TREE_TYPE (TREE_TYPE (fndecl)))
!= integer_type_node)
{
- /* You would expect the sense of this test to be the other way
- around, but if warn_main is set, we will already have warned,
- so this would be a duplicate. This is the warning you get
- in some environments even if you *don't* ask for it, because
- these are environments where it may be more of a problem than
- usual. */
+ /* If warn_main is 1 (-Wmain) or 2 (-Wall), we have already warned.
+ If warn_main is -1 (-Wno-main) we don't want to be warned. */
if (! warn_main)
pedwarn_with_decl (fndecl, "return type of `%s' is not `int'");
}
/* So we can tell if jump_optimize sets it to 1. */
can_reach_end = 0;
+ /* If this is a nested function, protect the local variables in the stack
+ above us from being collected while we're compiling this function. */
+ if (nested)
+ ggc_push_context ();
+
/* Run the optimizers and output the assembler code for this function. */
rest_of_compilation (fndecl);
+ /* Undo the GC context switch. */
+ if (nested)
+ ggc_pop_context ();
+
current_function_returns_null |= can_reach_end;
+ if (warn_missing_noreturn
+ && !TREE_THIS_VOLATILE (fndecl)
+ && !current_function_returns_null
+ && !current_function_returns_value)
+ warning ("function might be possible candidate for attribute `noreturn'");
+
if (TREE_THIS_VOLATILE (fndecl) && current_function_returns_null)
warning ("`noreturn' function does return");
else if (warn_return_type && can_reach_end
if (warn_larger_than && !DECL_EXTERNAL (fndecl) && TREE_TYPE (fndecl))
{
- register tree ret_type = TREE_TYPE (TREE_TYPE (fndecl));
+ tree ret_type = TREE_TYPE (TREE_TYPE (fndecl));
- if (ret_type)
+ if (ret_type && TREE_CODE (TYPE_SIZE_UNIT (ret_type)) == INTEGER_CST
+ && 0 < compare_tree_int (TYPE_SIZE_UNIT (ret_type),
+ larger_than_size))
{
- register tree ret_type_size = TYPE_SIZE (ret_type);
+ unsigned int size_as_int
+ = TREE_INT_CST_LOW (TYPE_SIZE_UNIT (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);
- }
+ if (compare_tree_int (TYPE_SIZE_UNIT (ret_type), size_as_int) == 0)
+ warning_with_decl (fndecl,
+ "size of return value of `%s' is %u bytes",
+ size_as_int);
+ else
+ warning_with_decl (fndecl,
+ "size of return value of `%s' is larger than %d bytes",
+ larger_than_size);
}
}
- /* Free all the tree nodes making up this function. */
- /* Switch back to allocating nodes permanently
- until we start another function. */
- if (! nested)
- permanent_allocation (1);
-
if (DECL_SAVED_INSNS (fndecl) == 0 && ! nested)
{
- /* Stop pointing to the local nodes about to be freed. */
- /* 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. */
- /* If rest_of_compilation set this to 0, leave it 0. */
+ /* Stop pointing to the local nodes about to be freed.
+ 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.
+ 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;
}
{
#ifndef ASM_OUTPUT_CONSTRUCTOR
if (! flag_gnu_linker)
- static_ctors = perm_tree_cons (NULL_TREE, fndecl, static_ctors);
+ static_ctors = tree_cons (NULL_TREE, fndecl, static_ctors);
else
#endif
- assemble_constructor (IDENTIFIER_POINTER (DECL_NAME (fndecl)));
+ assemble_constructor (IDENTIFIER_POINTER (DECL_ASSEMBLER_NAME (fndecl)));
+
}
if (DECL_STATIC_DESTRUCTOR (fndecl))
{
#ifndef ASM_OUTPUT_DESTRUCTOR
if (! flag_gnu_linker)
- static_dtors = perm_tree_cons (NULL_TREE, fndecl, static_dtors);
+ static_dtors = tree_cons (NULL_TREE, fndecl, static_dtors);
else
#endif
- assemble_destructor (IDENTIFIER_POINTER (DECL_NAME (fndecl)));
+ assemble_destructor (IDENTIFIER_POINTER (DECL_ASSEMBLER_NAME (fndecl)));
}
if (! nested)
that keep track of the progress of compilation of the current function.
Used for nested functions. */
-struct c_function
+struct language_function
{
- struct c_function *next;
tree named_labels;
tree shadowed_labels;
int returns_value;
struct binding_level *binding_level;
};
-struct c_function *c_function_chain;
-
/* Save and reinitialize the variables
used during compilation of a C function. */
void
-push_c_function_context ()
+push_c_function_context (f)
+ struct function *f;
{
- struct c_function *p
- = (struct c_function *) xmalloc (sizeof (struct c_function));
-
- if (pedantic)
- pedwarn ("ANSI C forbids nested functions");
-
- push_function_context ();
-
- p->next = c_function_chain;
- c_function_chain = p;
+ struct language_function *p;
+ p = (struct language_function *) xmalloc (sizeof (struct language_function));
+ f->language = p;
p->named_labels = named_labels;
p->shadowed_labels = shadowed_labels;
/* Restore the variables used during compilation of a C function. */
void
-pop_c_function_context ()
+pop_c_function_context (f)
+ struct function *f;
{
- struct c_function *p = c_function_chain;
+ struct language_function *p = f->language;
tree link;
/* Bring back all the labels that were shadowed. */
DECL_ARGUMENTS (current_function_decl) = 0;
}
- pop_function_context ();
-
- c_function_chain = p->next;
-
named_labels = p->named_labels;
shadowed_labels = p->shadowed_labels;
current_function_returns_value = p->returns_value;
current_binding_level = p->binding_level;
free (p);
+ f->language = 0;
+}
+
+/* Mark the language specific parts of F for GC. */
+void
+mark_c_function_context (f)
+ struct function *f;
+{
+ struct language_function *p = f->language;
+
+ if (p == 0)
+ return;
+
+ ggc_mark_tree (p->shadowed_labels);
+ ggc_mark_tree (p->named_labels);
+ mark_binding_level (&p->binding_level);
}
/* integrate_decl_tree calls this function, but since we don't use the
tree node ATTRIBUTE_UNUSED;
{
}
+
+/* Mark ARG for GC. */
+void
+lang_mark_false_label_stack (arg)
+ struct label_node *arg;
+{
+ /* C doesn't use false_label_stack. It better be NULL. */
+ if (arg != NULL)
+ abort();
+}
+
+/* Mark the language specific bits in T for GC. */
+void
+lang_mark_tree (t)
+ tree t;
+{
+ if (TREE_CODE (t) == IDENTIFIER_NODE)
+ {
+ struct lang_identifier *i = (struct lang_identifier *) t;
+ ggc_mark_tree (i->global_value);
+ ggc_mark_tree (i->local_value);
+ ggc_mark_tree (i->label_value);
+ ggc_mark_tree (i->implicit_decl);
+ ggc_mark_tree (i->error_locus);
+ ggc_mark_tree (i->limbo_value);
+ }
+ else if (TYPE_P (t) && TYPE_LANG_SPECIFIC (t))
+ ggc_mark (TYPE_LANG_SPECIFIC (t));
+}