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>
|
2000-08-26 Gabriel Dos Reis <gdr@codesourcery.com>
|
||||||
|
|
||||||
* ir.texi (Expressions): Fix typo.
|
* ir.texi (Expressions): Fix typo.
|
||||||
|
@ -3852,7 +3852,7 @@ pushdecl (x)
|
|||||||
nesting. */
|
nesting. */
|
||||||
&& !(TREE_CODE (x) == FUNCTION_DECL && !DECL_INITIAL (x))
|
&& !(TREE_CODE (x) == FUNCTION_DECL && !DECL_INITIAL (x))
|
||||||
/* A local declaration for an `extern' variable is in the
|
/* 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. */
|
function. */
|
||||||
&& !(TREE_CODE (x) == VAR_DECL && DECL_EXTERNAL (x))
|
&& !(TREE_CODE (x) == VAR_DECL && DECL_EXTERNAL (x))
|
||||||
&& !DECL_CONTEXT (x))
|
&& !DECL_CONTEXT (x))
|
||||||
@ -3871,20 +3871,40 @@ pushdecl (x)
|
|||||||
name = DECL_NAME (x);
|
name = DECL_NAME (x);
|
||||||
if (name)
|
if (name)
|
||||||
{
|
{
|
||||||
#if 0
|
int different_binding_level = 0;
|
||||||
/* Not needed...see below. */
|
|
||||||
char *file;
|
|
||||||
int line;
|
|
||||||
#endif
|
|
||||||
if (TREE_CODE (name) == TEMPLATE_ID_EXPR)
|
if (TREE_CODE (name) == TEMPLATE_ID_EXPR)
|
||||||
name = TREE_OPERAND (name, 0);
|
name = TREE_OPERAND (name, 0);
|
||||||
|
|
||||||
/* Namespace-scoped variables are not found in the current level. */
|
/* In case this decl was explicitly namespace-qualified, look it
|
||||||
if (TREE_CODE (x) == VAR_DECL && DECL_NAMESPACE_SCOPE_P (x))
|
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));
|
t = namespace_binding (name, DECL_CONTEXT (x));
|
||||||
else
|
else
|
||||||
t = lookup_name_current_level (name);
|
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
|
/* If we are declaring a function, and the result of name-lookup
|
||||||
was an OVERLOAD, look for an overloaded instance that is
|
was an OVERLOAD, look for an overloaded instance that is
|
||||||
actually the same as the function we are declaring. (If
|
actually the same as the function we are declaring. (If
|
||||||
@ -3919,7 +3939,16 @@ pushdecl (x)
|
|||||||
}
|
}
|
||||||
else if (t != NULL_TREE)
|
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)
|
if (DECL_CONTEXT (t) == NULL_TREE)
|
||||||
fatal ("parse errors have confused me too much");
|
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…
x
Reference in New Issue
Block a user