From d9ea6b0aa41791e83bcf29f688aac3085181a4c5 Mon Sep 17 00:00:00 2001 From: Jonas Hahnfeld Date: Fri, 8 Aug 2025 13:44:24 +0200 Subject: [PATCH 1/4] [core] Move TClass tests to core/meta The test in core/clingutils is meant for unit testing of TClingUtils and statically links ClingUtils and Cling/Clang/LLVM libraries. Calling Cling, TInterpreter, or TClass results in two copies of the functions being around (in libCling.so and the test binary) with not much guarantees which ones are called at which moment. --- core/clingutils/test/TClingUtilsTests.cxx | 30 ++++------------------- core/meta/test/testTClass.cxx | 24 ++++++++++++++++++ 2 files changed, 29 insertions(+), 25 deletions(-) diff --git a/core/clingutils/test/TClingUtilsTests.cxx b/core/clingutils/test/TClingUtilsTests.cxx index 7380886e60e55..5fbe599b6d5b9 100644 --- a/core/clingutils/test/TClingUtilsTests.cxx +++ b/core/clingutils/test/TClingUtilsTests.cxx @@ -15,15 +15,17 @@ *************************************************************************/ #include -#include -#include + +// This test must under no circumstances include other ROOT headers. It must not call into Cling, TInterpreter, TClass. +// It is meant for unit testing of TClingUtils and statically links ClingUtils and Cling/Clang/LLVM libraries. If the +// test was to do any of the above, there would be two copies of functions around (in libCling.so and the test binary) +// with not much guarantees which ones are called at which moment. #include #include "gtest/gtest.h" #include -#include TEST(TClingUtilsTests, GetCppName) { @@ -88,25 +90,3 @@ TEST(TClingUtilsTests, GetRealPath) std::remove("./realfile2"); #endif // not R__WIN32 } - -TEST(TClingUtilsTests, CollectionSizeof) -{ - // https://its.cern.ch/jira/browse/ROOT-9889 - EXPECT_EQ(sizeof(std::deque), TClass::GetClass("std::deque")->GetClassSize()); - EXPECT_EQ(sizeof(std::deque), TClass::GetClass("std::deque")->GetClassSize()); - EXPECT_EQ(sizeof(std::deque), TClass::GetClass("std::deque")->GetClassSize()); - EXPECT_EQ(sizeof(std::deque), TClass::GetClass("std::deque")->GetClassSize()); - EXPECT_EQ(sizeof(std::deque), TClass::GetClass("std::deque")->GetClassSize()); - EXPECT_EQ(sizeof(std::deque), TClass::GetClass("std::deque")->GetClassSize()); -} - -TEST(TClingUtilsTests, ReSubstTemplateArg) -{ - // #18811 - gInterpreter->Declare("template struct S {};" - "template struct Two { using value_type = S; };" - "template struct One { Two::value_type *t; };"); - - auto c = TClass::GetClass("One"); - c->BuildRealData(); -} diff --git a/core/meta/test/testTClass.cxx b/core/meta/test/testTClass.cxx index fd6b09e7a0b09..7fc7231eed3c5 100644 --- a/core/meta/test/testTClass.cxx +++ b/core/meta/test/testTClass.cxx @@ -7,6 +7,8 @@ #include "gtest/gtest.h" +#include + TEST(TClass, DictCheck) { gInterpreter->ProcessLine(".L stlDictCheck.h+"); @@ -80,3 +82,25 @@ TEST(TClass, ConsistentSTLLookup) auto second = first->GetActualClass(&map); EXPECT_EQ(first, second); } + +TEST(TClass, CollectionSizeof) +{ + // https://its.cern.ch/jira/browse/ROOT-9889 + EXPECT_EQ(sizeof(std::deque), TClass::GetClass("std::deque")->GetClassSize()); + EXPECT_EQ(sizeof(std::deque), TClass::GetClass("std::deque")->GetClassSize()); + EXPECT_EQ(sizeof(std::deque), TClass::GetClass("std::deque")->GetClassSize()); + EXPECT_EQ(sizeof(std::deque), TClass::GetClass("std::deque")->GetClassSize()); + EXPECT_EQ(sizeof(std::deque), TClass::GetClass("std::deque")->GetClassSize()); + EXPECT_EQ(sizeof(std::deque), TClass::GetClass("std::deque")->GetClassSize()); +} + +TEST(TClass, ReSubstTemplateArg) +{ + // #18811 + gInterpreter->Declare("template struct S {};" + "template struct Two { using value_type = S; };" + "template struct One { Two::value_type *t; };"); + + auto c = TClass::GetClass("One"); + c->BuildRealData(); +} From 1244720b3522138d82fe60abad44c0bd920494e9 Mon Sep 17 00:00:00 2001 From: Jonas Hahnfeld Date: Fri, 8 Aug 2025 14:18:00 +0200 Subject: [PATCH 2/4] [core] Remove include RConversionRuleParser.h from TClingUtils.h Fix a couple of missing includes. --- core/clingutils/res/TClingUtils.h | 2 -- core/clingutils/src/TClingUtils.cxx | 1 + core/dictgen/src/XMLReader.cxx | 1 + core/dictgen/src/rootcling_impl.cxx | 1 + core/metacling/src/TClingCallbacks.cxx | 1 + 5 files changed, 4 insertions(+), 2 deletions(-) diff --git a/core/clingutils/res/TClingUtils.h b/core/clingutils/res/TClingUtils.h index afb8b6252dce8..467f271ebe03d 100644 --- a/core/clingutils/res/TClingUtils.h +++ b/core/clingutils/res/TClingUtils.h @@ -12,8 +12,6 @@ #ifndef ROOT_TMetaUtils #define ROOT_TMetaUtils -#include "RConversionRuleParser.h" - #include #include #include diff --git a/core/clingutils/src/TClingUtils.cxx b/core/clingutils/src/TClingUtils.cxx index 699757af88fc8..d8ca763e52866 100644 --- a/core/clingutils/src/TClingUtils.cxx +++ b/core/clingutils/src/TClingUtils.cxx @@ -25,6 +25,7 @@ #include #include "RConfigure.h" +#include "RConversionRuleParser.h" #include #include #include "Rtypes.h" diff --git a/core/dictgen/src/XMLReader.cxx b/core/dictgen/src/XMLReader.cxx index f4a28eae56543..a65b4c633a393 100644 --- a/core/dictgen/src/XMLReader.cxx +++ b/core/dictgen/src/XMLReader.cxx @@ -18,6 +18,7 @@ #include "XMLReader.h" +#include "RConversionRuleParser.h" #include "SelectionRules.h" #include "TClingUtils.h" diff --git a/core/dictgen/src/rootcling_impl.cxx b/core/dictgen/src/rootcling_impl.cxx index cea4c0bbff909..fb5961732e7a1 100644 --- a/core/dictgen/src/rootcling_impl.cxx +++ b/core/dictgen/src/rootcling_impl.cxx @@ -12,6 +12,7 @@ #include "rootclingCommandLineOptionsHelp.h" #include "RConfigure.h" +#include "RConversionRuleParser.h" #include #include #include "snprintf.h" diff --git a/core/metacling/src/TClingCallbacks.cxx b/core/metacling/src/TClingCallbacks.cxx index b3d30495251f7..5f18e0da5b85b 100644 --- a/core/metacling/src/TClingCallbacks.cxx +++ b/core/metacling/src/TClingCallbacks.cxx @@ -11,6 +11,7 @@ #include "TClingCallbacks.h" +#include // for R__EXTERN #include #include "cling/Interpreter/DynamicLibraryManager.h" From c632b917a98cd8d5a32acac61c67ac029db43946 Mon Sep 17 00:00:00 2001 From: Jonas Hahnfeld Date: Fri, 8 Aug 2025 14:18:55 +0200 Subject: [PATCH 3/4] [core] Link clingutils tests only against Core This is (unfortunately) needed for core/foundation headers. --- core/clingutils/test/CMakeLists.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/core/clingutils/test/CMakeLists.txt b/core/clingutils/test/CMakeLists.txt index 15cc3ff48ad0d..a2d5bd79c4a28 100644 --- a/core/clingutils/test/CMakeLists.txt +++ b/core/clingutils/test/CMakeLists.txt @@ -30,4 +30,4 @@ if(NOT builtin_clang) link_directories("${LLVM_LIBRARY_DIR}") endif() -ROOT_ADD_UNITTEST_DIR(Core RIO ${CLING_LIBRARIES} $) +ROOT_ADD_UNITTEST_DIR(Core ${CLING_LIBRARIES} $) From 44e5bb26f3f3ef682836fb6285d32d120fc044eb Mon Sep 17 00:00:00 2001 From: Jonas Hahnfeld Date: Tue, 12 Aug 2025 09:14:16 +0200 Subject: [PATCH 4/4] [core] Enforce uninitialized gCling in test --- core/clingutils/test/TClingUtilsTests.cxx | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/core/clingutils/test/TClingUtilsTests.cxx b/core/clingutils/test/TClingUtilsTests.cxx index 5fbe599b6d5b9..311e124f7953a 100644 --- a/core/clingutils/test/TClingUtilsTests.cxx +++ b/core/clingutils/test/TClingUtilsTests.cxx @@ -21,6 +21,7 @@ // test was to do any of the above, there would be two copies of functions around (in libCling.so and the test binary) // with not much guarantees which ones are called at which moment. +#include #include #include "gtest/gtest.h" @@ -90,3 +91,13 @@ TEST(TClingUtilsTests, GetRealPath) std::remove("./realfile2"); #endif // not R__WIN32 } + +// Forward-declare gCling to not include TInterpreter.h just for checking that the interpreter has not been initialized. +class TInterpreter; +R__EXTERN TInterpreter *gCling; + +class InterpreterCheck : public testing::Environment { + void TearDown() override { ASSERT_EQ(gCling, nullptr); } +}; + +testing::Environment *gInterpreterCheck = testing::AddGlobalTestEnvironment(new InterpreterCheck);