diff --git a/core/base/test/CMakeLists.txt b/core/base/test/CMakeLists.txt index d45732eb43935..7aae746725a39 100644 --- a/core/base/test/CMakeLists.txt +++ b/core/base/test/CMakeLists.txt @@ -23,6 +23,7 @@ ROOT_ADD_GTEST(CoreBaseTests TStringTest.cxx TUrlTest.cxx TBitsTests.cxx + TRefTests.cxx LIBRARIES ${extralibs} RIO Core) ROOT_ADD_GTEST(CoreErrorTests TErrorTests.cxx LIBRARIES Core) diff --git a/core/base/test/TRefTests.cxx b/core/base/test/TRefTests.cxx new file mode 100644 index 0000000000000..aab7e2bec06b2 --- /dev/null +++ b/core/base/test/TRefTests.cxx @@ -0,0 +1,47 @@ +#include "gtest/gtest.h" + +#include "TClass.h" +#include "TInterpreter.h" +#include "TStreamerElement.h" +#include "TVirtualStreamerInfo.h" + +#include + +// See ROOT-7052 +TEST(TRef, Exec) +{ + + // Needed because we do not generate dictionaries and we do no not want to see warnings + ROOT::TestSupport::CheckDiagsRAII checkDiag; + checkDiag.requiredDiag(kWarning, "TStreamerInfo::Build", "MyClass: ", /*matchFullMessage=*/false); + + gInterpreter->ProcessLine("class Foo1 : public TRef {\n" + " int i;\n" + "ClassDef(Foo1, 1);\n" + "};" + "class Foo2 : public TRefArray {\n" + " int i;\n" + "ClassDef(Foo2, 1);\n" + "};" + "class TRefFoo {int i;};\n" + "class Foo3 {int i;};\n" + " class MyClass {\n" + " Foo1 m1; // EXEC:GetFoo\n" + " Foo2 m2; // EXEC:GetFoo\n" + " TRefFoo m3; // EXEC:GetFoo\n" + " Foo3 m4; // EXEC:GetFoo\n" + "};"); + + auto c = TClass::GetClass("MyClass"); + auto si = c->GetStreamerInfo(); + int o; + auto se1 = si->GetStreamerElement("m1", o); + auto se2 = si->GetStreamerElement("m2", o); + auto se3 = si->GetStreamerElement("m3", o); + auto se4 = si->GetStreamerElement("m4", o); + + EXPECT_EQ(1, se1->GetExecID()); + EXPECT_EQ(1, se2->GetExecID()); + EXPECT_EQ(0, se3->GetExecID()); + EXPECT_EQ(0, se4->GetExecID()); +} \ No newline at end of file diff --git a/core/meta/src/TStreamerElement.cxx b/core/meta/src/TStreamerElement.cxx index 43bbad87fa099..8d216d3383522 100644 --- a/core/meta/src/TStreamerElement.cxx +++ b/core/meta/src/TStreamerElement.cxx @@ -9,12 +9,6 @@ * For the list of contributors see $ROOTSYS/README/CREDITS. * *************************************************************************/ -////////////////////////////////////////////////////////////////////////// -// // -// // -////////////////////////////////////////////////////////////////////////// - - #include "TROOT.h" #include "TStreamerElement.h" #include "TVirtualStreamerInfo.h" @@ -308,8 +302,15 @@ TClass *TStreamerElement::GetClassPointer() const Int_t TStreamerElement::GetExecID() const { - //check if element is a TRef or TRefArray - if (strncmp(fTypeName.Data(),"TRef",4) != 0) return 0; + TString typeName = fTypeName; + if (typeName != "TRef" && typeName != "TRefArray") { + // It's not a ROOT standard TRef or TRefArray class, but it could be a user class + // inheriting from it (see ROOT-7052) + const TString clName = ExtractClassName(fTypeName); + const auto cl = TClass::GetClass(clName, kFALSE, kTRUE); + if (!cl || (nullptr == cl->GetBaseClass("TRef") && nullptr == cl->GetBaseClass("TRefArray"))) + return 0; + } //if the UniqueID of this element has already been set, we assume //that it contains the exec id of a TRef object.