blob: 240b0f6c1fe1f1efe061641dd8b78d04ec582749 [file] [log] [blame]
Ted Kremenek585b3182010-08-27 21:57:20 +00001//===- 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"
Douglas Gregor49f6f542010-08-31 22:12:17 +000018#include "clang/AST/DeclTemplate.h"
Ted Kremenek585b3182010-08-27 21:57:20 +000019
20using namespace clang;
Douglas Gregore0329ac2010-09-02 00:07:54 +000021using namespace clang::cxcursor;
Ted Kremenek585b3182010-08-27 21:57:20 +000022
23extern "C" {
24
25unsigned clang_isVirtualBase(CXCursor C) {
26 if (C.kind != CXCursor_CXXBaseSpecifier)
27 return 0;
28
Douglas Gregore0329ac2010-09-02 00:07:54 +000029 CXXBaseSpecifier *B = getCursorCXXBaseSpecifier(C);
Ted Kremenek585b3182010-08-27 21:57:20 +000030 return B->isVirtual();
31}
32
33enum CX_CXXAccessSpecifier clang_getCXXAccessSpecifier(CXCursor C) {
Argyrios Kyrtzidis2dfdb942011-09-30 17:58:23 +000034 AccessSpecifier spec = AS_none;
35
36 if (C.kind == CXCursor_CXXAccessSpecifier)
37 spec = getCursorDecl(C)->getAccess();
38 else if (C.kind == CXCursor_CXXBaseSpecifier)
39 spec = getCursorCXXBaseSpecifier(C)->getAccessSpecifier();
40 else
Ted Kremenek585b3182010-08-27 21:57:20 +000041 return CX_CXXInvalidAccessSpecifier;
42
Argyrios Kyrtzidis2dfdb942011-09-30 17:58:23 +000043 switch (spec) {
Ted Kremenek585b3182010-08-27 21:57:20 +000044 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 }
David Blaikie7530c032012-01-17 06:56:22 +000049
50 llvm_unreachable("Invalid AccessSpecifier!");
Ted Kremenek585b3182010-08-27 21:57:20 +000051}
52
Douglas Gregor49f6f542010-08-31 22:12:17 +000053enum 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 (TemplateDecl *Template
60 = dyn_cast_or_null<TemplateDecl>(getCursorDecl(C)))
61 return MakeCXCursor(Template->getTemplatedDecl(),
Ted Kremeneka60ed472010-11-16 08:15:36 +000062 static_cast<CXTranslationUnit>(C.data[2])).kind;
Douglas Gregor49f6f542010-08-31 22:12:17 +000063 break;
64
65 case CXCursor_ClassTemplatePartialSpecialization:
66 if (ClassTemplateSpecializationDecl *PartialSpec
67 = dyn_cast_or_null<ClassTemplatePartialSpecializationDecl>(
68 getCursorDecl(C))) {
69 switch (PartialSpec->getTagKind()) {
70 case TTK_Class: return CXCursor_ClassDecl;
71 case TTK_Struct: return CXCursor_StructDecl;
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
Douglas Gregore0329ac2010-09-02 00:07:54 +000085CXCursor clang_getSpecializedCursorTemplate(CXCursor C) {
86 if (!clang_isDeclaration(C.kind))
87 return clang_getNullCursor();
88
89 Decl *D = getCursorDecl(C);
90 if (!D)
91 return clang_getNullCursor();
92
93 Decl *Template = 0;
94 if (CXXRecordDecl *CXXRecord = dyn_cast<CXXRecordDecl>(D)) {
95 if (ClassTemplatePartialSpecializationDecl *PartialSpec
96 = dyn_cast<ClassTemplatePartialSpecializationDecl>(CXXRecord))
97 Template = PartialSpec->getSpecializedTemplate();
98 else if (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 (FunctionDecl *Function = dyn_cast<FunctionDecl>(D)) {
111 Template = Function->getPrimaryTemplate();
112 if (!Template)
113 Template = Function->getInstantiatedFromMemberFunction();
114 } else if (VarDecl *Var = dyn_cast<VarDecl>(D)) {
115 if (Var->isStaticDataMember())
116 Template = Var->getInstantiatedFromStaticDataMember();
117 } else if (RedeclarableTemplateDecl *Tmpl
118 = dyn_cast<RedeclarableTemplateDecl>(D))
119 Template = Tmpl->getInstantiatedFromMemberTemplate();
120
121 if (!Template)
122 return clang_getNullCursor();
123
Ted Kremeneka60ed472010-11-16 08:15:36 +0000124 return MakeCXCursor(Template, static_cast<CXTranslationUnit>(C.data[2]));
Douglas Gregore0329ac2010-09-02 00:07:54 +0000125}
126
Ted Kremenek585b3182010-08-27 21:57:20 +0000127} // end extern "C"