From: Patrick Palka Date: Sat, 3 Jun 2023 13:26:43 +0000 (-0400) Subject: c++: is_specialization_of_friend confusion [PR109923] X-Git-Tag: basepoints/gcc-15~8620 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=38af81df6aac11d49f9378d1c628ccc3c815c3ff;p=thirdparty%2Fgcc.git c++: is_specialization_of_friend confusion [PR109923] The check for a non-template member function of a class template in is_specialization_of_friend is overbroad, and accidentally holds for a non-template hidden friend too, which for the testcase below causes the predicate to bogusly return true for decl = void non_templ_friend(A, A) friend_decl = void non_templ_friend(A, A) This patch refines the check appropriately. PR c++/109923 gcc/cp/ChangeLog: * pt.cc (is_specialization_of_friend): Fix overbroad check for a non-template member function of a class template. gcc/testsuite/ChangeLog: * g++.dg/template/friend79.C: New test. --- diff --git a/gcc/cp/pt.cc b/gcc/cp/pt.cc index dae3815f62a9..6b20c58ce666 100644 --- a/gcc/cp/pt.cc +++ b/gcc/cp/pt.cc @@ -1319,6 +1319,7 @@ is_specialization_of_friend (tree decl, tree friend_decl) of a template class, we want to check if DECL is a specialization if this. */ if (TREE_CODE (friend_decl) == FUNCTION_DECL + && DECL_CLASS_SCOPE_P (friend_decl) && DECL_TEMPLATE_INFO (friend_decl) && !DECL_USE_TEMPLATE (friend_decl)) { diff --git a/gcc/testsuite/g++.dg/template/friend79.C b/gcc/testsuite/g++.dg/template/friend79.C new file mode 100644 index 000000000000..7603adf5bead --- /dev/null +++ b/gcc/testsuite/g++.dg/template/friend79.C @@ -0,0 +1,20 @@ +// PR c++/109923 + +template +struct A { +private: + int x; + +public: + A() : x(0) { } + + friend void non_templ_friend(A val, A weird) { + val.x++; // always works + weird.x++; // { dg-error "private" } should only work when T=void + } +}; + +int main() { + non_templ_friend(A(), A()); // { dg-bogus "" } + non_templ_friend(A(), A()); // { dg-message "required from here" } +}