Skip to content

Commit b1cdd91

Browse files
committed
Implement a slow string-based function template instantiation.
This routine should be used only in cases where we cannot do anything else. It takes the string and tries to force the compiler to instantiate by requesting the address to the function.
1 parent 48af188 commit b1cdd91

File tree

3 files changed

+36
-0
lines changed

3 files changed

+36
-0
lines changed

include/clang/Interpreter/CppInterOp.h

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -471,6 +471,13 @@ namespace Cpp {
471471
/// Returns the class template instantiation arguments of \c templ_instance.
472472
void GetClassTemplateInstantiationArgs(TCppScope_t templ_instance,
473473
std::vector<TemplateArgInfo> &args);
474+
475+
/// Instantiates a function template from a given string representation. This
476+
/// function also does overload resolution.
477+
///\returns the instantiated function template declaration.
478+
TCppFunction_t
479+
InstantiateTemplateFunctionFromString(const char* function_template);
480+
474481
std::vector<std::string> GetAllCppNames(TCppScope_t scope);
475482

476483
void DumpScope(TCppScope_t scope);

lib/Interpreter/CppInterOp.cpp

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -474,6 +474,8 @@ namespace Cpp {
474474
Type = Type->getUnqualifiedDesugaredType();
475475
if (auto *ET = llvm::dyn_cast<EnumType>(Type))
476476
return ET->getDecl();
477+
if (auto* FnType = llvm::dyn_cast<FunctionProtoType>(Type))
478+
Type = const_cast<clang::Type*>(FnType->getReturnType().getTypePtr());
477479
return Type->getAsCXXRecordDecl();
478480
}
479481
return 0;
@@ -2651,6 +2653,24 @@ namespace Cpp {
26512653
}
26522654
}
26532655

2656+
TCppFunction_t
2657+
InstantiateTemplateFunctionFromString(const char* function_template) {
2658+
// FIXME: Drop this interface and replace it with the proper overload
2659+
// resolution handling and template instantiation selection.
2660+
2661+
// Try to force template instantiation and overload resolution.
2662+
static unsigned long long var_count = 0;
2663+
std::string id = "__Cppyy_GetMethTmpl_" + std::to_string(var_count++);
2664+
std::string instance = "auto " + id + " = " + function_template + ";\n";
2665+
2666+
if (!Cpp::Declare(instance.c_str(), /*silent=*/false)) {
2667+
VarDecl* VD = (VarDecl*)Cpp::GetNamed(id, 0);
2668+
DeclRefExpr* DRE = (DeclRefExpr*)VD->getInit()->IgnoreImpCasts();
2669+
return DRE->getDecl();
2670+
}
2671+
return nullptr;
2672+
}
2673+
26542674
std::vector<std::string> GetAllCppNames(TCppScope_t scope) {
26552675
auto *D = (clang::Decl *)scope;
26562676
clang::DeclContext *DC;

unittests/CppInterOp/ScopeReflectionTest.cpp

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -704,6 +704,15 @@ TEST(ScopeReflectionTest, InstantiateNNTPClassTemplate) {
704704
/*type_size*/ args1.size()));
705705
}
706706

707+
TEST(ScopeReflectionTest, InstantiateTemplateFunctionFromString) {
708+
Cpp::CreateInterpreter();
709+
std::string code = R"(#include <memory>)";
710+
Interp->process(code);
711+
const char* str = "std::make_unique<int,int>";
712+
auto* Instance1 = (Decl*)Cpp::InstantiateTemplateFunctionFromString(str);
713+
EXPECT_TRUE(Instance1);
714+
}
715+
707716
TEST(ScopeReflectionTest, InstantiateClassTemplate) {
708717
std::vector<Decl *> Decls;
709718
std::string code = R"(

0 commit comments

Comments
 (0)