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
