#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));
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));
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
}
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);
}
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))
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)
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)
/* 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;
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;
}
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;
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));
/* Return the namespace that is the common ancestor
of two given namespaces. */
-static tree
+tree
namespace_ancestor (ns1, ns2)
tree ns1, ns2;
{
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))
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);
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
}
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);