Skip to content

Commit 955cdf7

Browse files
[WIP] APIs to enable TypeHints in cppyy
1 parent 2df83a9 commit 955cdf7

File tree

3 files changed

+172
-8
lines changed

3 files changed

+172
-8
lines changed

include/CppInterOp/CppInterOp.h

Lines changed: 20 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -301,7 +301,10 @@ CPPINTEROP_API size_t SizeOf(TCppScope_t scope);
301301
/// Checks if it is a "built-in" or a "complex" type.
302302
CPPINTEROP_API bool IsBuiltin(TCppType_t type);
303303

304-
/// Checks if it is a templated class.
304+
/// Checks if it is a template class.
305+
CPPINTEROP_API bool IsTemplateClass(TCppScope_t handle);
306+
307+
/// Checks if it is a template.
305308
CPPINTEROP_API bool IsTemplate(TCppScope_t handle);
306309

307310
/// Checks if it is a class template specialization class.
@@ -373,6 +376,8 @@ CPPINTEROP_API bool IsVariable(TCppScope_t scope);
373376
/// namespace, variable, or a function).
374377
CPPINTEROP_API std::string GetName(TCppScope_t klass);
375378

379+
CPPINTEROP_API std::string GetDocString(TCppScope_t scope);
380+
376381
/// This is similar to GetName() function, but besides
377382
/// the name, it also gets the template arguments.
378383
CPPINTEROP_API std::string GetCompleteName(TCppScope_t klass);
@@ -437,6 +442,12 @@ CPPINTEROP_API bool IsSubclass(TCppScope_t derived, TCppScope_t base);
437442
CPPINTEROP_API int64_t GetBaseClassOffset(TCppScope_t derived,
438443
TCppScope_t base);
439444

445+
CPPINTEROP_API void GetDatamembersInNamespace(TCppScope_t ns, std::vector<TCppScope_t>& members);
446+
CPPINTEROP_API void GetFunctionsInNamespace(TCppScope_t ns, std::vector<TCppScope_t>& members);
447+
CPPINTEROP_API void GetClassInNamespace(TCppScope_t ns, std::vector<TCppScope_t>& members);
448+
CPPINTEROP_API void GetTemplatedClassInNamespace(TCppScope_t ns, std::vector<TCppScope_t>& members);
449+
CPPINTEROP_API void GetTemplatedFunctionsInNamespace(TCppScope_t ns, std::vector<TCppScope_t>& members);
450+
440451
/// Sets a list of all the Methods that are in the Class that is
441452
/// supplied as a parameter.
442453
///\param[in] klass - Pointer to the scope/class under which the methods have
@@ -490,6 +501,8 @@ CPPINTEROP_API std::string GetFunctionSignature(TCppFunction_t func);
490501
///\returns if a function was marked as \c =delete.
491502
CPPINTEROP_API bool IsFunctionDeleted(TCppConstFunction_t function);
492503

504+
CPPINTEROP_API bool IsTemplateInstantiationOrSpecialization(TCppScope_t scope);
505+
493506
CPPINTEROP_API bool IsTemplatedFunction(TCppFunction_t func);
494507

495508
/// This function performs a lookup to check if there is a
@@ -670,6 +683,12 @@ CPPINTEROP_API bool IsConstMethod(TCppFunction_t method);
670683
CPPINTEROP_API std::string GetFunctionArgDefault(TCppFunction_t func,
671684
TCppIndex_t param_index);
672685

686+
///\returns the size of template arguments
687+
CPPINTEROP_API TCppIndex_t GetTemplateNumArgs(TCppScope_t scope);
688+
689+
///\returns the template argument name of template as string.
690+
CPPINTEROP_API std::string GetTemplateArgName(TCppScope_t scope, TCppIndex_t param_index);
691+
673692
///\returns the argument name of function as string.
674693
CPPINTEROP_API std::string GetFunctionArgName(TCppFunction_t func,
675694
TCppIndex_t param_index);

lib/CppInterOp/CppInterOp.cpp

Lines changed: 150 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@
1212
#include "Compatibility.h"
1313

1414
#include "clang/AST/Attrs.inc"
15+
#include "clang/AST/Comment.h"
1516
#include "clang/AST/CXXInheritance.h"
1617
#include "clang/AST/Decl.h"
1718
#include "clang/AST/DeclAccessPair.h"
@@ -380,6 +381,11 @@ bool IsBuiltin(TCppType_t type) {
380381
return llvm::StringRef(Ty.getAsString()).contains("complex");
381382
}
382383

384+
bool IsTemplateClass(TCppScope_t handle) {
385+
auto* D = (clang::Decl*)handle;
386+
return llvm::isa_and_nonnull<clang::ClassTemplateDecl>(D);
387+
}
388+
383389
bool IsTemplate(TCppScope_t handle) {
384390
auto* D = (clang::Decl*)handle;
385391
return llvm::isa_and_nonnull<clang::TemplateDecl>(D);
@@ -546,6 +552,15 @@ bool IsVariable(TCppScope_t scope) {
546552
return llvm::isa_and_nonnull<clang::VarDecl>(D);
547553
}
548554

555+
std::string GetDocString(TCppScope_t scope) {
556+
auto *D = static_cast<Decl*>(scope);
557+
auto &AST = getASTContext(D);
558+
const clang::RawComment *Comment = AST.getRawCommentForAnyRedecl(D);
559+
if (!Comment)
560+
return "";
561+
return Comment->getFormattedText(AST.getSourceManager(), AST.getDiagnostics());
562+
}
563+
549564
std::string GetName(TCppType_t klass) {
550565
auto* D = (clang::NamedDecl*)klass;
551566

@@ -877,6 +892,98 @@ int64_t GetBaseClassOffset(TCppScope_t derived, TCppScope_t base) {
877892
return ComputeBaseOffset(getSema().getASTContext(), DCXXRD, Paths.front());
878893
}
879894

895+
template <typename DeclType>
896+
static void GetNamespaceDecls(TCppScope_t ns,
897+
std::vector<TCppScope_t>& members) {
898+
if (!ns)
899+
return;
900+
901+
auto* D = (clang::Decl*)ns;
902+
LOCK(getInterpInfo(D));
903+
904+
if (!D || !isa<NamespaceDecl>(D))
905+
return;
906+
907+
auto* NSD = dyn_cast<NamespaceDecl>(D)->getMostRecentDecl();
908+
while (NSD) {
909+
for (Decl* DI : NSD->decls()) {
910+
if (auto* MD = dyn_cast<DeclType>(DI))
911+
members.push_back(MD);
912+
else if (auto* USD = dyn_cast<UsingShadowDecl>(DI)) {
913+
if (auto *MD = dyn_cast<DeclType>(USD->getTargetDecl()))
914+
members.push_back(MD);
915+
}
916+
}
917+
NSD = NSD->getPreviousDecl();
918+
}
919+
}
920+
921+
void GetDatamembersInNamespace(TCppScope_t ns, std::vector<TCppScope_t>& members) {
922+
GetNamespaceDecls<VarDecl>(ns, members);
923+
}
924+
925+
void GetFunctionsInNamespace(TCppScope_t ns, std::vector<TCppScope_t>& members) {
926+
GetNamespaceDecls<FunctionDecl>(ns, members);
927+
}
928+
929+
void GetClassInNamespace(TCppScope_t ns, std::vector<TCppScope_t>& members) {
930+
GetNamespaceDecls<RecordDecl>(ns, members);
931+
}
932+
933+
void GetTemplatedClassInNamespace(TCppScope_t ns, std::vector<TCppScope_t>& members) {
934+
GetNamespaceDecls<ClassTemplateDecl>(ns, members);
935+
}
936+
937+
void GetTemplatedFunctionsInNamespace(TCppScope_t ns, std::vector<TCppScope_t>& members) {
938+
GetNamespaceDecls<FunctionTemplateDecl>(ns, members);
939+
}
940+
941+
template <typename DeclType>
942+
static void GetNamespaceDecls(TCppScope_t ns,
943+
std::vector<TCppScope_t>& members) {
944+
if (!ns)
945+
return;
946+
947+
auto* D = (clang::Decl*)ns;
948+
LOCK(getInterpInfo(D));
949+
950+
if (!D || !isa<NamespaceDecl>(D))
951+
return;
952+
953+
auto* NSD = dyn_cast<NamespaceDecl>(D)->getMostRecentDecl();
954+
while (NSD) {
955+
for (Decl* DI : NSD->decls()) {
956+
if (auto* MD = dyn_cast<DeclType>(DI))
957+
members.push_back(MD);
958+
else if (auto* USD = dyn_cast<UsingShadowDecl>(DI)) {
959+
if (auto *MD = dyn_cast<DeclType>(USD->getTargetDecl()))
960+
members.push_back(MD);
961+
}
962+
}
963+
NSD = NSD->getPreviousDecl();
964+
}
965+
}
966+
967+
void GetDatamembersInNamespace(TCppScope_t ns, std::vector<TCppScope_t>& members) {
968+
GetNamespaceDecls<VarDecl>(ns, members);
969+
}
970+
971+
void GetFunctionsInNamespace(TCppScope_t ns, std::vector<TCppScope_t>& members) {
972+
GetNamespaceDecls<FunctionDecl>(ns, members);
973+
}
974+
975+
void GetClassInNamespace(TCppScope_t ns, std::vector<TCppScope_t>& members) {
976+
GetNamespaceDecls<RecordDecl>(ns, members);
977+
}
978+
979+
void GetTemplatedClassInNamespace(TCppScope_t ns, std::vector<TCppScope_t>& members) {
980+
GetNamespaceDecls<ClassTemplateDecl>(ns, members);
981+
}
982+
983+
void GetTemplatedFunctionsInNamespace(TCppScope_t ns, std::vector<TCppScope_t>& members) {
984+
GetNamespaceDecls<FunctionTemplateDecl>(ns, members);
985+
}
986+
880987
template <typename DeclType>
881988
static void GetClassDecls(TCppScope_t klass,
882989
std::vector<TCppFunction_t>& methods) {
@@ -888,6 +995,10 @@ static void GetClassDecls(TCppScope_t klass,
888995
if (auto* TD = dyn_cast<TypedefNameDecl>(D))
889996
D = GetScopeFromType(TD->getUnderlyingType());
890997

998+
if (auto *CTD = llvm::dyn_cast_or_null<ClassTemplateDecl>(D)) {
999+
D = CTD->getTemplatedDecl();
1000+
}
1001+
8911002
if (!D || !isa<CXXRecordDecl>(D))
8921003
return;
8931004

@@ -1011,7 +1122,7 @@ TCppType_t GetFunctionReturnType(TCppFunction_t func) {
10111122
QualType Type = FD->getReturnType();
10121123
if (Type->isUndeducedAutoType()) {
10131124
bool needInstantiation = false;
1014-
if (IsTemplatedFunction(FD) && !FD->isDefined())
1125+
if (IsTemplateInstantiationOrSpecialization(FD) && !FD->isDefined())
10151126
needInstantiation = true;
10161127
if (auto* MD = llvm::dyn_cast<clang::CXXMethodDecl>(FD)) {
10171128
if (IsTemplateSpecialization(MD->getParent()))
@@ -1055,8 +1166,10 @@ TCppIndex_t GetFunctionRequiredArgs(TCppConstFunction_t func) {
10551166
}
10561167

10571168
TCppType_t GetFunctionArgType(TCppFunction_t func, TCppIndex_t iarg) {
1058-
auto* D = (clang::Decl*)func;
1059-
1169+
auto* D = static_cast<clang::Decl*>(func);
1170+
if (auto *FTD = llvm::dyn_cast_or_null<FunctionTemplateDecl>(D)) {
1171+
D = FTD->getTemplatedDecl();
1172+
}
10601173
if (auto* FD = llvm::dyn_cast_or_null<clang::FunctionDecl>(D)) {
10611174
if (iarg < FD->getNumParams()) {
10621175
auto* PVD = FD->getParamDecl(iarg);
@@ -1122,7 +1235,12 @@ bool IsFunctionDeleted(TCppConstFunction_t function) {
11221235

11231236
bool IsTemplatedFunction(TCppFunction_t func) {
11241237
auto* D = (Decl*)func;
1125-
return IsTemplatedFunction(D) || IsTemplateInstantiationOrSpecialization(D);
1238+
return IsTemplatedFunction(D) /*|| IsTemplateInstantiationOrSpecialization(D)*/;
1239+
}
1240+
1241+
bool IsTemplateInstantiationOrSpecialization(TCppScope_t scope) {
1242+
auto *D = static_cast<Decl*>(scope);
1243+
return IsTemplateInstantiationOrSpecialization(D);
11261244
}
11271245

11281246
// FIXME: This lookup is broken, and should no longer be used in favour of
@@ -1334,6 +1452,9 @@ bool IsDestructor(TCppConstFunction_t method) {
13341452

13351453
bool IsStaticMethod(TCppConstFunction_t method) {
13361454
const auto* D = static_cast<const Decl*>(method);
1455+
if (auto *FTD = llvm::dyn_cast_or_null<FunctionTemplateDecl>(D)) {
1456+
D = FTD->getTemplatedDecl();
1457+
}
13371458
if (auto* CXXMD = llvm::dyn_cast_or_null<CXXMethodDecl>(D)) {
13381459
return CXXMD->isStatic();
13391460
}
@@ -1404,6 +1525,9 @@ bool IsVirtualMethod(TCppFunction_t method) {
14041525

14051526
void GetDatamembers(TCppScope_t scope, std::vector<TCppScope_t>& datamembers) {
14061527
auto* D = (Decl*)scope;
1528+
if (auto *CTD = llvm::dyn_cast_or_null<ClassTemplateDecl>(D)) {
1529+
D = CTD->getTemplatedDecl();
1530+
}
14071531

14081532
if (auto* CXXRD = llvm::dyn_cast_or_null<CXXRecordDecl>(D)) {
14091533
getSema().ForceDeclarationOfImplicitMembers(CXXRD);
@@ -1497,7 +1621,7 @@ TCppType_t GetVariableType(TCppScope_t var) {
14971621
QualType QT = DD->getType();
14981622

14991623
// Check if the type is a typedef type
1500-
if (QT->isTypedefNameType()) {
1624+
if (QT->isTypedefNameType() || QT->getAs<clang::TemplateTypeParmType>()) {
15011625
return QT.getAsOpaquePtr();
15021626
}
15031627

@@ -1758,6 +1882,8 @@ TCppType_t GetCanonicalType(TCppType_t type) {
17581882
if (!type)
17591883
return 0;
17601884
QualType QT = QualType::getFromOpaquePtr(type);
1885+
if (QT->getAs<clang::TemplateTypeParmType>())
1886+
return type;
17611887
return QT.getCanonicalType().getAsOpaquePtr();
17621888
}
17631889

@@ -3841,6 +3967,25 @@ bool IsConstMethod(TCppFunction_t method) {
38413967
return false;
38423968
}
38433969

3970+
TCppIndex_t GetTemplateNumArgs(TCppScope_t scope) {
3971+
auto *D = static_cast<Decl*>(scope);
3972+
if (auto *TD = llvm::dyn_cast<TemplateDecl>(D)) {
3973+
auto *TPL = TD->getTemplateParameters();
3974+
return TPL->size();
3975+
}
3976+
return -1;
3977+
}
3978+
3979+
std::string GetTemplateArgName(TCppScope_t scope, TCppIndex_t param_index) {
3980+
auto *D = static_cast<Decl*>(scope);
3981+
if (auto *TD = llvm::dyn_cast<TemplateDecl>(D)) {
3982+
auto *TPL = TD->getTemplateParameters();
3983+
NamedDecl *ND = TPL->getParam(param_index);
3984+
return ND->getNameAsString();
3985+
}
3986+
return "";
3987+
}
3988+
38443989
std::string GetFunctionArgName(TCppFunction_t func, TCppIndex_t param_index) {
38453990
auto* D = (clang::Decl*)func;
38463991
clang::ParmVarDecl* PI = nullptr;

unittests/CppInterOp/FunctionReflectionTest.cpp

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -929,7 +929,7 @@ TYPED_TEST(CppInterOpTest, FunctionReflectionTestInstantiateVariadicFunction) {
929929
C.IntTy.getAsOpaquePtr()};
930930
auto Instance1 = Cpp::InstantiateTemplate(Decls[1], args1.data(),
931931
/*type_size*/ args1.size());
932-
EXPECT_TRUE(Cpp::IsTemplatedFunction(Instance1));
932+
EXPECT_TRUE(Cpp::IsTemplateInstantiationOrSpecialization(Instance1));
933933
EXPECT_EQ(Cpp::GetFunctionSignature(Instance1),
934934
"template<> void VariadicFn<<double, int>>(double args, int args)");
935935

@@ -952,7 +952,7 @@ TYPED_TEST(CppInterOpTest, FunctionReflectionTestInstantiateVariadicFunction) {
952952
// instantiate VariadicFnExtended
953953
auto Instance2 =
954954
Cpp::InstantiateTemplate(Decls[2], args2.data(), args2.size(), true);
955-
EXPECT_TRUE(Cpp::IsTemplatedFunction(Instance2));
955+
EXPECT_TRUE(Cpp::IsTemplateInstantiationOrSpecialization(Instance2));
956956

957957
FunctionDecl* FD2 = cast<FunctionDecl>((Decl*)Instance2);
958958
FunctionDecl* FnTD2 = FD2->getTemplateInstantiationPattern();

0 commit comments

Comments
 (0)