-
Notifications
You must be signed in to change notification settings - Fork 100
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
Dp
apparently 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.