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

Jason Merrill jason at redhat.com
Thu Jun 17 19:14:52 UTC 2010


On 05/17/2010 08:20 PM, Mike Herrick wrote:
> Generally speaking, the idea is to provide a mangling for entities that don't have a "describable" type (https://www.codesourcery.com/archives/cxx-abi-dev/msg01984.html).

Note that I abandoned the notion of describable type (and type stubs) 
because a dependent expression of describable type could differ in 
SFINAE handling from another one with the same describable type.

> In that vein, rules were added to<expression>  to handle cases such as:
>
>    struct A {
>      int m;
>    } *pa;
>    int f(void);
>    template<class T>  auto f1(T p1) ->  decltype(p1->m); // _Z2f1IP1AEDtptfp_1mET_
>    template<class T>  auto f2(T p1) ->  decltype(p1());  // _Z2f2IPFivEEDTclfp_EET_
>    int main() {
>      f1(pa);
>      f2(f);
>    }

> As a general rule, expressions (that appear in decltype/sizeof/alignof) with dependent types are mangled in full (using the newly added rules), while expressions with non-dependent types simply use the expression type.

Right.

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

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

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

Jason



More information about the cxx-abi-dev mailing list