From: Jim Wilson Date: Wed, 29 Nov 1995 18:55:34 +0000 (-0800) Subject: (duplicate_decls): Add new paramter different_binding_level. X-Git-Url: https://git.libre-soc.org/?a=commitdiff_plain;h=bf44f7de98853f60f55246c1c385c4c878a501b4;p=gcc.git (duplicate_decls): Add new paramter different_binding_level. Lots of changes to use new new parameter. (pushdecl): Delete variable declared_global. New variable different_binding_level and code to set it. Move extern/static warning before duplicate_decls call. Don't let global typedefs conflict with nested extern declarations. Move oldglobal test inside code for setting IDENTIFIER_LIMBO_VALUE. (lookup_name_current_level_global): Delete. From-SVN: r10618 --- diff --git a/gcc/c-decl.c b/gcc/c-decl.c index ca33a4c99f3..20165214f94 100644 --- a/gcc/c-decl.c +++ b/gcc/c-decl.c @@ -1307,11 +1307,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 @@ -1404,8 +1408,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 +1426,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 (); } @@ -1691,6 +1696,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 +1714,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 +1752,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 +1802,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 +1818,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)) @@ -1823,33 +1844,48 @@ 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 (different_binding_level) + { + /* Don't output a duplicate symbol for this declaration. */ + TREE_ASM_WRITTEN (newdecl) = 1; + return 0; } /* Copy most of the decl-specific fields of NEWDECL into OLDDECL. @@ -1900,15 +1936,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 +1964,27 @@ 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) + /* 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)); + } + + if (t != 0 && duplicate_decls (x, t, different_binding_level)) { if (TREE_CODE (t) == PARM_DECL) { @@ -1934,32 +1993,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 @@ -2145,6 +2179,10 @@ 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)); @@ -2217,11 +2255,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. @@ -2731,29 +2769,6 @@ 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).