Commit bf44f7de by Jim Wilson

(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
parent 1417e9bd
...@@ -1307,11 +1307,15 @@ pushtag (name, type) ...@@ -1307,11 +1307,15 @@ pushtag (name, type)
Prints an error message if appropriate. Prints an error message if appropriate.
If safely possible, alter OLDDECL to look like NEWDECL, and return 1. 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 static int
duplicate_decls (newdecl, olddecl) duplicate_decls (newdecl, olddecl, different_binding_level)
register tree newdecl, olddecl; register tree newdecl, olddecl;
int different_binding_level;
{ {
int types_match = comptypes (TREE_TYPE (newdecl), TREE_TYPE (olddecl)); int types_match = comptypes (TREE_TYPE (newdecl), TREE_TYPE (olddecl));
int new_is_definition = (TREE_CODE (newdecl) == FUNCTION_DECL int new_is_definition = (TREE_CODE (newdecl) == FUNCTION_DECL
...@@ -1404,8 +1408,8 @@ duplicate_decls (newdecl, olddecl) ...@@ -1404,8 +1408,8 @@ duplicate_decls (newdecl, olddecl)
else if (!types_match) else if (!types_match)
{ {
/* Accept the return type of the new declaration if same modes. */ /* Accept the return type of the new declaration if same modes. */
tree oldreturntype = TREE_TYPE (TREE_TYPE (olddecl)); tree oldreturntype = TREE_TYPE (oldtype);
tree newreturntype = TREE_TYPE (TREE_TYPE (newdecl)); tree newreturntype = TREE_TYPE (newtype);
/* Make sure we put the new type in the same obstack as the old ones. /* 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 If the old types are not both in the same obstack, use the
...@@ -1422,36 +1426,37 @@ duplicate_decls (newdecl, olddecl) ...@@ -1422,36 +1426,37 @@ duplicate_decls (newdecl, olddecl)
{ {
/* Function types may be shared, so we can't just modify /* Function types may be shared, so we can't just modify
the return type of olddecl's function type. */ the return type of olddecl's function type. */
tree newtype tree trytype
= build_function_type (newreturntype, = 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) if (types_match)
TREE_TYPE (olddecl) = newtype; oldtype = trytype;
} }
/* Accept harmless mismatch in first argument type also. /* Accept harmless mismatch in first argument type also.
This is for ffs. */ This is for ffs. */
if (TYPE_ARG_TYPES (TREE_TYPE (newdecl)) != 0 if (TYPE_ARG_TYPES (TREE_TYPE (newdecl)) != 0
&& TYPE_ARG_TYPES (TREE_TYPE (olddecl)) != 0 && TYPE_ARG_TYPES (oldtype) != 0
&& TREE_VALUE (TYPE_ARG_TYPES (TREE_TYPE (newdecl))) != 0 && TREE_VALUE (TYPE_ARG_TYPES (newtype)) != 0
&& TREE_VALUE (TYPE_ARG_TYPES (TREE_TYPE (olddecl))) != 0 && TREE_VALUE (TYPE_ARG_TYPES (oldtype)) != 0
&& (TYPE_MODE (TREE_VALUE (TYPE_ARG_TYPES (TREE_TYPE (newdecl)))) && (TYPE_MODE (TREE_VALUE (TYPE_ARG_TYPES (newtype)))
== == TYPE_MODE (TREE_VALUE (TYPE_ARG_TYPES (oldtype)))))
TYPE_MODE (TREE_VALUE (TYPE_ARG_TYPES (TREE_TYPE (olddecl))))))
{ {
/* Function types may be shared, so we can't just modify /* Function types may be shared, so we can't just modify
the return type of olddecl's function type. */ the return type of olddecl's function type. */
tree newtype tree trytype
= build_function_type (TREE_TYPE (TREE_TYPE (olddecl)), = build_function_type (TREE_TYPE (oldtype),
tree_cons (NULL_TREE, tree_cons (NULL_TREE,
TREE_VALUE (TYPE_ARG_TYPES (TREE_TYPE (newdecl))), TREE_VALUE (TYPE_ARG_TYPES (newtype)),
TREE_CHAIN (TYPE_ARG_TYPES (TREE_TYPE (olddecl))))); TREE_CHAIN (TYPE_ARG_TYPES (oldtype))));
types_match = comptypes (TREE_TYPE (newdecl), newtype); types_match = comptypes (newtype, trytype);
if (types_match) if (types_match)
TREE_TYPE (olddecl) = newtype; oldtype = trytype;
} }
if (! different_binding_level)
TREE_TYPE (olddecl) = oldtype;
pop_obstacks (); pop_obstacks ();
} }
...@@ -1691,6 +1696,11 @@ duplicate_decls (newdecl, olddecl) ...@@ -1691,6 +1696,11 @@ duplicate_decls (newdecl, olddecl)
if (types_match) 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. /* 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 If the old types are not both in the same obstack, use the permanent
one. */ one. */
...@@ -1704,9 +1714,18 @@ duplicate_decls (newdecl, olddecl) ...@@ -1704,9 +1714,18 @@ duplicate_decls (newdecl, olddecl)
/* Merge the data types specified in the two decls. */ /* Merge the data types specified in the two decls. */
if (TREE_CODE (newdecl) != FUNCTION_DECL || !DECL_BUILT_IN (olddecl)) if (TREE_CODE (newdecl) != FUNCTION_DECL || !DECL_BUILT_IN (olddecl))
{
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 (newdecl)
= TREE_TYPE (olddecl) = TREE_TYPE (olddecl)
= common_type (newtype, oldtype); = common_type (newtype, oldtype);
}
/* Lay the type out, unless already done. */ /* Lay the type out, unless already done. */
if (oldtype != TREE_TYPE (newdecl)) if (oldtype != TREE_TYPE (newdecl))
...@@ -1733,37 +1752,37 @@ duplicate_decls (newdecl, olddecl) ...@@ -1733,37 +1752,37 @@ duplicate_decls (newdecl, olddecl)
/* Merge the type qualifiers. */ /* Merge the type qualifiers. */
if (DECL_BUILT_IN_NONANSI (olddecl) && TREE_THIS_VOLATILE (olddecl) if (DECL_BUILT_IN_NONANSI (olddecl) && TREE_THIS_VOLATILE (olddecl)
&& !TREE_THIS_VOLATILE (newdecl)) && !TREE_THIS_VOLATILE (newdecl))
TREE_THIS_VOLATILE (olddecl) = 0; TREE_THIS_VOLATILE (write_olddecl) = 0;
if (TREE_READONLY (newdecl)) if (TREE_READONLY (newdecl))
TREE_READONLY (olddecl) = 1; TREE_READONLY (write_olddecl) = 1;
if (TREE_THIS_VOLATILE (newdecl)) if (TREE_THIS_VOLATILE (newdecl))
{ {
TREE_THIS_VOLATILE (olddecl) = 1; TREE_THIS_VOLATILE (write_olddecl) = 1;
if (TREE_CODE (newdecl) == VAR_DECL) if (TREE_CODE (newdecl) == VAR_DECL)
make_var_volatile (newdecl); make_var_volatile (newdecl);
} }
/* Keep source location of definition rather than declaration. /* Keep source location of definition rather than declaration. */
Likewise, keep decl at outer scope. */ /* When called with different_binding_level set, keep the old
if ((DECL_INITIAL (newdecl) == 0 && DECL_INITIAL (olddecl) != 0) information so that meaningful diagnostics can be given. */
|| (DECL_CONTEXT (newdecl) != 0 && DECL_CONTEXT (olddecl) == 0)) if (DECL_INITIAL (newdecl) == 0 && DECL_INITIAL (olddecl) != 0
&& ! different_binding_level)
{ {
DECL_SOURCE_LINE (newdecl) = DECL_SOURCE_LINE (olddecl); DECL_SOURCE_LINE (newdecl) = DECL_SOURCE_LINE (olddecl);
DECL_SOURCE_FILE (newdecl) = DECL_SOURCE_FILE (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. */ /* Merge the unused-warning information. */
if (DECL_IN_SYSTEM_HEADER (olddecl)) if (DECL_IN_SYSTEM_HEADER (olddecl))
DECL_IN_SYSTEM_HEADER (newdecl) = 1; DECL_IN_SYSTEM_HEADER (newdecl) = 1;
else if (DECL_IN_SYSTEM_HEADER (newdecl)) else if (DECL_IN_SYSTEM_HEADER (newdecl))
DECL_IN_SYSTEM_HEADER (olddecl) = 1; DECL_IN_SYSTEM_HEADER (write_olddecl) = 1;
/* Merge the initialization information. */ /* 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); DECL_INITIAL (newdecl) = DECL_INITIAL (olddecl);
/* Merge the section attribute. /* Merge the section attribute.
...@@ -1783,7 +1802,7 @@ duplicate_decls (newdecl, olddecl) ...@@ -1783,7 +1802,7 @@ duplicate_decls (newdecl, olddecl)
} }
/* If cannot merge, then use the new type and qualifiers, /* If cannot merge, then use the new type and qualifiers,
and don't preserve the old rtl. */ and don't preserve the old rtl. */
else else if (! different_binding_level)
{ {
TREE_TYPE (olddecl) = TREE_TYPE (newdecl); TREE_TYPE (olddecl) = TREE_TYPE (newdecl);
TREE_READONLY (olddecl) = TREE_READONLY (newdecl); TREE_READONLY (olddecl) = TREE_READONLY (newdecl);
...@@ -1799,6 +1818,8 @@ duplicate_decls (newdecl, olddecl) ...@@ -1799,6 +1818,8 @@ duplicate_decls (newdecl, olddecl)
TREE_PUBLIC (newdecl) &= TREE_PUBLIC (olddecl); TREE_PUBLIC (newdecl) &= TREE_PUBLIC (olddecl);
/* This is since we don't automatically /* This is since we don't automatically
copy the attributes of NEWDECL into OLDDECL. */ 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); TREE_PUBLIC (olddecl) = TREE_PUBLIC (newdecl);
/* If this clears `static', clear it in the identifier too. */ /* If this clears `static', clear it in the identifier too. */
if (! TREE_PUBLIC (olddecl)) if (! TREE_PUBLIC (olddecl))
...@@ -1823,34 +1844,49 @@ duplicate_decls (newdecl, olddecl) ...@@ -1823,34 +1844,49 @@ duplicate_decls (newdecl, olddecl)
DECL_INLINE (olddecl) = 1; DECL_INLINE (olddecl) = 1;
DECL_INLINE (newdecl) = DECL_INLINE (olddecl); DECL_INLINE (newdecl) = DECL_INLINE (olddecl);
if (TREE_CODE (newdecl) == FUNCTION_DECL)
{
if (DECL_BUILT_IN (olddecl))
{
/* Get rid of any built-in function if new arg types don't match it /* Get rid of any built-in function if new arg types don't match it
or if we have a function definition. */ or if we have a function definition. */
if (TREE_CODE (newdecl) == FUNCTION_DECL if (! types_match || new_is_definition)
&& DECL_BUILT_IN (olddecl) {
&& (!types_match || new_is_definition)) if (! different_binding_level)
{ {
TREE_TYPE (olddecl) = TREE_TYPE (newdecl); TREE_TYPE (olddecl) = TREE_TYPE (newdecl);
DECL_BUILT_IN (olddecl) = 0; DECL_BUILT_IN (olddecl) = 0;
} }
}
/* If redeclaring a builtin function, and not a definition, else
it stays built in.
Also preserve various other info from the definition. */
if (TREE_CODE (newdecl) == FUNCTION_DECL && !new_is_definition)
{
if (DECL_BUILT_IN (olddecl))
{ {
/* If redeclaring a builtin function, and not a definition,
it stays built in. */
DECL_BUILT_IN (newdecl) = 1; DECL_BUILT_IN (newdecl) = 1;
DECL_FUNCTION_CODE (newdecl) = DECL_FUNCTION_CODE (olddecl); 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_FRAME_SIZE (newdecl) = DECL_FRAME_SIZE (olddecl);
if (! new_is_definition)
{
DECL_RESULT (newdecl) = DECL_RESULT (olddecl); 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_INITIAL (newdecl) = DECL_INITIAL (olddecl);
DECL_SAVED_INSNS (newdecl) = DECL_SAVED_INSNS (olddecl); DECL_SAVED_INSNS (newdecl) = DECL_SAVED_INSNS (olddecl);
DECL_ARGUMENTS (newdecl) = DECL_ARGUMENTS (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. /* Copy most of the decl-specific fields of NEWDECL into OLDDECL.
But preserve OLDdECL's DECL_UID. */ But preserve OLDdECL's DECL_UID. */
...@@ -1900,15 +1936,21 @@ pushdecl (x) ...@@ -1900,15 +1936,21 @@ pushdecl (x)
{ {
char *file; char *file;
int line; 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 /* Don't type check externs here when -traditional. This is so that
code with conflicting declarations inside blocks will get warnings code with conflicting declarations inside blocks will get warnings
not errors. X11 for instance depends on this. */ not errors. X11 for instance depends on this. */
if (DECL_EXTERNAL (x) && TREE_PUBLIC (x) && ! flag_traditional) if (! t && DECL_EXTERNAL (x) && TREE_PUBLIC (x) && ! flag_traditional)
t = lookup_name_current_level_global (name); {
else t = IDENTIFIER_GLOBAL_VALUE (name);
t = lookup_name_current_level (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) if (t != 0 && t == error_mark_node)
/* error_mark_node is 0 for a while during initialization! */ /* error_mark_node is 0 for a while during initialization! */
{ {
...@@ -1922,43 +1964,35 @@ pushdecl (x) ...@@ -1922,43 +1964,35 @@ pushdecl (x)
line = DECL_SOURCE_LINE (t); 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 (TREE_CODE (t) == PARM_DECL)
{
/* Don't allow more than one "real" duplicate
of a forward parm decl. */
TREE_ASM_WRITTEN (t) = TREE_ASM_WRITTEN (x);
return t;
}
/* If this decl is `static' and an implicit decl was seen previously, /* If this decl is `static' and an implicit decl was seen previously,
warn. But don't complain if -traditional, warn. But don't complain if -traditional,
since traditional compilers don't complain. */ since traditional compilers don't complain. */
if (!flag_traditional && TREE_PUBLIC (name) if (! flag_traditional && TREE_PUBLIC (name)
/* Don't test for DECL_EXTERNAL, because grokdeclarator
/* should this be '&& ! declared_global' ? */ sets this for all functions. */
&& ! TREE_PUBLIC (x) && ! DECL_EXTERNAL (x) && ! TREE_PUBLIC (x)
/* We used to warn also for explicit extern followed by static, /* We used to warn also for explicit extern followed by static,
but sometimes you need to do it that way. */ but sometimes you need to do it that way. */
&& IDENTIFIER_IMPLICIT_DECL (name) != 0) && IDENTIFIER_IMPLICIT_DECL (name) != 0)
{ {
pedwarn ("`%s' was declared implicitly `extern' and later `static'", pedwarn ("`%s' was declared implicitly `extern' and later `static'",
IDENTIFIER_POINTER (name)); IDENTIFIER_POINTER (name));
pedwarn_with_file_and_line (file, line, pedwarn_with_file_and_line
(DECL_SOURCE_FILE (IDENTIFIER_IMPLICIT_DECL (name)),
DECL_SOURCE_LINE (IDENTIFIER_IMPLICIT_DECL (name)),
"previous declaration of `%s'", "previous declaration of `%s'",
IDENTIFIER_POINTER (name)); IDENTIFIER_POINTER (name));
} }
/* If this is a global decl, and there exists a conflicting local if (t != 0 && duplicate_decls (x, t, different_binding_level))
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 (TREE_CODE (t) == PARM_DECL)
/* A test for TREE_PUBLIC (x) will fail for variables that have {
been declared static first, and extern now. */ /* Don't allow more than one "real" duplicate
if (! declared_global || lookup_name (name) == t) of a forward parm decl. */
TREE_ASM_WRITTEN (t) = TREE_ASM_WRITTEN (x);
return t;
}
return t; return t;
} }
...@@ -2145,6 +2179,10 @@ pushdecl (x) ...@@ -2145,6 +2179,10 @@ pushdecl (x)
/* Okay to declare a non-ANSI built-in as anything. */ /* Okay to declare a non-ANSI built-in as anything. */
else if (t != 0 && DECL_BUILT_IN_NONANSI (t)) 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)) else if (IDENTIFIER_IMPLICIT_DECL (name))
pedwarn ("`%s' was declared implicitly `extern' and later `static'", pedwarn ("`%s' was declared implicitly `extern' and later `static'",
IDENTIFIER_POINTER (name)); IDENTIFIER_POINTER (name));
...@@ -2217,10 +2255,10 @@ pushdecl (x) ...@@ -2217,10 +2255,10 @@ pushdecl (x)
and no file-scope declaration has yet been seen, and no file-scope declaration has yet been seen,
then if we later have a file-scope decl it must not be static. */ then if we later have a file-scope decl it must not be static. */
if (oldlocal == 0 if (oldlocal == 0
&& oldglobal == 0
&& DECL_EXTERNAL (x) && DECL_EXTERNAL (x)
&& TREE_PUBLIC (x)) && TREE_PUBLIC (x))
{ {
if (oldglobal == 0)
TREE_PUBLIC (name) = 1; TREE_PUBLIC (name) = 1;
/* Save this decl, so that we can do type checking against /* Save this decl, so that we can do type checking against
...@@ -2732,29 +2770,6 @@ lookup_name_current_level (name) ...@@ -2732,29 +2770,6 @@ lookup_name_current_level (name)
return t; 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, /* 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. Initialize the global binding level.
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment