blob: 7f09290de40fad17c130ea85b399707b6aca8c49 [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;
Argyrios Kyrtzidis194b28e2017-03-16 18:25:40 +000025
26 Stmt *getParentStmt() const {
27 return StmtStack.size() < 2 ? nullptr : StmtStack.end()[-2];
28 }
Argyrios Kyrtzidisf4fb85b2016-02-12 23:10:59 +000029public:
30 BodyIndexer(IndexingContext &indexCtx,
31 const NamedDecl *Parent, const DeclContext *DC)
32 : IndexCtx(indexCtx), Parent(Parent), ParentDC(DC) { }
33
34 bool shouldWalkTypesOfTypeLocs() const { return false; }
35
Argyrios Kyrtzidisa36dd122016-02-13 01:24:19 +000036 bool dataTraverseStmtPre(Stmt *S) {
Argyrios Kyrtzidisf4fb85b2016-02-12 23:10:59 +000037 StmtStack.push_back(S);
Argyrios Kyrtzidisa36dd122016-02-13 01:24:19 +000038 return true;
39 }
40
41 bool dataTraverseStmtPost(Stmt *S) {
42 assert(StmtStack.back() == S);
Argyrios Kyrtzidisf4fb85b2016-02-12 23:10:59 +000043 StmtStack.pop_back();
Argyrios Kyrtzidisa36dd122016-02-13 01:24:19 +000044 return true;
Argyrios Kyrtzidisf4fb85b2016-02-12 23:10:59 +000045 }
46
47 bool TraverseTypeLoc(TypeLoc TL) {
48 IndexCtx.indexTypeLoc(TL, Parent, ParentDC);
49 return true;
50 }
51
52 bool TraverseNestedNameSpecifierLoc(NestedNameSpecifierLoc NNS) {
53 IndexCtx.indexNestedNameSpecifierLoc(NNS, Parent, ParentDC);
54 return true;
55 }
56
57 SymbolRoleSet getRolesForRef(const Expr *E,
58 SmallVectorImpl<SymbolRelation> &Relations) {
59 SymbolRoleSet Roles{};
60 assert(!StmtStack.empty() && E == StmtStack.back());
61 if (StmtStack.size() == 1)
62 return Roles;
63 auto It = StmtStack.end()-2;
64 while (isa<CastExpr>(*It) || isa<ParenExpr>(*It)) {
65 if (auto ICE = dyn_cast<ImplicitCastExpr>(*It)) {
66 if (ICE->getCastKind() == CK_LValueToRValue)
67 Roles |= (unsigned)(unsigned)SymbolRole::Read;
68 }
69 if (It == StmtStack.begin())
70 break;
71 --It;
72 }
73 const Stmt *Parent = *It;
74
75 if (auto BO = dyn_cast<BinaryOperator>(Parent)) {
76 if (BO->getOpcode() == BO_Assign && BO->getLHS()->IgnoreParenCasts() == E)
77 Roles |= (unsigned)SymbolRole::Write;
78
79 } else if (auto UO = dyn_cast<UnaryOperator>(Parent)) {
80 if (UO->isIncrementDecrementOp()) {
81 Roles |= (unsigned)SymbolRole::Read;
82 Roles |= (unsigned)SymbolRole::Write;
83 } else if (UO->getOpcode() == UO_AddrOf) {
84 Roles |= (unsigned)SymbolRole::AddressOf;
85 }
86
87 } else if (auto CA = dyn_cast<CompoundAssignOperator>(Parent)) {
88 if (CA->getLHS()->IgnoreParenCasts() == E) {
89 Roles |= (unsigned)SymbolRole::Read;
90 Roles |= (unsigned)SymbolRole::Write;
91 }
92
93 } else if (auto CE = dyn_cast<CallExpr>(Parent)) {
94 if (CE->getCallee()->IgnoreParenCasts() == E) {
Argyrios Kyrtzidisa8b51c12016-02-29 07:56:00 +000095 addCallRole(Roles, Relations);
Argyrios Kyrtzidisf4fb85b2016-02-12 23:10:59 +000096 if (auto *ME = dyn_cast<MemberExpr>(E)) {
97 if (auto *CXXMD = dyn_cast_or_null<CXXMethodDecl>(ME->getMemberDecl()))
98 if (CXXMD->isVirtual() && !ME->hasQualifier()) {
99 Roles |= (unsigned)SymbolRole::Dynamic;
100 auto BaseTy = ME->getBase()->IgnoreImpCasts()->getType();
101 if (!BaseTy.isNull())
102 if (auto *CXXRD = BaseTy->getPointeeCXXRecordDecl())
103 Relations.emplace_back((unsigned)SymbolRole::RelationReceivedBy,
104 CXXRD);
105 }
106 }
107 } else if (auto CXXOp = dyn_cast<CXXOperatorCallExpr>(CE)) {
108 if (CXXOp->getNumArgs() > 0 && CXXOp->getArg(0)->IgnoreParenCasts() == E) {
109 OverloadedOperatorKind Op = CXXOp->getOperator();
110 if (Op == OO_Equal) {
111 Roles |= (unsigned)SymbolRole::Write;
112 } else if ((Op >= OO_PlusEqual && Op <= OO_PipeEqual) ||
113 Op == OO_LessLessEqual || Op == OO_GreaterGreaterEqual ||
114 Op == OO_PlusPlus || Op == OO_MinusMinus) {
115 Roles |= (unsigned)SymbolRole::Read;
116 Roles |= (unsigned)SymbolRole::Write;
117 } else if (Op == OO_Amp) {
118 Roles |= (unsigned)SymbolRole::AddressOf;
119 }
120 }
121 }
122 }
123
124 return Roles;
125 }
126
Argyrios Kyrtzidisa8b51c12016-02-29 07:56:00 +0000127 void addCallRole(SymbolRoleSet &Roles,
128 SmallVectorImpl<SymbolRelation> &Relations) {
129 Roles |= (unsigned)SymbolRole::Call;
130 if (auto *FD = dyn_cast<FunctionDecl>(ParentDC))
131 Relations.emplace_back((unsigned)SymbolRole::RelationCalledBy, FD);
132 else if (auto *MD = dyn_cast<ObjCMethodDecl>(ParentDC))
133 Relations.emplace_back((unsigned)SymbolRole::RelationCalledBy, MD);
134 }
135
Argyrios Kyrtzidisf4fb85b2016-02-12 23:10:59 +0000136 bool VisitDeclRefExpr(DeclRefExpr *E) {
137 SmallVector<SymbolRelation, 4> Relations;
138 SymbolRoleSet Roles = getRolesForRef(E, Relations);
139 return IndexCtx.handleReference(E->getDecl(), E->getLocation(),
140 Parent, ParentDC, Roles, Relations, E);
141 }
142
143 bool VisitMemberExpr(MemberExpr *E) {
144 SourceLocation Loc = E->getMemberLoc();
145 if (Loc.isInvalid())
146 Loc = E->getLocStart();
147 SmallVector<SymbolRelation, 4> Relations;
148 SymbolRoleSet Roles = getRolesForRef(E, Relations);
149 return IndexCtx.handleReference(E->getMemberDecl(), Loc,
150 Parent, ParentDC, Roles, Relations, E);
151 }
152
153 bool VisitDesignatedInitExpr(DesignatedInitExpr *E) {
David Majnemerf7e36092016-06-23 00:15:04 +0000154 for (DesignatedInitExpr::Designator &D : llvm::reverse(E->designators())) {
Argyrios Kyrtzidisf60c3952016-08-03 05:38:53 +0000155 if (D.isFieldDesignator() && D.getField())
David Majnemerf7e36092016-06-23 00:15:04 +0000156 return IndexCtx.handleReference(D.getField(), D.getFieldLoc(), Parent,
157 ParentDC, SymbolRoleSet(), {}, E);
Argyrios Kyrtzidisf4fb85b2016-02-12 23:10:59 +0000158 }
159 return true;
160 }
161
162 bool VisitObjCIvarRefExpr(ObjCIvarRefExpr *E) {
163 SmallVector<SymbolRelation, 4> Relations;
164 SymbolRoleSet Roles = getRolesForRef(E, Relations);
165 return IndexCtx.handleReference(E->getDecl(), E->getLocation(),
166 Parent, ParentDC, Roles, Relations, E);
167 }
168
169 bool VisitObjCMessageExpr(ObjCMessageExpr *E) {
170 auto isDynamic = [](const ObjCMessageExpr *MsgE)->bool {
171 if (MsgE->getReceiverKind() != ObjCMessageExpr::Instance)
172 return false;
173 if (auto *RecE = dyn_cast<ObjCMessageExpr>(
174 MsgE->getInstanceReceiver()->IgnoreParenCasts())) {
175 if (RecE->getMethodFamily() == OMF_alloc)
176 return false;
177 }
178 return true;
179 };
180
181 if (ObjCMethodDecl *MD = E->getMethodDecl()) {
Argyrios Kyrtzidisa8b51c12016-02-29 07:56:00 +0000182 SymbolRoleSet Roles{};
183 SmallVector<SymbolRelation, 2> Relations;
184 addCallRole(Roles, Relations);
Argyrios Kyrtzidis194b28e2017-03-16 18:25:40 +0000185 Stmt *Containing = getParentStmt();
186 if (E->isImplicit() || (Containing && isa<PseudoObjectExpr>(Containing)))
Argyrios Kyrtzidisf4fb85b2016-02-12 23:10:59 +0000187 Roles |= (unsigned)SymbolRole::Implicit;
188
Argyrios Kyrtzidisf4fb85b2016-02-12 23:10:59 +0000189 if (isDynamic(E)) {
190 Roles |= (unsigned)SymbolRole::Dynamic;
191 if (auto *RecD = E->getReceiverInterface())
192 Relations.emplace_back((unsigned)SymbolRole::RelationReceivedBy, RecD);
193 }
194
195 return IndexCtx.handleReference(MD, E->getSelectorStartLoc(),
196 Parent, ParentDC, Roles, Relations, E);
197 }
198 return true;
199 }
200
201 bool VisitObjCPropertyRefExpr(ObjCPropertyRefExpr *E) {
Argyrios Kyrtzidis194b28e2017-03-16 18:25:40 +0000202 if (E->isExplicitProperty()) {
203 SmallVector<SymbolRelation, 2> Relations;
204 SymbolRoleSet Roles = getRolesForRef(E, Relations);
Argyrios Kyrtzidisf4fb85b2016-02-12 23:10:59 +0000205 return IndexCtx.handleReference(E->getExplicitProperty(), E->getLocation(),
Argyrios Kyrtzidis194b28e2017-03-16 18:25:40 +0000206 Parent, ParentDC, Roles, Relations, E);
207 }
Argyrios Kyrtzidisf4fb85b2016-02-12 23:10:59 +0000208
209 // No need to do a handleReference for the objc method, because there will
210 // be a message expr as part of PseudoObjectExpr.
211 return true;
212 }
213
214 bool VisitMSPropertyRefExpr(MSPropertyRefExpr *E) {
215 return IndexCtx.handleReference(E->getPropertyDecl(), E->getMemberLoc(),
216 Parent, ParentDC, SymbolRoleSet(), {}, E);
217 }
218
219 bool VisitObjCProtocolExpr(ObjCProtocolExpr *E) {
220 return IndexCtx.handleReference(E->getProtocol(), E->getProtocolIdLoc(),
221 Parent, ParentDC, SymbolRoleSet(), {}, E);
222 }
223
Argyrios Kyrtzidisa8b51c12016-02-29 07:56:00 +0000224 bool passObjCLiteralMethodCall(const ObjCMethodDecl *MD, const Expr *E) {
225 SymbolRoleSet Roles{};
226 SmallVector<SymbolRelation, 2> Relations;
227 addCallRole(Roles, Relations);
228 Roles |= (unsigned)SymbolRole::Implicit;
229 return IndexCtx.handleReference(MD, E->getLocStart(),
230 Parent, ParentDC, Roles, Relations, E);
231 }
232
Argyrios Kyrtzidisf4fb85b2016-02-12 23:10:59 +0000233 bool VisitObjCBoxedExpr(ObjCBoxedExpr *E) {
234 if (ObjCMethodDecl *MD = E->getBoxingMethod()) {
Argyrios Kyrtzidisa8b51c12016-02-29 07:56:00 +0000235 return passObjCLiteralMethodCall(MD, E);
Argyrios Kyrtzidisf4fb85b2016-02-12 23:10:59 +0000236 }
237 return true;
238 }
239
240 bool VisitObjCDictionaryLiteral(ObjCDictionaryLiteral *E) {
241 if (ObjCMethodDecl *MD = E->getDictWithObjectsMethod()) {
Argyrios Kyrtzidisa8b51c12016-02-29 07:56:00 +0000242 return passObjCLiteralMethodCall(MD, E);
Argyrios Kyrtzidisf4fb85b2016-02-12 23:10:59 +0000243 }
244 return true;
245 }
246
247 bool VisitObjCArrayLiteral(ObjCArrayLiteral *E) {
248 if (ObjCMethodDecl *MD = E->getArrayWithObjectsMethod()) {
Argyrios Kyrtzidisa8b51c12016-02-29 07:56:00 +0000249 return passObjCLiteralMethodCall(MD, E);
Argyrios Kyrtzidisf4fb85b2016-02-12 23:10:59 +0000250 }
251 return true;
252 }
253
254 bool VisitCXXConstructExpr(CXXConstructExpr *E) {
Argyrios Kyrtzidisa8b51c12016-02-29 07:56:00 +0000255 SymbolRoleSet Roles{};
256 SmallVector<SymbolRelation, 2> Relations;
257 addCallRole(Roles, Relations);
Argyrios Kyrtzidisf4fb85b2016-02-12 23:10:59 +0000258 return IndexCtx.handleReference(E->getConstructor(), E->getLocation(),
Argyrios Kyrtzidisa8b51c12016-02-29 07:56:00 +0000259 Parent, ParentDC, Roles, Relations, E);
Argyrios Kyrtzidisf4fb85b2016-02-12 23:10:59 +0000260 }
261
262 bool TraverseCXXOperatorCallExpr(CXXOperatorCallExpr *E,
263 DataRecursionQueue *Q = nullptr) {
264 if (E->getOperatorLoc().isInvalid())
265 return true; // implicit.
Argyrios Kyrtzidisd7511c82016-03-01 02:46:32 +0000266 return base::TraverseCXXOperatorCallExpr(E, Q);
Argyrios Kyrtzidisf4fb85b2016-02-12 23:10:59 +0000267 }
268
269 bool VisitDeclStmt(DeclStmt *S) {
270 if (IndexCtx.shouldIndexFunctionLocalSymbols()) {
271 IndexCtx.indexDeclGroupRef(S->getDeclGroup());
272 return true;
273 }
274
275 DeclGroupRef DG = S->getDeclGroup();
276 for (DeclGroupRef::iterator I = DG.begin(), E = DG.end(); I != E; ++I) {
277 const Decl *D = *I;
278 if (!D)
279 continue;
Argyrios Kyrtzidis6d1a15b22017-02-26 05:37:56 +0000280 if (!isFunctionLocalSymbol(D))
Argyrios Kyrtzidisf4fb85b2016-02-12 23:10:59 +0000281 IndexCtx.indexTopLevelDecl(D);
282 }
283
284 return true;
285 }
286
Martin Bohmed5f94a62016-08-17 14:59:53 +0000287 bool TraverseLambdaCapture(LambdaExpr *LE, const LambdaCapture *C,
288 Expr *Init) {
Argyrios Kyrtzidisf4fb85b2016-02-12 23:10:59 +0000289 if (C->capturesThis() || C->capturesVLAType())
290 return true;
291
292 if (C->capturesVariable() && IndexCtx.shouldIndexFunctionLocalSymbols())
293 return IndexCtx.handleReference(C->getCapturedVar(), C->getLocation(),
294 Parent, ParentDC, SymbolRoleSet());
295
296 // FIXME: Lambda init-captures.
297 return true;
298 }
299
300 // RecursiveASTVisitor visits both syntactic and semantic forms, duplicating
301 // the things that we visit. Make sure to only visit the semantic form.
302 // Also visit things that are in the syntactic form but not the semantic one,
303 // for example the indices in DesignatedInitExprs.
304 bool TraverseInitListExpr(InitListExpr *S, DataRecursionQueue *Q = nullptr) {
Argyrios Kyrtzidisf4fb85b2016-02-12 23:10:59 +0000305 auto visitForm = [&](InitListExpr *Form) {
306 for (Stmt *SubStmt : Form->children()) {
Argyrios Kyrtzidisd7511c82016-03-01 02:46:32 +0000307 if (!TraverseStmt(SubStmt, Q))
Argyrios Kyrtzidisf4fb85b2016-02-12 23:10:59 +0000308 return false;
309 }
310 return true;
311 };
312
Argyrios Kyrtzidis4db30af2016-11-01 04:29:39 +0000313 auto visitSyntacticDesignatedInitExpr = [&](DesignatedInitExpr *E) -> bool {
314 for (DesignatedInitExpr::Designator &D : llvm::reverse(E->designators())) {
315 if (D.isFieldDesignator())
316 return IndexCtx.handleReference(D.getField(), D.getFieldLoc(),
317 Parent, ParentDC, SymbolRoleSet(),
318 {}, E);
319 }
320 return true;
321 };
322
Argyrios Kyrtzidisf4fb85b2016-02-12 23:10:59 +0000323 InitListExpr *SemaForm = S->isSemanticForm() ? S : S->getSemanticForm();
324 InitListExpr *SyntaxForm = S->isSemanticForm() ? S->getSyntacticForm() : S;
325
326 if (SemaForm) {
327 // Visit things present in syntactic form but not the semantic form.
328 if (SyntaxForm) {
Argyrios Kyrtzidis4db30af2016-11-01 04:29:39 +0000329 for (Expr *init : SyntaxForm->inits()) {
330 if (auto *DIE = dyn_cast<DesignatedInitExpr>(init))
331 visitSyntacticDesignatedInitExpr(DIE);
332 }
Argyrios Kyrtzidisf4fb85b2016-02-12 23:10:59 +0000333 }
334 return visitForm(SemaForm);
335 }
336
337 // No semantic, try the syntactic.
338 if (SyntaxForm) {
339 return visitForm(SyntaxForm);
340 }
341
342 return true;
343 }
344};
345
346} // anonymous namespace
347
348void IndexingContext::indexBody(const Stmt *S, const NamedDecl *Parent,
349 const DeclContext *DC) {
350 if (!S)
351 return;
352
353 if (!DC)
354 DC = Parent->getLexicalDeclContext();
355 BodyIndexer(*this, Parent, DC).TraverseStmt(const_cast<Stmt*>(S));
356}