From a5b4c5ee0e2c2b6834ea92431d1beb46527953b3 Mon Sep 17 00:00:00 2001 From: Vipul Cariappa Date: Wed, 26 Nov 2025 14:49:35 +0100 Subject: [PATCH] fix: overload resolution for template pack of rvalue reference --- lib/CppInterOp/CppInterOp.cpp | 4 +- .../CppInterOp/FunctionReflectionTest.cpp | 42 +++++++++++++++++++ 2 files changed, 45 insertions(+), 1 deletion(-) diff --git a/lib/CppInterOp/CppInterOp.cpp b/lib/CppInterOp/CppInterOp.cpp index 3a5a345f4..845e1c2cd 100755 --- a/lib/CppInterOp/CppInterOp.cpp +++ b/lib/CppInterOp/CppInterOp.cpp @@ -1233,7 +1233,9 @@ BestOverloadFunctionMatch(const std::vector& candidates, size_t idx = 0; for (auto i : arg_types) { QualType Type = QualType::getFromOpaquePtr(i.m_Type); - ExprValueKind ExprKind = ExprValueKind::VK_PRValue; + // XValue is an object that can be "moved" whereas PRValue is temporary + // value. This enables overloads that require the object to be moved + ExprValueKind ExprKind = ExprValueKind::VK_XValue; if (Type->isLValueReferenceType()) ExprKind = ExprValueKind::VK_LValue; diff --git a/unittests/CppInterOp/FunctionReflectionTest.cpp b/unittests/CppInterOp/FunctionReflectionTest.cpp index 96dd45477..e2a3f77a2 100644 --- a/unittests/CppInterOp/FunctionReflectionTest.cpp +++ b/unittests/CppInterOp/FunctionReflectionTest.cpp @@ -1272,6 +1272,48 @@ TYPED_TEST(CppInterOpTest, FunctionReflectionTestBestOverloadFunctionMatch4) { "template<> void B::fn(A x, A y)"); } +TYPED_TEST(CppInterOpTest, FunctionReflectionTestBestOverloadFunctionMatch5) { + std::vector Decls; + std::string code = R"( + template + void callme(T1 t1, T2 t2) {} + + template + void callback(F callable, Args&&... args) { + callable(args...); + } + )"; + GetAllTopLevelDecls(code, Decls); + EXPECT_EQ(Decls.size(), 2); + + std::vector candidates; + candidates.push_back(Decls[1]); + + ASTContext& C = Interp->getCI()->getASTContext(); + std::vector explicit_params = { + C.DoubleTy.getAsOpaquePtr(), + C.IntTy.getAsOpaquePtr(), + }; + + Cpp::TCppScope_t callme = Cpp::InstantiateTemplate( + Decls[0], explicit_params.data(), explicit_params.size()); + EXPECT_TRUE(callme); + + std::vector arg_types = { + Cpp::GetTypeFromScope(callme), + C.getLValueReferenceType(C.DoubleTy).getAsOpaquePtr(), + C.getLValueReferenceType(C.IntTy).getAsOpaquePtr(), + }; + + Cpp::TCppScope_t callback = + Cpp::BestOverloadFunctionMatch(candidates, {}, arg_types); + EXPECT_TRUE(callback); + + EXPECT_EQ(Cpp::GetFunctionSignature(callback), + "template<> void callback>(void (*callable)(double, int), double &args, int &args)"); +} + TYPED_TEST(CppInterOpTest, FunctionReflectionTestIsPublicMethod) { std::vector Decls, SubDecls; std::string code = R"(