blob: 3ade5195d8f8c95ba7c66c9c267fbbbfac96d4c6 [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;
21using namespace clang::cxstring;
Douglas Gregore0329ac2010-09-02 00:07:54 +000022using namespace clang::cxcursor;
Ted Kremenek585b3182010-08-27 21:57:20 +000023
24extern "C" {
25
26unsigned clang_isVirtualBase(CXCursor C) {
27 if (C.kind != CXCursor_CXXBaseSpecifier)
28 return 0;
29
Douglas Gregore0329ac2010-09-02 00:07:54 +000030 CXXBaseSpecifier *B = getCursorCXXBaseSpecifier(C);
Ted Kremenek585b3182010-08-27 21:57:20 +000031 return B->isVirtual();
32}
33
34enum CX_CXXAccessSpecifier clang_getCXXAccessSpecifier(CXCursor C) {
35 if (C.kind != CXCursor_CXXBaseSpecifier)
36 return CX_CXXInvalidAccessSpecifier;
37
Douglas Gregore0329ac2010-09-02 00:07:54 +000038 CXXBaseSpecifier *B = getCursorCXXBaseSpecifier(C);
Ted Kremenek585b3182010-08-27 21:57:20 +000039 switch (B->getAccessSpecifier()) {
40 case AS_public: return CX_CXXPublic;
41 case AS_protected: return CX_CXXProtected;
42 case AS_private: return CX_CXXPrivate;
43 case AS_none: return CX_CXXInvalidAccessSpecifier;
44 }
45
46 // FIXME: Clang currently thinks this is reachable.
47 return CX_CXXInvalidAccessSpecifier;
48}
49
Douglas Gregor49f6f542010-08-31 22:12:17 +000050enum CXCursorKind clang_getTemplateCursorKind(CXCursor C) {
51 using namespace clang::cxcursor;
52
53 switch (C.kind) {
54 case CXCursor_ClassTemplate:
55 case CXCursor_FunctionTemplate:
56 if (TemplateDecl *Template
57 = dyn_cast_or_null<TemplateDecl>(getCursorDecl(C)))
58 return MakeCXCursor(Template->getTemplatedDecl(),
59 getCursorASTUnit(C)).kind;
60 break;
61
62 case CXCursor_ClassTemplatePartialSpecialization:
63 if (ClassTemplateSpecializationDecl *PartialSpec
64 = dyn_cast_or_null<ClassTemplatePartialSpecializationDecl>(
65 getCursorDecl(C))) {
66 switch (PartialSpec->getTagKind()) {
67 case TTK_Class: return CXCursor_ClassDecl;
68 case TTK_Struct: return CXCursor_StructDecl;
69 case TTK_Union: return CXCursor_UnionDecl;
70 case TTK_Enum: return CXCursor_NoDeclFound;
71 }
72 }
73 break;
74
75 default:
76 break;
77 }
78
79 return CXCursor_NoDeclFound;
80}
81
Douglas Gregore0329ac2010-09-02 00:07:54 +000082CXCursor clang_getSpecializedCursorTemplate(CXCursor C) {
83 if (!clang_isDeclaration(C.kind))
84 return clang_getNullCursor();
85
86 Decl *D = getCursorDecl(C);
87 if (!D)
88 return clang_getNullCursor();
89
90 Decl *Template = 0;
91 if (CXXRecordDecl *CXXRecord = dyn_cast<CXXRecordDecl>(D)) {
92 if (ClassTemplatePartialSpecializationDecl *PartialSpec
93 = dyn_cast<ClassTemplatePartialSpecializationDecl>(CXXRecord))
94 Template = PartialSpec->getSpecializedTemplate();
95 else if (ClassTemplateSpecializationDecl *ClassSpec
96 = dyn_cast<ClassTemplateSpecializationDecl>(CXXRecord)) {
97 llvm::PointerUnion<ClassTemplateDecl *,
98 ClassTemplatePartialSpecializationDecl *> Result
99 = ClassSpec->getSpecializedTemplateOrPartial();
100 if (Result.is<ClassTemplateDecl *>())
101 Template = Result.get<ClassTemplateDecl *>();
102 else
103 Template = Result.get<ClassTemplatePartialSpecializationDecl *>();
104
105 } else
106 Template = CXXRecord->getInstantiatedFromMemberClass();
107 } else if (FunctionDecl *Function = dyn_cast<FunctionDecl>(D)) {
108 Template = Function->getPrimaryTemplate();
109 if (!Template)
110 Template = Function->getInstantiatedFromMemberFunction();
111 } else if (VarDecl *Var = dyn_cast<VarDecl>(D)) {
112 if (Var->isStaticDataMember())
113 Template = Var->getInstantiatedFromStaticDataMember();
114 } else if (RedeclarableTemplateDecl *Tmpl
115 = dyn_cast<RedeclarableTemplateDecl>(D))
116 Template = Tmpl->getInstantiatedFromMemberTemplate();
117
118 if (!Template)
119 return clang_getNullCursor();
120
121 return MakeCXCursor(Template, getCursorASTUnit(C));
122}
123
Ted Kremenek585b3182010-08-27 21:57:20 +0000124} // end extern "C"