|
6 | 6 | #include "clang/Interpreter/CppInterOp.h"
|
7 | 7 | #include "clang/Sema/Sema.h"
|
8 | 8 |
|
| 9 | +#include <llvm/ADT/ArrayRef.h> |
| 10 | + |
9 | 11 | #include "clang-c/CXCppInterOp.h"
|
10 | 12 |
|
11 | 13 | #include "gtest/gtest.h"
|
@@ -847,6 +849,69 @@ TEST(FunctionReflectionTest, GetClassTemplatedMethods_VariadicsAndOthers) {
|
847 | 849 | "void MyClass::staticVariadic(T t, Args ...args)");
|
848 | 850 | }
|
849 | 851 |
|
| 852 | +TEST(FunctionReflectionTest, InstantiateVariadicFunction) { |
| 853 | + std::vector<Decl*> Decls; |
| 854 | + std::string code = R"( |
| 855 | + class MyClass {}; |
| 856 | +
|
| 857 | + template<typename... Args> |
| 858 | + void VariadicFn(Args... args) {} |
| 859 | +
|
| 860 | + template<typename... Args> |
| 861 | + void VariadicFnExtended(int fixedParam, Args... args) {} |
| 862 | + )"; |
| 863 | + |
| 864 | + GetAllTopLevelDecls(code, Decls); |
| 865 | + ASTContext& C = Interp->getCI()->getASTContext(); |
| 866 | + |
| 867 | + std::vector<Cpp::TemplateArgInfo> args1 = {C.DoubleTy.getAsOpaquePtr(), |
| 868 | + C.IntTy.getAsOpaquePtr()}; |
| 869 | + auto Instance1 = Cpp::InstantiateTemplate(Decls[1], args1.data(), |
| 870 | + /*type_size*/ args1.size()); |
| 871 | + EXPECT_TRUE(Cpp::IsTemplatedFunction(Instance1)); |
| 872 | + EXPECT_EQ(Cpp::GetFunctionSignature(Instance1), |
| 873 | + "template<> void VariadicFn<<double, int>>(double args, int args)"); |
| 874 | + |
| 875 | + FunctionDecl* FD = cast<FunctionDecl>((Decl*)Instance1); |
| 876 | + FunctionDecl* FnTD1 = FD->getTemplateInstantiationPattern(); |
| 877 | + EXPECT_TRUE(FnTD1->isThisDeclarationADefinition()); |
| 878 | + EXPECT_EQ(FD->getNumParams(), 2); |
| 879 | + |
| 880 | + const TemplateArgumentList* TA1 = FD->getTemplateSpecializationArgs(); |
| 881 | + llvm::ArrayRef<TemplateArgument> Args = TA1->get(0).getPackAsArray(); |
| 882 | + EXPECT_EQ(Args.size(), 2); |
| 883 | + EXPECT_TRUE(Args[0].getAsType()->isFloatingType()); |
| 884 | + EXPECT_TRUE(Args[1].getAsType()->isIntegerType()); |
| 885 | + |
| 886 | + // handle to MyClass type |
| 887 | + auto MyClassType = Cpp::GetTypeFromScope(Decls[0]); |
| 888 | + std::vector<Cpp::TemplateArgInfo> args2 = {MyClassType, |
| 889 | + C.DoubleTy.getAsOpaquePtr()}; |
| 890 | + |
| 891 | + // instantiate VariadicFnExtended |
| 892 | + auto Instance2 = |
| 893 | + Cpp::InstantiateTemplate(Decls[2], args2.data(), args2.size()); |
| 894 | + EXPECT_TRUE(Cpp::IsTemplatedFunction(Instance2)); |
| 895 | + |
| 896 | + FunctionDecl* FD2 = cast<FunctionDecl>((Decl*)Instance2); |
| 897 | + FunctionDecl* FnTD2 = FD2->getTemplateInstantiationPattern(); |
| 898 | + EXPECT_TRUE(FnTD2->isThisDeclarationADefinition()); |
| 899 | + |
| 900 | + // VariadicFnExtended has one fixed param + 2 elements in TemplateArgument |
| 901 | + // pack |
| 902 | + EXPECT_EQ(FD2->getNumParams(), 3); |
| 903 | + |
| 904 | + const TemplateArgumentList* TA2 = FD2->getTemplateSpecializationArgs(); |
| 905 | + llvm::ArrayRef<TemplateArgument> PackArgs2 = TA2->get(0).getPackAsArray(); |
| 906 | + EXPECT_EQ(PackArgs2.size(), 2); |
| 907 | + |
| 908 | + EXPECT_TRUE(PackArgs2[0].getAsType()->isRecordType()); // MyClass |
| 909 | + EXPECT_TRUE(PackArgs2[1].getAsType()->isFloatingType()); // double |
| 910 | + EXPECT_EQ(Cpp::GetFunctionSignature(Instance2), |
| 911 | + "template<> void VariadicFnExtended<<MyClass, double>>(int " |
| 912 | + "fixedParam, MyClass args, double args)"); |
| 913 | +} |
| 914 | + |
850 | 915 | TEST(FunctionReflectionTest, BestOverloadFunctionMatch1) {
|
851 | 916 | std::vector<Decl*> Decls;
|
852 | 917 | std::string code = R"(
|
|
0 commit comments