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 if (C.kind != CXCursor_CXXBaseSpecifier) 35 return CX_CXXInvalidAccessSpecifier; 36 37 CXXBaseSpecifier *B = getCursorCXXBaseSpecifier(C); 38 switch (B->getAccessSpecifier()) { 39 case AS_public: return CX_CXXPublic; 40 case AS_protected: return CX_CXXProtected; 41 case AS_private: return CX_CXXPrivate; 42 case AS_none: return CX_CXXInvalidAccessSpecifier; 43 } 44 45 // FIXME: Clang currently thinks this is reachable. 46 return CX_CXXInvalidAccessSpecifier; 47 } 48 49 enum CXCursorKind clang_getTemplateCursorKind(CXCursor C) { 50 using namespace clang::cxcursor; 51 52 switch (C.kind) { 53 case CXCursor_ClassTemplate: 54 case CXCursor_FunctionTemplate: 55 if (TemplateDecl *Template 56 = dyn_cast_or_null<TemplateDecl>(getCursorDecl(C))) 57 return MakeCXCursor(Template->getTemplatedDecl(), 58 static_cast<CXTranslationUnit>(C.data[2])).kind; 59 break; 60 61 case CXCursor_ClassTemplatePartialSpecialization: 62 if (ClassTemplateSpecializationDecl *PartialSpec 63 = dyn_cast_or_null<ClassTemplatePartialSpecializationDecl>( 64 getCursorDecl(C))) { 65 switch (PartialSpec->getTagKind()) { 66 case TTK_Class: return CXCursor_ClassDecl; 67 case TTK_Struct: return CXCursor_StructDecl; 68 case TTK_Union: return CXCursor_UnionDecl; 69 case TTK_Enum: return CXCursor_NoDeclFound; 70 } 71 } 72 break; 73 74 default: 75 break; 76 } 77 78 return CXCursor_NoDeclFound; 79 } 80 81 CXCursor clang_getSpecializedCursorTemplate(CXCursor C) { 82 if (!clang_isDeclaration(C.kind)) 83 return clang_getNullCursor(); 84 85 Decl *D = getCursorDecl(C); 86 if (!D) 87 return clang_getNullCursor(); 88 89 Decl *Template = 0; 90 if (CXXRecordDecl *CXXRecord = dyn_cast<CXXRecordDecl>(D)) { 91 if (ClassTemplatePartialSpecializationDecl *PartialSpec 92 = dyn_cast<ClassTemplatePartialSpecializationDecl>(CXXRecord)) 93 Template = PartialSpec->getSpecializedTemplate(); 94 else if (ClassTemplateSpecializationDecl *ClassSpec 95 = dyn_cast<ClassTemplateSpecializationDecl>(CXXRecord)) { 96 llvm::PointerUnion<ClassTemplateDecl *, 97 ClassTemplatePartialSpecializationDecl *> Result 98 = ClassSpec->getSpecializedTemplateOrPartial(); 99 if (Result.is<ClassTemplateDecl *>()) 100 Template = Result.get<ClassTemplateDecl *>(); 101 else 102 Template = Result.get<ClassTemplatePartialSpecializationDecl *>(); 103 104 } else 105 Template = CXXRecord->getInstantiatedFromMemberClass(); 106 } else if (FunctionDecl *Function = dyn_cast<FunctionDecl>(D)) { 107 Template = Function->getPrimaryTemplate(); 108 if (!Template) 109 Template = Function->getInstantiatedFromMemberFunction(); 110 } else if (VarDecl *Var = dyn_cast<VarDecl>(D)) { 111 if (Var->isStaticDataMember()) 112 Template = Var->getInstantiatedFromStaticDataMember(); 113 } else if (RedeclarableTemplateDecl *Tmpl 114 = dyn_cast<RedeclarableTemplateDecl>(D)) 115 Template = Tmpl->getInstantiatedFromMemberTemplate(); 116 117 if (!Template) 118 return clang_getNullCursor(); 119 120 return MakeCXCursor(Template, static_cast<CXTranslationUnit>(C.data[2])); 121 } 122 123 } // end extern "C" 124