Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
17 changes: 6 additions & 11 deletions interpreter/CppInterOp/lib/CppInterOp/CppInterOp.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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<<type1, type2, ...>` is invalid syntax
// whereas `operator< <type1, type2, ...>` 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<FunctionTemplateDecl>(FD->getPrimaryTemplate());
Expand All @@ -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;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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<typename T1, typename T2>
struct Product {};

template<typename T>
struct KlassProduct {
template<typename O>
const Product<T, O>
operator*(const KlassProduct<O> &other) const { return Product<T, O>(); }

template<typename TT, typename O>
const Product<TT, O>
operator*(const KlassProduct<O> &other) const { return Product<TT, O>(); }
};
)");

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) {
Expand Down
Loading