Skip to content

Commit bb9da05

Browse files
committed
Consolidate the template instantiation logic.
This patch offers a single interface for instantiation of class, function and variable templates. That would simplify user code where we do not need to care what is the underlying template pattern (most of the time).
1 parent 23973b8 commit bb9da05

File tree

4 files changed

+97
-36
lines changed

4 files changed

+97
-36
lines changed

include/clang/Interpreter/CppInterOp.h

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -534,9 +534,10 @@ namespace Cpp {
534534
TemplateArgInfo(TCppScope_t type, const char* integral_value = nullptr)
535535
: m_Type(type), m_IntegralValue(integral_value) {}
536536
};
537-
CPPINTEROP_API TCppScope_t
538-
InstantiateClassTemplate(TCppScope_t tmpl, TemplateArgInfo* template_args,
539-
size_t template_args_size);
537+
/// Builds a template instantiation for a given templated declaration.
538+
CPPINTEROP_API TCppScope_t InstantiateTemplate(TCppScope_t tmpl,
539+
TemplateArgInfo* template_args,
540+
size_t template_args_size);
540541

541542
/// Returns the class template instantiation arguments of \c templ_instance.
542543
CPPINTEROP_API void

lib/Interpreter/CppInterOp.cpp

Lines changed: 36 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,7 @@
2424
#include "clang/Frontend/CompilerInstance.h"
2525
#include "clang/Sema/Lookup.h"
2626
#include "clang/Sema/Sema.h"
27+
#include "clang/Sema/TemplateDeduction.h"
2728

2829
#include "llvm/ADT/StringRef.h"
2930
#include "llvm/Support/Casting.h"
@@ -2768,18 +2769,38 @@ namespace Cpp {
27682769
return getInterp().toString(type, obj);
27692770
}
27702771

2771-
static QualType InstantiateTemplate(TemplateDecl* ClassDecl,
2772-
TemplateArgumentListInfo& TLI, Sema &S) {
2773-
// This will instantiate tape<T> type and return it.
2774-
SourceLocation noLoc;
2775-
QualType TT = S.CheckTemplateIdType(TemplateName(ClassDecl), noLoc, TLI);
2776-
2772+
static Decl* InstantiateTemplate(TemplateDecl* TemplateD,
2773+
TemplateArgumentListInfo& TLI, Sema& S) {
27772774
// This is not right but we don't have a lot of options to choose from as a
27782775
// template instantiation requires a valid source location.
27792776
SourceLocation fakeLoc = GetValidSLoc(S);
2777+
if (auto* FunctionTemplate = dyn_cast<FunctionTemplateDecl>(TemplateD)) {
2778+
FunctionDecl* Specialization = nullptr;
2779+
clang::sema::TemplateDeductionInfo Info(fakeLoc);
2780+
if (Sema::TemplateDeductionResult Result = S.DeduceTemplateArguments(
2781+
FunctionTemplate, &TLI, Specialization, Info,
2782+
/*IsAddressOfFunction*/ true)) {
2783+
// FIXME: Diagnose what happened.
2784+
(void)Result;
2785+
}
2786+
return Specialization;
2787+
}
2788+
2789+
if (auto* VarTemplate = dyn_cast<VarTemplateDecl>(TemplateD)) {
2790+
DeclResult R = S.CheckVarTemplateId(VarTemplate, fakeLoc, fakeLoc, TLI);
2791+
if (R.isInvalid()) {
2792+
// FIXME: Diagnose
2793+
}
2794+
return R.get();
2795+
}
2796+
2797+
// This will instantiate tape<T> type and return it.
2798+
SourceLocation noLoc;
2799+
QualType TT = S.CheckTemplateIdType(TemplateName(TemplateD), noLoc, TLI);
2800+
27802801
// Perhaps we can extract this into a new interface.
27812802
S.RequireCompleteType(fakeLoc, TT, diag::err_tentative_def_incomplete_type);
2782-
return TT;
2803+
return GetScopeFromType(TT);
27832804

27842805
// ASTContext &C = S.getASTContext();
27852806
// // Get clad namespace and its identifier clad::.
@@ -2792,21 +2813,21 @@ namespace Cpp {
27922813
// return C.getElaboratedType(ETK_None, NS, TT);
27932814
}
27942815

2795-
static QualType InstantiateTemplate(TemplateDecl* ClassDecl,
2796-
ArrayRef<TemplateArgument> TemplateArgs,
2797-
Sema &S) {
2816+
static Decl* InstantiateTemplate(TemplateDecl* TemplateD,
2817+
ArrayRef<TemplateArgument> TemplateArgs,
2818+
Sema& S) {
27982819
// Create a list of template arguments.
27992820
TemplateArgumentListInfo TLI{};
28002821
for (auto TA : TemplateArgs)
28012822
TLI.addArgument(S.getTrivialTemplateArgumentLoc(TA,QualType(),
28022823
SourceLocation()));
28032824

2804-
return InstantiateTemplate(ClassDecl, TLI, S);
2825+
return InstantiateTemplate(TemplateD, TLI, S);
28052826
}
28062827

2807-
TCppScope_t InstantiateClassTemplate(TCppScope_t tmpl,
2808-
TemplateArgInfo* template_args,
2809-
size_t template_args_size) {
2828+
TCppScope_t InstantiateTemplate(TCppScope_t tmpl,
2829+
TemplateArgInfo* template_args,
2830+
size_t template_args_size) {
28102831
ASTContext &C = getASTContext();
28112832

28122833
llvm::SmallVector<TemplateArgument> TemplateArgs;
@@ -2830,8 +2851,7 @@ namespace Cpp {
28302851
#ifdef USE_CLING
28312852
cling::Interpreter::PushTransactionRAII RAII(&getInterp());
28322853
#endif
2833-
QualType Instance = InstantiateTemplate(TmplD, TemplateArgs, getSema());
2834-
return GetScopeFromType(Instance);
2854+
return InstantiateTemplate(TmplD, TemplateArgs, getSema());
28352855
}
28362856

28372857
void GetClassTemplateInstantiationArgs(TCppScope_t templ_instance,

unittests/CppInterOp/FunctionReflectionTest.cpp

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -709,8 +709,8 @@ TEST(FunctionReflectionTest, GetFunctionCallWrapper) {
709709
ASTContext& C = Interp->getCI()->getASTContext();
710710

711711
std::vector<Cpp::TemplateArgInfo> argument = {C.IntTy.getAsOpaquePtr()};
712-
auto Instance1 = Cpp::InstantiateClassTemplate(Decls1[0], argument.data(),
713-
/*type_size*/ argument.size());
712+
auto Instance1 = Cpp::InstantiateTemplate(Decls1[0], argument.data(),
713+
/*type_size*/ argument.size());
714714
EXPECT_TRUE(isa<ClassTemplateSpecializationDecl>((Decl*)Instance1));
715715
auto* CTSD1 = static_cast<ClassTemplateSpecializationDecl*>(Instance1);
716716
auto* Add_D = Cpp::GetNamed("Add",CTSD1);

unittests/CppInterOp/ScopeReflectionTest.cpp

Lines changed: 55 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -750,8 +750,52 @@ TEST(ScopeReflectionTest, InstantiateNNTPClassTemplate) {
750750
ASTContext &C = Interp->getCI()->getASTContext();
751751
Cpp::TCppType_t IntTy = C.IntTy.getAsOpaquePtr();
752752
std::vector<Cpp::TemplateArgInfo> args1 = {{IntTy, "5"}};
753-
EXPECT_TRUE(Cpp::InstantiateClassTemplate(Decls[0], args1.data(),
754-
/*type_size*/ args1.size()));
753+
EXPECT_TRUE(Cpp::InstantiateTemplate(Decls[0], args1.data(),
754+
/*type_size*/ args1.size()));
755+
}
756+
757+
TEST(ScopeReflectionTest, InstantiateVarTemplate) {
758+
std::vector<Decl*> Decls;
759+
std::string code = R"(
760+
template<class T> constexpr T pi = T(3.1415926535897932385L);
761+
)";
762+
763+
GetAllTopLevelDecls(code, Decls);
764+
ASTContext& C = Interp->getCI()->getASTContext();
765+
766+
std::vector<Cpp::TemplateArgInfo> args1 = {C.IntTy.getAsOpaquePtr()};
767+
auto Instance1 = Cpp::InstantiateTemplate(Decls[0], args1.data(),
768+
/*type_size*/ args1.size());
769+
EXPECT_TRUE(isa<VarDecl>((Decl*)Instance1));
770+
auto* VD = cast<VarTemplateSpecializationDecl>((Decl*)Instance1);
771+
VarTemplateDecl* VDTD1 = VD->getSpecializedTemplate();
772+
EXPECT_TRUE(VDTD1->isThisDeclarationADefinition());
773+
#if CLANG_VERSION_MAJOR > 13
774+
TemplateArgument TA1 = (*VD->getTemplateArgsInfo())[0].getArgument();
775+
#else
776+
TemplateArgument TA1 = VD->getTemplateArgsInfo()[0].getArgument();
777+
#endif // CLANG_VERSION_MAJOR
778+
EXPECT_TRUE(TA1.getAsType()->isIntegerType());
779+
}
780+
781+
TEST(ScopeReflectionTest, InstantiateFunctionTemplate) {
782+
std::vector<Decl*> Decls;
783+
std::string code = R"(
784+
template<typename T> T TrivialFnTemplate() { return T(); }
785+
)";
786+
787+
GetAllTopLevelDecls(code, Decls);
788+
ASTContext& C = Interp->getCI()->getASTContext();
789+
790+
std::vector<Cpp::TemplateArgInfo> args1 = {C.IntTy.getAsOpaquePtr()};
791+
auto Instance1 = Cpp::InstantiateTemplate(Decls[0], args1.data(),
792+
/*type_size*/ args1.size());
793+
EXPECT_TRUE(isa<FunctionDecl>((Decl*)Instance1));
794+
FunctionDecl* FD = cast<FunctionDecl>((Decl*)Instance1);
795+
FunctionDecl* FnTD1 = FD->getTemplateInstantiationPattern();
796+
EXPECT_TRUE(FnTD1->isThisDeclarationADefinition());
797+
TemplateArgument TA1 = FD->getTemplateSpecializationArgs()->get(0);
798+
EXPECT_TRUE(TA1.getAsType()->isIntegerType());
755799
}
756800

757801
TEST(ScopeReflectionTest, InstantiateTemplateFunctionFromString) {
@@ -807,29 +851,26 @@ TEST(ScopeReflectionTest, InstantiateClassTemplate) {
807851
ASTContext &C = Interp->getCI()->getASTContext();
808852

809853
std::vector<Cpp::TemplateArgInfo> args1 = {C.IntTy.getAsOpaquePtr()};
810-
auto Instance1 = Cpp::InstantiateClassTemplate(Decls[0],
811-
args1.data(),
812-
/*type_size*/args1.size());
854+
auto Instance1 = Cpp::InstantiateTemplate(Decls[0], args1.data(),
855+
/*type_size*/ args1.size());
813856
EXPECT_TRUE(isa<ClassTemplateSpecializationDecl>((Decl*)Instance1));
814857
auto *CTSD1 = static_cast<ClassTemplateSpecializationDecl*>(Instance1);
815858
EXPECT_TRUE(CTSD1->hasDefinition());
816859
TemplateArgument TA1 = CTSD1->getTemplateArgs().get(0);
817860
EXPECT_TRUE(TA1.getAsType()->isIntegerType());
818861
EXPECT_TRUE(CTSD1->hasDefinition());
819862

820-
auto Instance2 = Cpp::InstantiateClassTemplate(Decls[1],
821-
nullptr,
822-
/*type_size*/0);
863+
auto Instance2 = Cpp::InstantiateTemplate(Decls[1], nullptr,
864+
/*type_size*/ 0);
823865
EXPECT_TRUE(isa<ClassTemplateSpecializationDecl>((Decl*)Instance2));
824866
auto *CTSD2 = static_cast<ClassTemplateSpecializationDecl*>(Instance2);
825867
EXPECT_TRUE(CTSD2->hasDefinition());
826868
TemplateArgument TA2 = CTSD2->getTemplateArgs().get(0);
827869
EXPECT_TRUE(TA2.getAsType()->isIntegerType());
828870

829871
std::vector<Cpp::TemplateArgInfo> args3 = {C.IntTy.getAsOpaquePtr()};
830-
auto Instance3 = Cpp::InstantiateClassTemplate(Decls[2],
831-
args3.data(),
832-
/*type_size*/args3.size());
872+
auto Instance3 = Cpp::InstantiateTemplate(Decls[2], args3.data(),
873+
/*type_size*/ args3.size());
833874
EXPECT_TRUE(isa<ClassTemplateSpecializationDecl>((Decl*)Instance3));
834875
auto *CTSD3 = static_cast<ClassTemplateSpecializationDecl*>(Instance3);
835876
EXPECT_TRUE(CTSD3->hasDefinition());
@@ -844,9 +885,8 @@ TEST(ScopeReflectionTest, InstantiateClassTemplate) {
844885

845886
std::vector<Cpp::TemplateArgInfo> args4 = {C.IntTy.getAsOpaquePtr(),
846887
{C.IntTy.getAsOpaquePtr(), "3"}};
847-
auto Instance4 = Cpp::InstantiateClassTemplate(Decls[3],
848-
args4.data(),
849-
/*type_size*/args4.size());
888+
auto Instance4 = Cpp::InstantiateTemplate(Decls[3], args4.data(),
889+
/*type_size*/ args4.size());
850890

851891
EXPECT_TRUE(isa<ClassTemplateSpecializationDecl>((Decl*)Instance4));
852892
auto *CTSD4 = static_cast<ClassTemplateSpecializationDecl*>(Instance4);
@@ -901,4 +941,4 @@ TEST(ScopeReflectionTest, IncludeVector) {
901941
#include <iostream>
902942
)";
903943
Interp->process(code);
904-
}
944+
}

0 commit comments

Comments
 (0)