diff options
Diffstat (limited to 'clang/tools')
-rw-r--r-- | clang/tools/c-index-test/c-index-test.c | 31 | ||||
-rw-r--r-- | clang/tools/libclang/CXCursor.cpp | 134 | ||||
-rw-r--r-- | clang/tools/libclang/libclang.exports | 5 |
3 files changed, 168 insertions, 2 deletions
diff --git a/clang/tools/c-index-test/c-index-test.c b/clang/tools/c-index-test/c-index-test.c index d7c28ddb1e9..56e4101399a 100644 --- a/clang/tools/c-index-test/c-index-test.c +++ b/clang/tools/c-index-test/c-index-test.c @@ -796,15 +796,42 @@ static void PrintCursor(CXCursor Cursor, const char *CommentSchemaFile) { printf(" [access=%s isVirtual=%s]", accessStr, isVirtual ? "true" : "false"); } - + SpecializationOf = clang_getSpecializedCursorTemplate(Cursor); if (!clang_equalCursors(SpecializationOf, clang_getNullCursor())) { CXSourceLocation Loc = clang_getCursorLocation(SpecializationOf); CXString Name = clang_getCursorSpelling(SpecializationOf); clang_getSpellingLocation(Loc, 0, &line, &column, 0); - printf(" [Specialization of %s:%d:%d]", + printf(" [Specialization of %s:%d:%d]", clang_getCString(Name), line, column); clang_disposeString(Name); + + if (Cursor.kind == CXCursor_FunctionDecl) { + /* Collect the template parameter kinds from the base template. */ + unsigned NumTemplateArgs = clang_Cursor_getNumTemplateArguments(Cursor); + unsigned I; + for (I = 0; I < NumTemplateArgs; I++) { + enum CXTemplateArgumentKind TAK = + clang_Cursor_getTemplateArgumentKind(Cursor, I); + switch(TAK) { + case CXTemplateArgumentKind_Type: + { + CXType T = clang_Cursor_getTemplateArgumentType(Cursor, I); + CXString S = clang_getTypeSpelling(T); + printf(" [Template arg %d: kind: %d, type: %s]", + I, TAK, clang_getCString(S)); + clang_disposeString(S); + } + break; + case CXTemplateArgumentKind_Integral: + printf(" [Template arg %d: kind: %d, intval: %lld]", + I, TAK, clang_Cursor_getTemplateArgumentValue(Cursor, I)); + break; + default: + printf(" [Template arg %d: kind: %d]\n", I, TAK); + } + } + } } clang_getOverriddenCursors(Cursor, &overridden, &num_overridden); diff --git a/clang/tools/libclang/CXCursor.cpp b/clang/tools/libclang/CXCursor.cpp index 782f05e1e85..6590b158e5c 100644 --- a/clang/tools/libclang/CXCursor.cpp +++ b/clang/tools/libclang/CXCursor.cpp @@ -1074,6 +1074,140 @@ CXCursor clang_Cursor_getArgument(CXCursor C, unsigned i) { return clang_getNullCursor(); } +int clang_Cursor_getNumTemplateArguments(CXCursor C) { + if (clang_getCursorKind(C) != CXCursor_FunctionDecl) { + return -1; + } + + const FunctionDecl *FD = llvm::dyn_cast_or_null<clang::FunctionDecl>( + getCursorDecl(C)); + if (!FD) { + return -1; + } + + const FunctionTemplateSpecializationInfo* SpecInfo = + FD->getTemplateSpecializationInfo(); + if (!SpecInfo) { + return -1; + } + + return SpecInfo->TemplateArguments->size(); +} + +enum CXGetTemplateArgumentStatus { + /** \brief The operation completed successfully */ + CXGetTemplateArgumentStatus_Success = 0, + + /** \brief The specified cursor did not represent a FunctionDecl. */ + CXGetTemplateArgumentStatus_CursorNotFunctionDecl = -1, + + /** \brief The specified cursor was not castable to a FunctionDecl. */ + CXGetTemplateArgumentStatus_BadFunctionDeclCast = -2, + + /** \brief A NULL FunctionTemplateSpecializationInfo was retrieved. */ + CXGetTemplateArgumentStatus_NullTemplSpecInfo = -3, + + /** \brief An invalid (OOB) argument index was specified */ + CXGetTemplateArgumentStatus_InvalidIndex = -4 +}; + +static int clang_Cursor_getTemplateArgument( + CXCursor C, unsigned I, TemplateArgument *TA) { + if (clang_getCursorKind(C) != CXCursor_FunctionDecl) { + return CXGetTemplateArgumentStatus_CursorNotFunctionDecl; + } + + const FunctionDecl *FD = llvm::dyn_cast_or_null<clang::FunctionDecl>( + getCursorDecl(C)); + if (!FD) { + return CXGetTemplateArgumentStatus_BadFunctionDeclCast; + } + + const FunctionTemplateSpecializationInfo* SpecInfo = + FD->getTemplateSpecializationInfo(); + if (!SpecInfo) { + return CXGetTemplateArgumentStatus_NullTemplSpecInfo; + } + + if (I >= SpecInfo->TemplateArguments->size()) { + return CXGetTemplateArgumentStatus_InvalidIndex; + } + + *TA = SpecInfo->TemplateArguments->get(I); + return 0; +} + +enum CXTemplateArgumentKind clang_Cursor_getTemplateArgumentKind(CXCursor C, + unsigned I) { + TemplateArgument TA; + if (clang_Cursor_getTemplateArgument(C, I, &TA)) { + return CXTemplateArgumentKind_Invalid; + } + + switch (TA.getKind()) { + case TemplateArgument::Null: return CXTemplateArgumentKind_Null; + case TemplateArgument::Type: return CXTemplateArgumentKind_Type; + case TemplateArgument::Declaration: + return CXTemplateArgumentKind_Declaration; + case TemplateArgument::NullPtr: return CXTemplateArgumentKind_NullPtr; + case TemplateArgument::Integral: return CXTemplateArgumentKind_Integral; + case TemplateArgument::Template: return CXTemplateArgumentKind_Template; + case TemplateArgument::TemplateExpansion: + return CXTemplateArgumentKind_TemplateExpansion; + case TemplateArgument::Expression: return CXTemplateArgumentKind_Expression; + case TemplateArgument::Pack: return CXTemplateArgumentKind_Pack; + } + + return CXTemplateArgumentKind_Invalid; +} + +CXType clang_Cursor_getTemplateArgumentType(CXCursor C, unsigned I) { + TemplateArgument TA; + if (clang_Cursor_getTemplateArgument(C, I, &TA) != + CXGetTemplateArgumentStatus_Success) { + return cxtype::MakeCXType(QualType(), getCursorTU(C)); + } + + if (TA.getKind() != TemplateArgument::Type) { + return cxtype::MakeCXType(QualType(), getCursorTU(C)); + } + + return cxtype::MakeCXType(TA.getAsType(), getCursorTU(C)); +} + +long long clang_Cursor_getTemplateArgumentValue(CXCursor C, unsigned I) { + TemplateArgument TA; + if (clang_Cursor_getTemplateArgument(C, I, &TA) != + CXGetTemplateArgumentStatus_Success) { + assert(0 && "Unable to retrieve TemplateArgument"); + return 0; + } + + if (TA.getKind() != TemplateArgument::Integral) { + assert(0 && "Passed template argument is not Integral"); + return 0; + } + + return TA.getAsIntegral().getSExtValue(); +} + +unsigned long long clang_Cursor_getTemplateArgumentUnsignedValue(CXCursor C, + unsigned I) { + TemplateArgument TA; + if (clang_Cursor_getTemplateArgument(C, I, &TA) != + CXGetTemplateArgumentStatus_Success) { + assert(0 && "Unable to retrieve TemplateArgument"); + return 0; + } + + if (TA.getKind() != TemplateArgument::Integral) { + assert(0 && "Passed template argument is not Integral"); + return 0; + } + + return TA.getAsIntegral().getZExtValue(); +} + } // end: extern "C" //===----------------------------------------------------------------------===// diff --git a/clang/tools/libclang/libclang.exports b/clang/tools/libclang/libclang.exports index 5a029f7e4f9..d7701ad9751 100644 --- a/clang/tools/libclang/libclang.exports +++ b/clang/tools/libclang/libclang.exports @@ -7,6 +7,11 @@ clang_CXXMethod_isPureVirtual clang_CXXMethod_isStatic clang_CXXMethod_isVirtual clang_Cursor_getArgument +clang_Cursor_getNumTemplateArguments +clang_Cursor_getTemplateArgumentKind +clang_Cursor_getTemplateArgumentType +clang_Cursor_getTemplateArgumentValue +clang_Cursor_getTemplateArgumentUnsignedValue clang_Cursor_getBriefCommentText clang_Cursor_getCommentRange clang_Cursor_getMangling |