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 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) 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 // FIXME: Clang currently thinks this is reachable. 51 return CX_CXXInvalidAccessSpecifier; 52 } 53 54 enum CXCursorKind clang_getTemplateCursorKind(CXCursor C) { 55 using namespace clang::cxcursor; 56 57 switch (C.kind) { 58 case CXCursor_ClassTemplate: 59 case CXCursor_FunctionTemplate: 60 if (TemplateDecl *Template 61 = dyn_cast_or_null<TemplateDecl>(getCursorDecl(C))) 62 return MakeCXCursor(Template->getTemplatedDecl(), 63 static_cast<CXTranslationUnit>(C.data[2])).kind; 64 break; 65 66 case CXCursor_ClassTemplatePartialSpecialization: 67 if (ClassTemplateSpecializationDecl *PartialSpec 68 = dyn_cast_or_null<ClassTemplatePartialSpecializationDecl>( 69 getCursorDecl(C))) { 70 switch (PartialSpec->getTagKind()) { 71 case TTK_Class: return CXCursor_ClassDecl; 72 case TTK_Struct: return CXCursor_StructDecl; 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 86 CXCursor 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