128 lines
4.2 KiB
C++
128 lines
4.2 KiB
C++
|
//===- 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 = 0;
|
||
|
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"
|