Why is declval present in the malformed character name?

I was playing around with GCC (4.9.2) abi :: __ cxa_demangle and I got to a case where it couldn't expand a specific symbol name.

This symbol:

_ZNK12DebugWrapperIR5TestClsE5getIdIIEEEDTcldtcl7declvalIS1_EEL_ZNKS0_5getIdEvEspfp_EEDpOT_ 

      

I'm surprised to see "declval" there.

This particular function is defined using this macro:

template <typename WrappedType>
class DebugWrapper
{
private:
WrappedType VALUE;
std::string NAME;
mutable std::string CALLER;

public:
...
#define WRAP_CONST_FUNCTION(name, enterLogging, exitLogging)                                    \
        template <typename ...Args>                                                             \
        auto name(Args&&... args) const -> decltype(std::declval<WrappedType>().name(args...))  \
        {                                                                                       \
                                                                                            \
            struct dummy                                                                        \
            {                                                                                   \
                const char* const FUNCTION = nullptr;                                           \
                const std::string& CALLER;                                                      \
                const WrappedType& VALUE;                                                       \
                                                                                                \
                dummy(  const char* const input,                                                \
                        const std::string& caller,                                              \
                        const WrappedType& value):                                              \
                    FUNCTION(input), CALLER(caller), VALUE(value)                               \
                {                                                                               \
                    enterLogging;                                                               \
                }                                                                               \
                                                                                                \
                ~dummy()                                                                        \
                {                                                                               \
                    exitLogging;                                                                \
                }                                                                               \
            }dummy(#name, CALLER, VALUE);                                                       \
                                                                                                \
            return VALUE.name(args...);                                                         \
        }
        WRAP_CONST_FUNCTION(getId, <whatever>, <whatever>)
...
};

      

I also quickly looked at the itanium C ++ abi spec for declval, but there was no result.

Why is he there? and why can't abi :: __ cxa_demangle untie it?

+3


source to share


1 answer


Template functions must have a return type in the mangled name because template functions can only be overloaded on return type. A simpler example:

template <typename T> void f() { }
template <typename T> auto g() -> decltype(f<T>()) { }
inline void h() { }
int main() { g<int>(); h(); }

      

Compiling this and checking the output I see:

$ g ++ -c h.cc -std = c ++ 11 && nm ho | c ++ filt
0000000000000000 T main
0000000000000000 W decltype ((f) ()) g ()
0000000000000000 W h ()

You can see the return type there for g

, but not for h

. The fact that h

it is not a template function already means that there cannot be another function h

in the same namespace with the same parameters.

This is why it getId

appears twice in your garbled name. One of them is the name itself, the other is its appearance in the reverse type.

declval

is not special here, so it is not called in the C ++ ABI. Any function, library, or user is handled the same way.

As for why he won't rule, it's hard to say. A real example code that generates a mangled name in your question will help here, but 5TestCls

it doesn't look right because the number that precedes the name indicates the length, and I'm under the impression that the TestCls

full name should have been. If it is indeed a name, then demangling fails because the mangled name is invalid.

As per the complete example you posted in the comments, I can come up with a shortcut program and it looks like this is a member access operator that is being handled incorrectly by the demangler:



extern struct A { void f(); static void g(); } a;
template <typename...T> auto f(T...t) -> decltype(a.f(t...));
template <typename...T> auto g(T...t) -> decltype(A::g(t...));
int main() { f(); g(); }

      

$ g ++ -std = c ++ 11 -pedantic -c h.cc && nm ho && nm -C ho
0000000000000000 T main
                 U _Z1fIJEEDTcldtL_Z1aEL_ZN1A1fEvEspfp_EEDpT_
                 U _Z1gIJEEDTclL_ZN1A1gEvEspfp_EEDpT_
0000000000000000 T main
                 U _Z1fIJEEDTcldtL_Z1aEL_ZN1A1fEvEspfp_EEDpT_
                 U decltype (A :: g ({parm # 1} ...)) g <> ()

The difference between _Z1fIJEEDTcldtL_Z1aEL_ZN1A1fEvEspfp_EEDpT_

and is _Z1gIJEEDTclL_ZN1A1gEvEspfp_EEDpT_

more obvious with some extra spacing:

_Z1fIJEEDTcldtL_Z1aEL_ZN1A1fEvEspfp_EEDpT_
_Z1gIJEEDTcl L_ZN1A1gEvEspfp_EEDpT_

The only differences are f

vs. g

and dtL_Z1aE

.

The CIIA Itanium C ++ language states what is x.y

mangled as dt <expression> <unresolved-name>

. There <expression>

is L_Z1aE

. This part looks correct. This indicates a "mangled" (not real) global variable name a

. But <unresolved-name>

- _ZN1A1fEvE

. It is not right. This is right for the version decltype(A::g(t...))

where the left-most operand of the function call operator can be represented as a malformed name through <expr-primary> ::= L <mangled-name> E

, but not for the version decltype(a.f(t...))

. That would mean something like A::f()

, but <unresolved-name>

shouldn't have namespace qualifiers unless they appear in the source code, and even then, only with the special prefix ( sr

). It should also not have parameter information. <unresolved-name>

should be 1f

.

If the corrected name is in use, then the demanger can handle it:

$ c ++ filt <<< _Z1fIJEEDTcldtL_Z1aE1fspfp_EEDpT_              
decltype ((af) ({parm # 1} ...)) f <> ()

clang generates the correct name as seen on Coliru by simply changing g++

to clang++

invocation in your command. You can report this as a bug to the GCC developers.

+2


source







All Articles