mirror of
git://gcc.gnu.org/git/gcc.git
synced 2025-04-19 13:10:50 +08:00
(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
This commit is contained in:
parent
1417e9bdd0
commit
bf44f7de98
253
gcc/c-decl.c
253
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).
|
||||
|
Loading…
x
Reference in New Issue
Block a user