diff --git a/clang/docs/ReleaseNotes.rst b/clang/docs/ReleaseNotes.rst --- a/clang/docs/ReleaseNotes.rst +++ b/clang/docs/ReleaseNotes.rst @@ -402,6 +402,10 @@ the behavior of ``QualType::getNonReferenceType`` for ``CXType``. - Introduced the new function ``clang_CXXMethod_isDeleted``, which queries whether the method is declared ``= delete``. +- ``clang_Cursor_getNumTemplateArguments``, ``clang_Cursor_getTemplateArgumentKind``, + ``clang_Cursor_getTemplateArgumentType``, ``clang_Cursor_getTemplateArgumentValue`` and + ``clang_Cursor_getTemplateArgumentUnsignedValue`` now work on struct, class and partial template specialization + cursors in addition to function cursors. Static Analyzer --------------- diff --git a/clang/include/clang-c/Index.h b/clang/include/clang-c/Index.h --- a/clang/include/clang-c/Index.h +++ b/clang/include/clang-c/Index.h @@ -3591,8 +3591,8 @@ }; /** - *Returns the number of template args of a function decl representing a - * template specialization. + *Returns the number of template args of a function, struct, or class decl + *representing a template specialization. * * If the argument cursor cannot be converted into a template function * declaration, -1 is returned. @@ -3611,8 +3611,9 @@ /** * Retrieve the kind of the I'th template argument of the CXCursor C. * - * If the argument CXCursor does not represent a FunctionDecl, an invalid - * template argument kind is returned. + * If the argument CXCursor does not represent a FunctionDecl, StructDecl, or + * ClassTemplatePartialSpecialization, an invalid template argument kind is + * returned. * * For example, for the following declaration and specialization: * template @@ -3631,9 +3632,9 @@ * Retrieve a CXType representing the type of a TemplateArgument of a * function decl representing a template specialization. * - * If the argument CXCursor does not represent a FunctionDecl whose I'th - * template argument has a kind of CXTemplateArgKind_Integral, an invalid type - * is returned. + * If the argument CXCursor does not represent a FunctionDecl, StructDecl, + * ClassDecl or ClassTemplatePartialSpecialization whose I'th template argument + * has a kind of CXTemplateArgKind_Integral, an invalid type is returned. * * For example, for the following declaration and specialization: * template @@ -3653,7 +3654,8 @@ * decl representing a template specialization) as a signed long long. * * It is undefined to call this function on a CXCursor that does not represent a - * FunctionDecl or whose I'th template argument is not an integral value. + * FunctionDecl, StructDecl, ClassDecl or ClassTemplatePartialSpecialization + * whose I'th template argument is not an integral value. * * For example, for the following declaration and specialization: * template @@ -3673,7 +3675,8 @@ * decl representing a template specialization) as an unsigned long long. * * It is undefined to call this function on a CXCursor that does not represent a - * FunctionDecl or whose I'th template argument is not an integral value. + * FunctionDecl, StructDecl, ClassDecl or ClassTemplatePartialSpecialization or + * whose I'th template argument is not an integral value. * * For example, for the following declaration and specialization: * template diff --git a/clang/tools/libclang/CXCursor.cpp b/clang/tools/libclang/CXCursor.cpp --- a/clang/tools/libclang/CXCursor.cpp +++ b/clang/tools/libclang/CXCursor.cpp @@ -1353,34 +1353,42 @@ } int clang_Cursor_getNumTemplateArguments(CXCursor C) { - if (clang_getCursorKind(C) != CXCursor_FunctionDecl) { + CXCursorKind kind = clang_getCursorKind(C); + if (kind != CXCursor_FunctionDecl && kind != CXCursor_StructDecl && + kind != CXCursor_ClassDecl && + kind != CXCursor_ClassTemplatePartialSpecialization) { return -1; } - const FunctionDecl *FD = - llvm::dyn_cast_or_null(getCursorDecl(C)); - if (!FD) { - return -1; - } - - const FunctionTemplateSpecializationInfo *SpecInfo = - FD->getTemplateSpecializationInfo(); - if (!SpecInfo) { + if (const FunctionDecl *FD = + llvm::dyn_cast_if_present(getCursorDecl(C))) { + const FunctionTemplateSpecializationInfo *SpecInfo = + FD->getTemplateSpecializationInfo(); + if (!SpecInfo) { + return -1; + } + return SpecInfo->TemplateArguments->size(); + } else if (const ClassTemplateSpecializationDecl *SD = + llvm::dyn_cast_if_present< + clang::ClassTemplateSpecializationDecl>( + getCursorDecl(C))) { + return SD->getTemplateArgs().size(); + } else { return -1; } - - return SpecInfo->TemplateArguments->size(); } enum CXGetTemplateArgumentStatus { /** The operation completed successfully */ CXGetTemplateArgumentStatus_Success = 0, - /** The specified cursor did not represent a FunctionDecl. */ - CXGetTemplateArgumentStatus_CursorNotFunctionDecl = -1, + /** The specified cursor did not represent a FunctionDecl or + ClassTemplateSpecializationDecl. */ + CXGetTemplateArgumentStatus_CursorNotCompatibleDecl = -1, - /** The specified cursor was not castable to a FunctionDecl. */ - CXGetTemplateArgumentStatus_BadFunctionDeclCast = -2, + /** The specified cursor was not castable to a FunctionDecl or + ClassTemplateSpecializationDecl. */ + CXGetTemplateArgumentStatus_BadDeclCast = -2, /** A NULL FunctionTemplateSpecializationInfo was retrieved. */ CXGetTemplateArgumentStatus_NullTemplSpecInfo = -3, @@ -1391,28 +1399,43 @@ static int clang_Cursor_getTemplateArgument(CXCursor C, unsigned I, TemplateArgument *TA) { - if (clang_getCursorKind(C) != CXCursor_FunctionDecl) { - return CXGetTemplateArgumentStatus_CursorNotFunctionDecl; + CXCursorKind kind = clang_getCursorKind(C); + if (kind != CXCursor_FunctionDecl && kind != CXCursor_StructDecl && + kind != CXCursor_ClassDecl && + kind != CXCursor_ClassTemplatePartialSpecialization) { + return -1; } - const FunctionDecl *FD = - llvm::dyn_cast_or_null(getCursorDecl(C)); - if (!FD) { - return CXGetTemplateArgumentStatus_BadFunctionDeclCast; - } + if (const FunctionDecl *FD = + llvm::dyn_cast_if_present(getCursorDecl(C))) { - const FunctionTemplateSpecializationInfo *SpecInfo = - FD->getTemplateSpecializationInfo(); - if (!SpecInfo) { - return CXGetTemplateArgumentStatus_NullTemplSpecInfo; - } + const FunctionTemplateSpecializationInfo *SpecInfo = + FD->getTemplateSpecializationInfo(); + if (!SpecInfo) { + return CXGetTemplateArgumentStatus_NullTemplSpecInfo; + } - if (I >= SpecInfo->TemplateArguments->size()) { - return CXGetTemplateArgumentStatus_InvalidIndex; - } + if (I >= SpecInfo->TemplateArguments->size()) { + return CXGetTemplateArgumentStatus_InvalidIndex; + } - *TA = SpecInfo->TemplateArguments->get(I); - return 0; + *TA = SpecInfo->TemplateArguments->get(I); + return 0; + } else if (const ClassTemplateSpecializationDecl *SD = + llvm::dyn_cast_if_present< + clang::ClassTemplateSpecializationDecl>( + getCursorDecl(C))) { + if (I >= SD->getTemplateArgs().size()) { + printf("INVALID INDEX\n"); + return CXGetTemplateArgumentStatus_InvalidIndex; + } + + *TA = SD->getTemplateArgs()[I]; + return 0; + } else { + printf("CAST FAILED\n"); + return CXGetTemplateArgumentStatus_BadDeclCast; + } } enum CXTemplateArgumentKind clang_Cursor_getTemplateArgumentKind(CXCursor C,