Skip to content

Commit

Permalink
Refactoring, move common code to static function
Browse files Browse the repository at this point in the history
  • Loading branch information
aaronj0 committed Apr 12, 2024
1 parent 488ef5f commit 423b3e1
Show file tree
Hide file tree
Showing 3 changed files with 105 additions and 122 deletions.
55 changes: 44 additions & 11 deletions include/clang/Interpreter/CppInterOp.h
Original file line number Diff line number Diff line change
Expand Up @@ -284,13 +284,19 @@ namespace Cpp {
CPPINTEROP_API int64_t GetBaseClassOffset(TCppScope_t derived,
TCppScope_t base);

/// Gets a list of all the Methods that are in the Class that is
/// Sets a list of all the Methods that are in the Class that is
/// supplied as a parameter.
CPPINTEROP_API void GetClassMethods(TCppScope_t klass, std::vector<TCppFunction_t> &methods);
///\param[in] klass - Pointer to the scope/class under which the methods have
/// to be retrieved
///\param[out] methods - Vector of methods in the class
CPPINTEROP_API void GetClassMethods(TCppScope_t klass,
std::vector<TCppFunction_t>& methods);

///\returns Template function pointer list to add proxies for
/// un-instantiated/non-overloaded templated methods
CPPINTEROP_API void GetFunctionTemplatedDecls(TCppScope_t klass, std::vector<TCppFunction_t> &methods);
CPPINTEROP_API void
GetFunctionTemplatedDecls(TCppScope_t klass,
std::vector<TCppFunction_t>& methods);

///\returns if a class has a default constructor.
CPPINTEROP_API bool HasDefaultConstructor(TCppScope_t scope);
Expand Down Expand Up @@ -335,8 +341,15 @@ namespace Cpp {
CPPINTEROP_API bool ExistsFunctionTemplate(const std::string& name,
TCppScope_t parent = nullptr);

CPPINTEROP_API std::vector<TCppFunction_t>
GetTemplatedMethods(const std::string& name, TCppScope_t parent = nullptr);
/// Sets a list of all the Templated Methods that are in the Class that is
/// supplied as a parameter.
///\param[in] name - method name
///\param[in] parent - Pointer to the scope/class under which the methods have
/// to be retrieved
///\param[out] funcs - vector of function pointers matching the name
CPPINTEROP_API void
GetClassTemplatedMethods(const std::string& name, TCppScope_t parent,
std::vector<TCppFunction_t>& funcs);

/// Checks if the provided parameter is a method.
CPPINTEROP_API bool IsMethod(TCppConstFunction_t method);
Expand Down Expand Up @@ -542,11 +555,24 @@ namespace Cpp {
: m_Type(type), m_IntegralValue(integral_value) {}
};
/// Builds a template instantiation for a given templated declaration.
CPPINTEROP_API TCppScope_t InstantiateTemplate(TCppScope_t tmpl,
const TemplateArgInfo* template_args,
size_t template_args_size);
/// Offers a single interface for instantiation of class, function and
/// variable templates
///
///\param[in] tmpl - Uninstantiated template class/function
///\param[in] template_args - Pointer to vector of template arguments stored
/// in the \c TemplateArgInfo struct
///\param[in] template_args_size - Size of the vector of template arguments
/// passed as \c template_args
///
///\returns Instantiated templated class/function/variable pointer
CPPINTEROP_API TCppScope_t
InstantiateTemplate(TCppScope_t tmpl, const TemplateArgInfo* template_args,
size_t template_args_size);

/// Returns the class template instantiation arguments of \c templ_instance.
/// Sets the class template instantiation arguments of \c templ_instance.
///
///\param[in] templ_instance - Pointer to the template instance
///\param[out] args - Vector of instantiation arguments
CPPINTEROP_API void
GetClassTemplateInstantiationArgs(TCppScope_t templ_instance,
std::vector<TemplateArgInfo>& args);
Expand All @@ -557,8 +583,15 @@ namespace Cpp {
CPPINTEROP_API TCppFunction_t
InstantiateTemplateFunctionFromString(const char* function_template);

// Find best template match based on explicit template parameters and arg
// types
/// Finds best template match based on explicit template parameters and
/// argument types
///
///\param[in] candidates - Vector of suitable candidates that come under the
/// parent scope and have the same name (obtained using
/// GetClassTemplatedMethods)
///\param[in] explicit_types - set of expicitly instantiated template types
///\param[in] arg_types - set of argument types
///\returns Instantiated function pointer
CPPINTEROP_API TCppFunction_t
BestTemplateFunctionMatch(const std::vector<TCppFunction_t>& candidates,
const std::vector<TemplateArgInfo>& explicit_types,
Expand Down
170 changes: 60 additions & 110 deletions lib/Interpreter/CppInterOp.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -719,54 +719,46 @@ namespace Cpp {
return ComputeBaseOffset(getSema().getASTContext(), DCXXRD, Paths.front());
}

void GetClassMethods(TCppScope_t klass, std::vector<TCppFunction_t> &methods) {
if (!klass) return;

auto *D = (clang::Decl *) klass;

if (auto *TD = dyn_cast<TypedefNameDecl>(D))
D = GetScopeFromType(TD->getUnderlyingType());

if (D && isa<CXXRecordDecl>(D)) {
auto* CXXRD = dyn_cast<CXXRecordDecl>(D);
getSema().ForceDeclarationOfImplicitMembers(CXXRD);
for (Decl* DI : CXXRD->decls()) {
if (auto* MD = dyn_cast<CXXMethodDecl>(DI))
methods.push_back(MD);
else if (auto* USD = dyn_cast<UsingShadowDecl>(DI))
if (auto* MD = dyn_cast<CXXMethodDecl>(USD->getTargetDecl()))
methods.push_back(MD);
}
}
}

void GetFunctionTemplatedDecls(TCppScope_t klass, std::vector<TCppFunction_t> &methods) {
if (!klass) return;
template <typename DeclType>
static void GetClassDecls(TCppScope_t klass,
std::vector<TCppFunction_t>& methods) {
if (!klass)
return;

auto* D = (clang::Decl*)klass;

if (auto* TD = dyn_cast<TypedefNameDecl>(D))
D = GetScopeFromType(TD->getUnderlyingType());

if (D && isa<CXXRecordDecl>(D)) {
auto* CXXRD = dyn_cast<CXXRecordDecl>(D);
getSema().ForceDeclarationOfImplicitMembers(CXXRD);
for (Decl* DI : CXXRD->decls()) {
if (auto* MD = dyn_cast<FunctionTemplateDecl>(DI))
if (!D || !isa<CXXRecordDecl>(D))
return;

auto* CXXRD = dyn_cast<CXXRecordDecl>(D);
getSema().ForceDeclarationOfImplicitMembers(CXXRD);
for (Decl* DI : CXXRD->decls()) {
if (auto* MD = dyn_cast<DeclType>(DI))
methods.push_back(MD);
else if (auto* USD = dyn_cast<UsingShadowDecl>(DI))
if (auto* MD = dyn_cast<DeclType>(USD->getTargetDecl()))
methods.push_back(MD);
else if (auto* USD = dyn_cast<UsingShadowDecl>(DI))
if (auto* MD = dyn_cast<FunctionTemplateDecl>(USD->getTargetDecl()))
methods.push_back(MD);
}
}
}

void GetClassMethods(TCppScope_t klass,
std::vector<TCppFunction_t>& methods) {
GetClassDecls<CXXMethodDecl>(klass, methods);
}

void GetFunctionTemplatedDecls(TCppScope_t klass,
std::vector<TCppFunction_t>& methods) {
GetClassDecls<FunctionTemplateDecl>(klass, methods);
}

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

if (auto *CXXRD = llvm::dyn_cast_or_null<CXXRecordDecl>(D)) {
if (auto* CXXRD = llvm::dyn_cast_or_null<CXXRecordDecl>(D))
return CXXRD->hasDefaultConstructor();
}

return false;
}
Expand Down Expand Up @@ -833,21 +825,19 @@ namespace Cpp {
TCppType_t GetFunctionReturnType(TCppFunction_t func)
{
auto *D = (clang::Decl *) func;
if (auto *FD = llvm::dyn_cast_or_null<clang::FunctionDecl>(D)) {
return FD->getReturnType().getAsOpaquePtr();
}
if (auto* FD = llvm::dyn_cast_or_null<clang::FunctionDecl>(D))
return FD->getReturnType().getAsOpaquePtr();

if (auto* FD = llvm::dyn_cast_or_null<clang::FunctionTemplateDecl>(D)) {
return (FD->getTemplatedDecl())->getReturnType().getAsOpaquePtr();
}
if (auto* FD = llvm::dyn_cast_or_null<clang::FunctionTemplateDecl>(D))
return (FD->getTemplatedDecl())->getReturnType().getAsOpaquePtr();

return 0;
}

TCppIndex_t GetFunctionNumArgs(TCppFunction_t func)
{
auto *D = (clang::Decl *) func;
if (auto *FD = llvm::dyn_cast_or_null<FunctionDecl>(D))
if (auto* FD = llvm::dyn_cast_or_null<FunctionDecl>(D))
return FD->getNumParams();

if (auto* FD = llvm::dyn_cast_or_null<clang::FunctionTemplateDecl>(D))
Expand All @@ -859,9 +849,8 @@ namespace Cpp {
TCppIndex_t GetFunctionRequiredArgs(TCppConstFunction_t func)
{
auto *D = (const clang::Decl *) func;
if (auto *FD = llvm::dyn_cast_or_null<FunctionDecl> (D)) {
if (auto* FD = llvm::dyn_cast_or_null<FunctionDecl>(D))
return FD->getMinRequiredArguments();
}

if (auto* FD = llvm::dyn_cast_or_null<clang::FunctionTemplateDecl>(D))
return (FD->getTemplatedDecl())->getMinRequiredArguments();
Expand All @@ -883,9 +872,7 @@ namespace Cpp {
return 0;
}

std::string GetFunctionSignature(
TCppFunction_t func) { // FIXME : Doesn't work for template functions as
// it does in cling
std::string GetFunctionSignature(TCppFunction_t func) {
if (!func)
return "<unknown>";

Expand All @@ -903,18 +890,6 @@ namespace Cpp {
return Signature;
}

// FIXME: else if (auto *FD = llvm::dyn_cast<FunctionTemplateDecl>(D)) {
// std::string Signature;
// raw_string_ostream SS(Signature);
// PrintingPolicy Policy = getASTContext().getPrintingPolicy();
// // Skip printing the body
// Policy.TerseOutput = true;
// Policy.FullyQualifiedName = true;
// Policy.SuppressDefaultTemplateArgs = false;
// FD->print(SS, Policy);
// SS.flush();
// return Signature;
// }
return "<unknown>";
}

Expand Down Expand Up @@ -954,7 +929,7 @@ namespace Cpp {
{
DeclContext *Within = 0;
if (parent) {
auto *D = (Decl *)parent;
auto* D = (Decl*)parent;
Within = llvm::dyn_cast<DeclContext>(D);
}

Expand All @@ -970,17 +945,16 @@ namespace Cpp {
return true;
}

std::vector<TCppFunction_t> GetTemplatedMethods(const std::string& name,
TCppScope_t parent) {
void GetClassTemplatedMethods(const std::string& name, TCppScope_t parent,
std::vector<TCppFunction_t>& funcs) {

auto* D = (Decl*)parent;

if (!parent || name.empty())
return {};
return;

D = GetUnderlyingScope(D);

std::vector<TCppFunction_t> funcs;
llvm::StringRef Name(name);
auto& S = getSema();
DeclarationName DName = &getASTContext().Idents.get(name);
Expand All @@ -990,73 +964,49 @@ namespace Cpp {
Cpp_utils::Lookup::Named(&S, R, Decl::castToDeclContext(D));

if (R.empty())
return {};
return;

R.resolveKind();

for (auto* Found : R) {
for (auto* Found : R)
if (llvm::isa<FunctionTemplateDecl>(Found))
funcs.push_back(Found);
}

if (!funcs.empty())
return funcs;

return {};
}

TCppFunction_t
BestTemplateFunctionMatch(const std::vector<TCppFunction_t>& candidates,
const std::vector<TemplateArgInfo>& explicit_types,
const std::vector<TemplateArgInfo>& arg_types) {

int k = 1;
for (const auto& candidate : candidates) {
auto* TFD = (FunctionTemplateDecl*)candidate;
clang::TemplateParameterList* tpl = TFD->getTemplateParameters();

if (tpl->size() < explicit_types.size()) {
// template parameter size does not match
++k;
// template parameter size does not match
if (tpl->size() < explicit_types.size())
continue;
}

else {
// right now uninstantiated functions give template typenames instead of
// actual types. We make this match solely based on count

const FunctionDecl* func = TFD->getTemplatedDecl();
// right now uninstantiated functions give template typenames instead of
// actual types. We make this match solely based on count

// Check if number of function parameters match
if (func->getNumParams() != arg_types.size()) {
++k;
continue;
}
const FunctionDecl* func = TFD->getTemplatedDecl();
if (func->getNumParams() != arg_types.size())
continue;

else {
// TODO : first score based on the type similarity before forcing
// instantiation try instantiating
TCppFunction_t instantiated = InstantiateTemplate(
candidate, arg_types.data(), arg_types.size());
if (instantiated)
return instantiated;

// Force the instantiation with template params in case of no args
// maybe steer instantiation better with arg set returned from
// TemplateProxy?
else {
instantiated = InstantiateTemplate(candidate, explicit_types.data(),
explicit_types.size());
if (instantiated)
return instantiated;

else {
k++;
continue;
}
}
}
}
// TODO : first score based on the type similarity before forcing
// instantiation try instantiating
TCppFunction_t instantiated = InstantiateTemplate(
candidate, arg_types.data(), arg_types.size());
if (instantiated)
return instantiated;

// Force the instantiation with template params in case of no args
// maybe steer instantiation better with arg set returned from
// TemplateProxy?
instantiated = InstantiateTemplate(candidate, explicit_types.data(),
explicit_types.size());
if (instantiated)
return instantiated;
}
return nullptr;
}
Expand Down
2 changes: 1 addition & 1 deletion unittests/CppInterOp/FunctionReflectionTest.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -117,7 +117,7 @@ TEST(FunctionReflectionTest, ConstructorInGetClassMethods) {

GetAllTopLevelDecls(code, Decls);

auto has_constructor = [](Decl *D) {
auto has_constructor = [](Decl* D) {
std::vector<Cpp::TCppFunction_t> methods;
Cpp::GetClassMethods(D, methods);
for (auto method : methods) {
Expand Down

0 comments on commit 423b3e1

Please sign in to comment.