diff options
author | Nathan Sidwell <nathan@acm.org> | 2017-12-15 15:04:59 +0000 |
---|---|---|
committer | Nathan Sidwell <nathan@gcc.gnu.org> | 2017-12-15 15:04:59 +0000 |
commit | 0cf4820dd596a5884fb59c2c9874ed100a7ff614 (patch) | |
tree | 599aa3e7811f0d64352939a93b471f1440562272 | |
parent | e7425c18b5af5a12f68bde8b5f30adf02a774536 (diff) | |
download | gcc-0cf4820dd596a5884fb59c2c9874ed100a7ff614.zip gcc-0cf4820dd596a5884fb59c2c9874ed100a7ff614.tar.gz gcc-0cf4820dd596a5884fb59c2c9874ed100a7ff614.tar.bz2 |
[PR C++/59930] template friend classes & default args
https://gcc.gnu.org/ml/gcc-patches/2017-12/msg01055.html
PR c++/59930
* decl.c (xref_tag_1): Correct comments about template friends and
default args.
* friend.c (make_friend_class): Move comments concerning
self-friendliness to code dealing with such.
* pt.c (check_default_tmpl_args): Deal with template friend
classes too.
(push_template_decl_real): Check default args for non-function
template friends.
PR c++/59930
* g++.dg/cpp0x/temp_default4.C: Adjust diagnostic.
* g++.old-deja/g++.pt/friend23.C: Likewise.
* g++.old-deja/g++.pt/friend24.C: Delete.
From-SVN: r255698
-rw-r--r-- | gcc/cp/ChangeLog | 12 | ||||
-rw-r--r-- | gcc/cp/decl.c | 40 | ||||
-rw-r--r-- | gcc/cp/friend.c | 15 | ||||
-rw-r--r-- | gcc/cp/pt.c | 20 | ||||
-rw-r--r-- | gcc/testsuite/ChangeLog | 7 | ||||
-rw-r--r-- | gcc/testsuite/g++.dg/cpp0x/temp_default4.C | 4 | ||||
-rw-r--r-- | gcc/testsuite/g++.old-deja/g++.pt/friend23.C | 11 | ||||
-rw-r--r-- | gcc/testsuite/g++.old-deja/g++.pt/friend24.C | 18 |
8 files changed, 62 insertions, 65 deletions
diff --git a/gcc/cp/ChangeLog b/gcc/cp/ChangeLog index d7a1dde..37c129d 100644 --- a/gcc/cp/ChangeLog +++ b/gcc/cp/ChangeLog @@ -1,3 +1,15 @@ +2017-12-15 Nathan Sidwell <nathan@acm.org> + + PR c++/59930 + * decl.c (xref_tag_1): Correct comments about template friends and + default args. + * friend.c (make_friend_class): Move comments concerning + self-friendliness to code dealing with such. + * pt.c (check_default_tmpl_args): Deal with template friend + classes too. + (push_template_decl_real): Check default args for non-function + template friends. + 2017-12-14 Bernd Edlinger <bernd.edlinger@hotmail.de> * decl2.c (start_static_storage_duration_function): Avoid warning. diff --git a/gcc/cp/decl.c b/gcc/cp/decl.c index 445c23c..63a7b92 100644 --- a/gcc/cp/decl.c +++ b/gcc/cp/decl.c @@ -13538,37 +13538,28 @@ xref_tag_1 (enum tag_types tag_code, tree name, processing a (member) template declaration of a template class, we must be very careful; consider: - template <class X> - struct S1 + template <class X> struct S1 - template <class U> - struct S2 - { template <class V> - friend struct S1; }; + template <class U> struct S2 + { + template <class V> friend struct S1; + }; Here, the S2::S1 declaration should not be confused with the outer declaration. In particular, the inner version should - have a template parameter of level 2, not level 1. This - would be particularly important if the member declaration - were instead: - - template <class V = U> friend struct S1; + have a template parameter of level 2, not level 1. - say, when we should tsubst into `U' when instantiating - S2. On the other hand, when presented with: + On the other hand, when presented with: - template <class T> - struct S1 { - template <class U> - struct S2 {}; - template <class U> - friend struct S2; + template <class T> struct S1 + { + template <class U> struct S2 {}; + template <class U> friend struct S2; }; - we must find the inner binding eventually. We - accomplish this by making sure that the new type we - create to represent this declaration has the right - TYPE_CONTEXT. */ + the friend must find S1::S2 eventually. We accomplish this + by making sure that the new type we create to represent this + declaration has the right TYPE_CONTEXT. */ context = TYPE_CONTEXT (t); t = NULL_TREE; } @@ -13622,9 +13613,10 @@ xref_tag_1 (enum tag_types tag_code, tree name, return error_mark_node; } - /* Make injected friend class visible. */ if (scope != ts_within_enclosing_non_class && TYPE_HIDDEN_P (t)) { + /* This is no longer an invisible friend. Make it + visible. */ tree decl = TYPE_NAME (t); DECL_ANTICIPATED (decl) = false; diff --git a/gcc/cp/friend.c b/gcc/cp/friend.c index ef93bfe..e99ae68 100644 --- a/gcc/cp/friend.c +++ b/gcc/cp/friend.c @@ -283,21 +283,18 @@ make_friend_class (tree type, tree friend_type, bool complain) return; if (friend_depth) - /* If the TYPE is a template then it makes sense for it to be - friends with itself; this means that each instantiation is - friends with all other instantiations. */ { + /* [temp.friend] Friend declarations shall not declare partial + specializations. */ if (CLASS_TYPE_P (friend_type) && CLASSTYPE_TEMPLATE_SPECIALIZATION (friend_type) && uses_template_parms (friend_type)) { - /* [temp.friend] - Friend declarations shall not declare partial - specializations. */ error ("partial specialization %qT declared %<friend%>", friend_type); return; } + if (TYPE_TEMPLATE_INFO (friend_type) && !PRIMARY_TEMPLATE_P (TYPE_TI_TEMPLATE (friend_type))) { @@ -311,7 +308,11 @@ make_friend_class (tree type, tree friend_type, bool complain) return; } } - else if (same_type_p (type, friend_type)) + + /* It makes sense for a template class to be friends with itself, + that means the instantiations can be friendly. Other cases are + not so meaningful. */ + if (!friend_depth && same_type_p (type, friend_type)) { if (complain) warning (0, "class %qT is implicitly friends with itself", diff --git a/gcc/cp/pt.c b/gcc/cp/pt.c index 69b9535..5a6a7cf 100644 --- a/gcc/cp/pt.c +++ b/gcc/cp/pt.c @@ -4980,9 +4980,10 @@ fixed_parameter_pack_p (tree parm) a primary template. IS_PARTIAL is true if DECL is a partial specialization. - IS_FRIEND_DECL is nonzero if DECL is a friend function template - declaration (but not a definition); 1 indicates a declaration, 2 - indicates a redeclaration. When IS_FRIEND_DECL=2, no errors are + IS_FRIEND_DECL is nonzero if DECL is either a non-defining friend + function template declaration or a friend class template + declaration. In the function case, 1 indicates a declaration, 2 + indicates a redeclaration. When IS_FRIEND_DECL=2, no errors are emitted for extraneous default arguments. Returns TRUE if there were no errors found, FALSE otherwise. */ @@ -5130,7 +5131,7 @@ check_default_tmpl_args (tree decl, tree parms, bool is_primary, msg = G_("default template arguments may not be used in function template " "friend re-declaration"); else if (is_friend_decl) - msg = G_("default template arguments may not be used in function template " + msg = G_("default template arguments may not be used in template " "friend declarations"); else if (TREE_CODE (decl) == FUNCTION_DECL && (cxx_dialect == cxx98)) msg = G_("default template arguments may not be used in function templates " @@ -5277,7 +5278,7 @@ push_template_decl_real (tree decl, bool is_friend) is_friend = true; if (is_friend) - /* For a friend, we want the context of the friend function, not + /* For a friend, we want the context of the friend, not the type of which it is a friend. */ ctx = CP_DECL_CONTEXT (decl); else if (CP_DECL_CONTEXT (decl) @@ -5380,9 +5381,12 @@ push_template_decl_real (tree decl, bool is_friend) } /* Check to see that the rules regarding the use of default - arguments are not being violated. */ - check_default_tmpl_args (decl, current_template_parms, - is_primary, is_partial, /*is_friend_decl=*/0); + arguments are not being violated. We check args for a friend + functions when we know whether it's a definition, introducing + declaration or re-declaration. */ + if (!is_friend || TREE_CODE (decl) != FUNCTION_DECL) + check_default_tmpl_args (decl, current_template_parms, + is_primary, is_partial, is_friend); /* Ensure that there are no parameter packs in the type of this declaration that have not been expanded. */ diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog index c87d2cd..2a73f82 100644 --- a/gcc/testsuite/ChangeLog +++ b/gcc/testsuite/ChangeLog @@ -1,3 +1,10 @@ +2017-12-14 Nathan Sidwell <nathan@acm.org> + + PR c++/59930 + * g++.dg/cpp0x/temp_default4.C: Adjust diagnostic. + * g++.old-deja/g++.pt/friend23.C: Likewise. + * g++.old-deja/g++.pt/friend24.C: Delete. + 2017-12-15 Jakub Jelinek <jakub@redhat.com> PR tree-optimization/83269 diff --git a/gcc/testsuite/g++.dg/cpp0x/temp_default4.C b/gcc/testsuite/g++.dg/cpp0x/temp_default4.C index 783ff5b..0dc5854 100644 --- a/gcc/testsuite/g++.dg/cpp0x/temp_default4.C +++ b/gcc/testsuite/g++.dg/cpp0x/temp_default4.C @@ -1,9 +1,9 @@ // { dg-do compile { target c++11 } } class X { - template<typename T = int> friend void f(X) { } + template<typename T = int> friend void f(X) { } // OK template<typename T> friend void g(X); // { dg-message "previously declared here" } - template<typename T = int> friend void h(X); // { dg-error "function template friend" } + template<typename T = int> friend void h(X); // { dg-error "template friend" } }; template<typename T = int> void g(X) // { dg-error "default template argument" } diff --git a/gcc/testsuite/g++.old-deja/g++.pt/friend23.C b/gcc/testsuite/g++.old-deja/g++.pt/friend23.C index 93ce72e..b79a599 100644 --- a/gcc/testsuite/g++.old-deja/g++.pt/friend23.C +++ b/gcc/testsuite/g++.old-deja/g++.pt/friend23.C @@ -1,10 +1,9 @@ -// { dg-do assemble } +// PR 59930 (part) templated class friend declarations cannot have +// default args. -template <class T = int> // { dg-message "note: original definition" } +template <class T> struct S { - template <class U = int> - friend class S; // { dg-error "redefinition of default argument" } + template <class U = int> friend class R; // { dg-error "template friend" } + template <class U = int> friend class S; // { dg-error "template friend" } }; - -template struct S<int>; diff --git a/gcc/testsuite/g++.old-deja/g++.pt/friend24.C b/gcc/testsuite/g++.old-deja/g++.pt/friend24.C deleted file mode 100644 index 5a4116f..0000000 --- a/gcc/testsuite/g++.old-deja/g++.pt/friend24.C +++ /dev/null @@ -1,18 +0,0 @@ -// { dg-do assemble } - -template <class T> -struct S -{ - template <class U = T> - friend class S; - - void f(T); -}; - -template struct S<int>; - -void g() -{ - S<> s; - s.f(3); -} |