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