[cxx-abi-dev] Literal operator functions with 'li<length, ID>'
Mike Herrick
mjh at edg.com
Fri Aug 9 15:42:47 UTC 2013
On Aug 7, 2013, at 3:26 PM, Richard Smith <richardsmith at google.com> wrote:
> One follow-up related to the example that is given above; our UDL mangling produces a slightly different mangled name for this example: _Z1fIiEDTcmclL_Zli2_wPKcELA4_S0_EEfp_ET_, reflecting a difference in the cv-qualification of the type of the argument that is being passed to the literal operator. Clang's demangled name reflects the use of "char [4]" as the argument type and we're using "const char [4]":
>
> < decltype(((operator "" _w((char [4])"..."),param#1))) f<int>(T1)
> ---
> > decltype(((operator "" _w((const char [4])"..."),param#1))) f<int>(T1)
>
> From a Standards point-of-view, we think "const char [4]" is correct here (the call to a raw literal operator X is defined to be equivalent to operator "" X("n"), and the type of "n" is "array of const char"). Is this a clang bug or the result of some implicit conversion (and if so, should it be reflected in the mangling)?
>
> It looks like this was a transient bug -- I agree that your mangling is the correct one, and it's also the one that Clang trunk produces.
Thanks for that confirmation.
Another discrepancy seems to be in the use of <unresolved-name> production. For example:
typedef __SIZE_TYPE__ size_t;
void *operator "" _s(unsigned long long) {}
void *operator new(size_t) {}
void *f(unsigned long long) {}
template<typename T> auto f1(T x)->decltype(operator "" _s(x));
template<typename T> auto f2(T x)->decltype(operator new(x));
template<typename T> auto f3(T x)->decltype(f(x));
int main() {
f1(0); // neither g++ nor clang use <unresolved-name> for operator "" _s
// g++: _Z2f1IiEDTclli2_sfp_EET_
// clang: _Z2f1IiEDTclli2_sfp_EET_
// expected: _Z2f1IiEDTclonli2_sfp_EET_
f2(0); // g++ uses <unresolved-name> for operator new
// g++: _Z2f2IiEDTclonnwfp_EET_
// clang: _Z2f2IiEDTclnwfp_EET_
// expected: _Z2f2IiEDTclonnwfp_EET_
f3(0); // g++ and clang use <unresolved-name> for f
// g++: _Z2f3IiEDTcl1ffp_EET_
// clang: _Z2f3IiEDTcl1ffp_EET_
// expected: _Z2f3IiEDTcl1ffp_EET_
}
[Mangled names are from g++ 4.8.1 and clang 3.3.] We believe <unresolved-name> should be used for all of these cases.
There's another issue here: demangling the "li" <operator-name>. Each <operator-name> has an implied number of arguments (except the vendor extended operator where the number is explicitly supplied), but a literal operator can have zero, one or two arguments, so it's not clear which of these applies:
<expression> ::= <unary operator-name> <expression>
::= <binary operator-name> <expression> <expression>
Though GNU cxxfilt (from binutils 2.23) demangles the two names in this example properly:
typedef __SIZE_TYPE__ size_t;
void operator "" _s(const char *) {}
void operator "" _s(const char *, size_t) {}
template<typename T> auto f1(T x)->decltype(operator "" _s(x));
template<typename T> auto f2(T x)->decltype(operator "" _s(x, 0));
int main() {
f1("xyz"); // _Z2f1IPKcEDTclli2_sfp_EET_
f2("xyz"); // _Z2f2IPKcEDTclli2_sfp_Li0EEET_
}
Note that if the <unresolved-name> mangling is used here (i.e., with "clonli" rather than "clli"), there's no issue with the arguments because <unresolved-name> (rather than <unary/binary operator-name>) is used as the first argument to the "cl" and the remaining <expressions> are parsed as arguments to the "cl" (not the "li"). That's also the case with mangled names of the form "clL_Zli2_x..." (where <expr-primary> is used for the first "cl" <expression>").
An observation: because the "li" mangling always involves mangling of the implicit call to the literal operator, and the "cl" mangling already handles a variable number of <expression>s, we need to ensure that the arguments to the literal operator are demangled by the "cl" production, not the "li" production; i.e., either we don't produce mangled names with "clli" (because <unresolved-name> or <expr-primary> should instead be used), or we make a special case for "li" that it effectively takes zero <expression> arguments:
<expression> ::= <nullary operator-name> # literal operand (no arguments)
I'd prefer the first of these options (I haven't seen an example where the "clli" mangling makes sense), but I think demanglers need to implement the second option in order to deal with existing practice.
Mike Herrick
Edison Design Group
More information about the cxx-abi-dev
mailing list