Skip to content

Commit 1e4b64f

Browse files
authored
Add interfaces enabling template function logic (#215)
1 parent 8dd6b87 commit 1e4b64f

File tree

4 files changed

+235
-50
lines changed

4 files changed

+235
-50
lines changed

include/clang/Interpreter/CppInterOp.h

Lines changed: 58 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -246,7 +246,7 @@ namespace Cpp {
246246
/// passed as a parameter, and if the parent is not passed,
247247
/// then global scope will be assumed.
248248
CPPINTEROP_API TCppScope_t GetScope(const std::string& name,
249-
TCppScope_t parent = 0);
249+
TCppScope_t parent = nullptr);
250250

251251
/// When the namespace is known, then the parent doesn't need
252252
/// to be specified. This will probably be phased-out in
@@ -284,9 +284,22 @@ namespace Cpp {
284284
CPPINTEROP_API int64_t GetBaseClassOffset(TCppScope_t derived,
285285
TCppScope_t base);
286286

287-
/// Gets a list of all the Methods that are in the Class that is
287+
/// Sets a list of all the Methods that are in the Class that is
288288
/// supplied as a parameter.
289-
CPPINTEROP_API std::vector<TCppFunction_t> GetClassMethods(TCppScope_t klass);
289+
///\param[in] klass - Pointer to the scope/class under which the methods have
290+
/// to be retrieved
291+
///\param[out] methods - Vector of methods in the class
292+
CPPINTEROP_API void GetClassMethods(TCppScope_t klass,
293+
std::vector<TCppFunction_t>& methods);
294+
295+
/// Template function pointer list to add proxies for un-instantiated/
296+
/// non-overloaded templated methods
297+
///\param[in] klass - Pointer to the scope/class under which the methods have
298+
/// to be retrieved
299+
///\param[out] methods - Vector of methods in the class
300+
CPPINTEROP_API void
301+
GetFunctionTemplatedDecls(TCppScope_t klass,
302+
std::vector<TCppFunction_t>& methods);
290303

291304
///\returns if a class has a default constructor.
292305
CPPINTEROP_API bool HasDefaultConstructor(TCppScope_t scope);
@@ -329,7 +342,17 @@ namespace Cpp {
329342
/// This function performs a lookup to check if there is a
330343
/// templated function of that type.
331344
CPPINTEROP_API bool ExistsFunctionTemplate(const std::string& name,
332-
TCppScope_t parent = 0);
345+
TCppScope_t parent = nullptr);
346+
347+
/// Sets a list of all the Templated Methods that are in the Class that is
348+
/// supplied as a parameter.
349+
///\param[in] name - method name
350+
///\param[in] parent - Pointer to the scope/class under which the methods have
351+
/// to be retrieved
352+
///\param[out] funcs - vector of function pointers matching the name
353+
CPPINTEROP_API void
354+
GetClassTemplatedMethods(const std::string& name, TCppScope_t parent,
355+
std::vector<TCppFunction_t>& funcs);
333356

334357
/// Checks if the provided parameter is a method.
335358
CPPINTEROP_API bool IsMethod(TCppConstFunction_t method);
@@ -535,11 +558,24 @@ namespace Cpp {
535558
: m_Type(type), m_IntegralValue(integral_value) {}
536559
};
537560
/// 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);
561+
/// Offers a single interface for instantiation of class, function and
562+
/// variable templates
563+
///
564+
///\param[in] tmpl - Uninstantiated template class/function
565+
///\param[in] template_args - Pointer to vector of template arguments stored
566+
/// in the \c TemplateArgInfo struct
567+
///\param[in] template_args_size - Size of the vector of template arguments
568+
/// passed as \c template_args
569+
///
570+
///\returns Instantiated templated class/function/variable pointer
571+
CPPINTEROP_API TCppScope_t
572+
InstantiateTemplate(TCppScope_t tmpl, const TemplateArgInfo* template_args,
573+
size_t template_args_size);
541574

542-
/// Returns the class template instantiation arguments of \c templ_instance.
575+
/// Sets the class template instantiation arguments of \c templ_instance.
576+
///
577+
///\param[in] templ_instance - Pointer to the template instance
578+
///\param[out] args - Vector of instantiation arguments
543579
CPPINTEROP_API void
544580
GetClassTemplateInstantiationArgs(TCppScope_t templ_instance,
545581
std::vector<TemplateArgInfo>& args);
@@ -550,6 +586,20 @@ namespace Cpp {
550586
CPPINTEROP_API TCppFunction_t
551587
InstantiateTemplateFunctionFromString(const char* function_template);
552588

589+
/// Finds best template match based on explicit template parameters and
590+
/// argument types
591+
///
592+
///\param[in] candidates - Vector of suitable candidates that come under the
593+
/// parent scope and have the same name (obtained using
594+
/// GetClassTemplatedMethods)
595+
///\param[in] explicit_types - set of expicitly instantiated template types
596+
///\param[in] arg_types - set of argument types
597+
///\returns Instantiated function pointer
598+
CPPINTEROP_API TCppFunction_t
599+
BestTemplateFunctionMatch(const std::vector<TCppFunction_t>& candidates,
600+
const std::vector<TemplateArgInfo>& explicit_types,
601+
const std::vector<TemplateArgInfo>& arg_types);
602+
553603
CPPINTEROP_API std::vector<std::string> GetAllCppNames(TCppScope_t scope);
554604

555605
CPPINTEROP_API void DumpScope(TCppScope_t scope);

lib/Interpreter/CppInterOp.cpp

Lines changed: 103 additions & 33 deletions
Original file line numberDiff line numberDiff line change
@@ -719,39 +719,46 @@ namespace Cpp {
719719
return ComputeBaseOffset(getSema().getASTContext(), DCXXRD, Paths.front());
720720
}
721721

722-
// FIXME: We should make the std::vector<TCppFunction_t> an out parameter to
723-
// avoid copies.
724-
std::vector<TCppFunction_t> GetClassMethods(TCppScope_t klass)
725-
{
726-
722+
template <typename DeclType>
723+
static void GetClassDecls(TCppScope_t klass,
724+
std::vector<TCppFunction_t>& methods) {
727725
if (!klass)
728-
return {};
726+
return;
729727

730-
auto *D = (clang::Decl *) klass;
728+
auto* D = (clang::Decl*)klass;
731729

732-
if (auto *TD = dyn_cast<TypedefNameDecl>(D))
730+
if (auto* TD = dyn_cast<TypedefNameDecl>(D))
733731
D = GetScopeFromType(TD->getUnderlyingType());
734732

735-
std::vector<TCppFunction_t> methods;
736-
if (auto *CXXRD = dyn_cast_or_null<CXXRecordDecl>(D)) {
737-
getSema().ForceDeclarationOfImplicitMembers(CXXRD);
738-
for (Decl* DI : CXXRD->decls()) {
739-
if (auto* MD = dyn_cast<CXXMethodDecl>(DI))
733+
if (!D || !isa<CXXRecordDecl>(D))
734+
return;
735+
736+
auto* CXXRD = dyn_cast<CXXRecordDecl>(D);
737+
getSema().ForceDeclarationOfImplicitMembers(CXXRD);
738+
for (Decl* DI : CXXRD->decls()) {
739+
if (auto* MD = dyn_cast<DeclType>(DI))
740+
methods.push_back(MD);
741+
else if (auto* USD = dyn_cast<UsingShadowDecl>(DI))
742+
if (auto* MD = dyn_cast<DeclType>(USD->getTargetDecl()))
740743
methods.push_back(MD);
741-
else if (auto* USD = dyn_cast<UsingShadowDecl>(DI))
742-
if (auto* MD = dyn_cast<CXXMethodDecl>(USD->getTargetDecl()))
743-
methods.push_back(MD);
744-
}
745744
}
746-
return methods;
745+
}
746+
747+
void GetClassMethods(TCppScope_t klass,
748+
std::vector<TCppFunction_t>& methods) {
749+
GetClassDecls<CXXMethodDecl>(klass, methods);
750+
}
751+
752+
void GetFunctionTemplatedDecls(TCppScope_t klass,
753+
std::vector<TCppFunction_t>& methods) {
754+
GetClassDecls<FunctionTemplateDecl>(klass, methods);
747755
}
748756

749757
bool HasDefaultConstructor(TCppScope_t scope) {
750758
auto *D = (clang::Decl *) scope;
751759

752-
if (auto *CXXRD = llvm::dyn_cast_or_null<CXXRecordDecl>(D)) {
760+
if (auto* CXXRD = llvm::dyn_cast_or_null<CXXRecordDecl>(D))
753761
return CXXRD->hasDefaultConstructor();
754-
}
755762

756763
return false;
757764
}
@@ -818,21 +825,19 @@ namespace Cpp {
818825
TCppType_t GetFunctionReturnType(TCppFunction_t func)
819826
{
820827
auto *D = (clang::Decl *) func;
821-
if (auto *FD = llvm::dyn_cast_or_null<clang::FunctionDecl>(D)) {
822-
return FD->getReturnType().getAsOpaquePtr();
823-
}
828+
if (auto* FD = llvm::dyn_cast_or_null<clang::FunctionDecl>(D))
829+
return FD->getReturnType().getAsOpaquePtr();
824830

825-
if (auto* FD = llvm::dyn_cast_or_null<clang::FunctionTemplateDecl>(D)) {
826-
return (FD->getTemplatedDecl())->getReturnType().getAsOpaquePtr();
827-
}
831+
if (auto* FD = llvm::dyn_cast_or_null<clang::FunctionTemplateDecl>(D))
832+
return (FD->getTemplatedDecl())->getReturnType().getAsOpaquePtr();
828833

829834
return 0;
830835
}
831836

832837
TCppIndex_t GetFunctionNumArgs(TCppFunction_t func)
833838
{
834839
auto *D = (clang::Decl *) func;
835-
if (auto *FD = llvm::dyn_cast_or_null<FunctionDecl>(D))
840+
if (auto* FD = llvm::dyn_cast_or_null<FunctionDecl>(D))
836841
return FD->getNumParams();
837842

838843
if (auto* FD = llvm::dyn_cast_or_null<clang::FunctionTemplateDecl>(D))
@@ -844,9 +849,8 @@ namespace Cpp {
844849
TCppIndex_t GetFunctionRequiredArgs(TCppConstFunction_t func)
845850
{
846851
auto *D = (const clang::Decl *) func;
847-
if (auto *FD = llvm::dyn_cast_or_null<FunctionDecl> (D)) {
852+
if (auto* FD = llvm::dyn_cast_or_null<FunctionDecl>(D))
848853
return FD->getMinRequiredArguments();
849-
}
850854

851855
if (auto* FD = llvm::dyn_cast_or_null<clang::FunctionTemplateDecl>(D))
852856
return (FD->getTemplatedDecl())->getMinRequiredArguments();
@@ -868,8 +872,7 @@ namespace Cpp {
868872
return 0;
869873
}
870874

871-
std::string GetFunctionSignature(TCppFunction_t func)
872-
{
875+
std::string GetFunctionSignature(TCppFunction_t func) {
873876
if (!func)
874877
return "<unknown>";
875878

@@ -886,6 +889,7 @@ namespace Cpp {
886889
SS.flush();
887890
return Signature;
888891
}
892+
889893
return "<unknown>";
890894
}
891895

@@ -925,7 +929,7 @@ namespace Cpp {
925929
{
926930
DeclContext *Within = 0;
927931
if (parent) {
928-
auto *D = (Decl *)parent;
932+
auto* D = (Decl*)parent;
929933
Within = llvm::dyn_cast<DeclContext>(D);
930934
}
931935

@@ -941,6 +945,72 @@ namespace Cpp {
941945
return true;
942946
}
943947

948+
void GetClassTemplatedMethods(const std::string& name, TCppScope_t parent,
949+
std::vector<TCppFunction_t>& funcs) {
950+
951+
auto* D = (Decl*)parent;
952+
953+
if (!parent || name.empty())
954+
return;
955+
956+
D = GetUnderlyingScope(D);
957+
958+
llvm::StringRef Name(name);
959+
auto& S = getSema();
960+
DeclarationName DName = &getASTContext().Idents.get(name);
961+
clang::LookupResult R(S, DName, SourceLocation(), Sema::LookupOrdinaryName,
962+
Sema::ForVisibleRedeclaration);
963+
964+
Cpp_utils::Lookup::Named(&S, R, Decl::castToDeclContext(D));
965+
966+
if (R.empty())
967+
return;
968+
969+
R.resolveKind();
970+
971+
for (auto* Found : R)
972+
if (llvm::isa<FunctionTemplateDecl>(Found))
973+
funcs.push_back(Found);
974+
}
975+
976+
TCppFunction_t
977+
BestTemplateFunctionMatch(const std::vector<TCppFunction_t>& candidates,
978+
const std::vector<TemplateArgInfo>& explicit_types,
979+
const std::vector<TemplateArgInfo>& arg_types) {
980+
981+
for (const auto& candidate : candidates) {
982+
auto* TFD = (FunctionTemplateDecl*)candidate;
983+
clang::TemplateParameterList* tpl = TFD->getTemplateParameters();
984+
985+
// template parameter size does not match
986+
if (tpl->size() < explicit_types.size())
987+
continue;
988+
989+
// right now uninstantiated functions give template typenames instead of
990+
// actual types. We make this match solely based on count
991+
992+
const FunctionDecl* func = TFD->getTemplatedDecl();
993+
if (func->getNumParams() != arg_types.size())
994+
continue;
995+
996+
// FIXME : first score based on the type similarity before forcing
997+
// instantiation try instantiating
998+
TCppFunction_t instantiated =
999+
InstantiateTemplate(candidate, arg_types.data(), arg_types.size());
1000+
if (instantiated)
1001+
return instantiated;
1002+
1003+
// Force the instantiation with template params in case of no args
1004+
// maybe steer instantiation better with arg set returned from
1005+
// TemplateProxy?
1006+
instantiated = InstantiateTemplate(candidate, explicit_types.data(),
1007+
explicit_types.size());
1008+
if (instantiated)
1009+
return instantiated;
1010+
}
1011+
return nullptr;
1012+
}
1013+
9441014
// Gets the AccessSpecifier of the function and checks if it is equal to
9451015
// the provided AccessSpecifier.
9461016
bool CheckMethodAccess(TCppFunction_t method, AccessSpecifier AS)
@@ -2836,7 +2906,7 @@ namespace Cpp {
28362906
}
28372907

28382908
TCppScope_t InstantiateTemplate(TCppScope_t tmpl,
2839-
TemplateArgInfo* template_args,
2909+
const TemplateArgInfo* template_args,
28402910
size_t template_args_size) {
28412911
ASTContext &C = getASTContext();
28422912

0 commit comments

Comments
 (0)