A question about C++ mangling for a complicated template case

Hi,

I have a question about C++ name mangling.

For the following small program (I failed to get it further minimized), clang++ and g++ generate different symbols for function fin introduced by the last specialization statement.

clang++: AA<3>::aa BB::fin<3, AA>(AA const&)
g++: AA<3>::aa BB::fin<3, AA>(AA<3> const&)

If I change the return type of fin to be void, I can see the argument AA<3> can be correctly generated for clang++.

{code}

template
class AA
{
template struct Iter;

template <template class DH>
struct Iter<DH<3> >
{
typedef DH<3> AA_type;
};

typedef Iter<AA > IteratorSelector;
public:
typedef typename IteratorSelector::AA_type aa;
};

class BB
{
template <int dim, template class C>
static typename C::aa fin (const C &container);

template
static void pp (const AA& dof)
{
typename AA::aa temp = fin (dof);
}
};

template void BB::pp<3> (const AA<3>&);

{code}

So anybody know why?

This problem will cause failure of linking object files generated by clang++ and g++ separately, and potentially introduce run-time bugs.

Thanks,
-Jiangning

Hi,

I have a question about C++ name mangling.

For the following small program (I failed to get it further minimized),
clang++ and g++ generate different symbols for function fin introduced by
the last specialization statement.

clang++: AA<3>::aa BB::fin<3, AA>(AA const&)
g++: AA<3>::aa BB::fin<3, AA>(AA<3> const&)

Demangled names are not useful when talking about mangling differences. The
mangled names are:

  _ZN2BB3finILi3E2AAEENT0_IXT_EE2aaERKS2_ (from clang)
  _ZN2BB3finILi3E2AAEENT0_IXT_EE2aaERKS3_ (from gcc)

GCC's mangling appears to be correct here (modulo a bug in the ABI that
gives a mangling to an empty <prefix>). S2_ refers to T0_ from the
nested-name-specifier in the return type; S3_ refers to T0_IXT_EE, which is
what we want in the parameter's type.

Hi Richard,

Thanks a lot for your feedback!

Now I can generate an even smaller test case, so I filed a but at http://llvm.org/bugs/show_bug.cgi?id=21351.

The small test case is like

{code}

emplate class AA { public: AA(){} };

class BB
{
public:
template <template class C>
static C<3> fin (const C<3> &);
};

AA<3> f(const AA<3> &dof)
{
return BB::fin(dof);
}

{code}

I’m not familiar with clang, so what is the term or symbol T0_IXT_EE ? I can’t find it in clang source code. Can you explain more? I want to get this bug fixed, and it is blocking my benchmarking work.

Thanks,
-Jiangning

Hi Richard,

Thanks a lot for your feedback!

Now I can generate an even smaller test case, so I filed a but at
http://llvm.org/bugs/show_bug.cgi?id=21351.

The small test case is like

{code}
emplate <int dim> class AA { public: AA(){} };

class BB
{
public:
    template <template<int> class C>
    static C<3> fin (const C<3> &);
};

AA<3> f(const AA<3> &dof)
{
    return BB::fin(dof);
}
{code}

I'm not familiar with clang, so what is the term or symbol T0_IXT_EE ? I
can't find it in clang source code. Can you explain more? I want to get
this bug fixed, and it is blocking my benchmarking work.

This is part of the Itanium C++ ABI's name mangling scheme. T0_ means "the
second template parameter", I ... E denotes a template argument list, X ...
E denotes a template argument expression, and T_ means "the first template
parameter". So this whole thing means C<n> (where C is the second template
parameter and n is the first).

See http://mentorembedded.github.io/cxx-abi/abi.html#mangling for the gory
details.

A patch that fixes the bug is out for review. =)