sdkrystian wrote: Another example using class templates: ```cpp template<int N> struct A { template<typename T> struct B; };
template<> template<typename T> struct A<0>::B : A<1>::B<T> { }; template<> template<typename T> struct A<1>::B { static constexpr bool x = true; }; static_assert(A<0>::B<int>::x); // error: implicit instantiation of undefined template 'A<1>::B<int>' ``` This currently results in a crash on trunk. With this patch applied, we instantiate the undefined class template declared in the definition of `A` and complain. These differences in behavior arise from the fact that we bind names to the most recent redeclaration of an entity when creating `Expr` nodes that refer to that entity. In the above example, the explicit specialization of `A<1>::B` is declared after it is referenced in the explicit specialization of `A<0>::B`, resulting in the initial declaration being used to instantiate `B<int>`. IMO this behavior is correct per [[temp.expl.spec] p7](http://eel.is/c++draft/temp.expl.spec#7): > If a template, a member template or a member of a class template is > explicitly specialized, a declaration of that specialization shall be > reachable from every use of that specialization that would cause an implicit > instantiation to take place, in every translation unit in which such a use > occurs; no diagnostic is required. However, I would like to know what @erichkeane, @mizvekov, and @zygoloid think. In any case, the QT example can be fixed by reordering the explicit specialization such that each specialization is declared before being referenced. https://github.com/llvm/llvm-project/pull/106585 _______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits