Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
34 changes: 34 additions & 0 deletions core/metacling/test/TClingDataMemberInfoTests.cxx
Original file line number Diff line number Diff line change
Expand Up @@ -252,3 +252,37 @@ TEST(TClingDataMemberInfo, Offset)
EXPECT_EQ(-1L, (ptrdiff_t)GeoManagerInfo->GetAddress());
#endif // R__USE_CXXMODULES and R__HAS_GEOM
}

// https://github.com/root-project/root/issues/23055
// The 'typename' of a dependent alias is part of the spelling of the type, not
// of its identity: it must not end up in the normalized type name, which is
// what the I/O uses to match a member against the on-file description.
TEST(TClingDataMemberInfo, TypenameKeyword)
{
gInterpreter->Declare(R"CODE(
#include <vector>
namespace ROOT23055 {
struct Track {
int value = 0;
};
template <class T>
struct Container {
typedef typename std::vector<T *> seq_type;
seq_type fSequential;
std::vector<typename std::vector<T *>::value_type> fNested;
};
}
)CODE");

TClass *cl = TClass::GetClass("ROOT23055::Container<ROOT23055::Track>");
ASSERT_NE(cl, nullptr);
auto *members = cl->GetListOfDataMembers();

auto *sequential = (TDataMember *)members->FindObject("fSequential");
ASSERT_NE(sequential, nullptr);
EXPECT_STREQ(sequential->GetTrueTypeName(), "vector<ROOT23055::Track*>");

auto *nested = (TDataMember *)members->FindObject("fNested");
ASSERT_NE(nested, nullptr);
EXPECT_STREQ(nested->GetTrueTypeName(), "vector<ROOT23055::Track*>");
}
20 changes: 20 additions & 0 deletions interpreter/cling/lib/Utils/AST.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1545,6 +1545,26 @@ namespace utils {
}
}

// Part of the normalization is to remove the elaborated type keyword
// ('typename', 'struct', ...); it is pure syntax and must never show up in
// a normalized type name. The keyword of the *input* type is taken care of
// at the top of this function, but desugaring can expose a new one, as in
// typedef typename std::vector<T*> seq_type;
// where the keyword sits on the TemplateSpecializationType that the typedef
// resolves to.
Comment on lines +1550 to +1554

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What is *input*, where is something like this already "taken care of at the top of this function" (I don't see it), and what happens if there is a typedef pointing to another alias?

if (const auto* TST =
dyn_cast<TemplateSpecializationType>(QT.getTypePtr())) {
if (TST->getKeyword() != ElaboratedTypeKeyword::None) {
Qualifiers quals = QT.getLocalQualifiers();
QT = Ctx.getTemplateSpecializationType(ElaboratedTypeKeyword::None,
TST->getTemplateName(),
TST->template_arguments(),
/*CanonicalArgs=*/{},
TST->getCanonicalTypeInternal());
QT = Ctx.getQualifiedType(QT, quals);
}
}

// If we have a reference, array or pointer we still need to
// desugar what they point to.
if (isa<PointerType>(QT.getTypePtr()) ||
Expand Down
14 changes: 14 additions & 0 deletions interpreter/cling/test/Utils/Transform.C
Original file line number Diff line number Diff line change
Expand Up @@ -184,6 +184,14 @@ namespace NS4 {
}
typedef NS4::Inner::ConcreteTypedef GlobalAlias;

namespace NS5 {
class Track {};
template <typename T> class Container {
public:
typedef typename std::vector<T> seq_type;
};
}

.rawInput 0

const cling::LookupHelper& lookup = gCling->getLookupHelper();
Expand Down Expand Up @@ -538,3 +546,9 @@ QT = lookup.findType("const GlobalAlias&", diags);
std::cout << Transform::GetPartiallyDesugaredType(Ctx, QT, transConfig).getAsString().c_str() << std::endl;
// CHECK: NS4::Inner::TemplateClass<double> &

// The elaborated type keyword ('typename' here) is part of the spelling of the
// typedef target and must not survive the normalization.
QT = lookup.findType("NS5::Container<NS5::Track>::seq_type", diags);
std::cout << Transform::GetPartiallyDesugaredType(Ctx, QT, transConfig).getAsString().c_str() << std::endl;
// CHECK: std::vector<NS5::Track>

Loading