From 35b42b99a05cdcea3f5f18aa7711440c7cd44547 Mon Sep 17 00:00:00 2001 From: Danilo Piparo Date: Tue, 18 Aug 2026 21:01:46 +0200 Subject: [PATCH 1/2] [meta] Ctor name lookup is not enough for the class info the mechanism in place to allow the initialisation of TClingClassInfo based on names of forward declared classes was a bit too loose. It also allowed for finding a class by the name of its constructor. Fixes ROOT-10311 --- core/metacling/src/TClingClassInfo.cxx | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/core/metacling/src/TClingClassInfo.cxx b/core/metacling/src/TClingClassInfo.cxx index 434996e2cb5aa..6a703d627cb1a 100644 --- a/core/metacling/src/TClingClassInfo.cxx +++ b/core/metacling/src/TClingClassInfo.cxx @@ -99,9 +99,14 @@ TClingClassInfo::TClingClassInfo(cling::Interpreter *interp, const char *name, b &type, intantiateTemplate); } } + // The lookup finds the decl if the name corresponds to a namespace or a fully defined + // class; just a type in presence of a forward declaration of a class. + // This code identifies that case and prevents that a class type is found if the name + // of a constructor is passed (see ROOT-10311). if (!decl && type) { - if (const auto *TD = type->getAsTagDecl()) { - decl = TD; + const auto *CXXRD = type->getAsCXXRecordDecl(); + if (CXXRD && !CXXRD->hasDefinition()) { + decl = CXXRD; } } SetDecl(decl); From b51209a4e02a72506c267ae56c7a272e238eb9fe Mon Sep 17 00:00:00 2001 From: Danilo Piparo Date: Thu, 20 Aug 2026 16:20:41 +0200 Subject: [PATCH 2/2] [meta] Add a test for ROOT-10311 --- core/metacling/test/TClingTests.cxx | 21 ++++++++++++++++++++- 1 file changed, 20 insertions(+), 1 deletion(-) diff --git a/core/metacling/test/TClingTests.cxx b/core/metacling/test/TClingTests.cxx index 2a54d12864dd3..ec9833264f82e 100644 --- a/core/metacling/test/TClingTests.cxx +++ b/core/metacling/test/TClingTests.cxx @@ -467,4 +467,23 @@ using func0_ret_t = typename ROOT::TypeTraits::CallableTraits:: auto res = gInterpreter->Declare(expression.c_str()); EXPECT_TRUE(res); } -#endif \ No newline at end of file +#endif + +// ROOT-10311 +TEST_F(TClingTests, TClassByCtorName) +{ + auto res = gInterpreter->Declare("namespace TClassByCtorName{class Foo;};"); + EXPECT_TRUE(res); + { + ROOT::TestSupport::CheckDiagsRAII checkDiag; + checkDiag.requiredDiag(kWarning, "TClass::Init", "no dictionary for class TClassByCtorName::Foo is available", false); + EXPECT_TRUE(nullptr != TClass::GetClass("TClassByCtorName::Foo")); + } + const auto *wrongName = "TTree::TTree"; + EXPECT_TRUE(nullptr == TClass::GetClass(wrongName)); + EXPECT_TRUE(nullptr != TClass::GetClass("TTree")); + + std::string classInterpreterName; + gInterpreter->GetInterpreterTypeName(wrongName, classInterpreterName); + EXPECT_STREQ(classInterpreterName.c_str(), ""); +}