diff --git a/lib/Interpreter/CppInterOp.cpp b/lib/Interpreter/CppInterOp.cpp index 6eed01289..a1b3b97da 100644 --- a/lib/Interpreter/CppInterOp.cpp +++ b/lib/Interpreter/CppInterOp.cpp @@ -993,11 +993,17 @@ namespace Cpp { // actual types. We make this match solely based on count const FunctionDecl* func = TFD->getTemplatedDecl(); - if (func->getNumParams() != arg_types.size()) + +#ifdef USE_CLING + if (func->getNumParams() > arg_types.size()) continue; +#else // CLANG_REPL + if (func->getMinRequiredArguments() > arg_types.size()) + continue; +#endif // FIXME : first score based on the type similarity before forcing - // instantiation try instantiating + // instantiation. TCppFunction_t instantiated = InstantiateTemplate(candidate, arg_types.data(), arg_types.size()); if (instantiated) diff --git a/unittests/CppInterOp/FunctionReflectionTest.cpp b/unittests/CppInterOp/FunctionReflectionTest.cpp index afa5a584d..5b76e1001 100644 --- a/unittests/CppInterOp/FunctionReflectionTest.cpp +++ b/unittests/CppInterOp/FunctionReflectionTest.cpp @@ -589,6 +589,60 @@ TEST(FunctionReflectionTest, InstantiateTemplateMethod) { EXPECT_TRUE(TA1.getAsType()->isIntegerType()); } +TEST(FunctionReflectionTest, BestTemplateFunctionMatch) { + std::vector Decls; + std::string code = R"( + class MyTemplatedMethodClass { + public: + template long get_size(A&); + template long get_size(); + template long get_size(A a, B b); + }; + + template + long MyTemplatedMethodClass::get_size(A&) { + return sizeof(A); + } + + template + long MyTemplatedMethodClass::get_size() { + return sizeof(A) + 1; + } + + template + long MyTemplatedMethodClass::get_size(A a, B b) { + return sizeof(A) + sizeof(B); + } + )"; + + GetAllTopLevelDecls(code, Decls); + std::vector candidates; + + for (auto decl : Decls) + if (Cpp::IsTemplatedFunction(decl)) candidates.push_back((Cpp::TCppFunction_t)decl); + + ASTContext& C = Interp->getCI()->getASTContext(); + + std::vector args0; + std::vector args1 = {C.IntTy.getAsOpaquePtr()}; + std::vector args2 = {C.CharTy.getAsOpaquePtr(), C.FloatTy.getAsOpaquePtr()}; + + std::vector explicit_args0; + std::vector explicit_args1 = {C.IntTy.getAsOpaquePtr()}; + + + Cpp::TCppFunction_t func1 = Cpp::BestTemplateFunctionMatch(candidates, explicit_args0, args1); + Cpp::TCppFunction_t func2 = Cpp::BestTemplateFunctionMatch(candidates, explicit_args1, args0); + Cpp::TCppFunction_t func3 = Cpp::BestTemplateFunctionMatch(candidates, explicit_args0, args2); + + EXPECT_EQ(Cpp::GetFunctionSignature(func1), + "template<> long MyTemplatedMethodClass::get_size(int &)"); + EXPECT_EQ(Cpp::GetFunctionSignature(func2), + "template<> long MyTemplatedMethodClass::get_size()"); + EXPECT_EQ(Cpp::GetFunctionSignature(func3), + "template<> long MyTemplatedMethodClass::get_size(char a, float b)"); +} + TEST(FunctionReflectionTest, IsPublicMethod) { std::vector Decls, SubDecls; std::string code = R"(