decl.c (pushdecl): Matching decls for local externs are found in the current level.
* decl.c (pushdecl): Matching decls for local externs are found in the current level. Propagate linkage information from previous declarations. From-SVN: r36011
This commit is contained in:
parent
bbfbf340fc
commit
94dfccd136
@ -1,3 +1,9 @@
|
||||
2000-08-27 Jason Merrill <jason@redhat.com>
|
||||
|
||||
* decl.c (pushdecl): Matching decls for local externs are found in
|
||||
the current level. Propagate linkage information from previous
|
||||
declarations.
|
||||
|
||||
2000-08-26 Gabriel Dos Reis <gdr@codesourcery.com>
|
||||
|
||||
* ir.texi (Expressions): Fix typo.
|
||||
|
@ -3852,7 +3852,7 @@ pushdecl (x)
|
||||
nesting. */
|
||||
&& !(TREE_CODE (x) == FUNCTION_DECL && !DECL_INITIAL (x))
|
||||
/* A local declaration for an `extern' variable is in the
|
||||
scoped of the current namespace, not the current
|
||||
scope of the current namespace, not the current
|
||||
function. */
|
||||
&& !(TREE_CODE (x) == VAR_DECL && DECL_EXTERNAL (x))
|
||||
&& !DECL_CONTEXT (x))
|
||||
@ -3871,20 +3871,40 @@ pushdecl (x)
|
||||
name = DECL_NAME (x);
|
||||
if (name)
|
||||
{
|
||||
#if 0
|
||||
/* Not needed...see below. */
|
||||
char *file;
|
||||
int line;
|
||||
#endif
|
||||
int different_binding_level = 0;
|
||||
|
||||
if (TREE_CODE (name) == TEMPLATE_ID_EXPR)
|
||||
name = TREE_OPERAND (name, 0);
|
||||
|
||||
/* Namespace-scoped variables are not found in the current level. */
|
||||
if (TREE_CODE (x) == VAR_DECL && DECL_NAMESPACE_SCOPE_P (x))
|
||||
/* In case this decl was explicitly namespace-qualified, look it
|
||||
up in its namespace context. */
|
||||
if (TREE_CODE (x) == VAR_DECL && DECL_NAMESPACE_SCOPE_P (x)
|
||||
&& namespace_bindings_p ())
|
||||
t = namespace_binding (name, DECL_CONTEXT (x));
|
||||
else
|
||||
t = lookup_name_current_level (name);
|
||||
|
||||
/* [basic.link] If there is a visible declaration of an entity
|
||||
with linkage having the same name and type, ignoring entities
|
||||
declared outside the innermost enclosing namespace scope, the
|
||||
block scope declaration declares that same entity and
|
||||
receives the linkage of the previous declaration. */
|
||||
if (! t && current_function_decl && x != current_function_decl
|
||||
&& (TREE_CODE (x) == FUNCTION_DECL || TREE_CODE (x) == VAR_DECL)
|
||||
&& DECL_EXTERNAL (x))
|
||||
{
|
||||
/* Look in block scope. */
|
||||
t = IDENTIFIER_VALUE (name);
|
||||
/* Or in the innermost namespace. */
|
||||
if (! t)
|
||||
t = namespace_binding (name, DECL_CONTEXT (x));
|
||||
/* Does it have linkage? */
|
||||
if (t && ! (TREE_STATIC (t) || DECL_EXTERNAL (t)))
|
||||
t = NULL_TREE;
|
||||
if (t)
|
||||
different_binding_level = 1;
|
||||
}
|
||||
|
||||
/* If we are declaring a function, and the result of name-lookup
|
||||
was an OVERLOAD, look for an overloaded instance that is
|
||||
actually the same as the function we are declaring. (If
|
||||
@ -3919,7 +3939,16 @@ pushdecl (x)
|
||||
}
|
||||
else if (t != NULL_TREE)
|
||||
{
|
||||
if (TREE_CODE (t) == PARM_DECL)
|
||||
if (different_binding_level)
|
||||
{
|
||||
if (decls_match (x, t))
|
||||
/* The standard only says that the local extern
|
||||
inherits linkage from the previous decl; in
|
||||
particular, default args are not shared. It would
|
||||
be nice to propagate inlining info, though. FIXME. */
|
||||
TREE_PUBLIC (x) = TREE_PUBLIC (t);
|
||||
}
|
||||
else if (TREE_CODE (t) == PARM_DECL)
|
||||
{
|
||||
if (DECL_CONTEXT (t) == NULL_TREE)
|
||||
fatal ("parse errors have confused me too much");
|
||||
|
12
gcc/testsuite/g++.old-deja/g++.other/scope1.C
Normal file
12
gcc/testsuite/g++.old-deja/g++.other/scope1.C
Normal file
@ -0,0 +1,12 @@
|
||||
// Testcase for proper scoping of local externs.
|
||||
|
||||
int x = 1;
|
||||
|
||||
int main()
|
||||
{
|
||||
int x = 2;
|
||||
{
|
||||
extern int x;
|
||||
return (x != 1);
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue
Block a user