https://gcc.gnu.org/bugzilla/show_bug.cgi?id=61732
--- Comment #3 from Jonathan Wakely <redi at gcc dot gnu.org> --- (In reply to Joaquín M López Muñoz from comment #2) > Umm... This is not how I read [class]/3 (no mention to instances there). That refers to classes. in Your original example derived is not a class, it's a class template. It becomes a class when instantiated, but you never instantiate it. > And, moreover, if your interpretation was right then the following should > compile too: > > struct X final{}; > > struct derived:X{}; > > void foo(derived*){} > > int main() > { > foo(0); > } > > but GCC, here, does complain that derived can't derive from X. But there are no templates to be instantiated there. The definition of derived is ill-formed, period. In your original example the definition of derived is only ill-formed if the base class is final, and base classes are only checked when the template is instantiated (because there could be an explicit specialization later in the translation unit that doesn't derive from the template argument, making derived<X> well-formed). [temp.arg]/6 "If the use of a template-argument gives rise to an ill-formed construct in the instantiation of a template specialization, the program is ill-formed." N.B. "in the instantiation" not earlier. [temp.inst] says when the point of instantiation is, and your program doesn't instantiate derived<X>. FWIW clang and EDG accept your first example too.