Skip to content

Commit 4a789b0

Browse files
committed
[ntuple] fix TClass initializatin in RField<UserClass>
In the templated version of the RClassField, the type name passed to TClass::GetClass() must not use the RNTuple normalized name but the demangled name or the meta normalized name. Otherwise, RNTuple may normalize, e.g., `long long` to `std::int64_t`, which in turn gets normalized by Meta to `unsigned long`.
1 parent c4b3303 commit 4a789b0

File tree

4 files changed

+27
-1
lines changed

4 files changed

+27
-1
lines changed

tree/ntuple/inc/ROOT/RField.hxx

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -225,6 +225,8 @@ public:
225225
/// For polymorphic classes (that declare or inherit at least one virtual method), return the expected dynamic type
226226
/// of any user object. If the class is not polymorphic, return nullptr.
227227
const std::type_info *GetPolymorphicTypeInfo() const;
228+
/// Return the TClass instance backing this field.
229+
const TClass *GetClass() const { return fClass; }
228230
void AcceptVisitor(ROOT::Detail::RFieldVisitor &visitor) const final;
229231
};
230232

@@ -316,7 +318,7 @@ template <typename T, typename = void>
316318
class RField final : public RClassField {
317319
public:
318320
static std::string TypeName() { return ROOT::Internal::GetRenormalizedTypeName(typeid(T)); }
319-
RField(std::string_view name) : RClassField(name, TypeName())
321+
RField(std::string_view name) : RClassField(name, Internal::GetDemangledTypeName(typeid(T)))
320322
{
321323
static_assert(std::is_class_v<T>, "no I/O support for this basic C++ type");
322324
}

tree/ntuple/test/CustomStruct.hxx

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -103,6 +103,12 @@ public:
103103
T fMember;
104104
};
105105

106+
class EdmContainer {
107+
public:
108+
// Used to test that the streamer info for fWrapper will use long long
109+
EdmWrapper<long long> fWrapper;
110+
};
111+
106112
template <typename T>
107113
struct EdmHashTrait {
108114
using value_type = T;

tree/ntuple/test/CustomStructLinkDef.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,8 @@
2929

3030
#pragma link C++ class EdmWrapper<CustomStruct> +;
3131
#pragma link C++ class EdmHash < 1> + ;
32+
#pragma link C++ class EdmWrapper<long long>+;
33+
#pragma link C++ class EdmContainer;
3234

3335
#pragma link C++ class DataVector < int, double> + ;
3436
#pragma link C++ class DataVector < int, float> + ;

tree/ntuple/test/rfield_class.cxx

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -371,3 +371,19 @@ TEST(RNTuple, PolymorphicPointer)
371371
EXPECT_THROW(writer->Fill(), ROOT::RException);
372372
}
373373
}
374+
375+
TEST(RNTuple, TClassMetaName)
376+
{
377+
auto f1 = ROOT::RClassField("f", "EdmWrapper<long long>");
378+
EXPECT_STREQ("EdmWrapper<Long64_t>", f1.GetClass()->GetName());
379+
380+
auto f2 = std::make_unique<ROOT::RField<EdmWrapper<long long>>>("f");
381+
EXPECT_STREQ("EdmWrapper<Long64_t>", static_cast<ROOT::RClassField *>(f2.get())->GetClass()->GetName());
382+
383+
auto f3 = RFieldBase::Create("f", "EdmWrapper<long long>").Unwrap();
384+
EXPECT_STREQ("EdmWrapper<Long64_t>", static_cast<ROOT::RClassField *>(f3.get())->GetClass()->GetName());
385+
386+
auto f4 = RFieldBase::Create("f", "EdmContainer").Unwrap();
387+
EXPECT_STREQ("EdmWrapper<Long64_t>",
388+
static_cast<const ROOT::RClassField *>(f4->GetConstSubfields()[0])->GetClass()->GetName());
389+
}

0 commit comments

Comments
 (0)