This is the mail archive of the mailing list for the GCC project.

Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

Re: C++ ABI: name mangling of operator new [bug 6057]

On Fri, 27 Jul 2007, Richard Smith wrote:

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

Good question.  

There are two levels here: the C++ language level, and the compiler
internals level.

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.

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.

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

| 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, these are
| functionally equivalent but not equivalent and thus render
| the program ill-formed; no diagnostic required.)

That is correct.

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

The scheme I used is similar; the difference being that I also 
encoded the number of arguments (counting the function to call as an
argument), so it looks like

      cl <positive number> <function expression> <args expression-list>

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

Note also that there are other cases that GCC/g++ does not distinguish:
implicit specialization vs. explicit instantiation vs. explicit

-- Gaby

Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]