https://gcc.gnu.org/bugzilla/show_bug.cgi?id=79163
Bug ID: 79163 Summary: Access-checking not done in template argument list of partial specialization Product: gcc Version: 7.0 Status: UNCONFIRMED Keywords: rejects-valid Severity: normal Priority: P3 Component: c++ Assignee: unassigned at gcc dot gnu.org Reporter: redi at gcc dot gnu.org Blocks: 59002 Target Milestone: --- Access-checking is not done in the template-id of a class template partial specialization, but is done in the body. This breaks the "detection idiom" as used by std::allocator_traits and std::pointer_traits, because the check for whether a substituted type is valid ignores access, and then an invalid type gets used. template<typename> using void_t = void; template<typename T, typename = void> struct Detect { using type = int; }; template<typename T> struct Detect<T, void_t<typename T::type>> { using type = typename T::type; }; class X { using type = long; }; Detect<X>::type i; This should compile, but issues five very similar errors, but using three different locations: access.cc: In instantiation of ‘struct Detect<X>’: access.cc:14:10: required from here access.cc:10:3: error: ‘using type = long int’ is private within this context { using type = typename T::type; }; ^ access.cc:12:28: note: declared private here class X { using type = long; }; ^ access.cc:10:3: error: ‘using type = long int’ is private within this context { using type = typename T::type; }; ^ access.cc:12:28: note: declared private here class X { using type = long; }; ^ access.cc:10:34: error: ‘using type = long int’ is private within this context { using type = typename T::type; }; ^ access.cc:12:28: note: declared private here class X { using type = long; }; ^ access.cc:10:34: error: ‘using type = long int’ is private within this context { using type = typename T::type; }; ^ access.cc:12:28: note: declared private here class X { using type = long; }; ^ access.cc:14:1: error: ‘using type = long int’ is private within this context Detect<X>::type i; ^~~~~~~~~ access.cc:12:28: note: declared private here class X { using type = long; }; ^ Clang compiles this successfully, although EDG fails in the same way as GCC (but only issues one error): "access.cc", line 10: error: type "X::type" (declared at line 12) is inaccessible { using type = typename T::type; }; ^ detected during instantiation of class "Detect<T, void> [with T=X]" at line 14 1 error detected in the compilation of "access.cc". This has some similarities to Bug 40901 but that was fixed in 4.9.0 Referenced Bugs: https://gcc.gnu.org/bugzilla/show_bug.cgi?id=59002 [Bug 59002] [meta-bug] Access checking in templates