Skip to content
Open
Changes from 3 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
102 changes: 92 additions & 10 deletions abi.html
Original file line number Diff line number Diff line change
Expand Up @@ -4990,14 +4990,52 @@ <h5><a href="#mangle.template-param">5.1.5.8 Template parameters</a></h5>
that is the actual parameter.
</p>

<p>
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:

<pre><code>
template&lt;typename&gt; struct A {
// Type of a is TL0_0_, type of b is T_, type of c is TL0__, type of u is TL1__.
template&lt;typename T&gt; void f(decltype([]&lt;typename U, template&lt;U u&gt; typename&gt;(auto a, T b, U c){})) {}
};
</code></pre>
</p>

<pre><code><font color=blue>
&lt;template-param&gt; ::= T_ # first template parameter
::= T &lt;<i>parameter-2 non-negative</i> <a href="#mangle.number">number</a>&gt; _
&lt;template-param&gt; ::= T_ # L == 0, first parameter
::= T &lt;<i>parameter-2 non-negative</i> <a href="#mangle.number">number</a>&gt; _ # L == 0, second and later parameters
::= TL &lt;<i>L-1 non-negative</i> <a href="#mangle.number">number</a>&gt; __ # L &gt; 0, first parameter
::= TL &lt;<i>L-1 non-negative</i> <a href="#mangle.number">number</a>&gt; _ &lt;<i>parameter-2 non-negative</i> <a href="#mangle.number">number</a>&gt; _ # L &gt; 0, second and later parameters
&lt;<a name="mangle.template-template-param">template-template-param</a>&gt; ::= &lt;<a href="#mangle.template-param">template-param</a>&gt;
::= &lt;<a href="#mangle.substitution">substitution</a>&gt;
</font></code></pre>

<p>
Within a &lt;<a href="#mangle.lambda-sig">lambda-sig</a>&gt;,
explicit template parameter declarations are mangled.
</p>

<a name="mangle.template-param-decl">
<pre><code><font color=blue>
&lt;template-param-decl&gt; ::= Ty # template type parameter
::= Tn &lt;<a href="#mangle.type">type</a>&gt; # template non-type parameter
::= Tt &lt;<a href="#mangle.template-param-decl">template-param-decl</a>&gt;* E # template template parameter
::= Tp &lt;<i>non-pack</i> <a href="#mangle.template-param-decl">template-param-decl</a>&gt; # template parameter pack
</font></code></pre>

<p>
(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.)
</p>

<a name="mangle.function-param">
<h5><a href="#mangle.function-param">5.1.5.9 Function parameter references</a></h5>

Expand Down Expand Up @@ -5208,6 +5246,7 @@ <h4><a href="#expressions">5.1.6 Expressions</a></h4>
::= L &lt;<i>nullptr</i> <a href="#mangle.type">type</a>&gt; E # nullptr literal (i.e., "LDnE")
::= L &lt;<i>pointer</i> <a href="#mangle.type">type</a>&gt; 0 E # null pointer template argument
::= L &lt;<a href="#mangle.type">type</a>&gt; &lt;<i>real-part</i> <a href="#mangle.float">float</a>&gt; _ &lt;<i>imag-part</i> <a href="#mangle.float">float</a>&gt; E # complex floating point literal (C 2000)
::= L &lt;<i>lambda</i> <a href="#mangle.closure-type-name">closure-type-name</a>&gt; E # lambda expression
::= L _Z &lt;<a href="#mangle.encoding">encoding</a>&gt; E # external name

&lt;<a name="mangle.braced-expression">braced-expression</a>&gt; ::= &lt;<a href="#mangle.expression">expression</a>&gt;
Expand All @@ -5227,6 +5266,16 @@ <h4><a href="#expressions">5.1.6 Expressions</a></h4>
(e.g., <code>::x</code>).
</p>

<p>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 &lt;<a href="#mangle.closure-type-name">closure-type-name</a>&gt;,
excluding any name prefix, but including its number within its context.
The context is implied by the remaining portion of the encoding.</p>

<p><code>tl</code> is used for direct-list-initializations, where the type name is directly followed by a braced-init-list; e.g., <code>MyArray{1,2,3}</code> should be mangled <code>tl7MyArrayLi1ELi2ELi3EE</code>. If the braced-init-list is parenthesized, this is not a direct-list-initialization, and it should be mangled with <code>cv</code> and a nested <code>il</code>; for example, <code>MyArray({1,2,3})</code> should be mangled <code>cv7MyArrayilLi1ELi2ELi3EE</code>.</p>

<p>If an implementation supports the full C99 designated initializer syntax (as an extension), a designator list comprising multiple designators results in
Expand Down Expand Up @@ -5521,6 +5570,7 @@ <h4><a href="#closure-types">5.1.8 Closure Types (Lambdas)</a></h4>
<li>default member initializers</li>
<li>the bodies of inline or templated functions</li>
<li>the initializers of inline or templated variables</li>
<li>the remaining contexts in class definitions</li>
</ul>

In all these contexts, the encoding of the closure types builds on an
Expand All @@ -5531,7 +5581,8 @@ <h4><a href="#closure-types">5.1.8 Closure Types (Lambdas)</a></h4>
&lt;<a name="mangle.closure-type-name">closure-type-name</a>&gt; ::= Ul &lt;<a href="#mangle.lambda-sig">lambda-sig</a>&gt; E [ &lt;<i>nonnegative</i> <a href="#mangle.number">number</a>&gt; ] _
</pre></font></code>
with
<pre><code><font color=blue> &lt;<a name="mangle.lambda-sig">lambda-sig</a>&gt; ::= &lt;<i>parameter</i> <a href="#mangle.type">type</a>&gt;+ # Parameter types or "v" if the lambda has no parameters
<pre><code><font color=blue> &lt;<a name="mangle.lambda-sig">lambda-sig</a>&gt; ::= &lt;<i>explicit</i> <a href="#mangle.template-param-decl">template-param-decl</a>&gt;* # Excluding template parameters introduced for <code>auto</code> parameters
&lt;<i>parameter</i> <a href="#mangle.type">type</a>&gt;+ # Parameter types or "v" if the lambda has no parameters
</pre></font></code>
The number is omitted for the first closure type with a given
&lt;<a href="#mangle.lambda-sig">lambda-sig</a>&gt; in a given context; it is n-2 for the nth closure
Expand Down Expand Up @@ -5608,16 +5659,47 @@ <h4><a href="#closure-types">5.1.8 Closure Types (Lambdas)</a></h4>
// Corresponding operator(): _ZNK1SIiE1xMUlvE_clEv
</pre></code>

<p>
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:
<code><pre><font color=blue> &lt;<a href="#mangle.local-name">local-name</a>&gt; ::= Z &lt;<i>class</i> <a href="#mangle.name">name</a>&gt; E &lt;<i>entity</i> <a href="#mangle.name">name</a>&gt;
</font></pre></code>
As above, the <code>&lt;<i>entity</i> <a href="#mangle.name">name</a>&gt;</code> will contain a
<code>&lt;<a href="#mangle.closure-type-name">closure-type-name</a>&gt;</code>,
which is numbered within the class, counting only those closure types for which
this mangling rule applies.
For example:
<code><pre>
struct S {
// Template argument is LZ1SEUlvE_E; f&lt;true&gt; is _ZN1S1fILb1EEEv1XILUlvE_EE
template&lt;bool B&gt; void f(X&lt;[]{ return B; }()&gt;) { ... }
int n = []{ return 0; }(); // not counted towards numbering in struct S
// Template argument is LZ1SEUlvE0_E; f&lt;true&gt; is _ZN1S1fILb1EEEv1XILUlvE0_EE
template&lt;bool B&gt; void f(X&lt;[]{ return !B; }()&gt;) { ... }
};
</pre></code>


<p>
In a generic lambda, uses of <code>auto</code> 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 &lt;<a
href="#mangle.template-param">template-param</a>&gt; in a &lt;<a
href="#mangle.lambda-sig">lambda-sig</a>&gt; 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 of <code>auto</code>)
are encoded as <code>&lt;<a href="#mangle.template-param">template-param</a>&gt;</code>s
with a non-zero level.
</p>

<p>
<img src=warning.gif alt="<b>NOTE</b>:">
<i>
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.
</i>
</p>

<p>
<a name="mangling-compression">
Expand Down