mercredi 6 janvier 2016

Why decltype expressions in return types have to be mangled in the symbol name?

I recently found out that decltype expressions are mangled as part of the functions symbol names, when used as return types, and that this can be the cause of nasty segmentation faults while demangling the expressions (in debugging sessions for example), if the expression is too complex.

The first version, using decltype in function return type, where the full expression gets mangled (http://goo.gl/EALubx):

#include <cstdint>
#include <utility>

struct A { void bar() const; };

template<typename T>
decltype(std::declval<T>().bar()) foo(T const& a);

void foo() { A a; return foo(a); }

Is compiled to (GCC 5.2.0):

foo():
        sub     rsp, 24
        lea     rdi, [rsp+15]
        call    decltype ((((declval<A>)()).bar)()) foo<A>(A const&)
        add     rsp, 24
        ret

The second version, almost equivalent, where the expression type is resolved as part of an additional template parameter (http://goo.gl/DfQGR5):

#include <cstdint>
#include <utility>

struct A { void bar() const; };

template<typename T, typename R=decltype(std::declval<T>().bar())>
R foo(T const& a);

void foo() { A a; return foo(a); }

Is compiled to (GCC 5.2.0):

foo():
        sub     rsp, 24
        lea     rdi, [rsp+15]
        call    void foo<A, void>(A const&)
        add     rsp, 24
        ret

I understand that template functions can be overloaded on their return type only, but shouldn't the compiler be able to resolve the decltype expression on its own and mangle the resulting type instead?

Could anyone tell me about why, or point me where in the C++ specification it is specified?

Aucun commentaire:

Enregistrer un commentaire