//===- 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"