Gabriel Dos Reis wrote:

> On Wednesday July 18, 2007 I brought factual evidence to
> that claim by showing g++ behaviour on all of the examples
> discussed (including those from the "decltype" proposal).
> (All I did was to encode call expressions, new expressions
> and a few other tree nodes).

I'm curious as to how this works with overloaded functions.

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, for

  template <int I> void fn( A<-I> );

the specialisation fn<1> would be mangled as

  _Z2fnILi1EEv1AIXngT_EE   void fn<I>( A<-I> ) [with I=1]

instead of, say,

  _Z2fnILi1EEv1AILin1EE    void fn<I>( A<-1> ) [with I=1]

This has the result that all specialisations of this
template have the mangled form

  _Z2fnI{parameters}Ev1AIXngT_EE

(I'm not convinced this is absolutely necessary, even though
it seems a good idea.  The oft-quoted example is

  template <int I, int J> A<I+J> fn(A<I>, A<J>);
  template <int I, int J> A<I-J> fn(A<I>, A<J>);

and then setting I=J=0.  If you substuted the arguments,
you'd get _Z2fnILi0ELi0EE1AILi0EES0_ILi0EES0_ILi0EE for
both.  However, by my reading of 14.5.5.1, these are
functionally equivalent but not equivalent and thus render
the program ill-formed; no diagnostic required.)

However, the obvious strategy for dealing with overloaded
functions is to perform overload resolution and then mangle
the selected overload.  For example, if we make up the
syntax

  <expression> ::= ...
               ::= cl <function expression> <args expression-list>
_
  <expression-list> ::= <expression>+ _

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.)  An alernative is to propagate bar's
parameter into foo's argument:

  _Z3barIiLi42EEv1AIXszclL_Z3fooIT_EiT_ET0__EE

But then extending this to an overloaded function call of
foo looks very hard, as you no longer know the function is
being called when you want to mangle the expression
'foo(V)'.  Effectively, you have a choice: mangle the whole
of the candidate set (or enough information to regenerate
it); or mangle the name after overload resolution and loose
the ability to mangle 'functionally equivalent' expressions
accurately.  The latter sounds far easier, but is contrary
to the spirit of the existing ABI.

Richard Smith

Reply via email to