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 
26   Stmt *getParentStmt() const {
27     return StmtStack.size() < 2 ? nullptr : StmtStack.end()[-2];
28   }
29 public:
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 
36   bool dataTraverseStmtPre(Stmt *S) {
37     StmtStack.push_back(S);
38     return true;
39   }
40 
41   bool dataTraverseStmtPost(Stmt *S) {
42     assert(StmtStack.back() == S);
43     StmtStack.pop_back();
44     return true;
45   }
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) {
95         addCallRole(Roles, Relations);
96         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 
127   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 
136   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) {
154     for (DesignatedInitExpr::Designator &D : llvm::reverse(E->designators())) {
155       if (D.isFieldDesignator() && D.getField())
156         return IndexCtx.handleReference(D.getField(), D.getFieldLoc(), Parent,
157                                         ParentDC, SymbolRoleSet(), {}, E);
158     }
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()) {
182       SymbolRoleSet Roles{};
183       SmallVector<SymbolRelation, 2> Relations;
184       addCallRole(Roles, Relations);
185       Stmt *Containing = getParentStmt();
186       if (E->isImplicit() || (Containing && isa<PseudoObjectExpr>(Containing)))
187         Roles |= (unsigned)SymbolRole::Implicit;
188 
189       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) {
202     if (E->isExplicitProperty()) {
203       SmallVector<SymbolRelation, 2> Relations;
204       SymbolRoleSet Roles = getRolesForRef(E, Relations);
205       return IndexCtx.handleReference(E->getExplicitProperty(), E->getLocation(),
206                                       Parent, ParentDC, Roles, Relations, E);
207     }
208 
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 
224   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 
233   bool VisitObjCBoxedExpr(ObjCBoxedExpr *E) {
234     if (ObjCMethodDecl *MD = E->getBoxingMethod()) {
235       return passObjCLiteralMethodCall(MD, E);
236     }
237     return true;
238   }
239 
240   bool VisitObjCDictionaryLiteral(ObjCDictionaryLiteral *E) {
241     if (ObjCMethodDecl *MD = E->getDictWithObjectsMethod()) {
242       return passObjCLiteralMethodCall(MD, E);
243     }
244     return true;
245   }
246 
247   bool VisitObjCArrayLiteral(ObjCArrayLiteral *E) {
248     if (ObjCMethodDecl *MD = E->getArrayWithObjectsMethod()) {
249       return passObjCLiteralMethodCall(MD, E);
250     }
251     return true;
252   }
253 
254   bool VisitCXXConstructExpr(CXXConstructExpr *E) {
255     SymbolRoleSet Roles{};
256     SmallVector<SymbolRelation, 2> Relations;
257     addCallRole(Roles, Relations);
258     return IndexCtx.handleReference(E->getConstructor(), E->getLocation(),
259                                     Parent, ParentDC, Roles, Relations, E);
260   }
261 
262   bool TraverseCXXOperatorCallExpr(CXXOperatorCallExpr *E,
263                                    DataRecursionQueue *Q = nullptr) {
264     if (E->getOperatorLoc().isInvalid())
265       return true; // implicit.
266     return base::TraverseCXXOperatorCallExpr(E, Q);
267   }
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;
280       if (!isFunctionLocalSymbol(D))
281         IndexCtx.indexTopLevelDecl(D);
282     }
283 
284     return true;
285   }
286 
287   bool TraverseLambdaCapture(LambdaExpr *LE, const LambdaCapture *C,
288                              Expr *Init) {
289     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) {
305     auto visitForm = [&](InitListExpr *Form) {
306       for (Stmt *SubStmt : Form->children()) {
307         if (!TraverseStmt(SubStmt, Q))
308           return false;
309       }
310       return true;
311     };
312 
313     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 
323     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) {
329         for (Expr *init : SyntaxForm->inits()) {
330           if (auto *DIE = dyn_cast<DesignatedInitExpr>(init))
331             visitSyntacticDesignatedInitExpr(DIE);
332         }
333       }
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 
348 void 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 }
357