OSDN Git Service

PR c++/18825
authorlerdsuwa <lerdsuwa@138bc75d-0d04-0410-961f-82ee72b054a4>
Wed, 15 Dec 2004 15:21:11 +0000 (15:21 +0000)
committerlerdsuwa <lerdsuwa@138bc75d-0d04-0410-961f-82ee72b054a4>
Wed, 15 Dec 2004 15:21:11 +0000 (15:21 +0000)
* pt.c (instantiate_class_template): Set input_location for
friend function.
(tsubst_friend_function): Don't set input_location here.
Make sure the context is complete if necessary.

* g++.dg/template/friend32.C: New test.

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

gcc/cp/ChangeLog
gcc/cp/pt.c
gcc/testsuite/ChangeLog
gcc/testsuite/g++.dg/template/friend32.C [new file with mode: 0644]

index a879f4e..11e90b8 100644 (file)
@@ -1,3 +1,11 @@
+2004-12-15  Kriang Lerdsuwanakij  <lerdsuwa@users.sourceforge.net>
+
+       PR c++/18825
+       * pt.c (instantiate_class_template): Set input_location for
+       friend function.
+       (tsubst_friend_function): Don't set input_location here.
+       Make sure the context is complete if necessary.
+
 2004-12-15  Nathan Sidwell  <nathan@codesourcery.com>
 
        PR c++/18981
index 5da2806..db9b08f 100644 (file)
@@ -5098,9 +5098,6 @@ static tree
 tsubst_friend_function (tree decl, tree args)
 {
   tree new_friend;
-  location_t saved_loc = input_location;
-
-  input_location = DECL_SOURCE_LOCATION (decl);
 
   if (TREE_CODE (decl) == FUNCTION_DECL 
       && DECL_TEMPLATE_INSTANTIATION (decl)
@@ -5135,8 +5132,7 @@ tsubst_friend_function (tree decl, tree args)
                                       &new_args, 
                                       /*need_member_template=*/0,
                                       TREE_VEC_LENGTH (args));
-      new_friend = instantiate_template (tmpl, new_args, tf_error);
-      goto done;
+      return instantiate_template (tmpl, new_args, tf_error);
     }
 
   new_friend = tsubst (decl, args, tf_error | tf_warning, NULL_TREE);
@@ -5299,19 +5295,40 @@ tsubst_friend_function (tree decl, tree args)
          new_friend = old_decl;
        }
     }
-  else if (COMPLETE_TYPE_P (DECL_CONTEXT (new_friend)))
+  else
     {
-      /* Check to see that the declaration is really present, and,
-        possibly obtain an improved declaration.  */
-      tree fn = check_classfn (DECL_CONTEXT (new_friend), 
-                              new_friend, NULL_TREE);
-      
-      if (fn)
-       new_friend = fn;
+      tree context = DECL_CONTEXT (new_friend);
+      bool dependent_p;
+
+      /* In the code
+          template <class T> class C {
+            template <class U> friend void C1<U>::f (); // case 1
+            friend void C2<T>::f ();                    // case 2
+          };
+        we only need to make sure CONTEXT is a complete type for
+        case 2.  To distinguish between the two cases, we note that
+        CONTEXT of case 1 remains dependent type after tsubst while
+        this isn't true for case 2.  */
+      ++processing_template_decl;
+      dependent_p = dependent_type_p (context);
+      --processing_template_decl;
+
+      if (!dependent_p
+         && !complete_type_or_else (context, NULL_TREE))
+       return error_mark_node;
+
+      if (COMPLETE_TYPE_P (context))
+       {
+         /* Check to see that the declaration is really present, and,
+            possibly obtain an improved declaration.  */
+         tree fn = check_classfn (context,
+                                  new_friend, NULL_TREE);
+
+         if (fn)
+           new_friend = fn;
+       }
     }
 
- done:
-  input_location = saved_loc;
   return new_friend;
 }
 
@@ -5816,6 +5833,12 @@ instantiate_class_template (tree type)
              /* Build new DECL_FRIENDLIST.  */
              tree r;
 
+             /* The the file and line for this declaration, to
+                assist in error message reporting.  Since we
+                called push_tinst_level above, we don't need to
+                restore these.  */
+             input_location = DECL_SOURCE_LOCATION (t);
+
              if (TREE_CODE (t) == TEMPLATE_DECL)
                {
                  ++processing_template_decl;
index 80fb3cc..1f099eb 100644 (file)
@@ -1,3 +1,8 @@
+2004-12-15  Kriang Lerdsuwanakij  <lerdsuwa@users.sourceforge.net>
+
+       PR c++/18825
+       * g++.dg/template/friend32.C: New test.
+
 2004-12-15  Eric Botcazou  <ebotcazou@libertysurf.fr>
 
        * cpp/pragma-once-1.c: New test.
diff --git a/gcc/testsuite/g++.dg/template/friend32.C b/gcc/testsuite/g++.dg/template/friend32.C
new file mode 100644 (file)
index 0000000..4ce2ba3
--- /dev/null
@@ -0,0 +1,21 @@
+// { dg-do compile }
+
+// Origin: Steven Bosscher <steven@gcc.gnu.org>
+//        Serge Belyshev <belyshev@lubercy.com>
+
+// PR c++/18825: ICE member as friend
+
+template<class T> class A
+{
+  void f ();                   // { dg-error "private" }
+};
+
+template<class T> class B
+{
+  friend void A<T>::f ();      // { dg-error "this context" }
+};
+
+int f ()
+{
+  B<int> b;                    // { dg-error "instantiated" }
+}