OSDN Git Service

PR c++/41305, DR 384
authorjason <jason@138bc75d-0d04-0410-961f-82ee72b054a4>
Thu, 24 Dec 2009 21:46:14 +0000 (21:46 +0000)
committerjason <jason@138bc75d-0d04-0410-961f-82ee72b054a4>
Thu, 24 Dec 2009 21:46:14 +0000 (21:46 +0000)
* 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.

git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@155461 138bc75d-0d04-0410-961f-82ee72b054a4

gcc/cp/ChangeLog
gcc/cp/name-lookup.c
gcc/testsuite/ChangeLog
gcc/testsuite/g++.dg/lookup/koenig10.C [new file with mode: 0644]
gcc/testsuite/g++.dg/lookup/koenig11.C [new file with mode: 0644]
gcc/testsuite/g++.dg/lookup/koenig12.C [new file with mode: 0644]
gcc/testsuite/g++.dg/lookup/koenig9.C [new file with mode: 0644]

index ecd0c7a..57a4643 100644 (file)
@@ -1,3 +1,16 @@
+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>
 
        PR c++/42260
index 1371c8a..8f69346 100644 (file)
@@ -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 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);
 
@@ -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.
    Returns true on error.  */
 
@@ -4686,18 +4641,9 @@ arg_assoc_namespace (struct arg_lookup *k, tree scope)
     {
       /* We don't want to find arbitrary hidden functions via argument
         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)))
-       {
-         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;
-       }
+       continue;
 
       if (add_function (k, OVL_CURRENT (value)))
        return true;
@@ -4736,7 +4682,7 @@ arg_assoc_template_arg (struct arg_lookup *k, tree arg)
        return arg_assoc_namespace (k, ctx);
       /* Otherwise, it must be member template.  */
       else
-       return arg_assoc_class (k, ctx);
+       return arg_assoc_class_only (k, ctx);
     }
   /* It's an argument pack; handle it recursively.  */
   else if (ARGUMENT_PACK_P (arg))
@@ -4758,41 +4704,25 @@ arg_assoc_template_arg (struct arg_lookup *k, tree arg)
     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.  */
 
 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;
-  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.  */
   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_context (type);
   if (arg_assoc_namespace (k, context))
     return true;
 
   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.  */
   for (list = DECL_FRIENDLIST (TYPE_MAIN_DECL (type)); list;
        list = TREE_CHAIN (list))
@@ -4815,13 +4745,79 @@ arg_assoc_class (struct arg_lookup *k, tree type)
            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.  */
   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)
-       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;
@@ -4861,13 +4857,16 @@ arg_assoc_type (struct arg_lookup *k, tree type)
     case RECORD_TYPE:
       if (TYPE_PTRMEMFUNC_P (type))
        return arg_assoc_type (k, TYPE_PTRMEMFUNC_FN_TYPE (type));
+    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 UNION_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));
     case METHOD_TYPE:
       /* The basetype is referenced in the first arg type, so just
@@ -4951,34 +4950,17 @@ arg_assoc (struct arg_lookup *k, tree n)
     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...  */
+      /* 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);
-      tree ctx;
       int ix;
 
-      if (TREE_CODE (templ) == COMPONENT_REF)
-       templ = TREE_OPERAND (templ, 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.  */
-      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)
+      /* First the templates.  */
+      if (arg_assoc (k, templ))
        return true;
 
       /* Now the arguments.  */
index f2d8927..14bc7b7 100644 (file)
@@ -1,3 +1,11 @@
+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>
             Ramana Radhakrishnan  <ramana.radhakrishnan@arm.com>
 
diff --git a/gcc/testsuite/g++.dg/lookup/koenig10.C b/gcc/testsuite/g++.dg/lookup/koenig10.C
new file mode 100644 (file)
index 0000000..f2fce9c
--- /dev/null
@@ -0,0 +1,12 @@
+// Test for proper handling of class-scope enums.
+
+struct A
+{
+  enum E { e };
+  friend void f (E);
+};
+
+int main()
+{
+  f(A::e);
+}
diff --git a/gcc/testsuite/g++.dg/lookup/koenig11.C b/gcc/testsuite/g++.dg/lookup/koenig11.C
new file mode 100644 (file)
index 0000000..dab853b
--- /dev/null
@@ -0,0 +1,12 @@
+// Test that we treat unions like other classes in arg-dep lookup.
+
+union U
+{
+  friend void f (U);
+};
+
+int main()
+{
+  U u;
+  f(u);
+}
diff --git a/gcc/testsuite/g++.dg/lookup/koenig12.C b/gcc/testsuite/g++.dg/lookup/koenig12.C
new file mode 100644 (file)
index 0000000..c135899
--- /dev/null
@@ -0,0 +1,18 @@
+// 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);
+}
diff --git a/gcc/testsuite/g++.dg/lookup/koenig9.C b/gcc/testsuite/g++.dg/lookup/koenig9.C
new file mode 100644 (file)
index 0000000..f867a32
--- /dev/null
@@ -0,0 +1,25 @@
+// 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>);
+}