diff options
author | Jason Merrill <jason@redhat.com> | 2014-01-29 15:44:50 -0500 |
---|---|---|
committer | Jason Merrill <jason@gcc.gnu.org> | 2014-01-29 15:44:50 -0500 |
commit | 7651c656858e4c80febb67e1742c0aa0d716e1a1 (patch) | |
tree | f24433780390756fc9922334753b790abea23c6e /gcc | |
parent | d530142ddb708112ad0a7dabaf74f9b4072fa120 (diff) | |
download | gcc-7651c656858e4c80febb67e1742c0aa0d716e1a1.zip gcc-7651c656858e4c80febb67e1742c0aa0d716e1a1.tar.gz gcc-7651c656858e4c80febb67e1742c0aa0d716e1a1.tar.bz2 |
re PR c++/59956 (internal compiler error: unexpected expression ‘P_S’ of kind template_parm_index)
PR c++/59956
* friend.c (do_friend): Pass the TEMPLATE_DECL to add_friend if we
have a friend template in a class template.
* pt.c (tsubst_friend_function): Look through it.
(push_template_decl_real): A friend member template is
primary.
From-SVN: r207281
Diffstat (limited to 'gcc')
-rw-r--r-- | gcc/cp/ChangeLog | 9 | ||||
-rw-r--r-- | gcc/cp/friend.c | 8 | ||||
-rw-r--r-- | gcc/cp/pt.c | 14 | ||||
-rw-r--r-- | gcc/testsuite/g++.dg/template/friend55.C | 18 |
4 files changed, 45 insertions, 4 deletions
diff --git a/gcc/cp/ChangeLog b/gcc/cp/ChangeLog index 3215a43..723ce95 100644 --- a/gcc/cp/ChangeLog +++ b/gcc/cp/ChangeLog @@ -1,3 +1,12 @@ +2014-01-29 Jason Merrill <jason@redhat.com> + + PR c++/59956 + * friend.c (do_friend): Pass the TEMPLATE_DECL to add_friend if we + have a friend template in a class template. + * pt.c (tsubst_friend_function): Look through it. + (push_template_decl_real): A friend member template is + primary. + 2014-01-29 Paolo Carlini <paolo.carlini@oracle.com> PR c++/58846 diff --git a/gcc/cp/friend.c b/gcc/cp/friend.c index 4fd6ffa..150b392 100644 --- a/gcc/cp/friend.c +++ b/gcc/cp/friend.c @@ -501,7 +501,13 @@ do_friend (tree ctype, tree declarator, tree decl, ? current_template_parms : NULL_TREE); - if (template_member_p && decl && TREE_CODE (decl) == FUNCTION_DECL) + if ((template_member_p + /* Always pull out the TEMPLATE_DECL if we have a friend + template in a class template so that it gets tsubsted + properly later on (59956). tsubst_friend_function knows + how to tell this apart from a member template. */ + || (class_template_depth && friend_depth)) + && decl && TREE_CODE (decl) == FUNCTION_DECL) decl = DECL_TI_TEMPLATE (decl); if (decl) diff --git a/gcc/cp/pt.c b/gcc/cp/pt.c index ce679f6..943255d 100644 --- a/gcc/cp/pt.c +++ b/gcc/cp/pt.c @@ -4615,7 +4615,8 @@ push_template_decl_real (tree decl, bool is_friend) DECL_CONTEXT (decl) = FROB_CONTEXT (current_namespace); /* See if this is a primary template. */ - if (is_friend && ctx) + if (is_friend && ctx + && uses_template_parms_level (ctx, processing_template_decl)) /* A friend template that specifies a class context, i.e. template <typename T> friend void A<T>::f(); is not primary. */ @@ -8424,10 +8425,17 @@ tsubst_friend_function (tree decl, tree args) if (COMPLETE_TYPE_P (context)) { + tree fn = new_friend; + /* do_friend adds the TEMPLATE_DECL for any member friend + template even if it isn't a member template, i.e. + template <class T> friend A<T>::f(); + Look through it in that case. */ + if (TREE_CODE (fn) == TEMPLATE_DECL + && !PRIMARY_TEMPLATE_P (fn)) + fn = DECL_TEMPLATE_RESULT (fn); /* Check to see that the declaration is really present, and, possibly obtain an improved declaration. */ - tree fn = check_classfn (context, - new_friend, NULL_TREE); + fn = check_classfn (context, fn, NULL_TREE); if (fn) new_friend = fn; diff --git a/gcc/testsuite/g++.dg/template/friend55.C b/gcc/testsuite/g++.dg/template/friend55.C new file mode 100644 index 0000000..4abe6ce --- /dev/null +++ b/gcc/testsuite/g++.dg/template/friend55.C @@ -0,0 +1,18 @@ +// PR c++/59956 + +template <int I> struct A; +template <int I> class B { + int i; + template <int A_S> friend void A<A_S>::impl(); +}; + +B<0> b1; +template<int I>struct A { void impl(); }; +B<1> b2; + +template<int I> void A<I>::impl() { ++b1.i; ++b2.i; } + +int main() +{ + A<0>().impl(); +} |