CIndexCXX.cpp revision e0329acf5c9437e2086a2fb2bf7a95ae2ac96505
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 20using namespace clang; 21using namespace clang::cxstring; 22using namespace clang::cxcursor; 23 24extern "C" { 25 26unsigned clang_isVirtualBase(CXCursor C) { 27 if (C.kind != CXCursor_CXXBaseSpecifier) 28 return 0; 29 30 CXXBaseSpecifier *B = getCursorCXXBaseSpecifier(C); 31 return B->isVirtual(); 32} 33 34enum CX_CXXAccessSpecifier clang_getCXXAccessSpecifier(CXCursor C) { 35 if (C.kind != CXCursor_CXXBaseSpecifier) 36 return CX_CXXInvalidAccessSpecifier; 37 38 CXXBaseSpecifier *B = getCursorCXXBaseSpecifier(C); 39 switch (B->getAccessSpecifier()) { 40 case AS_public: return CX_CXXPublic; 41 case AS_protected: return CX_CXXProtected; 42 case AS_private: return CX_CXXPrivate; 43 case AS_none: return CX_CXXInvalidAccessSpecifier; 44 } 45 46 // FIXME: Clang currently thinks this is reachable. 47 return CX_CXXInvalidAccessSpecifier; 48} 49 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 (TemplateDecl *Template 57 = dyn_cast_or_null<TemplateDecl>(getCursorDecl(C))) 58 return MakeCXCursor(Template->getTemplatedDecl(), 59 getCursorASTUnit(C)).kind; 60 break; 61 62 case CXCursor_ClassTemplatePartialSpecialization: 63 if (ClassTemplateSpecializationDecl *PartialSpec 64 = dyn_cast_or_null<ClassTemplatePartialSpecializationDecl>( 65 getCursorDecl(C))) { 66 switch (PartialSpec->getTagKind()) { 67 case TTK_Class: return CXCursor_ClassDecl; 68 case TTK_Struct: return CXCursor_StructDecl; 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 82CXCursor clang_getSpecializedCursorTemplate(CXCursor C) { 83 if (!clang_isDeclaration(C.kind)) 84 return clang_getNullCursor(); 85 86 Decl *D = getCursorDecl(C); 87 if (!D) 88 return clang_getNullCursor(); 89 90 Decl *Template = 0; 91 if (CXXRecordDecl *CXXRecord = dyn_cast<CXXRecordDecl>(D)) { 92 if (ClassTemplatePartialSpecializationDecl *PartialSpec 93 = dyn_cast<ClassTemplatePartialSpecializationDecl>(CXXRecord)) 94 Template = PartialSpec->getSpecializedTemplate(); 95 else if (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 (FunctionDecl *Function = dyn_cast<FunctionDecl>(D)) { 108 Template = Function->getPrimaryTemplate(); 109 if (!Template) 110 Template = Function->getInstantiatedFromMemberFunction(); 111 } else if (VarDecl *Var = dyn_cast<VarDecl>(D)) { 112 if (Var->isStaticDataMember()) 113 Template = Var->getInstantiatedFromStaticDataMember(); 114 } else if (RedeclarableTemplateDecl *Tmpl 115 = dyn_cast<RedeclarableTemplateDecl>(D)) 116 Template = Tmpl->getInstantiatedFromMemberTemplate(); 117 118 if (!Template) 119 return clang_getNullCursor(); 120 121 return MakeCXCursor(Template, getCursorASTUnit(C)); 122} 123 124} // end extern "C" 125