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 && BO->getLHS()->IgnoreParenCasts() == E)
81        Roles |= (unsigned)SymbolRole::Write;
82
83    } else if (auto UO = dyn_cast<UnaryOperator>(Parent)) {
84      if (UO->isIncrementDecrementOp()) {
85        Roles |= (unsigned)SymbolRole::Read;
86        Roles |= (unsigned)SymbolRole::Write;
87      } else if (UO->getOpcode() == UO_AddrOf) {
88        Roles |= (unsigned)SymbolRole::AddressOf;
89      }
90
91    } else if (auto CA = dyn_cast<CompoundAssignOperator>(Parent)) {
92      if (CA->getLHS()->IgnoreParenCasts() == E) {
93        Roles |= (unsigned)SymbolRole::Read;
94        Roles |= (unsigned)SymbolRole::Write;
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 VisitMemberExpr(MemberExpr *E) {
148    SourceLocation Loc = E->getMemberLoc();
149    if (Loc.isInvalid())
150      Loc = E->getBeginLoc();
151    SmallVector<SymbolRelation, 4> Relations;
152    SymbolRoleSet Roles = getRolesForRef(E, Relations);
153    return IndexCtx.handleReference(E->getMemberDecl(), Loc,
154                                    Parent, ParentDC, Roles, Relations, E);
155  }
156
157  bool indexDependentReference(
158      const Expr *E, const Type *T, const DeclarationNameInfo &NameInfo,
159      llvm::function_ref<bool(const NamedDecl *ND)> Filter) {
160    if (!T)
161      return true;
162    const TemplateSpecializationType *TST =
163        T->getAs<TemplateSpecializationType>();
164    if (!TST)
165      return true;
166    TemplateName TN = TST->getTemplateName();
167    const ClassTemplateDecl *TD =
168        dyn_cast_or_null<ClassTemplateDecl>(TN.getAsTemplateDecl());
169    if (!TD)
170      return true;
171    CXXRecordDecl *RD = TD->getTemplatedDecl();
172    if (!RD->hasDefinition())
173      return true;
174    RD = RD->getDefinition();
175    std::vector<const NamedDecl *> Symbols =
176        RD->lookupDependentName(NameInfo.getName(), Filter);
177    // FIXME: Improve overload handling.
178    if (Symbols.size() != 1)
179      return true;
180    SourceLocation Loc = NameInfo.getLoc();
181    if (Loc.isInvalid())
182      Loc = E->getBeginLoc();
183    SmallVector<SymbolRelation, 4> Relations;
184    SymbolRoleSet Roles = getRolesForRef(E, Relations);
185    return IndexCtx.handleReference(Symbols[0], Loc, Parent, ParentDC, Roles,
186                                    Relations, E);
187  }
188
189  bool VisitCXXDependentScopeMemberExpr(CXXDependentScopeMemberExpr *E) {
190    const DeclarationNameInfo &Info = E->getMemberNameInfo();
191    return indexDependentReference(
192        E, E->getBaseType().getTypePtrOrNull(), Info,
193        [](const NamedDecl *D) { return D->isCXXInstanceMember(); });
194  }
195
196  bool VisitDependentScopeDeclRefExpr(DependentScopeDeclRefExpr *E) {
197    const DeclarationNameInfo &Info = E->getNameInfo();
198    const NestedNameSpecifier *NNS = E->getQualifier();
199    return indexDependentReference(
200        E, NNS->getAsType(), Info,
201        [](const NamedDecl *D) { return !D->isCXXInstanceMember(); });
202  }
203
204  bool VisitDesignatedInitExpr(DesignatedInitExpr *E) {
205    for (DesignatedInitExpr::Designator &D : llvm::reverse(E->designators())) {
206      if (D.isFieldDesignator() && D.getField())
207        return IndexCtx.handleReference(D.getField(), D.getFieldLoc(), Parent,
208                                        ParentDC, SymbolRoleSet(), {}, E);
209    }
210    return true;
211  }
212
213  bool VisitObjCIvarRefExpr(ObjCIvarRefExpr *E) {
214    SmallVector<SymbolRelation, 4> Relations;
215    SymbolRoleSet Roles = getRolesForRef(E, Relations);
216    return IndexCtx.handleReference(E->getDecl(), E->getLocation(),
217                                    Parent, ParentDC, Roles, Relations, E);
218  }
219
220  bool VisitObjCMessageExpr(ObjCMessageExpr *E) {
221    auto isDynamic = [](const ObjCMessageExpr *MsgE)->bool {
222      if (MsgE->getReceiverKind() != ObjCMessageExpr::Instance)
223        return false;
224      if (auto *RecE = dyn_cast<ObjCMessageExpr>(
225              MsgE->getInstanceReceiver()->IgnoreParenCasts())) {
226        if (RecE->getMethodFamily() == OMF_alloc)
227          return false;
228      }
229      return true;
230    };
231
232    if (ObjCMethodDecl *MD = E->getMethodDecl()) {
233      SymbolRoleSet Roles{};
234      SmallVector<SymbolRelation, 2> Relations;
235      addCallRole(Roles, Relations);
236      Stmt *Containing = getParentStmt();
237
238      auto IsImplicitProperty = [](const PseudoObjectExpr *POE) -> bool {
239        const auto *E = POE->getSyntacticForm();
240        if (const auto *BinOp = dyn_cast<BinaryOperator>(E))
241          E = BinOp->getLHS();
242        const auto *PRE = dyn_cast<ObjCPropertyRefExpr>(E);
243        if (!PRE)
244          return false;
245        if (PRE->isExplicitProperty())
246          return false;
247        if (const ObjCMethodDecl *Getter = PRE->getImplicitPropertyGetter()) {
248          // Class properties that are explicitly defined using @property
249          // declarations are represented implicitly as there is no ivar for
250          // class properties.
251          if (Getter->isClassMethod() &&
252              Getter->getCanonicalDecl()->findPropertyDecl())
253            return false;
254        }
255        return true;
256      };
257      bool IsPropCall = Containing && isa<PseudoObjectExpr>(Containing);
258      // Implicit property message sends are not 'implicit'.
259      if ((E->isImplicit() || IsPropCall) &&
260          !(IsPropCall &&
261            IsImplicitProperty(cast<PseudoObjectExpr>(Containing))))
262        Roles |= (unsigned)SymbolRole::Implicit;
263
264      if (isDynamic(E)) {
265        Roles |= (unsigned)SymbolRole::Dynamic;
266
267        auto addReceivers = [&](const ObjCObjectType *Ty) {
268          if (!Ty)
269            return;
270          if (const auto *clsD = Ty->getInterface()) {
271            Relations.emplace_back((unsigned)SymbolRole::RelationReceivedBy,
272                                   clsD);
273          }
274          for (const auto *protD : Ty->quals()) {
275            Relations.emplace_back((unsigned)SymbolRole::RelationReceivedBy,
276                                   protD);
277          }
278        };
279        QualType recT = E->getReceiverType();
280        if (const auto *Ptr = recT->getAs<ObjCObjectPointerType>())
281          addReceivers(Ptr->getObjectType());
282        else
283          addReceivers(recT->getAs<ObjCObjectType>());
284      }
285
286      return IndexCtx.handleReference(MD, E->getSelectorStartLoc(),
287                                      Parent, ParentDC, Roles, Relations, E);
288    }
289    return true;
290  }
291
292  bool VisitObjCPropertyRefExpr(ObjCPropertyRefExpr *E) {
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 (!base::TraverseStmt(Init))
396      return false;
397
398    if (C->capturesVariable() && IndexCtx.shouldIndexFunctionLocalSymbols())
399      return IndexCtx.handleReference(C->getCapturedVar(), C->getLocation(),
400                                      Parent, ParentDC, SymbolRoleSet());
401
402    return true;
403  }
404
405  // RecursiveASTVisitor visits both syntactic and semantic forms, duplicating
406  // the things that we visit. Make sure to only visit the semantic form.
407  // Also visit things that are in the syntactic form but not the semantic one,
408  // for example the indices in DesignatedInitExprs.
409  bool TraverseInitListExpr(InitListExpr *S, DataRecursionQueue *Q = nullptr) {
410    auto visitForm = [&](InitListExpr *Form) {
411      for (Stmt *SubStmt : Form->children()) {
412        if (!TraverseStmt(SubStmt, Q))
413          return false;
414      }
415      return true;
416    };
417
418    auto visitSyntacticDesignatedInitExpr = [&](DesignatedInitExpr *E) -> bool {
419      for (DesignatedInitExpr::Designator &D : llvm::reverse(E->designators())) {
420        if (D.isFieldDesignator() && D.getField())
421          return IndexCtx.handleReference(D.getField(), D.getFieldLoc(),
422                                          Parent, ParentDC, SymbolRoleSet(),
423                                          {}, E);
424      }
425      return true;
426    };
427
428    InitListExpr *SemaForm = S->isSemanticForm() ? S : S->getSemanticForm();
429    InitListExpr *SyntaxForm = S->isSemanticForm() ? S->getSyntacticForm() : S;
430
431    if (SemaForm) {
432      // Visit things present in syntactic form but not the semantic form.
433      if (SyntaxForm) {
434        for (Expr *init : SyntaxForm->inits()) {
435          if (auto *DIE = dyn_cast<DesignatedInitExpr>(init))
436            visitSyntacticDesignatedInitExpr(DIE);
437        }
438      }
439      return visitForm(SemaForm);
440    }
441
442    // No semantic, try the syntactic.
443    if (SyntaxForm) {
444      return visitForm(SyntaxForm);
445    }
446
447    return true;
448  }
449
450  bool VisitOffsetOfExpr(OffsetOfExpr *S) {
451    for (unsigned I = 0, E = S->getNumComponents(); I != E; ++I) {
452      const OffsetOfNode &Component = S->getComponent(I);
453      if (Component.getKind() == OffsetOfNode::Field)
454        IndexCtx.handleReference(Component.getField(), Component.getEndLoc(),
455                                 Parent, ParentDC, SymbolRoleSet(), {});
456      // FIXME: Try to resolve dependent field references.
457    }
458    return true;
459  }
460
461  bool VisitParmVarDecl(ParmVarDecl* D) {
462    // Index the parameters of lambda expression and requires expression.
463    if (IndexCtx.shouldIndexFunctionLocalSymbols()) {
464      const auto *DC = D->getDeclContext();
465      if (DC && (isLambdaCallOperator(DC) || isa<RequiresExprBodyDecl>(DC)))
466        IndexCtx.handleDecl(D);
467    }
468    return true;
469  }
470
471  bool VisitOverloadExpr(OverloadExpr *E) {
472    SmallVector<SymbolRelation, 4> Relations;
473    SymbolRoleSet Roles = getRolesForRef(E, Relations);
474    for (auto *D : E->decls())
475      IndexCtx.handleReference(D, E->getNameLoc(), Parent, ParentDC, Roles,
476                               Relations, E);
477    return true;
478  }
479
480  bool VisitConceptSpecializationExpr(ConceptSpecializationExpr *R) {
481    IndexCtx.handleReference(R->getNamedConcept(), R->getConceptNameLoc(),
482                             Parent, ParentDC);
483    return true;
484  }
485
486  bool TraverseTypeConstraint(const TypeConstraint *C) {
487    IndexCtx.handleReference(C->getNamedConcept(), C->getConceptNameLoc(),
488                             Parent, ParentDC);
489    return RecursiveASTVisitor::TraverseTypeConstraint(C);
490  }
491};
492
493} // anonymous namespace
494
495void IndexingContext::indexBody(const Stmt *S, const NamedDecl *Parent,
496                                const DeclContext *DC) {
497  if (!S)
498    return;
499
500  if (!DC)
501    DC = Parent->getLexicalDeclContext();
502  BodyIndexer(*this, Parent, DC).TraverseStmt(const_cast<Stmt*>(S));
503}
504