blob: c68dde7c2c22da5807de91288fff97e9c387fcd8 [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
Dmitri Gribenko67812b22013-01-11 21:01:49 +000029 const 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:
Dmitri Gribenkoe22339c2013-01-23 17:25:27 +000059 if (const TemplateDecl *Template
Douglas Gregor49f6f542010-08-31 22:12:17 +000060 = dyn_cast_or_null<TemplateDecl>(getCursorDecl(C)))
Dmitri Gribenko46f92522013-01-11 19:28:44 +000061 return MakeCXCursor(Template->getTemplatedDecl(), getCursorTU(C)).kind;
Douglas Gregor49f6f542010-08-31 22:12:17 +000062 break;
63
64 case CXCursor_ClassTemplatePartialSpecialization:
Dmitri Gribenkoe22339c2013-01-23 17:25:27 +000065 if (const ClassTemplateSpecializationDecl *PartialSpec
Joao Matos17d35c32012-08-31 22:18:20 +000066 = dyn_cast_or_null<ClassTemplatePartialSpecializationDecl>(
67 getCursorDecl(C))) {
68 switch (PartialSpec->getTagKind()) {
69 case TTK_Interface:
70 case TTK_Struct: return CXCursor_StructDecl;
71 case TTK_Class: return CXCursor_ClassDecl;
72 case TTK_Union: return CXCursor_UnionDecl;
73 case TTK_Enum: return CXCursor_NoDeclFound;
74 }
Douglas Gregor49f6f542010-08-31 22:12:17 +000075 }
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
Dmitri Gribenkoe22339c2013-01-23 17:25:27 +000089 const Decl *D = getCursorDecl(C);
Douglas Gregore0329ac2010-09-02 00:07:54 +000090 if (!D)
91 return clang_getNullCursor();
92
93 Decl *Template = 0;
Dmitri Gribenkoe22339c2013-01-23 17:25:27 +000094 if (const CXXRecordDecl *CXXRecord = dyn_cast<CXXRecordDecl>(D)) {
95 if (const ClassTemplatePartialSpecializationDecl *PartialSpec
Douglas Gregore0329ac2010-09-02 00:07:54 +000096 = dyn_cast<ClassTemplatePartialSpecializationDecl>(CXXRecord))
97 Template = PartialSpec->getSpecializedTemplate();
Dmitri Gribenkoe22339c2013-01-23 17:25:27 +000098 else if (const ClassTemplateSpecializationDecl *ClassSpec
Douglas Gregore0329ac2010-09-02 00:07:54 +000099 = 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();
Dmitri Gribenkoe22339c2013-01-23 17:25:27 +0000110 } else if (const FunctionDecl *Function = dyn_cast<FunctionDecl>(D)) {
Douglas Gregore0329ac2010-09-02 00:07:54 +0000111 Template = Function->getPrimaryTemplate();
112 if (!Template)
113 Template = Function->getInstantiatedFromMemberFunction();
Dmitri Gribenkoe22339c2013-01-23 17:25:27 +0000114 } else if (const VarDecl *Var = dyn_cast<VarDecl>(D)) {
Douglas Gregore0329ac2010-09-02 00:07:54 +0000115 if (Var->isStaticDataMember())
116 Template = Var->getInstantiatedFromStaticDataMember();
Dmitri Gribenkoe22339c2013-01-23 17:25:27 +0000117 } else if (const RedeclarableTemplateDecl *Tmpl
Douglas Gregore0329ac2010-09-02 00:07:54 +0000118 = dyn_cast<RedeclarableTemplateDecl>(D))
119 Template = Tmpl->getInstantiatedFromMemberTemplate();
120
121 if (!Template)
122 return clang_getNullCursor();
123
Dmitri Gribenko46f92522013-01-11 19:28:44 +0000124 return MakeCXCursor(Template, getCursorTU(C));
Douglas Gregore0329ac2010-09-02 00:07:54 +0000125}
126
Ted Kremenek585b3182010-08-27 21:57:20 +0000127} // end extern "C"