Skip to content

Commit

Permalink
Update template function selection to use min required args (#309)
Browse files Browse the repository at this point in the history
  • Loading branch information
aaronj0 authored Jul 16, 2024
1 parent e0fa91e commit cff06c7
Show file tree
Hide file tree
Showing 2 changed files with 62 additions and 2 deletions.
10 changes: 8 additions & 2 deletions lib/Interpreter/CppInterOp.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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)
Expand Down
54 changes: 54 additions & 0 deletions unittests/CppInterOp/FunctionReflectionTest.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -589,6 +589,60 @@ TEST(FunctionReflectionTest, InstantiateTemplateMethod) {
EXPECT_TRUE(TA1.getAsType()->isIntegerType());
}

TEST(FunctionReflectionTest, BestTemplateFunctionMatch) {
std::vector<Decl*> Decls;
std::string code = R"(
class MyTemplatedMethodClass {
public:
template<class A> long get_size(A&);
template<class A> long get_size();
template<class A, class B> long get_size(A a, B b);
};
template<class A>
long MyTemplatedMethodClass::get_size(A&) {
return sizeof(A);
}
template<class A>
long MyTemplatedMethodClass::get_size() {
return sizeof(A) + 1;
}
template<class A, class B>
long MyTemplatedMethodClass::get_size(A a, B b) {
return sizeof(A) + sizeof(B);
}
)";

GetAllTopLevelDecls(code, Decls);
std::vector<Cpp::TCppFunction_t> candidates;

for (auto decl : Decls)
if (Cpp::IsTemplatedFunction(decl)) candidates.push_back((Cpp::TCppFunction_t)decl);

ASTContext& C = Interp->getCI()->getASTContext();

std::vector<Cpp::TemplateArgInfo> args0;
std::vector<Cpp::TemplateArgInfo> args1 = {C.IntTy.getAsOpaquePtr()};
std::vector<Cpp::TemplateArgInfo> args2 = {C.CharTy.getAsOpaquePtr(), C.FloatTy.getAsOpaquePtr()};

std::vector<Cpp::TemplateArgInfo> explicit_args0;
std::vector<Cpp::TemplateArgInfo> 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>(int &)");
EXPECT_EQ(Cpp::GetFunctionSignature(func2),
"template<> long MyTemplatedMethodClass::get_size<int>()");
EXPECT_EQ(Cpp::GetFunctionSignature(func3),
"template<> long MyTemplatedMethodClass::get_size<char, float>(char a, float b)");
}

TEST(FunctionReflectionTest, IsPublicMethod) {
std::vector<Decl *> Decls, SubDecls;
std::string code = R"(
Expand Down

0 comments on commit cff06c7

Please sign in to comment.