return NULL;
}
-/* [basic.lookup.koenig] */
-/* A nonzero return value in the functions below indicates an error. */
-
-struct arg_lookup
-{
- tree name;
- vec<tree, va_gc> *args;
- vec<tree, va_gc> *namespaces;
- vec<tree, va_gc> *classes;
- tree functions;
+struct name_lookup
+{
+public:
+ tree name; /* The identifier being looked for. */
+ tree value; /* A (possibly ambiguous) set of things found. */
+ tree type; /* A type that has been found. */
+ vec<tree, va_heap, vl_embed> *scopes;
+ name_lookup *previous; /* Previously active lookup. */
hash_set<tree> *fn_set;
-};
-static bool arg_assoc (struct arg_lookup*, tree);
-static bool arg_assoc_args (struct arg_lookup*, tree);
-static bool arg_assoc_args_vec (struct arg_lookup*, vec<tree, va_gc> *);
-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_only (struct arg_lookup *, tree);
-static bool arg_assoc_bases (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. */
+protected:
+ /* Marked scope stack for outermost name lookup. */
+ static vec<tree, va_heap, vl_embed> *shared_scopes;
+ /* Currently active lookup. */
+ static name_lookup *active;
-static bool
-add_function (struct arg_lookup *k, tree fn)
-{
- if (!is_overloaded_fn (fn))
- /* All names except those of (possibly overloaded) functions and
- function templates are ignored. */;
- else if (k->fn_set && k->fn_set->add (fn))
- /* It's already in the list. */;
- else if (!k->functions && TREE_CODE (fn) != TEMPLATE_DECL)
- k->functions = fn;
- else if (fn == k->functions)
- ;
- else
- k->functions = lookup_add (fn, k->functions);
+public:
+ name_lookup (tree n)
+ : name (n), value (NULL_TREE), type (NULL_TREE),
+ scopes (NULL), previous (NULL), fn_set (NULL)
+ {
+ preserve_state ();
+ }
+ ~name_lookup ()
+ {
+ gcc_checking_assert (!fn_set);
+ restore_state ();
+ }
- return false;
-}
+private: /* Uncopyable, unmovable, unassignable. I am a rock. */
+ name_lookup (const name_lookup &);
+ name_lookup &operator= (const name_lookup &);
-/* Returns true iff CURRENT has declared itself to be an associated
- namespace of SCOPE via a strong using-directive (or transitive chain
- thereof). Both are namespaces. */
+protected:
+ static bool seen_p (tree scope)
+ {
+ return LOOKUP_SEEN_P (scope);
+ }
+ static bool found_p (tree scope)
+ {
+ return LOOKUP_FOUND_P (scope);
+ }
+
+ void mark_seen (tree scope); /* Mark and add to scope vector. */
+ static void mark_found (tree scope)
+ {
+ gcc_checking_assert (seen_p (scope));
+ LOOKUP_FOUND_P (scope) = true;
+ }
+ bool see_and_mark (tree scope)
+ {
+ bool ret = seen_p (scope);
+ if (!ret)
+ mark_seen (scope);
+ return ret;
+ }
+ bool find_and_mark (tree scope);
+
+private:
+ void preserve_state ();
+ void restore_state ();
+
+ private:
+ void add_fns (tree);
+
+ void adl_expr (tree);
+ void adl_type (tree);
+ void adl_template_arg (tree);
+ void adl_class (tree);
+ void adl_bases (tree);
+ void adl_class_only (tree);
+ void adl_namespace (tree);
+ void adl_namespace_only (tree);
+
+public:
+ tree search_adl (tree fns, vec<tree, va_gc> *args);
+};
-bool
-is_associated_namespace (tree current, tree scope)
-{
- vec<tree, va_gc> *seen = make_tree_vector ();
- vec<tree, va_gc> *todo = make_tree_vector ();
- tree t;
- bool ret;
+/* Scope stack shared by all outermost lookups. This avoids us
+ allocating and freeing on every single lookup. */
+vec<tree, va_heap, vl_embed> *name_lookup::shared_scopes;
- while (1)
+/* Currently active lookup. */
+name_lookup *name_lookup::active;
+
+/* Name lookup is recursive, becase ADL can cause template
+ instatiation. This is of course a rare event, so we optimize for
+ it not happening. When we discover an active name-lookup, which
+ must be an ADL lookup, we need to unmark the marked scopes and also
+ unmark the lookup we might have been accumulating. */
+
+void
+name_lookup::preserve_state ()
+{
+ previous = active;
+ if (previous)
{
- if (scope == current)
- {
- ret = true;
- break;
- }
- vec_safe_push (seen, scope);
- for (t = DECL_NAMESPACE_ASSOCIATIONS (scope); t; t = TREE_CHAIN (t))
- if (!vec_member (TREE_PURPOSE (t), seen))
- vec_safe_push (todo, TREE_PURPOSE (t));
- if (!todo->is_empty ())
+ unsigned length = vec_safe_length (previous->scopes);
+ vec_safe_reserve (previous->scopes, length * 2);
+ for (unsigned ix = length; ix--;)
{
- scope = todo->last ();
- todo->pop ();
- }
- else
- {
- ret = false;
- break;
- }
- }
+ tree decl = (*previous->scopes)[ix];
- release_tree_vector (seen);
- release_tree_vector (todo);
+ gcc_checking_assert (LOOKUP_SEEN_P (decl));
+ LOOKUP_SEEN_P (decl) = false;
- return ret;
+ /* Preserve the FOUND_P state on the interrupted lookup's
+ stack. */
+ if (LOOKUP_FOUND_P (decl))
+ {
+ LOOKUP_FOUND_P (decl) = false;
+ previous->scopes->quick_push (decl);
+ }
+ }
+ }
+ else
+ scopes = shared_scopes;
+ active = this;
}
-/* Add functions of a namespace to the lookup structure.
- Returns true on error. */
+/* Restore the marking state of a lookup we interrupted. */
-static bool
-arg_assoc_namespace (struct arg_lookup *k, tree scope)
+void
+name_lookup::restore_state ()
{
- tree value;
+ /* Unmark and empty this lookup's scope stack. */
+ for (unsigned ix = vec_safe_length (scopes); ix--;)
+ {
+ tree decl = scopes->pop ();
+ gcc_checking_assert (LOOKUP_SEEN_P (decl));
+ LOOKUP_SEEN_P (decl) = false;
+ LOOKUP_FOUND_P (decl) = false;
+ }
- if (vec_member (scope, k->namespaces))
- return false;
- vec_safe_push (k->namespaces, scope);
+ active = previous;
+ if (previous)
+ {
+ unsigned length = vec_safe_length (previous->scopes);
+ for (unsigned ix = 0; ix != length; ix++)
+ {
+ tree decl = (*previous->scopes)[ix];
+ if (LOOKUP_SEEN_P (decl))
+ {
+ /* The remainder of the scope stack must be recording
+ FOUND_P decls, which we want to pop off. */
+ do
+ {
+ tree decl = previous->scopes->pop ();
+ gcc_checking_assert (LOOKUP_SEEN_P (decl)
+ && !LOOKUP_FOUND_P (decl));
+ LOOKUP_FOUND_P (decl) = true;
+ }
+ while (++ix != length);
+ break;
+ }
- /* Check out our super-users. */
- for (value = DECL_NAMESPACE_ASSOCIATIONS (scope); value;
- value = TREE_CHAIN (value))
- if (arg_assoc_namespace (k, TREE_PURPOSE (value)))
- return true;
+ gcc_checking_assert (!LOOKUP_FOUND_P (decl));
+ LOOKUP_SEEN_P (decl) = true;
+ }
- /* Also look down into inline namespaces. */
- for (value = DECL_NAMESPACE_USING (scope); value;
- value = TREE_CHAIN (value))
- if (is_associated_namespace (scope, TREE_PURPOSE (value)))
- if (arg_assoc_namespace (k, TREE_PURPOSE (value)))
- return true;
+ free (scopes);
+ }
+ else
+ shared_scopes = scopes;
+}
- value = get_namespace_binding (scope, k->name);
- if (!value)
- return false;
+void
+name_lookup::mark_seen (tree scope)
+{
+ gcc_checking_assert (!seen_p (scope));
+ LOOKUP_SEEN_P (scope) = true;
+ vec_safe_push (scopes, scope);
+}
- value = ovl_skip_hidden (value);
-
- for (; value; value = OVL_NEXT (value))
+bool
+name_lookup::find_and_mark (tree scope)
+{
+ bool result = LOOKUP_FOUND_P (scope);
+ if (!result)
{
- if (add_function (k, OVL_CURRENT (value)))
- return true;
+ LOOKUP_FOUND_P (scope) = true;
+ if (!LOOKUP_SEEN_P (scope))
+ vec_safe_push (scopes, scope);
}
- return false;
+ return result;
}
-/* Adds everything associated with a template argument to the lookup
- structure. Returns true on error. */
+/* FNS is a value binding. If it is a (set of overloaded) functions,
+ add them into the current value. */
-static bool
-arg_assoc_template_arg (struct arg_lookup *k, tree arg)
+void
+name_lookup::add_fns (tree fns)
{
- /* [basic.lookup.koenig]
+ if (!fns)
+ return;
+ else if (TREE_CODE (fns) == OVERLOAD)
+ {
+ if (TREE_TYPE (fns) != unknown_type_node)
+ fns = OVL_FUNCTION (fns);
+ }
+ else if (!DECL_DECLARES_FUNCTION_P (fns))
+ return;
- 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. ] */
+ /* Only add those that aren't already there. */
+ for (ovl_iterator iter (fns); iter; ++iter)
+ if (!fn_set->add (*iter))
+ value = lookup_add (*iter, value);
+}
- /* 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);
+/* Add functions of a namespace to the lookup structure. */
- /* 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_only (k, ctx);
- }
- /* It's an argument pack; handle it recursively. */
- else if (ARGUMENT_PACK_P (arg))
- {
- tree args = ARGUMENT_PACK_ARGS (arg);
- int i, len = TREE_VEC_LENGTH (args);
- for (i = 0; i < len; ++i)
- if (arg_assoc_template_arg (k, TREE_VEC_ELT (args, i)))
- return true;
+void
+name_lookup::adl_namespace_only (tree scope)
+{
+ mark_seen (scope);
- return false;
- }
- /* 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;
+ /* Look down into inline namespaces. */
+ for (tree inner = NAMESPACE_LEVEL (scope)->namespaces;
+ inner; inner = TREE_CHAIN (inner))
+ if (DECL_NAMESPACE_INLINE_P (inner))
+ adl_namespace_only (inner);
+
+ if (cxx_binding *binding = find_namespace_binding (scope, name))
+ add_fns (ovl_skip_hidden (binding->value));
}
-/* Adds the class and its friends to the lookup structure.
- Returns true on error. */
+/* Find the containing non-inlined namespace, add it and all its
+ inlinees. */
-static bool
-arg_assoc_class_only (struct arg_lookup *k, tree type)
+void
+name_lookup::adl_namespace (tree scope)
{
- tree list, friends, context;
+ if (seen_p (scope))
+ return;
+
+ /* Find the containing non-inline namespace. */
+ while (DECL_NAMESPACE_INLINE_P (scope))
+ scope = CP_DECL_CONTEXT (scope);
+
+ adl_namespace_only (scope);
+}
+/* Adds the class and its friends to the lookup structure. */
+
+void
+name_lookup::adl_class_only (tree type)
+{
/* Backend-built structures, such as __builtin_va_list, aren't
affected by all this. */
if (!CLASS_TYPE_P (type))
- return false;
+ return;
- context = decl_namespace_context (type);
- if (arg_assoc_namespace (k, context))
- return true;
+ type = TYPE_MAIN_VARIANT (type);
+
+ if (see_and_mark (type))
+ return;
+
+ tree context = decl_namespace_context (type);
+ adl_namespace (context);
complete_type (type);
- /* Process friends. */
- for (list = DECL_FRIENDLIST (TYPE_MAIN_DECL (type)); list;
+ /* Add friends. */
+ for (tree list = DECL_FRIENDLIST (TYPE_MAIN_DECL (type)); list;
list = TREE_CHAIN (list))
- if (k->name == FRIEND_NAME (list))
- for (friends = FRIEND_DECLS (list); friends;
+ if (name == FRIEND_NAME (list))
+ for (tree friends = FRIEND_DECLS (list); friends;
friends = TREE_CHAIN (friends))
{
tree fn = TREE_VALUE (friends);
(i.e. unqualified) declarations. */
if (CP_DECL_CONTEXT (fn) != context)
continue;
+
/* Template specializations are never found by name lookup.
(Templates themselves can be found, but not template
specializations.) */
if (TREE_CODE (fn) == FUNCTION_DECL && DECL_USE_TEMPLATE (fn))
continue;
- if (add_function (k, fn))
- return true;
- }
- return false;
+ add_fns (fn);
+ }
}
/* Adds the class and its bases to the lookup structure.
Returns true on error. */
-static bool
-arg_assoc_bases (struct arg_lookup *k, tree type)
+void
+name_lookup::adl_bases (tree type)
{
- if (arg_assoc_class_only (k, type))
- return true;
+ adl_class_only (type);
- if (TYPE_BINFO (type))
+ /* Process baseclasses. */
+ if (tree binfo = TYPE_BINFO (type))
{
- /* Process baseclasses. */
- tree binfo, base_binfo;
+ tree base_binfo;
int i;
- for (binfo = TYPE_BINFO (type), i = 0;
- BINFO_BASE_ITERATE (binfo, i, base_binfo); i++)
- if (arg_assoc_bases (k, BINFO_TYPE (base_binfo)))
- return true;
+ for (i = 0; BINFO_BASE_ITERATE (binfo, i, base_binfo); i++)
+ adl_bases (BINFO_TYPE (base_binfo));
}
-
- return false;
}
/* Adds everything associated with a class argument type to the lookup
non-type template arguments do not contribute to the set of associated
namespaces. --end note] */
-static bool
-arg_assoc_class (struct arg_lookup *k, tree type)
+void
+name_lookup::adl_class (tree type)
{
- tree list;
- int i;
-
/* Backend build structures, such as __builtin_va_list, aren't
affected by all this. */
if (!CLASS_TYPE_P (type))
- return false;
+ return;
- if (vec_member (type, k->classes))
- return false;
- vec_safe_push (k->classes, type);
+ type = TYPE_MAIN_VARIANT (type);
+ /* We don't set found here because we have to have set seen first,
+ which is done in the adl_bases walk. */
+ if (found_p (type))
+ return;
- if (TYPE_CLASS_SCOPE_P (type)
- && arg_assoc_class_only (k, TYPE_CONTEXT (type)))
- return true;
+ adl_bases (type);
+ mark_found (type);
- if (arg_assoc_bases (k, type))
- return true;
+ if (TYPE_CLASS_SCOPE_P (type))
+ adl_class_only (TYPE_CONTEXT (type));
/* Process template arguments. */
if (CLASSTYPE_TEMPLATE_INFO (type)
&& PRIMARY_TEMPLATE_P (CLASSTYPE_TI_TEMPLATE (type)))
{
- list = INNERMOST_TEMPLATE_ARGS (CLASSTYPE_TI_ARGS (type));
- for (i = 0; i < TREE_VEC_LENGTH (list); ++i)
- if (arg_assoc_template_arg (k, TREE_VEC_ELT (list, i)))
- return true;
+ tree list = INNERMOST_TEMPLATE_ARGS (CLASSTYPE_TI_ARGS (type));
+ for (int i = 0; i < TREE_VEC_LENGTH (list); ++i)
+ adl_template_arg (TREE_VEC_ELT (list, i));
}
-
- return false;
}
-/* Adds everything associated with a given type.
- Returns 1 on error. */
+void
+name_lookup::adl_expr (tree expr)
+{
+ if (!expr)
+ return;
-static bool
-arg_assoc_type (struct arg_lookup *k, tree type)
+ gcc_assert (!TYPE_P (expr));
+
+ if (TREE_TYPE (expr) != unknown_type_node)
+ {
+ adl_type (TREE_TYPE (expr));
+ return;
+ }
+
+ if (TREE_CODE (expr) == ADDR_EXPR)
+ expr = TREE_OPERAND (expr, 0);
+ if (TREE_CODE (expr) == COMPONENT_REF
+ || TREE_CODE (expr) == OFFSET_REF)
+ expr = TREE_OPERAND (expr, 1);
+ expr = MAYBE_BASELINK_FUNCTIONS (expr);
+
+ if (OVL_P (expr))
+ for (lkp_iterator iter (expr); iter; ++iter)
+ adl_type (TREE_TYPE (*iter));
+ else if (TREE_CODE (expr) == TEMPLATE_ID_EXPR)
+ {
+ /* The working paper doesn't currently say how to handle
+ template-id arguments. The sensible thing would seem to be
+ to handle the list of template candidates like a normal
+ overload set, and handle the template arguments like we do
+ for class template specializations. */
+
+ /* First the templates. */
+ adl_expr (TREE_OPERAND (expr, 0));
+
+ /* Now the arguments. */
+ if (tree args = TREE_OPERAND (expr, 1))
+ for (int ix = TREE_VEC_LENGTH (args); ix--;)
+ adl_template_arg (TREE_VEC_ELT (args, ix));
+ }
+}
+
+void
+name_lookup::adl_type (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;
+ return;
if (TYPE_PTRDATAMEM_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));
+ adl_type (TYPE_PTRMEM_CLASS_TYPE (type));
+ adl_type (TYPE_PTRMEM_POINTED_TO_TYPE (type));
+ return;
}
- else switch (TREE_CODE (type))
+
+ 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 BOOLEAN_TYPE:
- case FIXED_POINT_TYPE:
- case DECLTYPE_TYPE:
- case NULLPTR_TYPE:
- return false;
case RECORD_TYPE:
if (TYPE_PTRMEMFUNC_P (type))
- return arg_assoc_type (k, TYPE_PTRMEMFUNC_FN_TYPE (type));
+ {
+ adl_type (TYPE_PTRMEMFUNC_FN_TYPE (type));
+ return;
+ }
/* FALLTHRU */
case UNION_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 ENUMERAL_TYPE:
- if (TYPE_CLASS_SCOPE_P (type)
- && arg_assoc_class_only (k, TYPE_CONTEXT (type)))
- return true;
- return arg_assoc_namespace (k, decl_namespace_context (type));
+ adl_class (type);
+ return;
+
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;
+ for (tree args = TYPE_ARG_TYPES (type); args; args = TREE_CHAIN (args))
+ adl_type (TREE_VALUE (args));
+ /* FALLTHROUGH */
+
+ case POINTER_TYPE:
+ case REFERENCE_TYPE:
+ case ARRAY_TYPE:
+ adl_type (TREE_TYPE (type));
+ return;
+
+ case ENUMERAL_TYPE:
+ if (TYPE_CLASS_SCOPE_P (type))
+ adl_class_only (TYPE_CONTEXT (type));
+ adl_namespace (decl_namespace_context (type));
+ return;
+
case LANG_TYPE:
gcc_assert (type == unknown_type_node
|| type == init_list_type_node);
- return false;
+ return;
+
case TYPE_PACK_EXPANSION:
- return arg_assoc_type (k, PACK_EXPANSION_PATTERN (type));
+ adl_type (PACK_EXPANSION_PATTERN (type));
+ return;
default:
- gcc_unreachable ();
+ break;
}
- 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 an argument vector. Returns true
- on error. */
-
-static bool
-arg_assoc_args_vec (struct arg_lookup *k, vec<tree, va_gc> *args)
-{
- unsigned int ix;
- tree arg;
-
- FOR_EACH_VEC_SAFE_ELT (args, ix, arg)
- if (arg_assoc (k, arg))
- return true;
- return false;
-}
-
-/* Adds everything associated with a given tree_node. Returns 1 on error. */
+/* Adds everything associated with a template argument to the lookup
+ structure. */
-static bool
-arg_assoc (struct arg_lookup *k, tree n)
+void
+name_lookup::adl_template_arg (tree arg)
{
- if (n == error_mark_node)
- return false;
+ /* [basic.lookup.koenig]
- 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 (BASELINK_P (n))
- 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)
- {
- /* The working paper doesn't currently say how to handle template-id
- arguments. The sensible thing would seem to be to handle the list
- of template candidates like a normal overload set, and handle the
- template arguments like we do for class template
- specializations. */
- tree templ = TREE_OPERAND (n, 0);
- tree args = TREE_OPERAND (n, 1);
- int ix;
+ 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. ] */
- /* First the templates. */
- if (arg_assoc (k, templ))
- return true;
+ /* Consider first template template arguments. */
+ if (TREE_CODE (arg) == TEMPLATE_TEMPLATE_PARM
+ || TREE_CODE (arg) == UNBOUND_CLASS_TEMPLATE)
+ ;
+ else if (TREE_CODE (arg) == TEMPLATE_DECL)
+ {
+ tree ctx = CP_DECL_CONTEXT (arg);
- /* Now the arguments. */
- if (args)
- for (ix = TREE_VEC_LENGTH (args); ix--;)
- if (arg_assoc_template_arg (k, TREE_VEC_ELT (args, ix)) == 1)
- return true;
+ /* It's not a member template. */
+ if (TREE_CODE (ctx) == NAMESPACE_DECL)
+ adl_namespace (ctx);
+ /* Otherwise, it must be member template. */
+ else
+ adl_class_only (ctx);
}
- else if (TREE_CODE (n) == OVERLOAD)
+ /* It's an argument pack; handle it recursively. */
+ else if (ARGUMENT_PACK_P (arg))
{
- for (; n; n = OVL_NEXT (n))
- if (arg_assoc_type (k, TREE_TYPE (OVL_CURRENT (n))))
- return true;
+ tree args = ARGUMENT_PACK_ARGS (arg);
+ int i, len = TREE_VEC_LENGTH (args);
+ for (i = 0; i < len; ++i)
+ adl_template_arg (TREE_VEC_ELT (args, i));
}
-
- return false;
+ /* It's not a template template argument, but it is a type template
+ argument. */
+ else if (TYPE_P (arg))
+ adl_type (arg);
}
-/* Performs Koenig lookup depending on arguments, where fns
- are the functions found in normal lookup. */
+/* Perform ADL lookup. FNS is the existing lookup result and ARGS are
+ the call arguments. */
-static cp_expr
-lookup_arg_dependent_1 (tree name, tree fns, vec<tree, va_gc> *args)
+tree
+name_lookup::search_adl (tree fns, vec<tree, va_gc> *args)
{
- struct arg_lookup k;
+ value = fns;
- /* Remove any hidden friend functions from the list of functions
- found so far. They will be added back by arg_assoc_class as
- appropriate. */
- fns = ovl_skip_hidden (fns);
+ /* Add the current overload set into the hash table. */
+ fn_set = new hash_set<tree>;
+ for (lkp_iterator iter (fns); iter; ++iter)
+ fn_set->add (*iter);
- k.name = name;
- k.args = args;
- k.functions = fns;
- k.classes = make_tree_vector ();
-
- /* We previously performed an optimization here by setting
- NAMESPACES to the current namespace when it was safe. However, DR
- 164 says that namespaces that were already searched in the first
- stage of template processing are searched again (potentially
- picking up later definitions) in the second stage. */
- k.namespaces = make_tree_vector ();
+ unsigned ix;
+ tree arg;
- /* We used to allow duplicates and let joust discard them, but
- since the above change for DR 164 we end up with duplicates of
- all the functions found by unqualified lookup. So keep track
- of which ones we've seen. */
- if (fns)
- {
- tree ovl;
- /* We shouldn't be here if lookup found something other than
- namespace-scope functions. */
- gcc_assert (DECL_NAMESPACE_SCOPE_P (OVL_CURRENT (fns)));
- k.fn_set = new hash_set<tree>;
- for (ovl = fns; ovl; ovl = OVL_NEXT (ovl))
- k.fn_set->add (OVL_CURRENT (ovl));
- }
- else
- k.fn_set = NULL;
+ FOR_EACH_VEC_ELT_REVERSE (*args, ix, arg)
+ /* OMP reduction operators put a type as the first arg. I don't
+ suppose we should ADL on that? */
+ if (!TYPE_P (arg))
+ adl_expr (arg);
- arg_assoc_args_vec (&k, args);
+ delete fn_set;
+ fn_set = NULL;
- fns = k.functions;
-
- if (fns
- && !VAR_P (fns)
- && !is_overloaded_fn (fns))
- {
- error ("argument dependent lookup finds %q+D", fns);
- error (" in call to %qD", name);
- fns = error_mark_node;
- }
+ fns = value;
- release_tree_vector (k.classes);
- release_tree_vector (k.namespaces);
- delete k.fn_set;
-
return fns;
}
-/* Wrapper for lookup_arg_dependent_1. */
+/* ADL lookup of NAME. FNS is the result of regular lookup, and we
+ don't add duplicates to it. ARGS is the vector of call
+ arguments (which will not be empty). */
-cp_expr
+tree
lookup_arg_dependent (tree name, tree fns, vec<tree, va_gc> *args)
{
- cp_expr ret;
- bool subtime;
- subtime = timevar_cond_start (TV_NAME_LOOKUP);
- ret = lookup_arg_dependent_1 (name, fns, args);
+ bool subtime = timevar_cond_start (TV_NAME_LOOKUP);
+ name_lookup lookup (name);
+ fns = lookup.search_adl (fns, args);
timevar_cond_stop (TV_NAME_LOOKUP, subtime);
+ return fns;
+}
+
+/* Returns true iff CURRENT has declared itself to be an associated
+ namespace of SCOPE via a strong using-directive (or transitive chain
+ thereof). Both are namespaces. */
+
+bool
+is_associated_namespace (tree current, tree scope)
+{
+ vec<tree, va_gc> *seen = make_tree_vector ();
+ vec<tree, va_gc> *todo = make_tree_vector ();
+ tree t;
+ bool ret;
+
+ while (1)
+ {
+ if (scope == current)
+ {
+ ret = true;
+ break;
+ }
+ vec_safe_push (seen, scope);
+ for (t = DECL_NAMESPACE_ASSOCIATIONS (scope); t; t = TREE_CHAIN (t))
+ if (!vec_member (TREE_PURPOSE (t), seen))
+ vec_safe_push (todo, TREE_PURPOSE (t));
+ if (!todo->is_empty ())
+ {
+ scope = todo->last ();
+ todo->pop ();
+ }
+ else
+ {
+ ret = false;
+ break;
+ }
+ }
+
+ release_tree_vector (seen);
+ release_tree_vector (todo);
+
return ret;
}