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

Reply via email to