IndexBody.cpp revision 344779
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
14using namespace clang;
15using namespace clang::index;
16
17namespace {
18
19class 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  }
30public:
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
472void 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