1*e5dd7070Spatrick //===- CIndexCXX.cpp - Clang-C Source Indexing Library --------------------===// 2*e5dd7070Spatrick // 3*e5dd7070Spatrick // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 4*e5dd7070Spatrick // See https://llvm.org/LICENSE.txt for license information. 5*e5dd7070Spatrick // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 6*e5dd7070Spatrick // 7*e5dd7070Spatrick //===----------------------------------------------------------------------===// 8*e5dd7070Spatrick // 9*e5dd7070Spatrick // This file implements the libclang support for C++ cursors. 10*e5dd7070Spatrick // 11*e5dd7070Spatrick //===----------------------------------------------------------------------===// 12*e5dd7070Spatrick 13*e5dd7070Spatrick #include "CIndexer.h" 14*e5dd7070Spatrick #include "CXCursor.h" 15*e5dd7070Spatrick #include "CXType.h" 16*e5dd7070Spatrick #include "clang/AST/DeclCXX.h" 17*e5dd7070Spatrick #include "clang/AST/DeclTemplate.h" 18*e5dd7070Spatrick 19*e5dd7070Spatrick using namespace clang; 20*e5dd7070Spatrick using namespace clang::cxcursor; 21*e5dd7070Spatrick clang_isVirtualBase(CXCursor C)22*e5dd7070Spatrickunsigned clang_isVirtualBase(CXCursor C) { 23*e5dd7070Spatrick if (C.kind != CXCursor_CXXBaseSpecifier) 24*e5dd7070Spatrick return 0; 25*e5dd7070Spatrick 26*e5dd7070Spatrick const CXXBaseSpecifier *B = getCursorCXXBaseSpecifier(C); 27*e5dd7070Spatrick return B->isVirtual(); 28*e5dd7070Spatrick } 29*e5dd7070Spatrick clang_getCXXAccessSpecifier(CXCursor C)30*e5dd7070Spatrickenum CX_CXXAccessSpecifier clang_getCXXAccessSpecifier(CXCursor C) { 31*e5dd7070Spatrick AccessSpecifier spec = AS_none; 32*e5dd7070Spatrick 33*e5dd7070Spatrick if (C.kind == CXCursor_CXXAccessSpecifier || clang_isDeclaration(C.kind)) 34*e5dd7070Spatrick spec = getCursorDecl(C)->getAccess(); 35*e5dd7070Spatrick else if (C.kind == CXCursor_CXXBaseSpecifier) 36*e5dd7070Spatrick spec = getCursorCXXBaseSpecifier(C)->getAccessSpecifier(); 37*e5dd7070Spatrick else 38*e5dd7070Spatrick return CX_CXXInvalidAccessSpecifier; 39*e5dd7070Spatrick 40*e5dd7070Spatrick switch (spec) { 41*e5dd7070Spatrick case AS_public: return CX_CXXPublic; 42*e5dd7070Spatrick case AS_protected: return CX_CXXProtected; 43*e5dd7070Spatrick case AS_private: return CX_CXXPrivate; 44*e5dd7070Spatrick case AS_none: return CX_CXXInvalidAccessSpecifier; 45*e5dd7070Spatrick } 46*e5dd7070Spatrick 47*e5dd7070Spatrick llvm_unreachable("Invalid AccessSpecifier!"); 48*e5dd7070Spatrick } 49*e5dd7070Spatrick clang_getTemplateCursorKind(CXCursor C)50*e5dd7070Spatrickenum CXCursorKind clang_getTemplateCursorKind(CXCursor C) { 51*e5dd7070Spatrick using namespace clang::cxcursor; 52*e5dd7070Spatrick 53*e5dd7070Spatrick switch (C.kind) { 54*e5dd7070Spatrick case CXCursor_ClassTemplate: 55*e5dd7070Spatrick case CXCursor_FunctionTemplate: 56*e5dd7070Spatrick if (const TemplateDecl *Template 57*e5dd7070Spatrick = dyn_cast_or_null<TemplateDecl>(getCursorDecl(C))) 58*e5dd7070Spatrick return MakeCXCursor(Template->getTemplatedDecl(), getCursorTU(C)).kind; 59*e5dd7070Spatrick break; 60*e5dd7070Spatrick 61*e5dd7070Spatrick case CXCursor_ClassTemplatePartialSpecialization: 62*e5dd7070Spatrick if (const ClassTemplateSpecializationDecl *PartialSpec 63*e5dd7070Spatrick = dyn_cast_or_null<ClassTemplatePartialSpecializationDecl>( 64*e5dd7070Spatrick getCursorDecl(C))) { 65*e5dd7070Spatrick switch (PartialSpec->getTagKind()) { 66*e5dd7070Spatrick case TTK_Interface: 67*e5dd7070Spatrick case TTK_Struct: return CXCursor_StructDecl; 68*e5dd7070Spatrick case TTK_Class: return CXCursor_ClassDecl; 69*e5dd7070Spatrick case TTK_Union: return CXCursor_UnionDecl; 70*e5dd7070Spatrick case TTK_Enum: return CXCursor_NoDeclFound; 71*e5dd7070Spatrick } 72*e5dd7070Spatrick } 73*e5dd7070Spatrick break; 74*e5dd7070Spatrick 75*e5dd7070Spatrick default: 76*e5dd7070Spatrick break; 77*e5dd7070Spatrick } 78*e5dd7070Spatrick 79*e5dd7070Spatrick return CXCursor_NoDeclFound; 80*e5dd7070Spatrick } 81*e5dd7070Spatrick clang_getSpecializedCursorTemplate(CXCursor C)82*e5dd7070SpatrickCXCursor clang_getSpecializedCursorTemplate(CXCursor C) { 83*e5dd7070Spatrick if (!clang_isDeclaration(C.kind)) 84*e5dd7070Spatrick return clang_getNullCursor(); 85*e5dd7070Spatrick 86*e5dd7070Spatrick const Decl *D = getCursorDecl(C); 87*e5dd7070Spatrick if (!D) 88*e5dd7070Spatrick return clang_getNullCursor(); 89*e5dd7070Spatrick 90*e5dd7070Spatrick Decl *Template = nullptr; 91*e5dd7070Spatrick if (const CXXRecordDecl *CXXRecord = dyn_cast<CXXRecordDecl>(D)) { 92*e5dd7070Spatrick if (const ClassTemplatePartialSpecializationDecl *PartialSpec 93*e5dd7070Spatrick = dyn_cast<ClassTemplatePartialSpecializationDecl>(CXXRecord)) 94*e5dd7070Spatrick Template = PartialSpec->getSpecializedTemplate(); 95*e5dd7070Spatrick else if (const ClassTemplateSpecializationDecl *ClassSpec 96*e5dd7070Spatrick = dyn_cast<ClassTemplateSpecializationDecl>(CXXRecord)) { 97*e5dd7070Spatrick llvm::PointerUnion<ClassTemplateDecl *, 98*e5dd7070Spatrick ClassTemplatePartialSpecializationDecl *> Result 99*e5dd7070Spatrick = ClassSpec->getSpecializedTemplateOrPartial(); 100*e5dd7070Spatrick if (Result.is<ClassTemplateDecl *>()) 101*e5dd7070Spatrick Template = Result.get<ClassTemplateDecl *>(); 102*e5dd7070Spatrick else 103*e5dd7070Spatrick Template = Result.get<ClassTemplatePartialSpecializationDecl *>(); 104*e5dd7070Spatrick 105*e5dd7070Spatrick } else 106*e5dd7070Spatrick Template = CXXRecord->getInstantiatedFromMemberClass(); 107*e5dd7070Spatrick } else if (const FunctionDecl *Function = dyn_cast<FunctionDecl>(D)) { 108*e5dd7070Spatrick Template = Function->getPrimaryTemplate(); 109*e5dd7070Spatrick if (!Template) 110*e5dd7070Spatrick Template = Function->getInstantiatedFromMemberFunction(); 111*e5dd7070Spatrick } else if (const VarDecl *Var = dyn_cast<VarDecl>(D)) { 112*e5dd7070Spatrick if (Var->isStaticDataMember()) 113*e5dd7070Spatrick Template = Var->getInstantiatedFromStaticDataMember(); 114*e5dd7070Spatrick } else if (const RedeclarableTemplateDecl *Tmpl 115*e5dd7070Spatrick = dyn_cast<RedeclarableTemplateDecl>(D)) 116*e5dd7070Spatrick Template = Tmpl->getInstantiatedFromMemberTemplate(); 117*e5dd7070Spatrick 118*e5dd7070Spatrick if (!Template) 119*e5dd7070Spatrick return clang_getNullCursor(); 120*e5dd7070Spatrick 121*e5dd7070Spatrick return MakeCXCursor(Template, getCursorTU(C)); 122*e5dd7070Spatrick } 123