aboutsummaryrefslogtreecommitdiff
path: root/gcc/cp/decl.c
diff options
context:
space:
mode:
authorJason Merrill <jason@redhat.com>2000-08-27 21:16:08 -0400
committerJason Merrill <jason@gcc.gnu.org>2000-08-27 21:16:08 -0400
commit94dfccd136eece4162a4c78bcc14b3fa61767c0e (patch)
treee2496e43b37d7c4c672ec630c8be922f91b318bb /gcc/cp/decl.c
parentbbfbf340fc90540e37aff95581596c7225ae926b (diff)
downloadgcc-94dfccd136eece4162a4c78bcc14b3fa61767c0e.zip
gcc-94dfccd136eece4162a4c78bcc14b3fa61767c0e.tar.gz
gcc-94dfccd136eece4162a4c78bcc14b3fa61767c0e.tar.bz2
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
Diffstat (limited to 'gcc/cp/decl.c')
-rw-r--r--gcc/cp/decl.c47
1 files changed, 38 insertions, 9 deletions
diff --git a/gcc/cp/decl.c b/gcc/cp/decl.c
index 613c44e..552070b 100644
--- a/gcc/cp/decl.c
+++ b/gcc/cp/decl.c
@@ -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");