This is the mail archive of the
gcc-patches@gcc.gnu.org
mailing list for the GCC project.
[C++ PATCH] Fix problem with "unmatched" friend template declaration (PR c++/34399)
- From: "Doug Gregor" <doug dot gregor at gmail dot com>
- To: "GCC Patches" <gcc-patches at gcc dot gnu dot org>
- Date: Mon, 14 Jan 2008 20:01:31 -0500
- Subject: [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" }
+};