Skip to content
Merged
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
32 changes: 30 additions & 2 deletions lib/CppInterOp/CppInterOp.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -616,8 +616,6 @@
Type = Type->getUnqualifiedDesugaredType();
if (auto* ET = llvm::dyn_cast<EnumType>(Type))
return ET->getDecl();
if (auto* FnType = llvm::dyn_cast<FunctionProtoType>(Type))
Type = const_cast<clang::Type*>(FnType->getReturnType().getTypePtr());
return Type->getAsCXXRecordDecl();
}
return 0;
Expand Down Expand Up @@ -1689,6 +1687,10 @@
PrintingPolicy Policy((LangOptions()));
Policy.Bool = true; // Print bool instead of _Bool.
Policy.SuppressTagKeyword = true; // Do not print `class std::string`.
#if CLANG_VERSION_MAJOR > 16
Policy.SuppressElaboration = true;
#endif
Policy.FullyQualifiedName = true;
return compat::FixTypeName(QT.getAsString(Policy));
}

Expand Down Expand Up @@ -2103,6 +2105,30 @@
std::string template_args = complete_name.substr(idx);
name = name_without_template_args +
(template_args.empty() ? "" : " " + template_args);

// 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.
if (FD->isTemplateInstantiation() && FD->getPrimaryTemplate()) {
const FunctionTemplateDecl* FTDecl =
llvm::dyn_cast<FunctionTemplateDecl>(FD->getPrimaryTemplate());
if (FTDecl) {
auto* templateParms = FTDecl->getTemplateParameters();
int numPacks = 0;
for (size_t iParam = 0, nParams = templateParms->size();
iParam < nParams; ++iParam) {
if (templateParms->getParam(iParam)->isTemplateParameterPack())
numPacks += 1;
else
numPacks = 0;
}
if (numPacks > 1) {
name = name_without_template_args;
}
}
}
}
if (op_flag || N <= 1)
callbuf << name;
Expand Down Expand Up @@ -3422,6 +3448,8 @@
// This will instantiate tape<T> type and return it.
SourceLocation noLoc;
QualType TT = S.CheckTemplateIdType(TemplateName(TemplateD), noLoc, TLI);
if (TT.isNull())
return nullptr;

Check warning on line 3452 in lib/CppInterOp/CppInterOp.cpp

View check run for this annotation

Codecov / codecov/patch

lib/CppInterOp/CppInterOp.cpp#L3452

Added line #L3452 was not covered by tests
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'd drop that if we can't cover it with tests.

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is required; it is due to a template instantiation failing in Eigen (crashes).
Also, fixing the instantiation in this PR does not make sense. Will look into that once I get to the eigen tests.
And writing a test that is supposed to fail is bad again.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ok. Understood

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Let’s merge it then.


// Perhaps we can extract this into a new interface.
S.RequireCompleteType(fakeLoc, TT, diag::err_tentative_def_incomplete_type);
Expand Down
25 changes: 25 additions & 0 deletions unittests/CppInterOp/FunctionReflectionTest.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1969,6 +1969,31 @@ TEST(FunctionReflectionTest, GetFunctionCallWrapper) {
EXPECT_TRUE(err_msg.find("instantiation with no body") != std::string::npos);
EXPECT_EQ(instantiation_in_host_callable.getKind(),
Cpp::JitCall::kUnknown); // expect to fail

Interp->process(R"(
template<typename ...T>
struct tuple {};

template<typename ...Ts, typename ...TTs>
void tuple_tuple(tuple<Ts...> one, tuple<TTs...> two) { return; }

tuple<int, double> tuple_one;
tuple<char, char> tuple_two;
)");

unresolved_candidate_methods.clear();
Cpp::GetClassTemplatedMethods("tuple_tuple", Cpp::GetGlobalScope(),
unresolved_candidate_methods);
EXPECT_EQ(unresolved_candidate_methods.size(), 1);

Cpp::TCppScope_t tuple_tuple = Cpp::BestOverloadFunctionMatch(
unresolved_candidate_methods, {},
{Cpp::GetVariableType(Cpp::GetNamed("tuple_one")),
Cpp::GetVariableType(Cpp::GetNamed("tuple_two"))});
EXPECT_TRUE(tuple_tuple);

auto tuple_tuple_callable = Cpp::MakeFunctionCallable(tuple_tuple);
EXPECT_EQ(tuple_tuple_callable.getKind(), Cpp::JitCall::kGenericCall);
}

TEST(FunctionReflectionTest, IsConstMethod) {
Expand Down
Loading