diff options
Diffstat (limited to 'contrib/gcc/c-decl.c')
| -rw-r--r-- | contrib/gcc/c-decl.c | 954 |
1 files changed, 673 insertions, 281 deletions
diff --git a/contrib/gcc/c-decl.c b/contrib/gcc/c-decl.c index ca33a4c99f3a..ccaa7d2be36b 100644 --- a/contrib/gcc/c-decl.c +++ b/contrib/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. @@ -27,12 +27,20 @@ Boston, MA 02111-1307, 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 <stdio.h> +#include "toplev.h" + +#if USE_CPPLIB +#include "cpplib.h" +extern cpp_reader parse_in; +extern cpp_options parse_options; +static int cpp_initialized; +#endif /* In grokdeclarator, distinguish syntactic contexts of declarators. */ enum decl_context @@ -143,11 +151,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. */ @@ -411,16 +421,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. */ @@ -450,8 +464,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'. */ @@ -463,9 +481,18 @@ 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; + +/* Nonzero means warn about usage of long long when `-pedantic'. */ + +int warn_long_long = 1; -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 @@ -521,7 +548,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; @@ -541,44 +568,80 @@ 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 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 > 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); - return 0 if not recognized. */ + Return the number of strings consumed. */ int -c_decode_option (p) - char *p; +c_decode_option (argc, argv) + int argc; + char **argv; { + int strings_processed; + char *p = argv[0]; +#if USE_CPPLIB + if (! cpp_initialized) + { + cpp_reader_init (&parse_in); + parse_in.data = &parse_options; + cpp_options_init (&parse_options); + cpp_initialized = 1; + } + strings_processed = cpp_handle_option (&parse_in, argc, argv); +#else + strings_processed = 0; +#endif /* ! USE_CPPLIB */ + if (!strcmp (p, "-ftraditional") || !strcmp (p, "-traditional")) { 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")) @@ -626,11 +689,29 @@ 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, "-Wlong-long")) + warn_long_long = 1; + else if (!strcmp (p, "-Wno-long-long")) + warn_long_long = 0; else if (!strcmp (p, "-Wwrite-strings")) warn_write_strings = 1; else if (!strcmp (p, "-Wno-write-strings")) @@ -703,6 +784,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")) @@ -711,6 +796,24 @@ 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, "-Wmultichar")) + warn_multichar = 1; + else if (!strcmp (p, "-Wno-multichar")) + warn_multichar = 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 @@ -718,7 +821,8 @@ c_decode_option (p) 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,9 +830,14 @@ 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; + return strings_processed; return 1; } @@ -737,17 +846,17 @@ c_decode_option (p) void print_lang_decl (file, node, indent) - FILE *file; - tree node; - int indent; + FILE *file ATTRIBUTE_UNUSED; + tree node ATTRIBUTE_UNUSED; + int indent ATTRIBUTE_UNUSED; { } void print_lang_type (file, node, indent) - FILE *file; - tree node; - int indent; + FILE *file ATTRIBUTE_UNUSED; + tree node ATTRIBUTE_UNUSED; + int indent ATTRIBUTE_UNUSED; { } @@ -772,13 +881,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 +1002,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 +1108,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 +1171,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 +1429,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 +1441,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 +1459,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 +1543,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 +1561,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 +1812,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 +1831,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 +1849,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,37 +1887,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 - && TREE_CODE (newdecl) != FUNCTION_DECL) - 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. @@ -1783,7 +1937,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); @@ -1799,6 +1953,8 @@ duplicate_decls (newdecl, olddecl) 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)) @@ -1810,6 +1966,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 { @@ -1823,37 +1981,62 @@ 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); + 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. - 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); + Do not set TREE_ASM_WRITTEN for a FUNCTION_DECL since we may actually + just have two declarations without a definition. VAR_DECLs may need + the same treatment, I'm not sure. */ + if (TREE_CODE (newdecl) == FUNCTION_DECL) + DECL_IGNORED_P (newdecl) = 1; + else + 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); @@ -1863,6 +2046,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; } @@ -1900,15 +2087,21 @@ pushdecl (x) { char *file; int line; - int declared_global; + 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! */ { @@ -1922,10 +2115,29 @@ pushdecl (x) line = DECL_SOURCE_LINE (t); } - /* duplicate_decls might write to TREE_PUBLIC (x) and DECL_EXTERNAL (x) - to make it identical to the initial declaration. */ - declared_global = TREE_PUBLIC (x) || DECL_EXTERNAL (x); - 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) { @@ -1934,32 +2146,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) - - /* should this be '&& ! declared_global' ? */ - && ! 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. */ - /* A test for TREE_PUBLIC (x) will fail for variables that have - been declared static first, and extern now. */ - if (! declared_global || lookup_name (name) == t) - return t; + return t; } /* If we are processing a typedef statement, generate a whole new @@ -1981,7 +2168,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 @@ -2012,10 +2199,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; @@ -2145,9 +2333,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)); @@ -2217,11 +2412,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. @@ -2363,9 +2558,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)); @@ -2731,32 +2932,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. */ @@ -2767,8 +2945,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; @@ -2816,37 +2994,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"), @@ -2868,6 +3038,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, intTI_type_node)); + unsigned_intQI_type_node = make_unsigned_type (GET_MODE_BITSIZE (QImode)); pushdecl (build_decl (TYPE_DECL, NULL_TREE, unsigned_intQI_type_node)); @@ -2880,6 +3053,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], @@ -3074,6 +3250,19 @@ init_decl_processing () sizetype, endlink)))); + memset_ftype /* memset prototype */ + = build_function_type (traditional_ptr_type_node, + tree_cons (NULL_TREE, ptr_type_node, + tree_cons (NULL_TREE, integer_type_node, + tree_cons (NULL_TREE, + sizetype, + endlink)))); + + 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); @@ -3091,6 +3280,44 @@ 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_old", ptr_ftype_void, + BUILT_IN_EH_STUB_OLD, NULL_PTR); + builtin_function ("__builtin_eh_stub", ptr_ftype_void, + BUILT_IN_EH_STUB, NULL_PTR); + 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, @@ -3182,6 +3409,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, @@ -3206,6 +3435,22 @@ 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); + builtin_function ("__builtin_trap", + build_function_type (void_type_node, endlink), + BUILT_IN_TRAP, NULL_PTR); /* In an ANSI C program, it is okay to supply built-in meanings for these functions, since applications cannot validly use them @@ -3222,6 +3467,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, @@ -3264,8 +3510,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, @@ -3285,6 +3529,8 @@ init_decl_processing () init_iterators (); incomplete_decl_finalize_hook = finish_incomplete_decl; + + lang_get_alias_set = &c_get_alias_set; } /* Return a definition for a builtin function named NAME and whose data type @@ -3351,10 +3597,15 @@ shadow_tag_warned (declspecs, warned) { int found_tag = 0; register tree link; + tree specs, attrs; pending_invalid_xref = 0; - for (link = declspecs; link; link = TREE_CHAIN (link)) + /* Remove the attributes from declspecs, since they will confuse the + following code. */ + split_specs_attrs (declspecs, &specs, &attrs); + + for (link = specs; link; link = TREE_CHAIN (link)) { register tree value = TREE_VALUE (link); register enum tree_code code = TREE_CODE (value); @@ -3467,6 +3718,10 @@ start_decl (declarator, declspecs, initialized, attributes, prefix_attributes) /* The corresponding pop_obstacks is in finish_decl. */ push_obstacks_nochange (); + if (warn_main && TREE_CODE (decl) != FUNCTION_DECL + && !strcmp (IDENTIFIER_POINTER (DECL_NAME (decl)), "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 @@ -3551,9 +3806,17 @@ start_decl (declarator, declspecs, initialized, attributes, prefix_attributes) if (TREE_CODE (decl) == FUNCTION_DECL) gen_aux_info_record (decl, 0, 0, TYPE_ARG_TYPES (TREE_TYPE (decl)) != 0); - /* For C and Objective-C, we by default put things in .common when - possible. */ - DECL_COMMON (decl) = 1; + /* 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; + +#ifdef SET_DEFAULT_DECL_ATTRIBUTES + SET_DEFAULT_DECL_ATTRIBUTES (decl, attributes); +#endif /* Set attributes here so if duplicate decl, will have proper attributes. */ decl_attributes (decl, attributes, prefix_attributes); @@ -3703,10 +3966,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. */ @@ -3724,6 +3988,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 @@ -3748,7 +4015,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 (); } @@ -3871,7 +4140,7 @@ finish_decl (decl, init, asmspec_tree) tree maybe_build_cleanup (decl) - tree decl; + tree decl ATTRIBUTE_UNUSED; { /* There are no cleanups in C. */ return NULL_TREE; @@ -3990,12 +4259,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. */ @@ -4151,7 +4414,7 @@ grokdeclarator (declarator, declspecs, decl_context, initialized) error ("`long long long' is too long for GCC"); else { - if (pedantic && ! in_system_header) + if (pedantic && ! in_system_header && warn_long_long) pedwarn ("ANSI C does not support `long long'"); longlong = 1; } @@ -4201,10 +4464,23 @@ 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)))) + /* Don't warn about typedef foo = bar. */ + && ! (specbits & (1 << (int) RID_TYPEDEF) && initialized) + && ! (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; } @@ -4214,7 +4490,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); @@ -4228,11 +4504,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) @@ -4240,10 +4514,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; @@ -4538,6 +4823,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); @@ -4656,7 +4953,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; @@ -4713,6 +5010,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)) @@ -4725,11 +5029,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; } @@ -4909,6 +5213,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"); @@ -4922,13 +5233,8 @@ grokdeclarator (declarator, declspecs, decl_context, initialized) /* Record presence of `inline', if it is reasonable. */ if (inlinep) { - tree last = tree_last (TYPE_ARG_TYPES (type)); - 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; @@ -5248,7 +5554,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", @@ -5351,6 +5657,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'"), @@ -5364,6 +5671,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; } @@ -5398,9 +5706,12 @@ 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; { + tree *x = (tree *)xp, *y = (tree *)yp; + if (DECL_NAME (*x) == DECL_NAME (*y)) return 0; if (DECL_NAME (*x) == NULL) @@ -5450,9 +5761,17 @@ finish_struct (t, fieldlist, attributes) 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. @@ -5554,8 +5873,15 @@ finish_struct (t, fieldlist, attributes) { 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) @@ -5565,14 +5891,15 @@ finish_struct (t, fieldlist, attributes) 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. */ @@ -5675,27 +6002,6 @@ finish_struct (t, fieldlist, attributes) 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 @@ -5703,7 +6009,7 @@ finish_struct (t, fieldlist, attributes) && TYPE_MODE (t) != DECL_MODE (TYPE_FIELDS (t))) { TYPE_TRANSPARENT_UNION (t) = 0; - warning ("cannot make `%s' a transparent union"); + warning ("union cannot be made transparent"); } /* If this structure or union completes the type of any previous @@ -5805,6 +6111,9 @@ start_enum (name) enum_next_value = integer_zero_node; enum_overflow = 0; + if (flag_short_enums) + TYPE_PACKED (enumtype) = 1; + return enumtype; } @@ -5861,10 +6170,17 @@ finish_enum (enumtype, values, attributes) highprec = min_precision (maxnode, TREE_UNSIGNED (enumtype)); precision = MAX (lowprec, highprec); - if (flag_short_enums || TYPE_PACKED (enumtype) - || 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); @@ -5900,6 +6216,7 @@ finish_enum (enumtype, values, attributes) TYPE_MIN_VALUE (tem) = TYPE_MIN_VALUE (enumtype); TYPE_MAX_VALUE (tem) = TYPE_MAX_VALUE (enumtype); TYPE_SIZE (tem) = TYPE_SIZE (enumtype); + TYPE_SIZE_UNIT (tem) = TYPE_SIZE_UNIT (enumtype); TYPE_MODE (tem) = TYPE_MODE (enumtype); TYPE_PRECISION (tem) = TYPE_PRECISION (enumtype); TYPE_ALIGN (tem) = TYPE_ALIGN (enumtype); @@ -6007,7 +6324,7 @@ start_function (declspecs, declarator, prefix_attributes, attributes, nested) 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; @@ -6023,7 +6340,10 @@ start_function (declspecs, declarator, prefix_attributes, 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; + } decl_attributes (decl1, prefix_attributes, attributes); @@ -6116,6 +6436,67 @@ start_function (declspecs, declarator, prefix_attributes, 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. */ @@ -6729,7 +7110,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)); } @@ -6766,19 +7149,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); @@ -6962,6 +7354,6 @@ pop_c_function_context () void copy_lang_decl (node) - tree node; + tree node ATTRIBUTE_UNUSED; { } |
