IndexBody.cpp revision 327952
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
13using namespace clang;
14using namespace clang::index;
15
16namespace {
17
18class 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  }
29public:
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 indexDependentReference(
154      const Expr *E, const Type *T, const DeclarationNameInfo &NameInfo,
155      llvm::function_ref<bool(const NamedDecl *ND)> Filter) {
156    if (!T)
157      return true;
158    const TemplateSpecializationType *TST =
159        T->getAs<TemplateSpecializationType>();
160    if (!TST)
161      return true;
162    TemplateName TN = TST->getTemplateName();
163    const ClassTemplateDecl *TD =
164        dyn_cast_or_null<ClassTemplateDecl>(TN.getAsTemplateDecl());
165    if (!TD)
166      return true;
167    CXXRecordDecl *RD = TD->getTemplatedDecl();
168    if (!RD->hasDefinition())
169      return true;
170    RD = RD->getDefinition();
171    std::vector<const NamedDecl *> Symbols =
172        RD->lookupDependentName(NameInfo.getName(), Filter);
173    // FIXME: Improve overload handling.
174    if (Symbols.size() != 1)
175      return true;
176    SourceLocation Loc = NameInfo.getLoc();
177    if (Loc.isInvalid())
178      Loc = E->getLocStart();
179    SmallVector<SymbolRelation, 4> Relations;
180    SymbolRoleSet Roles = getRolesForRef(E, Relations);
181    return IndexCtx.handleReference(Symbols[0], Loc, Parent, ParentDC, Roles,
182                                    Relations, E);
183  }
184
185  bool VisitCXXDependentScopeMemberExpr(CXXDependentScopeMemberExpr *E) {
186    const DeclarationNameInfo &Info = E->getMemberNameInfo();
187    return indexDependentReference(
188        E, E->getBaseType().getTypePtrOrNull(), Info,
189        [](const NamedDecl *D) { return D->isCXXInstanceMember(); });
190  }
191
192  bool VisitDependentScopeDeclRefExpr(DependentScopeDeclRefExpr *E) {
193    const DeclarationNameInfo &Info = E->getNameInfo();
194    const NestedNameSpecifier *NNS = E->getQualifier();
195    return indexDependentReference(
196        E, NNS->getAsType(), Info,
197        [](const NamedDecl *D) { return !D->isCXXInstanceMember(); });
198  }
199
200  bool VisitDesignatedInitExpr(DesignatedInitExpr *E) {
201    for (DesignatedInitExpr::Designator &D : llvm::reverse(E->designators())) {
202      if (D.isFieldDesignator() && D.getField())
203        return IndexCtx.handleReference(D.getField(), D.getFieldLoc(), Parent,
204                                        ParentDC, SymbolRoleSet(), {}, E);
205    }
206    return true;
207  }
208
209  bool VisitObjCIvarRefExpr(ObjCIvarRefExpr *E) {
210    SmallVector<SymbolRelation, 4> Relations;
211    SymbolRoleSet Roles = getRolesForRef(E, Relations);
212    return IndexCtx.handleReference(E->getDecl(), E->getLocation(),
213                                    Parent, ParentDC, Roles, Relations, E);
214  }
215
216  bool VisitObjCMessageExpr(ObjCMessageExpr *E) {
217    auto isDynamic = [](const ObjCMessageExpr *MsgE)->bool {
218      if (MsgE->getReceiverKind() != ObjCMessageExpr::Instance)
219        return false;
220      if (auto *RecE = dyn_cast<ObjCMessageExpr>(
221              MsgE->getInstanceReceiver()->IgnoreParenCasts())) {
222        if (RecE->getMethodFamily() == OMF_alloc)
223          return false;
224      }
225      return true;
226    };
227
228    if (ObjCMethodDecl *MD = E->getMethodDecl()) {
229      SymbolRoleSet Roles{};
230      SmallVector<SymbolRelation, 2> Relations;
231      addCallRole(Roles, Relations);
232      Stmt *Containing = getParentStmt();
233
234      auto IsImplicitProperty = [](const PseudoObjectExpr *POE) -> bool {
235        const auto *E = POE->getSyntacticForm();
236        if (const auto *BinOp = dyn_cast<BinaryOperator>(E))
237          E = BinOp->getLHS();
238        const auto *PRE = dyn_cast<ObjCPropertyRefExpr>(E);
239        if (!PRE)
240          return false;
241        if (PRE->isExplicitProperty())
242          return false;
243        if (const ObjCMethodDecl *Getter = PRE->getImplicitPropertyGetter()) {
244          // Class properties that are explicitly defined using @property
245          // declarations are represented implicitly as there is no ivar for
246          // class properties.
247          if (Getter->isClassMethod() &&
248              Getter->getCanonicalDecl()->findPropertyDecl())
249            return false;
250        }
251        return true;
252      };
253      bool IsPropCall = Containing && isa<PseudoObjectExpr>(Containing);
254      // Implicit property message sends are not 'implicit'.
255      if ((E->isImplicit() || IsPropCall) &&
256          !(IsPropCall &&
257            IsImplicitProperty(cast<PseudoObjectExpr>(Containing))))
258        Roles |= (unsigned)SymbolRole::Implicit;
259
260      if (isDynamic(E)) {
261        Roles |= (unsigned)SymbolRole::Dynamic;
262        if (auto *RecD = E->getReceiverInterface())
263          Relations.emplace_back((unsigned)SymbolRole::RelationReceivedBy, RecD);
264      }
265
266      return IndexCtx.handleReference(MD, E->getSelectorStartLoc(),
267                                      Parent, ParentDC, Roles, Relations, E);
268    }
269    return true;
270  }
271
272  bool VisitObjCPropertyRefExpr(ObjCPropertyRefExpr *E) {
273    if (E->isClassReceiver())
274      IndexCtx.handleReference(E->getClassReceiver(), E->getReceiverLocation(),
275                               Parent, ParentDC);
276    if (E->isExplicitProperty()) {
277      SmallVector<SymbolRelation, 2> Relations;
278      SymbolRoleSet Roles = getRolesForRef(E, Relations);
279      return IndexCtx.handleReference(E->getExplicitProperty(), E->getLocation(),
280                                      Parent, ParentDC, Roles, Relations, E);
281    } else if (const ObjCMethodDecl *Getter = E->getImplicitPropertyGetter()) {
282      // Class properties that are explicitly defined using @property
283      // declarations are represented implicitly as there is no ivar for class
284      // properties.
285      if (Getter->isClassMethod()) {
286        if (const auto *PD = Getter->getCanonicalDecl()->findPropertyDecl()) {
287          SmallVector<SymbolRelation, 2> Relations;
288          SymbolRoleSet Roles = getRolesForRef(E, Relations);
289          return IndexCtx.handleReference(PD, E->getLocation(), Parent,
290                                          ParentDC, Roles, Relations, E);
291        }
292      }
293    }
294
295    // No need to do a handleReference for the objc method, because there will
296    // be a message expr as part of PseudoObjectExpr.
297    return true;
298  }
299
300  bool VisitMSPropertyRefExpr(MSPropertyRefExpr *E) {
301    return IndexCtx.handleReference(E->getPropertyDecl(), E->getMemberLoc(),
302                                    Parent, ParentDC, SymbolRoleSet(), {}, E);
303  }
304
305  bool VisitObjCProtocolExpr(ObjCProtocolExpr *E) {
306    return IndexCtx.handleReference(E->getProtocol(), E->getProtocolIdLoc(),
307                                    Parent, ParentDC, SymbolRoleSet(), {}, E);
308  }
309
310  bool passObjCLiteralMethodCall(const ObjCMethodDecl *MD, const Expr *E) {
311    SymbolRoleSet Roles{};
312    SmallVector<SymbolRelation, 2> Relations;
313    addCallRole(Roles, Relations);
314    Roles |= (unsigned)SymbolRole::Implicit;
315    return IndexCtx.handleReference(MD, E->getLocStart(),
316                                    Parent, ParentDC, Roles, Relations, E);
317  }
318
319  bool VisitObjCBoxedExpr(ObjCBoxedExpr *E) {
320    if (ObjCMethodDecl *MD = E->getBoxingMethod()) {
321      return passObjCLiteralMethodCall(MD, E);
322    }
323    return true;
324  }
325
326  bool VisitObjCDictionaryLiteral(ObjCDictionaryLiteral *E) {
327    if (ObjCMethodDecl *MD = E->getDictWithObjectsMethod()) {
328      return passObjCLiteralMethodCall(MD, E);
329    }
330    return true;
331  }
332
333  bool VisitObjCArrayLiteral(ObjCArrayLiteral *E) {
334    if (ObjCMethodDecl *MD = E->getArrayWithObjectsMethod()) {
335      return passObjCLiteralMethodCall(MD, E);
336    }
337    return true;
338  }
339
340  bool VisitCXXConstructExpr(CXXConstructExpr *E) {
341    SymbolRoleSet Roles{};
342    SmallVector<SymbolRelation, 2> Relations;
343    addCallRole(Roles, Relations);
344    return IndexCtx.handleReference(E->getConstructor(), E->getLocation(),
345                                    Parent, ParentDC, Roles, Relations, E);
346  }
347
348  bool TraverseCXXOperatorCallExpr(CXXOperatorCallExpr *E,
349                                   DataRecursionQueue *Q = nullptr) {
350    if (E->getOperatorLoc().isInvalid())
351      return true; // implicit.
352    return base::TraverseCXXOperatorCallExpr(E, Q);
353  }
354
355  bool VisitDeclStmt(DeclStmt *S) {
356    if (IndexCtx.shouldIndexFunctionLocalSymbols()) {
357      IndexCtx.indexDeclGroupRef(S->getDeclGroup());
358      return true;
359    }
360
361    DeclGroupRef DG = S->getDeclGroup();
362    for (DeclGroupRef::iterator I = DG.begin(), E = DG.end(); I != E; ++I) {
363      const Decl *D = *I;
364      if (!D)
365        continue;
366      if (!isFunctionLocalSymbol(D))
367        IndexCtx.indexTopLevelDecl(D);
368    }
369
370    return true;
371  }
372
373  bool TraverseLambdaCapture(LambdaExpr *LE, const LambdaCapture *C,
374                             Expr *Init) {
375    if (C->capturesThis() || C->capturesVLAType())
376      return true;
377
378    if (C->capturesVariable() && IndexCtx.shouldIndexFunctionLocalSymbols())
379      return IndexCtx.handleReference(C->getCapturedVar(), C->getLocation(),
380                                      Parent, ParentDC, SymbolRoleSet());
381
382    // FIXME: Lambda init-captures.
383    return true;
384  }
385
386  // RecursiveASTVisitor visits both syntactic and semantic forms, duplicating
387  // the things that we visit. Make sure to only visit the semantic form.
388  // Also visit things that are in the syntactic form but not the semantic one,
389  // for example the indices in DesignatedInitExprs.
390  bool TraverseInitListExpr(InitListExpr *S, DataRecursionQueue *Q = nullptr) {
391    auto visitForm = [&](InitListExpr *Form) {
392      for (Stmt *SubStmt : Form->children()) {
393        if (!TraverseStmt(SubStmt, Q))
394          return false;
395      }
396      return true;
397    };
398
399    auto visitSyntacticDesignatedInitExpr = [&](DesignatedInitExpr *E) -> bool {
400      for (DesignatedInitExpr::Designator &D : llvm::reverse(E->designators())) {
401        if (D.isFieldDesignator())
402          return IndexCtx.handleReference(D.getField(), D.getFieldLoc(),
403                                          Parent, ParentDC, SymbolRoleSet(),
404                                          {}, E);
405      }
406      return true;
407    };
408
409    InitListExpr *SemaForm = S->isSemanticForm() ? S : S->getSemanticForm();
410    InitListExpr *SyntaxForm = S->isSemanticForm() ? S->getSyntacticForm() : S;
411
412    if (SemaForm) {
413      // Visit things present in syntactic form but not the semantic form.
414      if (SyntaxForm) {
415        for (Expr *init : SyntaxForm->inits()) {
416          if (auto *DIE = dyn_cast<DesignatedInitExpr>(init))
417            visitSyntacticDesignatedInitExpr(DIE);
418        }
419      }
420      return visitForm(SemaForm);
421    }
422
423    // No semantic, try the syntactic.
424    if (SyntaxForm) {
425      return visitForm(SyntaxForm);
426    }
427
428    return true;
429  }
430
431  bool VisitOffsetOfExpr(OffsetOfExpr *S) {
432    for (unsigned I = 0, E = S->getNumComponents(); I != E; ++I) {
433      const OffsetOfNode &Component = S->getComponent(I);
434      if (Component.getKind() == OffsetOfNode::Field)
435        IndexCtx.handleReference(Component.getField(), Component.getLocEnd(),
436                                 Parent, ParentDC, SymbolRoleSet(), {});
437      // FIXME: Try to resolve dependent field references.
438    }
439    return true;
440  }
441};
442
443} // anonymous namespace
444
445void IndexingContext::indexBody(const Stmt *S, const NamedDecl *Parent,
446                                const DeclContext *DC) {
447  if (!S)
448    return;
449
450  if (!DC)
451    DC = Parent->getLexicalDeclContext();
452  BodyIndexer(*this, Parent, DC).TraverseStmt(const_cast<Stmt*>(S));
453}
454