1 //===- 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
13 using namespace clang;
14 using namespace clang::index;
15
16 namespace {
17
18 class 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;
25 public:
BodyIndexer(IndexingContext & indexCtx,const NamedDecl * Parent,const DeclContext * DC)26 BodyIndexer(IndexingContext &indexCtx,
27 const NamedDecl *Parent, const DeclContext *DC)
28 : IndexCtx(indexCtx), Parent(Parent), ParentDC(DC) { }
29
shouldWalkTypesOfTypeLocs() const30 bool shouldWalkTypesOfTypeLocs() const { return false; }
31
dataTraverseStmtPre(Stmt * S)32 bool dataTraverseStmtPre(Stmt *S) {
33 StmtStack.push_back(S);
34 return true;
35 }
36
dataTraverseStmtPost(Stmt * S)37 bool dataTraverseStmtPost(Stmt *S) {
38 assert(StmtStack.back() == S);
39 StmtStack.pop_back();
40 return true;
41 }
42
TraverseTypeLoc(TypeLoc TL)43 bool TraverseTypeLoc(TypeLoc TL) {
44 IndexCtx.indexTypeLoc(TL, Parent, ParentDC);
45 return true;
46 }
47
TraverseNestedNameSpecifierLoc(NestedNameSpecifierLoc NNS)48 bool TraverseNestedNameSpecifierLoc(NestedNameSpecifierLoc NNS) {
49 IndexCtx.indexNestedNameSpecifierLoc(NNS, Parent, ParentDC);
50 return true;
51 }
52
getRolesForRef(const Expr * E,SmallVectorImpl<SymbolRelation> & Relations)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) {
91 addCallRole(Roles, Relations);
92 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
addCallRole(SymbolRoleSet & Roles,SmallVectorImpl<SymbolRelation> & Relations)123 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
VisitDeclRefExpr(DeclRefExpr * E)132 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
VisitMemberExpr(MemberExpr * E)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
VisitDesignatedInitExpr(DesignatedInitExpr * E)149 bool VisitDesignatedInitExpr(DesignatedInitExpr *E) {
150 for (DesignatedInitExpr::Designator &D : llvm::reverse(E->designators())) {
151 if (D.isFieldDesignator())
152 return IndexCtx.handleReference(D.getField(), D.getFieldLoc(), Parent,
153 ParentDC, SymbolRoleSet(), {}, E);
154 }
155 return true;
156 }
157
VisitObjCIvarRefExpr(ObjCIvarRefExpr * E)158 bool VisitObjCIvarRefExpr(ObjCIvarRefExpr *E) {
159 SmallVector<SymbolRelation, 4> Relations;
160 SymbolRoleSet Roles = getRolesForRef(E, Relations);
161 return IndexCtx.handleReference(E->getDecl(), E->getLocation(),
162 Parent, ParentDC, Roles, Relations, E);
163 }
164
VisitObjCMessageExpr(ObjCMessageExpr * E)165 bool VisitObjCMessageExpr(ObjCMessageExpr *E) {
166 auto isDynamic = [](const ObjCMessageExpr *MsgE)->bool {
167 if (MsgE->getReceiverKind() != ObjCMessageExpr::Instance)
168 return false;
169 if (auto *RecE = dyn_cast<ObjCMessageExpr>(
170 MsgE->getInstanceReceiver()->IgnoreParenCasts())) {
171 if (RecE->getMethodFamily() == OMF_alloc)
172 return false;
173 }
174 return true;
175 };
176
177 if (ObjCMethodDecl *MD = E->getMethodDecl()) {
178 SymbolRoleSet Roles{};
179 SmallVector<SymbolRelation, 2> Relations;
180 addCallRole(Roles, Relations);
181 if (E->isImplicit())
182 Roles |= (unsigned)SymbolRole::Implicit;
183
184 if (isDynamic(E)) {
185 Roles |= (unsigned)SymbolRole::Dynamic;
186 if (auto *RecD = E->getReceiverInterface())
187 Relations.emplace_back((unsigned)SymbolRole::RelationReceivedBy, RecD);
188 }
189
190 return IndexCtx.handleReference(MD, E->getSelectorStartLoc(),
191 Parent, ParentDC, Roles, Relations, E);
192 }
193 return true;
194 }
195
VisitObjCPropertyRefExpr(ObjCPropertyRefExpr * E)196 bool VisitObjCPropertyRefExpr(ObjCPropertyRefExpr *E) {
197 if (E->isExplicitProperty())
198 return IndexCtx.handleReference(E->getExplicitProperty(), E->getLocation(),
199 Parent, ParentDC, SymbolRoleSet(), {}, E);
200
201 // No need to do a handleReference for the objc method, because there will
202 // be a message expr as part of PseudoObjectExpr.
203 return true;
204 }
205
VisitMSPropertyRefExpr(MSPropertyRefExpr * E)206 bool VisitMSPropertyRefExpr(MSPropertyRefExpr *E) {
207 return IndexCtx.handleReference(E->getPropertyDecl(), E->getMemberLoc(),
208 Parent, ParentDC, SymbolRoleSet(), {}, E);
209 }
210
VisitObjCProtocolExpr(ObjCProtocolExpr * E)211 bool VisitObjCProtocolExpr(ObjCProtocolExpr *E) {
212 return IndexCtx.handleReference(E->getProtocol(), E->getProtocolIdLoc(),
213 Parent, ParentDC, SymbolRoleSet(), {}, E);
214 }
215
passObjCLiteralMethodCall(const ObjCMethodDecl * MD,const Expr * E)216 bool passObjCLiteralMethodCall(const ObjCMethodDecl *MD, const Expr *E) {
217 SymbolRoleSet Roles{};
218 SmallVector<SymbolRelation, 2> Relations;
219 addCallRole(Roles, Relations);
220 Roles |= (unsigned)SymbolRole::Implicit;
221 return IndexCtx.handleReference(MD, E->getLocStart(),
222 Parent, ParentDC, Roles, Relations, E);
223 }
224
VisitObjCBoxedExpr(ObjCBoxedExpr * E)225 bool VisitObjCBoxedExpr(ObjCBoxedExpr *E) {
226 if (ObjCMethodDecl *MD = E->getBoxingMethod()) {
227 return passObjCLiteralMethodCall(MD, E);
228 }
229 return true;
230 }
231
VisitObjCDictionaryLiteral(ObjCDictionaryLiteral * E)232 bool VisitObjCDictionaryLiteral(ObjCDictionaryLiteral *E) {
233 if (ObjCMethodDecl *MD = E->getDictWithObjectsMethod()) {
234 return passObjCLiteralMethodCall(MD, E);
235 }
236 return true;
237 }
238
VisitObjCArrayLiteral(ObjCArrayLiteral * E)239 bool VisitObjCArrayLiteral(ObjCArrayLiteral *E) {
240 if (ObjCMethodDecl *MD = E->getArrayWithObjectsMethod()) {
241 return passObjCLiteralMethodCall(MD, E);
242 }
243 return true;
244 }
245
VisitCXXConstructExpr(CXXConstructExpr * E)246 bool VisitCXXConstructExpr(CXXConstructExpr *E) {
247 SymbolRoleSet Roles{};
248 SmallVector<SymbolRelation, 2> Relations;
249 addCallRole(Roles, Relations);
250 return IndexCtx.handleReference(E->getConstructor(), E->getLocation(),
251 Parent, ParentDC, Roles, Relations, E);
252 }
253
TraverseCXXOperatorCallExpr(CXXOperatorCallExpr * E,DataRecursionQueue * Q=nullptr)254 bool TraverseCXXOperatorCallExpr(CXXOperatorCallExpr *E,
255 DataRecursionQueue *Q = nullptr) {
256 if (E->getOperatorLoc().isInvalid())
257 return true; // implicit.
258 return base::TraverseCXXOperatorCallExpr(E, Q);
259 }
260
VisitDeclStmt(DeclStmt * S)261 bool VisitDeclStmt(DeclStmt *S) {
262 if (IndexCtx.shouldIndexFunctionLocalSymbols()) {
263 IndexCtx.indexDeclGroupRef(S->getDeclGroup());
264 return true;
265 }
266
267 DeclGroupRef DG = S->getDeclGroup();
268 for (DeclGroupRef::iterator I = DG.begin(), E = DG.end(); I != E; ++I) {
269 const Decl *D = *I;
270 if (!D)
271 continue;
272 if (!IndexCtx.isFunctionLocalDecl(D))
273 IndexCtx.indexTopLevelDecl(D);
274 }
275
276 return true;
277 }
278
TraverseLambdaCapture(LambdaExpr * LE,const LambdaCapture * C)279 bool TraverseLambdaCapture(LambdaExpr *LE, const LambdaCapture *C) {
280 if (C->capturesThis() || C->capturesVLAType())
281 return true;
282
283 if (C->capturesVariable() && IndexCtx.shouldIndexFunctionLocalSymbols())
284 return IndexCtx.handleReference(C->getCapturedVar(), C->getLocation(),
285 Parent, ParentDC, SymbolRoleSet());
286
287 // FIXME: Lambda init-captures.
288 return true;
289 }
290
291 // RecursiveASTVisitor visits both syntactic and semantic forms, duplicating
292 // the things that we visit. Make sure to only visit the semantic form.
293 // Also visit things that are in the syntactic form but not the semantic one,
294 // for example the indices in DesignatedInitExprs.
TraverseInitListExpr(InitListExpr * S,DataRecursionQueue * Q=nullptr)295 bool TraverseInitListExpr(InitListExpr *S, DataRecursionQueue *Q = nullptr) {
296
297 class SyntacticFormIndexer :
298 public RecursiveASTVisitor<SyntacticFormIndexer> {
299 IndexingContext &IndexCtx;
300 const NamedDecl *Parent;
301 const DeclContext *ParentDC;
302
303 public:
304 SyntacticFormIndexer(IndexingContext &indexCtx,
305 const NamedDecl *Parent, const DeclContext *DC)
306 : IndexCtx(indexCtx), Parent(Parent), ParentDC(DC) { }
307
308 bool shouldWalkTypesOfTypeLocs() const { return false; }
309
310 bool VisitDesignatedInitExpr(DesignatedInitExpr *E) {
311 for (DesignatedInitExpr::Designator &D : llvm::reverse(E->designators())) {
312 if (D.isFieldDesignator())
313 return IndexCtx.handleReference(D.getField(), D.getFieldLoc(),
314 Parent, ParentDC, SymbolRoleSet(),
315 {}, E);
316 }
317 return true;
318 }
319 };
320
321 auto visitForm = [&](InitListExpr *Form) {
322 for (Stmt *SubStmt : Form->children()) {
323 if (!TraverseStmt(SubStmt, Q))
324 return false;
325 }
326 return true;
327 };
328
329 InitListExpr *SemaForm = S->isSemanticForm() ? S : S->getSemanticForm();
330 InitListExpr *SyntaxForm = S->isSemanticForm() ? S->getSyntacticForm() : S;
331
332 if (SemaForm) {
333 // Visit things present in syntactic form but not the semantic form.
334 if (SyntaxForm) {
335 SyntacticFormIndexer(IndexCtx, Parent, ParentDC).TraverseStmt(SyntaxForm);
336 }
337 return visitForm(SemaForm);
338 }
339
340 // No semantic, try the syntactic.
341 if (SyntaxForm) {
342 return visitForm(SyntaxForm);
343 }
344
345 return true;
346 }
347 };
348
349 } // anonymous namespace
350
indexBody(const Stmt * S,const NamedDecl * Parent,const DeclContext * DC)351 void IndexingContext::indexBody(const Stmt *S, const NamedDecl *Parent,
352 const DeclContext *DC) {
353 if (!S)
354 return;
355
356 if (!DC)
357 DC = Parent->getLexicalDeclContext();
358 BodyIndexer(*this, Parent, DC).TraverseStmt(const_cast<Stmt*>(S));
359 }
360