decl.c (qualify_lookup): Handle templates.

* decl.c (qualify_lookup): Handle templates.
	* decl2.c (do_using_directive): Don't pass ancestor.
	* decl.c (push_using_directive): Calculate ancestor.
	* decl2.c (do_nonmember_using_decl): Allow for type shadowing.
	* decl.c (pushdecl): Move type shadowing handling from here...
	(duplicate_decls): ...to here.
	* decl.c (set_identifier_local_value_with_scope): New fn.
	(pushdecl): Use it.
	(set_identifier_local_value, lookup_type_current_level): New fns.
	* decl2.c (do_local_using_decl): Handle types and binding level
	stuff properly.

From-SVN: r21223
This commit is contained in:
Jason Merrill 1998-07-16 21:16:06 +00:00 committed by Jason Merrill
parent 3cab3dc87e
commit 9ed182dca4
4 changed files with 115 additions and 49 deletions

View File

@ -1,5 +1,19 @@
1998-07-16 Jason Merrill <jason@yorick.cygnus.com>
* decl.c (qualify_lookup): Handle templates.
* decl2.c (do_using_directive): Don't pass ancestor.
* decl.c (push_using_directive): Calculate ancestor.
* decl2.c (do_nonmember_using_decl): Allow for type shadowing.
* decl.c (pushdecl): Move type shadowing handling from here...
(duplicate_decls): ...to here.
* decl.c (set_identifier_local_value_with_scope): New fn.
(pushdecl): Use it.
(set_identifier_local_value, lookup_type_current_level): New fns.
* decl2.c (do_local_using_decl): Handle types and binding level
stuff properly.
* init.c (build_offset_ref): Don't call mark_used on an OVERLOAD.
* decl.c (select_decl): Extract a lone function from an OVERLOAD.
(lookup_namespace_name): Likewise.

View File

@ -2379,7 +2379,7 @@ extern void pushdecl_nonclass_level PROTO((tree));
#endif
extern tree pushdecl_namespace_level PROTO((tree));
extern tree push_using_decl PROTO((tree, tree));
extern tree push_using_directive PROTO((tree, tree));
extern tree push_using_directive PROTO((tree));
extern void push_class_level_binding PROTO((tree, tree));
extern tree push_using_decl PROTO((tree, tree));
extern tree implicitly_declare PROTO((tree));
@ -2403,9 +2403,11 @@ extern tree lookup_name_nonclass PROTO((tree));
extern tree lookup_function_nonclass PROTO((tree, tree));
extern tree lookup_name PROTO((tree, int));
extern tree lookup_name_current_level PROTO((tree));
extern tree lookup_type_current_level PROTO((tree));
extern tree lookup_name_namespace_only PROTO((tree));
extern void begin_only_namespace_names PROTO((void));
extern void end_only_namespace_names PROTO((void));
extern tree namespace_ancestor PROTO((tree, tree));
extern int lookup_using_namespace PROTO((tree,tree,tree,tree,int));
extern int qualified_lookup_using_namespace PROTO((tree,tree,tree,int));
extern tree auto_function PROTO((tree, tree, enum built_in_function));

View File

@ -2159,6 +2159,26 @@ set_identifier_type_value (id, type)
set_identifier_type_value_with_scope (id, type, inner_binding_level);
}
void
set_identifier_local_value_with_scope (id, val, b)
tree id, val;
struct binding_level *b;
{
tree oldlocal;
my_friendly_assert (! b->namespace_p, 980716);
oldlocal = IDENTIFIER_LOCAL_VALUE (id);
b->shadowed = tree_cons (id, oldlocal, b->shadowed);
IDENTIFIER_LOCAL_VALUE (id) = val;
}
void
set_identifier_local_value (id, val)
tree id, val;
{
set_identifier_local_value_with_scope (id, val, current_binding_level);
}
/* Return the type associated with id. */
tree
@ -2646,12 +2666,30 @@ duplicate_decls (newdecl, olddecl)
}
else if (TREE_CODE (olddecl) != TREE_CODE (newdecl))
{
if ((TREE_CODE (olddecl) == TYPE_DECL && DECL_ARTIFICIAL (olddecl)
&& TREE_CODE (newdecl) != TYPE_DECL
&& ! (TREE_CODE (newdecl) == TEMPLATE_DECL
&& TREE_CODE (DECL_TEMPLATE_RESULT (newdecl)) == TYPE_DECL))
|| (TREE_CODE (newdecl) == TYPE_DECL && DECL_ARTIFICIAL (newdecl)
&& TREE_CODE (olddecl) != TYPE_DECL
&& ! (TREE_CODE (olddecl) == TEMPLATE_DECL
&& (TREE_CODE (DECL_TEMPLATE_RESULT (olddecl))
== TYPE_DECL))))
{
/* We do nothing special here, because C++ does such nasty
things with TYPE_DECLs. Instead, just let the TYPE_DECL
get shadowed, and know that if we need to find a TYPE_DECL
for a given name, we can look in the IDENTIFIER_TYPE_VALUE
slot of the identifier. */
return 0;
}
if ((TREE_CODE (newdecl) == FUNCTION_DECL
&& DECL_FUNCTION_TEMPLATE_P (olddecl))
|| (TREE_CODE (olddecl) == FUNCTION_DECL
&& DECL_FUNCTION_TEMPLATE_P (newdecl)))
return 0;
cp_error ("`%#D' redeclared as different kind of symbol", newdecl);
if (TREE_CODE (olddecl) == TREE_LIST)
olddecl = TREE_VALUE (olddecl);
@ -3319,24 +3357,7 @@ pushdecl (x)
}
else if (TREE_CODE (t) != TREE_CODE (x))
{
if ((TREE_CODE (t) == TYPE_DECL && DECL_ARTIFICIAL (t)
&& TREE_CODE (x) != TYPE_DECL
&& ! (TREE_CODE (x) == TEMPLATE_DECL
&& TREE_CODE (DECL_TEMPLATE_RESULT (x)) == TYPE_DECL))
|| (TREE_CODE (x) == TYPE_DECL && DECL_ARTIFICIAL (x)
&& TREE_CODE (t) != TYPE_DECL
&& ! (TREE_CODE (t) == TEMPLATE_DECL
&& (TREE_CODE (DECL_TEMPLATE_RESULT (t))
== TYPE_DECL))))
{
/* We do nothing special here, because C++ does such nasty
things with TYPE_DECLs. Instead, just let the TYPE_DECL
get shadowed, and know that if we need to find a TYPE_DECL
for a given name, we can look in the IDENTIFIER_TYPE_VALUE
slot of the identifier. */
;
}
else if (duplicate_decls (x, t))
if (duplicate_decls (x, t))
return t;
}
else if (duplicate_decls (x, t))
@ -3519,10 +3540,7 @@ pushdecl (x)
if (TREE_CODE (x) != TYPE_DECL
|| t == NULL_TREE
|| ! DECL_ARTIFICIAL (x))
{
b->shadowed = tree_cons (name, oldlocal, b->shadowed);
IDENTIFIER_LOCAL_VALUE (name) = x;
}
set_identifier_local_value_with_scope (name, x, b);
/* If this is a TYPE_DECL, push it into the type value slot. */
if (TREE_CODE (x) == TYPE_DECL)
@ -3851,12 +3869,11 @@ push_using_decl (scope, name)
TREE_LIST otherwise. */
tree
push_using_directive (used, ancestor)
push_using_directive (used)
tree used;
tree ancestor;
{
tree ud = current_binding_level->using_directives;
tree iter;
tree iter, ancestor;
/* Check if we already have this. */
if (purpose_member (used, ud) != NULL_TREE)
@ -3864,8 +3881,9 @@ push_using_directive (used, ancestor)
/* Recursively add all namespaces used. */
for (iter = DECL_NAMESPACE_USING (used); iter; iter = TREE_CHAIN (iter))
push_using_directive (TREE_PURPOSE (iter), ancestor);
push_using_directive (TREE_PURPOSE (iter));
ancestor = namespace_ancestor (current_decl_namespace (), used);
ud = current_binding_level->using_directives;
ud = perm_tree_cons (used, ancestor, ud);
current_binding_level->using_directives = ud;
@ -4859,7 +4877,10 @@ qualify_lookup (val, flags)
return val;
if (LOOKUP_NAMESPACES_ONLY (flags) && TREE_CODE (val) != NAMESPACE_DECL)
return NULL_TREE;
if (LOOKUP_TYPES_ONLY (flags) && TREE_CODE (val) != TYPE_DECL)
if (LOOKUP_TYPES_ONLY (flags) && TREE_CODE (val) != TYPE_DECL
&& ! ((flags & LOOKUP_TEMPLATES_EXPECTED)
&& TREE_CODE (val) == TEMPLATE_DECL
&& DECL_CLASS_TEMPLATE_P (val)))
return NULL_TREE;
return val;
}
@ -5133,16 +5154,41 @@ lookup_name_current_level (name)
struct binding_level *b = current_binding_level;
while (1)
{
for (t = b->names; t; t = TREE_CHAIN (t))
if (DECL_NAME (t) == name || DECL_ASSEMBLER_NAME (t) == name)
goto out;
if (purpose_member (name, b->shadowed))
return IDENTIFIER_LOCAL_VALUE (name);
if (b->keep == 2)
b = b->level_chain;
else
break;
}
}
return t;
}
/* Like lookup_name_current_level, but for types. */
tree
lookup_type_current_level (name)
tree name;
{
register tree t = NULL_TREE;
my_friendly_assert (! current_binding_level->namespace_p, 980716);
if (REAL_IDENTIFIER_TYPE_VALUE (name) != NULL_TREE
&& REAL_IDENTIFIER_TYPE_VALUE (name) != global_type_node)
{
struct binding_level *b = current_binding_level;
while (1)
{
if (purpose_member (name, b->type_shadowed))
return REAL_IDENTIFIER_TYPE_VALUE (name);
if (b->keep == 2)
b = b->level_chain;
else
break;
}
out:
;
}
return t;

View File

@ -58,7 +58,6 @@ static int finish_vtable_vardecl PROTO((tree, tree));
static int prune_vtable_vardecl PROTO((tree, tree));
static void finish_sigtable_vardecl PROTO((tree, tree));
static int is_namespace_ancestor PROTO((tree, tree));
static tree namespace_ancestor PROTO((tree, tree));
static void add_using_namespace PROTO((tree, tree, int));
static tree ambiguous_decl PROTO((tree, tree, tree,int));
static tree build_anon_union_vars PROTO((tree, tree*, int, int));
@ -3839,7 +3838,7 @@ is_namespace_ancestor (root, child)
/* Return the namespace that is the common ancestor
of two given namespaces. */
static tree
tree
namespace_ancestor (ns1, ns2)
tree ns1, ns2;
{
@ -4495,10 +4494,16 @@ do_nonmember_using_decl (scope, name, oldval, oldtype, newval, newtype)
if (BINDING_VALUE (decls) && is_overloaded_fn (BINDING_VALUE (decls)))
{
tree tmp, tmp1;
if (oldval && !is_overloaded_fn (oldval))
{
duplicate_decls (OVL_CURRENT (BINDING_VALUE (decls)), oldval);
oldval = NULL_TREE;
}
*newval = oldval;
for (tmp = BINDING_VALUE (decls); tmp; tmp = OVL_NEXT (tmp))
{
/* Compare each new function with each old one.
If the old function was also used, there is no conflict. */
for (tmp1 = oldval; tmp1; tmp1 = OVL_NEXT (tmp1))
@ -4522,8 +4527,8 @@ do_nonmember_using_decl (scope, name, oldval, oldtype, newval, newtype)
else
{
*newval = BINDING_VALUE (decls);
if (oldval && oldval != *newval && !duplicate_decls (*newval, oldval))
*newval = oldval;
if (oldval)
duplicate_decls (*newval, oldval);
}
*newtype = BINDING_TYPE (decls);
@ -4563,27 +4568,28 @@ do_toplevel_using_decl (decl)
return;
}
/* Process a using-declaration at function scope. */
void
do_local_using_decl (decl)
tree decl;
{
tree scope, name;
tree oldval, oldtype, newval, newtype;
decl = validate_nonmember_using_decl (decl, &scope, &name);
if (decl == NULL_TREE)
return;
/* XXX nested values */
oldval = IDENTIFIER_LOCAL_VALUE (name);
/* XXX get local type */
oldtype = NULL_TREE;
oldval = lookup_name_current_level (name);
oldtype = lookup_type_current_level (name);
do_nonmember_using_decl (scope, name, oldval, oldtype, &newval, &newtype);
if (newval)
/* XXX update bindings */
IDENTIFIER_LOCAL_VALUE (name) = newval;
/* XXX type */
set_identifier_local_value (name, newval);
if (newtype)
set_identifier_type_value (name, newtype);
}
tree
@ -4638,9 +4644,7 @@ do_using_directive (namespace)
}
namespace = ORIGINAL_NAMESPACE (namespace);
if (!toplevel_bindings_p ())
push_using_directive
(namespace, namespace_ancestor (current_decl_namespace(),
current_namespace));
push_using_directive (namespace);
else
/* direct usage */
add_using_namespace (current_namespace, namespace, 0);