X-Git-Url: http://git.sourceforge.jp/view?a=blobdiff_plain;f=gcc%2Fc-decl.c;h=c199f6d095443839c8843715ff31d38c47753336;hb=6f8178291d6a29282c4da1aedcf451c1172945a0;hp=f465875a909cf2554a1b1798be9082ae94f2bf0f;hpb=4edb36051b0ccdda4c1ea67938e3cad5b8e194c1;p=pf3gnuchains%2Fgcc-fork.git diff --git a/gcc/c-decl.c b/gcc/c-decl.c index f465875a909..c199f6d0954 100644 --- a/gcc/c-decl.c +++ b/gcc/c-decl.c @@ -1,6 +1,6 @@ /* Process declarations and variables for C compiler. Copyright (C) 1988, 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999, 2000, - 2001, 2002 Free Software Foundation, Inc. + 2001, 2002, 2003 Free Software Foundation, Inc. This file is part of GCC. @@ -28,6 +28,8 @@ Software Foundation, 59 Temple Place - Suite 330, Boston, MA #include "config.h" #include "system.h" +#include "coretypes.h" +#include "tm.h" #include "intl.h" #include "tree.h" #include "tree-inline.h" @@ -37,7 +39,6 @@ Software Foundation, 59 Temple Place - Suite 330, Boston, MA #include "output.h" #include "expr.h" #include "c-tree.h" -#include "c-lex.h" #include "toplev.h" #include "ggc.h" #include "tm_p.h" @@ -46,6 +47,11 @@ Software Foundation, 59 Temple Place - Suite 330, Boston, MA #include "debug.h" #include "timevar.h" #include "c-common.h" +#include "c-pragma.h" +#include "cgraph.h" +#include "hashtab.h" +#include "libfuncs.h" +#include "except.h" /* In grokdeclarator, distinguish syntactic contexts of declarators. */ enum decl_context @@ -62,8 +68,7 @@ enum decl_context tree pending_invalid_xref; /* File and line to appear in the eventual error message. */ -const char *pending_invalid_xref_file; -int pending_invalid_xref_line; +location_t pending_invalid_xref_location; /* While defining an enum type, this is 1 plus the last enumerator constant value. Note that will do not have to save this or `enum_overflow' @@ -98,31 +103,29 @@ static tree current_function_parm_tags; /* Similar, for the file and line that the prototype came from if this is an old-style definition. */ -static const char *current_function_prototype_file; -static int current_function_prototype_line; +static location_t current_function_prototype_locus; /* The current statement tree. */ -static struct stmt_tree_s c_stmt_tree; +static GTY(()) struct stmt_tree_s c_stmt_tree; /* The current scope statement stack. */ -static tree c_scope_stmt_stack; +static GTY(()) tree c_scope_stmt_stack; /* A list (chain of TREE_LIST nodes) of all LABEL_DECLs in the function that have names. Here so we can clear out their names' definitions at the end of the function. */ -static tree named_labels; +static GTY(()) tree named_labels; /* A list of LABEL_DECLs from outer contexts that are currently shadowed. */ -static tree shadowed_labels; +static GTY(()) tree shadowed_labels; -/* Nonzero when store_parm_decls is called indicates a varargs function. - Value not meaningful after store_parm_decls. */ - -static int c_function_varargs; +/* A list of external DECLs that appeared at block scope when there was + some other global meaning for that identifier. */ +static GTY(()) tree truly_local_externals; /* Set to 0 at beginning of a function definition, set to 1 if a return statement that specifies a return value is seen. */ @@ -161,10 +164,7 @@ static int current_extern_inline; * the current one out to the global one. */ -/* Note that the information in the `names' component of the global contour - is duplicated in the IDENTIFIER_GLOBAL_VALUEs of all identifiers. */ - -struct binding_level +struct binding_level GTY(()) { /* A chain of _DECL nodes for all variables, constants, functions, and typedef types. These are in the reverse of the order supplied. @@ -179,35 +179,34 @@ struct binding_level */ tree tags; - /* For each level, a list of shadowed outer-level local definitions + /* For each level, a list of shadowed outer-level definitions to be restored when this level is popped. Each link is a TREE_LIST whose TREE_PURPOSE is an identifier and whose TREE_VALUE is its old definition (a kind of ..._DECL node). */ tree shadowed; + /* For each level, a list of shadowed outer-level tag definitions + to be restored when this level is popped. + Each link is a TREE_LIST whose TREE_PURPOSE is an identifier and + whose TREE_VALUE is its old definition (a kind of ..._TYPE node). */ + tree shadowed_tags; + /* For each level (except not the global one), a chain of BLOCK nodes for all the levels that were entered and exited one level down. */ tree blocks; - /* The BLOCK node for this level, if one has been preallocated. - If 0, the BLOCK is allocated (if needed) when the level is popped. */ - tree this_block; - /* The binding level which this one is contained in (inherits from). */ struct binding_level *level_chain; - /* Nonzero for the level that holds the parameters of a function. */ + /* Nonzero if we are currently filling this level with parameter + declarations. */ char parm_flag; - /* Nonzero if this level "doesn't exist" for tags. */ - char tag_transparent; - - /* Nonzero if sublevels of this level "don't exist" for tags. - This is set in the parm level of a function definition - while reading the function body, so that the outermost block - of the function body will be tag-transparent. */ - char subblocks_tag_transparent; + /* Nonzero if this is the outermost block scope of a function body. + This scope contains both the parameters and the local variables + declared in the outermost block. */ + char function_body; /* Nonzero means make a BLOCK for this level regardless of all else. */ char keep; @@ -215,9 +214,9 @@ struct binding_level /* Nonzero means make a BLOCK if this level has any subblocks. */ char keep_if_subblocks; - /* Number of decls in `names' that have incomplete - structure or union types. */ - int n_incomplete; + /* List of decls in `names' that have incomplete structure or + union types. */ + tree incomplete_list; /* A list of decls giving the (reversed) specified order of parms, not including any forward-decls in the parmlist. @@ -229,23 +228,17 @@ struct binding_level /* The binding level currently in effect. */ -static struct binding_level *current_binding_level; +static GTY(()) struct binding_level *current_binding_level; /* A chain of binding_level structures awaiting reuse. */ -static struct binding_level *free_binding_level; +static GTY((deletable (""))) struct binding_level *free_binding_level; /* The outermost binding level, for names of file scope. This is created when the compiler is started and exists through the entire run. */ -static struct binding_level *global_binding_level; - -/* Binding level structures are initialized by copying this one. */ - -static struct binding_level clear_binding_level - = {NULL, NULL, NULL, NULL, NULL, NULL_BINDING_LEVEL, 0, 0, 0, 0, 0, 0, - NULL}; +static GTY(()) struct binding_level *global_binding_level; /* Nonzero means unconditionally make a BLOCK for the next level pushed. */ @@ -262,7 +255,7 @@ static int keep_next_if_subblocks; saved values of named_labels and shadowed_labels for a label binding level outside the current one. */ -static struct binding_level *label_level_chain; +static GTY(()) struct binding_level *label_level_chain; /* Functions called automatically at the beginning and end of execution. */ @@ -270,177 +263,31 @@ tree static_ctors, static_dtors; /* Forward declarations. */ -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, int)); -static void c_expand_body PARAMS ((tree, int, int)); -static void warn_if_shadowing PARAMS ((tree, tree)); +static struct binding_level *make_binding_level (void); +static void pop_binding_level (struct binding_level **); +static int duplicate_decls (tree, tree, int); +static int redeclaration_error_message (tree, tree); +static void implicit_decl_warning (tree); +static void storedecls (tree); +static void storetags (tree); +static tree lookup_tag (enum tree_code, tree, int); +static tree lookup_name_current_level (tree); +static tree grokdeclarator (tree, tree, enum decl_context, int); +static tree grokparms (tree, int); +static void layout_array_type (tree); +static tree c_make_fname_decl (tree, int); +static void c_expand_body_1 (tree, int); +static tree any_external_decl (tree); +static void record_external_decl (tree); +static void warn_if_shadowing (tree, tree); +static void clone_underlying_type (tree); +static bool flexible_array_type_p (tree); -/* C-specific option variables. */ - -/* Nonzero means allow type mismatches in conditional expressions; - just make their values `void'. */ - -int flag_cond_mismatch; - -/* Nonzero means don't recognize the keyword `asm'. */ - -int flag_no_asm; - -/* Nonzero means enable C89 Amendment 1 features. */ - -int flag_isoc94 = 0; - -/* 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; - -/* Nonzero means add default format_arg attributes for functions not - in ISO C. */ - -int flag_noniso_default_format_attributes = 1; - -/* Nonzero means to treat bitfields as signed unless they say `unsigned'. */ - -int flag_signed_bitfields = 1; -int explicit_flag_signed_bitfields = 0; - -/* Nonzero means warn about use of implicit int. */ - -int warn_implicit_int; - -/* Nonzero means warn about usage of long long when `-pedantic'. */ - -int warn_long_long = 1; - -/* Nonzero means message about use of implicit function declarations; - 1 means warning; 2 means error. */ - -int mesg_implicit_function_declaration = -1; - -/* Nonzero means give string constants the type `const char *' - to get extra warnings from them. These warnings will be too numerous - to be useful, except in thoroughly ANSIfied programs. */ - -int flag_const_strings; - -/* Nonzero means warn about pointer casts that can drop a type qualifier - from the pointer target type. */ - -int warn_cast_qual; - -/* Nonzero means warn when casting a function call to a type that does - not match the return type (e.g. (float)sqrt() or (anything*)malloc() - when there is no previous declaration of sqrt or malloc. */ - -int warn_bad_function_cast; - -/* Warn about functions which might be candidates for format attributes. */ - -int warn_missing_format_attribute; - -/* Warn about traditional constructs whose meanings changed in ANSI C. */ - -int warn_traditional; - -/* Nonzero means warn about sizeof(function) or addition/subtraction - of function pointers. */ - -int warn_pointer_arith; - -/* Nonzero means warn for non-prototype function decls - or non-prototyped defs without previous prototype. */ - -int warn_strict_prototypes; - -/* Nonzero means warn for any global function def - without separate previous prototype decl. */ - -int warn_missing_prototypes; - -/* Nonzero means warn for any global function def - without separate previous decl. */ - -int warn_missing_declarations; - -/* Nonzero means warn about multiple (redundant) decls for the same single - variable or function. */ - -int warn_redundant_decls = 0; - -/* Nonzero means warn about extern declarations of objects not at - file-scope level and about *all* declarations of functions (whether - extern or static) not at file-scope level. Note that we exclude - implicit function declarations. To get warnings about those, use - -Wimplicit. */ - -int warn_nested_externs = 0; - -/* Warn about a subscript that has type char. */ - -int warn_char_subscripts = 0; - -/* Warn if a type conversion is done that might have confusing results. */ - -int warn_conversion; - -/* Warn if adding () is suggested. */ - -int warn_parentheses; - -/* Warn if initializer is not completely bracketed. */ - -int warn_missing_braces; - -/* Warn if main is suspicious. */ - -int warn_main; - -/* Warn about #pragma directives that are not recognised. */ - -int warn_unknown_pragmas = 0; /* Tri state variable. */ - -/* Warn about comparison of signed and unsigned values. - If -1, neither -Wsign-compare nor -Wno-sign-compare has been specified. */ - -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; - -/* Nonzero means `$' can be in an identifier. */ - -#ifndef DOLLARS_IN_IDENTIFIERS -#define DOLLARS_IN_IDENTIFIERS 1 -#endif -int dollars_in_ident = DOLLARS_IN_IDENTIFIERS; - /* States indicating how grokdeclarator() should handle declspecs marked with __attribute__((deprecated)). An object declared as __attribute__((deprecated)) suppresses warnings of uses of other deprecated items. */ - + enum deprecated_states { DEPRECATED_NORMAL, DEPRECATED_SUPPRESS @@ -448,359 +295,18 @@ enum deprecated_states { static enum deprecated_states deprecated_state = DEPRECATED_NORMAL; -/* Decode the string P as a language-specific option for C. - Return the number of strings consumed. Should not complain - if it does not recognise the option. */ - -int -c_decode_option (argc, argv) - int argc ATTRIBUTE_UNUSED; - char **argv; -{ - int strings_processed; - char *p = argv[0]; - - strings_processed = cpp_handle_option (parse_in, argc, argv, 0); - - if (!strcmp (p, "-fhosted") || !strcmp (p, "-fno-freestanding")) - { - flag_hosted = 1; - flag_no_builtin = 0; - } - else if (!strcmp (p, "-ffreestanding") || !strcmp (p, "-fno-hosted")) - { - flag_hosted = 0; - flag_no_builtin = 1; - /* warn_main will be 2 if set by -Wall, 1 if set by -Wmain */ - if (warn_main == 2) - warn_main = 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 *const argstart = &p[5]; - - if (!strcmp (argstart, "iso9899:1990") - || !strcmp (argstart, "c89")) - { - iso_1990: - flag_isoc94 = 0; - iso_1994: - flag_writable_strings = 0; - flag_no_asm = 1; - flag_no_nonansi_builtin = 1; - flag_noniso_default_format_attributes = 0; - flag_isoc99 = 0; - } - else if (!strcmp (argstart, "iso9899:199409")) - { - flag_isoc94 = 1; - goto iso_1994; - } - else if (!strcmp (argstart, "iso9899:199x") - || !strcmp (argstart, "iso9899:1999") - || !strcmp (argstart, "c9x") - || !strcmp (argstart, "c99")) - { - flag_writable_strings = 0; - flag_no_asm = 1; - flag_no_nonansi_builtin = 1; - flag_noniso_default_format_attributes = 0; - flag_isoc99 = 1; - flag_isoc94 = 1; - } - else if (!strcmp (argstart, "gnu89")) - { - flag_writable_strings = 0; - flag_no_asm = 0; - flag_no_nonansi_builtin = 0; - flag_noniso_default_format_attributes = 1; - flag_isoc99 = 0; - flag_isoc94 = 0; - } - else if (!strcmp (argstart, "gnu9x") || !strcmp (argstart, "gnu99")) - { - flag_writable_strings = 0; - flag_no_asm = 0; - flag_no_nonansi_builtin = 0; - flag_noniso_default_format_attributes = 1; - flag_isoc99 = 1; - flag_isoc94 = 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")) - dollars_in_ident = 0; - else if (!strcmp (p, "-fsigned-char")) - flag_signed_char = 1; - else if (!strcmp (p, "-funsigned-char")) - flag_signed_char = 0; - else if (!strcmp (p, "-fno-signed-char")) - flag_signed_char = 0; - else if (!strcmp (p, "-fno-unsigned-char")) - flag_signed_char = 1; - else if (!strcmp (p, "-fsigned-bitfields") - || !strcmp (p, "-fno-unsigned-bitfields")) - { - flag_signed_bitfields = 1; - explicit_flag_signed_bitfields = 1; - } - else if (!strcmp (p, "-funsigned-bitfields") - || !strcmp (p, "-fno-signed-bitfields")) - { - flag_signed_bitfields = 0; - explicit_flag_signed_bitfields = 1; - } - else if (!strcmp (p, "-fshort-enums")) - 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_cond_mismatch = 0; - else if (!strcmp (p, "-fshort-double")) - flag_short_double = 1; - else if (!strcmp (p, "-fno-short-double")) - flag_short_double = 0; - else if (!strcmp (p, "-fasm")) - flag_no_asm = 0; - else if (!strcmp (p, "-fno-asm")) - flag_no_asm = 1; - else if (!strcmp (p, "-fbuiltin")) - flag_no_builtin = 0; - else if (!strcmp (p, "-fno-builtin")) - flag_no_builtin = 1; - else if (!strncmp (p, "-fno-builtin-", strlen ("-fno-builtin-"))) - disable_builtin_function (p + strlen ("-fno-builtin-")); - else if (p[0] == '-' && p[1] == 'f' && dump_switch_p (p + 2)) - ; - else if (!strcmp (p, "-ansi")) - goto iso_1990; - else if (!strcmp (p, "-Werror-implicit-function-declaration")) - mesg_implicit_function_declaration = 2; - else if (!strcmp (p, "-Wimplicit-function-declaration")) - mesg_implicit_function_declaration = 1; - else if (!strcmp (p, "-Wno-implicit-function-declaration")) - mesg_implicit_function_declaration = 0; - else if (!strcmp (p, "-Wimplicit-int")) - warn_implicit_int = 1; - else if (!strcmp (p, "-Wno-implicit-int")) - warn_implicit_int = 0; - else if (!strcmp (p, "-Wimplicit")) - { - warn_implicit_int = 1; - if (mesg_implicit_function_declaration != 2) - mesg_implicit_function_declaration = 1; - } - else if (!strcmp (p, "-Wno-implicit")) - warn_implicit_int = 0, mesg_implicit_function_declaration = 0; - else if (!strcmp (p, "-Wlong-long")) - warn_long_long = 1; - else if (!strcmp (p, "-Wno-long-long")) - warn_long_long = 0; - else if (!strcmp (p, "-Wwrite-strings")) - flag_const_strings = 1; - else if (!strcmp (p, "-Wno-write-strings")) - flag_const_strings = 0; - else if (!strcmp (p, "-Wcast-qual")) - warn_cast_qual = 1; - else if (!strcmp (p, "-Wno-cast-qual")) - warn_cast_qual = 0; - else if (!strcmp (p, "-Wbad-function-cast")) - warn_bad_function_cast = 1; - else if (!strcmp (p, "-Wno-bad-function-cast")) - warn_bad_function_cast = 0; - else if (!strcmp (p, "-Wno-missing-noreturn")) - warn_missing_noreturn = 0; - else if (!strcmp (p, "-Wmissing-format-attribute")) - warn_missing_format_attribute = 1; - else if (!strcmp (p, "-Wno-missing-format-attribute")) - warn_missing_format_attribute = 0; - else if (!strcmp (p, "-Wpointer-arith")) - warn_pointer_arith = 1; - else if (!strcmp (p, "-Wno-pointer-arith")) - warn_pointer_arith = 0; - else if (!strcmp (p, "-Wstrict-prototypes")) - warn_strict_prototypes = 1; - else if (!strcmp (p, "-Wno-strict-prototypes")) - warn_strict_prototypes = 0; - else if (!strcmp (p, "-Wmissing-prototypes")) - warn_missing_prototypes = 1; - else if (!strcmp (p, "-Wno-missing-prototypes")) - warn_missing_prototypes = 0; - else if (!strcmp (p, "-Wmissing-declarations")) - warn_missing_declarations = 1; - else if (!strcmp (p, "-Wno-missing-declarations")) - warn_missing_declarations = 0; - else if (!strcmp (p, "-Wredundant-decls")) - warn_redundant_decls = 1; - else if (!strcmp (p, "-Wno-redundant-decls")) - warn_redundant_decls = 0; - else if (!strcmp (p, "-Wnested-externs")) - warn_nested_externs = 1; - else if (!strcmp (p, "-Wno-nested-externs")) - warn_nested_externs = 0; - else if (!strcmp (p, "-Wtraditional")) - warn_traditional = 1; - else if (!strcmp (p, "-Wno-traditional")) - warn_traditional = 0; - else if (!strncmp (p, "-Wformat=", 9)) - set_Wformat (atoi (p + 9)); - else if (!strcmp (p, "-Wformat")) - set_Wformat (1); - else if (!strcmp (p, "-Wno-format")) - set_Wformat (0); - else if (!strcmp (p, "-Wformat-y2k")) - warn_format_y2k = 1; - else if (!strcmp (p, "-Wno-format-y2k")) - warn_format_y2k = 0; - else if (!strcmp (p, "-Wformat-extra-args")) - warn_format_extra_args = 1; - else if (!strcmp (p, "-Wno-format-extra-args")) - warn_format_extra_args = 0; - else if (!strcmp (p, "-Wformat-nonliteral")) - warn_format_nonliteral = 1; - else if (!strcmp (p, "-Wno-format-nonliteral")) - warn_format_nonliteral = 0; - else if (!strcmp (p, "-Wformat-security")) - warn_format_security = 1; - else if (!strcmp (p, "-Wno-format-security")) - warn_format_security = 0; - else if (!strcmp (p, "-Wchar-subscripts")) - warn_char_subscripts = 1; - else if (!strcmp (p, "-Wno-char-subscripts")) - warn_char_subscripts = 0; - else if (!strcmp (p, "-Wconversion")) - warn_conversion = 1; - else if (!strcmp (p, "-Wno-conversion")) - warn_conversion = 0; - else if (!strcmp (p, "-Wparentheses")) - warn_parentheses = 1; - else if (!strcmp (p, "-Wno-parentheses")) - warn_parentheses = 0; - else if (!strcmp (p, "-Wreturn-type")) - warn_return_type = 1; - else if (!strcmp (p, "-Wno-return-type")) - warn_return_type = 0; - else if (!strcmp (p, "-Wsequence-point")) - warn_sequence_point = 1; - else if (!strcmp (p, "-Wno-sequence-point")) - warn_sequence_point = 0; - else if (!strcmp (p, "-Wcomment")) - ; /* cpp handles this one. */ - else if (!strcmp (p, "-Wno-comment")) - ; /* cpp handles this one. */ - else if (!strcmp (p, "-Wcomments")) - ; /* cpp handles this one. */ - else if (!strcmp (p, "-Wno-comments")) - ; /* cpp handles this one. */ - else if (!strcmp (p, "-Wtrigraphs")) - ; /* cpp handles this one. */ - else if (!strcmp (p, "-Wno-trigraphs")) - ; /* cpp handles this one. */ - else if (!strcmp (p, "-Wundef")) - ; /* cpp handles this one. */ - else if (!strcmp (p, "-Wno-undef")) - ; /* cpp handles this one. */ - else if (!strcmp (p, "-Wimport")) - ; /* cpp handles this one. */ - else if (!strcmp (p, "-Wno-import")) - ; /* cpp handles this one. */ - else if (!strcmp (p, "-Wmissing-braces")) - warn_missing_braces = 1; - else if (!strcmp (p, "-Wno-missing-braces")) - warn_missing_braces = 0; - else if (!strcmp (p, "-Wmain")) - warn_main = 1; - else if (!strcmp (p, "-Wno-main")) - 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")) - warn_multichar = 0; - else if (!strcmp (p, "-Wdiv-by-zero")) - warn_div_by_zero = 1; - else if (!strcmp (p, "-Wno-div-by-zero")) - warn_div_by_zero = 0; - else if (!strcmp (p, "-Wunknown-pragmas")) - /* Set to greater than 1, so that even unknown pragmas in system - headers will be warned about. */ - warn_unknown_pragmas = 2; - else if (!strcmp (p, "-Wno-unknown-pragmas")) - warn_unknown_pragmas = 0; - else if (!strcmp (p, "-Wall")) - { - /* We save the value of warn_uninitialized, since if they put - -Wuninitialized on the command line, we need to generate a - warning about not using it without also specifying -O. */ - if (warn_uninitialized != 1) - warn_uninitialized = 2; - warn_implicit_int = 1; - mesg_implicit_function_declaration = 1; - warn_return_type = 1; - set_Wunused (1); - warn_switch = 1; - set_Wformat (1); - warn_char_subscripts = 1; - warn_parentheses = 1; - warn_sequence_point = 1; - warn_missing_braces = 1; - /* We set this to 2 here, but 1 in -Wmain, so -ffreestanding can turn - it off only if it's not explicit. */ - warn_main = 2; - /* Only warn about unknown pragmas that are not in system headers. */ - warn_unknown_pragmas = 1; - } - else - return strings_processed; - - return 1; -} - void -c_print_identifier (file, node, indent) - FILE *file; - tree node; - int indent; +c_print_identifier (FILE *file, tree node, int indent) { - print_node (file, "global", IDENTIFIER_GLOBAL_VALUE (node), indent + 4); - print_node (file, "local", IDENTIFIER_LOCAL_VALUE (node), indent + 4); + print_node (file, "symbol", IDENTIFIER_SYMBOL_VALUE (node), indent + 4); + print_node (file, "tag", IDENTIFIER_TAG_VALUE (node), indent + 4); print_node (file, "label", IDENTIFIER_LABEL_VALUE (node), indent + 4); - print_node (file, "implicit", IDENTIFIER_IMPLICIT_DECL (node), indent + 4); - print_node (file, "error locus", IDENTIFIER_ERROR_LOCUS (node), indent + 4); - print_node (file, "limbo value", IDENTIFIER_LIMBO_VALUE (node), indent + 4); if (C_IS_RESERVED_WORD (node)) { tree rid = ridpointers[C_RID_CODE (node)]; indent_to (file, indent + 4); - fprintf (file, "rid "); - fprintf (file, HOST_PTR_PRINTF, (void *)rid); - fprintf (file, " \"%s\"", IDENTIFIER_POINTER (rid)); + fprintf (file, "rid " HOST_PTR_PRINTF " \"%s\"", + (void *) rid, IDENTIFIER_POINTER (rid)); } } @@ -808,8 +314,7 @@ c_print_identifier (file, node, indent) for a top-level tentative array defn that wasn't complete before. */ void -finish_incomplete_decl (decl) - tree decl; +c_finish_incomplete_decl (tree decl) { if (TREE_CODE (decl) == VAR_DECL) { @@ -828,25 +333,48 @@ finish_incomplete_decl (decl) } } -/* Create a new `struct binding_level'. */ +/* Reuse or create a struct for this binding level. */ static struct binding_level * -make_binding_level () +make_binding_level (void) { - /* NOSTRICT */ - return (struct binding_level *) xmalloc (sizeof (struct binding_level)); + struct binding_level *result; + if (free_binding_level) + { + result = free_binding_level; + free_binding_level = result->level_chain; + memset (result, 0, sizeof(struct binding_level)); + } + else + result = (struct binding_level *) + ggc_alloc_cleared (sizeof (struct binding_level)); + + return result; +} + +/* Remove a binding level from a list and add it to the level chain. */ + +static void +pop_binding_level (struct binding_level **lp) +{ + struct binding_level *l = *lp; + *lp = l->level_chain; + + memset (l, 0, sizeof (struct binding_level)); + l->level_chain = free_binding_level; + free_binding_level = l; } /* Nonzero if we are currently in the global binding level. */ int -global_bindings_p () +global_bindings_p (void) { return current_binding_level == global_binding_level; } void -keep_next_level () +keep_next_level (void) { keep_next_level_flag = 1; } @@ -854,14 +382,13 @@ keep_next_level () /* Nonzero if the current level needs to have a BLOCK made. */ int -kept_level_p () +kept_level_p (void) { return ((current_binding_level->keep_if_subblocks && current_binding_level->blocks != 0) || current_binding_level->keep || current_binding_level->names != 0 - || (current_binding_level->tags != 0 - && !current_binding_level->tag_transparent)); + || current_binding_level->tags != 0); } /* Identify this binding level as a level of parameters. @@ -870,8 +397,7 @@ kept_level_p () DEFINITION_FLAG, so we ignore it. */ void -declare_parm_level (definition_flag) - int definition_flag ATTRIBUTE_UNUSED; +declare_parm_level (int definition_flag ATTRIBUTE_UNUSED) { current_binding_level->parm_flag = 1; } @@ -879,72 +405,49 @@ declare_parm_level (definition_flag) /* Nonzero if currently making parm declarations. */ int -in_parm_level_p () +in_parm_level_p (void) { return current_binding_level->parm_flag; } -/* Enter a new binding level. - If TAG_TRANSPARENT is nonzero, do so only for the name space of variables, - not for that of tags. */ +/* Enter a new binding level. */ void -pushlevel (tag_transparent) - int tag_transparent; +pushlevel (int dummy ATTRIBUTE_UNUSED) { - struct binding_level *newlevel = NULL_BINDING_LEVEL; - - /* If this is the top level of a function, - just make sure that NAMED_LABELS is 0. */ + /* If this is the top level of a function, make sure that + NAMED_LABELS is 0. */ if (current_binding_level == global_binding_level) + named_labels = 0; + + if (keep_next_if_subblocks) { - named_labels = 0; - } + /* This is the transition from the parameters to the top level + of the function body. These are the same scope + (C99 6.2.1p4,6) so we do not push another binding level. - /* Reuse or create a struct for this binding level. */ + XXX Note kludge - keep_next_if_subblocks is set only by + store_parm_decls, which in turn is called when and only + when we are about to encounter the opening curly brace for + the function body. */ + current_binding_level->parm_flag = 0; + current_binding_level->function_body = 1; + current_binding_level->keep |= keep_next_level_flag; + current_binding_level->keep_if_subblocks = 1; - if (free_binding_level) - { - newlevel = free_binding_level; - free_binding_level = free_binding_level->level_chain; + keep_next_level_flag = 0; + keep_next_if_subblocks = 0; } else { - newlevel = make_binding_level (); - } - - /* Add this level to the front of the chain (stack) of levels that - are active. */ - - *newlevel = clear_binding_level; - newlevel->tag_transparent - = (tag_transparent - || (current_binding_level - ? current_binding_level->subblocks_tag_transparent - : 0)); - newlevel->level_chain = current_binding_level; - current_binding_level = newlevel; - newlevel->keep = keep_next_level_flag; - keep_next_level_flag = 0; - newlevel->keep_if_subblocks = keep_next_if_subblocks; - keep_next_if_subblocks = 0; -} - -/* Clear the limbo values of all identifiers defined in BLOCK or a subblock. */ - -static void -clear_limbo_values (block) - tree block; -{ - tree tem; + struct binding_level *newlevel = make_binding_level (); - for (tem = BLOCK_VARS (block); tem; tem = TREE_CHAIN (tem)) - if (DECL_NAME (tem) != 0) - IDENTIFIER_LIMBO_VALUE (DECL_NAME (tem)) = 0; - - for (tem = BLOCK_SUBBLOCKS (block); tem; tem = TREE_CHAIN (tem)) - clear_limbo_values (tem); + newlevel->keep = keep_next_level_flag; + newlevel->level_chain = current_binding_level; + current_binding_level = newlevel; + keep_next_level_flag = 0; + } } /* Exit a binding level. @@ -963,101 +466,106 @@ clear_limbo_values (block) them into the BLOCK. */ tree -poplevel (keep, reverse, functionbody) - int keep; - int reverse; - int functionbody; +poplevel (int keep, int reverse, int functionbody) { tree link; - /* The chain of decls was accumulated in reverse order. - Put it into forward order, just for cleanliness. */ - tree decls; + tree block; + tree decl; + tree decls = current_binding_level->names; tree tags = current_binding_level->tags; tree subblocks = current_binding_level->blocks; - tree block = 0; - tree decl; - int block_previously_created; - keep |= current_binding_level->keep; + functionbody |= current_binding_level->function_body; + keep |= (current_binding_level->keep || functionbody + || (current_binding_level->keep_if_subblocks && subblocks != 0)); - /* This warning is turned off because it causes warnings for - declarations like `extern struct foo *x'. */ -#if 0 - /* Warn about incomplete structure types in this level. */ + /* We used to warn about unused variables in expand_end_bindings, + i.e. while generating RTL. But in function-at-a-time mode we may + choose to never expand a function at all (e.g. auto inlining), so + we do this explicitly now. */ + warn_about_unused_variables (decls); + + /* Clear out the name-meanings declared on this level. + Propagate TREE_ADDRESSABLE from nested functions to their + containing functions. */ + for (link = decls; link; link = TREE_CHAIN (link)) + { + if (DECL_NAME (link) != 0) + { + if (DECL_EXTERNAL (link)) + /* External decls stay in the symbol-value slot but are + inaccessible. */ + C_DECL_INVISIBLE (link) = 1; + else + IDENTIFIER_SYMBOL_VALUE (DECL_NAME (link)) = 0; + } + + if (TREE_CODE (link) == FUNCTION_DECL + && ! TREE_ASM_WRITTEN (link) + && DECL_INITIAL (link) != 0 + && TREE_ADDRESSABLE (link) + && DECL_ABSTRACT_ORIGIN (link) != 0 + && DECL_ABSTRACT_ORIGIN (link) != link) + TREE_ADDRESSABLE (DECL_ABSTRACT_ORIGIN (link)) = 1; + } + + /* Clear out the tag-meanings declared on this level. */ for (link = tags; link; link = TREE_CHAIN (link)) - if (!COMPLETE_TYPE_P (TREE_VALUE (link))) - { - tree type = TREE_VALUE (link); - 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: - error ("`struct %s' incomplete in scope ending here", id); - break; - case UNION_TYPE: - error ("`union %s' incomplete in scope ending here", id); - break; - case ENUMERAL_TYPE: - error ("`enum %s' incomplete in scope ending here", id); - break; - } - } -#endif /* 0 */ + if (TREE_PURPOSE (link)) + IDENTIFIER_TAG_VALUE (TREE_PURPOSE (link)) = 0; + + /* Restore all name-meanings of the outer levels + that were shadowed by this level. */ + + for (link = current_binding_level->shadowed; link; link = TREE_CHAIN (link)) + IDENTIFIER_SYMBOL_VALUE (TREE_PURPOSE (link)) = TREE_VALUE (link); + + /* Restore all tag-meanings of the outer levels + that were shadowed by this level. */ + + for (link = current_binding_level->shadowed_tags; link; + link = TREE_CHAIN (link)) + IDENTIFIER_TAG_VALUE (TREE_PURPOSE (link)) = TREE_VALUE (link); + + /* If this is the top level block of a function, remove all + PARM_DECLs from current_binding_level->names; they are already + stored in DECL_ARGUMENTS of cfun->decl in proper order, should + not be put in BLOCK_VARS, and furthermore reversing them will + cause trouble later. They are all together at the end of the + list. */ + if (functionbody && decls) + { + if (TREE_CODE (decls) == PARM_DECL) + decls = 0; + else + { + link = decls; + while (TREE_CHAIN (link) + && TREE_CODE (TREE_CHAIN (link)) != PARM_DECL) + link = TREE_CHAIN (link); + + TREE_CHAIN (link) = 0; + } + } /* Get the decls in the order they were written. Usually current_binding_level->names is in reverse order. But parameter decls were previously put in forward order. */ if (reverse) - current_binding_level->names - = decls = nreverse (current_binding_level->names); - else - decls = current_binding_level->names; - - /* Output any nested inline functions within this block - if they weren't already output. */ - - for (decl = decls; decl; decl = TREE_CHAIN (decl)) - if (TREE_CODE (decl) == FUNCTION_DECL - && ! TREE_ASM_WRITTEN (decl) - && DECL_INITIAL (decl) != 0 - && TREE_ADDRESSABLE (decl)) - { - /* If this decl was copied from a file-scope decl - on account of a block-scope extern decl, - propagate TREE_ADDRESSABLE to the file-scope decl. - - DECL_ABSTRACT_ORIGIN can be set to itself if warn_return_type is - true, since then the decl goes through save_for_inline_copying. */ - if (DECL_ABSTRACT_ORIGIN (decl) != 0 - && DECL_ABSTRACT_ORIGIN (decl) != decl) - TREE_ADDRESSABLE (DECL_ABSTRACT_ORIGIN (decl)) = 1; - } - - /* We used to warn about unused variables in expand_end_bindings, - i.e. while generating RTL. But in function-at-a-time mode we may - choose to never expand a function at all (e.g. auto inlining), so - we do this explicitly now. */ - warn_about_unused_variables (getdecls ()); + decls = nreverse (decls); /* If there were any declarations or structure tags in that level, or if this level is a function body, create a BLOCK to record them for the life of this function. */ block = 0; - block_previously_created = (current_binding_level->this_block != 0); - if (block_previously_created) - block = current_binding_level->this_block; - else if (keep || functionbody - || (current_binding_level->keep_if_subblocks && subblocks != 0)) - block = make_node (BLOCK); - if (block != 0) + if (keep) { + block = make_node (BLOCK); BLOCK_VARS (block) = decls; BLOCK_SUBBLOCKS (block) = subblocks; + TREE_USED (block) = 1; } /* In each subblock, record that this is its superior. */ @@ -1065,50 +573,31 @@ poplevel (keep, reverse, functionbody) for (link = subblocks; link; link = TREE_CHAIN (link)) BLOCK_SUPERCONTEXT (link) = block; - /* Clear out the meanings of the local variables of this level. */ - - for (link = decls; link; link = TREE_CHAIN (link)) - { - if (DECL_NAME (link) != 0) - { - /* If the ident. was used or addressed via a local extern decl, - don't forget that fact. */ - if (DECL_EXTERNAL (link)) - { - if (TREE_USED (link)) - TREE_USED (DECL_NAME (link)) = 1; - if (TREE_ADDRESSABLE (link)) - TREE_ADDRESSABLE (DECL_ASSEMBLER_NAME (link)) = 1; - } - IDENTIFIER_LOCAL_VALUE (DECL_NAME (link)) = 0; - } - } + /* Set the TYPE_CONTEXTs for all of the tagged types belonging to this + binding contour so that they point to the appropriate construct, i.e. + either to the current FUNCTION_DECL node, or else to the BLOCK node + we just constructed. - /* Restore all name-meanings of the outer levels - that were shadowed by this level. */ + Note that for tagged types whose scope is just the formal parameter + list for some function type specification, we can't properly set + their TYPE_CONTEXTs here, because we don't have a pointer to the + appropriate FUNCTION_TYPE node readily available to us. For those + cases, the TYPE_CONTEXTs of the relevant tagged type nodes get set + in `grokdeclarator' as soon as we have created the FUNCTION_TYPE + node which will represent the "scope" for these "parameter list local" + tagged types. */ - for (link = current_binding_level->shadowed; link; link = TREE_CHAIN (link)) - IDENTIFIER_LOCAL_VALUE (TREE_PURPOSE (link)) = TREE_VALUE (link); + decl = functionbody ? current_function_decl : block; + if (decl) + for (link = tags; link; link = TREE_CHAIN (link)) + TYPE_CONTEXT (TREE_VALUE (link)) = decl; - /* If the level being exited is the top level of a function, - check over all the labels, and clear out the current - (function local) meanings of their names. */ + /* If the level being exited is the top level of a function, check + over all the labels, and clear out the current (function local) + meanings of their names. Then add them to BLOCK_VARS. */ if (functionbody) { - clear_limbo_values (block); - - /* If this is the top level block of a function, - the vars are the function's parameters. - Don't leave them in the BLOCK because they are - found in the FUNCTION_DECL instead. */ - - BLOCK_VARS (block) = 0; - - /* Clear out the definitions of all label names, - since their scopes end here, - and add them to BLOCK_VARS. */ - for (link = named_labels; link; link = TREE_CHAIN (link)) { tree label = TREE_VALUE (link); @@ -1117,8 +606,7 @@ poplevel (keep, reverse, functionbody) { error_with_decl (label, "label `%s' used but not defined"); /* Avoid crashing later. */ - define_label (input_filename, lineno, - DECL_NAME (label)); + define_label (input_location, DECL_NAME (label)); } else if (warn_unused_label && !TREE_USED (label)) warning_with_decl (label, "label `%s' defined but not used"); @@ -1133,23 +621,14 @@ poplevel (keep, reverse, functionbody) /* Pop the current level, and free the structure for reuse. */ - { - struct binding_level *level = current_binding_level; - current_binding_level = current_binding_level->level_chain; - - level->level_chain = free_binding_level; - free_binding_level = level; - } + pop_binding_level (¤t_binding_level); /* Dispose of the block that we just made inside some higher level. */ if (functionbody) DECL_INITIAL (current_function_decl) = block; else if (block) - { - if (!block_previously_created) - current_binding_level->blocks - = chainon (current_binding_level->blocks, block); - } + current_binding_level->blocks + = chainon (current_binding_level->blocks, block); /* If we did not make a block for the level just exited, any blocks made for inner levels (since they cannot be recorded as subblocks in that level) @@ -1159,30 +638,6 @@ poplevel (keep, reverse, functionbody) current_binding_level->blocks = chainon (current_binding_level->blocks, subblocks); - /* Set the TYPE_CONTEXTs for all of the tagged types belonging to this - binding contour so that they point to the appropriate construct, i.e. - either to the current FUNCTION_DECL node, or else to the BLOCK node - we just constructed. - - Note that for tagged types whose scope is just the formal parameter - list for some function type specification, we can't properly set - their TYPE_CONTEXTs here, because we don't have a pointer to the - appropriate FUNCTION_TYPE node readily available to us. For those - cases, the TYPE_CONTEXTs of the relevant tagged type nodes get set - in `grokdeclarator' as soon as we have created the FUNCTION_TYPE - node which will represent the "scope" for these "parameter list local" - tagged types. */ - - if (functionbody) - for (link = tags; link; link = TREE_CHAIN (link)) - TYPE_CONTEXT (TREE_VALUE (link)) = current_function_decl; - else if (block) - for (link = tags; link; link = TREE_CHAIN (link)) - TYPE_CONTEXT (TREE_VALUE (link)) = block; - - if (block) - TREE_USED (block) = 1; - return block; } @@ -1191,44 +646,28 @@ poplevel (keep, reverse, functionbody) to handle the BLOCK node inside the BIND_EXPR. */ void -insert_block (block) - tree block; +insert_block (tree block) { TREE_USED (block) = 1; current_binding_level->blocks = chainon (current_binding_level->blocks, block); } -/* Set the BLOCK node for the innermost scope - (the one we are currently in). */ +/* Set the BLOCK node for the innermost scope (the one we are + currently in). The RTL expansion machinery requires us to provide + this hook, but it is not useful in function-at-a-time mode. */ void -set_block (block) - tree block; +set_block (tree block ATTRIBUTE_UNUSED) { - current_binding_level->this_block = block; - current_binding_level->names = chainon (current_binding_level->names, - BLOCK_VARS (block)); - current_binding_level->blocks = chainon (current_binding_level->blocks, - BLOCK_SUBBLOCKS (block)); } void -push_label_level () +push_label_level (void) { struct binding_level *newlevel; - /* Reuse or create a struct for this binding level. */ - - if (free_binding_level) - { - newlevel = free_binding_level; - free_binding_level = free_binding_level->level_chain; - } - else - { - newlevel = make_binding_level (); - } + newlevel = make_binding_level (); /* Add this level to the front of the chain (stack) of label levels. */ @@ -1242,7 +681,7 @@ push_label_level () } void -pop_label_level () +pop_label_level (void) { struct binding_level *level = label_level_chain; tree link, prev; @@ -1258,8 +697,7 @@ pop_label_level () error_with_decl (TREE_VALUE (link), "label `%s' used but not defined"); /* Avoid crashing later. */ - define_label (input_filename, lineno, - DECL_NAME (TREE_VALUE (link))); + define_label (input_location, DECL_NAME (TREE_VALUE (link))); } else if (warn_unused_label && !TREE_USED (TREE_VALUE (link))) warning_with_decl (TREE_VALUE (link), @@ -1290,9 +728,7 @@ pop_label_level () shadowed_labels = level->shadowed; /* Pop the current level, and free the structure for reuse. */ - label_level_chain = label_level_chain->level_chain; - level->level_chain = free_binding_level; - free_binding_level = level; + pop_binding_level (&label_level_chain); } /* Push a definition or a declaration of struct, union or enum tag "name". @@ -1303,15 +739,9 @@ pop_label_level () In that case, the TYPE_SIZE will be zero. */ void -pushtag (name, type) - tree name, type; +pushtag (tree name, tree type) { - struct binding_level *b; - - /* Find the proper binding level for this type tag. */ - - for (b = current_binding_level; b->tag_transparent; b = b->level_chain) - continue; + struct binding_level *b = current_binding_level; if (name) { @@ -1319,6 +749,11 @@ pushtag (name, type) if (TYPE_NAME (type) == 0) TYPE_NAME (type) = name; + + if (IDENTIFIER_TAG_VALUE (name)) + b->shadowed_tags = tree_cons (name, IDENTIFIER_TAG_VALUE (name), + b->shadowed_tags); + IDENTIFIER_TAG_VALUE (name) = type; } b->tags = tree_cons (name, type, b->tags); @@ -1349,9 +784,7 @@ pushtag (name, type) and OLDDECL is in an outer binding level and should thus not be changed. */ static int -duplicate_decls (newdecl, olddecl, different_binding_level) - tree newdecl, olddecl; - int different_binding_level; +duplicate_decls (tree newdecl, tree olddecl, int different_binding_level) { int types_match = comptypes (TREE_TYPE (newdecl), TREE_TYPE (olddecl)); int new_is_definition = (TREE_CODE (newdecl) == FUNCTION_DECL @@ -1409,30 +842,16 @@ duplicate_decls (newdecl, olddecl, different_binding_level) if (TREE_CODE (olddecl) != TREE_CODE (newdecl)) { if (TREE_CODE (olddecl) == FUNCTION_DECL - && (DECL_BUILT_IN (olddecl) - || DECL_BUILT_IN_NONANSI (olddecl))) + && DECL_BUILT_IN (olddecl)) { /* If you declare a built-in or predefined function name as static, the old definition is overridden, but optionally warn this was a bad choice of name. */ if (!TREE_PUBLIC (newdecl)) { - if (!warn_shadow) - ; - else if (DECL_BUILT_IN (olddecl)) + if (warn_shadow) warning_with_decl (newdecl, "shadowing built-in function `%s'"); - else - warning_with_decl (newdecl, "shadowing library function `%s'"); } - /* Likewise, if the built-in is not ansi, then programs can - override it even globally without an error. */ - else if (! DECL_BUILT_IN (olddecl)) - warning_with_decl (newdecl, - "library function `%s' declared as non-function"); - - else if (DECL_BUILT_IN_NONANSI (olddecl)) - warning_with_decl (newdecl, - "built-in function `%s' declared as non-function"); else warning_with_decl (newdecl, "built-in function `%s' declared as non-function"); @@ -1446,11 +865,14 @@ duplicate_decls (newdecl, olddecl, different_binding_level) return 0; } - /* For real parm decl following a forward decl, - return 1 so old decl will be reused. */ + /* For real parm decl following a forward decl, return 1 so old decl + will be reused. Only allow this to happen once. */ if (types_match && TREE_CODE (newdecl) == PARM_DECL && TREE_ASM_WRITTEN (olddecl) && ! TREE_ASM_WRITTEN (newdecl)) - return 1; + { + TREE_ASM_WRITTEN (olddecl) = 0; + return 1; + } /* The new declaration is the same kind of object as the old one. The declarations may partially match. Print warnings if they don't @@ -1587,6 +1009,20 @@ duplicate_decls (newdecl, olddecl, different_binding_level) we will come back here again. */ DECL_IN_SYSTEM_HEADER (newdecl) = 1; } + /* Permit void foo (...) to match int foo (...) if the latter is the + definition and implicit int was used. See c-torture/compile/920625-2.c. */ + else if (!types_match && new_is_definition + && TREE_CODE (olddecl) == FUNCTION_DECL + && TREE_CODE (newdecl) == FUNCTION_DECL + && TYPE_MAIN_VARIANT (TREE_TYPE (oldtype)) == void_type_node + && TYPE_MAIN_VARIANT (TREE_TYPE (newtype)) == integer_type_node + && C_FUNCTION_IMPLICIT_INT (newdecl)) + { + pedwarn_with_decl (newdecl, "conflicting types for `%s'"); + /* Make sure we keep void as the return type. */ + TREE_TYPE (newdecl) = newtype = oldtype; + C_FUNCTION_IMPLICIT_INT (newdecl) = 0; + } else if (!types_match /* Permit char *foo (int, ...); followed by char *foo (); if not pedantic. */ @@ -1624,13 +1060,37 @@ duplicate_decls (newdecl, olddecl, different_binding_level) break; } - if (simple_type_promotes_to (type) != NULL_TREE) + if (c_type_promotes_to (type) != type) { error ("an argument type that has a default promotion can't match an empty parameter name list declaration"); break; } } } + if (C_DECL_IMPLICIT (olddecl)) + error_with_decl (olddecl, "previous implicit declaration of `%s'"); + else + error_with_decl (olddecl, "previous declaration of `%s'"); + + /* This is safer because the initializer might contain references + to variables that were declared between olddecl and newdecl. This + will make the initializer invalid for olddecl in case it gets + assigned to olddecl below. */ + if (TREE_CODE (newdecl) == VAR_DECL) + DECL_INITIAL (newdecl) = 0; + } + /* TLS cannot follow non-TLS declaration. */ + else if (TREE_CODE (olddecl) == VAR_DECL && TREE_CODE (newdecl) == VAR_DECL + && !DECL_THREAD_LOCAL (olddecl) && DECL_THREAD_LOCAL (newdecl)) + { + error_with_decl (newdecl, "thread-local declaration of `%s' follows non thread-local declaration"); + error_with_decl (olddecl, "previous declaration of `%s'"); + } + /* non-TLS declaration cannot follow TLS declaration. */ + else if (TREE_CODE (olddecl) == VAR_DECL && TREE_CODE (newdecl) == VAR_DECL + && DECL_THREAD_LOCAL (olddecl) && !DECL_THREAD_LOCAL (newdecl)) + { + error_with_decl (newdecl, "non thread-local declaration of `%s' follows thread-local declaration"); error_with_decl (olddecl, "previous declaration of `%s'"); } else @@ -1841,11 +1301,6 @@ duplicate_decls (newdecl, olddecl, different_binding_level) COPY_DECL_RTL (olddecl, newdecl); /* Merge the type qualifiers. */ - 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; @@ -1904,6 +1359,10 @@ duplicate_decls (newdecl, olddecl, different_binding_level) DECL_NO_LIMIT_STACK (newdecl) |= DECL_NO_LIMIT_STACK (olddecl); DECL_NO_INSTRUMENT_FUNCTION_ENTRY_EXIT (newdecl) |= DECL_NO_INSTRUMENT_FUNCTION_ENTRY_EXIT (olddecl); + TREE_THIS_VOLATILE (newdecl) |= TREE_THIS_VOLATILE (olddecl); + TREE_READONLY (newdecl) |= TREE_READONLY (olddecl); + DECL_IS_MALLOC (newdecl) |= DECL_IS_MALLOC (olddecl); + DECL_IS_PURE (newdecl) |= DECL_IS_PURE (olddecl); } } /* If cannot merge, then use the new type and qualifiers, @@ -1917,7 +1376,8 @@ duplicate_decls (newdecl, olddecl, different_binding_level) } /* Merge the storage class information. */ - DECL_WEAK (newdecl) |= DECL_WEAK (olddecl); + merge_weak (newdecl, olddecl); + /* For functions, static overrides non-static. */ if (TREE_CODE (newdecl) == FUNCTION_DECL) { @@ -1958,9 +1418,10 @@ duplicate_decls (newdecl, olddecl, different_binding_level) inline, make sure we emit debug info for the inline before we throw it away, in case it was inlined into a function that hasn't been written out yet. */ - if (new_is_definition && DECL_INITIAL (olddecl) && TREE_USED (olddecl)) + if (new_is_definition && DECL_INITIAL (olddecl)) { - (*debug_hooks->outlining_inline_function) (olddecl); + if (TREE_USED (olddecl)) + (*debug_hooks->outlining_inline_function) (olddecl); /* The new defn must not be inline. */ DECL_INLINE (newdecl) = 0; @@ -2051,66 +1512,148 @@ duplicate_decls (newdecl, olddecl, different_binding_level) Update OLDDECL to be the same. */ DECL_ATTRIBUTES (olddecl) = DECL_ATTRIBUTES (newdecl); + /* If OLDDECL had its DECL_RTL instantiated, re-invoke make_decl_rtl + so that encode_section_info has a chance to look at the new decl + flags and attributes. */ + if (DECL_RTL_SET_P (olddecl) + && (TREE_CODE (olddecl) == FUNCTION_DECL + || (TREE_CODE (olddecl) == VAR_DECL + && TREE_STATIC (olddecl)))) + make_decl_rtl (olddecl, NULL); + return 1; } +/* Return any external DECL associated with ID, whether or not it is + currently in scope. */ + +static tree +any_external_decl (tree id) +{ + tree decl = IDENTIFIER_SYMBOL_VALUE (id); + tree t; + + if (decl == 0 || TREE_CODE (decl) == ERROR_MARK) + return 0; + else if (TREE_CODE (decl) != TYPE_DECL && DECL_EXTERNAL (decl)) + return decl; + + t = purpose_member (id, truly_local_externals); + if (t) + return TREE_VALUE (t); + + return 0; +} + +/* Record an external decl DECL. This only does something if a + shadowing decl already exists. */ +static void +record_external_decl (tree decl) +{ + tree name = DECL_NAME (decl); + if (!IDENTIFIER_SYMBOL_VALUE (name)) + return; + + truly_local_externals = tree_cons (name, decl, truly_local_externals); +} + /* Check whether decl-node X shadows an existing declaration. - OLDLOCAL is the old IDENTIFIER_LOCAL_VALUE of the DECL_NAME of X, + OLD is the old IDENTIFIER_SYMBOL_VALUE of the DECL_NAME of X, which might be a NULL_TREE. */ static void -warn_if_shadowing (x, oldlocal) - tree x, oldlocal; +warn_if_shadowing (tree x, tree old) { - tree name; + const char *name; - if (DECL_EXTERNAL (x)) + /* Nothing to shadow? */ + if (old == 0 + /* Shadow warnings not wanted? */ + || !warn_shadow + /* No shadow warnings for internally generated vars. */ + || DECL_SOURCE_LINE (x) == 0 + /* No shadow warnings for vars made for inlining. */ + || DECL_FROM_INLINE (x) + /* Don't warn about the parm names in function declarator + within a function declarator. + It would be nice to avoid warning in any function + declarator in a declaration, as opposed to a definition, + but there is no way to tell it's not a definition. */ + || (TREE_CODE (x) == PARM_DECL + && current_binding_level->level_chain->parm_flag)) return; - name = DECL_NAME (x); + name = IDENTIFIER_POINTER (DECL_NAME (x)); + + if (TREE_CODE (old) == PARM_DECL) + shadow_warning (SW_PARAM, name, old); + else if (DECL_CONTEXT (old) == 0) + shadow_warning (SW_GLOBAL, name, old); + else + shadow_warning (SW_LOCAL, name, old); +} + + +/* Subroutine of pushdecl. + + X is a TYPE_DECL for a typedef statement. Create a brand new + ..._TYPE node (which will be just a variant of the existing + ..._TYPE node with identical properties) and then install X + as the TYPE_NAME of this brand new (duplicate) ..._TYPE node. + + The whole point here is to end up with a situation where each + and every ..._TYPE node the compiler creates will be uniquely + associated with AT MOST one node representing a typedef name. + This way, even though the compiler substitutes corresponding + ..._TYPE nodes for TYPE_DECL (i.e. "typedef name") nodes very + early on, later parts of the compiler can always do the reverse + translation and get back the corresponding typedef name. For + example, given: + + typedef struct S MY_TYPE; + MY_TYPE object; + + Later parts of the compiler might only know that `object' was of + type `struct S' if it were not for code just below. With this + code however, later parts of the compiler see something like: + + struct S' == struct S + typedef struct S' MY_TYPE; + struct S' object; - /* Warn if shadowing an argument at the top level of the body. */ - if (oldlocal != 0 - /* This warning doesn't apply to the parms of a nested fcn. */ - && ! current_binding_level->parm_flag - /* Check that this is one level down from the parms. */ - && current_binding_level->level_chain->parm_flag - /* Check that the decl being shadowed - comes from the parm level, one level up. */ - && chain_member (oldlocal, current_binding_level->level_chain->names)) + And they can then deduce (from the node for type struct S') that + the original object declaration was: + + MY_TYPE object; + + Being able to do this is important for proper support of protoize, + and also for generating precise symbolic debugging information + which takes full account of the programmer's (typedef) vocabulary. + + Obviously, we don't want to generate a duplicate ..._TYPE node if + the TYPE_DECL node that we are now processing really represents a + standard built-in type. + + Since all standard types are effectively declared at line zero + in the source file, we can easily check to see if we are working + on a standard type by checking the current value of lineno. */ + +static void +clone_underlying_type (tree x) +{ + if (DECL_SOURCE_LINE (x) == 0) { - if (TREE_CODE (oldlocal) == PARM_DECL) - pedwarn ("declaration of `%s' shadows a parameter", - IDENTIFIER_POINTER (name)); - else - pedwarn ("declaration of `%s' shadows a symbol from the parameter list", - IDENTIFIER_POINTER (name)); + if (TYPE_NAME (TREE_TYPE (x)) == 0) + TYPE_NAME (TREE_TYPE (x)) = x; } - /* Maybe warn if shadowing something else. */ - else if (warn_shadow - /* No shadow warnings for internally generated vars. */ - && DECL_SOURCE_LINE (x) != 0 - /* No shadow warnings for vars made for inlining. */ - && ! DECL_FROM_INLINE (x)) + else if (TREE_TYPE (x) != error_mark_node + && DECL_ORIGINAL_TYPE (x) == NULL_TREE) { - if (TREE_CODE (x) == PARM_DECL - && current_binding_level->level_chain->parm_flag) - /* Don't warn about the parm names in function declarator - within a function declarator. - It would be nice to avoid warning in any function - declarator in a declaration, as opposed to a definition, - but there is no way to tell it's not a definition. */ - ; - else if (oldlocal) - { - if (TREE_CODE (oldlocal) == PARM_DECL) - shadow_warning ("a parameter", name, oldlocal); - else - shadow_warning ("a previous local", name, oldlocal); - } - else if (IDENTIFIER_GLOBAL_VALUE (name) != 0 - && IDENTIFIER_GLOBAL_VALUE (name) != error_mark_node) - shadow_warning ("a global declaration", name, - IDENTIFIER_GLOBAL_VALUE (name)); + tree tt = TREE_TYPE (x); + DECL_ORIGINAL_TYPE (x) = tt; + tt = build_type_copy (tt); + TYPE_NAME (tt) = x; + TREE_USED (tt) = TREE_USED (x); + TREE_TYPE (x) = tt; } } @@ -2123,348 +1666,83 @@ warn_if_shadowing (x, oldlocal) to agree with what X says. */ tree -pushdecl (x) - tree x; +pushdecl (tree x) { - tree t; tree name = DECL_NAME (x); - struct binding_level *b = current_binding_level; + struct binding_level *scope = current_binding_level; + +#ifdef ENABLE_CHECKING + if (error_mark_node == 0) + /* Called too early. */ + abort (); +#endif /* Functions need the lang_decl data. */ if (TREE_CODE (x) == FUNCTION_DECL && ! DECL_LANG_SPECIFIC (x)) DECL_LANG_SPECIFIC (x) = (struct lang_decl *) ggc_alloc_cleared (sizeof (struct lang_decl)); - DECL_CONTEXT (x) = current_function_decl; /* A local extern declaration for a function doesn't constitute nesting. A local auto declaration does, since it's a forward decl for a nested function coming later. */ if ((TREE_CODE (x) == FUNCTION_DECL || TREE_CODE (x) == VAR_DECL) && DECL_INITIAL (x) == 0 && DECL_EXTERNAL (x)) DECL_CONTEXT (x) = 0; + else + DECL_CONTEXT (x) = current_function_decl; if (name) { - int different_binding_level = 0; + tree old; if (warn_nested_externs + && scope != global_binding_level && DECL_EXTERNAL (x) - && b != global_binding_level - && x != IDENTIFIER_IMPLICIT_DECL (name) - /* No error messages for __FUNCTION__ and __PRETTY_FUNCTION__. */ && !DECL_IN_SYSTEM_HEADER (x)) warning ("nested extern declaration of `%s'", IDENTIFIER_POINTER (name)); - t = lookup_name_current_level (name); - if (! t && DECL_EXTERNAL (x) && TREE_PUBLIC (x)) - { - t = IDENTIFIER_GLOBAL_VALUE (name); - /* Type decls at global scope don't conflict with externs declared - inside lexical blocks. */ - if (! t || TREE_CODE (t) == TYPE_DECL) - /* If there's no visible global declaration, try for an - invisible one. */ - t = IDENTIFIER_LIMBO_VALUE (name); - different_binding_level = 1; - } - if (t != 0 && t == error_mark_node) - /* error_mark_node is 0 for a while during initialization! */ - { - t = 0; - error_with_decl (x, "`%s' used prior to declaration"); - } - - /* If this decl is `static' and an implicit decl was seen previously, - warn. */ - if (TREE_PUBLIC (name) - /* Don't test for DECL_EXTERNAL, because grokdeclarator - sets this for all functions. */ - && ! TREE_PUBLIC (x) - && (TREE_CODE (x) == FUNCTION_DECL || b == global_binding_level) - /* We used to warn also for explicit extern followed by static, - but sometimes you need to do it that way. */ - && IDENTIFIER_IMPLICIT_DECL (name) != 0) + old = lookup_name_current_level (name); + if (old && duplicate_decls (x, old, 0)) + return old; + if (DECL_EXTERNAL (x) || scope == global_binding_level) { - pedwarn ("`%s' was declared implicitly `extern' and later `static'", - IDENTIFIER_POINTER (name)); - pedwarn_with_file_and_line - (DECL_SOURCE_FILE (IDENTIFIER_IMPLICIT_DECL (name)), - DECL_SOURCE_LINE (IDENTIFIER_IMPLICIT_DECL (name)), - "previous declaration of `%s'", - IDENTIFIER_POINTER (name)); - TREE_THIS_VOLATILE (name) = 1; - } - - if (t != 0 && duplicate_decls (x, t, different_binding_level)) - { - if (TREE_CODE (t) == PARM_DECL) - { - /* Don't allow more than one "real" duplicate - of a forward parm decl. */ - TREE_ASM_WRITTEN (t) = TREE_ASM_WRITTEN (x); - return t; - } - return t; - } - - /* If we are processing a typedef statement, generate a whole new - ..._TYPE node (which will be just an variant of the existing - ..._TYPE node with identical properties) and then install the - TYPE_DECL node generated to represent the typedef name as the - TYPE_NAME of this brand new (duplicate) ..._TYPE node. - - The whole point here is to end up with a situation where each - and every ..._TYPE node the compiler creates will be uniquely - associated with AT MOST one node representing a typedef name. - This way, even though the compiler substitutes corresponding - ..._TYPE nodes for TYPE_DECL (i.e. "typedef name") nodes very - early on, later parts of the compiler can always do the reverse - translation and get back the corresponding typedef name. For - example, given: - - typedef struct S MY_TYPE; - MY_TYPE object; - - Later parts of the compiler might only know that `object' was of - type `struct S' if it were not for code just below. With this - code however, later parts of the compiler see something like: - - struct S' == struct S - typedef struct S' MY_TYPE; - struct S' object; - - And they can then deduce (from the node for type struct S') that - the original object declaration was: - - MY_TYPE object; - - Being able to do this is important for proper support of protoize, - and also for generating precise symbolic debugging information - which takes full account of the programmer's (typedef) vocabulary. - - Obviously, we don't want to generate a duplicate ..._TYPE node if - the TYPE_DECL node that we are now processing really represents a - standard built-in type. - - Since all standard types are effectively declared at line zero - in the source file, we can easily check to see if we are working - on a standard type by checking the current value of lineno. */ - - if (TREE_CODE (x) == TYPE_DECL) - { - if (DECL_SOURCE_LINE (x) == 0) + /* Find and check against a previous, not-in-scope, external + decl for this identifier. (C99 s???: If two declarations + with external linkage, referring to the same object, have + incompatible types, the behavior is undefined). */ + tree ext = any_external_decl (name); + if (ext) { - if (TYPE_NAME (TREE_TYPE (x)) == 0) - TYPE_NAME (TREE_TYPE (x)) = x; + if (duplicate_decls (x, ext, scope != global_binding_level)) + x = copy_node (ext); } - else if (TREE_TYPE (x) != error_mark_node - && DECL_ORIGINAL_TYPE (x) == NULL_TREE) - { - tree tt = TREE_TYPE (x); - DECL_ORIGINAL_TYPE (x) = tt; - tt = build_type_copy (tt); - TYPE_NAME (tt) = x; - TREE_USED (tt) = TREE_USED (x); - TREE_TYPE (x) = tt; - } - } - - /* Multiple external decls of the same identifier ought to match. - We get warnings about inline functions where they are defined. - Avoid duplicate warnings where they are used. */ - if (TREE_PUBLIC (x) - && ! (TREE_CODE (x) == FUNCTION_DECL && DECL_INLINE (x))) - { - tree decl; - - if (IDENTIFIER_LIMBO_VALUE (name) != 0) - /* Decls in limbo are always extern, so no need to check that. */ - decl = IDENTIFIER_LIMBO_VALUE (name); else - decl = 0; - - if (decl && ! comptypes (TREE_TYPE (x), TREE_TYPE (decl)) - /* If old decl is built-in, we already warned if we should. */ - && !DECL_BUILT_IN (decl)) - { - pedwarn_with_decl (x, - "type mismatch with previous external decl"); - pedwarn_with_decl (decl, "previous external decl of `%s'"); - } - } - - /* If a function has had an implicit declaration, and then is defined, - make sure they are compatible. */ - - if (IDENTIFIER_IMPLICIT_DECL (name) != 0 - && IDENTIFIER_GLOBAL_VALUE (name) == 0 - && TREE_CODE (x) == FUNCTION_DECL - && ! comptypes (TREE_TYPE (x), - TREE_TYPE (IDENTIFIER_IMPLICIT_DECL (name)))) - { - warning_with_decl (x, "type mismatch with previous implicit declaration"); - warning_with_decl (IDENTIFIER_IMPLICIT_DECL (name), - "previous implicit declaration of `%s'"); + record_external_decl (x); } - /* This name is new in its binding level. - Install the new declaration and return it. */ - if (b == global_binding_level) + if (TREE_CODE (x) == TYPE_DECL) + clone_underlying_type (x); + + /* If storing a local value, there may already be one + (inherited). If so, record it for restoration when this + binding level ends. Take care not to do this if we are + replacing an older decl in the same binding level (i.e. + duplicate_decls returned false, above). */ + if (scope != global_binding_level + && IDENTIFIER_SYMBOL_VALUE (name) + && IDENTIFIER_SYMBOL_VALUE (name) != old) { - /* Install a global value. */ - - /* If the first global decl has external linkage, - warn if we later see static one. */ - if (IDENTIFIER_GLOBAL_VALUE (name) == 0 && TREE_PUBLIC (x)) - TREE_PUBLIC (name) = 1; - - IDENTIFIER_GLOBAL_VALUE (name) = x; - - /* We no longer care about any previous block level declarations. */ - IDENTIFIER_LIMBO_VALUE (name) = 0; - - /* Don't forget if the function was used via an implicit decl. */ - if (IDENTIFIER_IMPLICIT_DECL (name) - && TREE_USED (IDENTIFIER_IMPLICIT_DECL (name))) - TREE_USED (x) = 1, TREE_USED (name) = 1; - - /* Don't forget if its address was taken in that way. */ - if (IDENTIFIER_IMPLICIT_DECL (name) - && TREE_ADDRESSABLE (IDENTIFIER_IMPLICIT_DECL (name))) - TREE_ADDRESSABLE (x) = 1; - - /* Warn about mismatches against previous implicit decl. */ - if (IDENTIFIER_IMPLICIT_DECL (name) != 0 - /* If this real decl matches the implicit, don't complain. */ - && ! (TREE_CODE (x) == FUNCTION_DECL - && (TYPE_MAIN_VARIANT (TREE_TYPE (TREE_TYPE (x))) - == integer_type_node))) - pedwarn ("`%s' was previously implicitly declared to return `int'", - IDENTIFIER_POINTER (name)); - - /* If this decl is `static' and an `extern' was seen previously, - that is erroneous. */ - if (TREE_PUBLIC (name) - && ! TREE_PUBLIC (x) && ! DECL_EXTERNAL (x)) - { - /* Okay to redeclare an ANSI built-in as static. */ - if (t != 0 && DECL_BUILT_IN (t)) - ; - /* Okay to declare a non-ANSI built-in as anything. */ - else if (t != 0 && DECL_BUILT_IN_NONANSI (t)) - ; - /* Okay to have global type decl after an earlier extern - declaration inside a lexical block. */ - else if (TREE_CODE (x) == TYPE_DECL) - ; - else if (IDENTIFIER_IMPLICIT_DECL (name)) - { - if (! TREE_THIS_VOLATILE (name)) - pedwarn ("`%s' was declared implicitly `extern' and later `static'", - IDENTIFIER_POINTER (name)); - } - else - pedwarn ("`%s' was declared `extern' and later `static'", - IDENTIFIER_POINTER (name)); - } + warn_if_shadowing (x, IDENTIFIER_SYMBOL_VALUE (name)); + scope->shadowed = tree_cons (name, IDENTIFIER_SYMBOL_VALUE (name), + scope->shadowed); } - else - { - /* 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 - && oldglobal != 0 - && TREE_CODE (x) == FUNCTION_DECL - && TREE_CODE (oldglobal) == FUNCTION_DECL - && DECL_EXTERNAL (x) - && ! DECL_DECLARED_INLINE_P (x)) - { - /* We have one. Their types must agree. */ - if (! comptypes (TREE_TYPE (x), - TREE_TYPE (IDENTIFIER_GLOBAL_VALUE (name)))) - pedwarn_with_decl (x, "extern declaration of `%s' doesn't match global one"); - else - { - /* Inner extern decl is inline if global one is. - Copy enough to really inline it. */ - if (DECL_DECLARED_INLINE_P (oldglobal)) - { - DECL_DECLARED_INLINE_P (x) - = DECL_DECLARED_INLINE_P (oldglobal); - DECL_INLINE (x) = DECL_INLINE (oldglobal); - DECL_INITIAL (x) = (current_function_decl == oldglobal - ? 0 : DECL_INITIAL (oldglobal)); - DECL_SAVED_INSNS (x) = DECL_SAVED_INSNS (oldglobal); - DECL_NUM_STMTS (x) = DECL_NUM_STMTS (oldglobal); - DECL_ARGUMENTS (x) = DECL_ARGUMENTS (oldglobal); - DECL_RESULT (x) = DECL_RESULT (oldglobal); - TREE_ASM_WRITTEN (x) = TREE_ASM_WRITTEN (oldglobal); - DECL_ABSTRACT_ORIGIN (x) - = DECL_ABSTRACT_ORIGIN (oldglobal); - } - /* Inner extern decl is built-in if global one is. */ - if (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. */ - if (TYPE_ARG_TYPES (TREE_TYPE (oldglobal)) != 0 - && DECL_INITIAL (oldglobal) - && TYPE_ARG_TYPES (TREE_TYPE (x)) == 0) - TREE_TYPE (x) = TREE_TYPE (oldglobal); - } - } - -#if 0 - /* This case is probably sometimes the right thing to do. */ - /* If we have a local external declaration, - then any file-scope declaration should not - have been static. */ - if (oldlocal == 0 && oldglobal != 0 - && !TREE_PUBLIC (oldglobal) - && DECL_EXTERNAL (x) && TREE_PUBLIC (x)) - warning ("`%s' locally external but globally static", - IDENTIFIER_POINTER (name)); -#endif - - /* If we have a local external declaration, - and no file-scope declaration has yet been seen, - then if we later have a file-scope decl it must not be static. */ - if (oldlocal == 0 - && DECL_EXTERNAL (x) - && TREE_PUBLIC (x)) - { - if (oldglobal == 0) - TREE_PUBLIC (name) = 1; - - /* Save this decl, so that we can do type checking against - other decls after it falls out of scope. - - Only save it once. This prevents temporary decls created in - expand_inline_function from being used here, since this - will have been set when the inline function was parsed. - It also helps give slightly better warnings. */ - if (IDENTIFIER_LIMBO_VALUE (name) == 0) - IDENTIFIER_LIMBO_VALUE (name) = x; - } - warn_if_shadowing (x, oldlocal); + /* Install the new declaration in the requested binding level. */ + IDENTIFIER_SYMBOL_VALUE (name) = x; + C_DECL_INVISIBLE (x) = 0; - /* If storing a local value, there may already be one (inherited). - If so, record it for restoration when this binding level ends. */ - if (oldlocal != 0) - b->shadowed = tree_cons (name, oldlocal, b->shadowed); - } - - /* Keep count of variables in this level with incomplete type. + /* Keep list of variables in this level with incomplete type. If the input is erroneous, we can have error_mark in the type slot (e.g. "f(void a, ...)") - that doesn't count as an incomplete type. */ @@ -2477,84 +1755,133 @@ pushdecl (x) element = TREE_TYPE (element); if (TREE_CODE (element) == RECORD_TYPE || TREE_CODE (element) == UNION_TYPE) - ++b->n_incomplete; + scope->incomplete_list = tree_cons (NULL_TREE, x, + scope->incomplete_list); } } /* Put decls on list in reverse order. We will reverse them later if necessary. */ - TREE_CHAIN (x) = b->names; - b->names = x; + TREE_CHAIN (x) = scope->names; + scope->names = x; return x; } -/* Like pushdecl, only it places X in GLOBAL_BINDING_LEVEL, if appropriate. */ - +/* Record X as belonging to the global scope (C99 "file scope"). + This is used only internally by the Objective-C front end, + and is limited to its needs. It will hork if there is _any_ + visible binding for X (not just a global one). */ tree -pushdecl_top_level (x) - tree x; +pushdecl_top_level (tree x) { - tree t; - struct binding_level *b = current_binding_level; + tree name, old; - current_binding_level = global_binding_level; - t = pushdecl (x); - current_binding_level = b; - return t; + if (TREE_CODE (x) != VAR_DECL) + abort (); + + name = DECL_NAME (x); + old = IDENTIFIER_SYMBOL_VALUE (name); + + if (old) + { + if (DECL_CONTEXT (old)) + abort (); + + if (!duplicate_decls (x, old, 0)) + abort (); + + return old; + } + + DECL_CONTEXT (x) = 0; + IDENTIFIER_SYMBOL_VALUE (name) = x; + TREE_CHAIN (x) = global_binding_level->names; + global_binding_level->names = x; + return x; } - -/* Generate an implicit declaration for identifier FUNCTIONID - as a function of type int (). Print a warning if appropriate. */ +/* Record X as belonging to the outermost scope of the current + function. This is used only internally, by c_make_fname_decl and + build_external_ref, and is limited to their needs. The NAME is + provided as a separate argument because build_external_ref wants to + use error_mark_node for X. For VAR_DECLs, duplicate_decls is not + called; if there is any preexisting decl for this identifier, it is + an ICE. */ tree -implicitly_declare (functionid) - tree functionid; +pushdecl_function_level (tree x, tree name) { - tree decl; - int traditional_warning = 0; - /* Only one "implicit declaration" warning per identifier. */ - int implicit_warning; + struct binding_level *scope; - /* We used to reuse an old implicit decl here, - but this loses with inline functions because it can clobber - the saved decl chains. */ -#if 0 - if (IDENTIFIER_IMPLICIT_DECL (functionid) != 0) - decl = IDENTIFIER_IMPLICIT_DECL (functionid); - else -#endif - decl = build_decl (FUNCTION_DECL, functionid, default_function_type); + scope = current_binding_level; + while (scope->function_body == 0) + scope = scope->level_chain; + if (!scope) + abort (); + + if (x == error_mark_node) + scope->shadowed = tree_cons (name, IDENTIFIER_SYMBOL_VALUE (name), + scope->shadowed); + else if (TREE_CODE (x) == VAR_DECL) + { + if (name != DECL_NAME (x)) + abort (); + if (IDENTIFIER_SYMBOL_VALUE (name)) + abort (); + + DECL_CONTEXT (x) = current_function_decl; + TREE_CHAIN (x) = scope->names; + scope->names = x; + } + + IDENTIFIER_SYMBOL_VALUE (name) = x; + return x; +} + +/* Generate an implicit declaration for identifier FUNCTIONID as a + function of type int (). */ - /* Warn of implicit decl following explicit local extern decl. - This is probably a program designed for traditional C. */ - if (TREE_PUBLIC (functionid) && IDENTIFIER_GLOBAL_VALUE (functionid) == 0) - traditional_warning = 1; +tree +implicitly_declare (tree functionid) +{ + tree decl = any_external_decl (functionid); - /* Warn once of an implicit declaration. */ - implicit_warning = (IDENTIFIER_IMPLICIT_DECL (functionid) == 0); + if (decl && decl != error_mark_node) + { + /* Implicit declaration of a function already declared + (somehow) in a different scope, or as a built-in. + If this is the first time this has happened, warn; + then recycle the old declaration. */ + if (!C_DECL_IMPLICIT (decl)) + { + implicit_decl_warning (DECL_NAME (decl)); + if (DECL_CONTEXT (decl)) + warning_with_decl (decl, "previous declaration of `%s'"); + C_DECL_IMPLICIT (decl) = 1; + } + /* If this function is global, then it must already be in the + global binding level, so there's no need to push it again. */ + if (current_binding_level == global_binding_level) + return decl; + /* If this is a local declaration, make a copy; we can't have + the same DECL listed in two different binding levels. */ + return pushdecl (copy_node (decl)); + } + /* Not seen before. */ + decl = build_decl (FUNCTION_DECL, functionid, default_function_type); DECL_EXTERNAL (decl) = 1; TREE_PUBLIC (decl) = 1; - - /* Record that we have an implicit decl and this is it. */ - IDENTIFIER_IMPLICIT_DECL (functionid) = decl; + C_DECL_IMPLICIT (decl) = 1; + implicit_decl_warning (functionid); /* ANSI standard says implicit declarations are in the innermost block. So we record the decl in the standard fashion. */ - pushdecl (decl); - - /* This is a no-op in c-lang.c or something real in objc-actions.c. */ - maybe_objc_check_decl (decl); + decl = pushdecl (decl); + /* No need to call objc_check_decl here - it's a function type. */ rest_of_decl_compilation (decl, NULL, 0, 0); - if (implicit_warning) - implicit_decl_warning (functionid); - else if (warn_traditional && traditional_warning) - warning ("function `%s' was previously declared within a block", - IDENTIFIER_POINTER (functionid)); - /* Write a record describing this implicit function declaration to the prototypes file (if requested). */ @@ -2566,9 +1893,8 @@ implicitly_declare (functionid) return decl; } -void -implicit_decl_warning (id) - tree id; +static void +implicit_decl_warning (tree id) { const char *name = IDENTIFIER_POINTER (id); if (mesg_implicit_function_declaration == 2) @@ -2584,8 +1910,7 @@ implicit_decl_warning (id) and 3 if it is a conflicting declaration. */ static int -redeclaration_error_message (newdecl, olddecl) - tree newdecl, olddecl; +redeclaration_error_message (tree newdecl, tree olddecl) { if (TREE_CODE (newdecl) == TYPE_DECL) { @@ -2646,8 +1971,7 @@ redeclaration_error_message (newdecl, olddecl) This function is called for both label definitions and label references. */ tree -lookup_label (id) - tree id; +lookup_label (tree id) { tree decl = IDENTIFIER_LABEL_VALUE (id); @@ -2677,8 +2001,7 @@ lookup_label (id) /* Say where one reference is to the label, for the sake of the error if it is not defined. */ - DECL_SOURCE_LINE (decl) = lineno; - DECL_SOURCE_FILE (decl) = input_filename; + DECL_SOURCE_LOCATION (decl) = input_location; IDENTIFIER_LABEL_VALUE (id) = decl; @@ -2696,8 +2019,7 @@ lookup_label (id) requires calling declare_nonlocal_label right away. */ tree -shadow_label (name) - tree name; +shadow_label (tree name) { tree decl = IDENTIFIER_LABEL_VALUE (name); @@ -2730,10 +2052,7 @@ shadow_label (name) Otherwise return 0. */ tree -define_label (filename, line, name) - const char *filename; - int line; - tree name; +define_label (location_t location, tree name) { tree decl = lookup_label (name); @@ -2746,14 +2065,12 @@ define_label (filename, line, name) } if (warn_traditional && !in_system_header && lookup_name (name)) - warning_with_file_and_line (filename, line, - "traditional C lacks a separate namespace for labels, identifier `%s' conflicts", - IDENTIFIER_POINTER (name)); + warning ("%Htraditional C lacks a separate namespace for labels, " + "identifier `%s' conflicts", &location, IDENTIFIER_POINTER (name)); if (DECL_INITIAL (decl) != 0) { - error_with_file_and_line (filename, line, "duplicate label `%s'", - IDENTIFIER_POINTER (name)); + error ("%Hduplicate label `%s'", &location, IDENTIFIER_POINTER (name)); return 0; } else @@ -2761,8 +2078,7 @@ define_label (filename, line, name) /* Mark label as having been defined. */ DECL_INITIAL (decl) = error_mark_node; /* Say where in the source. */ - DECL_SOURCE_FILE (decl) = filename; - DECL_SOURCE_LINE (decl) = line; + DECL_SOURCE_LOCATION (decl) = location; return decl; } } @@ -2773,7 +2089,7 @@ define_label (filename, line, name) store the result back using `storedecls' or you will lose. */ tree -getdecls () +getdecls (void) { return current_binding_level->names; } @@ -2781,7 +2097,7 @@ getdecls () /* Return the list of type-tags (for structs, etc) of the current level. */ tree -gettags () +gettags (void) { return current_binding_level->tags; } @@ -2791,8 +2107,7 @@ gettags () after they are modified in the light of any missing parameters. */ static void -storedecls (decls) - tree decls; +storedecls (tree decls) { current_binding_level->names = decls; } @@ -2800,63 +2115,53 @@ storedecls (decls) /* Similarly, store the list of tags of the current level. */ static void -storetags (tags) - tree tags; +storetags (tree tags) { current_binding_level->tags = tags; } /* Given NAME, an IDENTIFIER_NODE, return the structure (or union or enum) definition for that name. - Searches binding levels from BINDING_LEVEL up to the global level. - If THISLEVEL_ONLY is nonzero, searches only the specified context - (but skips any tag-transparent contexts to find one that is - meaningful for tags). + If THISLEVEL_ONLY is nonzero, searches only the current_binding_level. CODE says which kind of type the caller wants; it is RECORD_TYPE or UNION_TYPE or ENUMERAL_TYPE. If the wrong kind of type is found, an error is reported. */ static tree -lookup_tag (code, name, binding_level, thislevel_only) - enum tree_code code; - struct binding_level *binding_level; - tree name; - int thislevel_only; +lookup_tag (enum tree_code code, tree name, int thislevel_only) { - struct binding_level *level; - int thislevel = 1; + tree tag = IDENTIFIER_TAG_VALUE (name); + int thislevel = 0; + + if (!tag) + return 0; - for (level = binding_level; level; level = level->level_chain) + /* We only care about whether it's in this level if + thislevel_only was set or it might be a type clash. */ + if (thislevel_only || TREE_CODE (tag) != code) { - tree tail; - for (tail = level->tags; tail; tail = TREE_CHAIN (tail)) - { - if (TREE_PURPOSE (tail) == name) - { - if (TREE_CODE (TREE_VALUE (tail)) != code) - { - /* Definition isn't the kind we were looking for. */ - pending_invalid_xref = name; - pending_invalid_xref_file = input_filename; - pending_invalid_xref_line = lineno; - /* If in the same binding level as a declaration as a tag - of a different type, this must not be allowed to - shadow that tag, so give the error immediately. - (For example, "struct foo; union foo;" is invalid.) */ - if (thislevel) - pending_xref_error (); - } - return TREE_VALUE (tail); - } - } - if (! level->tag_transparent) - { - if (thislevel_only) - return NULL_TREE; - thislevel = 0; - } + if (current_binding_level == global_binding_level + || purpose_member (name, current_binding_level->tags)) + thislevel = 1; } - return NULL_TREE; + + if (thislevel_only && !thislevel) + return 0; + + if (TREE_CODE (tag) != code) + { + /* Definition isn't the kind we were looking for. */ + pending_invalid_xref = name; + pending_invalid_xref_location = input_location; + + /* If in the same binding level as a declaration as a tag + of a different type, this must not be allowed to + shadow that tag, so give the error immediately. + (For example, "struct foo; union foo;" is invalid.) */ + if (thislevel) + pending_xref_error (); + } + return tag; } /* Print an error message now @@ -2865,36 +2170,15 @@ lookup_tag (code, name, binding_level, thislevel_only) when used in the `struct foo;' construct for shadowing. */ void -pending_xref_error () +pending_xref_error (void) { if (pending_invalid_xref != 0) - error_with_file_and_line (pending_invalid_xref_file, - pending_invalid_xref_line, - "`%s' defined as wrong kind of tag", - IDENTIFIER_POINTER (pending_invalid_xref)); + error ("%H`%s' defined as wrong kind of tag", + &pending_invalid_xref_location, + IDENTIFIER_POINTER (pending_invalid_xref)); pending_invalid_xref = 0; } -/* Given a type, find the tag that was defined for it and return the tag name. - Otherwise return 0. */ - -static tree -lookup_tag_reverse (type) - tree type; -{ - struct binding_level *level; - - for (level = current_binding_level; level; level = level->level_chain) - { - tree tail; - for (tail = level->tags; tail; tail = TREE_CHAIN (tail)) - { - if (TREE_VALUE (tail) == type) - return TREE_PURPOSE (tail); - } - } - return NULL_TREE; -} /* Look up NAME in the current binding level and its superiors in the namespace of variables, functions and typedefs. @@ -2902,70 +2186,48 @@ lookup_tag_reverse (type) or return 0 if it is undefined. */ tree -lookup_name (name) - tree name; +lookup_name (tree name) { - tree val; - - if (current_binding_level != global_binding_level - && IDENTIFIER_LOCAL_VALUE (name)) - val = IDENTIFIER_LOCAL_VALUE (name); - else - val = IDENTIFIER_GLOBAL_VALUE (name); - return val; + tree decl = IDENTIFIER_SYMBOL_VALUE (name); + if (decl == 0 || decl == error_mark_node) + return decl; + if (C_DECL_INVISIBLE (decl)) + return 0; + return decl; } -/* Similar to `lookup_name' but look only at current binding level. */ +/* Similar to `lookup_name' but look only at the current binding level. */ -tree -lookup_name_current_level (name) - tree name; +static tree +lookup_name_current_level (tree name) { - tree t; - - if (current_binding_level == global_binding_level) - return IDENTIFIER_GLOBAL_VALUE (name); + tree decl = IDENTIFIER_SYMBOL_VALUE (name); - if (IDENTIFIER_LOCAL_VALUE (name) == 0) + if (decl == 0 || decl == error_mark_node || C_DECL_INVISIBLE (decl)) return 0; - for (t = current_binding_level->names; t; t = TREE_CHAIN (t)) - if (DECL_NAME (t) == name) - break; - - return t; -} - -/* Mark ARG for GC. */ + if (current_binding_level == global_binding_level) + return decl; -static void -mark_binding_level (arg) - void *arg; -{ - struct binding_level *level = *(struct binding_level **) arg; + /* Scan the current scope for a decl with name NAME. */ + if (chain_member (decl, current_binding_level->names)) + return decl; - for (; level != 0; level = level->level_chain) - { - 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); - } + return 0; } - + /* Create the predefined scalar types of C, and some nodes representing standard constants (0, 1, (void *) 0). Initialize the global binding level. Make definitions for built-in primitive functions. */ void -c_init_decl_processing () +c_init_decl_processing (void) { tree endlink; tree ptr_ftype_void, ptr_ftype_ptr; - + location_t save_loc = input_location; + /* Adds some ggc roots, and reserved words for c-parse.in. */ c_parse_init (); @@ -2977,6 +2239,11 @@ c_init_decl_processing () /* Make the binding_level structure for global names. */ pushlevel (0); global_binding_level = current_binding_level; + /* Declarations from c_common_nodes_and_builtins must not be associated + with this input file, lest we get differences between using and not + using preprocessed headers. */ + input_location.file = ""; + input_location.line = 0; build_common_tree_nodes (flag_signed_char); @@ -2986,8 +2253,7 @@ c_init_decl_processing () boolean_true_node = integer_one_node; boolean_false_node = integer_zero_node; - /* With GCC, C99's _Bool is always of size 1. */ - c_bool_type_node = make_unsigned_type (CHAR_TYPE_SIZE); + c_bool_type_node = make_unsigned_type (BOOL_TYPE_SIZE); TREE_SET_CODE (c_bool_type_node, BOOLEAN_TYPE); TYPE_MAX_VALUE (c_bool_type_node) = build_int_2 (1, 0); TREE_TYPE (TYPE_MAX_VALUE (c_bool_type_node)) = c_bool_type_node; @@ -3005,75 +2271,12 @@ c_init_decl_processing () = build_function_type (ptr_type_node, tree_cons (NULL_TREE, ptr_type_node, endlink)); - /* Types which are common to the fortran compiler and libf2c. When - changing these, you also need to be concerned with f/com.h. */ - - if (TYPE_PRECISION (float_type_node) - == TYPE_PRECISION (long_integer_type_node)) - { - g77_integer_type_node = long_integer_type_node; - g77_uinteger_type_node = long_unsigned_type_node; - } - else if (TYPE_PRECISION (float_type_node) - == TYPE_PRECISION (integer_type_node)) - { - g77_integer_type_node = integer_type_node; - g77_uinteger_type_node = unsigned_type_node; - } - else - g77_integer_type_node = g77_uinteger_type_node = NULL_TREE; - - if (g77_integer_type_node != NULL_TREE) - { - pushdecl (build_decl (TYPE_DECL, get_identifier ("__g77_integer"), - g77_integer_type_node)); - pushdecl (build_decl (TYPE_DECL, get_identifier ("__g77_uinteger"), - g77_uinteger_type_node)); - } - - if (TYPE_PRECISION (float_type_node) * 2 - == TYPE_PRECISION (long_integer_type_node)) - { - g77_longint_type_node = long_integer_type_node; - g77_ulongint_type_node = long_unsigned_type_node; - } - else if (TYPE_PRECISION (float_type_node) * 2 - == TYPE_PRECISION (long_long_integer_type_node)) - { - g77_longint_type_node = long_long_integer_type_node; - g77_ulongint_type_node = long_long_unsigned_type_node; - } - else - g77_longint_type_node = g77_ulongint_type_node = NULL_TREE; - - if (g77_longint_type_node != NULL_TREE) - { - pushdecl (build_decl (TYPE_DECL, get_identifier ("__g77_longint"), - g77_longint_type_node)); - pushdecl (build_decl (TYPE_DECL, get_identifier ("__g77_ulongint"), - g77_ulongint_type_node)); - } + input_location = save_loc; pedantic_lvalues = pedantic; make_fname_decl = c_make_fname_decl; start_fname_decls (); - - incomplete_decl_finalize_hook = finish_incomplete_decl; - - /* Record our roots. */ - - ggc_add_tree_root (c_global_trees, CTI_MAX); - ggc_add_root (&c_stmt_tree, 1, sizeof c_stmt_tree, mark_stmt_tree); - ggc_add_tree_root (&c_scope_stmt_stack, 1); - 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 @@ -3085,9 +2288,7 @@ c_init_decl_processing () are string merging candidates, which is wrong for C99's __func__. FIXME. */ static tree -c_make_fname_decl (id, type_dep) - tree id; - int type_dep; +c_make_fname_decl (tree id, int type_dep) { const char *name = fname_as_string (type_dep); tree decl, type, init; @@ -3098,19 +2299,20 @@ c_make_fname_decl (id, type_dep) build_index_type (size_int (length))); decl = build_decl (VAR_DECL, id, type); - /* We don't push the decl, so have to set its context here. */ - DECL_CONTEXT (decl) = current_function_decl; - + TREE_STATIC (decl) = 1; TREE_READONLY (decl) = 1; DECL_ARTIFICIAL (decl) = 1; - + init = build_string (length + 1, name); TREE_TYPE (init) = type; DECL_INITIAL (decl) = init; TREE_USED (decl) = 1; - + + if (current_function_decl) + pushdecl_function_level (decl, DECL_NAME (decl)); + finish_decl (decl, init, NULL_TREE); return decl; @@ -3122,15 +2324,13 @@ c_make_fname_decl (id, type_dep) See tree.h for its possible values. If LIBRARY_NAME is nonzero, use that for DECL_ASSEMBLER_NAME, - the name to be called if we can't opencode the function. */ + the name to be called if we can't opencode the function. If + ATTRS is nonzero, use that for the function's attribute list. */ tree -builtin_function (name, type, function_code, class, library_name) - const char *name; - tree type; - int function_code; - enum built_in_class class; - const char *library_name; +builtin_function (const char *name, tree type, int function_code, + enum built_in_class class, const char *library_name, + tree attrs) { tree decl = build_decl (FUNCTION_DECL, get_identifier (name), type); DECL_EXTERNAL (decl) = 1; @@ -3142,17 +2342,16 @@ builtin_function (name, type, function_code, class, library_name) DECL_BUILT_IN_CLASS (decl) = class; DECL_FUNCTION_CODE (decl) = function_code; - /* The return builtins leave the current function. */ - if (function_code == BUILT_IN_RETURN || function_code == BUILT_IN_EH_RETURN) - TREE_THIS_VOLATILE (decl) = 1; - /* Warn if a function in the namespace for users is used without an occasion to consider it declared. */ if (name[0] != '_' || name[1] != '_') - C_DECL_ANTICIPATED (decl) = 1; + C_DECL_INVISIBLE (decl) = 1; /* Possibly apply some default attributes to this built-in function. */ - decl_attributes (&decl, NULL_TREE, 0); + if (attrs) + decl_attributes (&decl, attrs, ATTR_FLAG_BUILT_IN); + else + decl_attributes (&decl, NULL_TREE, 0); return decl; } @@ -3161,8 +2360,7 @@ builtin_function (name, type, function_code, class, library_name) attributes. */ void -insert_default_attributes (decl) - tree decl; +c_insert_default_attributes (tree decl) { if (!TREE_PUBLIC (decl)) return; @@ -3178,16 +2376,15 @@ insert_default_attributes (decl) Otherwise, it is an error. */ void -shadow_tag (declspecs) - tree declspecs; +shadow_tag (tree declspecs) { shadow_tag_warned (declspecs, 0); } void -shadow_tag_warned (declspecs, warned) - tree declspecs; - int warned; +shadow_tag_warned (tree declspecs, int warned) + + /* 1 => we have done a pedwarn. 2 => we have done a warning, but no pedwarn. */ { @@ -3210,7 +2407,7 @@ shadow_tag_warned (declspecs, warned) /* Used to test also that TYPE_SIZE (value) != 0. That caused warning for `struct foo;' at top level in the file. */ { - tree name = lookup_tag_reverse (value); + tree name = TYPE_NAME (value); tree t; found_tag++; @@ -3226,7 +2423,7 @@ shadow_tag_warned (declspecs, warned) } else { - t = lookup_tag (code, name, current_binding_level, 1); + t = lookup_tag (code, name, 1); if (t == 0) { @@ -3258,8 +2455,8 @@ shadow_tag_warned (declspecs, warned) /* Construct an array declarator. EXPR is the expression inside [], or NULL_TREE. QUALS are the type qualifiers inside the [] (to be applied to the pointer to which a parameter array is converted). STATIC_P is - non-zero if "static" is inside the [], zero otherwise. VLA_UNSPEC_P - is non-zero is the array is [*], a VLA of unspecified length which is + nonzero if "static" is inside the [], zero otherwise. VLA_UNSPEC_P + is nonzero is the array is [*], a VLA of unspecified length which is nevertheless a complete type (not currently implemented by GCC), zero otherwise. The declarator is constructed as an ARRAY_REF (to be decoded by grokdeclarator), whose operand 0 is what's on the @@ -3268,11 +2465,7 @@ shadow_tag_warned (declspecs, warned) which has TREE_STATIC set if "static" is used. */ tree -build_array_declarator (expr, quals, static_p, vla_unspec_p) - tree expr; - tree quals; - int static_p; - int vla_unspec_p; +build_array_declarator (tree expr, tree quals, int static_p, int vla_unspec_p) { tree decl; decl = build_nt (ARRAY_REF, NULL_TREE, expr); @@ -3281,9 +2474,9 @@ build_array_declarator (expr, quals, static_p, vla_unspec_p) if (pedantic && !flag_isoc99) { if (static_p || quals != NULL_TREE) - pedwarn ("ISO C89 does not support `static' or type qualifiers in parameter array declarators"); + pedwarn ("ISO C90 does not support `static' or type qualifiers in parameter array declarators"); if (vla_unspec_p) - pedwarn ("ISO C89 does not support `[*]' array declarators"); + pedwarn ("ISO C90 does not support `[*]' array declarators"); } if (vla_unspec_p) warning ("GCC does not yet properly implement `[*]' array declarators"); @@ -3292,16 +2485,13 @@ build_array_declarator (expr, quals, static_p, vla_unspec_p) /* Set the type of an array declarator. DECL is the declarator, as constructed by build_array_declarator; TYPE is what appears on the left - of the [] and goes in operand 0. ABSTRACT_P is non-zero if it is an + of the [] and goes in operand 0. ABSTRACT_P is nonzero if it is an abstract declarator, zero otherwise; this is used to reject static and type qualifiers in abstract declarators, where they are not in the C99 grammar. */ tree -set_array_declarator_type (decl, type, abstract_p) - tree decl; - tree type; - int abstract_p; +set_array_declarator_type (tree decl, tree type, int abstract_p) { TREE_OPERAND (decl, 0) = type; if (abstract_p && (TREE_TYPE (decl) != NULL_TREE || TREE_STATIC (decl))) @@ -3312,8 +2502,7 @@ set_array_declarator_type (decl, type, abstract_p) /* Decode a "typename", such as "int **", returning a ..._TYPE node. */ tree -groktypename (typename) - tree typename; +groktypename (tree typename) { tree specs, attrs; @@ -3333,8 +2522,7 @@ groktypename (typename) /* Return a PARM_DECL node for a given pair of specs and declarator. */ tree -groktypename_in_parm_context (typename) - tree typename; +groktypename_in_parm_context (tree typename) { if (TREE_CODE (typename) != TREE_LIST) return typename; @@ -3359,14 +2547,11 @@ groktypename_in_parm_context (typename) grokfield and not through here. */ tree -start_decl (declarator, declspecs, initialized, attributes) - tree declarator, declspecs; - int initialized; - tree attributes; +start_decl (tree declarator, tree declspecs, int initialized, tree attributes) { tree decl; tree tem; - + /* An object declared as __attribute__((deprecated)) suppresses warnings of uses of other deprecated items. */ if (lookup_attribute ("deprecated", attributes)) @@ -3374,7 +2559,7 @@ start_decl (declarator, declspecs, initialized, attributes) decl = grokdeclarator (declarator, declspecs, NORMAL, initialized); - + deprecated_state = DEPRECATED_NORMAL; if (warn_main > 0 && TREE_CODE (decl) != FUNCTION_DECL @@ -3388,15 +2573,9 @@ start_decl (declarator, declspecs, initialized, attributes) switch (TREE_CODE (decl)) { case TYPE_DECL: - /* typedef foo = bar means give foo the same type as bar. - We haven't parsed bar yet, so `finish_decl' will fix that up. - Any other case of an initialization in a TYPE_DECL is an error. */ - if (pedantic || list_length (declspecs) > 1) - { - error ("typedef `%s' is initialized", - IDENTIFIER_POINTER (DECL_NAME (decl))); - initialized = 0; - } + error ("typedef `%s' is initialized (use __typeof__ instead)", + IDENTIFIER_POINTER (DECL_NAME (decl))); + initialized = 0; break; case FUNCTION_DECL: @@ -3474,14 +2653,28 @@ start_decl (declarator, declspecs, initialized, attributes) /* ANSI specifies that a tentative definition which is not merged with a non-tentative definition behaves exactly like a definition with an initializer equal to zero. (Section 3.7.2) - -fno-common gives strict ANSI behavior. Usually you don't want it. - This matters only for variables with external linkage. */ - if (! flag_no_common || ! TREE_PUBLIC (decl)) + + -fno-common gives strict ANSI behavior, though this tends to break + a large body of code that grew up without this rule. + + Thread-local variables are never common, since there's no entrenched + body of code to break, and it allows more efficient variable references + in the presence of dynamic linking. */ + + if (TREE_CODE (decl) == VAR_DECL + && !initialized + && TREE_PUBLIC (decl) + && !DECL_THREAD_LOCAL (decl) + && !flag_no_common) DECL_COMMON (decl) = 1; /* Set attributes here so if duplicate decl, will have proper attributes. */ decl_attributes (&decl, attributes, 0); + /* If #pragma weak was used, mark the decl weak now. */ + if (current_binding_level == global_binding_level) + maybe_apply_pragma_weak (decl); + if (TREE_CODE (decl) == FUNCTION_DECL && DECL_DECLARED_INLINE_P (decl) && DECL_UNINLINABLE (decl) @@ -3518,37 +2711,28 @@ start_decl (declarator, declspecs, initialized, attributes) it must be determined now, from the initial value, or it is an error. */ void -finish_decl (decl, init, asmspec_tree) - tree decl, init; - tree asmspec_tree; +finish_decl (tree decl, tree init, tree asmspec_tree) { tree type = TREE_TYPE (decl); int was_incomplete = (DECL_SIZE (decl) == 0); const char *asmspec = 0; /* If a name was specified, get the string. */ + if (current_binding_level == global_binding_level) + asmspec_tree = maybe_apply_renaming_pragma (decl, asmspec_tree); if (asmspec_tree) asmspec = TREE_STRING_POINTER (asmspec_tree); /* If `start_decl' didn't like having an initialization, ignore it now. */ if (init != 0 && DECL_INITIAL (decl) == 0) init = 0; - + /* Don't crash if parm is initialized. */ if (TREE_CODE (decl) == PARM_DECL) init = 0; if (init) - { - if (TREE_CODE (decl) != TYPE_DECL) - store_init_value (decl, init); - else - { - /* typedef foo = bar; store the type of bar as the type of foo. */ - TREE_TYPE (decl) = TREE_TYPE (init); - DECL_INITIAL (decl) = init = 0; - } - } + store_init_value (decl, init); /* Deduce size of array from initialization, if not already known */ if (TREE_CODE (type) == ARRAY_TYPE @@ -3634,14 +2818,36 @@ finish_decl (decl, init, asmspec_tree) TREE_USED (decl) = 1; } - /* If this is a function and an assembler name is specified, it isn't - builtin any more. Also reset DECL_RTL so we can give it its new - name. */ + /* If this is a function and an assembler name is specified, reset DECL_RTL + so we can give it its new name. Also, update built_in_decls if it + was a normal built-in. */ if (TREE_CODE (decl) == FUNCTION_DECL && asmspec) { - DECL_BUILT_IN_CLASS (decl) = NOT_BUILT_IN; + /* ASMSPEC is given, and not the name of a register. Mark the + name with a star so assemble_name won't munge it. */ + char *starred = alloca (strlen (asmspec) + 2); + starred[0] = '*'; + strcpy (starred + 1, asmspec); + + if (DECL_BUILT_IN_CLASS (decl) == BUILT_IN_NORMAL) + { + tree builtin = built_in_decls [DECL_FUNCTION_CODE (decl)]; + SET_DECL_RTL (builtin, NULL_RTX); + SET_DECL_ASSEMBLER_NAME (builtin, get_identifier (starred)); +#ifdef TARGET_MEM_FUNCTIONS + if (DECL_FUNCTION_CODE (decl) == BUILT_IN_MEMCPY) + init_block_move_fn (starred); + else if (DECL_FUNCTION_CODE (decl) == BUILT_IN_MEMSET) + init_block_clear_fn (starred); +#else + if (DECL_FUNCTION_CODE (decl) == BUILT_IN_BCOPY) + init_block_move_fn (starred); + else if (DECL_FUNCTION_CODE (decl) == BUILT_IN_BZERO) + init_block_clear_fn (starred); +#endif + } SET_DECL_RTL (decl, NULL_RTX); - SET_DECL_ASSEMBLER_NAME (decl, get_identifier (asmspec)); + SET_DECL_ASSEMBLER_NAME (decl, get_identifier (starred)); } /* Output the assembler code and/or RTL code for variables and functions, @@ -3650,8 +2856,9 @@ finish_decl (decl, init, asmspec_tree) if (TREE_CODE (decl) == VAR_DECL || TREE_CODE (decl) == FUNCTION_DECL) { - /* This is a no-op in c-lang.c or something real in objc-actions.c. */ - maybe_objc_check_decl (decl); + /* This is a no-op in c-lang.c or something real in objc-act.c. */ + if (c_dialect_objc ()) + objc_check_decl (decl); if (!DECL_CONTEXT (decl)) { @@ -3682,7 +2889,7 @@ finish_decl (decl, init, asmspec_tree) ordinary, non-register local variable. Historically, GCC has accepted -- but ignored -- the ASMSPEC in this case. */ - if (TREE_CODE (decl) == VAR_DECL + if (TREE_CODE (decl) == VAR_DECL && !DECL_REGISTER (decl) && !TREE_STATIC (decl)) warning_with_decl (decl, @@ -3713,8 +2920,9 @@ finish_decl (decl, init, asmspec_tree) if (TREE_CODE (decl) == TYPE_DECL) { - /* This is a no-op in c-lang.c or something real in objc-actions.c. */ - maybe_objc_check_decl (decl); + /* This is a no-op in c-lang.c or something real in objc-act.c. */ + if (c_dialect_objc ()) + objc_check_decl (decl); rest_of_decl_compilation (decl, NULL, DECL_CONTEXT (decl) == 0, 0); } @@ -3723,17 +2931,41 @@ finish_decl (decl, init, asmspec_tree) computing them in the following function definition. */ if (current_binding_level == global_binding_level) get_pending_sizes (); -} -/* If DECL has a cleanup, build and return that cleanup here. - This is a callback called by expand_expr. */ + /* Install a cleanup (aka destructor) if one was given. */ + if (TREE_CODE (decl) == VAR_DECL && !TREE_STATIC (decl)) + { + tree attr = lookup_attribute ("cleanup", DECL_ATTRIBUTES (decl)); + if (attr) + { + static bool eh_initialized_p; + + tree cleanup_id = TREE_VALUE (TREE_VALUE (attr)); + tree cleanup_decl = lookup_name (cleanup_id); + tree cleanup; -tree -maybe_build_cleanup (decl) - tree decl ATTRIBUTE_UNUSED; -{ - /* There are no cleanups in C. */ - return NULL_TREE; + /* Build "cleanup(&decl)" for the destructor. */ + cleanup = build_unary_op (ADDR_EXPR, decl, 0); + cleanup = build_tree_list (NULL_TREE, cleanup); + cleanup = build_function_call (cleanup_decl, cleanup); + + /* Don't warn about decl unused; the cleanup uses it. */ + TREE_USED (decl) = 1; + + /* Initialize EH, if we've been told to do so. */ + if (flag_exceptions && !eh_initialized_p) + { + eh_initialized_p = true; + eh_personality_libfunc + = init_one_libfunc (USING_SJLJ_EXCEPTIONS + ? "__gcc_personality_sj0" + : "__gcc_personality_v0"); + using_eh_for_cleanups (); + } + + add_stmt (build_stmt (CLEANUP_STMT, decl, cleanup)); + } + } } /* Given a parsed parameter declaration, @@ -3742,8 +2974,7 @@ maybe_build_cleanup (decl) record the given order of parms in `parm_order'. */ void -push_parm_decl (parm) - tree parm; +push_parm_decl (tree parm) { tree decl; int old_immediate_size_expand = immediate_size_expand; @@ -3781,20 +3012,20 @@ push_parm_decl (parm) and also at semicolon terminating forward decls. */ void -clear_parm_order () +clear_parm_order (void) { current_binding_level->parm_order = NULL_TREE; } +static GTY(()) int compound_literal_number; + /* Build a COMPOUND_LITERAL_EXPR. TYPE is the type given in the compound literal, which may be an incomplete array type completed by the initializer; INIT is a CONSTRUCTOR that initializes the compound literal. */ tree -build_compound_literal (type, init) - tree type; - tree init; +build_compound_literal (tree type, tree init) { /* We do not use start_decl here because we have a type, not a declarator; and do not use finish_decl because the decl should be stored inside @@ -3808,6 +3039,7 @@ build_compound_literal (type, init) DECL_CONTEXT (decl) = current_function_decl; TREE_USED (decl) = 1; TREE_TYPE (decl) = type; + TREE_READONLY (decl) = TREE_READONLY (type); store_init_value (decl, init); if (TREE_CODE (type) == ARRAY_TYPE && !COMPLETE_TYPE_P (type)) @@ -3830,12 +3062,18 @@ build_compound_literal (type, init) if (TREE_STATIC (decl)) { /* This decl needs a name for the assembler output. We also need - a unique suffix to be added to the name, for which DECL_CONTEXT - must be set. */ - DECL_NAME (decl) = get_identifier ("__compound_literal"); - DECL_CONTEXT (decl) = complit; + a unique suffix to be added to the name. */ + char *name; + + ASM_FORMAT_PRIVATE_NAME (name, "__compound_literal", + compound_literal_number); + compound_literal_number++; + DECL_NAME (decl) = get_identifier (name); + DECL_DEFER_OUTPUT (decl) = 1; + DECL_COMDAT (decl) = 1; + DECL_ARTIFICIAL (decl) = 1; + pushdecl (decl); rest_of_decl_compilation (decl, NULL, 1, 0); - DECL_CONTEXT (decl) = NULL_TREE; } return complit; @@ -3846,10 +3084,7 @@ build_compound_literal (type, init) 2 if there was no information (in which case assume 1 if DO_DEFAULT). */ int -complete_array_type (type, initial_value, do_default) - tree type; - tree initial_value; - int do_default; +complete_array_type (tree type, tree initial_value, int do_default) { tree maxindex = NULL_TREE; int value = 0; @@ -3911,6 +3146,39 @@ complete_array_type (type, initial_value, do_default) return value; } +/* Determine whether TYPE is a structure with a flexible array member, + or a union containing such a structure (possibly recursively). */ + +static bool +flexible_array_type_p (tree type) +{ + tree x; + switch (TREE_CODE (type)) + { + case RECORD_TYPE: + x = TYPE_FIELDS (type); + if (x == NULL_TREE) + return false; + while (TREE_CHAIN (x) != NULL_TREE) + x = TREE_CHAIN (x); + if (TREE_CODE (TREE_TYPE (x)) == ARRAY_TYPE + && TYPE_SIZE (TREE_TYPE (x)) == NULL_TREE + && TYPE_DOMAIN (TREE_TYPE (x)) != NULL_TREE + && TYPE_MAX_VALUE (TYPE_DOMAIN (TREE_TYPE (x))) == NULL_TREE) + return true; + return false; + case UNION_TYPE: + for (x = TYPE_FIELDS (type); x != NULL_TREE; x = TREE_CHAIN (x)) + { + if (flexible_array_type_p (TREE_TYPE (x))) + return true; + } + return false; + default: + return false; + } +} + /* Given declspecs and a declarator, determine the name and type of the object declared and construct a ..._DECL node for it. @@ -3941,11 +3209,8 @@ complete_array_type (type, initial_value, do_default) and `extern' are interpreted. */ static tree -grokdeclarator (declarator, declspecs, decl_context, initialized) - tree declspecs; - tree declarator; - enum decl_context decl_context; - int initialized; +grokdeclarator (tree declarator, tree declspecs, + enum decl_context decl_context, int initialized) { int specbits = 0; tree spec; @@ -4062,7 +3327,7 @@ grokdeclarator (declarator, declspecs, decl_context, initialized) enum rid i = C_RID_CODE (id); if ((int) i <= (int) RID_LAST_MODIFIER) { - if (i == RID_LONG && (specbits & (1 << (int) i))) + if (i == RID_LONG && (specbits & (1 << (int) RID_LONG))) { if (longlong) error ("`long long long' is too long for GCC"); @@ -4070,12 +3335,33 @@ grokdeclarator (declarator, declspecs, decl_context, initialized) { if (pedantic && !flag_isoc99 && ! in_system_header && warn_long_long) - pedwarn ("ISO C89 does not support `long long'"); + pedwarn ("ISO C90 does not support `long long'"); longlong = 1; } } else if (specbits & (1 << (int) i)) - pedwarn ("duplicate `%s'", IDENTIFIER_POINTER (id)); + { + if (i == RID_CONST || i == RID_VOLATILE || i == RID_RESTRICT) + { + if (!flag_isoc99) + pedwarn ("duplicate `%s'", IDENTIFIER_POINTER (id)); + } + else + error ("duplicate `%s'", IDENTIFIER_POINTER (id)); + } + + /* Diagnose "__thread extern". Recall that this list + is in the reverse order seen in the text. */ + if (i == RID_THREAD + && (specbits & (1 << (int) RID_EXTERN + | 1 << (int) RID_STATIC))) + { + if (specbits & 1 << (int) RID_EXTERN) + error ("`__thread' before `extern'"); + else + error ("`__thread' before `static'"); + } + specbits |= 1 << (int) i; goto found; } @@ -4195,12 +3481,11 @@ grokdeclarator (declarator, declspecs, decl_context, initialized) else { ok = 1; - if (!explicit_int && !defaulted_int && !explicit_char && pedantic) + if (!explicit_int && !defaulted_int && !explicit_char) { - pedwarn ("long, short, signed or unsigned used invalidly for `%s'", - name); - if (flag_pedantic_errors) - ok = 0; + error ("long, short, signed or unsigned used invalidly for `%s'", + name); + ok = 0; } } @@ -4241,7 +3526,7 @@ grokdeclarator (declarator, declspecs, decl_context, initialized) else if (type == char_type_node) type = unsigned_char_type_node; else if (typedef_decl) - type = unsigned_type (type); + type = c_common_unsigned_type (type); else type = unsigned_type_node; } @@ -4258,7 +3543,7 @@ grokdeclarator (declarator, declspecs, decl_context, initialized) if (specbits & 1 << (int) RID_COMPLEX) { if (pedantic && !flag_isoc99) - pedwarn ("ISO C89 does not support complex types"); + pedwarn ("ISO C90 does not support complex types"); /* If we just have "complex", it is equivalent to "complex double", but if any modifiers at all are specified it is the complex form of TYPE. E.g, "complex short" is @@ -4325,6 +3610,12 @@ grokdeclarator (declarator, declspecs, decl_context, initialized) if (specbits & 1 << (int) RID_REGISTER) nclasses++; if (specbits & 1 << (int) RID_TYPEDEF) nclasses++; + /* "static __thread" and "extern __thread" are allowed. */ + if ((specbits & (1 << (int) RID_THREAD + | 1 << (int) RID_STATIC + | 1 << (int) RID_EXTERN)) == (1 << (int) RID_THREAD)) + nclasses++; + /* Warn about storage classes that are invalid for certain kinds of declarations (parameters, typenames, etc.). */ @@ -4334,7 +3625,8 @@ grokdeclarator (declarator, declspecs, decl_context, initialized) && (specbits & ((1 << (int) RID_REGISTER) | (1 << (int) RID_AUTO) - | (1 << (int) RID_TYPEDEF)))) + | (1 << (int) RID_TYPEDEF) + | (1 << (int) RID_THREAD)))) { if (specbits & 1 << (int) RID_AUTO && (pedantic || current_binding_level == global_binding_level)) @@ -4343,8 +3635,10 @@ grokdeclarator (declarator, declspecs, decl_context, initialized) error ("function definition declared `register'"); if (specbits & 1 << (int) RID_TYPEDEF) error ("function definition declared `typedef'"); + if (specbits & 1 << (int) RID_THREAD) + error ("function definition declared `__thread'"); specbits &= ~((1 << (int) RID_TYPEDEF) | (1 << (int) RID_REGISTER) - | (1 << (int) RID_AUTO)); + | (1 << (int) RID_AUTO) | (1 << (int) RID_THREAD)); } else if (decl_context != NORMAL && nclasses > 0) { @@ -4367,7 +3661,7 @@ grokdeclarator (declarator, declspecs, decl_context, initialized) } specbits &= ~((1 << (int) RID_TYPEDEF) | (1 << (int) RID_REGISTER) | (1 << (int) RID_AUTO) | (1 << (int) RID_STATIC) - | (1 << (int) RID_EXTERN)); + | (1 << (int) RID_EXTERN) | (1 << (int) RID_THREAD)); } } else if (specbits & 1 << (int) RID_EXTERN && initialized && ! funcdef_flag) @@ -4378,12 +3672,25 @@ grokdeclarator (declarator, declspecs, decl_context, initialized) else error ("`%s' has both `extern' and initializer", name); } - else if (specbits & 1 << (int) RID_EXTERN && funcdef_flag - && current_binding_level != global_binding_level) - error ("nested function `%s' declared `extern'", name); - else if (current_binding_level == global_binding_level - && specbits & (1 << (int) RID_AUTO)) - error ("top-level declaration of `%s' specifies `auto'", name); + else if (current_binding_level == global_binding_level) + { + if (specbits & 1 << (int) RID_AUTO) + error ("top-level declaration of `%s' specifies `auto'", name); + } + else + { + if (specbits & 1 << (int) RID_EXTERN && funcdef_flag) + error ("nested function `%s' declared `extern'", name); + else if ((specbits & (1 << (int) RID_THREAD + | 1 << (int) RID_EXTERN + | 1 << (int) RID_STATIC)) + == (1 << (int) RID_THREAD)) + { + error ("function-scope `%s' implicitly auto and declared `__thread'", + name); + specbits &= ~(1 << (int) RID_THREAD); + } + } } /* Now figure out the structure of the declarator proper. @@ -4451,7 +3758,7 @@ grokdeclarator (declarator, declspecs, decl_context, initialized) tree itype = NULL_TREE; tree size = TREE_OPERAND (declarator, 1); /* The index is a signed object `sizetype' bits wide. */ - tree index_type = signed_type (sizetype); + tree index_type = c_common_signed_type (sizetype); array_ptr_quals = TREE_TYPE (declarator); array_parm_static = TREE_STATIC (declarator); @@ -4472,6 +3779,9 @@ grokdeclarator (declarator, declspecs, decl_context, initialized) type = error_mark_node; } + if (pedantic && flexible_array_type_p (type)) + pedwarn ("invalid use of structure with flexible array member"); + if (size == error_mark_node) type = error_mark_node; @@ -4511,13 +3821,13 @@ grokdeclarator (declarator, declspecs, decl_context, initialized) even if it is (eg) a const variable with known value. */ size_varies = 1; - if (pedantic) + if (!flag_isoc99 && pedantic) { if (TREE_CONSTANT (size)) - pedwarn ("ISO C89 forbids array `%s' whose size can't be evaluated", + pedwarn ("ISO C90 forbids array `%s' whose size can't be evaluated", name); else - pedwarn ("ISO C89 forbids variable-size array `%s'", + pedwarn ("ISO C90 forbids variable-size array `%s'", name); } } @@ -4553,18 +3863,27 @@ grokdeclarator (declarator, declspecs, decl_context, initialized) } if (size_varies) - itype = variable_size (itype); + { + /* We must be able to distinguish the + SAVE_EXPR_CONTEXT for the variably-sized type + so that we can set it correctly in + set_save_expr_context. The convention is + that all SAVE_EXPRs that need to be reset + have NULL_TREE for their SAVE_EXPR_CONTEXT. */ + tree cfd = current_function_decl; + if (decl_context == PARM) + current_function_decl = NULL_TREE; + itype = variable_size (itype); + if (decl_context == PARM) + current_function_decl = cfd; + } itype = build_index_type (itype); } } else if (decl_context == FIELD) { - /* ??? Need to check somewhere that this is a structure - and not a union, that this field is last, and that - this structure has at least one other named member. */ - if (pedantic && !flag_isoc99 && !in_system_header) - pedwarn ("ISO C89 does not support flexible array members"); + pedwarn ("ISO C90 does not support flexible array members"); /* ISO C99 Flexible array members are effectively identical to GCC's zero-length array extension. */ @@ -4651,7 +3970,7 @@ grokdeclarator (declarator, declspecs, decl_context, initialized) { /* Type qualifiers on a function return type are normally permitted by the standard but have no effect, so give a - warning at -W. Qualifiers on a void return type have + warning at -Wextra. Qualifiers on a void return type have meaning as a GNU extension, and are banned on function definitions in ISO C. FIXME: strictly we shouldn't pedwarn for qualified void return types except on function @@ -4908,7 +4227,7 @@ grokdeclarator (declarator, declspecs, decl_context, initialized) } else if (type_quals) type = c_build_qualified_type (type, type_quals); - + type_as_written = type; decl = build_decl (PARM_DECL, declarator, type); @@ -4923,11 +4242,7 @@ grokdeclarator (declarator, declspecs, decl_context, initialized) if (type == error_mark_node) promoted_type = type; else - { - promoted_type = simple_type_promotes_to (type); - if (! promoted_type) - promoted_type = type; - } + promoted_type = c_type_promotes_to (type); DECL_ARG_TYPE (decl) = promoted_type; DECL_ARG_TYPE_AS_WRITTEN (decl) = type_as_written; @@ -4979,6 +4294,8 @@ grokdeclarator (declarator, declspecs, decl_context, initialized) pedwarn ("invalid storage class for function `%s'", name); if (specbits & (1 << (int) RID_REGISTER)) error ("invalid storage class for function `%s'", name); + if (specbits & (1 << (int) RID_THREAD)) + error ("invalid storage class for function `%s'", name); /* Function declaration not at top level. Storage classes other than `extern' are not allowed and `extern' makes no difference. */ @@ -5038,6 +4355,8 @@ grokdeclarator (declarator, declspecs, decl_context, initialized) needed, and let dwarf2 know that the function is inlinable. */ else if (flag_inline_trees == 2 && initialized) { + if (!DECL_INLINE (decl)) + DID_INLINE_FUNC (decl) = 1; DECL_INLINE (decl) = 1; DECL_DECLARED_INLINE_P (decl) = 0; } @@ -5062,7 +4381,22 @@ grokdeclarator (declarator, declspecs, decl_context, initialized) } else if (type_quals) type = c_build_qualified_type (type, type_quals); - + + /* It is invalid to create an `extern' declaration for a + variable if there is a global declaration that is + `static'. */ + if (extern_ref && current_binding_level != global_binding_level) + { + tree global_decl; + + global_decl = identifier_global_value (declarator); + if (global_decl + && TREE_CODE (global_decl) == VAR_DECL + && !TREE_PUBLIC (global_decl)) + error ("variable previously declared `static' redeclared " + "`extern'"); + } + decl = build_decl (VAR_DECL, declarator, type); if (size_varies) C_DECL_VARIABLE_SIZE (decl) = 1; @@ -5071,22 +4405,32 @@ grokdeclarator (declarator, declspecs, decl_context, initialized) pedwarn_with_decl (decl, "variable `%s' declared `inline'"); DECL_EXTERNAL (decl) = extern_ref; + /* At top level, the presence of a `static' or `register' storage class specifier, or the absence of all storage class specifiers makes this declaration a definition (perhaps tentative). Also, the absence of both `static' and `register' makes it public. */ if (current_binding_level == global_binding_level) { - TREE_PUBLIC (decl) - = !(specbits - & ((1 << (int) RID_STATIC) | (1 << (int) RID_REGISTER))); - TREE_STATIC (decl) = ! DECL_EXTERNAL (decl); + TREE_PUBLIC (decl) = !(specbits & ((1 << (int) RID_STATIC) + | (1 << (int) RID_REGISTER))); + TREE_STATIC (decl) = !extern_ref; } /* Not at top level, only `static' makes a static definition. */ else { TREE_STATIC (decl) = (specbits & (1 << (int) RID_STATIC)) != 0; - TREE_PUBLIC (decl) = DECL_EXTERNAL (decl); + TREE_PUBLIC (decl) = extern_ref; + } + + if (specbits & 1 << (int) RID_THREAD) + { + if (targetm.have_tls) + DECL_THREAD_LOCAL (decl) = 1; + else + /* A mere warning is sure to result in improper semantics + at runtime. Don't bother to allow this to compile. */ + error ("thread-local storage not supported for this target"); } } @@ -5103,7 +4447,7 @@ grokdeclarator (declarator, declspecs, decl_context, initialized) 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); + c_mark_addressable (decl); decl_attributes (&decl, returned_attrs, 0); @@ -5130,9 +4474,7 @@ grokdeclarator (declarator, declspecs, decl_context, initialized) when FUNCDEF_FLAG is zero. */ static tree -grokparms (parms_info, funcdef_flag) - tree parms_info; - int funcdef_flag; +grokparms (tree parms_info, int funcdef_flag) { tree first_parm = TREE_CHAIN (parms_info); @@ -5227,8 +4569,7 @@ grokparms (parms_info, funcdef_flag) Zero means the parmlist ended with an ellipsis so don't append `void'. */ tree -get_parm_info (void_at_end) - int void_at_end; +get_parm_info (int void_at_end) { tree decl, t; tree types = 0; @@ -5328,7 +4669,7 @@ get_parm_info (void_at_end) defined within. Do so because these types cannot ever become complete. */ void -parmlist_tags_warning () +parmlist_tags_warning (void) { tree elt; static int already; @@ -5374,14 +4715,12 @@ parmlist_tags_warning () Define the tag as a forward-reference if it is not defined. */ tree -xref_tag (code, name) - enum tree_code code; - tree name; +xref_tag (enum tree_code code, tree name) { /* If a cross reference is requested, look up the type already defined for this tag and return it. */ - tree ref = lookup_tag (code, name, current_binding_level, 0); + tree ref = lookup_tag (code, name, 0); /* If this is the right type of tag, return what we found. (This reference will be shadowed by shadow_tag later if appropriate.) If this is the wrong type of tag, do not return it. If it was the @@ -5425,9 +4764,7 @@ xref_tag (code, name) CODE says which kind of tag NAME ought to be. */ tree -start_struct (code, name) - enum tree_code code; - tree name; +start_struct (enum tree_code code, tree name) { /* If there is already a tag defined at this binding level (as a forward reference), just return it. */ @@ -5435,28 +4772,25 @@ start_struct (code, name) tree ref = 0; if (name != 0) - ref = lookup_tag (code, name, current_binding_level, 1); + ref = lookup_tag (code, name, 1); if (ref && TREE_CODE (ref) == code) { - C_TYPE_BEING_DEFINED (ref) = 1; - TYPE_PACKED (ref) = flag_pack_struct; if (TYPE_FIELDS (ref)) { if (code == UNION_TYPE) - error ("redefinition of `union %s'", - IDENTIFIER_POINTER (name)); + error ("redefinition of `union %s'", IDENTIFIER_POINTER (name)); else - error ("redefinition of `struct %s'", - IDENTIFIER_POINTER (name)); - } - - return ref; + error ("redefinition of `struct %s'", IDENTIFIER_POINTER (name)); + } } + else + { + /* Otherwise create a forward-reference just so the tag is in scope. */ - /* Otherwise create a forward-reference just so the tag is in scope. */ + ref = make_node (code); + pushtag (name, ref); + } - ref = make_node (code); - pushtag (name, ref); C_TYPE_BEING_DEFINED (ref) = 1; TYPE_PACKED (ref) = flag_pack_struct; return ref; @@ -5471,21 +4805,50 @@ start_struct (code, name) are ultimately passed to `build_struct' to make the RECORD_TYPE node. */ tree -grokfield (filename, line, declarator, declspecs, width) - const char *filename ATTRIBUTE_UNUSED; - int line ATTRIBUTE_UNUSED; - tree declarator, declspecs, width; +grokfield (tree declarator, tree declspecs, tree width) { tree value; if (declarator == NULL_TREE && width == NULL_TREE) { - /* This is an unnamed decl. We only support unnamed - structs/unions, so check for other things and refuse them. */ - if (TREE_CODE (TREE_VALUE (declspecs)) != RECORD_TYPE - && TREE_CODE (TREE_VALUE (declspecs)) != UNION_TYPE) + /* This is an unnamed decl. + + If we have something of the form "union { list } ;" then this + is the anonymous union extension. Similarly for struct. + + If this is something of the form "struct foo;", then + If MS extensions are enabled, this is handled as an + anonymous struct. + Otherwise this is a forward declaration of a structure tag. + + If this is something of the form "foo;" and foo is a TYPE_DECL, then + If MS extensions are enabled and foo names a structure, then + again this is an anonymous struct. + Otherwise this is an error. + + Oh what a horrid tangled web we weave. I wonder if MS consciously + took this from Plan 9 or if it was an accident of implementation + that took root before someone noticed the bug... */ + + tree type = TREE_VALUE (declspecs); + + if (flag_ms_extensions && TREE_CODE (type) == TYPE_DECL) + type = TREE_TYPE (type); + if (TREE_CODE (type) == RECORD_TYPE || TREE_CODE (type) == UNION_TYPE) + { + if (flag_ms_extensions) + ; /* ok */ + else if (flag_iso) + goto warn_unnamed_field; + else if (TYPE_NAME (type) == NULL) + ; /* ok */ + else + goto warn_unnamed_field; + } + else { - error ("unnamed fields of type other than struct or union are not allowed"); + warn_unnamed_field: + warning ("declaration does not declare anything"); return NULL_TREE; } } @@ -5495,19 +4858,74 @@ grokfield (filename, line, declarator, declspecs, width) finish_decl (value, NULL_TREE, NULL_TREE); DECL_INITIAL (value) = width; - maybe_objc_check_decl (value); + if (c_dialect_objc ()) + objc_check_decl (value); return value; } +/* Generate an error for any duplicate field names in FIELDLIST. Munge + the list such that this does not present a problem later. */ + +static void +detect_field_duplicates (tree fieldlist) +{ + tree x, y; + int timeout = 10; + + /* First, see if there are more than "a few" fields. + This is trivially true if there are zero or one fields. */ + if (!fieldlist) + return; + x = TREE_CHAIN (fieldlist); + if (!x) + return; + do { + timeout--; + x = TREE_CHAIN (x); + } while (timeout > 0 && x); + + /* If there were "few" fields, avoid the overhead of allocating + a hash table. Instead just do the nested traversal thing. */ + if (timeout > 0) + { + for (x = TREE_CHAIN (fieldlist); x ; x = TREE_CHAIN (x)) + if (DECL_NAME (x)) + { + for (y = fieldlist; y != x; y = TREE_CHAIN (y)) + if (DECL_NAME (y) == DECL_NAME (x)) + { + error_with_decl (x, "duplicate member `%s'"); + DECL_NAME (x) = NULL_TREE; + } + } + } + else + { + htab_t htab = htab_create (37, htab_hash_pointer, htab_eq_pointer, NULL); + void **slot; + + for (x = fieldlist; x ; x = TREE_CHAIN (x)) + if ((y = DECL_NAME (x)) != 0) + { + slot = htab_find_slot (htab, y, INSERT); + if (*slot) + { + error_with_decl (x, "duplicate member `%s'"); + DECL_NAME (x) = NULL_TREE; + } + *slot = y; + } + + htab_delete (htab); + } +} + /* 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. */ tree -finish_struct (t, fieldlist, attributes) - tree t; - tree fieldlist; - tree attributes; +finish_struct (tree t, tree fieldlist, tree attributes) { tree x; int toplevel = global_binding_level == current_binding_level; @@ -5651,38 +5069,9 @@ finish_struct (t, fieldlist, attributes) DECL_SIZE (x) = bitsize_int (width); DECL_BIT_FIELD (x) = 1; SET_DECL_C_BIT_FIELD (x); - - if (width == 0 - && ! (* targetm.ms_bitfield_layout_p) (t)) - { - /* field size 0 => force desired amount of alignment. */ -#ifdef 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))); - DECL_USER_ALIGN (x) |= TYPE_USER_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))); - - /* 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); - if (! DECL_PACKED (x)) - DECL_USER_ALIGN (x) |= TYPE_USER_ALIGN (TREE_TYPE (x)); - } - DECL_INITIAL (x) = 0; /* Detect flexible array member in an invalid context. */ @@ -5698,35 +5087,16 @@ finish_struct (t, fieldlist, attributes) else if (! saw_named_field) error_with_decl (x, "flexible array member in otherwise empty struct"); } + + if (pedantic && TREE_CODE (t) == RECORD_TYPE + && flexible_array_type_p (TREE_TYPE (x))) + pedwarn_with_decl (x, "invalid use of structure with flexible array member"); + if (DECL_NAME (x)) saw_named_field = 1; } - /* Delete all duplicate fields from the fieldlist */ - for (x = fieldlist; x && TREE_CHAIN (x);) - /* Anonymous fields aren't duplicates. */ - if (DECL_NAME (TREE_CHAIN (x)) == 0) - x = TREE_CHAIN (x); - else - { - tree y = fieldlist; - - while (1) - { - if (DECL_NAME (y) == DECL_NAME (TREE_CHAIN (x))) - break; - if (y == x) - break; - y = TREE_CHAIN (y); - } - if (DECL_NAME (y) == DECL_NAME (TREE_CHAIN (x))) - { - error_with_decl (TREE_CHAIN (x), "duplicate member `%s'"); - TREE_CHAIN (x) = TREE_CHAIN (TREE_CHAIN (x)); - } - else - x = TREE_CHAIN (x); - } + detect_field_duplicates (fieldlist); /* Now we have the nearly final fieldlist. Record it, then lay out the structure or union (including the fields). */ @@ -5771,22 +5141,29 @@ finish_struct (t, fieldlist, attributes) /* If this structure or union completes the type of any previous variable declaration, lay it out and output its rtl. */ - if (current_binding_level->n_incomplete != 0) + if (current_binding_level->incomplete_list != NULL_TREE) { - tree decl; - for (decl = current_binding_level->names; decl; decl = TREE_CHAIN (decl)) - { + tree prev = NULL_TREE; + + for (x = current_binding_level->incomplete_list; x; x = TREE_CHAIN (x)) + { + tree decl = TREE_VALUE (x); + if (TYPE_MAIN_VARIANT (TREE_TYPE (decl)) == TYPE_MAIN_VARIANT (t) && TREE_CODE (decl) != TYPE_DECL) { layout_decl (decl, 0); - /* This is a no-op in c-lang.c or something real in objc-actions.c. */ - maybe_objc_check_decl (decl); + /* This is a no-op in c-lang.c or something real in objc-act.c. */ + if (c_dialect_objc ()) + objc_check_decl (decl); rest_of_decl_compilation (decl, NULL, toplevel, 0); if (! toplevel) expand_decl (decl); - if (--current_binding_level->n_incomplete == 0) - break; + /* Unlink X from the incomplete list. */ + if (prev) + TREE_CHAIN (prev) = TREE_CHAIN (x); + else + current_binding_level->incomplete_list = TREE_CHAIN (x); } else if (!COMPLETE_TYPE_P (TREE_TYPE (decl)) && TREE_CODE (TREE_TYPE (decl)) == ARRAY_TYPE) @@ -5800,13 +5177,17 @@ finish_struct (t, fieldlist, attributes) if (TREE_CODE (decl) != TYPE_DECL) { layout_decl (decl, 0); - maybe_objc_check_decl (decl); + if (c_dialect_objc ()) + objc_check_decl (decl); rest_of_decl_compilation (decl, NULL, toplevel, 0); if (! toplevel) expand_decl (decl); } - if (--current_binding_level->n_incomplete == 0) - break; + /* Unlink X from the incomplete list. */ + if (prev) + TREE_CHAIN (prev) = TREE_CHAIN (x); + else + current_binding_level->incomplete_list = TREE_CHAIN (x); } } } @@ -5821,8 +5202,7 @@ finish_struct (t, fieldlist, attributes) /* Lay out the type T, and its element type, and so on. */ static void -layout_array_type (t) - tree t; +layout_array_type (tree t) { if (TREE_CODE (TREE_TYPE (t)) == ARRAY_TYPE) layout_array_type (TREE_TYPE (t)); @@ -5836,8 +5216,7 @@ layout_array_type (t) may be used to declare the individual values as they are read. */ tree -start_enum (name) - tree name; +start_enum (tree name) { tree enumtype = 0; @@ -5846,7 +5225,7 @@ start_enum (name) forward reference. */ if (name != 0) - enumtype = lookup_tag (ENUMERAL_TYPE, name, current_binding_level, 1); + enumtype = lookup_tag (ENUMERAL_TYPE, name, 1); if (enumtype == 0 || TREE_CODE (enumtype) != ENUMERAL_TYPE) { @@ -5882,10 +5261,7 @@ start_enum (name) Returns ENUMTYPE. */ tree -finish_enum (enumtype, values, attributes) - tree enumtype; - tree values; - tree attributes; +finish_enum (tree enumtype, tree values, tree attributes) { tree pair, tem; tree minnode = 0, maxnode = 0, enum_value_type; @@ -5923,7 +5299,7 @@ finish_enum (enumtype, values, attributes) min_precision (maxnode, unsign)); if (TYPE_PACKED (enumtype) || precision > TYPE_PRECISION (integer_type_node)) { - tree narrowest = type_for_size (precision, unsign); + tree narrowest = c_common_type_for_size (precision, unsign); if (narrowest == 0) { warning ("enumeration values exceed range of largest integer"); @@ -5936,7 +5312,7 @@ finish_enum (enumtype, values, attributes) precision = TYPE_PRECISION (integer_type_node); if (precision == TYPE_PRECISION (integer_type_node)) - enum_value_type = type_for_size (precision, 0); + enum_value_type = c_common_type_for_size (precision, 0); else enum_value_type = enumtype; @@ -5961,11 +5337,6 @@ finish_enum (enumtype, values, attributes) tree enu = 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_USER_ALIGN (enu) = TYPE_USER_ALIGN (enumtype); - DECL_MODE (enu) = TYPE_MODE (enumtype); /* The ISO C Standard mandates enumerators to have type int, even though the underlying type of an enum type is @@ -6015,8 +5386,7 @@ finish_enum (enumtype, values, attributes) Assignment of sequential values by default is handled here. */ tree -build_enumerator (name, value) - tree name, value; +build_enumerator (tree name, tree value) { tree decl, type; @@ -6064,10 +5434,11 @@ build_enumerator (name, value) /* Now create a declaration for the enum value name. */ type = TREE_TYPE (value); - type = type_for_size (MAX (TYPE_PRECISION (type), - TYPE_PRECISION (integer_type_node)), - (TYPE_PRECISION (type) >= TYPE_PRECISION (integer_type_node) - && TREE_UNSIGNED (type))); + type = c_common_type_for_size (MAX (TYPE_PRECISION (type), + TYPE_PRECISION (integer_type_node)), + (TYPE_PRECISION (type) + >= TYPE_PRECISION (integer_type_node) + && TREE_UNSIGNED (type))); decl = build_decl (CONST_DECL, name, type); DECL_INITIAL (decl) = convert (type, value); @@ -6090,8 +5461,7 @@ build_enumerator (name, value) yyparse to report a parse error. */ int -start_function (declspecs, declarator, attributes) - tree declarator, declspecs, attributes; +start_function (tree declspecs, tree declarator, tree attributes) { tree decl1, old_decl; tree restype; @@ -6102,7 +5472,6 @@ start_function (declspecs, declarator, attributes) current_function_returns_abnormally = 0; warn_about_return_type = 0; current_extern_inline = 0; - c_function_varargs = 0; named_labels = 0; shadowed_labels = 0; @@ -6121,6 +5490,10 @@ start_function (declspecs, declarator, attributes) decl_attributes (&decl1, attributes, 0); + /* If #pragma weak was used, mark the decl weak now. */ + if (current_binding_level == global_binding_level) + maybe_apply_pragma_weak (decl1); + if (DECL_DECLARED_INLINE_P (decl1) && DECL_UNINLINABLE (decl1) && lookup_attribute ("noinline", DECL_ATTRIBUTES (decl1))) @@ -6161,31 +5534,19 @@ start_function (declspecs, declarator, attributes) && TYPE_ARG_TYPES (TREE_TYPE (decl1)) == 0) { TREE_TYPE (decl1) = TREE_TYPE (old_decl); - current_function_prototype_file = DECL_SOURCE_FILE (old_decl); - current_function_prototype_line = DECL_SOURCE_LINE (old_decl); + current_function_prototype_locus = DECL_SOURCE_LOCATION (old_decl); } - /* If there is no explicit declaration, look for any out-of-scope implicit - declarations. */ - if (old_decl == 0) - old_decl = IDENTIFIER_IMPLICIT_DECL (DECL_NAME (decl1)); - /* Optionally warn of old-fashioned def with no previous prototype. */ if (warn_strict_prototypes && TYPE_ARG_TYPES (TREE_TYPE (decl1)) == 0 - && !(old_decl != 0 - && (TYPE_ARG_TYPES (TREE_TYPE (old_decl)) != 0 - || (DECL_BUILT_IN (old_decl) - && ! C_DECL_ANTICIPATED (old_decl))))) + && C_DECL_ISNT_PROTOTYPE (old_decl)) warning ("function declaration isn't a prototype"); /* Optionally warn of any global def with no previous prototype. */ else if (warn_missing_prototypes && TREE_PUBLIC (decl1) - && !(old_decl != 0 - && (TYPE_ARG_TYPES (TREE_TYPE (old_decl)) != 0 - || (DECL_BUILT_IN (old_decl) - && ! C_DECL_ANTICIPATED (old_decl)))) - && ! MAIN_NAME_P (DECL_NAME (decl1))) + && ! MAIN_NAME_P (DECL_NAME (decl1)) + && C_DECL_ISNT_PROTOTYPE (old_decl)) warning_with_decl (decl1, "no previous prototype for `%s'"); /* Optionally warn of any def with no previous prototype if the function has already been used. */ @@ -6204,7 +5565,7 @@ start_function (declspecs, declarator, attributes) if the function has already been used. */ else if (warn_missing_declarations && old_decl != 0 && TREE_USED (old_decl) - && old_decl == IDENTIFIER_IMPLICIT_DECL (DECL_NAME (decl1))) + && C_DECL_IMPLICIT (old_decl)) warning_with_decl (decl1, "`%s' was used with no declaration before its definition"); @@ -6287,7 +5648,6 @@ start_function (declspecs, declarator, attributes) pushlevel (0); declare_parm_level (1); - current_binding_level->subblocks_tag_transparent = 1; make_decl_rtl (current_function_decl, NULL); @@ -6314,18 +5674,8 @@ start_function (declspecs, declarator, attributes) immediate_size_expand = old_immediate_size_expand; start_fname_decls (); - - return 1; -} -/* Record that this function is going to be a varargs function. - This is called before store_parm_decls, which is too early - to call mark_varargs directly. */ - -void -c_mark_varargs () -{ - c_function_varargs = 1; + return 1; } /* Store the parameter declarations into the current function declaration. @@ -6336,7 +5686,7 @@ c_mark_varargs () to specify at least the number of arguments. */ void -store_parm_decls () +store_parm_decls (void) { tree fndecl = current_function_decl; tree parm; @@ -6362,10 +5712,10 @@ store_parm_decls () /* Nonzero if this definition is written with a prototype. */ int prototype = 0; - int saved_warn_shadow = warn_shadow; + bool saved_warn_shadow = warn_shadow; /* Don't re-emit shadow warnings. */ - warn_shadow = 0; + warn_shadow = false; if (specparms != 0 && TREE_CODE (specparms) != TREE_LIST) { @@ -6390,10 +5740,10 @@ store_parm_decls () for (decl = current_binding_level->names; decl; decl = TREE_CHAIN (decl)) if (DECL_NAME (decl)) - IDENTIFIER_LOCAL_VALUE (DECL_NAME (decl)) = 0; + IDENTIFIER_SYMBOL_VALUE (DECL_NAME (decl)) = 0; for (link = current_binding_level->shadowed; link; link = TREE_CHAIN (link)) - IDENTIFIER_LOCAL_VALUE (TREE_PURPOSE (link)) = TREE_VALUE (link); + IDENTIFIER_SYMBOL_VALUE (TREE_PURPOSE (link)) = TREE_VALUE (link); current_binding_level->names = 0; current_binding_level->shadowed = 0; } @@ -6523,8 +5873,7 @@ store_parm_decls () found = build_decl (PARM_DECL, TREE_VALUE (parm), integer_type_node); DECL_ARG_TYPE (found) = TREE_TYPE (found); - DECL_SOURCE_LINE (found) = DECL_SOURCE_LINE (fndecl); - DECL_SOURCE_FILE (found) = DECL_SOURCE_FILE (fndecl); + DECL_SOURCE_LOCATION (found) = DECL_SOURCE_LOCATION (fndecl); if (flag_isoc99) pedwarn_with_decl (found, "type of `%s' defaults to `int'"); else if (extra_warnings) @@ -6613,9 +5962,8 @@ store_parm_decls () || TYPE_MAIN_VARIANT (TREE_VALUE (type)) == void_type_node) { error ("number of arguments doesn't match prototype"); - error_with_file_and_line (current_function_prototype_file, - current_function_prototype_line, - "prototype declaration"); + error ("%Hprototype declaration", + ¤t_function_prototype_locus); break; } /* Type for passing arg must be consistent with that @@ -6644,19 +5992,16 @@ store_parm_decls () { pedwarn ("promoted argument `%s' doesn't match prototype", IDENTIFIER_POINTER (DECL_NAME (parm))); - warning_with_file_and_line - (current_function_prototype_file, - current_function_prototype_line, - "prototype declaration"); + warning ("%Hprototype declaration", + ¤t_function_prototype_locus); } } else { error ("argument `%s' doesn't match prototype", IDENTIFIER_POINTER (DECL_NAME (parm))); - error_with_file_and_line (current_function_prototype_file, - current_function_prototype_line, - "prototype declaration"); + error ("%Hprototype declaration", + ¤t_function_prototype_locus); } } } @@ -6723,7 +6068,7 @@ store_parm_decls () gen_aux_info_record (fndecl, 1, 0, prototype); /* Initialize the RTL code for the function. */ - init_function_start (fndecl, input_filename, lineno); + init_function_start (fndecl); /* Begin the statement tree for this function. */ begin_stmt_tree (&DECL_SAVED_TREE (current_function_decl)); @@ -6735,7 +6080,7 @@ store_parm_decls () { tree t; - DECL_LANG_SPECIFIC (fndecl)->pending_sizes + DECL_LANG_SPECIFIC (fndecl)->pending_sizes = nreverse (get_pending_sizes ()); for (t = DECL_LANG_SPECIFIC (fndecl)->pending_sizes; t; @@ -6762,19 +6107,35 @@ store_parm_decls () This is called after parsing the body of the function definition. - NESTED is nonzero if the function being finished is nested in another. */ + NESTED is nonzero if the function being finished is nested in another. + CAN_DEFER_P is nonzero if the function may be deferred. */ void -finish_function (nested) - int nested; +finish_function (int nested, int can_defer_p) { tree fndecl = current_function_decl; -/* TREE_READONLY (fndecl) = 1; - This caused &foo to be of type ptr-to-const-function - which then got a warning when stored in a ptr-to-function variable. */ + /* When a function declaration is totally empty, e.g. + void foo(void) { } + (the argument list is irrelevant) the compstmt rule will not + bother calling pushlevel/poplevel, which means we get here with + the binding_level stack out of sync. Detect this situation by + noticing that the current_binding_level is still as + store_parm_decls left it, and do a dummy push/pop to get back to + consistency. Note that the call to pushlevel does not actually + push another binding level - see there for details. */ + if (current_binding_level->parm_flag && keep_next_if_subblocks) + { + pushlevel (0); + poplevel (1, 0, 1); + } + +#if 0 + /* This caused &foo to be of type ptr-to-const-function which then + got a warning when stored in a ptr-to-function variable. */ + TREE_READONLY (fndecl) = 1; +#endif - poplevel (1, 0, 1); BLOCK_SUPERCONTEXT (DECL_INITIAL (fndecl)) = fndecl; /* Must mark the RESULT_DECL as being in this function. */ @@ -6802,7 +6163,7 @@ finish_function (nested) #endif } } - + finish_fname_decls (); /* Tie off the statement tree for this function. */ @@ -6830,13 +6191,72 @@ finish_function (nested) free_after_compilation (cfun); cfun = NULL; + if (flag_unit_at_a_time && can_defer_p) + { + cgraph_finalize_function (fndecl, DECL_SAVED_TREE (fndecl)); + current_function_decl = NULL; + return; + } + if (! nested) { - /* Generate RTL for the body of this function. */ - c_expand_body (fndecl, nested, 1); + /* Function is parsed. + Generate RTL for the body of this function or defer + it for later expansion. */ + int uninlinable = 1; + + /* There's no reason to do any of the work here if we're only doing + semantic analysis; this code just generates RTL. */ + if (flag_syntax_only) + { + current_function_decl = NULL; + DECL_SAVED_TREE (fndecl) = NULL_TREE; + return; + } + + if (flag_inline_trees) + { + /* First, cache whether the current function is inlinable. Some + predicates depend on cfun and current_function_decl to + function completely. */ + timevar_push (TV_INTEGRATION); + uninlinable = ! tree_inlinable_function_p (fndecl, 0); + + if (can_defer_p + /* We defer functions marked inline *even if* the function + itself is not inlinable. This is because we don't yet + know if the function will actually be used; we may be + able to avoid emitting it entirely. */ + && (! uninlinable || DECL_DECLARED_INLINE_P (fndecl)) + /* Save function tree for inlining. Should return 0 if the + language does not support function deferring or the + function could not be deferred. */ + && defer_fn (fndecl)) + { + /* Let the back-end know that this function exists. */ + (*debug_hooks->deferred_inline_function) (fndecl); + timevar_pop (TV_INTEGRATION); + current_function_decl = NULL; + return; + } + + /* Then, inline any functions called in it. */ + optimize_inline_calls (fndecl); + timevar_pop (TV_INTEGRATION); + } + + c_expand_body (fndecl); + + /* Keep the function body if it's needed for inlining or dumping. */ + if (uninlinable && !dump_enabled_p (TDI_all)) + { + /* Allow the body of the function to be garbage collected. */ + DECL_SAVED_TREE (fndecl) = NULL_TREE; + } + /* Let the error reporting routines know that we're outside a function. For a nested function, this value is used in - pop_c_function_context and then reset via pop_function_context. */ + c_pop_function_context and then reset via pop_function_context. */ current_function_decl = NULL; } } @@ -6844,60 +6264,50 @@ finish_function (nested) /* Generate the RTL for a deferred function FNDECL. */ void -c_expand_deferred_function (fndecl) - tree fndecl; +c_expand_deferred_function (tree fndecl) { /* DECL_INLINE or DECL_RESULT might got cleared after the inline function was deferred, e.g. in duplicate_decls. */ if (DECL_INLINE (fndecl) && DECL_RESULT (fndecl)) { - c_expand_body (fndecl, 0, 0); + if (flag_inline_trees) + { + timevar_push (TV_INTEGRATION); + optimize_inline_calls (fndecl); + timevar_pop (TV_INTEGRATION); + } + c_expand_body (fndecl); current_function_decl = NULL; } } -/* Generate the RTL for the body of FNDECL. If NESTED_P is non-zero, +/* Called to move the SAVE_EXPRs for parameter declarations in a + nested function into the nested function. DATA is really the + nested FUNCTION_DECL. */ + +static tree +set_save_expr_context (tree *tp, + int *walk_subtrees, + void *data) +{ + if (TREE_CODE (*tp) == SAVE_EXPR && !SAVE_EXPR_CONTEXT (*tp)) + SAVE_EXPR_CONTEXT (*tp) = (tree) data; + /* Do not walk back into the SAVE_EXPR_CONTEXT; that will cause + circularity. */ + else if (DECL_P (*tp)) + *walk_subtrees = 0; + + return NULL_TREE; +} + +/* Generate the RTL for the body of FNDECL. If NESTED_P is nonzero, then we are already in the process of generating RTL for another function. If can_defer_p is zero, we won't attempt to defer the generation of RTL. */ static void -c_expand_body (fndecl, nested_p, can_defer_p) - tree fndecl; - int nested_p, can_defer_p; +c_expand_body_1 (tree fndecl, int nested_p) { - int uninlinable = 1; - - /* There's no reason to do any of the work here if we're only doing - semantic analysis; this code just generates RTL. */ - if (flag_syntax_only) - return; - - if (flag_inline_trees) - { - /* First, cache whether the current function is inlinable. Some - predicates depend on cfun and current_function_decl to - function completely. */ - timevar_push (TV_INTEGRATION); - uninlinable = ! tree_inlinable_function_p (fndecl); - - if (! uninlinable && can_defer_p - /* Save function tree for inlining. Should return 0 if the - language does not support function deferring or the - function could not be deferred. */ - && defer_fn (fndecl)) - { - /* Let the back-end know that this function exists. */ - (*debug_hooks->deferred_inline_function) (fndecl); - timevar_pop (TV_INTEGRATION); - return; - } - - /* Then, inline any functions called in it. */ - optimize_inline_calls (fndecl); - timevar_pop (TV_INTEGRATION); - } - timevar_push (TV_EXPAND); if (nested_p) @@ -6911,8 +6321,8 @@ c_expand_body (fndecl, nested_p, can_defer_p) /* Initialize the RTL code for the function. */ current_function_decl = fndecl; - input_filename = DECL_SOURCE_FILE (fndecl); - init_function_start (fndecl, input_filename, DECL_SOURCE_LINE (fndecl)); + input_location = DECL_SOURCE_LOCATION (fndecl); + init_function_start (fndecl); /* This function is being processed in whole-function mode. */ cfun->x_whole_function_mode_p = 1; @@ -6924,13 +6334,18 @@ c_expand_body (fndecl, nested_p, can_defer_p) immediate_size_expand = 0; cfun->x_dont_save_pending_sizes_p = 1; - /* If this is a varargs function, inform function.c. */ - if (c_function_varargs) - mark_varargs (); - /* Set up parameters and prepare for return, for the function. */ expand_function_start (fndecl, 0); + /* If the function has a variably modified type, there may be + SAVE_EXPRs in the parameter types. Their context must be set to + refer to this function; they cannot be expanded in the containing + function. */ + if (decl_function_context (fndecl) + && variably_modified_type_p (TREE_TYPE (fndecl))) + walk_tree (&TREE_TYPE (fndecl), set_save_expr_context, fndecl, + NULL); + /* If this function is `main', emit a call to `__main' to run global initializers, etc. */ if (DECL_NAME (fndecl) @@ -6940,11 +6355,6 @@ c_expand_body (fndecl, nested_p, can_defer_p) /* Generate the RTL for this function. */ expand_stmt (DECL_SAVED_TREE (fndecl)); - if (uninlinable) - { - /* Allow the body of the function to be garbage collected. */ - DECL_SAVED_TREE (fndecl) = NULL_TREE; - } /* We hard-wired immediate_size_expand to zero above. expand_function_end will decrement this variable. So, we set the @@ -6957,7 +6367,7 @@ c_expand_body (fndecl, nested_p, can_defer_p) (*lang_expand_function_end) (); /* Generate rtl for function exit. */ - expand_function_end (input_filename, lineno, 0); + expand_function_end (); /* If this is a nested function, protect the local variables in the stack above us from being collected while we're compiling this function. */ @@ -6971,7 +6381,7 @@ c_expand_body (fndecl, nested_p, can_defer_p) if (nested_p) ggc_pop_context (); - /* With just -W, complain only if function returns both with + /* With just -Wextra, complain only if function returns both with and without a value. */ if (extra_warnings && current_function_returns_value @@ -7011,7 +6421,7 @@ c_expand_body (fndecl, nested_p, can_defer_p) /* 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. + For a nested function, this is done in c_pop_function_context. If rest_of_compilation set this to 0, leave it 0. */ if (DECL_INITIAL (fndecl) != 0) DECL_INITIAL (fndecl) = error_mark_node; @@ -7042,11 +6452,19 @@ c_expand_body (fndecl, nested_p, can_defer_p) pop_function_context (); timevar_pop (TV_EXPAND); } + +/* Like c_expand_body_1 but only for unnested functions. */ + +void +c_expand_body (tree fndecl) +{ + c_expand_body_1 (fndecl, 0); +} /* Check the declarations given in a for-loop for satisfying the C99 constraints. */ void -check_for_loop_decls () +check_for_loop_decls (void) { tree t; @@ -7077,7 +6495,7 @@ check_for_loop_decls () if (TREE_PURPOSE (t) != 0) { enum tree_code code = TREE_CODE (TREE_VALUE (t)); - + if (code == RECORD_TYPE) error ("`struct %s' declared in `for' loop initial declaration", IDENTIFIER_POINTER (TREE_PURPOSE (t))); @@ -7105,9 +6523,9 @@ check_for_loop_decls () that keep track of the progress of compilation of the current function. Used for nested functions. */ -struct c_language_function +struct language_function GTY(()) { - struct language_function base; + struct c_language_function base; tree named_labels; tree shadowed_labels; int returns_value; @@ -7122,13 +6540,12 @@ struct c_language_function used during compilation of a C function. */ void -push_c_function_context (f) - struct function *f; +c_push_function_context (struct function *f) { - struct c_language_function *p; - p = ((struct c_language_function *) - xmalloc (sizeof (struct c_language_function))); - f->language = (struct language_function *) p; + struct language_function *p; + p = ((struct language_function *) + ggc_alloc (sizeof (struct language_function))); + f->language = p; p->base.x_stmt_tree = c_stmt_tree; p->base.x_scope_stmt_stack = c_scope_stmt_stack; @@ -7145,11 +6562,9 @@ push_c_function_context (f) /* Restore the variables used during compilation of a C function. */ void -pop_c_function_context (f) - struct function *f; +c_pop_function_context (struct function *f) { - struct c_language_function *p - = (struct c_language_function *) f->language; + struct language_function *p = f->language; tree link; /* Bring back all the labels that were shadowed. */ @@ -7179,33 +6594,13 @@ pop_c_function_context (f) current_extern_inline = p->extern_inline; 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 c_language_function *p - = (struct c_language_function *) f->language; - - if (p == 0) - return; - - mark_c_language_function (&p->base); - ggc_mark_tree (p->shadowed_labels); - ggc_mark_tree (p->named_labels); - mark_binding_level (&p->binding_level); + f->language = NULL; } /* Copy the DECL_LANG_SPECIFIC data associated with DECL. */ void -c_dup_lang_specific_decl (decl) - tree decl; +c_dup_lang_specific_decl (tree decl) { struct lang_decl *ld; @@ -7218,43 +6613,17 @@ c_dup_lang_specific_decl (decl) DECL_LANG_SPECIFIC (decl) = ld; } -/* 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)); - else if (DECL_P (t) && DECL_LANG_SPECIFIC (t)) - { - ggc_mark (DECL_LANG_SPECIFIC (t)); - c_mark_lang_decl (&DECL_LANG_SPECIFIC (t)->base); - ggc_mark_tree (DECL_LANG_SPECIFIC (t)->pending_sizes); - } -} - /* The functions below are required for functionality of doing function at once processing in the C front end. Currently these functions are not called from anywhere in the C front end, but as these changes continue, that will change. */ -/* Returns non-zero if the current statement is a full expression, +/* Returns nonzero if the current statement is a full expression, i.e. temporaries created during that statement should be destroyed at the end of the statement. */ int -stmts_are_full_exprs_p () +stmts_are_full_exprs_p (void) { return 0; } @@ -7264,7 +6633,7 @@ stmts_are_full_exprs_p () returned. */ stmt_tree -current_stmt_tree () +current_stmt_tree (void) { return &c_stmt_tree; } @@ -7272,7 +6641,7 @@ current_stmt_tree () /* Returns the stack of SCOPE_STMTs for the current function. */ tree * -current_scope_stmt_stack () +current_scope_stmt_stack (void) { return &c_scope_stmt_stack; } @@ -7281,8 +6650,7 @@ current_scope_stmt_stack () C. */ int -anon_aggr_type_p (node) - tree node ATTRIBUTE_UNUSED; +anon_aggr_type_p (tree node ATTRIBUTE_UNUSED) { return 0; } @@ -7290,7 +6658,7 @@ anon_aggr_type_p (node) /* Dummy function in place of callback used by C++. */ void -extract_interface_info () +extract_interface_info (void) { } @@ -7298,7 +6666,7 @@ extract_interface_info () statement tree. */ tree -c_begin_compound_stmt () +c_begin_compound_stmt (void) { tree stmt; @@ -7312,8 +6680,7 @@ c_begin_compound_stmt () common code. */ void -c_expand_decl_stmt (t) - tree t; +c_expand_decl_stmt (tree t) { tree decl = DECL_STMT_DECL (t); @@ -7321,27 +6688,32 @@ c_expand_decl_stmt (t) if (TREE_CODE (decl) == FUNCTION_DECL && DECL_CONTEXT (decl) == current_function_decl && DECL_SAVED_TREE (decl)) - c_expand_body (decl, /*nested_p=*/1, /*can_defer_p=*/0); + c_expand_body_1 (decl, 1); } -/* Return the IDENTIFIER_GLOBAL_VALUE of T, for use in common code, since - the definition of IDENTIFIER_GLOBAL_VALUE is different for C and C++. */ +/* Return the global value of T as a symbol. */ tree -identifier_global_value (t) - tree t; +identifier_global_value (tree t) { - return IDENTIFIER_GLOBAL_VALUE (t); + tree decl = IDENTIFIER_SYMBOL_VALUE (t); + if (decl == 0 || DECL_CONTEXT (decl) == 0) + return decl; + + /* Shadowed by something else; find the true global value. */ + for (decl = global_binding_level->names; decl; decl = TREE_CHAIN (decl)) + if (DECL_NAME (decl) == t) + return decl; + + /* Only local values for this decl. */ + return 0; } /* Record a builtin type for C. If NAME is non-NULL, it is the name used; otherwise the name is found in ridpointers from RID_INDEX. */ void -record_builtin_type (rid_index, name, type) - enum rid rid_index; - const char *name; - tree type; +record_builtin_type (enum rid rid_index, const char *name, tree type) { tree id; if (name == 0) @@ -7353,8 +6725,30 @@ record_builtin_type (rid_index, name, type) /* Build the void_list_node (void_type_node having been created). */ tree -build_void_list_node () +build_void_list_node (void) { tree t = build_tree_list (NULL_TREE, void_type_node); return t; } + +/* Return something to represent absolute declarators containing a *. + TARGET is the absolute declarator that the * contains. + TYPE_QUALS_ATTRS is a list of modifiers such as const or volatile + to apply to the pointer type, represented as identifiers, possible mixed + with attributes. + + We return an INDIRECT_REF whose "contents" are TARGET (inside a TREE_LIST, + if attributes are present) and whose type is the modifier list. */ + +tree +make_pointer_declarator (tree type_quals_attrs, tree target) +{ + tree quals, attrs; + tree itarget = target; + split_specs_attrs (type_quals_attrs, &quals, &attrs); + if (attrs != NULL_TREE) + itarget = tree_cons (attrs, target, NULL_TREE); + return build1 (INDIRECT_REF, quals, itarget); +} + +#include "gt-c-decl.h"