summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorwilson <wilson@138bc75d-0d04-0410-961f-82ee72b054a4>1995-11-29 18:55:34 +0000
committerwilson <wilson@138bc75d-0d04-0410-961f-82ee72b054a4>1995-11-29 18:55:34 +0000
commitb33f0698089364738a90ec1ae6b083ddc39ce96c (patch)
tree13895fbf6cfabc15008f410474d91d4d9ebae8c3
parenta4b000b016814246710d6a57eabb9a5856157c8f (diff)
downloadgcc-b33f0698089364738a90ec1ae6b083ddc39ce96c.tar.gz
(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. git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@10618 138bc75d-0d04-0410-961f-82ee72b054a4
-rw-r--r--gcc/c-decl.c253
1 files changed, 134 insertions, 119 deletions
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).