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 #include "clang/AST/ASTLambda.h"
13 
14 using namespace clang;
15 using namespace clang::index;
16 
17 namespace {
18 
19 class BodyIndexer : public RecursiveASTVisitor<BodyIndexer> {
20   IndexingContext &IndexCtx;
21   const NamedDecl *Parent;
22   const DeclContext *ParentDC;
23   SmallVector<Stmt*, 16> StmtStack;
24 
25   typedef RecursiveASTVisitor<BodyIndexer> base;
26 
27   Stmt *getParentStmt() const {
28     return StmtStack.size() < 2 ? nullptr : StmtStack.end()[-2];
29   }
30 public:
31   BodyIndexer(IndexingContext &indexCtx,
32               const NamedDecl *Parent, const DeclContext *DC)
33     : IndexCtx(indexCtx), Parent(Parent), ParentDC(DC) { }
34 
35   bool shouldWalkTypesOfTypeLocs() const { return false; }
36 
37   bool dataTraverseStmtPre(Stmt *S) {
38     StmtStack.push_back(S);
39     return true;
40   }
41 
42   bool dataTraverseStmtPost(Stmt *S) {
43     assert(StmtStack.back() == S);
44     StmtStack.pop_back();
45     return true;
46   }
47 
48   bool TraverseTypeLoc(TypeLoc TL) {
49     IndexCtx.indexTypeLoc(TL, Parent, ParentDC);
50     return true;
51   }
52 
53   bool TraverseNestedNameSpecifierLoc(NestedNameSpecifierLoc NNS) {
54     IndexCtx.indexNestedNameSpecifierLoc(NNS, Parent, ParentDC);
55     return true;
56   }
57 
58   SymbolRoleSet getRolesForRef(const Expr *E,
59                                SmallVectorImpl<SymbolRelation> &Relations) {
60     SymbolRoleSet Roles{};
61     assert(!StmtStack.empty() && E == StmtStack.back());
62     if (StmtStack.size() == 1)
63       return Roles;
64     auto It = StmtStack.end()-2;
65     while (isa<CastExpr>(*It) || isa<ParenExpr>(*It)) {
66       if (auto ICE = dyn_cast<ImplicitCastExpr>(*It)) {
67         if (ICE->getCastKind() == CK_LValueToRValue)
68           Roles |= (unsigned)(unsigned)SymbolRole::Read;
69       }
70       if (It == StmtStack.begin())
71         break;
72       --It;
73     }
74     const Stmt *Parent = *It;
75 
76     if (auto BO = dyn_cast<BinaryOperator>(Parent)) {
77       if (BO->getOpcode() == BO_Assign && BO->getLHS()->IgnoreParenCasts() == E)
78         Roles |= (unsigned)SymbolRole::Write;
79 
80     } else if (auto UO = dyn_cast<UnaryOperator>(Parent)) {
81       if (UO->isIncrementDecrementOp()) {
82         Roles |= (unsigned)SymbolRole::Read;
83         Roles |= (unsigned)SymbolRole::Write;
84       } else if (UO->getOpcode() == UO_AddrOf) {
85         Roles |= (unsigned)SymbolRole::AddressOf;
86       }
87 
88     } else if (auto CA = dyn_cast<CompoundAssignOperator>(Parent)) {
89       if (CA->getLHS()->IgnoreParenCasts() == E) {
90         Roles |= (unsigned)SymbolRole::Read;
91         Roles |= (unsigned)SymbolRole::Write;
92       }
93 
94     } else if (auto CE = dyn_cast<CallExpr>(Parent)) {
95       if (CE->getCallee()->IgnoreParenCasts() == E) {
96         addCallRole(Roles, Relations);
97         if (auto *ME = dyn_cast<MemberExpr>(E)) {
98           if (auto *CXXMD = dyn_cast_or_null<CXXMethodDecl>(ME->getMemberDecl()))
99             if (CXXMD->isVirtual() && !ME->hasQualifier()) {
100               Roles |= (unsigned)SymbolRole::Dynamic;
101               auto BaseTy = ME->getBase()->IgnoreImpCasts()->getType();
102               if (!BaseTy.isNull())
103                 if (auto *CXXRD = BaseTy->getPointeeCXXRecordDecl())
104                   Relations.emplace_back((unsigned)SymbolRole::RelationReceivedBy,
105                                          CXXRD);
106             }
107         }
108       } else if (auto CXXOp = dyn_cast<CXXOperatorCallExpr>(CE)) {
109         if (CXXOp->getNumArgs() > 0 && CXXOp->getArg(0)->IgnoreParenCasts() == E) {
110           OverloadedOperatorKind Op = CXXOp->getOperator();
111           if (Op == OO_Equal) {
112             Roles |= (unsigned)SymbolRole::Write;
113           } else if ((Op >= OO_PlusEqual && Op <= OO_PipeEqual) ||
114                      Op == OO_LessLessEqual || Op == OO_GreaterGreaterEqual ||
115                      Op == OO_PlusPlus || Op == OO_MinusMinus) {
116             Roles |= (unsigned)SymbolRole::Read;
117             Roles |= (unsigned)SymbolRole::Write;
118           } else if (Op == OO_Amp) {
119             Roles |= (unsigned)SymbolRole::AddressOf;
120           }
121         }
122       }
123     }
124 
125     return Roles;
126   }
127 
128   void addCallRole(SymbolRoleSet &Roles,
129                    SmallVectorImpl<SymbolRelation> &Relations) {
130     Roles |= (unsigned)SymbolRole::Call;
131     if (auto *FD = dyn_cast<FunctionDecl>(ParentDC))
132       Relations.emplace_back((unsigned)SymbolRole::RelationCalledBy, FD);
133     else if (auto *MD = dyn_cast<ObjCMethodDecl>(ParentDC))
134       Relations.emplace_back((unsigned)SymbolRole::RelationCalledBy, MD);
135   }
136 
137   bool VisitDeclRefExpr(DeclRefExpr *E) {
138     SmallVector<SymbolRelation, 4> Relations;
139     SymbolRoleSet Roles = getRolesForRef(E, Relations);
140     return IndexCtx.handleReference(E->getDecl(), E->getLocation(),
141                                     Parent, ParentDC, Roles, Relations, E);
142   }
143 
144   bool VisitMemberExpr(MemberExpr *E) {
145     SourceLocation Loc = E->getMemberLoc();
146     if (Loc.isInvalid())
147       Loc = E->getBeginLoc();
148     SmallVector<SymbolRelation, 4> Relations;
149     SymbolRoleSet Roles = getRolesForRef(E, Relations);
150     return IndexCtx.handleReference(E->getMemberDecl(), Loc,
151                                     Parent, ParentDC, Roles, Relations, E);
152   }
153 
154   bool indexDependentReference(
155       const Expr *E, const Type *T, const DeclarationNameInfo &NameInfo,
156       llvm::function_ref<bool(const NamedDecl *ND)> Filter) {
157     if (!T)
158       return true;
159     const TemplateSpecializationType *TST =
160         T->getAs<TemplateSpecializationType>();
161     if (!TST)
162       return true;
163     TemplateName TN = TST->getTemplateName();
164     const ClassTemplateDecl *TD =
165         dyn_cast_or_null<ClassTemplateDecl>(TN.getAsTemplateDecl());
166     if (!TD)
167       return true;
168     CXXRecordDecl *RD = TD->getTemplatedDecl();
169     if (!RD->hasDefinition())
170       return true;
171     RD = RD->getDefinition();
172     std::vector<const NamedDecl *> Symbols =
173         RD->lookupDependentName(NameInfo.getName(), Filter);
174     // FIXME: Improve overload handling.
175     if (Symbols.size() != 1)
176       return true;
177     SourceLocation Loc = NameInfo.getLoc();
178     if (Loc.isInvalid())
179       Loc = E->getBeginLoc();
180     SmallVector<SymbolRelation, 4> Relations;
181     SymbolRoleSet Roles = getRolesForRef(E, Relations);
182     return IndexCtx.handleReference(Symbols[0], Loc, Parent, ParentDC, Roles,
183                                     Relations, E);
184   }
185 
186   bool VisitCXXDependentScopeMemberExpr(CXXDependentScopeMemberExpr *E) {
187     const DeclarationNameInfo &Info = E->getMemberNameInfo();
188     return indexDependentReference(
189         E, E->getBaseType().getTypePtrOrNull(), Info,
190         [](const NamedDecl *D) { return D->isCXXInstanceMember(); });
191   }
192 
193   bool VisitDependentScopeDeclRefExpr(DependentScopeDeclRefExpr *E) {
194     const DeclarationNameInfo &Info = E->getNameInfo();
195     const NestedNameSpecifier *NNS = E->getQualifier();
196     return indexDependentReference(
197         E, NNS->getAsType(), Info,
198         [](const NamedDecl *D) { return !D->isCXXInstanceMember(); });
199   }
200 
201   bool VisitDesignatedInitExpr(DesignatedInitExpr *E) {
202     for (DesignatedInitExpr::Designator &D : llvm::reverse(E->designators())) {
203       if (D.isFieldDesignator() && D.getField())
204         return IndexCtx.handleReference(D.getField(), D.getFieldLoc(), Parent,
205                                         ParentDC, SymbolRoleSet(), {}, E);
206     }
207     return true;
208   }
209 
210   bool VisitObjCIvarRefExpr(ObjCIvarRefExpr *E) {
211     SmallVector<SymbolRelation, 4> Relations;
212     SymbolRoleSet Roles = getRolesForRef(E, Relations);
213     return IndexCtx.handleReference(E->getDecl(), E->getLocation(),
214                                     Parent, ParentDC, Roles, Relations, E);
215   }
216 
217   bool VisitObjCMessageExpr(ObjCMessageExpr *E) {
218     auto isDynamic = [](const ObjCMessageExpr *MsgE)->bool {
219       if (MsgE->getReceiverKind() != ObjCMessageExpr::Instance)
220         return false;
221       if (auto *RecE = dyn_cast<ObjCMessageExpr>(
222               MsgE->getInstanceReceiver()->IgnoreParenCasts())) {
223         if (RecE->getMethodFamily() == OMF_alloc)
224           return false;
225       }
226       return true;
227     };
228 
229     if (ObjCMethodDecl *MD = E->getMethodDecl()) {
230       SymbolRoleSet Roles{};
231       SmallVector<SymbolRelation, 2> Relations;
232       addCallRole(Roles, Relations);
233       Stmt *Containing = getParentStmt();
234 
235       auto IsImplicitProperty = [](const PseudoObjectExpr *POE) -> bool {
236         const auto *E = POE->getSyntacticForm();
237         if (const auto *BinOp = dyn_cast<BinaryOperator>(E))
238           E = BinOp->getLHS();
239         const auto *PRE = dyn_cast<ObjCPropertyRefExpr>(E);
240         if (!PRE)
241           return false;
242         if (PRE->isExplicitProperty())
243           return false;
244         if (const ObjCMethodDecl *Getter = PRE->getImplicitPropertyGetter()) {
245           // Class properties that are explicitly defined using @property
246           // declarations are represented implicitly as there is no ivar for
247           // class properties.
248           if (Getter->isClassMethod() &&
249               Getter->getCanonicalDecl()->findPropertyDecl())
250             return false;
251         }
252         return true;
253       };
254       bool IsPropCall = Containing && isa<PseudoObjectExpr>(Containing);
255       // Implicit property message sends are not 'implicit'.
256       if ((E->isImplicit() || IsPropCall) &&
257           !(IsPropCall &&
258             IsImplicitProperty(cast<PseudoObjectExpr>(Containing))))
259         Roles |= (unsigned)SymbolRole::Implicit;
260 
261       if (isDynamic(E)) {
262         Roles |= (unsigned)SymbolRole::Dynamic;
263 
264         auto addReceivers = [&](const ObjCObjectType *Ty) {
265           if (!Ty)
266             return;
267           if (const auto *clsD = Ty->getInterface()) {
268             Relations.emplace_back((unsigned)SymbolRole::RelationReceivedBy,
269                                    clsD);
270           }
271           for (const auto *protD : Ty->quals()) {
272             Relations.emplace_back((unsigned)SymbolRole::RelationReceivedBy,
273                                    protD);
274           }
275         };
276         QualType recT = E->getReceiverType();
277         if (const auto *Ptr = recT->getAs<ObjCObjectPointerType>())
278           addReceivers(Ptr->getObjectType());
279         else
280           addReceivers(recT->getAs<ObjCObjectType>());
281       }
282 
283       return IndexCtx.handleReference(MD, E->getSelectorStartLoc(),
284                                       Parent, ParentDC, Roles, Relations, E);
285     }
286     return true;
287   }
288 
289   bool VisitObjCPropertyRefExpr(ObjCPropertyRefExpr *E) {
290     if (E->isClassReceiver())
291       IndexCtx.handleReference(E->getClassReceiver(), E->getReceiverLocation(),
292                                Parent, ParentDC);
293     if (E->isExplicitProperty()) {
294       SmallVector<SymbolRelation, 2> Relations;
295       SymbolRoleSet Roles = getRolesForRef(E, Relations);
296       return IndexCtx.handleReference(E->getExplicitProperty(), E->getLocation(),
297                                       Parent, ParentDC, Roles, Relations, E);
298     } else if (const ObjCMethodDecl *Getter = E->getImplicitPropertyGetter()) {
299       // Class properties that are explicitly defined using @property
300       // declarations are represented implicitly as there is no ivar for class
301       // properties.
302       if (Getter->isClassMethod()) {
303         if (const auto *PD = Getter->getCanonicalDecl()->findPropertyDecl()) {
304           SmallVector<SymbolRelation, 2> Relations;
305           SymbolRoleSet Roles = getRolesForRef(E, Relations);
306           return IndexCtx.handleReference(PD, E->getLocation(), Parent,
307                                           ParentDC, Roles, Relations, E);
308         }
309       }
310     }
311 
312     // No need to do a handleReference for the objc method, because there will
313     // be a message expr as part of PseudoObjectExpr.
314     return true;
315   }
316 
317   bool VisitMSPropertyRefExpr(MSPropertyRefExpr *E) {
318     return IndexCtx.handleReference(E->getPropertyDecl(), E->getMemberLoc(),
319                                     Parent, ParentDC, SymbolRoleSet(), {}, E);
320   }
321 
322   bool VisitObjCProtocolExpr(ObjCProtocolExpr *E) {
323     return IndexCtx.handleReference(E->getProtocol(), E->getProtocolIdLoc(),
324                                     Parent, ParentDC, SymbolRoleSet(), {}, E);
325   }
326 
327   bool passObjCLiteralMethodCall(const ObjCMethodDecl *MD, const Expr *E) {
328     SymbolRoleSet Roles{};
329     SmallVector<SymbolRelation, 2> Relations;
330     addCallRole(Roles, Relations);
331     Roles |= (unsigned)SymbolRole::Implicit;
332     return IndexCtx.handleReference(MD, E->getBeginLoc(), Parent, ParentDC,
333                                     Roles, Relations, E);
334   }
335 
336   bool VisitObjCBoxedExpr(ObjCBoxedExpr *E) {
337     if (ObjCMethodDecl *MD = E->getBoxingMethod()) {
338       return passObjCLiteralMethodCall(MD, E);
339     }
340     return true;
341   }
342 
343   bool VisitObjCDictionaryLiteral(ObjCDictionaryLiteral *E) {
344     if (ObjCMethodDecl *MD = E->getDictWithObjectsMethod()) {
345       return passObjCLiteralMethodCall(MD, E);
346     }
347     return true;
348   }
349 
350   bool VisitObjCArrayLiteral(ObjCArrayLiteral *E) {
351     if (ObjCMethodDecl *MD = E->getArrayWithObjectsMethod()) {
352       return passObjCLiteralMethodCall(MD, E);
353     }
354     return true;
355   }
356 
357   bool VisitCXXConstructExpr(CXXConstructExpr *E) {
358     SymbolRoleSet Roles{};
359     SmallVector<SymbolRelation, 2> Relations;
360     addCallRole(Roles, Relations);
361     return IndexCtx.handleReference(E->getConstructor(), E->getLocation(),
362                                     Parent, ParentDC, Roles, Relations, E);
363   }
364 
365   bool TraverseCXXOperatorCallExpr(CXXOperatorCallExpr *E,
366                                    DataRecursionQueue *Q = nullptr) {
367     if (E->getOperatorLoc().isInvalid())
368       return true; // implicit.
369     return base::TraverseCXXOperatorCallExpr(E, Q);
370   }
371 
372   bool VisitDeclStmt(DeclStmt *S) {
373     if (IndexCtx.shouldIndexFunctionLocalSymbols()) {
374       IndexCtx.indexDeclGroupRef(S->getDeclGroup());
375       return true;
376     }
377 
378     DeclGroupRef DG = S->getDeclGroup();
379     for (DeclGroupRef::iterator I = DG.begin(), E = DG.end(); I != E; ++I) {
380       const Decl *D = *I;
381       if (!D)
382         continue;
383       if (!isFunctionLocalSymbol(D))
384         IndexCtx.indexTopLevelDecl(D);
385     }
386 
387     return true;
388   }
389 
390   bool TraverseLambdaCapture(LambdaExpr *LE, const LambdaCapture *C,
391                              Expr *Init) {
392     if (C->capturesThis() || C->capturesVLAType())
393       return true;
394 
395     if (C->capturesVariable() && IndexCtx.shouldIndexFunctionLocalSymbols())
396       return IndexCtx.handleReference(C->getCapturedVar(), C->getLocation(),
397                                       Parent, ParentDC, SymbolRoleSet());
398 
399     // FIXME: Lambda init-captures.
400     return true;
401   }
402 
403   // RecursiveASTVisitor visits both syntactic and semantic forms, duplicating
404   // the things that we visit. Make sure to only visit the semantic form.
405   // Also visit things that are in the syntactic form but not the semantic one,
406   // for example the indices in DesignatedInitExprs.
407   bool TraverseInitListExpr(InitListExpr *S, DataRecursionQueue *Q = nullptr) {
408     auto visitForm = [&](InitListExpr *Form) {
409       for (Stmt *SubStmt : Form->children()) {
410         if (!TraverseStmt(SubStmt, Q))
411           return false;
412       }
413       return true;
414     };
415 
416     auto visitSyntacticDesignatedInitExpr = [&](DesignatedInitExpr *E) -> bool {
417       for (DesignatedInitExpr::Designator &D : llvm::reverse(E->designators())) {
418         if (D.isFieldDesignator())
419           return IndexCtx.handleReference(D.getField(), D.getFieldLoc(),
420                                           Parent, ParentDC, SymbolRoleSet(),
421                                           {}, E);
422       }
423       return true;
424     };
425 
426     InitListExpr *SemaForm = S->isSemanticForm() ? S : S->getSemanticForm();
427     InitListExpr *SyntaxForm = S->isSemanticForm() ? S->getSyntacticForm() : S;
428 
429     if (SemaForm) {
430       // Visit things present in syntactic form but not the semantic form.
431       if (SyntaxForm) {
432         for (Expr *init : SyntaxForm->inits()) {
433           if (auto *DIE = dyn_cast<DesignatedInitExpr>(init))
434             visitSyntacticDesignatedInitExpr(DIE);
435         }
436       }
437       return visitForm(SemaForm);
438     }
439 
440     // No semantic, try the syntactic.
441     if (SyntaxForm) {
442       return visitForm(SyntaxForm);
443     }
444 
445     return true;
446   }
447 
448   bool VisitOffsetOfExpr(OffsetOfExpr *S) {
449     for (unsigned I = 0, E = S->getNumComponents(); I != E; ++I) {
450       const OffsetOfNode &Component = S->getComponent(I);
451       if (Component.getKind() == OffsetOfNode::Field)
452         IndexCtx.handleReference(Component.getField(), Component.getEndLoc(),
453                                  Parent, ParentDC, SymbolRoleSet(), {});
454       // FIXME: Try to resolve dependent field references.
455     }
456     return true;
457   }
458 
459   bool VisitParmVarDecl(ParmVarDecl* D) {
460     // Index the parameters of lambda expression.
461     if (IndexCtx.shouldIndexFunctionLocalSymbols()) {
462       const auto *DC = D->getDeclContext();
463       if (DC && isLambdaCallOperator(DC))
464         IndexCtx.handleDecl(D);
465     }
466     return true;
467   }
468 };
469 
470 } // anonymous namespace
471 
472 void IndexingContext::indexBody(const Stmt *S, const NamedDecl *Parent,
473                                 const DeclContext *DC) {
474   if (!S)
475     return;
476 
477   if (!DC)
478     DC = Parent->getLexicalDeclContext();
479   BodyIndexer(*this, Parent, DC).TraverseStmt(const_cast<Stmt*>(S));
480 }
481