//===- CIndexCXX.cpp - Clang-C Source Indexing Library --------------------===// // // The LLVM Compiler Infrastructure // // This file is distributed under the University of Illinois Open Source // License. See LICENSE.TXT for details. // //===----------------------------------------------------------------------===// // // This file implements the libclang support for C++ cursors. // //===----------------------------------------------------------------------===// #include "CIndexer.h" #include "CXCursor.h" #include "CXType.h" #include "clang/AST/DeclCXX.h" #include "clang/AST/DeclTemplate.h" using namespace clang; using namespace clang::cxcursor; extern "C" { unsigned clang_isVirtualBase(CXCursor C) { if (C.kind != CXCursor_CXXBaseSpecifier) return 0; const CXXBaseSpecifier *B = getCursorCXXBaseSpecifier(C); return B->isVirtual(); } enum CX_CXXAccessSpecifier clang_getCXXAccessSpecifier(CXCursor C) { AccessSpecifier spec = AS_none; if (C.kind == CXCursor_CXXAccessSpecifier || clang_isDeclaration(C.kind)) spec = getCursorDecl(C)->getAccess(); else if (C.kind == CXCursor_CXXBaseSpecifier) spec = getCursorCXXBaseSpecifier(C)->getAccessSpecifier(); else return CX_CXXInvalidAccessSpecifier; switch (spec) { case AS_public: return CX_CXXPublic; case AS_protected: return CX_CXXProtected; case AS_private: return CX_CXXPrivate; case AS_none: return CX_CXXInvalidAccessSpecifier; } llvm_unreachable("Invalid AccessSpecifier!"); } enum CXCursorKind clang_getTemplateCursorKind(CXCursor C) { using namespace clang::cxcursor; switch (C.kind) { case CXCursor_ClassTemplate: case CXCursor_FunctionTemplate: if (const TemplateDecl *Template = dyn_cast_or_null<TemplateDecl>(getCursorDecl(C))) return MakeCXCursor(Template->getTemplatedDecl(), getCursorTU(C)).kind; break; case CXCursor_ClassTemplatePartialSpecialization: if (const ClassTemplateSpecializationDecl *PartialSpec = dyn_cast_or_null<ClassTemplatePartialSpecializationDecl>( getCursorDecl(C))) { switch (PartialSpec->getTagKind()) { case TTK_Interface: case TTK_Struct: return CXCursor_StructDecl; case TTK_Class: return CXCursor_ClassDecl; case TTK_Union: return CXCursor_UnionDecl; case TTK_Enum: return CXCursor_NoDeclFound; } } break; default: break; } return CXCursor_NoDeclFound; } CXCursor clang_getSpecializedCursorTemplate(CXCursor C) { if (!clang_isDeclaration(C.kind)) return clang_getNullCursor(); const Decl *D = getCursorDecl(C); if (!D) return clang_getNullCursor(); Decl *Template = nullptr; if (const CXXRecordDecl *CXXRecord = dyn_cast<CXXRecordDecl>(D)) { if (const ClassTemplatePartialSpecializationDecl *PartialSpec = dyn_cast<ClassTemplatePartialSpecializationDecl>(CXXRecord)) Template = PartialSpec->getSpecializedTemplate(); else if (const ClassTemplateSpecializationDecl *ClassSpec = dyn_cast<ClassTemplateSpecializationDecl>(CXXRecord)) { llvm::PointerUnion<ClassTemplateDecl *, ClassTemplatePartialSpecializationDecl *> Result = ClassSpec->getSpecializedTemplateOrPartial(); if (Result.is<ClassTemplateDecl *>()) Template = Result.get<ClassTemplateDecl *>(); else Template = Result.get<ClassTemplatePartialSpecializationDecl *>(); } else Template = CXXRecord->getInstantiatedFromMemberClass(); } else if (const FunctionDecl *Function = dyn_cast<FunctionDecl>(D)) { Template = Function->getPrimaryTemplate(); if (!Template) Template = Function->getInstantiatedFromMemberFunction(); } else if (const VarDecl *Var = dyn_cast<VarDecl>(D)) { if (Var->isStaticDataMember()) Template = Var->getInstantiatedFromStaticDataMember(); } else if (const RedeclarableTemplateDecl *Tmpl = dyn_cast<RedeclarableTemplateDecl>(D)) Template = Tmpl->getInstantiatedFromMemberTemplate(); if (!Template) return clang_getNullCursor(); return MakeCXCursor(Template, getCursorTU(C)); } } // end extern "C"