brintos

brintos / llvm-project-archived public Read only

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