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

Reply via email to