Skip to content

Commit 2b184ce

Browse files
fix MakeFunctionCallable's codegen for templated operators (#509)
1 parent b0c3e36 commit 2b184ce

File tree

2 files changed

+41
-1
lines changed

2 files changed

+41
-1
lines changed

lib/Interpreter/CppInterOp.cpp

Lines changed: 13 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1862,10 +1862,22 @@ namespace Cpp {
18621862
{
18631863
std::string name;
18641864
{
1865-
llvm::raw_string_ostream stream(name);
1865+
std::string complete_name;
1866+
llvm::raw_string_ostream stream(complete_name);
18661867
FD->getNameForDiagnostic(stream,
18671868
FD->getASTContext().getPrintingPolicy(),
18681869
/*Qualified=*/false);
1870+
1871+
// insert space between template argument list and the function name
1872+
// this is require if the function is `operator<`
1873+
// `operator<<type1, type2, ...>` is invalid syntax
1874+
// whereas `operator< <type1, type2, ...>` is valid
1875+
std::string simple_name = FD->getNameAsString();
1876+
size_t idx = complete_name.find(simple_name, 0) + simple_name.size();
1877+
std::string name_without_template_args = complete_name.substr(0, idx);
1878+
std::string template_args = complete_name.substr(idx);
1879+
name = name_without_template_args +
1880+
(template_args.empty() ? "" : " " + template_args);
18691881
}
18701882
callbuf << name;
18711883
}

unittests/CppInterOp/FunctionReflectionTest.cpp

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1043,6 +1043,34 @@ TEST(FunctionReflectionTest, GetFunctionCallWrapper) {
10431043
FCI_f.Invoke(&res, {nullptr, 0});
10441044
EXPECT_TRUE(res);
10451045
#endif
1046+
1047+
// templated operators
1048+
Interp->process(R"(
1049+
class TOperator{
1050+
public:
1051+
template<typename T>
1052+
bool operator<(T t) { return true; }
1053+
};
1054+
)");
1055+
Cpp::TCppScope_t TOperator = Cpp::GetNamed("TOperator");
1056+
1057+
auto* TOperatorCtor = Cpp::GetDefaultConstructor(TOperator);
1058+
auto FCI_TOperatorCtor = Cpp::MakeFunctionCallable(TOperatorCtor);
1059+
void* toperator = nullptr;
1060+
FCI_TOperatorCtor.Invoke((void*)&toperator);
1061+
1062+
EXPECT_TRUE(toperator);
1063+
std::vector<Cpp::TCppScope_t> operators;
1064+
Cpp::GetOperator(TOperator, Cpp::OP_Less, operators);
1065+
EXPECT_EQ(operators.size(), 1);
1066+
1067+
Cpp::TCppScope_t op_templated = operators[0];
1068+
auto TAI = Cpp::TemplateArgInfo(Cpp::GetType("int"));
1069+
Cpp::TCppScope_t op = Cpp::InstantiateTemplate(op_templated, &TAI, 1);
1070+
auto FCI_op = Cpp::MakeFunctionCallable(op);
1071+
bool boolean = false;
1072+
FCI_op.Invoke((void*)&boolean, {args, /*args_size=*/1}, object);
1073+
EXPECT_TRUE(boolean);
10461074
}
10471075

10481076
TEST(FunctionReflectionTest, IsConstMethod) {

0 commit comments

Comments
 (0)