[Bug c++/58993] incorrectly accept access of protected member method from derived class template
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=58993 Patrick Palka changed: What|Removed |Added CC||csaba_22 at yahoo dot co.uk --- Comment #12 from Patrick Palka --- *** Bug 105752 has been marked as a duplicate of this bug. ***
[Bug c++/58993] incorrectly accept access of protected member method from derived class template
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=58993 --- Comment #11 from CVS Commits --- The master branch has been updated by Jason Merrill : https://gcc.gnu.org/g:4df735e01e319997841574f353d2aa076a0335c2 commit r13-465-g4df735e01e319997841574f353d2aa076a0335c2 Author: Jason Merrill Date: Fri Mar 18 22:52:32 2022 -0400 c++: hidden friend access [DR1699] It has come up several times that Clang considers hidden friends of a class to be sufficiently memberly to be covered by a friend declaration naming the class. This is somewhat unclear in the standard: [class.friend] says "Declaring a class to be a friend implies that private and protected members of the class granting friendship can be named in the base-specifiers and member declarations of the befriended class." A hidden friend is a syntactic member-declaration, but is it a "member declaration"? CWG was ambivalent, and referred the question to EWG as a design choice. But recently Patrick mentioned that the current G++ choice not to treat it as a "member declaration" was making his library work significantly more cumbersome, so let's go ahead and vote the other way. This means that the testcases for 100502 and 58993 are now accepted. DR1699 PR c++/100502 PR c++/58993 gcc/cp/ChangeLog: * friend.cc (is_friend): Hidden friends count as members. * search.cc (friend_accessible_p): Likewise. gcc/testsuite/ChangeLog: * g++.dg/template/access37.C: Now OK. * g++.dg/template/friend69.C: Now OK. * g++.dg/lookup/friend23.C: New test.
[Bug c++/58993] incorrectly accept access of protected member method from derived class template
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=58993 Patrick Palka changed: What|Removed |Added Target Milestone|--- |11.0 Resolution|--- |FIXED Status|ASSIGNED|RESOLVED --- Comment #10 from Patrick Palka --- Fixed for GCC 11.
[Bug c++/58993] incorrectly accept access of protected member method from derived class template
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=58993 --- Comment #9 from CVS Commits --- The master branch has been updated by Patrick Palka : https://gcc.gnu.org/g:29853c653245c37ed31b6abcc9799b534372e938 commit r11-6800-g29853c653245c37ed31b6abcc9799b534372e938 Author: Patrick Palka Date: Tue Jan 19 16:20:00 2021 -0500 c++: Always check access during late-parsing of members [PR58993] This patch removes a vestigial use of dk_no_check from cp_parser_late_parsing_for_member, which ideally should have been removed as part of the PR41437 patch that improved access checking inside templates. This allows us to correctly reject f1 and f2 in the testcase access34.C below (whereas before we'd only reject f3). Additional testing revealed a new access issue when late-parsing a hidden friend within a class template. In the testcase friend68.C below, we're tripping over the checking assert from friend_accessible_p(f, S::j, S, S) during lookup of j in x.j (for which type_dependent_object_expression_p returns false, which is why we're doing the lookup at parse time). The reason for the assert failure is that DECL_FRIENDLIST(S) contains f but DECL_BEFRIENDING_CLASSES(f) is empty, and so friend_accessible_p (which looks at DECL_BEFRIENDING_CLASSES) wants to return false, but is_friend (which looks at DECL_FRIENDLIST) returns true. For sake of symmetry one would expect that DECL_BEFRIENDING_CLASSES(f) contains S, but add_friend avoids updating DECL_BEFRIENDING_CLASSES when the class type (S in this case) is dependent, for some reason. This patch works around this issue by making friend_accessible_p consider the DECL_FRIEND_CONTEXT of the access scope. Thus we sidestep the DECL_BEFRIENDING_CLASSES / DECL_FRIENDLIST asymmetry issue while correctly validating the x.j access at parse time. A earlier version of this patch checked friend_accessible_p instead of protected_accessible_p in the DECL_FRIEND_CONTEXT hunk below, but this had the side effect of making us accept the ill-formed testcase friend69.C below (ill-formed because the hidden friend g is not actually a member of A, so g doesn't have access to B's members despite B befriending A). gcc/cp/ChangeLog: PR c++/41437 PR c++/58993 * search.c (friend_accessible_p): If scope is a hidden friend defined inside a dependent class, consider access from the class. * parser.c (cp_parser_late_parsing_for_member): Don't push a dk_no_check access state. gcc/testsuite/ChangeLog: PR c++/41437 PR c++/58993 * g++.dg/opt/pr87974.C: Adjust. * g++.dg/template/access34.C: New test. * g++.dg/template/friend68.C: New test. * g++.dg/template/friend69.C: New test.
[Bug c++/58993] incorrectly accept access of protected member method from derived class template
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=58993 Patrick Palka changed: What|Removed |Added CC||ppalka at gcc dot gnu.org Status|NEW |ASSIGNED Assignee|unassigned at gcc dot gnu.org |ppalka at gcc dot gnu.org --- Comment #8 from Patrick Palka --- (In reply to Jonathan Wakely from comment #5) > Warning-free testcase: > > class base { > private: > void foo() { } > }; > > template > struct bar : public base { > void test() { > (void) ::foo; // should be rejected > } > }; > > template <> > struct bar : public base { > void test() { > // ::foo; // correctly rejected > } > }; > > int main() { > bar().test(); > bar().test(); > } > > Still accepted by trunk. > > > Clang says: > > 58993.cc:9:23: error: 'foo' is a private member of 'base' > (void) ::foo; // should be rejected > ^ > 58993.cc:3:10: note: declared private here > void foo() { } > ^ > 1 error generated. > > > and EDG says: > > "58993.cc", line 9: error: function "base::foo" (declared at line 3) is > inaccessible > (void) ::foo; // should be rejected > ^ > detected during instantiation of "void bar::test() [with T=int]" > at line 21 > > 1 error detected in the compilation of "58993.cc". With GCC 11 (after the PR41437 patch), we reject the first access only if bar::test() is defined out-of-line: class base { private: int foo() { } }; template struct bar : public base { void test(); }; template void bar::test() { ::foo; } int main() { bar().test(); } Investigating.
[Bug c++/58993] incorrectly accept access of protected member method from derived class template
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=58993 dennis at felsin9 dot de changed: What|Removed |Added CC||dennis at felsin9 dot de --- Comment #7 from dennis at felsin9 dot de --- Another example, no warnings in G++ 9.1.0, fails in Clang++ as expected: class C { struct Print { const class C& c; }; }; template struct D : public C { void create() { [[maybe_unused]] C::Print p{*this}; } }; int main() { D d; d.create(); }
[Bug c++/58993] incorrectly accept access of protected member method from derived class template
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=58993 Jonathan Wakely changed: What|Removed |Added CC||achuah at drwsg dot com --- Comment #6 from Jonathan Wakely --- *** Bug 85943 has been marked as a duplicate of this bug. ***
[Bug c++/58993] incorrectly accept access of protected member method from derived class template
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=58993 Jonathan Wakely changed: What|Removed |Added Last reconfirmed|2013-11-05 00:00:00 |2018-2-27 --- Comment #5 from Jonathan Wakely --- Warning-free testcase: class base { private: void foo() { } }; template struct bar : public base { void test() { (void) ::foo; // should be rejected } }; template <> struct bar : public base { void test() { // ::foo; // correctly rejected } }; int main() { bar().test(); bar().test(); } Still accepted by trunk. Clang says: 58993.cc:9:23: error: 'foo' is a private member of 'base' (void) ::foo; // should be rejected ^ 58993.cc:3:10: note: declared private here void foo() { } ^ 1 error generated. and EDG says: "58993.cc", line 9: error: function "base::foo" (declared at line 3) is inaccessible (void) ::foo; // should be rejected ^ detected during instantiation of "void bar::test() [with T=int]" at line 21 1 error detected in the compilation of "58993.cc".
[Bug c++/58993] incorrectly accept access of protected member method from derived class template
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=58993 Jonathan Wakely changed: What|Removed |Added CC||albin.olsson at volvocars dot com --- Comment #4 from Jonathan Wakely --- *** Bug 77368 has been marked as a duplicate of this bug. ***
[Bug c++/58993] incorrectly accept access of protected member method from derived class template
http://gcc.gnu.org/bugzilla/show_bug.cgi?id=58993 Jonathan Wakely redi at gcc dot gnu.org changed: What|Removed |Added Keywords||accepts-invalid Status|UNCONFIRMED |NEW Last reconfirmed||2013-11-05 Blocks||59002 Summary|failure to access pointer |incorrectly accept access |to protected member method |of protected member method |in base from derived class |from derived class template |specialization | Ever confirmed|0 |1 --- Comment #2 from Jonathan Wakely redi at gcc dot gnu.org --- Reduced test, where the base member is private, but the primary template can still access it class base { private: int foo() { } }; template typename T struct bar : public base { void test() { base::foo; // should be rejected } }; template struct barvoid : public base { void test() { // base::foo; // correctly rejected } }; int main() { barint().test(); barvoid().test(); }
[Bug c++/58993] incorrectly accept access of protected member method from derived class template
http://gcc.gnu.org/bugzilla/show_bug.cgi?id=58993 --- Comment #3 from Chris Studholme cvs at cs dot utoronto.ca --- Ah, thanks for the info. I thought I tried 'bar::foo' and it didn't work without 'using base::foo'. I just tried it again and it does work (in both cases) without the using declaration so I must have made some other mistake earlier.