[cxx-abi-dev] Decltype mangling and type dependency

Mike Herrick mjh at edg.com
Sat Jun 19 19:52:54 UTC 2010


On Jun 17, 2010, at 3:14 PM, Jason Merrill wrote:

> On 05/17/2010 08:20 PM, Mike Herrick wrote:
>> 
>> But what about these similar cases:
>> 
>>   struct A {
>>     int m;
>>   } *pa;
>>   int f(void);
>>   template<class T>  auto f1(T p1) ->  decltype(pa->m); // _Z2f1IP1AEDtptL_Z2paE1mET_ or _Z2f1IP1AEiT_?
>>   template<class T>  auto f2(T p1) ->  decltype(f());   // _Z2f2IPFivEEDTclL_Z1fvEEET_ or _Z2f2IPFivEEiT_?
>>   int main() {
>>     f1(pa);
>>     f2(f);
>>   }
>> 
>> Since the types of pa->m and f are non-dependent, is it required to mangle these with the full decltype expression mangling (as g++ 4.5 currently does)?
> 
> In the case of decltype(pa->m), access control might depend on the template parameters.

Could you expand on that?  How might access control depend on the template parameters in f1 above?

> 
>> Here are some other interesting cases:
>> 
>>   #include<typeinfo>
>>   struct A {
>>     A();
>>     A(int i);
>>     int m;
>>   } a;
>>   int f();
>>   template<class T>  auto f1(T p1) ->  decltype(p1);
>>   template<class T>  auto f2(T p1) ->  decltype(A(p1));
>>   template<class T>  auto f3(T p1) ->  decltype(typeid(p1));
>>   template<class T>  auto f4(T p1) ->  decltype(a.m);
>>   template<class T>  auto f5(T p1) ->  decltype(a.A::m);
>>   int main() {
>>     f1(0);
>>     f2(0);
>>     f3(0);
>>     f4(0);
>>     f5(0);
>>   }
>> 
>> We believe f1, f2, and f3 require decltype manglings, while f4 and f5 do not (g++ 4.5 takes the opposite view on each of these).  Even though the typeid expression in f3 above is not type-dependent (always returning an lvalue of const std::type_info regardless of its argument), it can still be used in ways where a distinct mangling is required; for example:
>> 
>>   template<class T>  auto f(T p) ->  decltype(g(typeid(p))) { ... }
>>   template<class T>  auto f(T p) ->  decltype(g(typeid(*p))) { ... }
> 
> Right.  Currently G++ just uses the type of non-type-dependent expressions that are not member access expressions, and of type-dependent expressions that are simple decls.  This does seem like an unnecessarily complex set, and is definitely wrong for f2 and f3.  I think G++ is right for f4 and f5 because of access control, and f1 is an aesthetic choice.

It sounds to me that you agree that in more complicated cases the full expression should be mangled, and you're wondering if perhaps the simple "decltype(p1)" case falls into that category?

> 
>> Similarly, we believe that constructors can be used in ways that require a full dependent mangling, as shown by this "if it's valid, it always means one thing, but it might not be valid, which means new-style SFINAE could knock it out of the candidate set" example:
>> 
>>   template<class T>  auto f(T p) ->  decltype(A(p)) { ... }
>>   template<class T>  auto f(T p) ->  decltype(A(p, 5)) { ... }
>> 
>> This seems to argue for a third designation, "partially-dependent", for cases where the expression type is non-dependent, but because of the new SFINAE rules, it can be distinguished by the programmer and therefore requires a distinct mangling (as though it were dependent).
> 
> The important thing is that we use different mangling for functions that are not functionally equivalent (14.5.6.1).  The definition of functionally equivalent doesn't mention well-formedness of the expression, but I think it can be read into it, since an ill-formed expression produces no value.
> 
> Adding value-dependency would get us closer, but that still doesn't cover f4 and f5 above.
> 
> Perhaps we should just always use the dependent mangling in template scope, as G++ does for sizeof.

I'm not sure what you mean by "template scope".  Certainly some expressions in "template scope" are folded to constant results in current practice going back many years, and we wouldn't want to change that.  We could say that the new decltype/sizeof cases would always get a full expression, but there doesn't seem to be a good dividing line between "old" sizeof/decltype cases and "new" ones.  Though distinguishing between "old" and "new" cases would make it easier for backward compatibility (for example, introducing new manglings for static_cast, etc. in decltype expressions without breaking the existing ABI).

We think it makes sense to mangle full expressions only for things that are dependent or value-dependent.

Mike.



More information about the cxx-abi-dev mailing list