Commit 5a167978 by Gabriel Dos Reis Committed by Gabriel Dos Reis

name-lookup.h (cxx_scope_find_binding_for_name): Don't export.

	* name-lookup.h (cxx_scope_find_binding_for_name): Don't export.
	(binding_for_name): Likewise.
	(cxx_binding_clear): Move to name-lookup.c.
	* name-lookup.c (cxx_scope_find_binding_for_name): Now static.
	(binding_for_name): Likewise.
	* decl2.c (is_ancestor): Move to name-lookup.c
	(namespace_ancestor): Likewise.
	(add_using_namespace): Likewise.
	(ambiguous_decl): Likewise.
	(lookup_using_namespace): Likewise.
	(qualified_lookup_using_namespace): Likewise.
	(set_decl_namespace): Likewise.
	(decl_namespace): Likewise.
	(current_decl_namespace): Likewise.
	(push_decl_namespace): Likewise.
	(pop_decl_namespace): Likewise.
	(push_scope): Likewise.
	(pop_scope): Likewise.
	(struct arg_lookup): Likewise.
	(arg_assoc): Likewise.
	(arg_assoc_args): Likewise.
	(arg_assoc_type): Likewise.
	(add_function): Likewise.
	(arg_assoc_namespace): Likewise.
	(arg_assoc_class): Likewise.
	(arg_assoc_template_arg): Likewise.
	(do_namespace_alias): Likewise.
	(validate_nonmember_using_decl): Likewise.
	(do_nonmember_using_decl): Likewise.
	(do_toplevel_using_decl): Likewise.
	(do_local_using_decl): Likewise.
	(do_class_using_decl): Likewise.
	(do_using_directive): Likewise.
	(constructor_name_full): Likewise.
	(constructor_name): Likewise.
	(constructor_name_p): Likewise.

From-SVN: r72462
parent 9dccaa6b
...@@ -4,6 +4,45 @@ ...@@ -4,6 +4,45 @@
2003-10-13 Gabriel Dos Reis <gdr@integrable-solutions.net> 2003-10-13 Gabriel Dos Reis <gdr@integrable-solutions.net>
* name-lookup.h (cxx_scope_find_binding_for_name): Don't export.
(binding_for_name): Likewise.
(cxx_binding_clear): Move to name-lookup.c.
* name-lookup.c (cxx_scope_find_binding_for_name): Now static.
(binding_for_name): Likewise.
* decl2.c (is_ancestor): Move to name-lookup.c
(namespace_ancestor): Likewise.
(add_using_namespace): Likewise.
(ambiguous_decl): Likewise.
(lookup_using_namespace): Likewise.
(qualified_lookup_using_namespace): Likewise.
(set_decl_namespace): Likewise.
(decl_namespace): Likewise.
(current_decl_namespace): Likewise.
(push_decl_namespace): Likewise.
(pop_decl_namespace): Likewise.
(push_scope): Likewise.
(pop_scope): Likewise.
(struct arg_lookup): Likewise.
(arg_assoc): Likewise.
(arg_assoc_args): Likewise.
(arg_assoc_type): Likewise.
(add_function): Likewise.
(arg_assoc_namespace): Likewise.
(arg_assoc_class): Likewise.
(arg_assoc_template_arg): Likewise.
(do_namespace_alias): Likewise.
(validate_nonmember_using_decl): Likewise.
(do_nonmember_using_decl): Likewise.
(do_toplevel_using_decl): Likewise.
(do_local_using_decl): Likewise.
(do_class_using_decl): Likewise.
(do_using_directive): Likewise.
(constructor_name_full): Likewise.
(constructor_name): Likewise.
(constructor_name_p): Likewise.
2003-10-13 Gabriel Dos Reis <gdr@integrable-solutions.net>
Break out decl.c (2/n) Break out decl.c (2/n)
* name-lookup.c: Include diagnostic.h * name-lookup.c: Include diagnostic.h
(cxx_binding_free): Make static. (cxx_binding_free): Make static.
......
...@@ -3615,11 +3615,7 @@ extern void check_goto (tree); ...@@ -3615,11 +3615,7 @@ extern void check_goto (tree);
extern void define_case_label (void); extern void define_case_label (void);
extern tree make_typename_type (tree, tree, tsubst_flags_t); extern tree make_typename_type (tree, tree, tsubst_flags_t);
extern tree make_unbound_class_template (tree, tree, tsubst_flags_t); extern tree make_unbound_class_template (tree, tree, tsubst_flags_t);
extern tree namespace_ancestor (tree, tree);
extern bool is_ancestor (tree, tree);
extern tree check_for_out_of_scope_variable (tree); extern tree check_for_out_of_scope_variable (tree);
extern bool lookup_using_namespace (tree, cxx_binding *, tree, tree, int, tree *);
extern bool qualified_lookup_using_namespace (tree, tree, cxx_binding *, int);
extern tree build_library_fn (tree, tree); extern tree build_library_fn (tree, tree);
extern tree build_library_fn_ptr (const char *, tree); extern tree build_library_fn_ptr (const char *, tree);
extern tree build_cp_library_fn_ptr (const char *, tree); extern tree build_cp_library_fn_ptr (const char *, tree);
...@@ -3709,9 +3705,6 @@ extern tree grokfield (tree, tree, tree, tree, tree); ...@@ -3709,9 +3705,6 @@ extern tree grokfield (tree, tree, tree, tree, tree);
extern tree grokbitfield (tree, tree, tree); extern tree grokbitfield (tree, tree, tree);
extern tree groktypefield (tree, tree); extern tree groktypefield (tree, tree);
extern void cplus_decl_attributes (tree *, tree, int); extern void cplus_decl_attributes (tree *, tree, int);
extern tree constructor_name_full (tree);
extern tree constructor_name (tree);
extern bool constructor_name_p (tree, tree);
extern void defer_fn (tree); extern void defer_fn (tree);
extern void finish_anon_union (tree); extern void finish_anon_union (tree);
extern tree finish_table (tree, tree, tree, int); extern tree finish_table (tree, tree, tree, int);
...@@ -3723,20 +3716,8 @@ extern void import_export_decl (tree); ...@@ -3723,20 +3716,8 @@ extern void import_export_decl (tree);
extern void import_export_tinfo (tree, tree, bool); extern void import_export_tinfo (tree, tree, bool);
extern tree build_cleanup (tree); extern tree build_cleanup (tree);
extern tree build_offset_ref_call_from_tree (tree, tree); extern tree build_offset_ref_call_from_tree (tree, tree);
extern void set_decl_namespace (tree, tree, bool);
extern tree current_decl_namespace (void);
extern void push_decl_namespace (tree);
extern void pop_decl_namespace (void);
extern void push_scope (tree);
extern void pop_scope (tree);
extern void do_namespace_alias (tree, tree);
extern void do_toplevel_using_decl (tree);
extern void do_local_using_decl (tree);
extern tree do_class_using_decl (tree);
extern void do_using_directive (tree);
extern void check_default_args (tree); extern void check_default_args (tree);
extern void mark_used (tree); extern void mark_used (tree);
extern tree lookup_arg_dependent (tree, tree, tree);
extern void finish_static_data_member_decl (tree, tree, tree, int); extern void finish_static_data_member_decl (tree, tree, tree, int);
extern tree cp_build_parm_decl (tree, tree); extern tree cp_build_parm_decl (tree, tree);
extern tree build_artificial_parm (tree, tree); extern tree build_artificial_parm (tree, tree);
......
...@@ -64,16 +64,10 @@ typedef struct priority_info_s { ...@@ -64,16 +64,10 @@ typedef struct priority_info_s {
static void mark_vtable_entries (tree); static void mark_vtable_entries (tree);
static void grok_function_init (tree, tree); static void grok_function_init (tree, tree);
static bool maybe_emit_vtables (tree); static bool maybe_emit_vtables (tree);
static void add_using_namespace (tree, tree, bool);
static cxx_binding *ambiguous_decl (tree, cxx_binding *, cxx_binding *, int);
static tree build_anon_union_vars (tree); static tree build_anon_union_vars (tree);
static bool acceptable_java_type (tree); static bool acceptable_java_type (tree);
static tree start_objects (int, int); static tree start_objects (int, int);
static void finish_objects (int, int, tree); static void finish_objects (int, int, tree);
static tree merge_functions (tree, tree);
static tree decl_namespace (tree);
static tree validate_nonmember_using_decl (tree, tree *, tree *);
static void do_nonmember_using_decl (tree, tree, tree, tree, tree *, tree *);
static tree start_static_storage_duration_function (unsigned); static tree start_static_storage_duration_function (unsigned);
static void finish_static_storage_duration_function (tree); static void finish_static_storage_duration_function (tree);
static priority_info get_priority_info (int); static priority_info get_priority_info (int);
...@@ -115,9 +109,6 @@ int at_eof; ...@@ -115,9 +109,6 @@ int at_eof;
tree static_ctors; tree static_ctors;
tree static_dtors; tree static_dtors;
/* The :: namespace. */
tree global_namespace;
/* Incorporate `const' and `volatile' qualifiers for member functions. /* Incorporate `const' and `volatile' qualifiers for member functions.
FUNCTION is a TYPE_DECL or a FUNCTION_DECL. FUNCTION is a TYPE_DECL or a FUNCTION_DECL.
...@@ -1150,58 +1141,6 @@ cplus_decl_attributes (tree *decl, tree attributes, int flags) ...@@ -1150,58 +1141,6 @@ cplus_decl_attributes (tree *decl, tree attributes, int flags)
SET_IDENTIFIER_TYPE_VALUE (DECL_NAME (*decl), TREE_TYPE (*decl)); SET_IDENTIFIER_TYPE_VALUE (DECL_NAME (*decl), TREE_TYPE (*decl));
} }
/* Return the name for the constructor (or destructor) for the
specified class TYPE. When given a template, this routine doesn't
lose the specialization. */
tree
constructor_name_full (tree type)
{
type = TYPE_MAIN_VARIANT (type);
if (CLASS_TYPE_P (type) && TYPE_WAS_ANONYMOUS (type)
&& TYPE_HAS_CONSTRUCTOR (type))
return DECL_NAME (OVL_CURRENT (CLASSTYPE_CONSTRUCTORS (type)));
else
return TYPE_IDENTIFIER (type);
}
/* Return the name for the constructor (or destructor) for the
specified class. When given a template, return the plain
unspecialized name. */
tree
constructor_name (tree type)
{
tree name;
name = constructor_name_full (type);
if (IDENTIFIER_TEMPLATE (name))
name = IDENTIFIER_TEMPLATE (name);
return name;
}
/* Returns TRUE if NAME is the name for the constructor for TYPE. */
bool
constructor_name_p (tree name, tree type)
{
tree ctor_name;
if (!name)
return false;
if (TREE_CODE (name) != IDENTIFIER_NODE)
return false;
ctor_name = constructor_name_full (type);
if (name == ctor_name)
return true;
if (IDENTIFIER_TEMPLATE (ctor_name)
&& name == IDENTIFIER_TEMPLATE (ctor_name))
return true;
return false;
}
/* Defer the compilation of the FN until the end of compilation. */ /* Defer the compilation of the FN until the end of compilation. */
void void
...@@ -3014,1114 +2953,6 @@ build_offset_ref_call_from_tree (tree fn, tree args) ...@@ -3014,1114 +2953,6 @@ build_offset_ref_call_from_tree (tree fn, tree args)
return expr; return expr;
} }
/* Returns true if ROOT (a namespace, class, or function) encloses
CHILD. CHILD may be either a class type or a namespace. */
bool
is_ancestor (tree root, tree child)
{
my_friendly_assert ((TREE_CODE (root) == NAMESPACE_DECL
|| TREE_CODE (root) == FUNCTION_DECL
|| CLASS_TYPE_P (root)), 20030307);
my_friendly_assert ((TREE_CODE (child) == NAMESPACE_DECL
|| CLASS_TYPE_P (child)),
20030307);
/* The global namespace encloses everything. */
if (root == global_namespace)
return true;
while (true)
{
/* If we've run out of scopes, stop. */
if (!child)
return false;
/* If we've reached the ROOT, it encloses CHILD. */
if (root == child)
return true;
/* Go out one level. */
if (TYPE_P (child))
child = TYPE_NAME (child);
child = DECL_CONTEXT (child);
}
}
/* Return the namespace that is the common ancestor
of two given namespaces. */
tree
namespace_ancestor (tree ns1, tree ns2)
{
timevar_push (TV_NAME_LOOKUP);
if (is_ancestor (ns1, ns2))
POP_TIMEVAR_AND_RETURN (TV_NAME_LOOKUP, ns1);
POP_TIMEVAR_AND_RETURN (TV_NAME_LOOKUP,
namespace_ancestor (CP_DECL_CONTEXT (ns1), ns2));
}
/* Insert USED into the using list of USER. Set INDIRECT_flag if this
directive is not directly from the source. Also find the common
ancestor and let our users know about the new namespace */
static void
add_using_namespace (tree user, tree used, bool indirect)
{
tree t;
timevar_push (TV_NAME_LOOKUP);
/* Using oneself is a no-op. */
if (user == used)
{
timevar_pop (TV_NAME_LOOKUP);
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. */
t = purpose_member (used, DECL_NAMESPACE_USING (user));
if (t != NULL_TREE)
{
if (!indirect)
/* Promote to direct usage. */
TREE_INDIRECT_USING (t) = 0;
timevar_pop (TV_NAME_LOOKUP);
return;
}
/* Add used to the user's using list. */
DECL_NAMESPACE_USING (user)
= tree_cons (used, namespace_ancestor (user, used),
DECL_NAMESPACE_USING (user));
TREE_INDIRECT_USING (DECL_NAMESPACE_USING (user)) = indirect;
/* Add user to the used's users list. */
DECL_NAMESPACE_USERS (used)
= tree_cons (user, 0, DECL_NAMESPACE_USERS (used));
/* Recursively add all namespaces used. */
for (t = DECL_NAMESPACE_USING (used); t; t = TREE_CHAIN (t))
/* indirect usage */
add_using_namespace (user, TREE_PURPOSE (t), 1);
/* Tell everyone using us about the new used namespaces. */
for (t = DECL_NAMESPACE_USERS (user); t; t = TREE_CHAIN (t))
add_using_namespace (TREE_PURPOSE (t), used, 1);
timevar_pop (TV_NAME_LOOKUP);
}
/* Combines two sets of overloaded functions into an OVERLOAD chain, removing
duplicates. The first list becomes the tail of the result.
The algorithm is O(n^2). We could get this down to O(n log n) by
doing a sort on the addresses of the functions, if that becomes
necessary. */
static tree
merge_functions (tree s1, tree s2)
{
for (; s2; s2 = OVL_NEXT (s2))
{
tree fn2 = OVL_CURRENT (s2);
tree fns1;
for (fns1 = s1; fns1; fns1 = OVL_NEXT (fns1))
{
tree fn1 = OVL_CURRENT (fns1);
/* If the function from S2 is already in S1, there is no
need to add it again. For `extern "C"' functions, we
might have two FUNCTION_DECLs for the same function, in
different namespaces; again, we only need one of them. */
if (fn1 == fn2
|| (DECL_EXTERN_C_P (fn1) && DECL_EXTERN_C_P (fn2)
&& DECL_NAME (fn1) == DECL_NAME (fn2)))
break;
}
/* If we exhausted all of the functions in S1, FN2 is new. */
if (!fns1)
s1 = build_overload (fn2, s1);
}
return s1;
}
/* This should return an error not all definitions define functions.
It is not an error if we find two functions with exactly the
same signature, only if these are selected in overload resolution.
old is the current set of bindings, new the freshly-found binding.
XXX Do we want to give *all* candidates in case of ambiguity?
XXX In what way should I treat extern declarations?
XXX I don't want to repeat the entire duplicate_decls here */
static cxx_binding *
ambiguous_decl (tree name, cxx_binding *old, cxx_binding *new, int flags)
{
tree val, type;
my_friendly_assert (old != NULL, 393);
/* Copy the value. */
val = new->value;
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)
&& !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;
case FUNCTION_DECL:
/* Ignore built-in functions that are still anticipated. */
if (LOOKUP_QUALIFIERS_ONLY (flags) || DECL_ANTICIPATED (val))
val = NULL_TREE;
break;
default:
if (LOOKUP_QUALIFIERS_ONLY (flags))
val = NULL_TREE;
}
if (!old->value)
old->value = val;
else if (val && val != old->value)
{
if (is_overloaded_fn (old->value) && is_overloaded_fn (val))
old->value = merge_functions (old->value, val);
else
{
/* Some declarations are functions, some are not. */
if (flags & LOOKUP_COMPLAIN)
{
/* If we've already given this error for this lookup,
old->value is error_mark_node, so let's not
repeat ourselves. */
if (old->value != error_mark_node)
{
error ("use of `%D' is ambiguous", name);
cp_error_at (" first declared as `%#D' here",
old->value);
}
cp_error_at (" also declared as `%#D' here", val);
}
old->value = error_mark_node;
}
}
/* ... and copy the type. */
type = new->type;
if (LOOKUP_NAMESPACES_ONLY (flags))
type = NULL_TREE;
if (!old->type)
old->type = type;
else if (type && old->type != type)
{
if (flags & LOOKUP_COMPLAIN)
{
error ("`%D' denotes an ambiguous type",name);
error ("%J first type here", TYPE_MAIN_DECL (old->type));
error ("%J other type here", TYPE_MAIN_DECL (type));
}
}
return old;
}
/* Subroutine of unualified_namespace_lookup:
Add the bindings of NAME in used namespaces to VAL.
We are currently looking for names in namespace SCOPE, so we
look through USINGS for using-directives of namespaces
which have SCOPE as a common ancestor with the current scope.
Returns false on errors. */
bool
lookup_using_namespace (tree name, cxx_binding *val, tree usings, tree scope,
int flags, tree *spacesp)
{
tree iter;
timevar_push (TV_NAME_LOOKUP);
/* Iterate over all used namespaces in current, searching for using
directives of scope. */
for (iter = usings; iter; iter = TREE_CHAIN (iter))
if (TREE_VALUE (iter) == scope)
{
tree used = ORIGINAL_NAMESPACE (TREE_PURPOSE (iter));
cxx_binding *val1 =
cxx_scope_find_binding_for_name (NAMESPACE_LEVEL (used), name);
if (spacesp)
*spacesp = tree_cons (used, NULL_TREE, *spacesp);
/* Resolve ambiguities. */
if (val1)
val = ambiguous_decl (name, val, val1, flags);
}
POP_TIMEVAR_AND_RETURN (TV_NAME_LOOKUP, val->value != error_mark_node);
}
/* [namespace.qual]
Accepts the NAME to lookup and its qualifying SCOPE.
Returns the name/type pair found into the cxx_binding *RESULT,
or false on error. */
bool
qualified_lookup_using_namespace (tree name, tree scope, cxx_binding *result,
int flags)
{
/* Maintain a list of namespaces visited... */
tree seen = NULL_TREE;
/* ... and a list of namespace yet to see. */
tree todo = NULL_TREE;
tree usings;
timevar_push (TV_NAME_LOOKUP);
/* Look through namespace aliases. */
scope = ORIGINAL_NAMESPACE (scope);
while (scope && result->value != error_mark_node)
{
cxx_binding *binding =
cxx_scope_find_binding_for_name (NAMESPACE_LEVEL (scope), name);
seen = tree_cons (scope, NULL_TREE, seen);
if (binding)
result = ambiguous_decl (name, result, binding, flags);
if (!result->value && !result->type)
/* Consider using directives. */
for (usings = DECL_NAMESPACE_USING (scope); usings;
usings = TREE_CHAIN (usings))
/* If this was a real directive, and we have not seen it. */
if (!TREE_INDIRECT_USING (usings)
&& !purpose_member (TREE_PURPOSE (usings), seen))
todo = tree_cons (TREE_PURPOSE (usings), NULL_TREE, todo);
if (todo)
{
scope = TREE_PURPOSE (todo);
todo = TREE_CHAIN (todo);
}
else
scope = NULL_TREE; /* If there never was a todo list. */
}
POP_TIMEVAR_AND_RETURN (TV_NAME_LOOKUP, result->value != error_mark_node);
}
/* [namespace.memdef]/2 */
/* Set the context of a declaration to scope. Complain if we are not
outside scope. */
void
set_decl_namespace (tree decl, tree scope, bool friendp)
{
tree old;
/* Get rid of namespace aliases. */
scope = ORIGINAL_NAMESPACE (scope);
/* It is ok for friends to be qualified in parallel space. */
if (!friendp && !is_ancestor (current_namespace, scope))
error ("declaration of `%D' not in a namespace surrounding `%D'",
decl, scope);
DECL_CONTEXT (decl) = FROB_CONTEXT (scope);
if (scope != current_namespace)
{
/* See whether this has been declared in the namespace. */
old = namespace_binding (DECL_NAME (decl), scope);
if (!old)
/* No old declaration at all. */
goto complain;
/* A template can be explicitly specialized in any namespace. */
if (processing_explicit_instantiation)
return;
if (!is_overloaded_fn (decl))
/* Don't compare non-function decls with decls_match here,
since it can't check for the correct constness at this
point. pushdecl will find those errors later. */
return;
/* Since decl is a function, old should contain a function decl. */
if (!is_overloaded_fn (old))
goto complain;
if (processing_template_decl || processing_specialization)
/* We have not yet called push_template_decl to turn a
FUNCTION_DECL into a TEMPLATE_DECL, so the declarations
won't match. But, we'll check later, when we construct the
template. */
return;
if (is_overloaded_fn (old))
{
for (; old; old = OVL_NEXT (old))
if (decls_match (decl, OVL_CURRENT (old)))
return;
}
else
if (decls_match (decl, old))
return;
}
else
return;
complain:
error ("`%D' should have been declared inside `%D'",
decl, scope);
}
/* Compute the namespace where a declaration is defined. */
static tree
decl_namespace (tree decl)
{
timevar_push (TV_NAME_LOOKUP);
if (TYPE_P (decl))
decl = TYPE_STUB_DECL (decl);
while (DECL_CONTEXT (decl))
{
decl = DECL_CONTEXT (decl);
if (TREE_CODE (decl) == NAMESPACE_DECL)
POP_TIMEVAR_AND_RETURN (TV_NAME_LOOKUP, decl);
if (TYPE_P (decl))
decl = TYPE_STUB_DECL (decl);
my_friendly_assert (DECL_P (decl), 390);
}
POP_TIMEVAR_AND_RETURN (TV_NAME_LOOKUP, global_namespace);
}
/* Return the namespace where the current declaration is declared. */
tree
current_decl_namespace (void)
{
tree result;
/* If we have been pushed into a different namespace, use it. */
if (decl_namespace_list)
return TREE_PURPOSE (decl_namespace_list);
if (current_class_type)
result = decl_namespace (TYPE_STUB_DECL (current_class_type));
else if (current_function_decl)
result = decl_namespace (current_function_decl);
else
result = current_namespace;
return result;
}
/* Temporarily set the namespace for the current declaration. */
void
push_decl_namespace (tree decl)
{
if (TREE_CODE (decl) != NAMESPACE_DECL)
decl = decl_namespace (decl);
decl_namespace_list = tree_cons (ORIGINAL_NAMESPACE (decl),
NULL_TREE, decl_namespace_list);
}
void
pop_decl_namespace (void)
{
decl_namespace_list = TREE_CHAIN (decl_namespace_list);
}
/* Enter a class or namespace scope. */
void
push_scope (tree t)
{
if (TREE_CODE (t) == NAMESPACE_DECL)
push_decl_namespace (t);
else if CLASS_TYPE_P (t)
push_nested_class (t);
}
/* Leave scope pushed by push_scope. */
void
pop_scope (tree t)
{
if (TREE_CODE (t) == NAMESPACE_DECL)
pop_decl_namespace ();
else if CLASS_TYPE_P (t)
pop_nested_class ();
}
/* [basic.lookup.koenig] */
/* A nonzero return value in the functions below indicates an error. */
struct arg_lookup
{
tree name;
tree namespaces;
tree classes;
tree functions;
};
static bool arg_assoc (struct arg_lookup*, tree);
static bool arg_assoc_args (struct arg_lookup*, tree);
static bool arg_assoc_type (struct arg_lookup*, tree);
static bool add_function (struct arg_lookup *, tree);
static bool arg_assoc_namespace (struct arg_lookup *, tree);
static bool arg_assoc_class (struct arg_lookup *, tree);
static bool arg_assoc_template_arg (struct arg_lookup*, tree);
/* Add a function to the lookup structure.
Returns true on error. */
static bool
add_function (struct arg_lookup *k, tree fn)
{
/* We used to check here to see if the function was already in the list,
but that's O(n^2), which is just too expensive for function lookup.
Now we deal with the occasional duplicate in joust. In doing this, we
assume that the number of duplicates will be small compared to the
total number of functions being compared, which should usually be the
case. */
/* We must find only functions, or exactly one non-function. */
if (!k->functions)
k->functions = fn;
else if (fn == k->functions)
;
else if (is_overloaded_fn (k->functions) && is_overloaded_fn (fn))
k->functions = build_overload (fn, k->functions);
else
{
tree f1 = OVL_CURRENT (k->functions);
tree f2 = fn;
if (is_overloaded_fn (f1))
{
fn = f1; f1 = f2; f2 = fn;
}
cp_error_at ("`%D' is not a function,", f1);
cp_error_at (" conflict with `%D'", f2);
error (" in call to `%D'", k->name);
return true;
}
return false;
}
/* Add functions of a namespace to the lookup structure.
Returns true on error. */
static bool
arg_assoc_namespace (struct arg_lookup *k, tree scope)
{
tree value;
if (purpose_member (scope, k->namespaces))
return 0;
k->namespaces = tree_cons (scope, NULL_TREE, k->namespaces);
value = namespace_binding (k->name, scope);
if (!value)
return false;
for (; value; value = OVL_NEXT (value))
if (add_function (k, OVL_CURRENT (value)))
return true;
return false;
}
/* Adds everything associated with a template argument to the lookup
structure. Returns true on error. */
static bool
arg_assoc_template_arg (struct arg_lookup *k, tree arg)
{
/* [basic.lookup.koenig]
If T is a template-id, its associated namespaces and classes are
... the namespaces and classes associated with the types of the
template arguments provided for template type parameters
(excluding template template parameters); the namespaces in which
any template template arguments are defined; and the classes in
which any member templates used as template template arguments
are defined. [Note: non-type template arguments do not
contribute to the set of associated namespaces. ] */
/* Consider first template template arguments. */
if (TREE_CODE (arg) == TEMPLATE_TEMPLATE_PARM
|| TREE_CODE (arg) == UNBOUND_CLASS_TEMPLATE)
return false;
else if (TREE_CODE (arg) == TEMPLATE_DECL)
{
tree ctx = CP_DECL_CONTEXT (arg);
/* It's not a member template. */
if (TREE_CODE (ctx) == NAMESPACE_DECL)
return arg_assoc_namespace (k, ctx);
/* Otherwise, it must be member template. */
else
return arg_assoc_class (k, ctx);
}
/* It's not a template template argument, but it is a type template
argument. */
else if (TYPE_P (arg))
return arg_assoc_type (k, arg);
/* It's a non-type template argument. */
else
return false;
}
/* Adds everything associated with class to the lookup structure.
Returns true on error. */
static bool
arg_assoc_class (struct arg_lookup *k, tree type)
{
tree list, friends, context;
int i;
/* Backend build structures, such as __builtin_va_list, aren't
affected by all this. */
if (!CLASS_TYPE_P (type))
return false;
if (purpose_member (type, k->classes))
return false;
k->classes = tree_cons (type, NULL_TREE, k->classes);
context = decl_namespace (TYPE_MAIN_DECL (type));
if (arg_assoc_namespace (k, context))
return true;
/* Process baseclasses. */
for (i = 0; i < CLASSTYPE_N_BASECLASSES (type); i++)
if (arg_assoc_class (k, TYPE_BINFO_BASETYPE (type, i)))
return true;
/* Process friends. */
for (list = DECL_FRIENDLIST (TYPE_MAIN_DECL (type)); list;
list = TREE_CHAIN (list))
if (k->name == FRIEND_NAME (list))
for (friends = FRIEND_DECLS (list); friends;
friends = TREE_CHAIN (friends))
/* Only interested in global functions with potentially hidden
(i.e. unqualified) declarations. */
if (CP_DECL_CONTEXT (TREE_VALUE (friends)) == context)
if (add_function (k, TREE_VALUE (friends)))
return true;
/* Process template arguments. */
if (CLASSTYPE_TEMPLATE_INFO (type))
{
list = INNERMOST_TEMPLATE_ARGS (CLASSTYPE_TI_ARGS (type));
for (i = 0; i < TREE_VEC_LENGTH (list); ++i)
arg_assoc_template_arg (k, TREE_VEC_ELT (list, i));
}
return false;
}
/* Adds everything associated with a given type.
Returns 1 on error. */
static bool
arg_assoc_type (struct arg_lookup *k, tree type)
{
/* As we do not get the type of non-type dependent expressions
right, we can end up with such things without a type. */
if (!type)
return false;
if (TYPE_PTRMEM_P (type))
{
/* Pointer to member: associate class type and value type. */
if (arg_assoc_type (k, TYPE_PTRMEM_CLASS_TYPE (type)))
return true;
return arg_assoc_type (k, TYPE_PTRMEM_POINTED_TO_TYPE (type));
}
else switch (TREE_CODE (type))
{
case ERROR_MARK:
return false;
case VOID_TYPE:
case INTEGER_TYPE:
case REAL_TYPE:
case COMPLEX_TYPE:
case VECTOR_TYPE:
case CHAR_TYPE:
case BOOLEAN_TYPE:
return false;
case RECORD_TYPE:
if (TYPE_PTRMEMFUNC_P (type))
return arg_assoc_type (k, TYPE_PTRMEMFUNC_FN_TYPE (type));
return arg_assoc_class (k, type);
case POINTER_TYPE:
case REFERENCE_TYPE:
case ARRAY_TYPE:
return arg_assoc_type (k, TREE_TYPE (type));
case UNION_TYPE:
case ENUMERAL_TYPE:
return arg_assoc_namespace (k, decl_namespace (TYPE_MAIN_DECL (type)));
case METHOD_TYPE:
/* The basetype is referenced in the first arg type, so just
fall through. */
case FUNCTION_TYPE:
/* Associate the parameter types. */
if (arg_assoc_args (k, TYPE_ARG_TYPES (type)))
return true;
/* Associate the return type. */
return arg_assoc_type (k, TREE_TYPE (type));
case TEMPLATE_TYPE_PARM:
case BOUND_TEMPLATE_TEMPLATE_PARM:
return false;
case TYPENAME_TYPE:
return false;
case LANG_TYPE:
if (type == unknown_type_node)
return false;
/* else fall through */
default:
abort ();
}
return false;
}
/* Adds everything associated with arguments. Returns true on error. */
static bool
arg_assoc_args (struct arg_lookup *k, tree args)
{
for (; args; args = TREE_CHAIN (args))
if (arg_assoc (k, TREE_VALUE (args)))
return true;
return false;
}
/* Adds everything associated with a given tree_node. Returns 1 on error. */
static bool
arg_assoc (struct arg_lookup *k, tree n)
{
if (n == error_mark_node)
return false;
if (TYPE_P (n))
return arg_assoc_type (k, n);
if (! type_unknown_p (n))
return arg_assoc_type (k, TREE_TYPE (n));
if (TREE_CODE (n) == ADDR_EXPR)
n = TREE_OPERAND (n, 0);
if (TREE_CODE (n) == COMPONENT_REF)
n = TREE_OPERAND (n, 1);
if (TREE_CODE (n) == OFFSET_REF)
n = TREE_OPERAND (n, 1);
while (TREE_CODE (n) == TREE_LIST)
n = TREE_VALUE (n);
if (TREE_CODE (n) == BASELINK)
n = BASELINK_FUNCTIONS (n);
if (TREE_CODE (n) == FUNCTION_DECL)
return arg_assoc_type (k, TREE_TYPE (n));
if (TREE_CODE (n) == TEMPLATE_ID_EXPR)
{
/* [basic.lookup.koenig]
If T is a template-id, its associated namespaces and classes
are the namespace in which the template is defined; for
member templates, the member template's class... */
tree template = TREE_OPERAND (n, 0);
tree args = TREE_OPERAND (n, 1);
tree ctx;
int ix;
if (TREE_CODE (template) == COMPONENT_REF)
template = TREE_OPERAND (template, 1);
/* First, the template. There may actually be more than one if
this is an overloaded function template. But, in that case,
we only need the first; all the functions will be in the same
namespace. */
template = OVL_CURRENT (template);
ctx = CP_DECL_CONTEXT (template);
if (TREE_CODE (ctx) == NAMESPACE_DECL)
{
if (arg_assoc_namespace (k, ctx) == 1)
return true;
}
/* It must be a member template. */
else if (arg_assoc_class (k, ctx) == 1)
return true;
/* Now the arguments. */
for (ix = TREE_VEC_LENGTH (args); ix--;)
if (arg_assoc_template_arg (k, TREE_VEC_ELT (args, ix)) == 1)
return true;
}
else
{
my_friendly_assert (TREE_CODE (n) == OVERLOAD, 980715);
for (; n; n = OVL_CHAIN (n))
if (arg_assoc_type (k, TREE_TYPE (OVL_FUNCTION (n))))
return true;
}
return false;
}
/* Performs Koenig lookup depending on arguments, where fns
are the functions found in normal lookup. */
tree
lookup_arg_dependent (tree name, tree fns, tree args)
{
struct arg_lookup k;
tree fn = NULL_TREE;
timevar_push (TV_NAME_LOOKUP);
k.name = name;
k.functions = fns;
k.classes = NULL_TREE;
/* Note that we've already looked at some namespaces during normal
unqualified lookup, unless we found a decl in function scope. */
if (fns)
fn = OVL_CURRENT (fns);
if (fn && TREE_CODE (fn) == FUNCTION_DECL && DECL_LOCAL_FUNCTION_P (fn))
k.namespaces = NULL_TREE;
else
unqualified_namespace_lookup (name, 0, &k.namespaces);
arg_assoc_args (&k, args);
POP_TIMEVAR_AND_RETURN (TV_NAME_LOOKUP, k.functions);
}
/* Process a namespace-alias declaration. */
void
do_namespace_alias (tree alias, tree namespace)
{
if (TREE_CODE (namespace) != NAMESPACE_DECL)
{
/* The parser did not find it, so it's not there. */
error ("unknown namespace `%D'", namespace);
return;
}
namespace = ORIGINAL_NAMESPACE (namespace);
/* Build the alias. */
alias = build_lang_decl (NAMESPACE_DECL, alias, void_type_node);
DECL_NAMESPACE_ALIAS (alias) = namespace;
DECL_EXTERNAL (alias) = 1;
pushdecl (alias);
}
/* Check a non-member using-declaration. Return the name and scope
being used, and the USING_DECL, or NULL_TREE on failure. */
static tree
validate_nonmember_using_decl (tree decl, tree *scope, tree *name)
{
*scope = global_namespace;
*name = NULL_TREE;
if (TREE_CODE (decl) == TEMPLATE_ID_EXPR)
{
*name = TREE_OPERAND (decl, 0);
/* 7.3.3/5
A using-declaration shall not name a template-id. */
error ("a using-declaration cannot specify a template-id. Try `using %D'", *name);
return NULL_TREE;
}
if (TREE_CODE (decl) == NAMESPACE_DECL)
{
error ("namespace `%D' not allowed in using-declaration", decl);
return NULL_TREE;
}
if (TREE_CODE (decl) == SCOPE_REF)
{
/* It's a nested name with template parameter dependent scope.
This can only be using-declaration for class member. */
error ("`%T' is not a namespace", TREE_OPERAND (decl, 0));
return NULL_TREE;
}
if (is_overloaded_fn (decl))
decl = get_first_fn (decl);
my_friendly_assert (DECL_P (decl), 20020908);
if (TREE_CODE (decl) == CONST_DECL)
/* Enumeration constants to not have DECL_CONTEXT set. */
*scope = TYPE_CONTEXT (TREE_TYPE (decl));
else
*scope = DECL_CONTEXT (decl);
if (!*scope)
*scope = global_namespace;
/* [namespace.udecl]
A using-declaration for a class member shall be a
member-declaration. */
if (TYPE_P (*scope))
{
error ("`%T' is not a namespace", *scope);
return NULL_TREE;
}
*name = DECL_NAME (decl);
/* Make a USING_DECL. */
return push_using_decl (*scope, *name);
}
/* Process local and global using-declarations. */
static void
do_nonmember_using_decl (tree scope, tree name, tree oldval, tree oldtype,
tree *newval, tree *newtype)
{
cxx_binding decls;
*newval = *newtype = NULL_TREE;
cxx_binding_clear (&decls);
if (!qualified_lookup_using_namespace (name, scope, &decls, 0))
/* Lookup error */
return;
if (!decls.value && !decls.type)
{
error ("`%D' not declared", name);
return;
}
/* Check for using functions. */
if (decls.value && is_overloaded_fn (decls.value))
{
tree tmp, tmp1;
if (oldval && !is_overloaded_fn (oldval))
{
if (!DECL_IMPLICIT_TYPEDEF_P (oldval))
error ("`%D' is already declared in this scope", name);
oldval = NULL_TREE;
}
*newval = oldval;
for (tmp = decls.value; tmp; tmp = OVL_NEXT (tmp))
{
tree new_fn = OVL_CURRENT (tmp);
/* [namespace.udecl]
If a function declaration in namespace scope or block
scope has the same name and the same parameter types as a
function introduced by a using declaration the program is
ill-formed. */
for (tmp1 = oldval; tmp1; tmp1 = OVL_NEXT (tmp1))
{
tree old_fn = OVL_CURRENT (tmp1);
if (new_fn == old_fn)
/* The function already exists in the current namespace. */
break;
else if (OVL_USED (tmp1))
continue; /* this is a using decl */
else if (compparms (TYPE_ARG_TYPES (TREE_TYPE (new_fn)),
TYPE_ARG_TYPES (TREE_TYPE (old_fn))))
{
/* There was already a non-using declaration in
this scope with the same parameter types. If both
are the same extern "C" functions, that's ok. */
if (decls_match (new_fn, old_fn))
{
/* If the OLD_FN was a builtin, there is now a
real declaration. */
if (DECL_ANTICIPATED (old_fn))
DECL_ANTICIPATED (old_fn) = 0;
break;
}
else if (!DECL_ANTICIPATED (old_fn))
{
/* If the OLD_FN was really declared, the
declarations don't match. */
error ("`%D' is already declared in this scope", name);
break;
}
/* If the OLD_FN was not really there, just ignore
it and keep going. */
}
}
/* If we broke out of the loop, there's no reason to add
this function to the using declarations for this
scope. */
if (tmp1)
continue;
*newval = build_overload (OVL_CURRENT (tmp), *newval);
if (TREE_CODE (*newval) != OVERLOAD)
*newval = ovl_cons (*newval, NULL_TREE);
OVL_USED (*newval) = 1;
}
}
else
{
*newval = decls.value;
if (oldval && !decls_match (*newval, oldval))
error ("`%D' is already declared in this scope", name);
}
*newtype = decls.type;
if (oldtype && *newtype && !same_type_p (oldtype, *newtype))
{
error ("using declaration `%D' introduced ambiguous type `%T'",
name, oldtype);
return;
}
}
/* Process a using-declaration not appearing in class or local scope. */
void
do_toplevel_using_decl (tree decl)
{
tree scope, name;
tree oldval, oldtype, newval, newtype;
cxx_binding *binding;
decl = validate_nonmember_using_decl (decl, &scope, &name);
if (decl == NULL_TREE)
return;
binding = binding_for_name (NAMESPACE_LEVEL (current_namespace), name);
oldval = binding->value;
oldtype = binding->type;
do_nonmember_using_decl (scope, name, oldval, oldtype, &newval, &newtype);
/* Copy declarations found. */
if (newval)
binding->value = newval;
if (newtype)
binding->type = newtype;
return;
}
/* Process a using-declaration at function scope. */
void
do_local_using_decl (tree decl)
{
tree scope, name;
tree oldval, oldtype, newval, newtype;
decl = validate_nonmember_using_decl (decl, &scope, &name);
if (decl == NULL_TREE)
return;
if (building_stmt_tree ()
&& at_function_scope_p ())
add_decl_stmt (decl);
oldval = lookup_name_current_level (name);
oldtype = lookup_type_current_level (name);
do_nonmember_using_decl (scope, name, oldval, oldtype, &newval, &newtype);
if (newval)
{
if (is_overloaded_fn (newval))
{
tree fn, term;
/* We only need to push declarations for those functions
that were not already bound in the current level.
The old value might be NULL_TREE, it might be a single
function, or an OVERLOAD. */
if (oldval && TREE_CODE (oldval) == OVERLOAD)
term = OVL_FUNCTION (oldval);
else
term = oldval;
for (fn = newval; fn && OVL_CURRENT (fn) != term;
fn = OVL_NEXT (fn))
push_overloaded_decl (OVL_CURRENT (fn),
PUSH_LOCAL | PUSH_USING);
}
else
push_local_binding (name, newval, PUSH_USING);
}
if (newtype)
set_identifier_type_value (name, newtype);
}
tree
do_class_using_decl (tree decl)
{
tree name, value, scope, type;
if (TREE_CODE (decl) != SCOPE_REF
|| !TREE_OPERAND (decl, 0)
|| !TYPE_P (TREE_OPERAND (decl, 0)))
{
error ("using-declaration for non-member at class scope");
return NULL_TREE;
}
scope = TREE_OPERAND (decl, 0);
name = TREE_OPERAND (decl, 1);
if (TREE_CODE (name) == BIT_NOT_EXPR)
{
error ("using-declaration cannot name destructor");
return NULL_TREE;
}
if (TREE_CODE (name) == TYPE_DECL)
name = DECL_NAME (name);
else if (TREE_CODE (name) == TEMPLATE_DECL)
name = DECL_NAME (name);
else if (BASELINK_P (name))
{
tree fns = BASELINK_FUNCTIONS (name);
name = DECL_NAME (get_first_fn (fns));
}
my_friendly_assert (TREE_CODE (name) == IDENTIFIER_NODE, 980716);
/* Dependent using decls have a NULL type, non-dependent ones have a
void type. */
type = dependent_type_p (scope) ? NULL_TREE : void_type_node;
value = build_lang_decl (USING_DECL, name, type);
DECL_INITIAL (value) = scope;
return value;
}
/* Process a using-directive. */
void
do_using_directive (tree namespace)
{
if (building_stmt_tree ())
add_stmt (build_stmt (USING_STMT, namespace));
/* using namespace A::B::C; */
if (TREE_CODE (namespace) == SCOPE_REF)
namespace = TREE_OPERAND (namespace, 1);
if (TREE_CODE (namespace) == IDENTIFIER_NODE)
{
/* Lookup in lexer did not find a namespace. */
if (!processing_template_decl)
error ("namespace `%T' undeclared", namespace);
return;
}
if (TREE_CODE (namespace) != NAMESPACE_DECL)
{
if (!processing_template_decl)
error ("`%T' is not a namespace", namespace);
return;
}
namespace = ORIGINAL_NAMESPACE (namespace);
if (!toplevel_bindings_p ())
push_using_directive (namespace);
else
/* direct usage */
add_using_namespace (current_namespace, namespace, 0);
}
void void
check_default_args (tree x) check_default_args (tree x)
......
...@@ -32,6 +32,11 @@ Boston, MA 02111-1307, USA. */ ...@@ -32,6 +32,11 @@ Boston, MA 02111-1307, USA. */
static cxx_scope *innermost_nonclass_level (void); static cxx_scope *innermost_nonclass_level (void);
static tree select_decl (cxx_binding *, int); static tree select_decl (cxx_binding *, int);
static cxx_binding *binding_for_name (cxx_scope *, tree);
/* The :: namespace. */
tree global_namespace;
/* Compute the chain index of a binding_entry given the HASH value of its /* Compute the chain index of a binding_entry given the HASH value of its
...@@ -300,6 +305,9 @@ binding_table_foreach (binding_table table, bt_foreach_proc proc, void *data) ...@@ -300,6 +305,9 @@ binding_table_foreach (binding_table table, bt_foreach_proc proc, void *data)
static GTY((deletable (""))) cxx_binding *free_bindings; static GTY((deletable (""))) cxx_binding *free_bindings;
/* Zero out a cxx_binding pointed to by B. */
#define cxx_binding_clear(B) memset ((B), 0, sizeof (cxx_binding))
/* (GC)-allocate a binding object with VALUE and TYPE member initialized. */ /* (GC)-allocate a binding object with VALUE and TYPE member initialized. */
static cxx_binding * static cxx_binding *
...@@ -1118,6 +1126,57 @@ set_identifier_type_value (tree id, tree decl) ...@@ -1118,6 +1126,57 @@ set_identifier_type_value (tree id, tree decl)
set_identifier_type_value_with_scope (id, decl, current_binding_level); set_identifier_type_value_with_scope (id, decl, current_binding_level);
} }
/* Return the name for the constructor (or destructor) for the
specified class TYPE. When given a template, this routine doesn't
lose the specialization. */
tree
constructor_name_full (tree type)
{
type = TYPE_MAIN_VARIANT (type);
if (CLASS_TYPE_P (type) && TYPE_WAS_ANONYMOUS (type)
&& TYPE_HAS_CONSTRUCTOR (type))
return DECL_NAME (OVL_CURRENT (CLASSTYPE_CONSTRUCTORS (type)));
else
return TYPE_IDENTIFIER (type);
}
/* Return the name for the constructor (or destructor) for the
specified class. When given a template, return the plain
unspecialized name. */
tree
constructor_name (tree type)
{
tree name;
name = constructor_name_full (type);
if (IDENTIFIER_TEMPLATE (name))
name = IDENTIFIER_TEMPLATE (name);
return name;
}
/* Returns TRUE if NAME is the name for the constructor for TYPE. */
bool
constructor_name_p (tree name, tree type)
{
tree ctor_name;
if (!name)
return false;
if (TREE_CODE (name) != IDENTIFIER_NODE)
return false;
ctor_name = constructor_name_full (type);
if (name == ctor_name)
return true;
if (IDENTIFIER_TEMPLATE (ctor_name)
&& name == IDENTIFIER_TEMPLATE (ctor_name))
return true;
return false;
}
/* Return (from the stack of) the BINDING, if any, establihsed at SCOPE. */ /* Return (from the stack of) the BINDING, if any, establihsed at SCOPE. */
static inline cxx_binding * static inline cxx_binding *
...@@ -1134,7 +1193,7 @@ find_binding (cxx_scope *scope, cxx_binding *binding) ...@@ -1134,7 +1193,7 @@ find_binding (cxx_scope *scope, cxx_binding *binding)
/* Return the binding for NAME in SCOPE, if any. Otherwise, return NULL. */ /* Return the binding for NAME in SCOPE, if any. Otherwise, return NULL. */
cxx_binding * static inline cxx_binding *
cxx_scope_find_binding_for_name (cxx_scope *scope, tree name) cxx_scope_find_binding_for_name (cxx_scope *scope, tree name)
{ {
cxx_binding *b = IDENTIFIER_NAMESPACE_BINDINGS (name); cxx_binding *b = IDENTIFIER_NAMESPACE_BINDINGS (name);
...@@ -1151,7 +1210,7 @@ cxx_scope_find_binding_for_name (cxx_scope *scope, tree name) ...@@ -1151,7 +1210,7 @@ cxx_scope_find_binding_for_name (cxx_scope *scope, tree name)
/* Always returns a binding for name in scope. If no binding is /* Always returns a binding for name in scope. If no binding is
found, make a new one. */ found, make a new one. */
cxx_binding * static cxx_binding *
binding_for_name (cxx_scope *scope, tree name) binding_for_name (cxx_scope *scope, tree name)
{ {
cxx_binding *result; cxx_binding *result;
...@@ -1198,6 +1257,218 @@ pushdecl_with_scope (tree x, cxx_scope *level) ...@@ -1198,6 +1257,218 @@ pushdecl_with_scope (tree x, cxx_scope *level)
POP_TIMEVAR_AND_RETURN (TV_NAME_LOOKUP, x); POP_TIMEVAR_AND_RETURN (TV_NAME_LOOKUP, x);
} }
/* Check a non-member using-declaration. Return the name and scope
being used, and the USING_DECL, or NULL_TREE on failure. */
static tree
validate_nonmember_using_decl (tree decl, tree *scope, tree *name)
{
*scope = global_namespace;
*name = NULL_TREE;
if (TREE_CODE (decl) == TEMPLATE_ID_EXPR)
{
*name = TREE_OPERAND (decl, 0);
/* 7.3.3/5
A using-declaration shall not name a template-id. */
error ("a using-declaration cannot specify a template-id. Try `using %D'", *name);
return NULL_TREE;
}
if (TREE_CODE (decl) == NAMESPACE_DECL)
{
error ("namespace `%D' not allowed in using-declaration", decl);
return NULL_TREE;
}
if (TREE_CODE (decl) == SCOPE_REF)
{
/* It's a nested name with template parameter dependent scope.
This can only be using-declaration for class member. */
error ("`%T' is not a namespace", TREE_OPERAND (decl, 0));
return NULL_TREE;
}
if (is_overloaded_fn (decl))
decl = get_first_fn (decl);
my_friendly_assert (DECL_P (decl), 20020908);
if (TREE_CODE (decl) == CONST_DECL)
/* Enumeration constants to not have DECL_CONTEXT set. */
*scope = TYPE_CONTEXT (TREE_TYPE (decl));
else
*scope = DECL_CONTEXT (decl);
if (!*scope)
*scope = global_namespace;
/* [namespace.udecl]
A using-declaration for a class member shall be a
member-declaration. */
if (TYPE_P (*scope))
{
error ("`%T' is not a namespace", *scope);
return NULL_TREE;
}
*name = DECL_NAME (decl);
/* Make a USING_DECL. */
return push_using_decl (*scope, *name);
}
/* Process local and global using-declarations. */
static void
do_nonmember_using_decl (tree scope, tree name, tree oldval, tree oldtype,
tree *newval, tree *newtype)
{
cxx_binding decls;
*newval = *newtype = NULL_TREE;
cxx_binding_clear (&decls);
if (!qualified_lookup_using_namespace (name, scope, &decls, 0))
/* Lookup error */
return;
if (!decls.value && !decls.type)
{
error ("`%D' not declared", name);
return;
}
/* Check for using functions. */
if (decls.value && is_overloaded_fn (decls.value))
{
tree tmp, tmp1;
if (oldval && !is_overloaded_fn (oldval))
{
if (!DECL_IMPLICIT_TYPEDEF_P (oldval))
error ("`%D' is already declared in this scope", name);
oldval = NULL_TREE;
}
*newval = oldval;
for (tmp = decls.value; tmp; tmp = OVL_NEXT (tmp))
{
tree new_fn = OVL_CURRENT (tmp);
/* [namespace.udecl]
If a function declaration in namespace scope or block
scope has the same name and the same parameter types as a
function introduced by a using declaration the program is
ill-formed. */
for (tmp1 = oldval; tmp1; tmp1 = OVL_NEXT (tmp1))
{
tree old_fn = OVL_CURRENT (tmp1);
if (new_fn == old_fn)
/* The function already exists in the current namespace. */
break;
else if (OVL_USED (tmp1))
continue; /* this is a using decl */
else if (compparms (TYPE_ARG_TYPES (TREE_TYPE (new_fn)),
TYPE_ARG_TYPES (TREE_TYPE (old_fn))))
{
/* There was already a non-using declaration in
this scope with the same parameter types. If both
are the same extern "C" functions, that's ok. */
if (decls_match (new_fn, old_fn))
{
/* If the OLD_FN was a builtin, there is now a
real declaration. */
if (DECL_ANTICIPATED (old_fn))
DECL_ANTICIPATED (old_fn) = 0;
break;
}
else if (!DECL_ANTICIPATED (old_fn))
{
/* If the OLD_FN was really declared, the
declarations don't match. */
error ("`%D' is already declared in this scope", name);
break;
}
/* If the OLD_FN was not really there, just ignore
it and keep going. */
}
}
/* If we broke out of the loop, there's no reason to add
this function to the using declarations for this
scope. */
if (tmp1)
continue;
*newval = build_overload (OVL_CURRENT (tmp), *newval);
if (TREE_CODE (*newval) != OVERLOAD)
*newval = ovl_cons (*newval, NULL_TREE);
OVL_USED (*newval) = 1;
}
}
else
{
*newval = decls.value;
if (oldval && !decls_match (*newval, oldval))
error ("`%D' is already declared in this scope", name);
}
*newtype = decls.type;
if (oldtype && *newtype && !same_type_p (oldtype, *newtype))
{
error ("using declaration `%D' introduced ambiguous type `%T'",
name, oldtype);
return;
}
}
/* Process a using-declaration at function scope. */
void
do_local_using_decl (tree decl)
{
tree scope, name;
tree oldval, oldtype, newval, newtype;
decl = validate_nonmember_using_decl (decl, &scope, &name);
if (decl == NULL_TREE)
return;
if (building_stmt_tree ()
&& at_function_scope_p ())
add_decl_stmt (decl);
oldval = lookup_name_current_level (name);
oldtype = lookup_type_current_level (name);
do_nonmember_using_decl (scope, name, oldval, oldtype, &newval, &newtype);
if (newval)
{
if (is_overloaded_fn (newval))
{
tree fn, term;
/* We only need to push declarations for those functions
that were not already bound in the current level.
The old value might be NULL_TREE, it might be a single
function, or an OVERLOAD. */
if (oldval && TREE_CODE (oldval) == OVERLOAD)
term = OVL_FUNCTION (oldval);
else
term = oldval;
for (fn = newval; fn && OVL_CURRENT (fn) != term;
fn = OVL_NEXT (fn))
push_overloaded_decl (OVL_CURRENT (fn),
PUSH_LOCAL | PUSH_USING);
}
else
push_local_binding (name, newval, PUSH_USING);
}
if (newtype)
set_identifier_type_value (name, newtype);
}
/* Return the type that should be used when TYPE's name is preceded /* Return the type that should be used when TYPE's name is preceded
by a tag such as 'struct' or 'union', or null if the name cannot by a tag such as 'struct' or 'union', or null if the name cannot
be used in this way. be used in this way.
...@@ -1379,6 +1650,60 @@ lookup_tag_reverse (tree type, tree name) ...@@ -1379,6 +1650,60 @@ lookup_tag_reverse (tree type, tree name)
POP_TIMEVAR_AND_RETURN (TV_NAME_LOOKUP, NULL_TREE); POP_TIMEVAR_AND_RETURN (TV_NAME_LOOKUP, NULL_TREE);
} }
/* Returns true if ROOT (a namespace, class, or function) encloses
CHILD. CHILD may be either a class type or a namespace. */
bool
is_ancestor (tree root, tree child)
{
my_friendly_assert ((TREE_CODE (root) == NAMESPACE_DECL
|| TREE_CODE (root) == FUNCTION_DECL
|| CLASS_TYPE_P (root)), 20030307);
my_friendly_assert ((TREE_CODE (child) == NAMESPACE_DECL
|| CLASS_TYPE_P (child)),
20030307);
/* The global namespace encloses everything. */
if (root == global_namespace)
return true;
while (true)
{
/* If we've run out of scopes, stop. */
if (!child)
return false;
/* If we've reached the ROOT, it encloses CHILD. */
if (root == child)
return true;
/* Go out one level. */
if (TYPE_P (child))
child = TYPE_NAME (child);
child = DECL_CONTEXT (child);
}
}
/* Enter a class or namespace scope. */
void
push_scope (tree t)
{
if (TREE_CODE (t) == NAMESPACE_DECL)
push_decl_namespace (t);
else if CLASS_TYPE_P (t)
push_nested_class (t);
}
/* Leave scope pushed by push_scope. */
void
pop_scope (tree t)
{
if (TREE_CODE (t) == NAMESPACE_DECL)
pop_decl_namespace ();
else if CLASS_TYPE_P (t)
pop_nested_class ();
}
/* Do a pushlevel for class declarations. */ /* Do a pushlevel for class declarations. */
void void
...@@ -1671,6 +1996,45 @@ push_class_level_binding (tree name, tree x) ...@@ -1671,6 +1996,45 @@ push_class_level_binding (tree name, tree x)
POP_TIMEVAR_AND_RETURN (TV_NAME_LOOKUP, false); POP_TIMEVAR_AND_RETURN (TV_NAME_LOOKUP, false);
} }
tree
do_class_using_decl (tree decl)
{
tree name, value, scope, type;
if (TREE_CODE (decl) != SCOPE_REF
|| !TREE_OPERAND (decl, 0)
|| !TYPE_P (TREE_OPERAND (decl, 0)))
{
error ("using-declaration for non-member at class scope");
return NULL_TREE;
}
scope = TREE_OPERAND (decl, 0);
name = TREE_OPERAND (decl, 1);
if (TREE_CODE (name) == BIT_NOT_EXPR)
{
error ("using-declaration cannot name destructor");
return NULL_TREE;
}
if (TREE_CODE (name) == TYPE_DECL)
name = DECL_NAME (name);
else if (TREE_CODE (name) == TEMPLATE_DECL)
name = DECL_NAME (name);
else if (BASELINK_P (name))
{
tree fns = BASELINK_FUNCTIONS (name);
name = DECL_NAME (get_first_fn (fns));
}
my_friendly_assert (TREE_CODE (name) == IDENTIFIER_NODE, 980716);
/* Dependent using decls have a NULL type, non-dependent ones have a
void type. */
type = dependent_type_p (scope) ? NULL_TREE : void_type_node;
value = build_lang_decl (USING_DECL, name, type);
DECL_INITIAL (value) = scope;
return value;
}
void void
set_class_shadows (tree shadows) set_class_shadows (tree shadows)
{ {
...@@ -1710,6 +2074,103 @@ set_namespace_binding (tree name, tree scope, tree val) ...@@ -1710,6 +2074,103 @@ set_namespace_binding (tree name, tree scope, tree val)
timevar_pop (TV_NAME_LOOKUP); timevar_pop (TV_NAME_LOOKUP);
} }
/* Compute the namespace where a declaration is defined. */
static tree
decl_namespace (tree decl)
{
timevar_push (TV_NAME_LOOKUP);
if (TYPE_P (decl))
decl = TYPE_STUB_DECL (decl);
while (DECL_CONTEXT (decl))
{
decl = DECL_CONTEXT (decl);
if (TREE_CODE (decl) == NAMESPACE_DECL)
POP_TIMEVAR_AND_RETURN (TV_NAME_LOOKUP, decl);
if (TYPE_P (decl))
decl = TYPE_STUB_DECL (decl);
my_friendly_assert (DECL_P (decl), 390);
}
POP_TIMEVAR_AND_RETURN (TV_NAME_LOOKUP, global_namespace);
}
/* Set the context of a declaration to scope. Complain if we are not
outside scope. */
void
set_decl_namespace (tree decl, tree scope, bool friendp)
{
tree old;
/* Get rid of namespace aliases. */
scope = ORIGINAL_NAMESPACE (scope);
/* It is ok for friends to be qualified in parallel space. */
if (!friendp && !is_ancestor (current_namespace, scope))
error ("declaration of `%D' not in a namespace surrounding `%D'",
decl, scope);
DECL_CONTEXT (decl) = FROB_CONTEXT (scope);
if (scope != current_namespace)
{
/* See whether this has been declared in the namespace. */
old = namespace_binding (DECL_NAME (decl), scope);
if (!old)
/* No old declaration at all. */
goto complain;
/* A template can be explicitly specialized in any namespace. */
if (processing_explicit_instantiation)
return;
if (!is_overloaded_fn (decl))
/* Don't compare non-function decls with decls_match here,
since it can't check for the correct constness at this
point. pushdecl will find those errors later. */
return;
/* Since decl is a function, old should contain a function decl. */
if (!is_overloaded_fn (old))
goto complain;
if (processing_template_decl || processing_specialization)
/* We have not yet called push_template_decl to turn a
FUNCTION_DECL into a TEMPLATE_DECL, so the declarations
won't match. But, we'll check later, when we construct the
template. */
return;
if (is_overloaded_fn (old))
{
for (; old; old = OVL_NEXT (old))
if (decls_match (decl, OVL_CURRENT (old)))
return;
}
else
if (decls_match (decl, old))
return;
}
else
return;
complain:
error ("`%D' should have been declared inside `%D'",
decl, scope);
}
/* Return the namespace where the current declaration is declared. */
tree
current_decl_namespace (void)
{
tree result;
/* If we have been pushed into a different namespace, use it. */
if (decl_namespace_list)
return TREE_PURPOSE (decl_namespace_list);
if (current_class_type)
result = decl_namespace (TYPE_STUB_DECL (current_class_type));
else if (current_function_decl)
result = decl_namespace (current_function_decl);
else
result = current_namespace;
return result;
}
/* Push into the scope of the NAME namespace. If NAME is NULL_TREE, then we /* Push into the scope of the NAME namespace. If NAME is NULL_TREE, then we
select a name that is unique to this compilation unit. */ select a name that is unique to this compilation unit. */
...@@ -1819,6 +2280,59 @@ pop_nested_namespace (tree ns) ...@@ -1819,6 +2280,59 @@ pop_nested_namespace (tree ns)
timevar_pop (TV_NAME_LOOKUP); timevar_pop (TV_NAME_LOOKUP);
} }
/* Temporarily set the namespace for the current declaration. */
void
push_decl_namespace (tree decl)
{
if (TREE_CODE (decl) != NAMESPACE_DECL)
decl = decl_namespace (decl);
decl_namespace_list = tree_cons (ORIGINAL_NAMESPACE (decl),
NULL_TREE, decl_namespace_list);
}
/* [namespace.memdef]/2 */
void
pop_decl_namespace (void)
{
decl_namespace_list = TREE_CHAIN (decl_namespace_list);
}
/* Return the namespace that is the common ancestor
of two given namespaces. */
tree
namespace_ancestor (tree ns1, tree ns2)
{
timevar_push (TV_NAME_LOOKUP);
if (is_ancestor (ns1, ns2))
POP_TIMEVAR_AND_RETURN (TV_NAME_LOOKUP, ns1);
POP_TIMEVAR_AND_RETURN (TV_NAME_LOOKUP,
namespace_ancestor (CP_DECL_CONTEXT (ns1), ns2));
}
/* Process a namespace-alias declaration. */
void
do_namespace_alias (tree alias, tree namespace)
{
if (TREE_CODE (namespace) != NAMESPACE_DECL)
{
/* The parser did not find it, so it's not there. */
error ("unknown namespace `%D'", namespace);
return;
}
namespace = ORIGINAL_NAMESPACE (namespace);
/* Build the alias. */
alias = build_lang_decl (NAMESPACE_DECL, alias, void_type_node);
DECL_NAMESPACE_ALIAS (alias) = namespace;
DECL_EXTERNAL (alias) = 1;
pushdecl (alias);
}
/* Like pushdecl, only it places X in the current namespace, /* Like pushdecl, only it places X in the current namespace,
if appropriate. */ if appropriate. */
...@@ -1865,6 +2379,237 @@ pushdecl_namespace_level (tree x) ...@@ -1865,6 +2379,237 @@ pushdecl_namespace_level (tree x)
POP_TIMEVAR_AND_RETURN (TV_NAME_LOOKUP, t); POP_TIMEVAR_AND_RETURN (TV_NAME_LOOKUP, t);
} }
/* Insert USED into the using list of USER. Set INDIRECT_flag if this
directive is not directly from the source. Also find the common
ancestor and let our users know about the new namespace */
static void
add_using_namespace (tree user, tree used, bool indirect)
{
tree t;
timevar_push (TV_NAME_LOOKUP);
/* Using oneself is a no-op. */
if (user == used)
{
timevar_pop (TV_NAME_LOOKUP);
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. */
t = purpose_member (used, DECL_NAMESPACE_USING (user));
if (t != NULL_TREE)
{
if (!indirect)
/* Promote to direct usage. */
TREE_INDIRECT_USING (t) = 0;
timevar_pop (TV_NAME_LOOKUP);
return;
}
/* Add used to the user's using list. */
DECL_NAMESPACE_USING (user)
= tree_cons (used, namespace_ancestor (user, used),
DECL_NAMESPACE_USING (user));
TREE_INDIRECT_USING (DECL_NAMESPACE_USING (user)) = indirect;
/* Add user to the used's users list. */
DECL_NAMESPACE_USERS (used)
= tree_cons (user, 0, DECL_NAMESPACE_USERS (used));
/* Recursively add all namespaces used. */
for (t = DECL_NAMESPACE_USING (used); t; t = TREE_CHAIN (t))
/* indirect usage */
add_using_namespace (user, TREE_PURPOSE (t), 1);
/* Tell everyone using us about the new used namespaces. */
for (t = DECL_NAMESPACE_USERS (user); t; t = TREE_CHAIN (t))
add_using_namespace (TREE_PURPOSE (t), used, 1);
timevar_pop (TV_NAME_LOOKUP);
}
/* Process a using-declaration not appearing in class or local scope. */
void
do_toplevel_using_decl (tree decl)
{
tree scope, name;
tree oldval, oldtype, newval, newtype;
cxx_binding *binding;
decl = validate_nonmember_using_decl (decl, &scope, &name);
if (decl == NULL_TREE)
return;
binding = binding_for_name (NAMESPACE_LEVEL (current_namespace), name);
oldval = binding->value;
oldtype = binding->type;
do_nonmember_using_decl (scope, name, oldval, oldtype, &newval, &newtype);
/* Copy declarations found. */
if (newval)
binding->value = newval;
if (newtype)
binding->type = newtype;
return;
}
/* Process a using-directive. */
void
do_using_directive (tree namespace)
{
if (building_stmt_tree ())
add_stmt (build_stmt (USING_STMT, namespace));
/* using namespace A::B::C; */
if (TREE_CODE (namespace) == SCOPE_REF)
namespace = TREE_OPERAND (namespace, 1);
if (TREE_CODE (namespace) == IDENTIFIER_NODE)
{
/* Lookup in lexer did not find a namespace. */
if (!processing_template_decl)
error ("namespace `%T' undeclared", namespace);
return;
}
if (TREE_CODE (namespace) != NAMESPACE_DECL)
{
if (!processing_template_decl)
error ("`%T' is not a namespace", namespace);
return;
}
namespace = ORIGINAL_NAMESPACE (namespace);
if (!toplevel_bindings_p ())
push_using_directive (namespace);
else
/* direct usage */
add_using_namespace (current_namespace, namespace, 0);
}
/* Combines two sets of overloaded functions into an OVERLOAD chain, removing
duplicates. The first list becomes the tail of the result.
The algorithm is O(n^2). We could get this down to O(n log n) by
doing a sort on the addresses of the functions, if that becomes
necessary. */
static tree
merge_functions (tree s1, tree s2)
{
for (; s2; s2 = OVL_NEXT (s2))
{
tree fn2 = OVL_CURRENT (s2);
tree fns1;
for (fns1 = s1; fns1; fns1 = OVL_NEXT (fns1))
{
tree fn1 = OVL_CURRENT (fns1);
/* If the function from S2 is already in S1, there is no
need to add it again. For `extern "C"' functions, we
might have two FUNCTION_DECLs for the same function, in
different namespaces; again, we only need one of them. */
if (fn1 == fn2
|| (DECL_EXTERN_C_P (fn1) && DECL_EXTERN_C_P (fn2)
&& DECL_NAME (fn1) == DECL_NAME (fn2)))
break;
}
/* If we exhausted all of the functions in S1, FN2 is new. */
if (!fns1)
s1 = build_overload (fn2, s1);
}
return s1;
}
/* This should return an error not all definitions define functions.
It is not an error if we find two functions with exactly the
same signature, only if these are selected in overload resolution.
old is the current set of bindings, new the freshly-found binding.
XXX Do we want to give *all* candidates in case of ambiguity?
XXX In what way should I treat extern declarations?
XXX I don't want to repeat the entire duplicate_decls here */
static cxx_binding *
ambiguous_decl (tree name, cxx_binding *old, cxx_binding *new, int flags)
{
tree val, type;
my_friendly_assert (old != NULL, 393);
/* Copy the value. */
val = new->value;
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)
&& !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;
case FUNCTION_DECL:
/* Ignore built-in functions that are still anticipated. */
if (LOOKUP_QUALIFIERS_ONLY (flags) || DECL_ANTICIPATED (val))
val = NULL_TREE;
break;
default:
if (LOOKUP_QUALIFIERS_ONLY (flags))
val = NULL_TREE;
}
if (!old->value)
old->value = val;
else if (val && val != old->value)
{
if (is_overloaded_fn (old->value) && is_overloaded_fn (val))
old->value = merge_functions (old->value, val);
else
{
/* Some declarations are functions, some are not. */
if (flags & LOOKUP_COMPLAIN)
{
/* If we've already given this error for this lookup,
old->value is error_mark_node, so let's not
repeat ourselves. */
if (old->value != error_mark_node)
{
error ("use of `%D' is ambiguous", name);
cp_error_at (" first declared as `%#D' here",
old->value);
}
cp_error_at (" also declared as `%#D' here", val);
}
old->value = error_mark_node;
}
}
/* ... and copy the type. */
type = new->type;
if (LOOKUP_NAMESPACES_ONLY (flags))
type = NULL_TREE;
if (!old->type)
old->type = type;
else if (type && old->type != type)
{
if (flags & LOOKUP_COMPLAIN)
{
error ("`%D' denotes an ambiguous type",name);
error ("%J first type here", TYPE_MAIN_DECL (old->type));
error ("%J other type here", TYPE_MAIN_DECL (type));
}
}
return old;
}
/* Return the declarations that are members of the namespace NS. */ /* Return the declarations that are members of the namespace NS. */
tree tree
...@@ -2120,6 +2865,79 @@ lookup_qualified_name (tree scope, tree name, bool is_type_p, bool complain) ...@@ -2120,6 +2865,79 @@ lookup_qualified_name (tree scope, tree name, bool is_type_p, bool complain)
return error_mark_node; return error_mark_node;
} }
/* Subroutine of unualified_namespace_lookup:
Add the bindings of NAME in used namespaces to VAL.
We are currently looking for names in namespace SCOPE, so we
look through USINGS for using-directives of namespaces
which have SCOPE as a common ancestor with the current scope.
Returns false on errors. */
bool
lookup_using_namespace (tree name, cxx_binding *val, tree usings, tree scope,
int flags, tree *spacesp)
{
tree iter;
timevar_push (TV_NAME_LOOKUP);
/* Iterate over all used namespaces in current, searching for using
directives of scope. */
for (iter = usings; iter; iter = TREE_CHAIN (iter))
if (TREE_VALUE (iter) == scope)
{
tree used = ORIGINAL_NAMESPACE (TREE_PURPOSE (iter));
cxx_binding *val1 =
cxx_scope_find_binding_for_name (NAMESPACE_LEVEL (used), name);
if (spacesp)
*spacesp = tree_cons (used, NULL_TREE, *spacesp);
/* Resolve ambiguities. */
if (val1)
val = ambiguous_decl (name, val, val1, flags);
}
POP_TIMEVAR_AND_RETURN (TV_NAME_LOOKUP, val->value != error_mark_node);
}
/* [namespace.qual]
Accepts the NAME to lookup and its qualifying SCOPE.
Returns the name/type pair found into the cxx_binding *RESULT,
or false on error. */
bool
qualified_lookup_using_namespace (tree name, tree scope, cxx_binding *result,
int flags)
{
/* Maintain a list of namespaces visited... */
tree seen = NULL_TREE;
/* ... and a list of namespace yet to see. */
tree todo = NULL_TREE;
tree usings;
timevar_push (TV_NAME_LOOKUP);
/* Look through namespace aliases. */
scope = ORIGINAL_NAMESPACE (scope);
while (scope && result->value != error_mark_node)
{
cxx_binding *binding =
cxx_scope_find_binding_for_name (NAMESPACE_LEVEL (scope), name);
seen = tree_cons (scope, NULL_TREE, seen);
if (binding)
result = ambiguous_decl (name, result, binding, flags);
if (!result->value && !result->type)
/* Consider using directives. */
for (usings = DECL_NAMESPACE_USING (scope); usings;
usings = TREE_CHAIN (usings))
/* If this was a real directive, and we have not seen it. */
if (!TREE_INDIRECT_USING (usings)
&& !purpose_member (TREE_PURPOSE (usings), seen))
todo = tree_cons (TREE_PURPOSE (usings), NULL_TREE, todo);
if (todo)
{
scope = TREE_PURPOSE (todo);
todo = TREE_CHAIN (todo);
}
else
scope = NULL_TREE; /* If there never was a todo list. */
}
POP_TIMEVAR_AND_RETURN (TV_NAME_LOOKUP, result->value != error_mark_node);
}
/* Look up NAME in the current binding level and its superiors in the /* Look up NAME in the current binding level and its superiors in the
namespace of variables, functions and typedefs. Return a ..._DECL namespace of variables, functions and typedefs. Return a ..._DECL
node of some kind representing its definition if there is only one node of some kind representing its definition if there is only one
...@@ -2305,6 +3123,355 @@ lookup_type_current_level (tree name) ...@@ -2305,6 +3123,355 @@ lookup_type_current_level (tree name)
POP_TIMEVAR_AND_RETURN (TV_NAME_LOOKUP, t); POP_TIMEVAR_AND_RETURN (TV_NAME_LOOKUP, t);
} }
/* [basic.lookup.koenig] */
/* A nonzero return value in the functions below indicates an error. */
struct arg_lookup
{
tree name;
tree namespaces;
tree classes;
tree functions;
};
static bool arg_assoc (struct arg_lookup*, tree);
static bool arg_assoc_args (struct arg_lookup*, tree);
static bool arg_assoc_type (struct arg_lookup*, tree);
static bool add_function (struct arg_lookup *, tree);
static bool arg_assoc_namespace (struct arg_lookup *, tree);
static bool arg_assoc_class (struct arg_lookup *, tree);
static bool arg_assoc_template_arg (struct arg_lookup*, tree);
/* Add a function to the lookup structure.
Returns true on error. */
static bool
add_function (struct arg_lookup *k, tree fn)
{
/* We used to check here to see if the function was already in the list,
but that's O(n^2), which is just too expensive for function lookup.
Now we deal with the occasional duplicate in joust. In doing this, we
assume that the number of duplicates will be small compared to the
total number of functions being compared, which should usually be the
case. */
/* We must find only functions, or exactly one non-function. */
if (!k->functions)
k->functions = fn;
else if (fn == k->functions)
;
else if (is_overloaded_fn (k->functions) && is_overloaded_fn (fn))
k->functions = build_overload (fn, k->functions);
else
{
tree f1 = OVL_CURRENT (k->functions);
tree f2 = fn;
if (is_overloaded_fn (f1))
{
fn = f1; f1 = f2; f2 = fn;
}
cp_error_at ("`%D' is not a function,", f1);
cp_error_at (" conflict with `%D'", f2);
error (" in call to `%D'", k->name);
return true;
}
return false;
}
/* Add functions of a namespace to the lookup structure.
Returns true on error. */
static bool
arg_assoc_namespace (struct arg_lookup *k, tree scope)
{
tree value;
if (purpose_member (scope, k->namespaces))
return 0;
k->namespaces = tree_cons (scope, NULL_TREE, k->namespaces);
value = namespace_binding (k->name, scope);
if (!value)
return false;
for (; value; value = OVL_NEXT (value))
if (add_function (k, OVL_CURRENT (value)))
return true;
return false;
}
/* Adds everything associated with a template argument to the lookup
structure. Returns true on error. */
static bool
arg_assoc_template_arg (struct arg_lookup *k, tree arg)
{
/* [basic.lookup.koenig]
If T is a template-id, its associated namespaces and classes are
... the namespaces and classes associated with the types of the
template arguments provided for template type parameters
(excluding template template parameters); the namespaces in which
any template template arguments are defined; and the classes in
which any member templates used as template template arguments
are defined. [Note: non-type template arguments do not
contribute to the set of associated namespaces. ] */
/* Consider first template template arguments. */
if (TREE_CODE (arg) == TEMPLATE_TEMPLATE_PARM
|| TREE_CODE (arg) == UNBOUND_CLASS_TEMPLATE)
return false;
else if (TREE_CODE (arg) == TEMPLATE_DECL)
{
tree ctx = CP_DECL_CONTEXT (arg);
/* It's not a member template. */
if (TREE_CODE (ctx) == NAMESPACE_DECL)
return arg_assoc_namespace (k, ctx);
/* Otherwise, it must be member template. */
else
return arg_assoc_class (k, ctx);
}
/* It's not a template template argument, but it is a type template
argument. */
else if (TYPE_P (arg))
return arg_assoc_type (k, arg);
/* It's a non-type template argument. */
else
return false;
}
/* Adds everything associated with class to the lookup structure.
Returns true on error. */
static bool
arg_assoc_class (struct arg_lookup *k, tree type)
{
tree list, friends, context;
int i;
/* Backend build structures, such as __builtin_va_list, aren't
affected by all this. */
if (!CLASS_TYPE_P (type))
return false;
if (purpose_member (type, k->classes))
return false;
k->classes = tree_cons (type, NULL_TREE, k->classes);
context = decl_namespace (TYPE_MAIN_DECL (type));
if (arg_assoc_namespace (k, context))
return true;
/* Process baseclasses. */
for (i = 0; i < CLASSTYPE_N_BASECLASSES (type); i++)
if (arg_assoc_class (k, TYPE_BINFO_BASETYPE (type, i)))
return true;
/* Process friends. */
for (list = DECL_FRIENDLIST (TYPE_MAIN_DECL (type)); list;
list = TREE_CHAIN (list))
if (k->name == FRIEND_NAME (list))
for (friends = FRIEND_DECLS (list); friends;
friends = TREE_CHAIN (friends))
/* Only interested in global functions with potentially hidden
(i.e. unqualified) declarations. */
if (CP_DECL_CONTEXT (TREE_VALUE (friends)) == context)
if (add_function (k, TREE_VALUE (friends)))
return true;
/* Process template arguments. */
if (CLASSTYPE_TEMPLATE_INFO (type))
{
list = INNERMOST_TEMPLATE_ARGS (CLASSTYPE_TI_ARGS (type));
for (i = 0; i < TREE_VEC_LENGTH (list); ++i)
arg_assoc_template_arg (k, TREE_VEC_ELT (list, i));
}
return false;
}
/* Adds everything associated with a given type.
Returns 1 on error. */
static bool
arg_assoc_type (struct arg_lookup *k, tree type)
{
/* As we do not get the type of non-type dependent expressions
right, we can end up with such things without a type. */
if (!type)
return false;
if (TYPE_PTRMEM_P (type))
{
/* Pointer to member: associate class type and value type. */
if (arg_assoc_type (k, TYPE_PTRMEM_CLASS_TYPE (type)))
return true;
return arg_assoc_type (k, TYPE_PTRMEM_POINTED_TO_TYPE (type));
}
else switch (TREE_CODE (type))
{
case ERROR_MARK:
return false;
case VOID_TYPE:
case INTEGER_TYPE:
case REAL_TYPE:
case COMPLEX_TYPE:
case VECTOR_TYPE:
case CHAR_TYPE:
case BOOLEAN_TYPE:
return false;
case RECORD_TYPE:
if (TYPE_PTRMEMFUNC_P (type))
return arg_assoc_type (k, TYPE_PTRMEMFUNC_FN_TYPE (type));
return arg_assoc_class (k, type);
case POINTER_TYPE:
case REFERENCE_TYPE:
case ARRAY_TYPE:
return arg_assoc_type (k, TREE_TYPE (type));
case UNION_TYPE:
case ENUMERAL_TYPE:
return arg_assoc_namespace (k, decl_namespace (TYPE_MAIN_DECL (type)));
case METHOD_TYPE:
/* The basetype is referenced in the first arg type, so just
fall through. */
case FUNCTION_TYPE:
/* Associate the parameter types. */
if (arg_assoc_args (k, TYPE_ARG_TYPES (type)))
return true;
/* Associate the return type. */
return arg_assoc_type (k, TREE_TYPE (type));
case TEMPLATE_TYPE_PARM:
case BOUND_TEMPLATE_TEMPLATE_PARM:
return false;
case TYPENAME_TYPE:
return false;
case LANG_TYPE:
if (type == unknown_type_node)
return false;
/* else fall through */
default:
abort ();
}
return false;
}
/* Adds everything associated with arguments. Returns true on error. */
static bool
arg_assoc_args (struct arg_lookup *k, tree args)
{
for (; args; args = TREE_CHAIN (args))
if (arg_assoc (k, TREE_VALUE (args)))
return true;
return false;
}
/* Adds everything associated with a given tree_node. Returns 1 on error. */
static bool
arg_assoc (struct arg_lookup *k, tree n)
{
if (n == error_mark_node)
return false;
if (TYPE_P (n))
return arg_assoc_type (k, n);
if (! type_unknown_p (n))
return arg_assoc_type (k, TREE_TYPE (n));
if (TREE_CODE (n) == ADDR_EXPR)
n = TREE_OPERAND (n, 0);
if (TREE_CODE (n) == COMPONENT_REF)
n = TREE_OPERAND (n, 1);
if (TREE_CODE (n) == OFFSET_REF)
n = TREE_OPERAND (n, 1);
while (TREE_CODE (n) == TREE_LIST)
n = TREE_VALUE (n);
if (TREE_CODE (n) == BASELINK)
n = BASELINK_FUNCTIONS (n);
if (TREE_CODE (n) == FUNCTION_DECL)
return arg_assoc_type (k, TREE_TYPE (n));
if (TREE_CODE (n) == TEMPLATE_ID_EXPR)
{
/* [basic.lookup.koenig]
If T is a template-id, its associated namespaces and classes
are the namespace in which the template is defined; for
member templates, the member template's class... */
tree template = TREE_OPERAND (n, 0);
tree args = TREE_OPERAND (n, 1);
tree ctx;
int ix;
if (TREE_CODE (template) == COMPONENT_REF)
template = TREE_OPERAND (template, 1);
/* First, the template. There may actually be more than one if
this is an overloaded function template. But, in that case,
we only need the first; all the functions will be in the same
namespace. */
template = OVL_CURRENT (template);
ctx = CP_DECL_CONTEXT (template);
if (TREE_CODE (ctx) == NAMESPACE_DECL)
{
if (arg_assoc_namespace (k, ctx) == 1)
return true;
}
/* It must be a member template. */
else if (arg_assoc_class (k, ctx) == 1)
return true;
/* Now the arguments. */
for (ix = TREE_VEC_LENGTH (args); ix--;)
if (arg_assoc_template_arg (k, TREE_VEC_ELT (args, ix)) == 1)
return true;
}
else
{
my_friendly_assert (TREE_CODE (n) == OVERLOAD, 980715);
for (; n; n = OVL_CHAIN (n))
if (arg_assoc_type (k, TREE_TYPE (OVL_FUNCTION (n))))
return true;
}
return false;
}
/* Performs Koenig lookup depending on arguments, where fns
are the functions found in normal lookup. */
tree
lookup_arg_dependent (tree name, tree fns, tree args)
{
struct arg_lookup k;
tree fn = NULL_TREE;
timevar_push (TV_NAME_LOOKUP);
k.name = name;
k.functions = fns;
k.classes = NULL_TREE;
/* Note that we've already looked at some namespaces during normal
unqualified lookup, unless we found a decl in function scope. */
if (fns)
fn = OVL_CURRENT (fns);
if (fn && TREE_CODE (fn) == FUNCTION_DECL && DECL_LOCAL_FUNCTION_P (fn))
k.namespaces = NULL_TREE;
else
unqualified_namespace_lookup (name, 0, &k.namespaces);
arg_assoc_args (&k, args);
POP_TIMEVAR_AND_RETURN (TV_NAME_LOOKUP, k.functions);
}
/* Add namespace to using_directives. Return NULL_TREE if nothing was /* Add namespace to using_directives. Return NULL_TREE if nothing was
changed (i.e. there was already a directive), or the fresh changed (i.e. there was already a directive), or the fresh
TREE_LIST otherwise. */ TREE_LIST otherwise. */
......
...@@ -70,9 +70,6 @@ typedef struct cp_binding_level cxx_scope; ...@@ -70,9 +70,6 @@ typedef struct cp_binding_level cxx_scope;
currently being defined. */ currently being defined. */
#define INHERITED_VALUE_BINDING_P(NODE) ((NODE)->value_is_inherited) #define INHERITED_VALUE_BINDING_P(NODE) ((NODE)->value_is_inherited)
/* Zero out a cxx_binding pointed to by B. */
#define cxx_binding_clear(B) memset ((B), 0, sizeof (cxx_binding))
struct cxx_binding GTY(()) struct cxx_binding GTY(())
{ {
/* Link to chain together various bindings for this name. */ /* Link to chain together various bindings for this name. */
...@@ -91,6 +88,9 @@ extern tree identifier_type_value (tree); ...@@ -91,6 +88,9 @@ extern tree identifier_type_value (tree);
extern void set_identifier_type_value (tree, tree); extern void set_identifier_type_value (tree, tree);
extern void pop_binding (tree, tree); extern void pop_binding (tree, tree);
extern void clear_identifier_class_values (void); extern void clear_identifier_class_values (void);
extern tree constructor_name_full (tree);
extern tree constructor_name (tree);
extern bool constructor_name_p (tree, tree);
/* The kinds of scopes we recognize. */ /* The kinds of scopes we recognize. */
typedef enum scope_kind { typedef enum scope_kind {
...@@ -267,16 +267,18 @@ extern void pop_from_top_level (void); ...@@ -267,16 +267,18 @@ extern void pop_from_top_level (void);
extern void maybe_push_to_top_level (int); extern void maybe_push_to_top_level (int);
extern void pop_everything (void); extern void pop_everything (void);
extern void keep_next_level (bool); extern void keep_next_level (bool);
extern bool is_ancestor (tree, tree);
extern void push_scope (tree);
extern void pop_scope (tree);
extern void push_namespace (tree); extern void push_namespace (tree);
extern void pop_namespace (void); extern void pop_namespace (void);
extern void push_nested_namespace (tree); extern void push_nested_namespace (tree);
extern void pop_nested_namespace (tree); extern void pop_nested_namespace (tree);
extern tree namespace_ancestor (tree, tree);
extern tree push_using_directive (tree); extern tree push_using_directive (tree);
extern void pushlevel_class (void); extern void pushlevel_class (void);
extern void poplevel_class (void); extern void poplevel_class (void);
extern cxx_binding *cxx_scope_find_binding_for_name (cxx_scope *, tree);
extern cxx_binding *binding_for_name (cxx_scope *, tree);
extern tree pushdecl_with_scope (tree, cxx_scope *); extern tree pushdecl_with_scope (tree, cxx_scope *);
extern tree lookup_tag (enum tree_code, tree, cxx_scope *, int); extern tree lookup_tag (enum tree_code, tree, cxx_scope *, int);
extern tree lookup_tag_reverse (tree, tree); extern tree lookup_tag_reverse (tree, tree);
...@@ -284,6 +286,8 @@ extern tree lookup_name (tree, int); ...@@ -284,6 +286,8 @@ extern tree lookup_name (tree, int);
extern tree lookup_name_real (tree, int, int, int, int); extern tree lookup_name_real (tree, int, int, int, int);
extern tree lookup_name_current_level (tree); extern tree lookup_name_current_level (tree);
extern tree lookup_type_current_level (tree); extern tree lookup_type_current_level (tree);
extern bool lookup_using_namespace (tree, cxx_binding *, tree, tree, int, tree *);
extern bool qualified_lookup_using_namespace (tree, tree, cxx_binding *, int);
extern tree namespace_binding (tree, tree); extern tree namespace_binding (tree, tree);
extern void add_decl_to_level (tree, cxx_scope *); extern void add_decl_to_level (tree, cxx_scope *);
extern void set_namespace_binding (tree, tree, tree); extern void set_namespace_binding (tree, tree, tree);
...@@ -301,6 +305,16 @@ extern void storetags (tree); ...@@ -301,6 +305,16 @@ extern void storetags (tree);
extern tree getdecls (void); extern tree getdecls (void);
extern tree cp_namespace_decls (tree); extern tree cp_namespace_decls (tree);
extern void set_class_shadows (tree); extern void set_class_shadows (tree);
extern void set_decl_namespace (tree, tree, bool);
extern tree current_decl_namespace (void);
extern void push_decl_namespace (tree);
extern void pop_decl_namespace (void);
extern void do_namespace_alias (tree, tree);
extern void do_toplevel_using_decl (tree);
extern void do_local_using_decl (tree);
extern tree do_class_using_decl (tree);
extern void do_using_directive (tree);
extern tree lookup_arg_dependent (tree, tree, tree);
/* Set *DECL to the (non-hidden) declaration for ID at global scope, /* Set *DECL to the (non-hidden) declaration for ID at global scope,
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment