Skip to content

Commit cff06c7

Browse files
authored
Update template function selection to use min required args (#309)
1 parent e0fa91e commit cff06c7

File tree

2 files changed

+62
-2
lines changed

2 files changed

+62
-2
lines changed

lib/Interpreter/CppInterOp.cpp

+8-2
Original file line numberDiff line numberDiff line change
@@ -993,11 +993,17 @@ namespace Cpp {
993993
// actual types. We make this match solely based on count
994994

995995
const FunctionDecl* func = TFD->getTemplatedDecl();
996-
if (func->getNumParams() != arg_types.size())
996+
997+
#ifdef USE_CLING
998+
if (func->getNumParams() > arg_types.size())
997999
continue;
1000+
#else // CLANG_REPL
1001+
if (func->getMinRequiredArguments() > arg_types.size())
1002+
continue;
1003+
#endif
9981004

9991005
// FIXME : first score based on the type similarity before forcing
1000-
// instantiation try instantiating
1006+
// instantiation.
10011007
TCppFunction_t instantiated =
10021008
InstantiateTemplate(candidate, arg_types.data(), arg_types.size());
10031009
if (instantiated)

unittests/CppInterOp/FunctionReflectionTest.cpp

+54
Original file line numberDiff line numberDiff line change
@@ -589,6 +589,60 @@ TEST(FunctionReflectionTest, InstantiateTemplateMethod) {
589589
EXPECT_TRUE(TA1.getAsType()->isIntegerType());
590590
}
591591

592+
TEST(FunctionReflectionTest, BestTemplateFunctionMatch) {
593+
std::vector<Decl*> Decls;
594+
std::string code = R"(
595+
class MyTemplatedMethodClass {
596+
public:
597+
template<class A> long get_size(A&);
598+
template<class A> long get_size();
599+
template<class A, class B> long get_size(A a, B b);
600+
};
601+
602+
template<class A>
603+
long MyTemplatedMethodClass::get_size(A&) {
604+
return sizeof(A);
605+
}
606+
607+
template<class A>
608+
long MyTemplatedMethodClass::get_size() {
609+
return sizeof(A) + 1;
610+
}
611+
612+
template<class A, class B>
613+
long MyTemplatedMethodClass::get_size(A a, B b) {
614+
return sizeof(A) + sizeof(B);
615+
}
616+
)";
617+
618+
GetAllTopLevelDecls(code, Decls);
619+
std::vector<Cpp::TCppFunction_t> candidates;
620+
621+
for (auto decl : Decls)
622+
if (Cpp::IsTemplatedFunction(decl)) candidates.push_back((Cpp::TCppFunction_t)decl);
623+
624+
ASTContext& C = Interp->getCI()->getASTContext();
625+
626+
std::vector<Cpp::TemplateArgInfo> args0;
627+
std::vector<Cpp::TemplateArgInfo> args1 = {C.IntTy.getAsOpaquePtr()};
628+
std::vector<Cpp::TemplateArgInfo> args2 = {C.CharTy.getAsOpaquePtr(), C.FloatTy.getAsOpaquePtr()};
629+
630+
std::vector<Cpp::TemplateArgInfo> explicit_args0;
631+
std::vector<Cpp::TemplateArgInfo> explicit_args1 = {C.IntTy.getAsOpaquePtr()};
632+
633+
634+
Cpp::TCppFunction_t func1 = Cpp::BestTemplateFunctionMatch(candidates, explicit_args0, args1);
635+
Cpp::TCppFunction_t func2 = Cpp::BestTemplateFunctionMatch(candidates, explicit_args1, args0);
636+
Cpp::TCppFunction_t func3 = Cpp::BestTemplateFunctionMatch(candidates, explicit_args0, args2);
637+
638+
EXPECT_EQ(Cpp::GetFunctionSignature(func1),
639+
"template<> long MyTemplatedMethodClass::get_size<int>(int &)");
640+
EXPECT_EQ(Cpp::GetFunctionSignature(func2),
641+
"template<> long MyTemplatedMethodClass::get_size<int>()");
642+
EXPECT_EQ(Cpp::GetFunctionSignature(func3),
643+
"template<> long MyTemplatedMethodClass::get_size<char, float>(char a, float b)");
644+
}
645+
592646
TEST(FunctionReflectionTest, IsPublicMethod) {
593647
std::vector<Decl *> Decls, SubDecls;
594648
std::string code = R"(

0 commit comments

Comments
 (0)