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