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 clang_isVirtualBase(CXCursor C)25unsigned clang_isVirtualBase(CXCursor C) { 26 if (C.kind != CXCursor_CXXBaseSpecifier) 27 return 0; 28 29 CXXBaseSpecifier *B = getCursorCXXBaseSpecifier(C); 30 return B->isVirtual(); 31 } 32 clang_getCXXAccessSpecifier(CXCursor C)33enum CX_CXXAccessSpecifier clang_getCXXAccessSpecifier(CXCursor C) { 34 AccessSpecifier spec = AS_none; 35 36 if (C.kind == CXCursor_CXXAccessSpecifier) 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 clang_getTemplateCursorKind(CXCursor C)53enum 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 (TemplateDecl *Template 60 = dyn_cast_or_null<TemplateDecl>(getCursorDecl(C))) 61 return MakeCXCursor(Template->getTemplatedDecl(), 62 static_cast<CXTranslationUnit>(C.data[2])).kind; 63 break; 64 65 case CXCursor_ClassTemplatePartialSpecialization: 66 if (ClassTemplateSpecializationDecl *PartialSpec 67 = dyn_cast_or_null<ClassTemplatePartialSpecializationDecl>( 68 getCursorDecl(C))) { 69 switch (PartialSpec->getTagKind()) { 70 case TTK_Interface: 71 case TTK_Struct: return CXCursor_StructDecl; 72 case TTK_Class: return CXCursor_ClassDecl; 73 case TTK_Union: return CXCursor_UnionDecl; 74 case TTK_Enum: return CXCursor_NoDeclFound; 75 } 76 } 77 break; 78 79 default: 80 break; 81 } 82 83 return CXCursor_NoDeclFound; 84 } 85 clang_getSpecializedCursorTemplate(CXCursor C)86CXCursor clang_getSpecializedCursorTemplate(CXCursor C) { 87 if (!clang_isDeclaration(C.kind)) 88 return clang_getNullCursor(); 89 90 Decl *D = getCursorDecl(C); 91 if (!D) 92 return clang_getNullCursor(); 93 94 Decl *Template = 0; 95 if (CXXRecordDecl *CXXRecord = dyn_cast<CXXRecordDecl>(D)) { 96 if (ClassTemplatePartialSpecializationDecl *PartialSpec 97 = dyn_cast<ClassTemplatePartialSpecializationDecl>(CXXRecord)) 98 Template = PartialSpec->getSpecializedTemplate(); 99 else if (ClassTemplateSpecializationDecl *ClassSpec 100 = dyn_cast<ClassTemplateSpecializationDecl>(CXXRecord)) { 101 llvm::PointerUnion<ClassTemplateDecl *, 102 ClassTemplatePartialSpecializationDecl *> Result 103 = ClassSpec->getSpecializedTemplateOrPartial(); 104 if (Result.is<ClassTemplateDecl *>()) 105 Template = Result.get<ClassTemplateDecl *>(); 106 else 107 Template = Result.get<ClassTemplatePartialSpecializationDecl *>(); 108 109 } else 110 Template = CXXRecord->getInstantiatedFromMemberClass(); 111 } else if (FunctionDecl *Function = dyn_cast<FunctionDecl>(D)) { 112 Template = Function->getPrimaryTemplate(); 113 if (!Template) 114 Template = Function->getInstantiatedFromMemberFunction(); 115 } else if (VarDecl *Var = dyn_cast<VarDecl>(D)) { 116 if (Var->isStaticDataMember()) 117 Template = Var->getInstantiatedFromStaticDataMember(); 118 } else if (RedeclarableTemplateDecl *Tmpl 119 = dyn_cast<RedeclarableTemplateDecl>(D)) 120 Template = Tmpl->getInstantiatedFromMemberTemplate(); 121 122 if (!Template) 123 return clang_getNullCursor(); 124 125 return MakeCXCursor(Template, static_cast<CXTranslationUnit>(C.data[2])); 126 } 127 128 } // end extern "C" 129