From 3ebf3e64c51b6c703621ebc39fc3af9e1f644557 Mon Sep 17 00:00:00 2001
From: Richard Smith 5.1.5.8 Template parameters
that is the actual parameter.
+Let L be the number of template parameter scopes enclosing the +template parameter scope in which the parameter is declared, +excluding any template parameter scopes whose template arguments +have already been substituted into the type or expression being mangled. +Typically L will be zero, but can be nonzero when a generic lambda +occurs within the signature of a function template or when mangling +a template template parameter declaration. For example: + +
+ template<typename> struct A {
+ // Type of a is TL0_0_, type of b is T_, type of c is TL0__, type of u is TL1__.
+ template<typename T> void f(decltype([]<typename U, template<U u> typename>(auto a, T b, U c){})) {}
+ };
+
+
+
- <template-param> ::= T_ # first template parameter
- ::= T <parameter-2 non-negative number> _
+ <template-param> ::= T_ # L == 0, first parameter
+ ::= T <parameter-2 non-negative number> _ # L == 0, second and later parameters
+ ::= TL <L-1 non-negative number> __ # L > 0, first parameter
+ ::= TL <L-1 non-negative number> _ <parameter-2 non-negative number> _ # L > 0, second and later parameters
<template-template-param> ::= <template-param>
::= <substitution>
+
+
++Within a <lambda-sig>, +explicit template parameter declarations are mangled. +
+ +
+ <template-param-decl> ::= Ty # template type parameter
+ ::= Tn <type> # template non-type parameter
+ ::= Tt <template-param-decl>* E # template template parameter
+ ::= Tp <non-pack template-param-decl> # template parameter pack
++(Note: the intent is to eventually use these template parameter +manglings more broadly, to distinguish between function templates +that are overloaded on template parameters but that are otherwise +indistinguishable.) +
++<lambda-sig> ::= <parameter type>+ # Parameter types or "v" if the lambda has no parameters +
The number is omitted for the first closure type with a given <lambda-sig> in a given context; it is n-2 for the nth closure @@ -5611,13 +5650,22 @@<lambda-sig> ::= <explicit template-param-decl>* # Excluding template parameters introduced for
auto
parameters + <parameter type>+ # Parameter types or "v" if the lambda has no parameters5.1.8 Closure Types (Lambdas)
In a generic lambda, uses of
+ +auto
in the parameter list are mangled as the corresponding artificial template type parameter. -This is never ambiguous with a lambda parameter whose type is an -enclosing template type parameter, because lambdas are never mangled -in a dependent context (they are forbidden from appearing in function -signatures). A <template-param> in a <lambda-sig> can only ever refer to a -template parameter of a generic lambda. +If a generic lambda appears in a dependent context (for example, in +the signature of a function template), references to its template +parameters (including those introduced by uses ofauto
) +are encoded as<template-param>
s +with a non-zero level. ++
+ +A non-member function template whose signature contains a lambda-expression can +never redeclare a function template declared in a different translation unit. +Implementations must ensure that such symbols are not linked together across +translation units, perhaps by giving affected symbols internal linkage. + +
From d87d707357d649d8a407fa289c6e95d6e18f6c8c Mon Sep 17 00:00:00 2001 From: Richard Smith
+Date: Fri, 6 Sep 2019 15:24:00 -0700 Subject: [PATCH 2/5] Add a mangling for lambda-expressions (which can now appear in unevaluated operands and therefore in function signatures). --- abi.html | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/abi.html b/abi.html index a9439ff3..ea65b86f 100644 --- a/abi.html +++ b/abi.html @@ -5246,6 +5246,7 @@ 5.1.6 Expressions
::= L <nullptr type> E # nullptr literal (i.e., "LDnE") ::= L <pointer type> 0 E # null pointer template argument ::= L <type> <real-part float> _ <imag-part float> E # complex floating point literal (C 2000) + ::= L <lambda closure-type-name> E # lambda expression ::= L _Z <encoding> E # external name <braced-expression> ::= <expression> @@ -5265,6 +5266,16 @@5.1.6 Expressions
(e.g.,::x
).When a lambda expression appears in the type of a function template at namespace scope, +that function template cannot be redeclared in other translation units, +so this ABI does not constrain its mangling except that it cannot collide +with symbols in other translation units. +When a lambda expression appears in an instantiation-dependent expression +in other contexts (for example, in the signature of a function template at class scope), +it is mangled as a <closure-type-name>, +excluding any name prefix, but including its number within its context. +The context is implied by the remaining portion of the encoding.
+
tl
is used for direct-list-initializations, where the type name is directly followed by a braced-init-list; e.g.,MyArray{1,2,3}
should be mangledtl7MyArrayLi1ELi2ELi3EE
. If the braced-init-list is parenthesized, this is not a direct-list-initialization, and it should be mangled withcv
and a nestedil
; for example,MyArray({1,2,3})
should be mangledcv7MyArrayilLi1ELi2ELi3EE
.If an implementation supports the full C99 designated initializer syntax (as an extension), a designator list comprising multiple designators results in From 9618b59f28475fa2959481ea5b44df39263f0dbd Mon Sep 17 00:00:00 2001 From: Richard Smith
Date: Fri, 6 Sep 2019 19:09:14 -0700 Subject: [PATCH 3/5] Add numbering rule for lambdas in class bodies outside of default arguments and default member initializers. --- abi.html | 23 +++++++++++++++++++++++ 1 file changed, 23 insertions(+) diff --git a/abi.html b/abi.html index ea65b86f..6a2922fd 100644 --- a/abi.html +++ b/abi.html @@ -5570,6 +5570,7 @@ 5.1.8 Closure Types (Lambdas)
default member initializers the bodies of inline or templated functions the initializers of inline or templated variables +the remaining contexts in class definitions In all these contexts, the encoding of the closure types builds on an @@ -5658,6 +5659,28 @@5.1.8 Closure Types (Lambdas)
// Corresponding operator(): _ZNK1SIiE1xMUlvE_clEv
+If the context is within a class definition,
+and not within one of the above more specific cases,
+the closure class and its members are encoded as follows:
+
+As above, the <local-name> ::= Z <class name> E <entity name>
+
<entity name>
will contain a
+<closure-type-name>
,
+which is numbered within the class, counting only those closure types for which
+this mangling rule applies.
+For example:
+
+
+
+ struct S {
+ // Template argument is LZ1SEUlvE_E; f<true> is _ZN1S1fILb1EEEv1XILUlvE_EE
+ template<bool B> void f(X<[]{ return B; }()>) { ... }
+ int n = []{ return 0; }(); // not counted towards numbering in struct S
+ // Template argument is LZ1SEUlvE0_E; f<true> is _ZN1S1fILb1EEEv1XILUlvE0_EE
+ template<bool B> void f(X<[]{ return !B; }()>) { ... }
+ };
+
In a generic lambda, uses of auto
in the parameter list
are mangled as the corresponding artificial template type parameter.
From 36bc62b8479244981b51629770b4c6f4b1715f3d Mon Sep 17 00:00:00 2001
From: Richard Smith 5.1.8 Closure Types (Lambdas)
5.1.8 Closure Types (Lambdas)
template<bool B> void f(X<[]{ return !B; }()>) { ... }
};
+
+When a lambda appears in the declaration portion of a function template,
+it is numbered within the enclosing context when determining
+the mangling of the function template and its instantiations.
+Similarly, when a lambda appears in the declaration portion
+of a non-template variable or function,
+it is numbered within the enclosing context.
+However, when a function or variable template is instantiated,
+all lambdas produced by that instantiation,
+including those in the declaration portion,
+are numbered within the resulting instantiated function or variable
+as part of the same numbering sequence as lambdas appearing
+in the function definition or variable initializer.
+For example:
+
+
+ struct S {
+ // S::f<int, int> is _ZN1S1fIJiiEEEv1XIJXspLUlvE_EEEE
+ // The lambda call operators for the two lambdas are
+ // _ZZN1S1fIJiiEEEv1XIJXspLUlvE_EEEEENKUlvE_clEi and
+ // _ZZN1S1fIJiiEEEv1XIJXspLUlvE_EEEEENKUlvE0_clEi,
+ // and numbering of lambdas with a <lambda-sig> of v
+ // within the body starts at UlvE1_.
+ template<typename ...T> void f(X<[]{ static T n; return &n; }...>) { ... }
+ };
+