[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