[cxx-abi-dev] Literal operator functions with 'li<length, ID>'

Richard Smith richardsmith at google.com
Sat Aug 10 01:46:15 UTC 2013


On Fri, Aug 9, 2013 at 8:42 AM, Mike Herrick <mjh at edg.com> wrote:

>
> 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.


Why is the 'on' ever necessary when the operator is the callee of a 'cl'?
It appears that Clang never emits it, and just uses the operator-name
directly.

Also, what about this:

  struct X{}; void operator+(X);
  template<typename ...T> auto f4(T... x) -> decltype(operator+(x...));
  int main() {
    f4(X{});
  }

Should we use 'pl' or 'ps' for the operator+ here? Clang uses 'clps', EDG
uses 'clonps', and GCC uses 'clonpl'.

Also, what about this:

struct X {}; void operator+(X);
struct Y; void operator+(Y);
template<typename T> void g(void(*)(T), T);
template<typename T> auto f(T x) -> decltype(g(operator+, x));
void h() { f(X{}); }

Here, GCC and Clang produce _Z1fI1XEDTcl1gplfp_EET_
EDG produces the surprising _Z1fI1XEDTcl1gL_Z9operator+Efp_EET_

Both manglings are malformed -- this looks like a case where we really do
need the 'on', and yet no-one emits it.
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://sourcerytools.com/pipermail/cxx-abi-dev/attachments/20130809/1ce83394/attachment.html>


More information about the cxx-abi-dev mailing list