Skip to content
Merged
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
14 changes: 1 addition & 13 deletions tree/ntuple/src/RFieldMeta.cxx
Original file line number Diff line number Diff line change
Expand Up @@ -161,28 +161,16 @@ ROOT::RClassField::RClassField(std::string_view fieldName, TClass *classp)
// context-dependent types (e.g. typedefs defined in the class itself - which will not be fully qualified in
// the string returned by dataMember->GetFullTypeName())
std::string typeName{dataMember->GetTrueTypeName()};
// RFieldBase::Create() set subField->fTypeAlias based on the assumption that the user specified typeName, which
// already went through one round of type resolution.
std::string origTypeName{dataMember->GetFullTypeName()};

// For C-style arrays, complete the type name with the size for each dimension, e.g. `int[4][2]`
if (dataMember->Property() & kIsArray) {
for (int dim = 0, n = dataMember->GetArrayDim(); dim < n; ++dim) {
const auto addedStr = "[" + std::to_string(dataMember->GetMaxIndex(dim)) + "]";
typeName += addedStr;
origTypeName += addedStr;
typeName += "[" + std::to_string(dataMember->GetMaxIndex(dim)) + "]";
}
}

auto subField = RFieldBase::Create(dataMember->GetName(), typeName).Unwrap();

const auto normTypeName = ROOT::Internal::GetNormalizedUnresolvedTypeName(origTypeName);
if (normTypeName == subField->GetTypeName()) {
subField->fTypeAlias = "";
} else {
subField->fTypeAlias = normTypeName;
}

fTraits &= subField->GetTraits();
Attach(std::move(subField), RSubFieldInfo{kDataMember, static_cast<std::size_t>(dataMember->GetOffset())});
}
Expand Down
13 changes: 12 additions & 1 deletion tree/ntuple/test/CustomStruct.hxx
Original file line number Diff line number Diff line change
Expand Up @@ -35,9 +35,17 @@ enum class CustomEnumInt64 : long int {};
enum class CustomEnumUInt64 : unsigned long int {};

struct CustomStruct {
template <typename T>
struct VectorWrapper {
std::vector<T> fVec;
};

template <typename T>
using MyVec = std::vector<T>;

template <typename T>
using MyVectorWrapper = VectorWrapper<T>;

float a = 0.0;
std::vector<float> v1;
std::vector<std::vector<float>> v2;
Expand All @@ -64,7 +72,10 @@ struct DerivedA2 : public CustomStruct {
};

struct DerivedWithTypedef : public CustomStruct {
MyVec<int> m;
MyVec<Double32_t> m1;
MyVec<Long64_t> m2;
MyVec<Int_t> m3;
MyVectorWrapper<Long64_t> m4;
};

struct DerivedB : public DerivedA {
Expand Down
1 change: 1 addition & 0 deletions tree/ntuple/test/CustomStructLinkDef.h
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@
#pragma link C++ enum CustomEnumUInt64;

#pragma link C++ class CustomStruct+;
#pragma link C++ class CustomStruct::VectorWrapper<Long64_t>+;
#pragma link C++ class DerivedA+;
#pragma link C++ class DerivedA2+;
#pragma link C++ class DerivedWithTypedef + ;
Expand Down
38 changes: 22 additions & 16 deletions tree/ntuple/test/ntuple_type_name.cxx
Original file line number Diff line number Diff line change
Expand Up @@ -216,13 +216,11 @@ TEST(RNTuple, TypeNameTemplatesNestedAlias)
ASSERT_EQ(2, hashSubfields.size());
EXPECT_EQ("fHash", hashSubfields[0]->GetFieldName());
EXPECT_EQ("std::string", hashSubfields[0]->GetTypeName());
EXPECT_EQ("EdmHash<1>::value_type", hashSubfields[0]->GetTypeAlias());
EXPECT_EQ("", hashSubfields[0]->GetTypeAlias());

EXPECT_EQ("fHash2", hashSubfields[1]->GetFieldName());
EXPECT_EQ("std::string", hashSubfields[1]->GetTypeName());
// FIXME: This should really be EdmHash<1>::value_typeT<EdmHash<1>::value_type>, but this is the value we get from
// TDataMember::GetFullTypeName right now...
EXPECT_EQ("value_typeT<EdmHash<1>::value_type>", hashSubfields[1]->GetTypeAlias());
EXPECT_EQ("", hashSubfields[1]->GetTypeAlias());
}

TEST(RNTuple, ContextDependentTypeNames)
Expand All @@ -236,28 +234,36 @@ TEST(RNTuple, ContextDependentTypeNames)
auto model = RNTupleModel::Create();
auto fieldBase = RFieldBase::Create("foo", "DerivedWithTypedef").Unwrap();
model->AddField(std::move(fieldBase));
auto ntuple = RNTupleWriter::Recreate(std::move(model), "ntpl", fileGuard.GetPath());
auto entry = ntuple->GetModel().CreateBareEntry();
auto ptr = std::make_unique<DerivedWithTypedef>();
entry->BindRawPtr("foo", ptr.get());
for (auto i = 0; i < 10; ++i) {
ptr->m.push_back(i);
ntuple->Fill(*entry);
ptr->m.clear();
}
auto writer = RNTupleWriter::Recreate(std::move(model), "ntpl", fileGuard.GetPath());
}

{
auto reader = RNTupleReader::Open("ntpl", fileGuard.GetPath());
EXPECT_EQ(reader->GetNEntries(), 10);

const auto &desc = reader->GetDescriptor();
const auto fooId = desc.FindFieldId("foo");
const auto baseId = desc.GetFieldDescriptor(fooId).GetLinkIds()[0];
{
const auto &fdesc = desc.GetFieldDescriptor(desc.FindFieldId("m", fooId));
const auto &fdesc = desc.GetFieldDescriptor(desc.FindFieldId("m1", fooId));
EXPECT_EQ(fdesc.GetTypeName(), "std::vector<double>");
// With LLVM20 (ROOT >= v6.38), the next line correctly tests
// EXPECT_EQ(fdesc.GetTypeAlias(), "std::vector<Double32_t>");
EXPECT_TRUE(fdesc.GetTypeAlias().empty());
}
{
const auto &fdesc = desc.GetFieldDescriptor(desc.FindFieldId("m2", fooId));
EXPECT_EQ(fdesc.GetTypeName(), "std::vector<std::int64_t>");
EXPECT_EQ(fdesc.GetTypeAlias(), "");
}
{
const auto &fdesc = desc.GetFieldDescriptor(desc.FindFieldId("m3", fooId));
EXPECT_EQ(fdesc.GetTypeName(), "std::vector<std::int32_t>");
EXPECT_EQ(fdesc.GetTypeAlias(), "MyVec<std::int32_t>");
EXPECT_EQ(fdesc.GetTypeAlias(), "");
}
{
const auto &fdesc = desc.GetFieldDescriptor(desc.FindFieldId("m4", fooId));
EXPECT_EQ(fdesc.GetTypeName(), "CustomStruct::VectorWrapper<std::int64_t>");
EXPECT_EQ(fdesc.GetTypeAlias(), "CustomStruct::VectorWrapper<Long64_t>");
}
{
const auto &fdesc = desc.GetFieldDescriptor(desc.FindFieldId("a", baseId));
Expand Down
23 changes: 16 additions & 7 deletions tree/ntuple/test/ntuple_types.cxx
Original file line number Diff line number Diff line change
Expand Up @@ -2250,9 +2250,15 @@ TEST(RNTuple, ContextDependentTypes)
auto ptr = std::make_unique<DerivedWithTypedef>();
entry->BindRawPtr("foo", ptr.get());
for (auto i = 0; i < 10; ++i) {
ptr->m.push_back(i);
ptr->m1.push_back(i);
ptr->m2.push_back(i);
ptr->m3.push_back(i);
ptr->m4.fVec.push_back(i);
ntuple->Fill(*entry);
ptr->m.clear();
ptr->m1.clear();
ptr->m2.clear();
ptr->m3.clear();
ptr->m4.fVec.clear();
}
}

Expand All @@ -2263,13 +2269,16 @@ TEST(RNTuple, ContextDependentTypes)
const auto &model = reader->GetModel();
const auto &field = model.GetConstField("foo");
EXPECT_EQ(field.GetTypeName(), "DerivedWithTypedef");
const auto &vec = model.GetConstField("foo.m");
EXPECT_EQ(vec.GetTypeName(), "std::vector<std::int32_t>");
EXPECT_EQ(vec.GetTypeAlias(), "MyVec<std::int32_t>");

auto vecView = reader->GetView<DerivedWithTypedef::MyVec<int>>("foo.m");
auto m1View = reader->GetView<DerivedWithTypedef::MyVec<Double32_t>>("foo.m1");
auto m2View = reader->GetView<DerivedWithTypedef::MyVec<Long64_t>>("foo.m2");
auto m3View = reader->GetView<DerivedWithTypedef::MyVec<Int_t>>("foo.m3");
auto m4View = reader->GetView<DerivedWithTypedef::MyVectorWrapper<Long64_t>>("foo.m4");
for (const auto &i : reader->GetEntryRange()) {
EXPECT_EQ(vecView(i), std::vector{static_cast<int>(i)});
EXPECT_DOUBLE_EQ(m1View(i)[0], std::vector<double>{static_cast<double>(i)}[0]);
EXPECT_EQ(m2View(i), std::vector<Long64_t>{static_cast<Long64_t>(i)});
EXPECT_EQ(m3View(i), std::vector<int>{static_cast<int>(i)});
EXPECT_EQ(m4View(i).fVec, std::vector<Long64_t>{static_cast<Long64_t>(i)});
}
}
}
Loading