1//===- CIndexCXX.cpp - Clang-C Source Indexing Library --------------------===//
2//
3// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4// See https://llvm.org/LICENSE.txt for license information.
5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6//
7//===----------------------------------------------------------------------===//
8//
9// This file implements the libclang support for C++ cursors.
10//
11//===----------------------------------------------------------------------===//
12
13#include "CIndexer.h"
14#include "CXCursor.h"
15#include "CXType.h"
16#include "clang/AST/DeclCXX.h"
17#include "clang/AST/DeclTemplate.h"
18
19using namespace clang;
20using namespace clang::cxcursor;
21
22unsigned clang_isVirtualBase(CXCursor C) {
23 if (C.kind != CXCursor_CXXBaseSpecifier)
24 return 0;
25
26 const CXXBaseSpecifier *B = getCursorCXXBaseSpecifier(C);
27 return B->isVirtual();
28}
29
30unsigned clang_visitCXXBaseClasses(CXType PT, CXFieldVisitor visitor,
31 CXClientData client_data) {
32 CXCursor PC = clang_getTypeDeclaration(T: PT);
33 if (clang_isInvalid(PC.kind))
34 return false;
35 const CXXRecordDecl *RD =
36 dyn_cast_if_present<CXXRecordDecl>(Val: cxcursor::getCursorDecl(Cursor: PC));
37 if (!RD || RD->isInvalidDecl())
38 return false;
39 RD = RD->getDefinition();
40 if (!RD || RD->isInvalidDecl())
41 return false;
42
43 for (auto &Base : RD->bases()) {
44 // Callback to the client.
45 switch (
46 visitor(cxcursor::MakeCursorCXXBaseSpecifier(B: &Base, TU: getCursorTU(Cursor: PC)),
47 client_data)) {
48 case CXVisit_Break:
49 return true;
50 case CXVisit_Continue:
51 break;
52 }
53 }
54 return true;
55}
56
57unsigned clang_visitCXXMethods(CXType PT, CXFieldVisitor visitor,
58 CXClientData client_data) {
59 CXCursor PC = clang_getTypeDeclaration(T: PT);
60 if (clang_isInvalid(PC.kind))
61 return false;
62 const auto *RD =
63 dyn_cast_if_present<CXXRecordDecl>(Val: cxcursor::getCursorDecl(Cursor: PC));
64 if (!RD || RD->isInvalidDecl())
65 return false;
66 RD = RD->getDefinition();
67 if (!RD || RD->isInvalidDecl())
68 return false;
69
70 for (const auto *Method : RD->methods()) {
71 // Callback to the client.
72 switch (
73 visitor(cxcursor::MakeCXCursor(Method, getCursorTU(Cursor: PC)), client_data)) {
74 case CXVisit_Break:
75 return true;
76 case CXVisit_Continue:
77 break;
78 }
79 }
80 return true;
81}
82
83enum CX_CXXAccessSpecifier clang_getCXXAccessSpecifier(CXCursor C) {
84 AccessSpecifier spec = AS_none;
85
86 if (C.kind == CXCursor_CXXAccessSpecifier || clang_isDeclaration(C.kind))
87 spec = getCursorDecl(Cursor: C)->getAccess();
88 else if (C.kind == CXCursor_CXXBaseSpecifier)
89 spec = getCursorCXXBaseSpecifier(C)->getAccessSpecifier();
90 else
91 return CX_CXXInvalidAccessSpecifier;
92
93 switch (spec) {
94 case AS_public: return CX_CXXPublic;
95 case AS_protected: return CX_CXXProtected;
96 case AS_private: return CX_CXXPrivate;
97 case AS_none: return CX_CXXInvalidAccessSpecifier;
98 }
99
100 llvm_unreachable("Invalid AccessSpecifier!");
101}
102
103enum CXCursorKind clang_getTemplateCursorKind(CXCursor C) {
104 using namespace clang::cxcursor;
105
106 switch (C.kind) {
107 case CXCursor_ClassTemplate:
108 case CXCursor_FunctionTemplate:
109 if (const TemplateDecl *Template
110 = dyn_cast_or_null<TemplateDecl>(Val: getCursorDecl(Cursor: C)))
111 return MakeCXCursor(Template->getTemplatedDecl(), getCursorTU(Cursor: C)).kind;
112 break;
113
114 case CXCursor_ClassTemplatePartialSpecialization:
115 if (const ClassTemplateSpecializationDecl *PartialSpec
116 = dyn_cast_or_null<ClassTemplatePartialSpecializationDecl>(
117 Val: getCursorDecl(Cursor: C))) {
118 switch (PartialSpec->getTagKind()) {
119 case TagTypeKind::Interface:
120 case TagTypeKind::Struct:
121 return CXCursor_StructDecl;
122 case TagTypeKind::Class:
123 return CXCursor_ClassDecl;
124 case TagTypeKind::Union:
125 return CXCursor_UnionDecl;
126 case TagTypeKind::Enum:
127 return CXCursor_NoDeclFound;
128 }
129 }
130 break;
131
132 default:
133 break;
134 }
135
136 return CXCursor_NoDeclFound;
137}
138
139CXCursor clang_getSpecializedCursorTemplate(CXCursor C) {
140 if (!clang_isDeclaration(C.kind))
141 return clang_getNullCursor();
142
143 const Decl *D = getCursorDecl(Cursor: C);
144 if (!D)
145 return clang_getNullCursor();
146
147 Decl *Template = nullptr;
148 if (const CXXRecordDecl *CXXRecord = dyn_cast<CXXRecordDecl>(Val: D)) {
149 if (const ClassTemplatePartialSpecializationDecl *PartialSpec
150 = dyn_cast<ClassTemplatePartialSpecializationDecl>(Val: CXXRecord))
151 Template = PartialSpec->getSpecializedTemplate();
152 else if (const ClassTemplateSpecializationDecl *ClassSpec
153 = dyn_cast<ClassTemplateSpecializationDecl>(Val: CXXRecord)) {
154 llvm::PointerUnion<ClassTemplateDecl *,
155 ClassTemplatePartialSpecializationDecl *> Result
156 = ClassSpec->getSpecializedTemplateOrPartial();
157 if (isa<ClassTemplateDecl *>(Val: Result))
158 Template = cast<ClassTemplateDecl *>(Val&: Result);
159 else
160 Template = cast<ClassTemplatePartialSpecializationDecl *>(Val&: Result);
161
162 } else
163 Template = CXXRecord->getInstantiatedFromMemberClass();
164 } else if (const FunctionDecl *Function = dyn_cast<FunctionDecl>(Val: D)) {
165 Template = Function->getPrimaryTemplate();
166 if (!Template)
167 Template = Function->getInstantiatedFromMemberFunction();
168 } else if (const VarDecl *Var = dyn_cast<VarDecl>(Val: D)) {
169 if (Var->isStaticDataMember())
170 Template = Var->getInstantiatedFromStaticDataMember();
171 } else if (const RedeclarableTemplateDecl *Tmpl
172 = dyn_cast<RedeclarableTemplateDecl>(Val: D))
173 Template = Tmpl->getInstantiatedFromMemberTemplate();
174
175 if (!Template)
176 return clang_getNullCursor();
177
178 return MakeCXCursor(D: Template, TU: getCursorTU(Cursor: C));
179}
180

Provided by KDAB

Privacy Policy
Learn to use CMake with our Intro Training
Find out more

source code of clang/tools/libclang/CIndexCXX.cpp