From 972cc1ed68e73df9a81a252fbb587b84f6ce58e4 Mon Sep 17 00:00:00 2001 From: Axel Naumann Date: Fri, 7 May 2021 18:25:08 +0200 Subject: [PATCH] [metacling] Test issue #7955. --- core/metacling/test/TClingMethodInfoTests.cxx | 142 ++++++++++++++++++ 1 file changed, 142 insertions(+) diff --git a/core/metacling/test/TClingMethodInfoTests.cxx b/core/metacling/test/TClingMethodInfoTests.cxx index de3da8684afa3..74a2235b63944 100644 --- a/core/metacling/test/TClingMethodInfoTests.cxx +++ b/core/metacling/test/TClingMethodInfoTests.cxx @@ -5,10 +5,13 @@ #include "TList.h" #include "TListOfFunctions.h" #include "TMethod.h" +#include "TMethodArg.h" #include "TROOT.h" #include "gtest/gtest.h" +#include + TEST(TClingMethodInfo, Prototype) { TClass *cl = TClass::GetClass("TObject"); @@ -555,3 +558,142 @@ namespace BUG6578 { std::cerr << " " << iCtorExpected.first << '\n'; } } + +// https://github.com/root-project/root/issues/7955 +TEST(TClingMethodInfo, NonDependentMemberTypes) +{ + gInterpreter->Declare(R"CODE( +struct AScope { + using TheType = int; +}; + + +template +struct Template1 { + using type1 = int; + using type2 = AScope; + void f0(type1); + void f1(type1*); + void g0(type2); + void g1(type2*); + void g2(type2::TheType); + void g3(type2::TheType*); +}; + +Template1 xf1; + +struct X1 { + void f1(Template1::type1) {} + void f2(Template1::type2) {} + void g1(Template1::type1) {} + void g2(Template1::type2) {} +}; + +struct Y1: Template1 { + void yf1(type1); + void yf2(type2); + void yf3(type2::TheType); +}; + +template using TAlias1 = Template1; +struct Z1 { + void f1(TAlias1::type1) {} + void f2(TAlias1::type2) {} + void g1(TAlias1::type1) {} + void g2(TAlias1::type2) {} +}; + +template +struct Template2 { + struct Inner { + using type = AScope; + }; + void f(typename Inner::type); +}; + +Template2 xf2; + +struct Y2 { + void g(Template2::Inner::type) {} + void h(Template2::Inner::type) {} +}; + +struct Z2: Template2 { + void one(Inner::type); +}; +)CODE"); + + + auto checkClass = [](const char *className, std::unordered_map funcPar0) { + TClass *cl = TClass::GetClass(className); + ASSERT_NE(cl, nullptr); + TListOfFunctions *methods = (TListOfFunctions *)cl->GetListOfMethods(); + for (TMethod *method : TRangeDynCast(methods)) { + auto args = method->GetListOfMethodArgs(); + if (args->GetSize() != 1) + continue; + auto arg0 = (TMethodArg*) args->At(0); + auto iExpected = funcPar0.find(std::string(method->GetName())); + if (iExpected == funcPar0.end()) + continue; + EXPECT_EQ(iExpected->second, arg0->GetFullTypeName()) + << " in function " << className << "::" << method->GetName(); + funcPar0.erase(iExpected); + } + EXPECT_EQ(funcPar0.size(), 0); + }; + checkClass("Template1", { + {"f0", "Template1::type1"}, + {"f1", "Template1::type1*"}, + {"g0", "Template1::type2"}, + {"g1", "Template1::type2*"}, + {"g2", "AScope::TheType"}, + {"g3", "AScope::TheType*"}}); + + // This one was giving "Template1::type1" before: + checkClass("Template1", { + {"f0", "Template1::type1"}, + {"f1", "Template1::type1*"}, + {"g0", "Template1::type2"}, + {"g1", "Template1::type2*"}, + {"g2", "AScope::TheType"}, + {"g3", "AScope::TheType*"}}); + + checkClass("TAlias1", { + {"f0", "Template1::type1"}, + {"f1", "Template1::type1*"}, + {"g0", "Template1::type2"}, + {"g1", "Template1::type2*"}, + {"g2", "AScope::TheType"}, + {"g3", "AScope::TheType*"}}); + + checkClass("X1", { + {"f1", "Template1::type1"}, + {"f2", "Template1::type2"}, + {"g1", "Template1::type1"}, + {"g2", "Template1::type2"}}); + + checkClass("Y1", { + {"yf1", "Template1::type1"}, + {"yf2", "Template1::type2"}, + {"yf3", "AScope::TheType"}}); + + checkClass("Z1", { + {"f1", "Template1::type1"}, + {"f2", "Template1::type2"}, + {"g1", "Template1::type1"}, + {"g2", "Template1::type2"}}); + + checkClass("Template2", { + {"f", "Template2::Inner::type"}}); + + checkClass("Template2", { + {"f", "Template2::Inner::type"}}); + + checkClass("Y2", { + {"g", "Template2::Inner::type"}, + {"h", "Template2::Inner::type"}}); + + checkClass("Z2", { + {"one", "Template2::Inner::type"}}); +}