7

GCC (8.3, 9.1), Clang (7, 8) and MSVC (19.20) differ is their ability to compile this code:

struct C;

template<typename T> struct S {
    void foo() {
        // C2 c;
        C c;
    }
};

class C {};

int main() {
    S<int> s;
    s.foo();
    return 0;
}

GCC and MSVC accept it, whereas Clang rejects it. Clang rejects it even if I make foo itself a template and/or do not call it at all.

My understanding is that foo is not instantiated unless it is called, and it is instantiated at the point where it is called. At that point C is complete, and the code should compile. Is this a reasoning of GCC?

As a side note, if foo is not called, MSVC accepts the code even if I replace C with an undeclared C2 inside foo - in this case it seems to just check the function body to be syntactically correct.

Which behaviour is correct according to the Standard? If it is Clang's, why does the Standard forbids the flexibility that GCC gives?

Evg
  • 25,259
  • 5
  • 41
  • 83
  • 1
    I believe the rational is that compilers are allowed to diagnose templates. If you write something nonsensical that can never work you should immediately get an error, not when instantiating. Unfortunately that makes various useful constructs like `static_assert(false);` ill-formed. – nwp May 07 '19 at 14:54
  • 1
    Near duplicate of [When does overload resolution of non-dependent name take place…](https://stackoverflow.com/questions/34154770/when-does-overload-resolution-of-non-dependent-name-take-place-in-definition-co), although it would have been hard to tell without the necessary terminology for the search. – Arne Vogel May 08 '19 at 08:11

1 Answers1

12

This is ill-formed, no diagnostic required, due to [temp.res]/8:

The program is ill-formed, no diagnostic required, if:

  • [...]
  • a hypothetical instantiation of a template immediately following its definition would be ill-formed due to a construct that does not depend on a template parameter, or [...]
  • [...]

So the whole program is bad, but implementations aren't required to diagnose it. Clang does, which is good for clang, gcc and MSVC don't, which isn't wrong.

Barry
  • 286,269
  • 29
  • 621
  • 977
  • The *reason* is that Clang remembers which *declarations* the template sees, while GCC remembers only which *entities* were found. – Davis Herring May 30 '19 at 22:48