* decl.c (qualify_lookup): New fn.
(lookup_name_real): Use it.
* decl2.c (add_using_namespace): When directly using a namespace
that was indirect before, promote it.
* cp-tree.h (LOOKUP_PREFER_TYPES, LOOKUP_PREFER_NAMESPACES,
LOOKUP_PREFER_BOTH, LOOKUP_NAMESPACES_ONLY, LOOKUP_TYPES_ONLY,
LOOKUP_QUALIFIERS_ONLY, LOOKUP_TEMPLATES_EXPECTED): New macros.
* decl.c (select_decl): Replace two flag parameters by one.
(unqualified_namespace_lookup): Likewise, pass flag.
(lookup_flags): New function.
(lookup_name_real): Compute flags, pass them.
(lookup_namespace_name): Call with zero-flag.
* decl2.c (ambiguous_decl): Add flag parameter, complain only
according to flags.
(lookup_using_namespace, qualified_lookup_using_namespace):
Add flag parameter, pass them through.
* lex.c (do_scoped_id): Call with zero-flag.
From-SVN: r21218
+1998-07-16 Jason Merrill <jason@yorick.cygnus.com>
+
+ * decl.c (qualify_lookup): New fn.
+ (lookup_name_real): Use it.
+
+1998-07-16 Martin v. Loewis <loewis@informatik.hu-berlin.de>
+
+ * decl2.c (add_using_namespace): When directly using a namespace
+ that was indirect before, promote it.
+
+ * cp-tree.h (LOOKUP_PREFER_TYPES, LOOKUP_PREFER_NAMESPACES,
+ LOOKUP_PREFER_BOTH, LOOKUP_NAMESPACES_ONLY, LOOKUP_TYPES_ONLY,
+ LOOKUP_QUALIFIERS_ONLY, LOOKUP_TEMPLATES_EXPECTED): New macros.
+ * decl.c (select_decl): Replace two flag parameters by one.
+ (unqualified_namespace_lookup): Likewise, pass flag.
+ (lookup_flags): New function.
+ (lookup_name_real): Compute flags, pass them.
+ (lookup_namespace_name): Call with zero-flag.
+ * decl2.c (ambiguous_decl): Add flag parameter, complain only
+ according to flags.
+ (lookup_using_namespace, qualified_lookup_using_namespace):
+ Add flag parameter, pass them through.
+ * lex.c (do_scoped_id): Call with zero-flag.
+
1998-07-16 Jason Merrill <jason@yorick.cygnus.com>
* typeck.c (convert_for_assignment): Use comptypes.
LOOKUP_NO_CONVERSION means that user-defined conversions are not
permitted. Built-in conversions are permitted.
LOOKUP_DESTRUCTOR means explicit call to destructor.
- LOOKUP_NO_TEMP_BIND means temporaries will not be bound to references. */
+ LOOKUP_NO_TEMP_BIND means temporaries will not be bound to references.
+
+ These are used in global lookup to support elaborated types and
+ qualifiers.
+
+ LOOKUP_PREFER_TYPES means not to accept objects, and possibly namespaces.
+ LOOKUP_PREFER_NAMESPACES means not to accept objects, and possibly types.
+ LOOKUP_PREFER_BOTH means class-or-namespace-name.
+ LOOKUP_TEMPLATES_EXPECTED means that class templates also count
+ as types. */
#define LOOKUP_PROTECT (1)
#define LOOKUP_COMPLAIN (2)
#define LOOKUP_NO_CONVERSION (512)
#define LOOKUP_DESTRUCTOR (512)
#define LOOKUP_NO_TEMP_BIND (1024)
+#define LOOKUP_PREFER_TYPES (2048)
+#define LOOKUP_PREFER_NAMESPACES (4096)
+#define LOOKUP_PREFER_BOTH (6144)
+#define LOOKUP_TEMPLATES_EXPECTED (8192)
+
+#define LOOKUP_NAMESPACES_ONLY(f) \
+ (((f) & LOOKUP_PREFER_NAMESPACES) && !((f) & LOOKUP_PREFER_TYPES))
+#define LOOKUP_TYPES_ONLY(f) \
+ (!((f) & LOOKUP_PREFER_NAMESPACES) && ((f) & LOOKUP_PREFER_TYPES))
+#define LOOKUP_QUALIFIERS_ONLY(f) ((f) & LOOKUP_PREFER_BOTH)
+
/* These flags are used by the conversion code.
CONV_IMPLICIT : Perform implicit conversions (standard and user-defined).
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 int lookup_using_namespace PROTO((tree,tree,tree,tree));
-extern int qualified_lookup_using_namespace PROTO((tree,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));
extern void init_decl_processing PROTO((void));
extern int init_type_desc PROTO((void));
my_friendly_assert (TREE_CODE (name) == IDENTIFIER_NODE, 373);
val = binding_init (&_b);
- if (!qualified_lookup_using_namespace (name, namespace, val))
+ if (!qualified_lookup_using_namespace (name, namespace, val, 0))
return error_mark_node;
if (BINDING_VALUE (val))
/* Select the right _DECL from multiple choices. */
static tree
-select_decl (binding, prefer_type, namespaces_only)
+select_decl (binding, flags)
tree binding;
- int prefer_type, namespaces_only;
+ int flags;
{
tree val;
val = BINDING_VALUE (binding);
- if (namespaces_only)
+ if (LOOKUP_NAMESPACES_ONLY (flags))
{
/* We are not interested in types. */
if (val && TREE_CODE (val) == NAMESPACE_DECL)
/* If we could have a type and
we have nothing or we need a type and have none. */
if (BINDING_TYPE (binding)
- && (!val || (prefer_type && TREE_CODE (val) != TYPE_DECL)))
+ && (!val || ((flags & LOOKUP_PREFER_TYPES)
+ && TREE_CODE (val) != TYPE_DECL)))
val = TYPE_STUB_DECL (BINDING_TYPE (binding));
/* Don't return non-types if we really prefer types. */
- else if (val && prefer_type > 1 && TREE_CODE (val) != TYPE_DECL
+ else if (val && LOOKUP_TYPES_ONLY (flags) && TREE_CODE (val) != TYPE_DECL
&& (!looking_for_template || TREE_CODE (val) != TEMPLATE_DECL))
val = NULL_TREE;
return val;
using namespace statements. */
static tree
-unqualified_namespace_lookup (name, prefer_type, namespaces_only)
+unqualified_namespace_lookup (name, flags)
tree name;
- int prefer_type;
- int namespaces_only;
+ int flags;
{
struct tree_binding _binding;
tree b = binding_init (&_binding);
for (level = current_binding_level;
!level->namespace_p;
level = level->level_chain)
- if (!lookup_using_namespace (name, b, level->using_directives, scope))
+ if (!lookup_using_namespace (name, b, level->using_directives,
+ scope, flags))
/* Give up because of error. */
return NULL_TREE;
while (1)
{
if (!lookup_using_namespace (name, b, DECL_NAMESPACE_USING (siter),
- scope))
+ scope, flags))
/* Give up because of error. */
return NULL_TREE;
if (siter == scope) break;
siter = CP_DECL_CONTEXT (siter);
}
- val = select_decl (b, prefer_type, namespaces_only);
+ val = select_decl (b, flags);
if (scope == global_namespace)
break;
scope = DECL_CONTEXT (scope);
return val;
}
+/* Combine prefer_type and namespaces_only into flags. */
+
+static int
+lookup_flags (prefer_type, namespaces_only)
+ int prefer_type, namespaces_only;
+{
+ if (namespaces_only)
+ return LOOKUP_PREFER_NAMESPACES;
+ if (prefer_type > 1)
+ return LOOKUP_PREFER_TYPES;
+ if (prefer_type > 0)
+ return LOOKUP_PREFER_BOTH;
+ return 0;
+}
+
+/* Given a lookup that returned VAL, use FLAGS to decide if we want to
+ ignore it or not. Subroutine of lookup_name_real. */
+
+static tree
+qualify_lookup (val, flags)
+ tree val;
+ int flags;
+{
+ if (val == NULL_TREE)
+ 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)
+ return NULL_TREE;
+ return val;
+}
+
/* Look up NAME in the current binding level and its superiors in the
namespace of variables, functions and typedefs. Return a ..._DECL
node of some kind representing its definition if there is only one
int yylex = 0;
tree from_obj = NULL_TREE;
tree locval, classval;
+ int flags;
/* Hack: copy flag set by parser, if set. */
if (only_namespace_names)
namespaces_only = 1;
-
+
if (prefer_type == -2)
{
extern int looking_for_typename;
yylex = 1;
prefer_type = looking_for_typename;
+ flags = lookup_flags (prefer_type, namespaces_only);
+ /* During parsing, we need to complain. */
+ flags |= LOOKUP_COMPLAIN;
+ /* If the next thing is '<', class templates are types. */
+ if (looking_for_template)
+ flags |= LOOKUP_TEMPLATES_EXPECTED;
+
/* std:: becomes :: for now. */
if (got_scope == std_node)
got_scope = void_type_node;
{
struct tree_binding b;
val = binding_init (&b);
- if (!qualified_lookup_using_namespace (name, type, val))
+ if (!qualified_lookup_using_namespace (name, type, val, flags))
return NULL_TREE;
- val = select_decl (val, prefer_type, namespaces_only);
+ val = select_decl (val, flags);
}
else if (! IS_AGGR_TYPE (type)
|| TREE_CODE (type) == TEMPLATE_TYPE_PARM
else if (got_object && val)
from_obj = val;
}
+ else
+ flags = lookup_flags (prefer_type, namespaces_only);
locval = classval = NULL_TREE;
- if (!current_binding_level->namespace_p
- && IDENTIFIER_LOCAL_VALUE (name))
- switch (TREE_CODE (IDENTIFIER_LOCAL_VALUE (name)))
- {
- case NAMESPACE_DECL:
- /* A namespace is rejected only if we strictly require types. */
- if (prefer_type <= 1)
- locval = IDENTIFIER_LOCAL_VALUE (name);
- break;
- case TYPE_DECL:
- /* A type is rejected only if we strictly require namespaces. */
- if (!namespaces_only)
- locval = IDENTIFIER_LOCAL_VALUE (name);
- break;
- default:
- /* We require neither types or namespaces. */
- if (!namespaces_only && prefer_type <= 0)
- locval = IDENTIFIER_LOCAL_VALUE (name);
- break;
- }
+ if (! namespace_bindings_p ())
+ locval = qualify_lookup (IDENTIFIER_LOCAL_VALUE (name), flags);
/* In C++ class fields are between local and global scope,
just before the global scope. */
created the COMPONENT_REF or anything like that. */
if (classval == NULL_TREE)
classval = lookup_nested_field (name, ! yylex);
+
+ classval = qualify_lookup (classval, flags);
}
if (locval && classval)
else if (classval)
val = classval;
else
- val = unqualified_namespace_lookup (name, prefer_type, namespaces_only);
+ val = unqualified_namespace_lookup (name, flags);
done:
if (val)
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));
+static tree ambiguous_decl PROTO((tree, tree, tree,int));
static tree build_anon_union_vars PROTO((tree, tree*, int, int));
static void check_decl_namespace PROTO((void));
tree used;
int indirect;
{
- tree iter;
+ tree t;
/* Using oneself is a no-op. */
if (user == used)
return;
my_friendly_assert (TREE_CODE (user) == NAMESPACE_DECL, 380);
my_friendly_assert (TREE_CODE (used) == NAMESPACE_DECL, 380);
/* Check if we already have this. */
- if (purpose_member (used, DECL_NAMESPACE_USING (user)) != NULL_TREE)
- return;
+ t = purpose_member (used, DECL_NAMESPACE_USING (user));
+ if (t != NULL_TREE)
+ {
+ if (!indirect)
+ /* Promote to direct usage. */
+ TREE_INDIRECT_USING (t) = 0;
+ return;
+ }
/* Add used to the user's using list. */
DECL_NAMESPACE_USING (user)
= perm_tree_cons (user, 0, DECL_NAMESPACE_USERS (used));
/* Recursively add all namespaces used. */
- for (iter = DECL_NAMESPACE_USING (used); iter; iter = TREE_CHAIN (iter))
+ for (t = DECL_NAMESPACE_USING (used); t; t = TREE_CHAIN (t))
/* indirect usage */
- add_using_namespace (user, TREE_PURPOSE (iter), 1);
+ add_using_namespace (user, TREE_PURPOSE (t), 1);
/* Tell everyone using us about the new used namespaces. */
- for (iter = DECL_NAMESPACE_USERS (user); iter; iter = TREE_CHAIN (iter))
- add_using_namespace (TREE_PURPOSE (iter), used, 1);
+ for (t = DECL_NAMESPACE_USERS (user); t; t = TREE_CHAIN (t))
+ add_using_namespace (TREE_PURPOSE (t), used, 1);
}
/* Combines two sets of overloaded functions into an OVERLOAD chain.
XXX I don't want to repeat the entire duplicate_decls here */
static tree
-ambiguous_decl (name, old, new)
+ambiguous_decl (name, old, new, flags)
tree name;
tree old;
tree new;
+ int flags;
{
+ tree val, type;
my_friendly_assert (old != NULL_TREE, 393);
/* Copy the value. */
+ val = BINDING_VALUE (new);
+ if (val)
+ switch (TREE_CODE (val))
+ {
+ case TEMPLATE_DECL:
+ /* If we expect types or namespaces, and not templates,
+ or this is not a template class. */
+ if (LOOKUP_QUALIFIERS_ONLY (flags)
+ && (!(flags & LOOKUP_TEMPLATES_EXPECTED)
+ || !DECL_CLASS_TEMPLATE_P (val)))
+ val = NULL_TREE;
+ break;
+ case TYPE_DECL:
+ if (LOOKUP_NAMESPACES_ONLY (flags))
+ val = NULL_TREE;
+ break;
+ case NAMESPACE_DECL:
+ if (LOOKUP_TYPES_ONLY (flags))
+ val = NULL_TREE;
+ break;
+ default:
+ if (LOOKUP_QUALIFIERS_ONLY (flags))
+ val = NULL_TREE;
+ }
+
if (!BINDING_VALUE (old))
- BINDING_VALUE (old) = BINDING_VALUE (new);
- else if (BINDING_VALUE (new)
- && BINDING_VALUE (new) != BINDING_VALUE (old))
+ BINDING_VALUE (old) = val;
+ else if (val && val != BINDING_VALUE (old))
{
if (is_overloaded_fn (BINDING_VALUE (old))
- && is_overloaded_fn (BINDING_VALUE (new)))
+ && is_overloaded_fn (val))
{
BINDING_VALUE (old) = merge_functions (BINDING_VALUE (old),
- BINDING_VALUE (new));
+ val);
}
else
{
/* Some declarations are functions, some are not. */
- cp_error ("use of `%D' is ambiguous", name);
- cp_error_at (" first declared as `%#D' here", BINDING_VALUE (old));
- cp_error_at (" also declared as `%#D' here", BINDING_VALUE (new));
+ if (flags & LOOKUP_COMPLAIN)
+ {
+ cp_error ("use of `%D' is ambiguous", name);
+ cp_error_at (" first declared as `%#D' here",
+ BINDING_VALUE (old));
+ cp_error_at (" also declared as `%#D' here", val);
+ }
return error_mark_node;
}
}
/* ... and copy the type. */
+ type = BINDING_TYPE (new);
+ if (LOOKUP_NAMESPACES_ONLY (flags))
+ type = NULL_TREE;
if (!BINDING_TYPE (old))
- BINDING_TYPE (old) = BINDING_TYPE (new);
- else if(BINDING_TYPE (new)
- && BINDING_TYPE (old) != BINDING_TYPE (new))
+ BINDING_TYPE (old) = type;
+ else if(type && BINDING_TYPE (old) != type)
{
- cp_error ("`%D' denotes an ambiguous type",name);
- cp_error_at ("first type here", BINDING_TYPE (old));
- cp_error_at ("other type here", BINDING_TYPE (new));
+ if (flags & LOOKUP_COMPLAIN)
+ {
+ cp_error ("`%D' denotes an ambiguous type",name);
+ cp_error_at (" first type here", BINDING_TYPE (old));
+ cp_error_at (" other type here", type);
+ }
}
return old;
}
Returns zero on errors. */
int
-lookup_using_namespace (name, val, usings, scope)
+lookup_using_namespace (name, val, usings, scope, flags)
tree name, val, usings, scope;
+ int flags;
{
tree iter;
tree val1;
{
val1 = binding_for_name (name, TREE_PURPOSE (iter));
/* Resolve ambiguities. */
- val = ambiguous_decl (name, val, val1);
+ val = ambiguous_decl (name, val, val1, flags);
}
return val != error_mark_node;
}
or 0 on error. */
int
-qualified_lookup_using_namespace (name, scope, result)
+qualified_lookup_using_namespace (name, scope, result, flags)
tree name;
tree scope;
tree result;
+ int flags;
{
/* Maintain a list of namespaces visited... */
tree seen = NULL_TREE;
while (scope && (result != error_mark_node))
{
seen = temp_tree_cons (scope, NULL_TREE, seen);
- result = ambiguous_decl (name, result, binding_for_name (name, scope));
+ result = ambiguous_decl (name, result,
+ binding_for_name (name, scope), flags);
if (!BINDING_VALUE (result) && !BINDING_TYPE (result))
/* Consider using directives. */
for (usings = DECL_NAMESPACE_USING (scope); usings;
*newval = *newtype = NULL_TREE;
decls = binding_init (&_decls);
- if (!qualified_lookup_using_namespace (name, scope, decls))
+ if (!qualified_lookup_using_namespace (name, scope, decls, 0))
/* Lookup error */
return;
{
struct tree_binding _b;
id = binding_init (&_b);
- if (!qualified_lookup_using_namespace (token, global_namespace, id))
+ if (!qualified_lookup_using_namespace (token, global_namespace, id, 0))
id = NULL_TREE;
else
id = BINDING_VALUE (id);