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