Commit db10df3d by Jason Merrill Committed by Jason Merrill

PR c++/41305, DR 384

	PR c++/41305, DR 384
	* name-lookup.c (arg_assoc_class): Split out arg_assoc_class_only
	and arg_assoc_bases.
	(friend_of_associated_class_p): Remove.
	(arg_assoc_namespace): Don't call it.
	(arg_assoc_template_arg): Use arg_assoc_class_only for member
	template context.
	(arg_assoc_type): Handle UNION_TYPE and ENUMERAL_TYPE properly.

	* name-lookup.c (arg_assoc): Handle TEMPLATE_ID_EXPR properly.

From-SVN: r155461
parent 17fad361
2009-12-24 Jason Merrill <jason@redhat.com>
PR c++/41305, DR 384
* name-lookup.c (arg_assoc_class): Split out arg_assoc_class_only
and arg_assoc_bases.
(friend_of_associated_class_p): Remove.
(arg_assoc_namespace): Don't call it.
(arg_assoc_template_arg): Use arg_assoc_class_only for member
template context.
(arg_assoc_type): Handle UNION_TYPE and ENUMERAL_TYPE properly.
* name-lookup.c (arg_assoc): Handle TEMPLATE_ID_EXPR properly.
2009-12-23 Dodji Seketeli <dodji@redhat.com> 2009-12-23 Dodji Seketeli <dodji@redhat.com>
PR c++/42260 PR c++/42260
......
...@@ -4549,6 +4549,8 @@ static bool arg_assoc_args_vec (struct arg_lookup*, VEC(tree,gc) *); ...@@ -4549,6 +4549,8 @@ static bool arg_assoc_args_vec (struct arg_lookup*, VEC(tree,gc) *);
static bool arg_assoc_type (struct arg_lookup*, tree); static bool arg_assoc_type (struct arg_lookup*, tree);
static bool add_function (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_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_class (struct arg_lookup *, tree);
static bool arg_assoc_template_arg (struct arg_lookup*, tree); static bool arg_assoc_template_arg (struct arg_lookup*, tree);
...@@ -4606,53 +4608,6 @@ is_associated_namespace (tree current, tree scope) ...@@ -4606,53 +4608,6 @@ is_associated_namespace (tree current, tree scope)
} }
} }
/* Return whether FN is a friend of an associated class of ARG. */
static bool
friend_of_associated_class_p (tree arg, tree fn)
{
tree type;
if (TYPE_P (arg))
type = arg;
else if (type_unknown_p (arg))
return false;
else
type = TREE_TYPE (arg);
/* If TYPE is a class, the class itself and all base classes are
associated classes. */
if (CLASS_TYPE_P (type))
{
if (is_friend (type, fn))
return true;
if (TYPE_BINFO (type))
{
tree binfo, base_binfo;
int i;
for (binfo = TYPE_BINFO (type), i = 0;
BINFO_BASE_ITERATE (binfo, i, base_binfo);
i++)
if (is_friend (BINFO_TYPE (base_binfo), fn))
return true;
}
}
/* If TYPE is a class member, the class of which it is a member is
an associated class. */
if ((CLASS_TYPE_P (type)
|| TREE_CODE (type) == UNION_TYPE
|| TREE_CODE (type) == ENUMERAL_TYPE)
&& TYPE_CONTEXT (type)
&& CLASS_TYPE_P (TYPE_CONTEXT (type))
&& is_friend (TYPE_CONTEXT (type), fn))
return true;
return false;
}
/* Add functions of a namespace to the lookup structure. /* Add functions of a namespace to the lookup structure.
Returns true on error. */ Returns true on error. */
...@@ -4686,18 +4641,9 @@ arg_assoc_namespace (struct arg_lookup *k, tree scope) ...@@ -4686,18 +4641,9 @@ arg_assoc_namespace (struct arg_lookup *k, tree scope)
{ {
/* We don't want to find arbitrary hidden functions via argument /* We don't want to find arbitrary hidden functions via argument
dependent lookup. We only want to find friends of associated dependent lookup. We only want to find friends of associated
classes. */ classes, which we'll do via arg_assoc_class. */
if (hidden_name_p (OVL_CURRENT (value))) if (hidden_name_p (OVL_CURRENT (value)))
{ continue;
unsigned int ix;
tree arg;
for (ix = 0; VEC_iterate (tree, k->args, ix, arg); ++ix)
if (friend_of_associated_class_p (arg, OVL_CURRENT (value)))
break;
if (ix >= VEC_length (tree, k->args))
continue;
}
if (add_function (k, OVL_CURRENT (value))) if (add_function (k, OVL_CURRENT (value)))
return true; return true;
...@@ -4736,7 +4682,7 @@ arg_assoc_template_arg (struct arg_lookup *k, tree arg) ...@@ -4736,7 +4682,7 @@ arg_assoc_template_arg (struct arg_lookup *k, tree arg)
return arg_assoc_namespace (k, ctx); return arg_assoc_namespace (k, ctx);
/* Otherwise, it must be member template. */ /* Otherwise, it must be member template. */
else else
return arg_assoc_class (k, ctx); return arg_assoc_class_only (k, ctx);
} }
/* It's an argument pack; handle it recursively. */ /* It's an argument pack; handle it recursively. */
else if (ARGUMENT_PACK_P (arg)) else if (ARGUMENT_PACK_P (arg))
...@@ -4758,41 +4704,25 @@ arg_assoc_template_arg (struct arg_lookup *k, tree arg) ...@@ -4758,41 +4704,25 @@ arg_assoc_template_arg (struct arg_lookup *k, tree arg)
return false; return false;
} }
/* Adds everything associated with class to the lookup structure. /* Adds the class and its friends to the lookup structure.
Returns true on error. */ Returns true on error. */
static bool static bool
arg_assoc_class (struct arg_lookup *k, tree type) arg_assoc_class_only (struct arg_lookup *k, tree type)
{ {
tree list, friends, context; tree list, friends, context;
int i;
/* Backend build structures, such as __builtin_va_list, aren't /* Backend-built structures, such as __builtin_va_list, aren't
affected by all this. */ affected by all this. */
if (!CLASS_TYPE_P (type)) if (!CLASS_TYPE_P (type))
return false; return false;
if (purpose_member (type, k->classes))
return false;
k->classes = tree_cons (type, NULL_TREE, k->classes);
context = decl_namespace_context (type); context = decl_namespace_context (type);
if (arg_assoc_namespace (k, context)) if (arg_assoc_namespace (k, context))
return true; return true;
complete_type (type); complete_type (type);
if (TYPE_BINFO (type))
{
/* Process baseclasses. */
tree binfo, base_binfo;
for (binfo = TYPE_BINFO (type), i = 0;
BINFO_BASE_ITERATE (binfo, i, base_binfo); i++)
if (arg_assoc_class (k, BINFO_TYPE (base_binfo)))
return true;
}
/* Process friends. */ /* Process friends. */
for (list = DECL_FRIENDLIST (TYPE_MAIN_DECL (type)); list; for (list = DECL_FRIENDLIST (TYPE_MAIN_DECL (type)); list;
list = TREE_CHAIN (list)) list = TREE_CHAIN (list))
...@@ -4815,13 +4745,79 @@ arg_assoc_class (struct arg_lookup *k, tree type) ...@@ -4815,13 +4745,79 @@ arg_assoc_class (struct arg_lookup *k, tree type)
return true; return true;
} }
return false;
}
/* 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)
{
if (arg_assoc_class_only (k, type))
return true;
if (TYPE_BINFO (type))
{
/* Process baseclasses. */
tree binfo, 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;
}
return false;
}
/* Adds everything associated with a class argument type to the lookup
structure. Returns true on error.
If T is a class type (including unions), its associated classes are: the
class itself; the class of which it is a member, if any; and its direct
and indirect base classes. Its associated namespaces are the namespaces
of which its associated classes are members. Furthermore, if T is a
class template specialization, its associated namespaces and classes
also include: the namespaces and classes associated with the types of
the template arguments provided for template type parameters (excluding
template template parameters); the namespaces of which any template
template arguments are members; and the classes of which any member
templates used as template template arguments are members. [ Note:
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)
{
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;
if (purpose_member (type, k->classes))
return false;
k->classes = tree_cons (type, NULL_TREE, k->classes);
if (TYPE_CLASS_SCOPE_P (type)
&& arg_assoc_class_only (k, TYPE_CONTEXT (type)))
return true;
if (arg_assoc_bases (k, type))
return true;
/* Process template arguments. */ /* Process template arguments. */
if (CLASSTYPE_TEMPLATE_INFO (type) if (CLASSTYPE_TEMPLATE_INFO (type)
&& PRIMARY_TEMPLATE_P (CLASSTYPE_TI_TEMPLATE (type))) && PRIMARY_TEMPLATE_P (CLASSTYPE_TI_TEMPLATE (type)))
{ {
list = INNERMOST_TEMPLATE_ARGS (CLASSTYPE_TI_ARGS (type)); list = INNERMOST_TEMPLATE_ARGS (CLASSTYPE_TI_ARGS (type));
for (i = 0; i < TREE_VEC_LENGTH (list); ++i) for (i = 0; i < TREE_VEC_LENGTH (list); ++i)
arg_assoc_template_arg (k, TREE_VEC_ELT (list, i)); if (arg_assoc_template_arg (k, TREE_VEC_ELT (list, i)))
return true;
} }
return false; return false;
...@@ -4861,13 +4857,16 @@ arg_assoc_type (struct arg_lookup *k, tree type) ...@@ -4861,13 +4857,16 @@ arg_assoc_type (struct arg_lookup *k, tree type)
case RECORD_TYPE: case RECORD_TYPE:
if (TYPE_PTRMEMFUNC_P (type)) if (TYPE_PTRMEMFUNC_P (type))
return arg_assoc_type (k, TYPE_PTRMEMFUNC_FN_TYPE (type)); return arg_assoc_type (k, TYPE_PTRMEMFUNC_FN_TYPE (type));
case UNION_TYPE:
return arg_assoc_class (k, type); return arg_assoc_class (k, type);
case POINTER_TYPE: case POINTER_TYPE:
case REFERENCE_TYPE: case REFERENCE_TYPE:
case ARRAY_TYPE: case ARRAY_TYPE:
return arg_assoc_type (k, TREE_TYPE (type)); return arg_assoc_type (k, TREE_TYPE (type));
case UNION_TYPE:
case ENUMERAL_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)); return arg_assoc_namespace (k, decl_namespace_context (type));
case METHOD_TYPE: case METHOD_TYPE:
/* The basetype is referenced in the first arg type, so just /* The basetype is referenced in the first arg type, so just
...@@ -4951,34 +4950,17 @@ arg_assoc (struct arg_lookup *k, tree n) ...@@ -4951,34 +4950,17 @@ arg_assoc (struct arg_lookup *k, tree n)
return arg_assoc_type (k, TREE_TYPE (n)); return arg_assoc_type (k, TREE_TYPE (n));
if (TREE_CODE (n) == TEMPLATE_ID_EXPR) if (TREE_CODE (n) == TEMPLATE_ID_EXPR)
{ {
/* [basic.lookup.koenig] /* The working paper doesn't currently say how to handle template-id
arguments. The sensible thing would seem to be to handle the list
If T is a template-id, its associated namespaces and classes of template candidates like a normal overload set, and handle the
are the namespace in which the template is defined; for template arguments like we do for class template
member templates, the member template's class... */ specializations. */
tree templ = TREE_OPERAND (n, 0); tree templ = TREE_OPERAND (n, 0);
tree args = TREE_OPERAND (n, 1); tree args = TREE_OPERAND (n, 1);
tree ctx;
int ix; int ix;
if (TREE_CODE (templ) == COMPONENT_REF) /* First the templates. */
templ = TREE_OPERAND (templ, 1); if (arg_assoc (k, templ))
/* 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. */
templ = OVL_CURRENT (templ);
ctx = CP_DECL_CONTEXT (templ);
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; return true;
/* Now the arguments. */ /* Now the arguments. */
......
2009-12-24 Jason Merrill <jason@redhat.com>
PR c++/41305
* g++.dg/lookup/koenig9.C: New test.
* g++.dg/lookup/koenig10.C: New test.
* g++.dg/lookup/koenig11.C: New test.
* g++.dg/lookup/koenig12.C: New test.
2009-12-24 Julian Brown <julian@codesourcery.com> 2009-12-24 Julian Brown <julian@codesourcery.com>
Ramana Radhakrishnan <ramana.radhakrishnan@arm.com> Ramana Radhakrishnan <ramana.radhakrishnan@arm.com>
......
// Test for proper handling of class-scope enums.
struct A
{
enum E { e };
friend void f (E);
};
int main()
{
f(A::e);
}
// Test that we treat unions like other classes in arg-dep lookup.
union U
{
friend void f (U);
};
int main()
{
U u;
f(u);
}
// PR c++/41305
// We got into infinite recursion instantiating the B<U> series.
template <class T> struct A { };
template <class T, class U = A<T> > struct B;
template <class T> struct C { };
template <class T, class U> struct B: C<B<U> >
{
friend void f(B) { }
};
B<int> b;
int main()
{
f(b);
}
// Test for sensible handling of template-ids with arg-dep lookup.
// This is still an open issue.
namespace N
{
struct A { };
void f(void (*)(int, N::A));
}
namespace M
{
struct B { };
void f(void (*)(B, N::A));
}
template <class T>
void g(T, N::A);
void g();
int main()
{
f(g<int>);
f(g<M::B>);
}
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