diff --git a/lib/Interpreter/exports.ld b/lib/Interpreter/exports.ld index 1f7301dd4..49b7b0d83 100644 --- a/lib/Interpreter/exports.ld +++ b/lib/Interpreter/exports.ld @@ -47,5 +47,7 @@ -Wl,--export=_ZNK5clang11DeclContext6lookupENS_15DeclarationNameE -Wl,--export=_ZNK5clang17ClassTemplateDecl18getSpecializationsEv -Wl,--export=_ZNK5clang4Sema15getStdNamespaceEv +-Wl,--export=_ZNK5clang4Type14isFloatingTypeEv +-Wl,--export=_ZNK5clang12FunctionDecl12getNumParamsEv -Wl,--export=__clang_Interpreter_SetValueNoAlloc -Wl,--export=__clang_Interpreter_SetValueWithAlloc \ No newline at end of file diff --git a/unittests/CppInterOp/FunctionReflectionTest.cpp b/unittests/CppInterOp/FunctionReflectionTest.cpp index ea8b4180d..3f1ddb27f 100644 --- a/unittests/CppInterOp/FunctionReflectionTest.cpp +++ b/unittests/CppInterOp/FunctionReflectionTest.cpp @@ -6,6 +6,8 @@ #include "clang/Interpreter/CppInterOp.h" #include "clang/Sema/Sema.h" +#include + #include "clang-c/CXCppInterOp.h" #include "gtest/gtest.h" @@ -846,6 +848,69 @@ TEST(FunctionReflectionTest, GetClassTemplatedMethods_VariadicsAndOthers) { "void MyClass::staticVariadic(T t, Args ...args)"); } +TEST(FunctionReflectionTest, InstantiateVariadicFunction) { + std::vector Decls; + std::string code = R"( + class MyClass {}; + + template + void VariadicFn(Args... args) {} + + template + void VariadicFnExtended(int fixedParam, Args... args) {} + )"; + + GetAllTopLevelDecls(code, Decls); + ASTContext& C = Interp->getCI()->getASTContext(); + + std::vector args1 = {C.DoubleTy.getAsOpaquePtr(), + C.IntTy.getAsOpaquePtr()}; + auto Instance1 = Cpp::InstantiateTemplate(Decls[1], args1.data(), + /*type_size*/ args1.size()); + EXPECT_TRUE(Cpp::IsTemplatedFunction(Instance1)); + EXPECT_EQ(Cpp::GetFunctionSignature(Instance1), + "template<> void VariadicFn<>(double args, int args)"); + + FunctionDecl* FD = cast((Decl*)Instance1); + FunctionDecl* FnTD1 = FD->getTemplateInstantiationPattern(); + EXPECT_TRUE(FnTD1->isThisDeclarationADefinition()); + EXPECT_EQ(FD->getNumParams(), 2); + + const TemplateArgumentList* TA1 = FD->getTemplateSpecializationArgs(); + llvm::ArrayRef Args = TA1->get(0).getPackAsArray(); + EXPECT_EQ(Args.size(), 2); + EXPECT_TRUE(Args[0].getAsType()->isFloatingType()); + EXPECT_TRUE(Args[1].getAsType()->isIntegerType()); + + // handle to MyClass type + auto MyClassType = Cpp::GetTypeFromScope(Decls[0]); + std::vector args2 = {MyClassType, + C.DoubleTy.getAsOpaquePtr()}; + + // instantiate VariadicFnExtended + auto Instance2 = + Cpp::InstantiateTemplate(Decls[2], args2.data(), args2.size()); + EXPECT_TRUE(Cpp::IsTemplatedFunction(Instance2)); + + FunctionDecl* FD2 = cast((Decl*)Instance2); + FunctionDecl* FnTD2 = FD2->getTemplateInstantiationPattern(); + EXPECT_TRUE(FnTD2->isThisDeclarationADefinition()); + + // VariadicFnExtended has one fixed param + 2 elements in TemplateArgument + // pack + EXPECT_EQ(FD2->getNumParams(), 3); + + const TemplateArgumentList* TA2 = FD2->getTemplateSpecializationArgs(); + llvm::ArrayRef PackArgs2 = TA2->get(0).getPackAsArray(); + EXPECT_EQ(PackArgs2.size(), 2); + + EXPECT_TRUE(PackArgs2[0].getAsType()->isRecordType()); // MyClass + EXPECT_TRUE(PackArgs2[1].getAsType()->isFloatingType()); // double + EXPECT_EQ(Cpp::GetFunctionSignature(Instance2), + "template<> void VariadicFnExtended<>(int " + "fixedParam, MyClass args, double args)"); +} + TEST(FunctionReflectionTest, BestOverloadFunctionMatch1) { std::vector Decls; std::string code = R"(