itanium-cxx-abi / cxx-abi

C++ ABI Summary
508 stars 96 forks source link

mangling for dual nature of *injected-class-name* as a template argument #185

Open zygoloid opened 5 months ago

zygoloid commented 5 months ago

An injected-class-name as a template argument is weird: it can be used as an argument for both a template template parameter and a type template parameter. For example:

template<typename U>
class A {
    template<typename T> using X = T::template apply<A>;
    template<typename T> using Y = T::template apply<::A>;
    template<typename T> using Z = T::template apply<A<U>>;

    template<typename T> X<T> f() {}
    template<typename T> Y<T> f() {}
    template<typename T> Z<T> f() {}
};

The first f accepts types T that have a member template that takes either a type or a template. The second f accepts types T that have a member template that takes a template. The third f accepts types T that have a member template that takes a type.

These are three different constraints, so we need three different manglings, but we seem to only have two.

For now, GCC and Clang at least both reject -- Clang thinks the third f redeclares the first, and GCC says they're different but can't be overloaded. EDG accepts the overloads, but rejects a call to the first f with an apply that takes a template. EDG mangles the first and third overloads the same, despite considering them to be different.