diff --git a/core/meta/src/TDataMember.cxx b/core/meta/src/TDataMember.cxx index 5042525da8d24..cd41dae094b11 100644 --- a/core/meta/src/TDataMember.cxx +++ b/core/meta/src/TDataMember.cxx @@ -446,7 +446,12 @@ const char *TDataMember::GetTrueTypeName() const Longptr_t TDataMember::GetOffset() const { - if (fOffset>=0) return fOffset; + if (Property() & (kIsStatic | kIsEnum)) { + Error("GetOffset", "Cannot get offset of static or enum data member %s", GetName()); + return -1; + } + + if (fOffset >= 0) return fOffset; R__LOCKGUARD(gInterpreterMutex); //case of an interpreted or emulated class @@ -495,13 +500,17 @@ Longptr_t TDataMember::GetOffset() const Longptr_t TDataMember::GetOffsetCint() const { - if (fOffset>=0) return fOffset; + if (fOffset >= 0) return fOffset; R__LOCKGUARD(gInterpreterMutex); TDataMember *dm = const_cast(this); - if (dm->IsValid()) return gCling->DataMemberInfo_Offset(dm->fInfo); - else return -1; + if (dm->IsValid()) { + Longptr_t offset = gCling->DataMemberInfo_Offset(dm->fInfo); + dm->fOffset = offset; + return offset; + } + return -1; } //////////////////////////////////////////////////////////////////////////////// diff --git a/roottest/root/meta/unit/datamem.cxx b/roottest/root/meta/unit/datamem.cxx index 5dfc46e95df8c..652c37fa4cf31 100644 --- a/roottest/root/meta/unit/datamem.cxx +++ b/roottest/root/meta/unit/datamem.cxx @@ -28,3 +28,21 @@ const int ROOT8499::s_info = ROOT8499::initHelper();"); EXPECT_NE(0, dm->GetOffsetCint()); } +TEST(TDataMemberTests, Issue23777) +{ + // Test that calling GetOffset() does not corrupt or interfere with GetOffsetCint() + TClass *cl = TClass::GetClass("TAttImage"); + ASSERT_NE(nullptr, cl); + TObject *obj = cl->GetListOfDataMembers()->FindObject("kImgBest"); + ASSERT_NE(nullptr, obj); + TDataMember *dm = dynamic_cast(obj); + ASSERT_NE(nullptr, dm); + + EXPECT_STREQ("TAttImage::EImageQuality", dm->GetTypeName()); + // Static and enum members do not have an instance offset; GetOffset() must return -1 + EXPECT_EQ(-1, dm->GetOffset()); + // GetOffsetCint() must return a non-zero address/offset from Cling even after GetOffset() was called + EXPECT_NE(0, dm->GetOffsetCint()); + // GetOffset() must still return -1 even after GetOffsetCint() cached the address + EXPECT_EQ(-1, dm->GetOffset()); +}