Bug 90880 - compile error instead of SFINAE with non-public member variables
Summary: compile error instead of SFINAE with non-public member variables
Status: NEW
Alias: None
Product: gcc
Classification: Unclassified
Component: c++ (show other bugs)
Version: 9.1.0
: P3 normal
Target Milestone: ---
Assignee: Not yet assigned to anyone
URL:
Keywords: rejects-valid
Depends on:
Blocks:
 
Reported: 2019-06-13 23:22 UTC by Federico Kircheis
Modified: 2019-06-15 15:59 UTC (History)
1 user (show)

See Also:
Host:
Target:
Build:
Known to work:
Known to fail:
Last reconfirmed: 2019-06-13 00:00:00


Attachments

Note You need to log in before you can comment on or make changes to this bug.
Description Federico Kircheis 2019-06-13 23:22:39 UTC
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.
Comment 1 Federico Kircheis 2019-06-13 23:54:13 UTC
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
Comment 2 Jonathan Wakely 2019-06-13 23:59:15 UTC
(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.
Comment 3 Federico Kircheis 2019-06-14 00:31:06 UTC
(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
Comment 4 Jonathan Wakely 2019-06-14 07:59:26 UTC
(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.