-
Notifications
You must be signed in to change notification settings - Fork 102
Description
Example:
template<typename T> struct X { X(T f) { f(0); } template<typename ...U> void operator()(U...); };
template<typename T> void f(T&&) { X{[](auto &&, auto...){}}(); }
void g() { f(0); }
GCC, Clang, and EDG agree that the operator() mangling comes out as _ZN1XIZ1fIiEvOT_EUlS2_DpT0_E_EclIJEEEvDpT_, which no-one can demangle. At least three different things go wrong here:
-
The
OT_referring to the first parameter in the lambda-sig got rewritten to a substitutionS2_. This completely breaks LLVM's demangling strategy, which rewrites template parameters (and substitutions) to the corresponding type as they're parsed, and so has no way to even represent a substitution that might mean two completely different things in different contexts, as happens here. -
The
Dpapparently confuses GCC's demangler, leaving it unable to see thatT0_meansauto. -
The (hidden by substitution)
T_andT0_appear in a context where there is a level of template parameters in scope already. That confuses LLVM's demangler (but that seems like a comparatively straightforward bug).
My focus here is problem 1: allowing references to the lambda's implicit template parameter to be rewritten as a substitution referring to f's template parameter seems problematic. It's not clear whether the rules intend that, but it's at least what three different compilers do. That choice means that we can't expand substitutions as we parse during demangling -- we must preserve the original form of the substitution string and re-process it, because a T_ appearing within it can mean different things for different uses of the same substitution.
Perhaps distinct template parameters should never be considered the same for the purpose of forming substitutions, even if they have the same depth and index.