aboutsummaryrefslogtreecommitdiff
path: root/gcc
diff options
context:
space:
mode:
authorJason Merrill <jason@yorick.cygnus.com>1998-07-16 21:16:06 +0000
committerJason Merrill <jason@gcc.gnu.org>1998-07-16 17:16:06 -0400
commit9ed182dca4ff768a67d63b6070067d5fd6fa4854 (patch)
tree1e93c1b7ac99ea5e5037ac1ffe84d6b6f6abf378 /gcc
parent3cab3dc87eec39db26713b537427a4664d4dbe4c (diff)
downloadgcc-9ed182dca4ff768a67d63b6070067d5fd6fa4854.zip
gcc-9ed182dca4ff768a67d63b6070067d5fd6fa4854.tar.gz
gcc-9ed182dca4ff768a67d63b6070067d5fd6fa4854.tar.bz2
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
Diffstat (limited to 'gcc')
-rw-r--r--gcc/cp/ChangeLog14
-rw-r--r--gcc/cp/cp-tree.h4
-rw-r--r--gcc/cp/decl.c112
-rw-r--r--gcc/cp/decl2.c34
4 files changed, 115 insertions, 49 deletions
diff --git a/gcc/cp/ChangeLog b/gcc/cp/ChangeLog
index 85e8e05..20e6653 100644
--- a/gcc/cp/ChangeLog
+++ b/gcc/cp/ChangeLog
@@ -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.
diff --git a/gcc/cp/cp-tree.h b/gcc/cp/cp-tree.h
index 3f8840a..f6c1e23 100644
--- a/gcc/cp/cp-tree.h
+++ b/gcc/cp/cp-tree.h
@@ -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));
diff --git a/gcc/cp/decl.c b/gcc/cp/decl.c
index 8071386..478d75b 100644
--- a/gcc/cp/decl.c
+++ b/gcc/cp/decl.c
@@ -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;
diff --git a/gcc/cp/decl2.c b/gcc/cp/decl2.c
index 5384e98..6713c65 100644
--- a/gcc/cp/decl2.c
+++ b/gcc/cp/decl2.c
@@ -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);