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