Skip to content

Commit 5e53412

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

File tree

3 files changed

+125
-8
lines changed

3 files changed

+125
-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: 103 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();
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,51 @@ 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+
903+
if (!D || !isa<NamespaceDecl>(D))
904+
return;
905+
906+
auto* NSD = dyn_cast<NamespaceDecl>(D)->getMostRecentDecl();
907+
while (NSD) {
908+
for (Decl* DI : NSD->decls()) {
909+
if (auto* MD = dyn_cast<DeclType>(DI))
910+
members.push_back(MD);
911+
else if (auto* USD = dyn_cast<UsingShadowDecl>(DI)) {
912+
if (auto *MD = dyn_cast<DeclType>(USD->getTargetDecl()))
913+
members.push_back(MD);
914+
}
915+
}
916+
NSD = NSD->getPreviousDecl();
917+
}
918+
}
919+
920+
void GetDatamembersInNamespace(TCppScope_t ns, std::vector<TCppScope_t>& members) {
921+
GetNamespaceDecls<VarDecl>(ns, members);
922+
}
923+
924+
void GetFunctionsInNamespace(TCppScope_t ns, std::vector<TCppScope_t>& members) {
925+
GetNamespaceDecls<FunctionDecl>(ns, members);
926+
}
927+
928+
void GetClassInNamespace(TCppScope_t ns, std::vector<TCppScope_t>& members) {
929+
GetNamespaceDecls<RecordDecl>(ns, members);
930+
}
931+
932+
void GetTemplatedClassInNamespace(TCppScope_t ns, std::vector<TCppScope_t>& members) {
933+
GetNamespaceDecls<ClassTemplateDecl>(ns, members);
934+
}
935+
936+
void GetTemplatedFunctionsInNamespace(TCppScope_t ns, std::vector<TCppScope_t>& members) {
937+
GetNamespaceDecls<FunctionTemplateDecl>(ns, members);
938+
}
939+
880940
template <typename DeclType>
881941
static void GetClassDecls(TCppScope_t klass,
882942
std::vector<TCppFunction_t>& methods) {
@@ -888,6 +948,10 @@ static void GetClassDecls(TCppScope_t klass,
888948
if (auto* TD = dyn_cast<TypedefNameDecl>(D))
889949
D = GetScopeFromType(TD->getUnderlyingType());
890950

951+
if (auto *CTD = llvm::dyn_cast_or_null<ClassTemplateDecl>(D)) {
952+
D = CTD->getTemplatedDecl();
953+
}
954+
891955
if (!D || !isa<CXXRecordDecl>(D))
892956
return;
893957

@@ -1011,7 +1075,7 @@ TCppType_t GetFunctionReturnType(TCppFunction_t func) {
10111075
QualType Type = FD->getReturnType();
10121076
if (Type->isUndeducedAutoType()) {
10131077
bool needInstantiation = false;
1014-
if (IsTemplatedFunction(FD) && !FD->isDefined())
1078+
if (IsTemplateInstantiationOrSpecialization(FD) && !FD->isDefined())
10151079
needInstantiation = true;
10161080
if (auto* MD = llvm::dyn_cast<clang::CXXMethodDecl>(FD)) {
10171081
if (IsTemplateSpecialization(MD->getParent()))
@@ -1055,8 +1119,10 @@ TCppIndex_t GetFunctionRequiredArgs(TCppConstFunction_t func) {
10551119
}
10561120

10571121
TCppType_t GetFunctionArgType(TCppFunction_t func, TCppIndex_t iarg) {
1058-
auto* D = (clang::Decl*)func;
1059-
1122+
auto* D = static_cast<clang::Decl*>(func);
1123+
if (auto *FTD = llvm::dyn_cast_or_null<FunctionTemplateDecl>(D)) {
1124+
D = FTD->getTemplatedDecl();
1125+
}
10601126
if (auto* FD = llvm::dyn_cast_or_null<clang::FunctionDecl>(D)) {
10611127
if (iarg < FD->getNumParams()) {
10621128
auto* PVD = FD->getParamDecl(iarg);
@@ -1122,7 +1188,12 @@ bool IsFunctionDeleted(TCppConstFunction_t function) {
11221188

11231189
bool IsTemplatedFunction(TCppFunction_t func) {
11241190
auto* D = (Decl*)func;
1125-
return IsTemplatedFunction(D) || IsTemplateInstantiationOrSpecialization(D);
1191+
return IsTemplatedFunction(D) /*|| IsTemplateInstantiationOrSpecialization(D)*/;
1192+
}
1193+
1194+
bool IsTemplateInstantiationOrSpecialization(TCppScope_t scope) {
1195+
auto *D = static_cast<Decl*>(scope);
1196+
return IsTemplateInstantiationOrSpecialization(D);
11261197
}
11271198

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

13351406
bool IsStaticMethod(TCppConstFunction_t method) {
13361407
const auto* D = static_cast<const Decl*>(method);
1408+
if (auto *FTD = llvm::dyn_cast_or_null<FunctionTemplateDecl>(D)) {
1409+
D = FTD->getTemplatedDecl();
1410+
}
13371411
if (auto* CXXMD = llvm::dyn_cast_or_null<CXXMethodDecl>(D)) {
13381412
return CXXMD->isStatic();
13391413
}
@@ -1404,6 +1478,9 @@ bool IsVirtualMethod(TCppFunction_t method) {
14041478

14051479
void GetDatamembers(TCppScope_t scope, std::vector<TCppScope_t>& datamembers) {
14061480
auto* D = (Decl*)scope;
1481+
if (auto *CTD = llvm::dyn_cast_or_null<ClassTemplateDecl>(D)) {
1482+
D = CTD->getTemplatedDecl();
1483+
}
14071484

14081485
if (auto* CXXRD = llvm::dyn_cast_or_null<CXXRecordDecl>(D)) {
14091486
getSema().ForceDeclarationOfImplicitMembers(CXXRD);
@@ -1497,7 +1574,7 @@ TCppType_t GetVariableType(TCppScope_t var) {
14971574
QualType QT = DD->getType();
14981575

14991576
// Check if the type is a typedef type
1500-
if (QT->isTypedefNameType()) {
1577+
if (QT->isTypedefNameType() || QT->getAs<clang::TemplateTypeParmType>()) {
15011578
return QT.getAsOpaquePtr();
15021579
}
15031580

@@ -1758,6 +1835,8 @@ TCppType_t GetCanonicalType(TCppType_t type) {
17581835
if (!type)
17591836
return 0;
17601837
QualType QT = QualType::getFromOpaquePtr(type);
1838+
if (QT->getAs<clang::TemplateTypeParmType>())
1839+
return type;
17611840
return QT.getCanonicalType().getAsOpaquePtr();
17621841
}
17631842

@@ -3841,6 +3920,25 @@ bool IsConstMethod(TCppFunction_t method) {
38413920
return false;
38423921
}
38433922

3923+
TCppIndex_t GetTemplateNumArgs(TCppScope_t scope) {
3924+
auto *D = static_cast<Decl*>(scope);
3925+
if (auto *TD = llvm::dyn_cast<TemplateDecl>(D)) {
3926+
auto *TPL = TD->getTemplateParameters();
3927+
return TPL->size();
3928+
}
3929+
return -1;
3930+
}
3931+
3932+
std::string GetTemplateArgName(TCppScope_t scope, TCppIndex_t param_index) {
3933+
auto *D = static_cast<Decl*>(scope);
3934+
if (auto *TD = llvm::dyn_cast<TemplateDecl>(D)) {
3935+
auto *TPL = TD->getTemplateParameters();
3936+
NamedDecl *ND = TPL->getParam(param_index);
3937+
return ND->getNameAsString();
3938+
}
3939+
return "";
3940+
}
3941+
38443942
std::string GetFunctionArgName(TCppFunction_t func, TCppIndex_t param_index) {
38453943
auto* D = (clang::Decl*)func;
38463944
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)