On Mon, 8 Dec 2025 at 08:42, Andrew Pinski via Gcc <[email protected]> wrote:
>
> On Sun, Dec 7, 2025 at 7:56 AM Andrey Tarasevich via Gcc
> <[email protected]> wrote:
> >
> > I'm curious about the following specific context: referring to a member type
> > (supposedly, an injected class name) through a dependent type name with a
> > `typename` keyword
> >
> >   struct S {};
> >
> >   template <typename T> void foo() {
> >     typename T::S s; // <-- this
> >   }
> >
> >   int main() {
> >     foo<S>();
> >   }
> >
> > GCC quietly accepts the declaration inside `foo` (even with `-pedantic`), 
> > i.e.
> > it treats `T::S` as a reference to the injected class name. Clang issues the
> > following diagnostic
> >
> >   warning: ISO C++ specifies that qualified reference to 'S' is a 
> > constructor
> >     name rather than a type in this context, despite preceding 'typename' 
> > keyword
> >     [-Winjected-class-name]
> >
> > which expectedly turns into an error in `-pedantic-errors` mode.
> >
> > Is Clang correct in this case? (Considering how elaborate and specific its
> > message is.)
> >
> > Note that the dilemma arises only when the actual argument is a type named 
> > `S`.
> > If a differently named type is passed as `T` (which just happens to have 
> > `S` as
> > a member type), both compilers accept the code (see the example below). This
> > distinction is what tempted me to test this context in the first place, and 
> > what
> > leads me to believe that Clang's behavior is "weird" (even if correct).
> >
> > The difference can be converted to something more tangible by exploiting it 
> > for
> > SFINAE purposes, e.g.
> >
> >   #include <iostream>
> >
> >   struct A { using B = int; };
> >   struct B {};
> >   struct C {};
> >
> >   template <typename T> void foo(int, typename T::B * = 0) {
> >     std::cout << "Hello World" << std::endl;
> >   }
> >
> >   template <typename T> void foo(...) {
> >     std::cout << "Goodbye World" << std::endl;
> >   }
> >
> >   int main() {
> >     foo<A>(0);
> >     foo<B>(0); // GCC vs Clang?
> >     foo<C>(0);
> >   }
>
> I don't know but here is a summary of the compilers I tried:
> GCC: 2 hello worlds
> clang: 2 goodbye worlds
> EDG: 2 goodbye worlds
> MSVC: 2 hello worlds.
>
> There are a few C++ defect reports in this area even.
> https://cplusplus.github.io/CWG/issues/1310.html
> and
> https://cplusplus.github.io/CWG/issues/318.html
>
> From my understanding (but I could still be wrong), GCC and MSVC are
> correct. because typename should cause the "function names" to be
> ignored (a nested-name-specifier).
> The reason why I could be wrong is clang marks as implementing DR 1310
> while GCC marks as unknown if it implements DR 1310.
> There could be still another reason why the injected name is the
> naming the constructor that I don't understand either.

I don't think GCC implements CWG 1310, and I think that's why GCC
gives the wrong answer.

This is https://gcc.gnu.org/bugzilla/show_bug.cgi?id=34810

Reply via email to