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::cxcursor; 22 23extern "C" { 24 25unsigned 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 33enum 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 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 (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 85CXCursor 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 = 0; 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