blob: 028b64a2b2d94b82a78a96b1183c50656d22dcf5 [file] [log] [blame]
Ted Kremenek378e93c2010-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 Gregorf11309e2010-08-31 22:12:17 +000018#include "clang/AST/DeclTemplate.h"
Ted Kremenek378e93c2010-08-27 21:57:20 +000019
20using namespace clang;
Douglas Gregord3f48bd2010-09-02 00:07:54 +000021using namespace clang::cxcursor;
Ted Kremenek378e93c2010-08-27 21:57:20 +000022
Ted Kremenek378e93c2010-08-27 21:57:20 +000023unsigned clang_isVirtualBase(CXCursor C) {
24 if (C.kind != CXCursor_CXXBaseSpecifier)
25 return 0;
26
Dmitri Gribenkoba2f7462013-01-11 21:01:49 +000027 const CXXBaseSpecifier *B = getCursorCXXBaseSpecifier(C);
Ted Kremenek378e93c2010-08-27 21:57:20 +000028 return B->isVirtual();
29}
30
31enum CX_CXXAccessSpecifier clang_getCXXAccessSpecifier(CXCursor C) {
Argyrios Kyrtzidis12afd702011-09-30 17:58:23 +000032 AccessSpecifier spec = AS_none;
33
Argyrios Kyrtzidis1ab09cc2013-04-11 17:02:10 +000034 if (C.kind == CXCursor_CXXAccessSpecifier || clang_isDeclaration(C.kind))
Argyrios Kyrtzidis12afd702011-09-30 17:58:23 +000035 spec = getCursorDecl(C)->getAccess();
36 else if (C.kind == CXCursor_CXXBaseSpecifier)
37 spec = getCursorCXXBaseSpecifier(C)->getAccessSpecifier();
38 else
Ted Kremenek378e93c2010-08-27 21:57:20 +000039 return CX_CXXInvalidAccessSpecifier;
40
Argyrios Kyrtzidis12afd702011-09-30 17:58:23 +000041 switch (spec) {
Ted Kremenek378e93c2010-08-27 21:57:20 +000042 case AS_public: return CX_CXXPublic;
43 case AS_protected: return CX_CXXProtected;
44 case AS_private: return CX_CXXPrivate;
45 case AS_none: return CX_CXXInvalidAccessSpecifier;
46 }
David Blaikie8a40f702012-01-17 06:56:22 +000047
48 llvm_unreachable("Invalid AccessSpecifier!");
Ted Kremenek378e93c2010-08-27 21:57:20 +000049}
50
Douglas Gregorf11309e2010-08-31 22:12:17 +000051enum CXCursorKind clang_getTemplateCursorKind(CXCursor C) {
52 using namespace clang::cxcursor;
53
54 switch (C.kind) {
55 case CXCursor_ClassTemplate:
56 case CXCursor_FunctionTemplate:
Dmitri Gribenkod15bb302013-01-23 17:25:27 +000057 if (const TemplateDecl *Template
Douglas Gregorf11309e2010-08-31 22:12:17 +000058 = dyn_cast_or_null<TemplateDecl>(getCursorDecl(C)))
Dmitri Gribenko2c173b42013-01-11 19:28:44 +000059 return MakeCXCursor(Template->getTemplatedDecl(), getCursorTU(C)).kind;
Douglas Gregorf11309e2010-08-31 22:12:17 +000060 break;
61
62 case CXCursor_ClassTemplatePartialSpecialization:
Dmitri Gribenkod15bb302013-01-23 17:25:27 +000063 if (const ClassTemplateSpecializationDecl *PartialSpec
Joao Matose9a3ed42012-08-31 22:18:20 +000064 = dyn_cast_or_null<ClassTemplatePartialSpecializationDecl>(
65 getCursorDecl(C))) {
66 switch (PartialSpec->getTagKind()) {
67 case TTK_Interface:
68 case TTK_Struct: return CXCursor_StructDecl;
69 case TTK_Class: return CXCursor_ClassDecl;
70 case TTK_Union: return CXCursor_UnionDecl;
71 case TTK_Enum: return CXCursor_NoDeclFound;
72 }
Douglas Gregorf11309e2010-08-31 22:12:17 +000073 }
74 break;
75
76 default:
77 break;
78 }
79
80 return CXCursor_NoDeclFound;
81}
82
Douglas Gregord3f48bd2010-09-02 00:07:54 +000083CXCursor clang_getSpecializedCursorTemplate(CXCursor C) {
84 if (!clang_isDeclaration(C.kind))
85 return clang_getNullCursor();
86
Dmitri Gribenkod15bb302013-01-23 17:25:27 +000087 const Decl *D = getCursorDecl(C);
Douglas Gregord3f48bd2010-09-02 00:07:54 +000088 if (!D)
89 return clang_getNullCursor();
Craig Topper69186e72014-06-08 08:38:04 +000090
91 Decl *Template = nullptr;
Dmitri Gribenkod15bb302013-01-23 17:25:27 +000092 if (const CXXRecordDecl *CXXRecord = dyn_cast<CXXRecordDecl>(D)) {
93 if (const ClassTemplatePartialSpecializationDecl *PartialSpec
Douglas Gregord3f48bd2010-09-02 00:07:54 +000094 = dyn_cast<ClassTemplatePartialSpecializationDecl>(CXXRecord))
95 Template = PartialSpec->getSpecializedTemplate();
Dmitri Gribenkod15bb302013-01-23 17:25:27 +000096 else if (const ClassTemplateSpecializationDecl *ClassSpec
Douglas Gregord3f48bd2010-09-02 00:07:54 +000097 = dyn_cast<ClassTemplateSpecializationDecl>(CXXRecord)) {
98 llvm::PointerUnion<ClassTemplateDecl *,
99 ClassTemplatePartialSpecializationDecl *> Result
100 = ClassSpec->getSpecializedTemplateOrPartial();
101 if (Result.is<ClassTemplateDecl *>())
102 Template = Result.get<ClassTemplateDecl *>();
103 else
104 Template = Result.get<ClassTemplatePartialSpecializationDecl *>();
105
106 } else
107 Template = CXXRecord->getInstantiatedFromMemberClass();
Dmitri Gribenkod15bb302013-01-23 17:25:27 +0000108 } else if (const FunctionDecl *Function = dyn_cast<FunctionDecl>(D)) {
Douglas Gregord3f48bd2010-09-02 00:07:54 +0000109 Template = Function->getPrimaryTemplate();
110 if (!Template)
111 Template = Function->getInstantiatedFromMemberFunction();
Dmitri Gribenkod15bb302013-01-23 17:25:27 +0000112 } else if (const VarDecl *Var = dyn_cast<VarDecl>(D)) {
Douglas Gregord3f48bd2010-09-02 00:07:54 +0000113 if (Var->isStaticDataMember())
114 Template = Var->getInstantiatedFromStaticDataMember();
Dmitri Gribenkod15bb302013-01-23 17:25:27 +0000115 } else if (const RedeclarableTemplateDecl *Tmpl
Douglas Gregord3f48bd2010-09-02 00:07:54 +0000116 = dyn_cast<RedeclarableTemplateDecl>(D))
117 Template = Tmpl->getInstantiatedFromMemberTemplate();
118
119 if (!Template)
120 return clang_getNullCursor();
121
Dmitri Gribenko2c173b42013-01-11 19:28:44 +0000122 return MakeCXCursor(Template, getCursorTU(C));
Douglas Gregord3f48bd2010-09-02 00:07:54 +0000123}