Skip to content

Commit ac0c286

Browse files
authored
Merge pull request #57 from zygoloid/anon-numbering
Describe the interaction of lexical ordering, pack expansion, and if constexpr.
2 parents 9504480 + 3a1080b commit ac0c286

File tree

1 file changed

+100
-19
lines changed

1 file changed

+100
-19
lines changed

abi.html

Lines changed: 100 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -4914,7 +4914,8 @@ <h5><a href="#mangling.named">5.1.5.5 Class, union, and enum types</a></h5>
49144914
</pre></font></code>
49154915

49164916
The number is omitted for the first unnamed type in the class; it is
4917-
n-2 for the nth unnamed type (in lexical order) otherwise.
4917+
n-2 for the nth unnamed type (in <a href="#lexical-ordering">lexical order</a>)
4918+
otherwise.
49184919
<p>
49194920
(The mangling of such unnamed types defined in namespace scope is
49204921
generally unspecified because they do not have to match across
@@ -5391,7 +5392,8 @@ <h4><a href="#mangling-scope">5.1.7 Scope Encoding</a></h4>
53915392
within a function if they are declared in different scopes. In this
53925393
case, a discriminator must be added to the
53935394
&lt;<a href="#mangle.local-name">local-name</a>&gt;. Entities with
5394-
the same "top-level" name are numbered in lexical order within
5395+
the same "top-level" name are numbered in
5396+
<a href="#lexical-ordering">lexical order</a> within
53955397
the function definition. A discriminator is added only for the second
53965398
and later occurrences of the same name, and so the
53975399
&lt;<a href="#mangle.number">number</a>&gt; in the discriminator
@@ -5412,8 +5414,8 @@ <h4><a href="#mangling-scope">5.1.7 Scope Encoding</a></h4>
54125414
</pre></font></code>
54135415

54145416
where the number is is omitted for the first unnamed type in the
5415-
function, and <i>n</i>-2 for the <i>n</i>th unnamed type (in lexical
5416-
order) otherwise.
5417+
function, and <i>n</i>-2 for the <i>n</i>th unnamed type
5418+
(in <a href="#lexical-ordering">lexical order</a>) otherwise.
54175419

54185420
<p>
54195421
For example:
@@ -5445,25 +5447,14 @@ <h4><a href="#mangling-scope">5.1.7 Scope Encoding</a></h4>
54455447
is used for string literals. The discriminator is used only if there
54465448
is more than one, for the second and subsequent ones. In this case
54475449
again &lt;<a href="#mangle.number">number</a>&gt; is <i>n</i>-2 for
5448-
the <i>n</i>th distinct string literal, in lexical order, appearing in
5450+
the <i>n</i>th distinct string literal, in
5451+
<a href="#lexical-ordering">lexical order</a>, appearing in
54495452
the function. Multiple references to the same string literal produce
54505453
one string object with one name in the sequence. <i>Note that this
54515454
assumes that the same string literal occurring twice in a given
54525455
function in fact represents a single entity, i.e. has a unique
54535456
address.</i>
54545457

5455-
<p>
5456-
In all cases, the numbering order is strictly lexical order based on
5457-
the original token sequence. All entities occurring in that sequence
5458-
are to be numbered, even if subsequent optimization makes some of them
5459-
unnecessary. The ordering of literals appearing in a
5460-
mem-initializer-list shall be the order that the literals appear in
5461-
the source, which may be different from the order in which the
5462-
initializers will be executed when the program runs. It is expected
5463-
that this will be the 'natural' order in most compilers. In any case,
5464-
conflicts would arise only if different compilation units including
5465-
the same code were compiled by different compilers.
5466-
54675458
<p>
54685459
For entities in constructors and destructors, the mangling of the
54695460
complete object constructor or destructor is used as the base function
@@ -5536,7 +5527,8 @@ <h4><a href="#closure-types">5.1.8 Closure Types (Lambdas)</a></h4>
55365527
</pre></font></code>
55375528
The number is omitted for the first closure type with a given
55385529
&lt;<a href="#mangle.lambda-sig">lambda-sig</a>&gt; in a given context; it is n-2 for the nth closure
5539-
type (in lexical order) with that same &lt;<a href="#mangle.lambda-sig">lambda-sig</a>&gt; and context.
5530+
type (in <a href="#lexical-ordering">lexical order</a>)
5531+
with that same &lt;<a href="#mangle.lambda-sig">lambda-sig</a>&gt; and context.
55405532
<p>
55415533

55425534
<p>
@@ -5620,9 +5612,98 @@ <h4><a href="#closure-types">5.1.8 Closure Types (Lambdas)</a></h4>
56205612
href="#mangle.lambda-sig">lambda-sig</a>&gt; can only ever refer to a
56215613
template parameter of a generic lambda.
56225614

5615+
<p>
5616+
<a name="lexical-ordering">
5617+
<h4><a href="#lexical-ordering">5.1.9 Lexical ordering</a></h4>
5618+
5619+
<p>
5620+
Lexical ordering is used for numbering local entities (named and unnamed
5621+
local classes and enumerations, closure types, and static local variables)
5622+
when there is no other way of distinguishing them. Except as described below,
5623+
all local entities are to be numbered, even if subsequent optimization makes
5624+
some of them unnecessary, or no mangled name is actually required for
5625+
some of them.
5626+
5627+
<p>
5628+
The order of entities is the source order of a key token unique to the
5629+
entity as if:
5630+
5631+
<ul>
5632+
<li>the discarded sub-statements of <tt>if constexpr</tt> within a
5633+
template did not exist and
5634+
<li>pack expansions were lexically expanded.
5635+
</ul>
5636+
5637+
<p>In all cases, this is meant to imitate the numbering that would
5638+
be produced by a simple implementation which numbered entities as it
5639+
processed the source and recursively expanded packs. Since discarded
5640+
substatements of <tt>if constexpr</tt> are still processed in
5641+
non-template code, entities within them are still numbered.
5642+
5643+
<p>Entities may be lexically nested without being in different
5644+
contexts for the purposes of mangling. For example, the lambdas in
5645+
<code>[x = []{}]{}</code> are both part of the enclosing context.
5646+
The order of such entities is determined by the source order of a key
5647+
token in the entity. In general, this token is the first token
5648+
past which the signature of the entity (as is necessary to mangle it)
5649+
is known:
5650+
5651+
<ul>
5652+
<li>The key token of a class or enum is the end of the
5653+
<code>enum-head-name</code> (<code>enum-key</code> if unnamed) or
5654+
<code>class-head-name</code> (<code>class-key</code> if unnamed)
5655+
in its first declaration.
5656+
<li>The key token of a lambda is its closing brace (<code>}</code>).
5657+
<li>The key token of a static local variable is the last token of its
5658+
<code>declarator</code> (not its initializer).
5659+
</ul>
5660+
5661+
<p>
5662+
All entities from one expansion of a pack are considered to occur
5663+
lexically before any entities from the next expansion of the same pack,
5664+
but the ordering is otherwise based on the original token sequence.
5665+
This is expected to match the numbering that would be established for
5666+
the corresponding non-template generated by substitution into the template.
5667+
As a consequence of these rules, the entity instantiated for a particular
5668+
source construct can have a different mangling number in different
5669+
instantiations of the same template. An entity appearing in the original
5670+
source may also go entirely un-numbered if it appears in a discarded
5671+
sub-statement of <code>if constexpr</code> or in a pack expansion of an
5672+
empty pack. For example:
5673+
5674+
<code><pre>
5675+
void g(...);
5676+
template&lt;bool b, typename ...T> void f() {
5677+
if constexpr(b) { []{}; }
5678+
g(([]{}, []{ static T n; return &amp;n; }())...);
5679+
}
5680+
5681+
// The first lambda is discarded and does not receive a number.
5682+
// The variables passed to g are therefore mangled as
5683+
// _ZZZ1fILb0EJiiEEvvENKUlvE0_clEvE1n and
5684+
// _ZZZ1fILb0EJiiEEvvENKUlvE2_clEvE1n.
5685+
template void f&lt;false, int, int>();
5686+
5687+
// The variable passed to g is mangled as
5688+
// _ZZZ1fILb1EJiEEvvENKUlvE1_clEvE1n and
5689+
template void f&lt;true, int>();
5690+
5691+
// Both lambdas are numbered; returns _ZZZ1hvENKUlvE0_clEvE1n.
5692+
inline int *h() {
5693+
if constexpr(false) { []{}; }
5694+
return []{ static int n; return &amp;n; }();
5695+
}
5696+
</pre></code>
5697+
5698+
<p>
5699+
Note that the numbering of entities appearing within a
5700+
<code>mem-initializer-list</code> reflects the order that the
5701+
initializers appear in the source, which may be different from the
5702+
order in which the initializers will be executed when the program runs.
5703+
56235704
<p>
56245705
<a name="mangling-compression">
5625-
<h4><a href="#mangling-compression">5.1.9 Compression</a></h4>
5706+
<h4><a href="#mangling-compression">5.1.10 Compression</a></h4>
56265707

56275708
<p>
56285709
To minimize the length of external names,

0 commit comments

Comments
 (0)