Gabriel Dos Reis wrote:

> At the C++ language level, there are concerns of how to specify the
> interaction.  All I claimed was that the observable semantics
> does not need further specification to make the examples work.
>
> At the compiler internals level, how overloads are handled has a much
> wider variety of practice and I do not think we should have a standard
> that says exactly how that should be implemented, as opposed to what the
> end behaviour should be.

Agreed.

> At the moment, GCC/g++ would ICE claiming that it does not know how
> mangle a call expression (and a few othr nodes).  My claim is that if
> that problem is solved (by whatever means), the overload and template
> machinery does not need further modification to handle all the examples
> officially presented so far.

That sounds a reasonable claim.

> | The general philosophy in the current ABI would seem to be
> | that the expression is encoded in terms of its template
> | parameters, and not with the evaluated expression with the
> | subsituted argument.
>
> That is correct.  For a compiler, such as GCC, that uses parse trees
> to represent a template declaration there is no additional
> difficultly in mangling the expression, compared to the 'ordinary' case.

My concern is how, practically, to mangle a call to an
overloaded function, as, if the philosophy of encoding the
expression in terms of template parameters is continued, you
have to introduce ways of mangling the linked list of
FUNCTION_DECLs in an OVERLOAD node.  This is certainly not
impossible, but likely to be long-winded.  And the
possibility of ADL means that the overload set won't be the
same for each instantiation of the template

E.g. in

  int foo(int);  long foo(long);
  template <int> A {};
  template <class T, T V> void bar( A<sizeof(foo(V))> );

we could introduce

  O <overloads expression-list> E

to represent a overload set and represent the sizeof
expression as

  szcl2OL_Z3fooiEL_Z3foolEET0_

(where I've adopted your mangling of call expression rather
than the one I suggested).


A better approach might be to fall back to the token stream
and mangle the token stream representing the function being
called.  E.g. in the same way that

  sr <type> <unqualified-name>

gives you a way of mangling sizeof( T::foo() ), a variant
could be introduced for unqualified names, e.g.

  su <unqualified-name>

which would allow the original sizeof(foo(V)) to be mangled
as

  szcl2su3fooT0_

which is much more concise than mangling the overload set,
and more accurately reflects the 'same token stream'
requirement of the standard.  (Though, 14.6.4.1/7 already
makes the program ill-formed, no diagnostic required, if a
specialisation has different meanings at different points of
instantiation, so the difference can only affect ill-formed
programs, I think.)


> | to mangle a function call, and you could mangle the
> | call to the non-overloaded function, foo:
> |
> |   template <class T> int foo(T);
> |   template <int> A {};
> |   template <class T, T V> void bar( A<sizeof(foo(V))> );
> |
> | The obvious strategy is to encode bar<int, 42> as (I think)
> |
> |   _Z3barIiLi42EEv1AIXszclL_Z3fooIiEiT_ET0__EE
> |
> | where _Z3fooIiEiT_ is the result of subsituting T=int into
> | the definition of foo.  But this means that the template
> | parameters of bar are repeated and all the specialisations
> | of bar no longer have the form
> |
> |   _Z3barI{parameters}Ev1AIXszclL_Z3fooIiEiT_ET0__EE
> |
> | ... because the 'i' from T=int is repeated.  (Again, this is
> | only a problem if one wants to mangle two 'functionally
> | equivalent' overloads.)
>
> The killing point for GCC/g++ is to mangle the original template
> declaration -- not just the result of instantiation -- that is close
> to the 'same token stream' requirement of the C++ definition.

But does this have to be a killing point for GCC?

Although it seems preferable to stick as close to the
original template declaration as possible, and the note in
14.5.5.8 suggests that as a QoI issue, a compiler should aim
to treat functionally equivalent declarations that are not
equivalent as distinct, the 'functionally equivalent not not
equivalent' [14.5.5.1/7] rule grants compilers licence to
ignore any particularly tricky cases.  That said, I think
my suggestion, above, of mangling the unmangled, unqualified
name gets around this.

Richard Smith

Reply via email to