X-Git-Url: http://git.sourceforge.jp/view?a=blobdiff_plain;f=gcc%2Fc-decl.c;h=ba67ec5c0374cedad21ba66ea744cf90e5f0e998;hb=d8bbef5c0154532ba0d2880a6e0398e02a0e831c;hp=fdad00745575a7824d758d957a91fa91c8c0ffad;hpb=c7a6ac3e2e1a23117f35f3f46a217def541d30be;p=pf3gnuchains%2Fgcc-fork.git diff --git a/gcc/c-decl.c b/gcc/c-decl.c index fdad0074557..ba67ec5c037 100644 --- a/gcc/c-decl.c +++ b/gcc/c-decl.c @@ -1,5 +1,5 @@ /* Process declarations and variables for C compiler. - Copyright (C) 1988, 1992, 1993, 1994, 1995 Free Software Foundation, Inc. + Copyright (C) 1988, 92-97, 1998 Free Software Foundation, Inc. This file is part of GNU CC. @@ -15,7 +15,8 @@ GNU General Public License for more details. You should have received a copy of the GNU General Public License along with GNU CC; see the file COPYING. If not, write to -the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */ +the Free Software Foundation, 59 Temple Place - Suite 330, +Boston, MA 02111-1307, USA. */ /* Process declarations and symbol lookup for C front end. @@ -26,12 +27,13 @@ the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */ line numbers. For example, the CONST_DECLs for enum values. */ #include "config.h" +#include "system.h" #include "tree.h" #include "flags.h" #include "output.h" #include "c-tree.h" #include "c-lex.h" -#include +#include "toplev.h" /* In grokdeclarator, distinguish syntactic contexts of declarators. */ enum decl_context @@ -142,11 +144,13 @@ tree intQI_type_node; tree intHI_type_node; tree intSI_type_node; tree intDI_type_node; +tree intTI_type_node; tree unsigned_intQI_type_node; tree unsigned_intHI_type_node; tree unsigned_intSI_type_node; tree unsigned_intDI_type_node; +tree unsigned_intTI_type_node; /* a VOID_TYPE node. */ @@ -410,16 +414,20 @@ tree static_ctors, static_dtors; /* Forward declarations. */ -static tree grokparms (), grokdeclarator (); -tree pushdecl (); -tree builtin_function (); -void shadow_tag_warned (); - -static tree lookup_tag (); -static tree lookup_tag_reverse (); -tree lookup_name_current_level (); -static char *redeclaration_error_message (); -static void layout_array_type (); +static struct binding_level * make_binding_level PROTO((void)); +static void clear_limbo_values PROTO((tree)); +static int duplicate_decls PROTO((tree, tree, int)); +static char *redeclaration_error_message PROTO((tree, tree)); +static void storedecls PROTO((tree)); +static void storetags PROTO((tree)); +static tree lookup_tag PROTO((enum tree_code, tree, + struct binding_level *, int)); +static tree lookup_tag_reverse PROTO((tree)); +static tree grokdeclarator PROTO((tree, tree, enum decl_context, + int)); +static tree grokparms PROTO((tree, int)); +static int field_decl_cmp PROTO((const GENERIC_PTR, const GENERIC_PTR)); +static void layout_array_type PROTO((tree)); /* C-specific option variables. */ @@ -449,8 +457,12 @@ int flag_no_nonansi_builtin; int flag_traditional; +/* Nonzero means that we have builtin functions, and main is an int */ + +int flag_hosted = 1; + /* Nonzero means to allow single precision math even if we're generally - being traditional. */ + being traditional. */ int flag_allow_single_precision = 0; /* Nonzero means to treat bitfields as signed unless they say `unsigned'. */ @@ -462,9 +474,14 @@ int explicit_flag_signed_bitfields = 0; int flag_no_ident = 0; -/* Nonzero means warn about implicit declarations. */ +/* Nonzero means warn about use of implicit int. */ + +int warn_implicit_int; -int warn_implicit; +/* Nonzero means message about use of implicit function declarations; + 1 means warning; 2 means error. */ + +int mesg_implicit_function_declaration; /* Nonzero means give string constants the type `const char *' to get extra warnings from them. These warnings will be too numerous @@ -520,7 +537,7 @@ int warn_redundant_decls = 0; int warn_nested_externs = 0; -/* Warn about *printf or *scanf format/argument anomalies. */ +/* Warn about *printf or *scanf format/argument anomalies. */ int warn_format; @@ -540,13 +557,25 @@ int warn_parentheses; int warn_missing_braces; -/* Nonzero means `$' can be in an identifier. - See cccp.c for reasons why this breaks some obscure ANSI C programs. */ +/* 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; + +/* Nonzero means `$' can be in an identifier. */ #ifndef DOLLARS_IN_IDENTIFIERS #define DOLLARS_IN_IDENTIFIERS 1 #endif -int dollars_in_ident = DOLLARS_IN_IDENTIFIERS > 1; +int dollars_in_ident = DOLLARS_IN_IDENTIFIERS; /* Decode the string P as a language-specific option for C. Return 1 if it is recognized (and handle it); @@ -560,24 +589,29 @@ c_decode_option (p) { flag_traditional = 1; flag_writable_strings = 1; -#if DOLLARS_IN_IDENTIFIERS > 0 - dollars_in_ident = 1; -#endif } else if (!strcmp (p, "-fallow-single-precision")) flag_allow_single_precision = 1; + else 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 (!strcmp (p, "-fnotraditional") || !strcmp (p, "-fno-traditional")) { flag_traditional = 0; flag_writable_strings = 0; - dollars_in_ident = DOLLARS_IN_IDENTIFIERS > 1; } else if (!strcmp (p, "-fdollars-in-identifiers")) - { -#if DOLLARS_IN_IDENTIFIERS > 0 - dollars_in_ident = 1; -#endif - } + dollars_in_ident = 1; else if (!strcmp (p, "-fno-dollars-in-identifiers")) dollars_in_ident = 0; else if (!strcmp (p, "-fsigned-char")) @@ -625,11 +659,25 @@ c_decode_option (p) else if (!strcmp (p, "-fident")) flag_no_ident = 0; else if (!strcmp (p, "-ansi")) - flag_no_asm = 1, flag_no_nonansi_builtin = 1, dollars_in_ident = 0; + flag_no_asm = 1, flag_no_nonansi_builtin = 1; + 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 = 1; + { + warn_implicit_int = 1; + if (mesg_implicit_function_declaration != 2) + mesg_implicit_function_declaration = 1; + } else if (!strcmp (p, "-Wno-implicit")) - warn_implicit = 0; + warn_implicit_int = 0, mesg_implicit_function_declaration = 0; else if (!strcmp (p, "-Wwrite-strings")) warn_write_strings = 1; else if (!strcmp (p, "-Wno-write-strings")) @@ -702,6 +750,10 @@ c_decode_option (p) ; /* 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")) @@ -710,15 +762,29 @@ c_decode_option (p) 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 = 0; + 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, "-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")) { - extra_warnings = 1; /* 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 = 1; + warn_implicit_int = 1; + mesg_implicit_function_declaration = 1; warn_return_type = 1; warn_unused = 1; warn_switch = 1; @@ -726,6 +792,11 @@ c_decode_option (p) warn_char_subscripts = 1; warn_parentheses = 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 0; @@ -772,13 +843,16 @@ void finish_incomplete_decl (decl) tree decl; { - if (TREE_CODE (decl) == VAR_DECL && TREE_TYPE (decl) != error_mark_node) + if (TREE_CODE (decl) == VAR_DECL) { tree type = TREE_TYPE (decl); - if (TREE_CODE (type) == ARRAY_TYPE - && TYPE_DOMAIN (type) == 0 - && TREE_CODE (decl) != TYPE_DECL) + if (type != error_mark_node + && TREE_CODE (type) == ARRAY_TYPE + && TYPE_DOMAIN (type) == 0) { + if (! DECL_EXTERNAL (decl)) + warning_with_decl (decl, "array `%s' assumed to have one element"); + complete_array_type (type, NULL_TREE, 1); layout_decl (decl, 0); @@ -890,6 +964,22 @@ pushlevel (tag_transparent) 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; + + 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); +} + /* Exit a binding level. Pop the level off, and restore the state of the identifier-decl mappings that were in effect when this level was entered. @@ -980,7 +1070,7 @@ poplevel (keep, reverse, functionbody) if (DECL_ABSTRACT_ORIGIN (decl) != 0 && DECL_ABSTRACT_ORIGIN (decl) != decl) TREE_ADDRESSABLE (DECL_ABSTRACT_ORIGIN (decl)) = 1; - else + else if (DECL_SAVED_INSNS (decl) != 0) { push_function_context (); output_inline_function (decl); @@ -1043,6 +1133,8 @@ poplevel (keep, reverse, functionbody) 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 @@ -1299,6 +1391,10 @@ pushtag (name, type) tagged type. */ TYPE_STUB_DECL (type) = pushdecl (build_decl (TYPE_DECL, NULL_TREE, type)); + + /* An approximation for now, so we can tell this is a function-scope tag. + This will be updated in poplevel. */ + TYPE_CONTEXT (type) = DECL_CONTEXT (TYPE_STUB_DECL (type)); } /* Handle when a new declaration NEWDECL @@ -1307,11 +1403,15 @@ pushtag (name, type) Prints an error message if appropriate. If safely possible, alter OLDDECL to look like NEWDECL, and return 1. - Otherwise, return 0. */ + Otherwise, return 0. + + When DIFFERENT_BINDING_LEVEL is true, NEWDECL is an external declaration, + and OLDDECL is in an outer binding level and should thus not be changed. */ static int -duplicate_decls (newdecl, olddecl) +duplicate_decls (newdecl, olddecl, different_binding_level) register tree newdecl, olddecl; + int different_binding_level; { int types_match = comptypes (TREE_TYPE (newdecl), TREE_TYPE (olddecl)); int new_is_definition = (TREE_CODE (newdecl) == FUNCTION_DECL @@ -1321,7 +1421,8 @@ duplicate_decls (newdecl, olddecl) char *errmsg = 0; if (TREE_CODE_CLASS (TREE_CODE (olddecl)) == 'd') - DECL_MACHINE_ATTRIBUTES (newdecl) = DECL_MACHINE_ATTRIBUTES (olddecl); + DECL_MACHINE_ATTRIBUTES (newdecl) + = merge_machine_decl_attributes (olddecl, newdecl); if (TREE_CODE (newtype) == ERROR_MARK || TREE_CODE (oldtype) == ERROR_MARK) @@ -1404,8 +1505,8 @@ duplicate_decls (newdecl, olddecl) else if (!types_match) { /* Accept the return type of the new declaration if same modes. */ - tree oldreturntype = TREE_TYPE (TREE_TYPE (olddecl)); - tree newreturntype = TREE_TYPE (TREE_TYPE (newdecl)); + tree oldreturntype = TREE_TYPE (oldtype); + tree newreturntype = TREE_TYPE (newtype); /* Make sure we put the new type in the same obstack as the old ones. If the old types are not both in the same obstack, use the @@ -1422,36 +1523,37 @@ duplicate_decls (newdecl, olddecl) { /* Function types may be shared, so we can't just modify the return type of olddecl's function type. */ - tree newtype + tree trytype = build_function_type (newreturntype, - TYPE_ARG_TYPES (TREE_TYPE (olddecl))); + TYPE_ARG_TYPES (oldtype)); - types_match = comptypes (TREE_TYPE (newdecl), newtype); + types_match = comptypes (newtype, trytype); if (types_match) - TREE_TYPE (olddecl) = newtype; + oldtype = trytype; } /* Accept harmless mismatch in first argument type also. This is for ffs. */ if (TYPE_ARG_TYPES (TREE_TYPE (newdecl)) != 0 - && TYPE_ARG_TYPES (TREE_TYPE (olddecl)) != 0 - && TREE_VALUE (TYPE_ARG_TYPES (TREE_TYPE (newdecl))) != 0 - && TREE_VALUE (TYPE_ARG_TYPES (TREE_TYPE (olddecl))) != 0 - && (TYPE_MODE (TREE_VALUE (TYPE_ARG_TYPES (TREE_TYPE (newdecl)))) - == - TYPE_MODE (TREE_VALUE (TYPE_ARG_TYPES (TREE_TYPE (olddecl)))))) + && TYPE_ARG_TYPES (oldtype) != 0 + && TREE_VALUE (TYPE_ARG_TYPES (newtype)) != 0 + && TREE_VALUE (TYPE_ARG_TYPES (oldtype)) != 0 + && (TYPE_MODE (TREE_VALUE (TYPE_ARG_TYPES (newtype))) + == TYPE_MODE (TREE_VALUE (TYPE_ARG_TYPES (oldtype))))) { /* Function types may be shared, so we can't just modify the return type of olddecl's function type. */ - tree newtype - = build_function_type (TREE_TYPE (TREE_TYPE (olddecl)), + tree trytype + = build_function_type (TREE_TYPE (oldtype), tree_cons (NULL_TREE, - TREE_VALUE (TYPE_ARG_TYPES (TREE_TYPE (newdecl))), - TREE_CHAIN (TYPE_ARG_TYPES (TREE_TYPE (olddecl))))); + TREE_VALUE (TYPE_ARG_TYPES (newtype)), + TREE_CHAIN (TYPE_ARG_TYPES (oldtype)))); - types_match = comptypes (TREE_TYPE (newdecl), newtype); + types_match = comptypes (newtype, trytype); if (types_match) - TREE_TYPE (olddecl) = newtype; + oldtype = trytype; } + if (! different_binding_level) + TREE_TYPE (olddecl) = oldtype; pop_obstacks (); } @@ -1672,7 +1774,7 @@ duplicate_decls (newdecl, olddecl) /* Optionally warn about more than one declaration for the same name. */ if (errmsg == 0 && warn_redundant_decls && DECL_SOURCE_LINE (olddecl) != 0 - /* Dont warn about a function declaration + /* Don't warn about a function declaration followed by a definition. */ && !(TREE_CODE (newdecl) == FUNCTION_DECL && DECL_INITIAL (newdecl) != 0 && DECL_INITIAL (olddecl) == 0) @@ -1691,6 +1793,11 @@ duplicate_decls (newdecl, olddecl) if (types_match) { + /* When copying info to olddecl, we store into write_olddecl + instead. This allows us to avoid modifying olddecl when + different_binding_level is true. */ + tree write_olddecl = different_binding_level ? newdecl : olddecl; + /* Make sure we put the new type in the same obstack as the old ones. If the old types are not both in the same obstack, use the permanent one. */ @@ -1704,9 +1811,18 @@ duplicate_decls (newdecl, olddecl) /* Merge the data types specified in the two decls. */ if (TREE_CODE (newdecl) != FUNCTION_DECL || !DECL_BUILT_IN (olddecl)) - TREE_TYPE (newdecl) - = TREE_TYPE (olddecl) - = common_type (newtype, oldtype); + { + if (different_binding_level) + TREE_TYPE (newdecl) + = build_type_attribute_variant + (newtype, + merge_attributes (TYPE_ATTRIBUTES (newtype), + TYPE_ATTRIBUTES (oldtype))); + else + TREE_TYPE (newdecl) + = TREE_TYPE (olddecl) + = common_type (newtype, oldtype); + } /* Lay the type out, unless already done. */ if (oldtype != TREE_TYPE (newdecl)) @@ -1733,36 +1849,37 @@ duplicate_decls (newdecl, olddecl) /* Merge the type qualifiers. */ if (DECL_BUILT_IN_NONANSI (olddecl) && TREE_THIS_VOLATILE (olddecl) && !TREE_THIS_VOLATILE (newdecl)) - TREE_THIS_VOLATILE (olddecl) = 0; + TREE_THIS_VOLATILE (write_olddecl) = 0; if (TREE_READONLY (newdecl)) - TREE_READONLY (olddecl) = 1; + TREE_READONLY (write_olddecl) = 1; if (TREE_THIS_VOLATILE (newdecl)) { - TREE_THIS_VOLATILE (olddecl) = 1; + TREE_THIS_VOLATILE (write_olddecl) = 1; if (TREE_CODE (newdecl) == VAR_DECL) make_var_volatile (newdecl); } - /* Keep source location of definition rather than declaration. - Likewise, keep decl at outer scope. */ - if ((DECL_INITIAL (newdecl) == 0 && DECL_INITIAL (olddecl) != 0) - || (DECL_CONTEXT (newdecl) != 0 && DECL_CONTEXT (olddecl) == 0)) + /* Keep source location of definition rather than declaration. */ + /* When called with different_binding_level set, keep the old + information so that meaningful diagnostics can be given. */ + if (DECL_INITIAL (newdecl) == 0 && DECL_INITIAL (olddecl) != 0 + && ! different_binding_level) { DECL_SOURCE_LINE (newdecl) = DECL_SOURCE_LINE (olddecl); DECL_SOURCE_FILE (newdecl) = DECL_SOURCE_FILE (olddecl); - - if (DECL_CONTEXT (olddecl) == 0) - DECL_CONTEXT (newdecl) = 0; } /* Merge the unused-warning information. */ if (DECL_IN_SYSTEM_HEADER (olddecl)) DECL_IN_SYSTEM_HEADER (newdecl) = 1; else if (DECL_IN_SYSTEM_HEADER (newdecl)) - DECL_IN_SYSTEM_HEADER (olddecl) = 1; + DECL_IN_SYSTEM_HEADER (write_olddecl) = 1; /* Merge the initialization information. */ - if (DECL_INITIAL (newdecl) == 0) + /* When called with different_binding_level set, don't copy over + DECL_INITIAL, so that we don't accidentally change function + declarations into function definitions. */ + if (DECL_INITIAL (newdecl) == 0 && ! different_binding_level) DECL_INITIAL (newdecl) = DECL_INITIAL (olddecl); /* Merge the section attribute. @@ -1782,7 +1899,7 @@ duplicate_decls (newdecl, olddecl) } /* If cannot merge, then use the new type and qualifiers, and don't preserve the old rtl. */ - else + else if (! different_binding_level) { TREE_TYPE (olddecl) = TREE_TYPE (newdecl); TREE_READONLY (olddecl) = TREE_READONLY (newdecl); @@ -1791,12 +1908,15 @@ duplicate_decls (newdecl, olddecl) } /* Merge the storage class information. */ + DECL_WEAK (newdecl) |= DECL_WEAK (olddecl); /* For functions, static overrides non-static. */ if (TREE_CODE (newdecl) == FUNCTION_DECL) { TREE_PUBLIC (newdecl) &= TREE_PUBLIC (olddecl); /* This is since we don't automatically copy the attributes of NEWDECL into OLDDECL. */ + /* No need to worry about different_binding_level here because + then TREE_PUBLIC (newdecl) was true. */ TREE_PUBLIC (olddecl) = TREE_PUBLIC (newdecl); /* If this clears `static', clear it in the identifier too. */ if (! TREE_PUBLIC (olddecl)) @@ -1808,6 +1928,8 @@ duplicate_decls (newdecl, olddecl) DECL_EXTERNAL (newdecl) = DECL_EXTERNAL (olddecl); /* An extern decl does not override previous storage class. */ TREE_PUBLIC (newdecl) = TREE_PUBLIC (olddecl); + if (! DECL_EXTERNAL (newdecl)) + DECL_CONTEXT (newdecl) = DECL_CONTEXT (olddecl); } else { @@ -1821,37 +1943,55 @@ duplicate_decls (newdecl, olddecl) DECL_INLINE (olddecl) = 1; DECL_INLINE (newdecl) = DECL_INLINE (olddecl); - /* Get rid of any built-in function if new arg types don't match it - or if we have a function definition. */ - if (TREE_CODE (newdecl) == FUNCTION_DECL - && DECL_BUILT_IN (olddecl) - && (!types_match || new_is_definition)) - { - TREE_TYPE (olddecl) = TREE_TYPE (newdecl); - DECL_BUILT_IN (olddecl) = 0; - } - - /* If redeclaring a builtin function, and not a definition, - it stays built in. - Also preserve various other info from the definition. */ - if (TREE_CODE (newdecl) == FUNCTION_DECL && !new_is_definition) + if (TREE_CODE (newdecl) == FUNCTION_DECL) { if (DECL_BUILT_IN (olddecl)) { - DECL_BUILT_IN (newdecl) = 1; - DECL_FUNCTION_CODE (newdecl) = DECL_FUNCTION_CODE (olddecl); + /* Get rid of any built-in function if new arg types don't match it + or if we have a function definition. */ + if (! types_match || new_is_definition) + { + if (! different_binding_level) + { + TREE_TYPE (olddecl) = TREE_TYPE (newdecl); + DECL_BUILT_IN (olddecl) = 0; + } + } + else + { + /* If redeclaring a builtin function, and not a definition, + it stays built in. */ + DECL_BUILT_IN (newdecl) = 1; + DECL_FUNCTION_CODE (newdecl) = DECL_FUNCTION_CODE (olddecl); + } } - else + /* Also preserve various other info from the definition. */ + else if (! new_is_definition) DECL_FRAME_SIZE (newdecl) = DECL_FRAME_SIZE (olddecl); - - DECL_RESULT (newdecl) = DECL_RESULT (olddecl); - DECL_INITIAL (newdecl) = DECL_INITIAL (olddecl); - DECL_SAVED_INSNS (newdecl) = DECL_SAVED_INSNS (olddecl); - DECL_ARGUMENTS (newdecl) = DECL_ARGUMENTS (olddecl); + if (! new_is_definition) + { + DECL_RESULT (newdecl) = DECL_RESULT (olddecl); + /* When called with different_binding_level set, don't copy over + DECL_INITIAL, so that we don't accidentally change function + declarations into function definitions. */ + if (! different_binding_level) + DECL_INITIAL (newdecl) = DECL_INITIAL (olddecl); + DECL_SAVED_INSNS (newdecl) = DECL_SAVED_INSNS (olddecl); + DECL_ARGUMENTS (newdecl) = DECL_ARGUMENTS (olddecl); + if (DECL_INLINE (newdecl)) + DECL_ABSTRACT_ORIGIN (newdecl) = olddecl; + } + } + if (different_binding_level) + { + /* Don't output a duplicate symbol or debugging information for this + declaration. */ + TREE_ASM_WRITTEN (newdecl) = DECL_IGNORED_P (newdecl) = 1; + return 0; } /* Copy most of the decl-specific fields of NEWDECL into OLDDECL. - But preserve OLDdECL's DECL_UID. */ + But preserve OLDDECL's DECL_UID. */ { register unsigned olddecl_uid = DECL_UID (olddecl); @@ -1861,6 +2001,10 @@ duplicate_decls (newdecl, olddecl) DECL_UID (olddecl) = olddecl_uid; } + /* NEWDECL contains the merged attribute lists. + Update OLDDECL to be the same. */ + DECL_MACHINE_ATTRIBUTES (olddecl) = DECL_MACHINE_ATTRIBUTES (newdecl); + return 1; } @@ -1898,14 +2042,21 @@ pushdecl (x) { char *file; int line; + int different_binding_level = 0; + t = lookup_name_current_level (name); /* Don't type check externs here when -traditional. This is so that code with conflicting declarations inside blocks will get warnings not errors. X11 for instance depends on this. */ - if (DECL_EXTERNAL (x) && TREE_PUBLIC (x) && ! flag_traditional) - t = lookup_name_current_level_global (name); - else - t = lookup_name_current_level (name); + if (! t && DECL_EXTERNAL (x) && TREE_PUBLIC (x) && ! flag_traditional) + { + 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) + t = 0; + different_binding_level = 1; + } if (t != 0 && t == error_mark_node) /* error_mark_node is 0 for a while during initialization! */ { @@ -1919,7 +2070,29 @@ pushdecl (x) line = DECL_SOURCE_LINE (t); } - if (t != 0 && duplicate_decls (x, t)) + /* If this decl is `static' and an implicit decl was seen previously, + warn. But don't complain if -traditional, + since traditional compilers don't complain. */ + if (! flag_traditional && 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) + { + 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) { @@ -1928,28 +2101,7 @@ pushdecl (x) TREE_ASM_WRITTEN (t) = TREE_ASM_WRITTEN (x); return t; } - /* If this decl is `static' and an implicit decl was seen previously, - warn. But don't complain if -traditional, - since traditional compilers don't complain. */ - if (!flag_traditional && TREE_PUBLIC (name) - && ! TREE_PUBLIC (x) && ! DECL_EXTERNAL (x) - /* 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) - { - pedwarn ("`%s' was declared implicitly `extern' and later `static'", - IDENTIFIER_POINTER (name)); - pedwarn_with_file_and_line (file, line, - "previous declaration of `%s'", - IDENTIFIER_POINTER (name)); - } - - /* If this is a global decl, and there exists a conflicting local - decl in a parent block, then we can't return as yet, because we - need to register this decl in the current binding block. */ - if (! DECL_EXTERNAL (x) || ! TREE_PUBLIC (x) - || lookup_name (name) == t) - return t; + return t; } /* If we are processing a typedef statement, generate a whole new @@ -1971,7 +2123,7 @@ pushdecl (x) MY_TYPE object; Later parts of the compiler might only know that `object' was of - type `struct S' if if were not for code just below. With this + 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 @@ -2002,10 +2154,11 @@ pushdecl (x) if (TYPE_NAME (TREE_TYPE (x)) == 0) TYPE_NAME (TREE_TYPE (x)) = x; } - else if (TREE_TYPE (x) != error_mark_node) + 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_TYPE (x) = tt; @@ -2135,9 +2288,16 @@ pushdecl (x) /* 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)) - pedwarn ("`%s' was declared implicitly `extern' and later `static'", - IDENTIFIER_POINTER (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)); @@ -2207,11 +2367,11 @@ pushdecl (x) 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 - && oldglobal == 0 && DECL_EXTERNAL (x) && TREE_PUBLIC (x)) { - TREE_PUBLIC (name) = 1; + 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. @@ -2353,9 +2513,15 @@ implicitly_declare (functionid) rest_of_decl_compilation (decl, NULL_PTR, 0, 0); - if (warn_implicit && implicit_warning) - warning ("implicit declaration of function `%s'", - IDENTIFIER_POINTER (functionid)); + if (mesg_implicit_function_declaration && implicit_warning) + { + if (mesg_implicit_function_declaration == 2) + error ("implicit declaration of function `%s'", + IDENTIFIER_POINTER (functionid)); + else + warning ("implicit declaration of function `%s'", + IDENTIFIER_POINTER (functionid)); + } else if (warn_traditional && traditional_warning) warning ("function `%s' was previously declared within a block", IDENTIFIER_POINTER (functionid)); @@ -2384,6 +2550,15 @@ redeclaration_error_message (newdecl, olddecl) { if (flag_traditional && TREE_TYPE (newdecl) == TREE_TYPE (olddecl)) return 0; + /* pushdecl creates distinct types for TYPE_DECLs by calling + build_type_copy, so the above comparison generally fails. We do + another test against the TYPE_MAIN_VARIANT of the olddecl, which + is equivalent to what this code used to do before the build_type_copy + call. The variant type distinction should not matter for traditional + code, because it doesn't have type qualifiers. */ + if (flag_traditional + && TYPE_MAIN_VARIANT (TREE_TYPE (olddecl)) == TREE_TYPE (newdecl)) + return 0; if (DECL_IN_SYSTEM_HEADER (olddecl) || DECL_IN_SYSTEM_HEADER (newdecl)) return 0; return "redefinition of `%s'"; @@ -2712,32 +2887,9 @@ lookup_name_current_level (name) return t; } - -/* Similar to `lookup_name_current_level' but also look at the global binding - level. */ - -tree -lookup_name_current_level_global (name) - tree name; -{ - register tree t = 0; - - if (current_binding_level == global_binding_level) - return IDENTIFIER_GLOBAL_VALUE (name); - - if (IDENTIFIER_LOCAL_VALUE (name) != 0) - for (t = current_binding_level->names; t; t = TREE_CHAIN (t)) - if (DECL_NAME (t) == name) - break; - - if (t == 0) - t = IDENTIFIER_GLOBAL_VALUE (name); - - return t; -} /* Create the predefined scalar types of C, - and some nodes representing standard constants (0, 1, (void *)0). + and some nodes representing standard constants (0, 1, (void *) 0). Initialize the global binding level. Make definitions for built-in primitive functions. */ @@ -2748,8 +2900,8 @@ init_decl_processing () /* Either char* or void*. */ tree traditional_ptr_type_node; /* Data types of memcpy and strlen. */ - tree memcpy_ftype, strlen_ftype; - tree void_ftype_any; + tree memcpy_ftype, memset_ftype, strlen_ftype; + tree void_ftype_any, ptr_ftype_void, ptr_ftype_ptr; int wchar_type_size; tree temp; tree array_domain_type; @@ -2797,37 +2949,29 @@ init_decl_processing () pushdecl (build_decl (TYPE_DECL, get_identifier ("long long unsigned int"), long_long_unsigned_type_node)); + short_integer_type_node = make_signed_type (SHORT_TYPE_SIZE); + pushdecl (build_decl (TYPE_DECL, get_identifier ("short int"), + short_integer_type_node)); + + short_unsigned_type_node = make_unsigned_type (SHORT_TYPE_SIZE); + pushdecl (build_decl (TYPE_DECL, get_identifier ("short unsigned int"), + short_unsigned_type_node)); + /* `unsigned long' is the standard type for sizeof. Traditionally, use a signed type. Note that stddef.h uses `unsigned long', - and this must agree, even of long and int are the same size. */ - sizetype - = TREE_TYPE (IDENTIFIER_GLOBAL_VALUE (get_identifier (SIZE_TYPE))); + and this must agree, even if long and int are the same size. */ + set_sizetype + (TREE_TYPE (IDENTIFIER_GLOBAL_VALUE (get_identifier (SIZE_TYPE)))); if (flag_traditional && TREE_UNSIGNED (sizetype)) - sizetype = signed_type (sizetype); + set_sizetype (signed_type (sizetype)); ptrdiff_type_node = TREE_TYPE (IDENTIFIER_GLOBAL_VALUE (get_identifier (PTRDIFF_TYPE))); - TREE_TYPE (TYPE_SIZE (integer_type_node)) = sizetype; - TREE_TYPE (TYPE_SIZE (char_type_node)) = sizetype; - TREE_TYPE (TYPE_SIZE (unsigned_type_node)) = sizetype; - TREE_TYPE (TYPE_SIZE (long_unsigned_type_node)) = sizetype; - TREE_TYPE (TYPE_SIZE (long_integer_type_node)) = sizetype; - TREE_TYPE (TYPE_SIZE (long_long_integer_type_node)) = sizetype; - TREE_TYPE (TYPE_SIZE (long_long_unsigned_type_node)) = sizetype; - error_mark_node = make_node (ERROR_MARK); TREE_TYPE (error_mark_node) = error_mark_node; - short_integer_type_node = make_signed_type (SHORT_TYPE_SIZE); - pushdecl (build_decl (TYPE_DECL, get_identifier ("short int"), - short_integer_type_node)); - - short_unsigned_type_node = make_unsigned_type (SHORT_TYPE_SIZE); - pushdecl (build_decl (TYPE_DECL, get_identifier ("short unsigned int"), - short_unsigned_type_node)); - /* Define both `signed char' and `unsigned char'. */ signed_char_type_node = make_signed_type (CHAR_TYPE_SIZE); pushdecl (build_decl (TYPE_DECL, get_identifier ("signed char"), @@ -2849,6 +2993,9 @@ init_decl_processing () intDI_type_node = make_signed_type (GET_MODE_BITSIZE (DImode)); pushdecl (build_decl (TYPE_DECL, NULL_TREE, intDI_type_node)); + intTI_type_node = make_signed_type (GET_MODE_BITSIZE (TImode)); + pushdecl (build_decl (TYPE_DECL, NULL_TREE, intDI_type_node)); + unsigned_intQI_type_node = make_unsigned_type (GET_MODE_BITSIZE (QImode)); pushdecl (build_decl (TYPE_DECL, NULL_TREE, unsigned_intQI_type_node)); @@ -2861,6 +3008,9 @@ init_decl_processing () unsigned_intDI_type_node = make_unsigned_type (GET_MODE_BITSIZE (DImode)); pushdecl (build_decl (TYPE_DECL, NULL_TREE, unsigned_intDI_type_node)); + unsigned_intTI_type_node = make_unsigned_type (GET_MODE_BITSIZE (TImode)); + pushdecl (build_decl (TYPE_DECL, NULL_TREE, unsigned_intTI_type_node)); + float_type_node = make_node (REAL_TYPE); TYPE_PRECISION (float_type_node) = FLOAT_TYPE_SIZE; pushdecl (build_decl (TYPE_DECL, ridpointers[(int) RID_FLOAT], @@ -3055,7 +3205,20 @@ init_decl_processing () sizetype, endlink)))); - builtin_function ("__builtin_constant_p", int_ftype_int, + memset_ftype /* memset prototype */ + = build_function_type (traditional_ptr_type_node, + tree_cons (NULL_TREE, ptr_type_node, + tree_cons (NULL_TREE, integer_type_node, + tree_cons (NULL_TREE, + sizetype, + endlink)))); + + ptr_ftype_void = build_function_type (ptr_type_node, endlink); + ptr_ftype_ptr + = build_function_type (ptr_type_node, + tree_cons (NULL_TREE, ptr_type_node, endlink)); + + builtin_function ("__builtin_constant_p", default_function_type, BUILT_IN_CONSTANT_P, NULL_PTR); builtin_function ("__builtin_return_address", @@ -3072,6 +3235,42 @@ init_decl_processing () endlink)), BUILT_IN_FRAME_ADDRESS, NULL_PTR); + builtin_function ("__builtin_aggregate_incoming_address", + build_function_type (ptr_type_node, NULL_TREE), + BUILT_IN_AGGREGATE_INCOMING_ADDRESS, NULL_PTR); + + /* Hooks for the DWARF 2 __throw routine. */ + builtin_function ("__builtin_unwind_init", + build_function_type (void_type_node, endlink), + BUILT_IN_UNWIND_INIT, NULL_PTR); + builtin_function ("__builtin_fp", ptr_ftype_void, BUILT_IN_FP, NULL_PTR); + builtin_function ("__builtin_sp", ptr_ftype_void, BUILT_IN_SP, NULL_PTR); + builtin_function ("__builtin_dwarf_fp_regnum", + build_function_type (unsigned_type_node, endlink), + BUILT_IN_DWARF_FP_REGNUM, NULL_PTR); + builtin_function ("__builtin_dwarf_reg_size", int_ftype_int, + BUILT_IN_DWARF_REG_SIZE, NULL_PTR); + builtin_function ("__builtin_frob_return_addr", ptr_ftype_ptr, + BUILT_IN_FROB_RETURN_ADDR, NULL_PTR); + builtin_function ("__builtin_extract_return_addr", ptr_ftype_ptr, + BUILT_IN_EXTRACT_RETURN_ADDR, NULL_PTR); + builtin_function ("__builtin_set_return_addr_reg", + build_function_type (void_type_node, + tree_cons (NULL_TREE, + ptr_type_node, + endlink)), + BUILT_IN_SET_RETURN_ADDR_REG, NULL_PTR); + builtin_function ("__builtin_eh_stub", ptr_ftype_void, + BUILT_IN_EH_STUB, NULL_PTR); + builtin_function + ("__builtin_set_eh_regs", + build_function_type (void_type_node, + tree_cons (NULL_TREE, ptr_type_node, + tree_cons (NULL_TREE, + type_for_mode (ptr_mode, 0), + endlink))), + BUILT_IN_SET_EH_REGS, NULL_PTR); + builtin_function ("__builtin_alloca", build_function_type (ptr_type_node, tree_cons (NULL_TREE, @@ -3163,6 +3362,8 @@ init_decl_processing () BUILT_IN_MEMCPY, "memcpy"); builtin_function ("__builtin_memcmp", int_ftype_cptr_cptr_sizet, BUILT_IN_MEMCMP, "memcmp"); + builtin_function ("__builtin_memset", memset_ftype, + BUILT_IN_MEMSET, "memset"); builtin_function ("__builtin_strcmp", int_ftype_string_string, BUILT_IN_STRCMP, "strcmp"); builtin_function ("__builtin_strcpy", string_ftype_ptr_ptr, @@ -3187,6 +3388,19 @@ init_decl_processing () BUILT_IN_COS, "cos"); builtin_function ("__builtin_cosl", ldouble_ftype_ldouble, BUILT_IN_COS, "cosl"); + builtin_function ("__builtin_setjmp", + build_function_type (integer_type_node, + tree_cons (NULL_TREE, + ptr_type_node, endlink)), + BUILT_IN_SETJMP, NULL_PTR); + builtin_function ("__builtin_longjmp", + build_function_type + (void_type_node, + tree_cons (NULL, ptr_type_node, + tree_cons (NULL_TREE, + integer_type_node, + endlink))), + BUILT_IN_LONGJMP, NULL_PTR); /* In an ANSI C program, it is okay to supply built-in meanings for these functions, since applications cannot validly use them @@ -3203,6 +3417,7 @@ init_decl_processing () builtin_function ("memcpy", memcpy_ftype, BUILT_IN_MEMCPY, NULL_PTR); builtin_function ("memcmp", int_ftype_cptr_cptr_sizet, BUILT_IN_MEMCMP, NULL_PTR); + builtin_function ("memset", memset_ftype, BUILT_IN_MEMSET, NULL_PTR); builtin_function ("strcmp", int_ftype_string_string, BUILT_IN_STRCMP, NULL_PTR); builtin_function ("strcpy", string_ftype_ptr_ptr, BUILT_IN_STRCPY, @@ -3245,8 +3460,6 @@ init_decl_processing () BUILT_IN_FMOD, NULL_PTR); builtin_function ("__builtin_frem", double_ftype_double_double, BUILT_IN_FREM, NULL_PTR); - builtin_function ("__builtin_memset", ptr_ftype_ptr_int_int, - BUILT_IN_MEMSET, NULL_PTR); builtin_function ("__builtin_getexp", double_ftype_double, BUILT_IN_GETEXP, NULL_PTR); builtin_function ("__builtin_getman", double_ftype_double, BUILT_IN_GETMAN, @@ -3332,9 +3545,14 @@ shadow_tag_warned (declspecs, warned) { int found_tag = 0; register tree link; + tree specs, attrs; pending_invalid_xref = 0; + /* Remove the attributes from declspecs, since they will confuse the + following code. */ + split_specs_attrs (declspecs, &specs, &attrs); + for (link = declspecs; link; link = TREE_CHAIN (link)) { register tree value = TREE_VALUE (link); @@ -3371,7 +3589,7 @@ shadow_tag_warned (declspecs, warned) } else { - if (!warned) + if (!warned && ! in_system_header) { warning ("useless keyword or type name in empty declaration"); warned = 2; @@ -3435,9 +3653,10 @@ groktypename_in_parm_context (typename) int debug_temp_inits = 1; tree -start_decl (declarator, declspecs, initialized) +start_decl (declarator, declspecs, initialized, attributes, prefix_attributes) tree declarator, declspecs; int initialized; + tree attributes, prefix_attributes; { register tree decl = grokdeclarator (declarator, declspecs, NORMAL, initialized); @@ -3447,6 +3666,9 @@ start_decl (declarator, declspecs, initialized) /* The corresponding pop_obstacks is in finish_decl. */ push_obstacks_nochange (); + if (warn_main && !strcmp (IDENTIFIER_POINTER (declarator), "main")) + warning_with_decl (decl, "`%s' is usually a function"); + if (initialized) /* Is it valid for this decl to have an initializer at all? If not, set INITIALIZED to zero, which will indirectly @@ -3531,14 +3753,21 @@ start_decl (declarator, declspecs, initialized) if (TREE_CODE (decl) == FUNCTION_DECL) gen_aux_info_record (decl, 0, 0, TYPE_ARG_TYPES (TREE_TYPE (decl)) != 0); + /* 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)) + DECL_COMMON (decl) = 1; + + /* Set attributes here so if duplicate decl, will have proper attributes. */ + decl_attributes (decl, attributes, prefix_attributes); + /* Add this decl to the current binding level. TEM may equal DECL or it may be a previous decl of the same name. */ tem = pushdecl (decl); - /* For C and Obective-C, we by default put things in .common when - possible. */ - DECL_COMMON (tem) = 1; - /* For a local variable, define the RTL now. */ if (current_binding_level != global_binding_level /* But not if this is a duplicate decl @@ -3680,10 +3909,11 @@ finish_decl (decl, init, asmspec_tree) Also if it is not file scope. Otherwise, let it through, but if it is not `extern' then it may cause an error message later. */ - /* We must use DECL_CONTEXT instead of current_binding_level, - because a duplicate_decls call could have changed the binding - level of this decl. */ - (DECL_INITIAL (decl) != 0 || DECL_CONTEXT (decl) != 0) + /* A duplicate_decls call could have changed an extern + declaration into a file scope one. This can be detected + by TREE_ASM_WRITTEN being set. */ + (DECL_INITIAL (decl) != 0 + || (DECL_CONTEXT (decl) != 0 && ! TREE_ASM_WRITTEN (decl))) : /* An automatic variable with an incomplete type is an error. */ @@ -3701,6 +3931,9 @@ finish_decl (decl, init, asmspec_tree) else error_with_decl (decl, "storage size of `%s' isn't constant"); } + + if (TREE_USED (type)) + TREE_USED (decl) = 1; } /* If this is a function and an assembler name is specified, it isn't @@ -3725,7 +3958,9 @@ finish_decl (decl, init, asmspec_tree) end_temporary_allocation (); /* This is a no-op in c-lang.c or something real in objc-actions.c. */ maybe_objc_check_decl (decl); - rest_of_decl_compilation (decl, asmspec, DECL_CONTEXT (decl) == 0, + rest_of_decl_compilation (decl, asmspec, + (DECL_CONTEXT (decl) == 0 + || TREE_ASM_WRITTEN (decl)), 0); pop_obstacks (); } @@ -3791,7 +4026,7 @@ finish_decl (decl, init, asmspec_tree) { preserve_initializer (); /* Hack? Set the permanent bit for something that is permanent, - but not on the permenent obstack, so as to convince + but not on the permanent obstack, so as to convince output_constant_def to make its rtl on the permanent obstack. */ TREE_PERMANENT (DECL_INITIAL (decl)) = 1; @@ -3871,7 +4106,10 @@ push_parm_decl (parm) /* The corresponding pop_obstacks is in finish_decl. */ push_obstacks_nochange (); - decl = grokdeclarator (TREE_VALUE (parm), TREE_PURPOSE (parm), PARM, 0); + decl = grokdeclarator (TREE_VALUE (TREE_PURPOSE (parm)), + TREE_PURPOSE (TREE_PURPOSE (parm)), PARM, 0); + decl_attributes (decl, TREE_VALUE (TREE_VALUE (parm)), + TREE_PURPOSE (TREE_VALUE (parm))); #if 0 if (DECL_NAME (decl)) @@ -3964,12 +4202,6 @@ complete_array_type (type, initial_value, do_default) TYPE_DOMAIN (type) = build_index_type (maxindex); if (!TREE_TYPE (maxindex)) TREE_TYPE (maxindex) = TYPE_DOMAIN (type); -#if 0 /* I took out this change - together with the change in build_array_type. --rms */ - change_main_variant (type, - build_array_type (TREE_TYPE (type), - TYPE_DOMAIN (type))); -#endif } /* Lay out the type now that we can get the real answer. */ @@ -4087,7 +4319,7 @@ grokdeclarator (declarator, declspecs, decl_context, initialized) even if it occurs where parms are expected. Then store_parm_decls will reject it and not use it as a parm. */ if (decl_context == NORMAL && !funcdef_flag - && current_binding_level->level_chain == global_binding_level) + && current_binding_level->parm_flag) decl_context = PARM; /* Look through the decl specs and record which ones appear. @@ -4175,10 +4407,21 @@ grokdeclarator (declarator, declspecs, decl_context, initialized) if (type == 0) { - if (funcdef_flag && warn_return_type - && ! (specbits & ((1 << (int) RID_LONG) | (1 << (int) RID_SHORT) - | (1 << (int) RID_SIGNED) | (1 << (int) RID_UNSIGNED)))) - warn_about_return_type = 1; + if ((! (specbits & ((1 << (int) RID_LONG) | (1 << (int) RID_SHORT) + | (1 << (int) RID_SIGNED) + | (1 << (int) RID_UNSIGNED)))) + && ! (in_system_header && ! allocation_temporary_p ())) + { + /* C9x will probably require a diagnostic here. + For now, issue a warning if -Wreturn-type and this is a function, + or if -Wimplicit; prefer the former warning since it is more + explicit. */ + if ((warn_implicit_int || warn_return_type) && funcdef_flag) + warn_about_return_type = 1; + else if (warn_implicit_int) + warning ("type defaults to `int' in declaration of `%s'", name); + } + defaulted_int = 1; type = integer_type_node; } @@ -4188,7 +4431,7 @@ grokdeclarator (declarator, declspecs, decl_context, initialized) /* Long double is a special combination. */ - if ((specbits & 1 << (int) RID_LONG) + if ((specbits & 1 << (int) RID_LONG) && ! longlong && TYPE_MAIN_VARIANT (type) == double_type_node) { specbits &= ~ (1 << (int) RID_LONG); @@ -4202,11 +4445,9 @@ grokdeclarator (declarator, declspecs, decl_context, initialized) { int ok = 0; - if (TREE_CODE (type) != INTEGER_TYPE) - error ("long, short, signed or unsigned invalid for `%s'", name); - else if ((specbits & 1 << (int) RID_LONG) - && (specbits & 1 << (int) RID_SHORT)) - error ("long and short specified together for `%s'", name); + if ((specbits & 1 << (int) RID_LONG) + && (specbits & 1 << (int) RID_SHORT)) + error ("both long and short specified for `%s'", name); else if (((specbits & 1 << (int) RID_LONG) || (specbits & 1 << (int) RID_SHORT)) && explicit_char) @@ -4214,10 +4455,21 @@ grokdeclarator (declarator, declspecs, decl_context, initialized) else if (((specbits & 1 << (int) RID_LONG) || (specbits & 1 << (int) RID_SHORT)) && TREE_CODE (type) == REAL_TYPE) - error ("long or short specified with floating type for `%s'", name); + { + static int already = 0; + + error ("long or short specified with floating type for `%s'", name); + if (! already && ! pedantic) + { + error ("the only valid combination is `long double'"); + already = 1; + } + } else if ((specbits & 1 << (int) RID_SIGNED) && (specbits & 1 << (int) RID_UNSIGNED)) - error ("signed and unsigned given together for `%s'", name); + error ("both signed and unsigned specified for `%s'", name); + else if (TREE_CODE (type) != INTEGER_TYPE) + error ("long, short, signed or unsigned invalid for `%s'", name); else { ok = 1; @@ -4512,6 +4764,18 @@ grokdeclarator (declarator, declspecs, decl_context, initialized) convert (index_type, size), convert (index_type, size_one_node))); + /* If that overflowed, the array is too big. + ??? While a size of INT_MAX+1 technically shouldn't cause + an overflow (because we subtract 1), the overflow is recorded + during the conversion to index_type, before the subtraction. + Handling this case seems like an unnecessary complication. */ + if (TREE_OVERFLOW (itype)) + { + error ("size of array `%s' is too large", name); + type = error_mark_node; + continue; + } + if (size_varies) itype = variable_size (itype); itype = build_index_type (itype); @@ -4630,7 +4894,7 @@ grokdeclarator (declarator, declspecs, decl_context, initialized) { register tree link; - for (link = current_function_parm_tags; + for (link = last_function_parm_tags; link; link = TREE_CHAIN (link)) TYPE_CONTEXT (TREE_VALUE (link)) = type; @@ -4687,6 +4951,13 @@ grokdeclarator (declarator, declspecs, decl_context, initialized) /* Now TYPE has the actual type. */ + /* Did array size calculations overflow? */ + + if (TREE_CODE (type) == ARRAY_TYPE + && TYPE_SIZE (type) + && TREE_OVERFLOW (TYPE_SIZE (type))) + error ("size of array `%s' is too large", name); + /* If this is declaring a typedef name, return a TYPE_DECL. */ if (specbits & (1 << (int) RID_TYPEDEF)) @@ -4699,11 +4970,11 @@ grokdeclarator (declarator, declspecs, decl_context, initialized) pedwarn ("ANSI C forbids const or volatile function types"); if (constp || volatilep) type = c_build_type_variant (type, constp, volatilep); - pop_obstacks (); decl = build_decl (TYPE_DECL, declarator, type); if ((specbits & (1 << (int) RID_SIGNED)) || (typedef_decl && C_TYPEDEF_EXPLICITLY_SIGNED (typedef_decl))) C_TYPEDEF_EXPLICITLY_SIGNED (decl) = 1; + pop_obstacks (); return decl; } @@ -4883,6 +5154,13 @@ grokdeclarator (declarator, declspecs, decl_context, initialized) && ! DECL_IN_SYSTEM_HEADER (decl)) pedwarn ("ANSI C forbids const or volatile functions"); + if (pedantic + && TYPE_MAIN_VARIANT (TREE_TYPE (TREE_TYPE (decl))) == void_type_node + && (TYPE_READONLY (TREE_TYPE (TREE_TYPE (decl))) + || TYPE_VOLATILE (TREE_TYPE (TREE_TYPE (decl)))) + && ! DECL_IN_SYSTEM_HEADER (decl)) + pedwarn ("ANSI C forbids const or volatile void function return type"); + if (volatilep && TREE_TYPE (TREE_TYPE (decl)) != void_type_node) warning ("`noreturn' function returns non-void value"); @@ -4900,9 +5178,6 @@ grokdeclarator (declarator, declspecs, decl_context, initialized) if (! strcmp (IDENTIFIER_POINTER (declarator), "main")) warning ("cannot inline function `main'"); - else if (last && (TYPE_MAIN_VARIANT (TREE_VALUE (last)) - != void_type_node)) - warning ("inline declaration ignored for function with `...'"); else /* Assume that otherwise the function can be inlined. */ DECL_INLINE (decl) = 1; @@ -5222,7 +5497,7 @@ parmlist_tags_warning () enum tree_code code = TREE_CODE (TREE_VALUE (elt)); /* An anonymous union parm type is meaningful as a GNU extension. So don't warn for that. */ - if (code == UNION_TYPE && !pedantic) + if (code == UNION_TYPE && TREE_PURPOSE (elt) == 0 && !pedantic) continue; if (TREE_PURPOSE (elt) != 0) warning ("`%s %s' declared inside parameter list", @@ -5325,6 +5600,7 @@ start_struct (code, name) if (ref && TREE_CODE (ref) == code) { C_TYPE_BEING_DEFINED (ref) = 1; + TYPE_PACKED (ref) = flag_pack_struct; if (TYPE_FIELDS (ref)) error ((code == UNION_TYPE ? "redefinition of `union %s'" : "redefinition of `struct %s'"), @@ -5338,6 +5614,7 @@ start_struct (code, name) ref = make_node (code); pushtag (name, ref); C_TYPE_BEING_DEFINED (ref) = 1; + TYPE_PACKED (ref) = flag_pack_struct; return ref; } @@ -5372,20 +5649,34 @@ grokfield (filename, line, declarator, declspecs, width) /* Function to help qsort sort FIELD_DECLs by name order. */ static int -field_decl_cmp (x, y) - tree *x, *y; +field_decl_cmp (xp, yp) + const GENERIC_PTR xp; + const GENERIC_PTR yp; { - return (long)DECL_NAME (*x) - (long)DECL_NAME (*y); + tree *x = (tree *)xp, *y = (tree *)yp; + + if (DECL_NAME (*x) == DECL_NAME (*y)) + return 0; + if (DECL_NAME (*x) == NULL) + return -1; + if (DECL_NAME (*y) == NULL) + return 1; + if (DECL_NAME (*x) < DECL_NAME (*y)) + return -1; + return 1; } /* Fill in the fields of a RECORD_TYPE or UNION_TYPE node, T. FIELDLIST is a chain of FIELD_DECL nodes for the fields. + ATTRIBUTES are attributes to be applied to the structure. We also do a pop_obstacks to match the push in start_struct. */ tree -finish_struct (t, fieldlist) - register tree t, fieldlist; +finish_struct (t, fieldlist, attributes) + tree t; + tree fieldlist; + tree attributes; { register tree x; int old_momentary; @@ -5396,6 +5687,8 @@ finish_struct (t, fieldlist) TYPE_SIZE (t) = 0; + decl_attributes (t, attributes, NULL_TREE); + /* Nameless union parm types are useful as GCC extension. */ if (! (TREE_CODE (t) == UNION_TYPE && TYPE_NAME (t) == 0) && !pedantic) /* Otherwise, warn about any struct or union def. in parmlist. */ @@ -5411,9 +5704,17 @@ finish_struct (t, fieldlist) old_momentary = suspend_momentary (); - if (fieldlist == 0 && pedantic) - pedwarn ((TREE_CODE (t) == UNION_TYPE ? "union has no members" - : "structure has no members")); + if (pedantic) + { + for (x = fieldlist; x; x = TREE_CHAIN (x)) + if (DECL_NAME (x) != 0) + break; + + if (x == 0) + pedwarn ("%s has no %smembers", + (TREE_CODE (t) == UNION_TYPE ? "union" : "structure"), + (fieldlist ? "named " : "")); + } /* Install struct as DECL_CONTEXT of each field decl. Also process specified field sizes. @@ -5425,6 +5726,7 @@ finish_struct (t, fieldlist) for (x = fieldlist; x; x = TREE_CHAIN (x)) { DECL_CONTEXT (x) = t; + DECL_PACKED (x) |= TYPE_PACKED (t); DECL_FIELD_SIZE (x) = 0; /* If any field is const, the structure type is pseudo-const. */ @@ -5514,8 +5816,15 @@ finish_struct (t, fieldlist) { register int width = TREE_INT_CST_LOW (DECL_INITIAL (x)); + if (TREE_CODE (TREE_TYPE (x)) == ENUMERAL_TYPE + && (width < min_precision (TYPE_MIN_VALUE (TREE_TYPE (x)), + TREE_UNSIGNED (TREE_TYPE (x))) + || width < min_precision (TYPE_MAX_VALUE (TREE_TYPE (x)), + TREE_UNSIGNED (TREE_TYPE (x))))) + warning_with_decl (x, "`%s' is narrower than values of its type"); + DECL_FIELD_SIZE (x) = width; - DECL_BIT_FIELD (x) = 1; + DECL_BIT_FIELD (x) = DECL_C_BIT_FIELD (x) = 1; DECL_INITIAL (x) = NULL; if (width == 0) @@ -5525,14 +5834,15 @@ finish_struct (t, fieldlist) DECL_ALIGN (x) = MAX (DECL_ALIGN (x), EMPTY_FIELD_BOUNDARY); #endif #ifdef PCC_BITFIELD_TYPE_MATTERS - DECL_ALIGN (x) = MAX (DECL_ALIGN (x), - TYPE_ALIGN (TREE_TYPE (x))); + if (PCC_BITFIELD_TYPE_MATTERS) + DECL_ALIGN (x) = MAX (DECL_ALIGN (x), + TYPE_ALIGN (TREE_TYPE (x))); #endif } } else if (TREE_TYPE (x) != error_mark_node) { - int min_align = (DECL_PACKED (x) ? BITS_PER_UNIT + 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. */ @@ -5635,26 +5945,15 @@ finish_struct (t, fieldlist) TYPE_ALIGN (x) = TYPE_ALIGN (t); } - /* Promote each bit-field's type to int if it is narrower than that. */ - for (x = fieldlist; x; x = TREE_CHAIN (x)) - if (DECL_BIT_FIELD (x) - && (C_PROMOTING_INTEGER_TYPE_P (TREE_TYPE (x)) - || DECL_FIELD_SIZE (x) < TYPE_PRECISION (integer_type_node))) - { - tree type = TREE_TYPE (x); - - /* Preserve unsignedness if traditional - or if not really getting any wider. */ - if (TREE_UNSIGNED (type) - && (flag_traditional - || - (TYPE_PRECISION (type) == TYPE_PRECISION (integer_type_node) - && - DECL_FIELD_SIZE (x) == TYPE_PRECISION (integer_type_node)))) - TREE_TYPE (x) = unsigned_type_node; - else - TREE_TYPE (x) = integer_type_node; - } + /* If this was supposed to be a transparent union, but we can't + make it one, warn and turn off the flag. */ + if (TREE_CODE (t) == UNION_TYPE + && TYPE_TRANSPARENT_UNION (t) + && TYPE_MODE (t) != DECL_MODE (TYPE_FIELDS (t))) + { + TYPE_TRANSPARENT_UNION (t) = 0; + warning ("union cannot be made transparent"); + } /* If this structure or union completes the type of any previous variable declaration, lay it out and output its rtl. */ @@ -5755,17 +6054,23 @@ start_enum (name) enum_next_value = integer_zero_node; enum_overflow = 0; + if (flag_short_enums) + TYPE_PACKED (enumtype) = 1; + return enumtype; } /* After processing and defining all the values of an enumeration type, install their decls in the enumeration type and finish it off. - ENUMTYPE is the type object and VALUES a list of decl-value pairs. + ENUMTYPE is the type object, VALUES a list of decl-value pairs, + and ATTRIBUTES are the specified attributes. Returns ENUMTYPE. */ tree -finish_enum (enumtype, values) - register tree enumtype, values; +finish_enum (enumtype, values, attributes) + tree enumtype; + tree values; + tree attributes; { register tree pair, tem; tree minnode = 0, maxnode = 0; @@ -5775,6 +6080,8 @@ finish_enum (enumtype, values) if (in_parm_level_p ()) warning ("enum defined inside parms"); + decl_attributes (enumtype, attributes, NULL_TREE); + /* Calculate the maximum value of any enumerator in this type. */ if (values == error_mark_node) @@ -5806,9 +6113,17 @@ finish_enum (enumtype, values) highprec = min_precision (maxnode, TREE_UNSIGNED (enumtype)); precision = MAX (lowprec, highprec); - if (flag_short_enums || precision > TYPE_PRECISION (integer_type_node)) - /* Use the width of the narrowest normal C type which is wide enough. */ - TYPE_PRECISION (enumtype) = TYPE_PRECISION (type_for_size (precision, 1)); + if (TYPE_PACKED (enumtype) || precision > TYPE_PRECISION (integer_type_node)) + { + tree narrowest = type_for_size (precision, 1); + if (narrowest == 0) + { + warning ("enumeration values exceed range of largest integer"); + narrowest = long_long_integer_type_node; + } + + TYPE_PRECISION (enumtype) = TYPE_PRECISION (narrowest); + } else TYPE_PRECISION (enumtype) = TYPE_PRECISION (integer_type_node); @@ -5929,8 +6244,8 @@ build_enumerator (name, value) } /* Create the FUNCTION_DECL for a function definition. - DECLSPECS, DECLARATOR, and ATTRIBUTES are the parts of the declaration; - they describe the function's name and the type it returns, + DECLSPECS, DECLARATOR, PREFIX_ATTRIBUTES and ATTRIBUTES are the parts of + the declaration; they describe the function's name and the type it returns, but twisted together in a fashion that parallels the syntax of C. This function creates a binding context for the function body @@ -5943,15 +6258,15 @@ build_enumerator (name, value) NESTED is nonzero for a function nested within another function. */ int -start_function (declspecs, declarator, attributes, nested) - tree declarator, declspecs, attributes; +start_function (declspecs, declarator, prefix_attributes, attributes, nested) + tree declarator, declspecs, prefix_attributes, attributes; int nested; { tree decl1, old_decl; tree restype; int old_immediate_size_expand = immediate_size_expand; - current_function_returns_value = 0; /* Assume, until we see it does. */ + current_function_returns_value = 0; /* Assume, until we see it does. */ current_function_returns_null = 0; warn_about_return_type = 0; current_extern_inline = 0; @@ -5967,10 +6282,12 @@ start_function (declspecs, declarator, attributes, nested) /* If the declarator is not suitable for a function definition, cause a syntax error. */ if (decl1 == 0) - return 0; + { + immediate_size_expand = old_immediate_size_expand; + return 0; + } - if (attributes) - decl_attributes (decl1, NULL_TREE, attributes); + decl_attributes (decl1, prefix_attributes, attributes); announce_function (decl1); @@ -6061,6 +6378,67 @@ start_function (declspecs, declarator, attributes, nested) if (current_function_decl != 0) TREE_PUBLIC (decl1) = 0; + /* Warn for unlikely, improbable, or stupid declarations of `main'. */ + if (warn_main + && strcmp ("main", IDENTIFIER_POINTER (DECL_NAME (decl1))) == 0) + { + tree args; + int argct = 0; + + if (TYPE_MAIN_VARIANT (TREE_TYPE (TREE_TYPE (decl1))) + != integer_type_node) + pedwarn_with_decl (decl1, "return type of `%s' is not `int'"); + + for (args = TYPE_ARG_TYPES (TREE_TYPE (decl1)); args; + args = TREE_CHAIN (args)) + { + tree type = args ? TREE_VALUE (args) : 0; + + if (type == void_type_node) + break; + + ++argct; + switch (argct) + { + case 1: + if (TYPE_MAIN_VARIANT (type) != integer_type_node) + pedwarn_with_decl (decl1, + "first argument of `%s' should be `int'"); + break; + + case 2: + if (TREE_CODE (type) != POINTER_TYPE + || TREE_CODE (TREE_TYPE (type)) != POINTER_TYPE + || (TYPE_MAIN_VARIANT (TREE_TYPE (TREE_TYPE (type))) + != char_type_node)) + pedwarn_with_decl (decl1, + "second argument of `%s' should be `char **'"); + break; + + case 3: + if (TREE_CODE (type) != POINTER_TYPE + || TREE_CODE (TREE_TYPE (type)) != POINTER_TYPE + || (TYPE_MAIN_VARIANT (TREE_TYPE (TREE_TYPE (type))) + != char_type_node)) + pedwarn_with_decl (decl1, + "third argument of `%s' should probably be `char **'"); + break; + } + } + + /* It is intentional that this message does not mention the third + argument, which is warned for only pedantically, because it's + blessed by mention in an appendix of the standard. */ + if (argct > 0 && (argct < 2 || argct > 3)) + pedwarn_with_decl (decl1, "`%s' takes only zero or two arguments"); + + if (argct == 3 && pedantic) + pedwarn_with_decl (decl1, "third argument of `%s' is deprecated"); + + if (! TREE_PUBLIC (decl1)) + pedwarn_with_decl (decl1, "`%s' is normally a non-static function"); + } + /* Record the decl so that the function name is defined. If we already have a decl for this name, and it is a FUNCTION_DECL, use the old decl. */ @@ -6674,7 +7052,9 @@ combine_parm_decls (specparms, parmlist, void_at_end) if (void_at_end) return saveable_tree_cons (parmdecls, nonparms, - nreverse (saveable_tree_cons (NULL_TREE, void_type_node, types))); + nreverse (saveable_tree_cons (NULL_TREE, + void_type_node, + types))); return saveable_tree_cons (parmdecls, nonparms, nreverse (types)); } @@ -6711,19 +7091,28 @@ finish_function (nested) setjmp_protect_args (); } -#ifdef DEFAULT_MAIN_RETURN if (! strcmp (IDENTIFIER_POINTER (DECL_NAME (fndecl)), "main")) { if (TYPE_MAIN_VARIANT (TREE_TYPE (TREE_TYPE (fndecl))) != integer_type_node) - warning_with_decl (fndecl, "return type of `%s' is not `int'"); + { + /* You would expect the sense of this test to be the other way + around, but if warn_main is set, we will already have warned, + so this would be a duplicate. This is the warning you get + in some environments even if you *don't* ask for it, because + these are environments where it may be more of a problem than + usual. */ + if (! warn_main) + pedwarn_with_decl (fndecl, "return type of `%s' is not `int'"); + } else { +#ifdef DEFAULT_MAIN_RETURN /* Make it so that `main' always returns success by default. */ DEFAULT_MAIN_RETURN; +#endif } } -#endif /* Generate rtl for function exit. */ expand_function_end (input_filename, lineno, 0);