Hello, I searched for bugs related to SFINAE, and I do not think that this one has already reported: ---- #include <type_traits> #include <cstdio> template <typename T, typename = void> struct status : std::false_type{}; template <typename T> struct status<T, decltype(T::member, void())> : std::true_type {}; struct s1{int member;}; struct s2{int _member;}; class c1{int member;}; class c2{int _member;}; int main(){ static_assert(status<s1>::value, "has member"); static_assert(!status<s2>::value, "has no member"); (void) status<c1>::value; //static_assert(status<c1>::value, "has member"); static_assert(!status<c2>::value, "has no member"); } ----- This code compiles fine with msvc and clang, but with g++ it triggers following compiler error: -- bug.cpp: In substitution of ‘template<class T> struct status<T, decltype ((T::member, void()))> [with T = c1]’: bug.cpp:15:19: required from here bug.cpp:6:58: error: ‘int c1::member’ is private within this context template <typename T> struct status<T, decltype(T::member, void())> : std::true_type {}; ~~~~~~~~~^~~~~~~~ bug.cpp:10:14: note: declared private here class c1{int member;}; ^~~~~~ bug.cpp: In instantiation of ‘struct status<c1>’: bug.cpp:15:19: required from here bug.cpp:6:58: error: ‘int c1::member’ is private within this context template <typename T> struct status<T, decltype(T::member, void())> : std::true_type {}; ~~~~~~~~~^~~~~~~~ bug.cpp:10:14: note: declared private here class c1{int member;}; ^~~~~~ bug.cpp:6:58: error: ‘int c1::member’ is private within this context template <typename T> struct status<T, decltype(T::member, void())> : std::true_type {}; ~~~~~~~~~^~~~~~~~ bug.cpp:10:14: note: declared private here class c1{int member;}; -- While the error message could be correct (more on that later), the issue is that because of SFINAE, this should never be compile-error (just like for `s2` and `c2`). I've commented `static_assert(status<c1>::value, "has member");` out, because clang++ compiles `status<c1>::value` to false, while msvc to true. I'm not 100% sure which of the compiler is correct, but `status<c1>::value` should definitively compile.
After researching a little bit more, I've convinced myself that `status<c1>::value` should be false, as `decltype` has no special rules for accessing private data, thus clang is correct. If someone could confirm this, I could try to make a bug report to the msvc team
(In reply to Federico Kircheis from comment #1) > After researching a little bit more, I've convinced myself that > `status<c1>::value` should be false, as `decltype` has no special rules for > accessing private data, thus clang is correct. Agreed. And G++ should accept it.
(In reply to Jonathan Wakely from comment #2) > (In reply to Federico Kircheis from comment #1) > > After researching a little bit more, I've convinced myself that > > `status<c1>::value` should be false, as `decltype` has no special rules for > > accessing private data, thus clang is correct. > > Agreed. And G++ should accept it. Thank you. Sorry if linking to external bug trackers in comments is bad practice, but I did not saw any rule about it. Since it could be interesting for those having this issue, here is the bug report for MSVC: https://developercommunity.visualstudio.com/content/problem/607019/incorrect-decltype-on-non-public-member-variables.html
(In reply to Federico Kircheis from comment #3) > Sorry if linking to external bug trackers in comments is bad practice, but I > did not saw any rule about it. There's no rule against it, it's useful. > Since it could be interesting for those having this issue, here is the bug > report for MSVC: > > https://developercommunity.visualstudio.com/content/problem/607019/incorrect- > decltype-on-non-public-member-variables.html Thanks.
The master branch has been updated by Patrick Palka <ppalka@gcc.gnu.org>: https://gcc.gnu.org/g:4f6c1ca287d2c64856ef67fa50bc462633d5b8cf commit r11-21-g4f6c1ca287d2c64856ef67fa50bc462633d5b8cf Author: Patrick Palka <ppalka@redhat.com> Date: Fri May 1 16:18:19 2020 -0400 c++: Missing SFINAE with inaccessible static data member [PR90880] This is a missing SFINAE issue when verifying the accessibility of a static data member. The cause is that check_accessibility_of_qualified_id unconditionally passes tf_warning_or_error to perform_or_defer_access_check, even when called from tsubst_qualified_id(..., complain=tf_none). This patch fixes this by plumbing 'complain' from tsubst_qualified_id through check_accessibility_of_qualified_id to reach perform_or_defer_access_check, and by giving check_accessibility_of_qualified_id the appropriate return value. gcc/cp/ChangeLog: PR c++/90880 * cp-tree.h (check_accessibility_of_qualified_id): Add tsubst_flags_t parameter and change return type to bool. * parser.c (cp_parser_lookup_name): Pass tf_warning_to_error to check_accessibility_of_qualified_id. * pt.c (tsubst_qualified_id): Return error_mark_node if check_accessibility_of_qualified_id returns false. * semantics.c (check_accessibility_of_qualified_id): Add complain parameter. Pass complain instead of tf_warning_or_error to perform_or_defer_access_check. Return true unless perform_or_defer_access_check returns false. gcc/testsuite/ChangeLog: PR c++/90880 * g++.dg/template/sfinae29.C: New test.
Fixed for GCC 11.