From c071d0a4cd3165a069c6f4142d41f1a9ddfa7896 Mon Sep 17 00:00:00 2001
From: John McCall
A reference to a template parameter is mangled using the index
@@ -5535,9 +5535,7 @@
Template argument lists appear after the unqualified template name,
and are bracketed by I/E. This is used in names for specializations
-in particular, but also in types and scope identification. Template
-argument packs are bracketed by J/E to distinguish them from other
-arguments.
+in particular, but also in types and scope identification.
@@ -5557,180 +5556,136 @@
-Template type arguments and template template arguments are mangled
-using their regular encoding. For example, the class template
+The mangling of template arguments in dependent contexts depends on
+whether the template argument can be matched with a template parameter
+and, if so, whether the argument can be checked against the parameter.
+In general, mangling assumes that all possible matching and checking
+has been performed. The conditions are not precisely laid out here,
+but matching is generally inhibited by an unresolved template name
+and in some situations with unexpanded pack expansions, while checking
+is generally inhibited by dependent arguments or parameters.
+In non-dependent contexts (in particular, in a top-level
+
+Under the ODR, function templates are distinguished by differences
+in their template head, such as a constraint on a template type
+parameter, the type of a non-type template parameter, or (recursively)
+the template head of a template template parameter. The template
+parameter list is not directly included in the
+
+The type of a non-type template parameter is said to contain deduced
+types if it is written with a placeholder type (
+When mangling the template arguments of a function template that
+is not the
+If a template parameter pack can be matched to a template argument
+pack, the pack is bracketed with
+A template type argument or template template argument is mangled
+as a type in the usual way. For example, the class template
specialization
-A non-type template argument is considered dependent if either the
-argument expression is instantiation-dependent or it is not matched
-with a template parameter of non-dependent type. (The latter can
-happen if, for example, the template name is dependent and not a
-template parameter.) If so, it is mangled as an expression in the
-usual way for a dependent mangling.
-Otherwise, it is converted to the template parameter type,
-constant-evaluated, and then mangled as a value. For example:
+If a non-type template argument cannot be matched with a parameter,
+or if it cannot be checked against that parameter, or if the
+argument expression is instantiation-dependent, it is mangled
+as an expression in the usual way for a
+dependent mangling. Otherwise,
+the argument is converted to the parameter type, constant-evaluated,
+and then mangled as an expression representing that value. Precise typing is required when mangling
+this constant if:
+
+For example:
-Non-type template argument values of integer, enumerated,
-floating-point, or complex type are mangled as
-literals of the template parameter
-type. Note that this can produce combinations which cannot normally
-be written in the source language, such as a literal of
-
-Non-type template argument values of pointer or member pointer type
-that are null are mangled as as a literal
-Non-type template argument values of reference or pointer type
-are mangled using the subobject
-specifier expression for the argument. If this is a simple
-declaration reference, it may be mangled as an
-
-Non-type template argument values of member pointer type
-that are not null are mangled as expressions applying the
-operator
-Non-type template argument values of class type are mangled as
-a direct initialization (
-Constant evaluation may result in a pointer or reference to a specific
-subobject of an object of static storage duration. This subobject is
-identified in the mangling as if written with a specific expression,
-called its subobject specifier expression.
-
-
-(To be specified. See
-for now.)
-
-
-
-The constant evaluation of an expression of class type assigns
-a constant value to each non-static data member of the class or,
-if the class is a union, to at most one non-static data member,
-called the active union member. Under the standard, this exact
-structure uniquely determines a value, including whether a union
-has an active union member member and (if so) which one. As
-different values can produce different template specializations,
-this structure must be faithfully represented in the mangling of
-a value as a template argument.
-
-
-A value is converted to a flattened sequence of values by applying
-the following expansions until no values of array or non-union class
-type remain:
-
-This sequence is then mangled as a sequence of
-
-Note that qualifiers on the type of a non-static data member are not
-part of the type of the value stored in that member.
-
-
-For example:
-
-5.1.5.7 Pointer-to-member types
produces the mangled name "
_Z1fM1AKFvvRE
".
-5.1.5.8 Template parameters
+5.1.5.8 Template parameter references
5.1.5.10 Template Arguments
<template-args> ::= I <template-arg>+ E
@@ -5546,6 +5544,7 @@
5.1.5.10 Template Arguments
::= X <expression> E # expression
::= <expr-primary> # simple expressions
::= J <template-arg>* E # argument pack
+ ::= <template-param-decl> <template-arg> # converted template argument
5.1.5.10 Template Arguments
N1AIT0_E1XE
.
<encoding>
), template arguments should always be
+fully matched and checked against the template parameters of the
+specialized template.
+
+<encoding>
of a function template specialization
+(except for the operator()
of a generic lambda),
+but it is indirectly reflected in the mangling of the template
+arguments as follows. A template parameter is said to be natural
+for a template argument that has been matched and checked against
+it if:
+
+
+
+auto
or
+decltype(auto)
) or a placeholder for a deduced class type
+(e.g. container
when that is a template with deducible
+template parameters).
+
+operator()
of a lambda, if a template
+argument has been matched and checked against a template parameter
+that is not natural for the template argument, a
+<template-param-decl>
must be prefixed to the
+template argument. Earlier versions of this ABI did not call for this
+and so could fail to distinguish templates that must be distinguished
+under the ODR. This is not done for class templates in order to
+reduce ABI incompatibility, and in particular to allow class templates
+to adopt constraints without breaking ABI. It is not done for
+generic lambdas because the template parameter list is already
+encoded in the <lambda-sig>
.
+
+J...E
+to distinguish it from other arguments. This is done even if some
+of the arguments in the pack cannot be checked against the parameter.
+If a <template-param-decl>
is required for the
+parameter, it is mangled immediately prior to the entire pack
+(the J
), not before the individual
+arguments in the pack.
+
+A<char, float>
is encoded as
1AIcfE
.
+
+
+operator()
of a generic lambda and a
+ <template-param-decl>
is not required.
+
-
-template
short
type.
-
-0
of the
-template parameter type. For example:
-
-
-
-
-struct A;
-template <void (A::*)()> void f();
-
-f<nullptr> // _Z1fILM1AFvvE0EEvv
-
<expr-primary>
.
-
-&
to the member function declaration
-as if it were a regular function. (Note that this does not
-distinguish between member pointers that have been converted
-to different types.) For example:
-
-
-
-
-struct A {
- void foo();
-};
-template <void (A::*)()> void f();
-
-f<&A::foo> // _Z1fIXadL_ZN1A3fooEvEEEvv
-
tl
) of the class type
-using the member
-initiializer sequence for the argument.
-
-
-5.1.5.11 Subobject specifier expressions
+
+5.1.5.11 Template parameter declarations
5.1.5.12 Member initializer sequences
-
-
-
-
-Values satisfying the following conditions are then removed from
-the end of the sequence until the final value does not satisfy
-these conditions or the sequence is empty:
-
-
-
-<braced-expression>
s
-as follows:
-
-
-
-L <type > E
.
-
+
-struct A {
- int x, y;
-};
-struct B {
- union { A a; };
- constexpr B(int x, int y) { a.x = x; a.y = y; }
-};
+Template parameter declarations are usually not mangled. To distinguish
+function templates with different template signatures, the ABI mostly
+relies on the mangling of template arguments to include enough
+information to determine which template is meant. However, there are
+some cases where this is not sufficient, such as when the template
+parameter contains deduced types, or when mangling generic lambdas.
+In these cases, the template parameter must be mangled directly.
-template <B v> struct C {};
-
-C<0,0> // 1CIXtl1BEEE
-C<1,0> // 1CIXtl1BtlNS0_Ut_Edi1atl1ALi1EEEEEE
-C<1,1> // 1CIXtl1BtlNS0_Ut_Edi1atl1ALi1ELi1EEEEEE
-
+ <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
+
5.1.6 Expressions
@@ -6022,6 +5977,298 @@ 5.1.6.2 References to declared ent
+It is sometimes necessary to mangle a constant value resulting from +constant evaluation. Currently this is limited to several places +in the mangling of a non-dependent non-type +template argument. In general, this is done by mangling a notional +expression with the value and type of the constant. For various reasons, +these mangled expressions do not always correspond to valid source +expressions. + +
+The mangling of constant values is sensitive to the converted type of
+the constant. For example, the expression 5
has type
+int
, but when it is used as the argument for a template
+parameter of type unsigned short
, it is converted to that
+type and mangled as Lt5E
. Some contexts require
+precise typing, meaning that constants must be mangled in a way
+that includes the exact converted type. In other contexts, some
+information not necessary to distinguish constants is omitted in
+order to reduce symbol sizes and preserve existing manglings.
+The places in this ABI that call for the mangling of a constant value
+all indicate whether precise typing is required for a particular
+constant.
+
+
+Values of integer, enumerated, floating-point, or complex type are
+mangled as literals of the approproiate
+type. Note that this can produce combinations which cannot normally be
+written in the source language, such as a literal of short
+type.
+
+
+Null pointers and member pointers are mangled as as a literal
+0
of their type. For example:
+
+
+
+
+struct A;
+template <void (A::*)()> void f();
+
+f<nullptr> // _Z1fILM1AFvvE0EEvv
+
+Non-null values of reference or pointer type are mangled using the
+constant object reference
+expression for the argument. Note that, if this is a simple
+declaration reference, it may end up being an
+<expr-primary>
+and must be mangled without X...E
when
+mangled as a template-arg
.
+
+
+Non-type template argument values of member pointer type +that are not null are mangled using the +member pointer +reference expression for the argument. + +
+Non-type template argument values of class type are mangled as
+a direct initialization (tl
) of the class type
+using the member
+initiializer sequence for the contents of the type.
+
+
+5.1.6.3 Constant object reference expressions
+
+
+
+Constant evaluation may result in a pointer or reference to a function +or to a subobject of an object of static storage duration, possibly +converted to a different type. Under the standard, references to +formally different subobjects are different template arguments even +if they coincide in their type and address. This entity is identified +in the mangling as if it were written with a specific expression, +called the reference expression. The exact expression depends on +whether precise typing is +required. + +
+Let ObjectType
be the unqualified type of the referenced
+function or subobject, and let ConstantType
be the pointee
+type of the constant type. These types can differ by more than just
+qualification if the constant has been converted to a type such as
+void*
.
+
+
+Initially, the reference expression is an expression referring
+to the function or top-level object, mangled with the L_Z
+production in
+<expr-primary>
.
+The notional type of this expression is the declared type of the
+function or object, including any qualifiers.
+
+
+Next, if the value refers to an object that is not a top-level object,
+the reference expression is wrapped in a special expression used only
+for this purpose, using the so
mangling
+below. The notional type of this expression is the encoded referent
+type.
+
ConstantType
differs from ObjectType
by
+ more than just qualification then the referent type for the mangling
+ is ObjectType
. Otherwise, the referent type for the
+ mangling is ConstantType
.
+
+ <expression> ::= so <referent type> <expression> [<offset number>] <union-selector>* E
+ <union-selector> ::= _ [<number>]
+
+
+
+Next, if the constant is a pointer, the reference expression is
+wrapped in a unary &
operator (that is, prefixed with
+ad
. The notional type of this expression
+is a pointer to the notional type of the previous reference expression.
+
+
+Finally, if precise typing is required and the notional type of the
+current reference expression doesn't match the type of the constant,
+the reference expression is wrapped in a C-style cast to the constant
+type (that is, prefixed with cv <type>
).
+
+
+5.1.6.4 Member pointer reference expressions
+
+
+
+Constant evaluation may result in a member pointer to a specific +member, possibly converted to a different type. As with other constant +manglings, this value is identified in the mangling as if it were written +with a certain expression, called the reference expression. The exact expression depends on whether precise +typing is required. + +
+The initial reference expression applies the prefix operator
+&
to the member declaration as if it were a regular
+function or variable. The notional type of this expression is a
+member pointer type using the declaring class and the declared type of
+the member. For example:
+
+
+
+
+struct A {
+ void foo();
+};
+template <void (A::*)()> void f();
+
+f<&A::foo> // _Z1fIXadL_ZN1A3fooEvEEEvv
+
+If the class type of the constant is not the declaring class of the
+member, the reference expression is wrapped in a special expression
+used only for this purpose, which encodes the this
-adjustment
+that must be applied to a pointer to the class type of the constant
+in order to produce a pointer to the declaring class of the member.
+The offset is omitted if zero. The notional type of this expression
+is a member pointer type using the class type of the constant and the
+declared type of the member.
+
+
+ <expression> ::= mc <class type> <expression> [<offset number>] E
+
+
+
+Finally, if precise typing is required and the notional type of the
+current reference expression is not the type of the constant, the
+reference expression is wrapped in a C-style cast to the constant
+type (that is, prefixed with cv <type>
).
+This can happen because static_cast
may add qualifiers
+to the member type.
+
+
+
+
+struct A {
+ char x;
+ void foo();
+};
+struct B {
+ char y;
+};
+
+struct C : A, B {};
+template <void (C::*)()> void f();
+
+f<&A::foo> // _Z1fIXmcM1CFvvEadL_ZN1A3fooEvE1EEEvv
+
+The mc
mangling uses an offset instead of
+a base path to avoid exposing private details of the class into the ABI,
+such as the names of any intermediate base classes.
+
+
+5.1.6.5 Member initializer sequences
+
+
+
+The constant evaluation of an expression of class type assigns +a constant value to each non-static data member of the class or, +if the class is a union, to at most one non-static data member, +called the active union member. Under the standard, this exact +structure uniquely determines a value, including whether a union +has an active union member member and (if so) which one. As +different values can produce different template specializations, +this structure must be faithfully represented in the mangling of +a value as a template argument. + +
+A value is converted to a flattened sequence of values by applying +the following expansions until no values of array or non-union class +type remain: +
+This sequence is then mangled as a sequence of
+<braced-expression>
s
+as follows:
+
L <type > E
.
+ +Precise typing is not required when mangling the constant member values. +Note that qualifiers on the type of a non-static data member are not +part of the type of the value stored in that member. + +
+For example:
+
+
+
+struct A {
+ int x, y;
+};
+struct B {
+ union { A a; };
+ constexpr B(int x, int y) { a.x = x; a.y = y; }
+};
+
+template <B v> struct C {};
+
+C<0,0> // 1CIXtl1BEEE
+C<1,0> // 1CIXtl1BtlNS0_Ut_Edi1atl1ALi1EEEEEE
+C<1,1> // 1CIXtl1BtlNS0_Ut_Edi1atl1ALi1ELi1EEEEEE
+
5.1.7 Scope Encoding