diff --git a/interpreter/CppInterOp/lib/CppInterOp/CppInterOp.cpp b/interpreter/CppInterOp/lib/CppInterOp/CppInterOp.cpp index b4dd7ad74a411..38ae61a43c5f0 100644 --- a/interpreter/CppInterOp/lib/CppInterOp/CppInterOp.cpp +++ b/interpreter/CppInterOp/lib/CppInterOp/CppInterOp.cpp @@ -2098,22 +2098,14 @@ void make_narg_call(const FunctionDecl* FD, const std::string& return_type, FD->getNameForDiagnostic(stream, PP, /*Qualified=*/false); - // insert space between template argument list and the function name - // this is require if the function is `operator<` - // `operator<` is invalid syntax - // whereas `operator< ` is valid - std::string simple_name = FD->getNameAsString(); - size_t idx = complete_name.find(simple_name, 0) + simple_name.size(); - std::string name_without_template_args = complete_name.substr(0, idx); - std::string template_args = complete_name.substr(idx); - name = name_without_template_args + - (template_args.empty() ? "" : " " + template_args); + name = complete_name; // If a template has consecutive parameter packs, then it is impossible to // use the explicit name in the wrapper, since the type deduction is what // determines the split of the packs. Instead, we'll revert to the // non-templated function name and hope that the type casts in the wrapper // will suffice. + std::string simple_name = FD->getNameAsString(); if (FD->isTemplateInstantiation() && FD->getPrimaryTemplate()) { const FunctionTemplateDecl* FTDecl = llvm::dyn_cast(FD->getPrimaryTemplate()); @@ -2128,10 +2120,13 @@ void make_narg_call(const FunctionDecl* FD, const std::string& return_type, numPacks = 0; } if (numPacks > 1) { - name = name_without_template_args; + name = simple_name; } } } + if (FD->isOverloadedOperator()) { + name = simple_name; + } } if (op_flag || N <= 1) callbuf << name; diff --git a/interpreter/CppInterOp/unittests/CppInterOp/FunctionReflectionTest.cpp b/interpreter/CppInterOp/unittests/CppInterOp/FunctionReflectionTest.cpp index d5cc81e78b1f2..b558ebfb98ea2 100644 --- a/interpreter/CppInterOp/unittests/CppInterOp/FunctionReflectionTest.cpp +++ b/interpreter/CppInterOp/unittests/CppInterOp/FunctionReflectionTest.cpp @@ -2009,6 +2009,44 @@ TEST(FunctionReflectionTest, GetFunctionCallWrapper) { auto bar_callable = Cpp::MakeFunctionCallable(bar); EXPECT_EQ(bar_callable.getKind(), Cpp::JitCall::kGenericCall); + + Cpp::Declare(R"( + template + struct Product {}; + + template + struct KlassProduct { + template + const Product + operator*(const KlassProduct &other) const { return Product(); } + + template + const Product + operator*(const KlassProduct &other) const { return Product(); } + }; + )"); + + Cpp::TCppScope_t KlassProduct = Cpp::GetNamed("KlassProduct"); + EXPECT_TRUE(KlassProduct); + + Cpp::TCppScope_t KlassProduct_int = + Cpp::InstantiateTemplate(KlassProduct, &TAI, 1); + EXPECT_TRUE(KlassProduct_int); + TAI = Cpp::TemplateArgInfo(Cpp::GetType("float")); + Cpp::TCppScope_t KlassProduct_float = + Cpp::InstantiateTemplate(KlassProduct, &TAI, 1); + EXPECT_TRUE(KlassProduct_float); + + operators.clear(); + Cpp::GetOperator(KlassProduct_int, Cpp::OP_Star, operators); + EXPECT_EQ(operators.size(), 2); + + op = Cpp::BestOverloadFunctionMatch( + operators, {}, {{Cpp::GetTypeFromScope(KlassProduct_float)}}); + EXPECT_TRUE(op); + + auto op_callable = Cpp::MakeFunctionCallable(op); + EXPECT_EQ(op_callable.getKind(), Cpp::JitCall::kGenericCall); } TEST(FunctionReflectionTest, IsConstMethod) {