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