This is the mail archive of the gcc-patches@gcc.gnu.org mailing list for the GCC project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

[C++ PATCH] Fix problem with "unmatched" friend template declaration (PR c++/34399)


This patch fixes PR c++/34399, a P2 logged against variadic templates
that's really also a latent issue in C++98. The problem here is that
the compiler ICEs when it sees a friend declaration for a member
function in a class template, but the template arguments in the friend
don't exactly match the template arguments for the class. In the PR,
the difference is that the friend used a template type parameter
instead of a template type parameter pack. In C++98, we can illustrate
the same issue by using non-type template parameters that don't match
types exactly, e.g.,

  template<int> struct X
  {
    void foo();
  };

  struct Y {
    template<long N> friend void X<N>::X::foo();
  };

This code currently causes the compiler to ICE (no C++0x features needed).

The patch does the simplest fix possible, making sure we don't do a
TYPE_BEING_DEFINED check on something that isn't always a class type
(X<N>::X actually ends up being a TYPENAME_TYPE).

Tested i686-pc-linux-gnu. Okay for mainline?

  - Doug


2008-01-14  Douglas Gregor  <doug.gregor@gmail.com>

	PR c++/34399
	* friend.c (do_friend): Don't query TYPE_BEING_DEFINED unless we
	know we have a class type.

2008-01-14  Douglas Gregor  <doug.gregor@gmail.com>

	PR c++/34399
	* g++.dg/cpp0x/vt-34399.C: New.
	* g++.dg/template/friend50.C: New.
Index: cp/friend.c
===================================================================
--- cp/friend.c	(revision 131535)
+++ cp/friend.c	(working copy)
@@ -468,7 +468,7 @@ do_friend (tree ctype, tree declarator, 
 	 the process of being defined.  */
       if (class_template_depth
 	  || COMPLETE_TYPE_P (ctype)
-	  || TYPE_BEING_DEFINED (ctype))
+	  || (CLASS_TYPE_P (ctype) && TYPE_BEING_DEFINED (ctype)))
 	{
 	  if (DECL_TEMPLATE_INFO (decl))
 	    /* DECL is a template specialization.  No need to
Index: testsuite/g++.dg/cpp0x/vt-34399.C
===================================================================
--- testsuite/g++.dg/cpp0x/vt-34399.C	(revision 0)
+++ testsuite/g++.dg/cpp0x/vt-34399.C	(revision 0)
@@ -0,0 +1,10 @@
+// { dg-options "-std=c++0x" }
+template<int...> struct A
+{
+  void foo();
+};
+
+struct B
+{
+  template<int N> friend void A<N>::A::foo(); // { dg-error "declared as friend" }
+};
Index: testsuite/g++.dg/template/friend50.C
===================================================================
--- testsuite/g++.dg/template/friend50.C	(revision 0)
+++ testsuite/g++.dg/template/friend50.C	(revision 0)
@@ -0,0 +1,9 @@
+// PR c++/34399
+template<int> struct X
+{
+  void foo();
+};
+
+struct Y {
+  template<long N> friend void X<N>::X::foo(); // { dg-error "declared as friend" }
+};

Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]