blob: fb0ccb146f7dcee0a4b7b6bcd9c0d0fa25b72ca7 [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 }
49
50 // FIXME: Clang currently thinks this is reachable.
51 return CX_CXXInvalidAccessSpecifier;
52}
53
Douglas Gregor49f6f542010-08-31 22:12:17 +000054enum CXCursorKind clang_getTemplateCursorKind(CXCursor C) {
55 using namespace clang::cxcursor;
56
57 switch (C.kind) {
58 case CXCursor_ClassTemplate:
59 case CXCursor_FunctionTemplate:
60 if (TemplateDecl *Template
61 = dyn_cast_or_null<TemplateDecl>(getCursorDecl(C)))
62 return MakeCXCursor(Template->getTemplatedDecl(),
Ted Kremeneka60ed472010-11-16 08:15:36 +000063 static_cast<CXTranslationUnit>(C.data[2])).kind;
Douglas Gregor49f6f542010-08-31 22:12:17 +000064 break;
65
66 case CXCursor_ClassTemplatePartialSpecialization:
67 if (ClassTemplateSpecializationDecl *PartialSpec
68 = dyn_cast_or_null<ClassTemplatePartialSpecializationDecl>(
69 getCursorDecl(C))) {
70 switch (PartialSpec->getTagKind()) {
71 case TTK_Class: return CXCursor_ClassDecl;
72 case TTK_Struct: return CXCursor_StructDecl;
73 case TTK_Union: return CXCursor_UnionDecl;
74 case TTK_Enum: return CXCursor_NoDeclFound;
75 }
76 }
77 break;
78
79 default:
80 break;
81 }
82
83 return CXCursor_NoDeclFound;
84}
85
Douglas Gregore0329ac2010-09-02 00:07:54 +000086CXCursor clang_getSpecializedCursorTemplate(CXCursor C) {
87 if (!clang_isDeclaration(C.kind))
88 return clang_getNullCursor();
89
90 Decl *D = getCursorDecl(C);
91 if (!D)
92 return clang_getNullCursor();
93
94 Decl *Template = 0;
95 if (CXXRecordDecl *CXXRecord = dyn_cast<CXXRecordDecl>(D)) {
96 if (ClassTemplatePartialSpecializationDecl *PartialSpec
97 = dyn_cast<ClassTemplatePartialSpecializationDecl>(CXXRecord))
98 Template = PartialSpec->getSpecializedTemplate();
99 else if (ClassTemplateSpecializationDecl *ClassSpec
100 = dyn_cast<ClassTemplateSpecializationDecl>(CXXRecord)) {
101 llvm::PointerUnion<ClassTemplateDecl *,
102 ClassTemplatePartialSpecializationDecl *> Result
103 = ClassSpec->getSpecializedTemplateOrPartial();
104 if (Result.is<ClassTemplateDecl *>())
105 Template = Result.get<ClassTemplateDecl *>();
106 else
107 Template = Result.get<ClassTemplatePartialSpecializationDecl *>();
108
109 } else
110 Template = CXXRecord->getInstantiatedFromMemberClass();
111 } else if (FunctionDecl *Function = dyn_cast<FunctionDecl>(D)) {
112 Template = Function->getPrimaryTemplate();
113 if (!Template)
114 Template = Function->getInstantiatedFromMemberFunction();
115 } else if (VarDecl *Var = dyn_cast<VarDecl>(D)) {
116 if (Var->isStaticDataMember())
117 Template = Var->getInstantiatedFromStaticDataMember();
118 } else if (RedeclarableTemplateDecl *Tmpl
119 = dyn_cast<RedeclarableTemplateDecl>(D))
120 Template = Tmpl->getInstantiatedFromMemberTemplate();
121
122 if (!Template)
123 return clang_getNullCursor();
124
Ted Kremeneka60ed472010-11-16 08:15:36 +0000125 return MakeCXCursor(Template, static_cast<CXTranslationUnit>(C.data[2]));
Douglas Gregore0329ac2010-09-02 00:07:54 +0000126}
127
Ted Kremenek585b3182010-08-27 21:57:20 +0000128} // end extern "C"