1 //===- CIndexCXX.cpp - Clang-C Source Indexing Library --------------------===// 2 // 3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 4 // See https://llvm.org/LICENSE.txt for license information. 5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 6 // 7 //===----------------------------------------------------------------------===// 8 // 9 // This file implements the libclang support for C++ cursors. 10 // 11 //===----------------------------------------------------------------------===// 12 13 #include "CIndexer.h" 14 #include "CXCursor.h" 15 #include "CXType.h" 16 #include "clang/AST/DeclCXX.h" 17 #include "clang/AST/DeclTemplate.h" 18 19 using namespace clang; 20 using namespace clang::cxcursor; 21 clang_isVirtualBase(CXCursor C)22unsigned clang_isVirtualBase(CXCursor C) { 23 if (C.kind != CXCursor_CXXBaseSpecifier) 24 return 0; 25 26 const CXXBaseSpecifier *B = getCursorCXXBaseSpecifier(C); 27 return B->isVirtual(); 28 } 29 clang_getCXXAccessSpecifier(CXCursor C)30enum CX_CXXAccessSpecifier clang_getCXXAccessSpecifier(CXCursor C) { 31 AccessSpecifier spec = AS_none; 32 33 if (C.kind == CXCursor_CXXAccessSpecifier || clang_isDeclaration(C.kind)) 34 spec = getCursorDecl(C)->getAccess(); 35 else if (C.kind == CXCursor_CXXBaseSpecifier) 36 spec = getCursorCXXBaseSpecifier(C)->getAccessSpecifier(); 37 else 38 return CX_CXXInvalidAccessSpecifier; 39 40 switch (spec) { 41 case AS_public: return CX_CXXPublic; 42 case AS_protected: return CX_CXXProtected; 43 case AS_private: return CX_CXXPrivate; 44 case AS_none: return CX_CXXInvalidAccessSpecifier; 45 } 46 47 llvm_unreachable("Invalid AccessSpecifier!"); 48 } 49 clang_getTemplateCursorKind(CXCursor C)50enum CXCursorKind clang_getTemplateCursorKind(CXCursor C) { 51 using namespace clang::cxcursor; 52 53 switch (C.kind) { 54 case CXCursor_ClassTemplate: 55 case CXCursor_FunctionTemplate: 56 if (const TemplateDecl *Template 57 = dyn_cast_or_null<TemplateDecl>(getCursorDecl(C))) 58 return MakeCXCursor(Template->getTemplatedDecl(), getCursorTU(C)).kind; 59 break; 60 61 case CXCursor_ClassTemplatePartialSpecialization: 62 if (const ClassTemplateSpecializationDecl *PartialSpec 63 = dyn_cast_or_null<ClassTemplatePartialSpecializationDecl>( 64 getCursorDecl(C))) { 65 switch (PartialSpec->getTagKind()) { 66 case TTK_Interface: 67 case TTK_Struct: return CXCursor_StructDecl; 68 case TTK_Class: return CXCursor_ClassDecl; 69 case TTK_Union: return CXCursor_UnionDecl; 70 case TTK_Enum: return CXCursor_NoDeclFound; 71 } 72 } 73 break; 74 75 default: 76 break; 77 } 78 79 return CXCursor_NoDeclFound; 80 } 81 clang_getSpecializedCursorTemplate(CXCursor C)82CXCursor clang_getSpecializedCursorTemplate(CXCursor C) { 83 if (!clang_isDeclaration(C.kind)) 84 return clang_getNullCursor(); 85 86 const Decl *D = getCursorDecl(C); 87 if (!D) 88 return clang_getNullCursor(); 89 90 Decl *Template = nullptr; 91 if (const CXXRecordDecl *CXXRecord = dyn_cast<CXXRecordDecl>(D)) { 92 if (const ClassTemplatePartialSpecializationDecl *PartialSpec 93 = dyn_cast<ClassTemplatePartialSpecializationDecl>(CXXRecord)) 94 Template = PartialSpec->getSpecializedTemplate(); 95 else if (const ClassTemplateSpecializationDecl *ClassSpec 96 = dyn_cast<ClassTemplateSpecializationDecl>(CXXRecord)) { 97 llvm::PointerUnion<ClassTemplateDecl *, 98 ClassTemplatePartialSpecializationDecl *> Result 99 = ClassSpec->getSpecializedTemplateOrPartial(); 100 if (Result.is<ClassTemplateDecl *>()) 101 Template = Result.get<ClassTemplateDecl *>(); 102 else 103 Template = Result.get<ClassTemplatePartialSpecializationDecl *>(); 104 105 } else 106 Template = CXXRecord->getInstantiatedFromMemberClass(); 107 } else if (const FunctionDecl *Function = dyn_cast<FunctionDecl>(D)) { 108 Template = Function->getPrimaryTemplate(); 109 if (!Template) 110 Template = Function->getInstantiatedFromMemberFunction(); 111 } else if (const VarDecl *Var = dyn_cast<VarDecl>(D)) { 112 if (Var->isStaticDataMember()) 113 Template = Var->getInstantiatedFromStaticDataMember(); 114 } else if (const RedeclarableTemplateDecl *Tmpl 115 = dyn_cast<RedeclarableTemplateDecl>(D)) 116 Template = Tmpl->getInstantiatedFromMemberTemplate(); 117 118 if (!Template) 119 return clang_getNullCursor(); 120 121 return MakeCXCursor(Template, getCursorTU(C)); 122 } 123