blob: 56fba28387d0fdd86a5bb2f86dd6657952d96100 [file] [log] [blame]
Argyrios Kyrtzidisf4fb85b2016-02-12 23:10:59 +00001//===- IndexBody.cpp - Indexing statements --------------------------------===//
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#include "IndexingContext.h"
11#include "clang/AST/RecursiveASTVisitor.h"
12
13using namespace clang;
14using namespace clang::index;
15
16namespace {
17
18class BodyIndexer : public RecursiveASTVisitor<BodyIndexer> {
19 IndexingContext &IndexCtx;
20 const NamedDecl *Parent;
21 const DeclContext *ParentDC;
22 SmallVector<Stmt*, 16> StmtStack;
23
24 typedef RecursiveASTVisitor<BodyIndexer> base;
25public:
26 BodyIndexer(IndexingContext &indexCtx,
27 const NamedDecl *Parent, const DeclContext *DC)
28 : IndexCtx(indexCtx), Parent(Parent), ParentDC(DC) { }
29
30 bool shouldWalkTypesOfTypeLocs() const { return false; }
31
32 bool TraverseStmt(Stmt *S) {
33 StmtStack.push_back(S);
34 bool ret = base::TraverseStmt(S);
35 StmtStack.pop_back();
36 return ret;
37 }
38
39 bool TraverseTypeLoc(TypeLoc TL) {
40 IndexCtx.indexTypeLoc(TL, Parent, ParentDC);
41 return true;
42 }
43
44 bool TraverseNestedNameSpecifierLoc(NestedNameSpecifierLoc NNS) {
45 IndexCtx.indexNestedNameSpecifierLoc(NNS, Parent, ParentDC);
46 return true;
47 }
48
49 SymbolRoleSet getRolesForRef(const Expr *E,
50 SmallVectorImpl<SymbolRelation> &Relations) {
51 SymbolRoleSet Roles{};
52 assert(!StmtStack.empty() && E == StmtStack.back());
53 if (StmtStack.size() == 1)
54 return Roles;
55 auto It = StmtStack.end()-2;
56 while (isa<CastExpr>(*It) || isa<ParenExpr>(*It)) {
57 if (auto ICE = dyn_cast<ImplicitCastExpr>(*It)) {
58 if (ICE->getCastKind() == CK_LValueToRValue)
59 Roles |= (unsigned)(unsigned)SymbolRole::Read;
60 }
61 if (It == StmtStack.begin())
62 break;
63 --It;
64 }
65 const Stmt *Parent = *It;
66
67 if (auto BO = dyn_cast<BinaryOperator>(Parent)) {
68 if (BO->getOpcode() == BO_Assign && BO->getLHS()->IgnoreParenCasts() == E)
69 Roles |= (unsigned)SymbolRole::Write;
70
71 } else if (auto UO = dyn_cast<UnaryOperator>(Parent)) {
72 if (UO->isIncrementDecrementOp()) {
73 Roles |= (unsigned)SymbolRole::Read;
74 Roles |= (unsigned)SymbolRole::Write;
75 } else if (UO->getOpcode() == UO_AddrOf) {
76 Roles |= (unsigned)SymbolRole::AddressOf;
77 }
78
79 } else if (auto CA = dyn_cast<CompoundAssignOperator>(Parent)) {
80 if (CA->getLHS()->IgnoreParenCasts() == E) {
81 Roles |= (unsigned)SymbolRole::Read;
82 Roles |= (unsigned)SymbolRole::Write;
83 }
84
85 } else if (auto CE = dyn_cast<CallExpr>(Parent)) {
86 if (CE->getCallee()->IgnoreParenCasts() == E) {
87 Roles |= (unsigned)SymbolRole::Call;
88 if (auto *ME = dyn_cast<MemberExpr>(E)) {
89 if (auto *CXXMD = dyn_cast_or_null<CXXMethodDecl>(ME->getMemberDecl()))
90 if (CXXMD->isVirtual() && !ME->hasQualifier()) {
91 Roles |= (unsigned)SymbolRole::Dynamic;
92 auto BaseTy = ME->getBase()->IgnoreImpCasts()->getType();
93 if (!BaseTy.isNull())
94 if (auto *CXXRD = BaseTy->getPointeeCXXRecordDecl())
95 Relations.emplace_back((unsigned)SymbolRole::RelationReceivedBy,
96 CXXRD);
97 }
98 }
99 } else if (auto CXXOp = dyn_cast<CXXOperatorCallExpr>(CE)) {
100 if (CXXOp->getNumArgs() > 0 && CXXOp->getArg(0)->IgnoreParenCasts() == E) {
101 OverloadedOperatorKind Op = CXXOp->getOperator();
102 if (Op == OO_Equal) {
103 Roles |= (unsigned)SymbolRole::Write;
104 } else if ((Op >= OO_PlusEqual && Op <= OO_PipeEqual) ||
105 Op == OO_LessLessEqual || Op == OO_GreaterGreaterEqual ||
106 Op == OO_PlusPlus || Op == OO_MinusMinus) {
107 Roles |= (unsigned)SymbolRole::Read;
108 Roles |= (unsigned)SymbolRole::Write;
109 } else if (Op == OO_Amp) {
110 Roles |= (unsigned)SymbolRole::AddressOf;
111 }
112 }
113 }
114 }
115
116 return Roles;
117 }
118
119 bool VisitDeclRefExpr(DeclRefExpr *E) {
120 SmallVector<SymbolRelation, 4> Relations;
121 SymbolRoleSet Roles = getRolesForRef(E, Relations);
122 return IndexCtx.handleReference(E->getDecl(), E->getLocation(),
123 Parent, ParentDC, Roles, Relations, E);
124 }
125
126 bool VisitMemberExpr(MemberExpr *E) {
127 SourceLocation Loc = E->getMemberLoc();
128 if (Loc.isInvalid())
129 Loc = E->getLocStart();
130 SmallVector<SymbolRelation, 4> Relations;
131 SymbolRoleSet Roles = getRolesForRef(E, Relations);
132 return IndexCtx.handleReference(E->getMemberDecl(), Loc,
133 Parent, ParentDC, Roles, Relations, E);
134 }
135
136 bool VisitDesignatedInitExpr(DesignatedInitExpr *E) {
137 for (DesignatedInitExpr::reverse_designators_iterator
138 D = E->designators_rbegin(), DEnd = E->designators_rend();
139 D != DEnd; ++D) {
140 if (D->isFieldDesignator())
141 return IndexCtx.handleReference(D->getField(), D->getFieldLoc(),
142 Parent, ParentDC, SymbolRoleSet(),
143 {}, E);
144 }
145 return true;
146 }
147
148 bool VisitObjCIvarRefExpr(ObjCIvarRefExpr *E) {
149 SmallVector<SymbolRelation, 4> Relations;
150 SymbolRoleSet Roles = getRolesForRef(E, Relations);
151 return IndexCtx.handleReference(E->getDecl(), E->getLocation(),
152 Parent, ParentDC, Roles, Relations, E);
153 }
154
155 bool VisitObjCMessageExpr(ObjCMessageExpr *E) {
156 auto isDynamic = [](const ObjCMessageExpr *MsgE)->bool {
157 if (MsgE->getReceiverKind() != ObjCMessageExpr::Instance)
158 return false;
159 if (auto *RecE = dyn_cast<ObjCMessageExpr>(
160 MsgE->getInstanceReceiver()->IgnoreParenCasts())) {
161 if (RecE->getMethodFamily() == OMF_alloc)
162 return false;
163 }
164 return true;
165 };
166
167 if (ObjCMethodDecl *MD = E->getMethodDecl()) {
168 SymbolRoleSet Roles = (unsigned)SymbolRole::Call;
169 if (E->isImplicit())
170 Roles |= (unsigned)SymbolRole::Implicit;
171
172 SmallVector<SymbolRelation, 2> Relations;
173 if (isDynamic(E)) {
174 Roles |= (unsigned)SymbolRole::Dynamic;
175 if (auto *RecD = E->getReceiverInterface())
176 Relations.emplace_back((unsigned)SymbolRole::RelationReceivedBy, RecD);
177 }
178
179 return IndexCtx.handleReference(MD, E->getSelectorStartLoc(),
180 Parent, ParentDC, Roles, Relations, E);
181 }
182 return true;
183 }
184
185 bool VisitObjCPropertyRefExpr(ObjCPropertyRefExpr *E) {
186 if (E->isExplicitProperty())
187 return IndexCtx.handleReference(E->getExplicitProperty(), E->getLocation(),
188 Parent, ParentDC, SymbolRoleSet(), {}, E);
189
190 // No need to do a handleReference for the objc method, because there will
191 // be a message expr as part of PseudoObjectExpr.
192 return true;
193 }
194
195 bool VisitMSPropertyRefExpr(MSPropertyRefExpr *E) {
196 return IndexCtx.handleReference(E->getPropertyDecl(), E->getMemberLoc(),
197 Parent, ParentDC, SymbolRoleSet(), {}, E);
198 }
199
200 bool VisitObjCProtocolExpr(ObjCProtocolExpr *E) {
201 return IndexCtx.handleReference(E->getProtocol(), E->getProtocolIdLoc(),
202 Parent, ParentDC, SymbolRoleSet(), {}, E);
203 }
204
205 bool VisitObjCBoxedExpr(ObjCBoxedExpr *E) {
206 if (ObjCMethodDecl *MD = E->getBoxingMethod()) {
207 SymbolRoleSet Roles = (unsigned)SymbolRole::Call;
208 Roles |= (unsigned)SymbolRole::Implicit;
209 return IndexCtx.handleReference(MD, E->getLocStart(),
210 Parent, ParentDC, Roles, {}, E);
211 }
212 return true;
213 }
214
215 bool VisitObjCDictionaryLiteral(ObjCDictionaryLiteral *E) {
216 if (ObjCMethodDecl *MD = E->getDictWithObjectsMethod()) {
217 SymbolRoleSet Roles = (unsigned)SymbolRole::Call;
218 Roles |= (unsigned)SymbolRole::Implicit;
219 return IndexCtx.handleReference(MD, E->getLocStart(),
220 Parent, ParentDC, Roles, {}, E);
221 }
222 return true;
223 }
224
225 bool VisitObjCArrayLiteral(ObjCArrayLiteral *E) {
226 if (ObjCMethodDecl *MD = E->getArrayWithObjectsMethod()) {
227 SymbolRoleSet Roles = (unsigned)SymbolRole::Call;
228 Roles |= (unsigned)SymbolRole::Implicit;
229 return IndexCtx.handleReference(MD, E->getLocStart(),
230 Parent, ParentDC, Roles, {}, E);
231 }
232 return true;
233 }
234
235 bool VisitCXXConstructExpr(CXXConstructExpr *E) {
236 return IndexCtx.handleReference(E->getConstructor(), E->getLocation(),
237 Parent, ParentDC, (unsigned)SymbolRole::Call, {}, E);
238 }
239
240 bool TraverseCXXOperatorCallExpr(CXXOperatorCallExpr *E,
241 DataRecursionQueue *Q = nullptr) {
242 if (E->getOperatorLoc().isInvalid())
243 return true; // implicit.
244 return base::TraverseCXXOperatorCallExpr(E);
245 }
246
247 bool VisitDeclStmt(DeclStmt *S) {
248 if (IndexCtx.shouldIndexFunctionLocalSymbols()) {
249 IndexCtx.indexDeclGroupRef(S->getDeclGroup());
250 return true;
251 }
252
253 DeclGroupRef DG = S->getDeclGroup();
254 for (DeclGroupRef::iterator I = DG.begin(), E = DG.end(); I != E; ++I) {
255 const Decl *D = *I;
256 if (!D)
257 continue;
258 if (!IndexCtx.isFunctionLocalDecl(D))
259 IndexCtx.indexTopLevelDecl(D);
260 }
261
262 return true;
263 }
264
265 bool TraverseLambdaCapture(LambdaExpr *LE, const LambdaCapture *C) {
266 if (C->capturesThis() || C->capturesVLAType())
267 return true;
268
269 if (C->capturesVariable() && IndexCtx.shouldIndexFunctionLocalSymbols())
270 return IndexCtx.handleReference(C->getCapturedVar(), C->getLocation(),
271 Parent, ParentDC, SymbolRoleSet());
272
273 // FIXME: Lambda init-captures.
274 return true;
275 }
276
277 // RecursiveASTVisitor visits both syntactic and semantic forms, duplicating
278 // the things that we visit. Make sure to only visit the semantic form.
279 // Also visit things that are in the syntactic form but not the semantic one,
280 // for example the indices in DesignatedInitExprs.
281 bool TraverseInitListExpr(InitListExpr *S, DataRecursionQueue *Q = nullptr) {
282
283 class SyntacticFormIndexer :
284 public RecursiveASTVisitor<SyntacticFormIndexer> {
285 IndexingContext &IndexCtx;
286 const NamedDecl *Parent;
287 const DeclContext *ParentDC;
288
289 public:
290 SyntacticFormIndexer(IndexingContext &indexCtx,
291 const NamedDecl *Parent, const DeclContext *DC)
292 : IndexCtx(indexCtx), Parent(Parent), ParentDC(DC) { }
293
294 bool shouldWalkTypesOfTypeLocs() const { return false; }
295
296 bool VisitDesignatedInitExpr(DesignatedInitExpr *E) {
297 for (DesignatedInitExpr::reverse_designators_iterator
298 D = E->designators_rbegin(), DEnd = E->designators_rend();
299 D != DEnd; ++D) {
300 if (D->isFieldDesignator())
301 return IndexCtx.handleReference(D->getField(), D->getFieldLoc(),
302 Parent, ParentDC, SymbolRoleSet(),
303 {}, E);
304 }
305 return true;
306 }
307 };
308
309 auto visitForm = [&](InitListExpr *Form) {
310 for (Stmt *SubStmt : Form->children()) {
311 if (!TraverseStmt(SubStmt))
312 return false;
313 }
314 return true;
315 };
316
317 InitListExpr *SemaForm = S->isSemanticForm() ? S : S->getSemanticForm();
318 InitListExpr *SyntaxForm = S->isSemanticForm() ? S->getSyntacticForm() : S;
319
320 if (SemaForm) {
321 // Visit things present in syntactic form but not the semantic form.
322 if (SyntaxForm) {
323 SyntacticFormIndexer(IndexCtx, Parent, ParentDC).TraverseStmt(SyntaxForm);
324 }
325 return visitForm(SemaForm);
326 }
327
328 // No semantic, try the syntactic.
329 if (SyntaxForm) {
330 return visitForm(SyntaxForm);
331 }
332
333 return true;
334 }
335};
336
337} // anonymous namespace
338
339void IndexingContext::indexBody(const Stmt *S, const NamedDecl *Parent,
340 const DeclContext *DC) {
341 if (!S)
342 return;
343
344 if (!DC)
345 DC = Parent->getLexicalDeclContext();
346 BodyIndexer(*this, Parent, DC).TraverseStmt(const_cast<Stmt*>(S));
347}