class VarUseAnalyze {
public:
  VarUseAnalyze(ASTContext *TheContext) : Context(TheContext){};

  void getDeclRefs(const Stmt *CodeContext, const Decl *Variable,
                   llvm::SmallPtrSetImpl<const DeclRefExpr *> *DeclRefs) {

    auto AddDeclRefs = [DeclRefs](const ArrayRef<BoundNodes> Matches) {
      for (const auto &Match : Matches) {
        const auto *DeclRef = Match.getNodeAs<DeclRefExpr>("declref");
        if (DeclRef) {
          // Ignore uses of a standard smart pointer that don't dereference
          // the pointer.
          DeclRefs->insert(DeclRef);
        }
      }
    };

    auto DeclRefMatcher =
        declRefExpr(hasDeclaration(equalsNode(Variable))).bind("declref");

    AddDeclRefs(match(traverse(TK_AsIs, findAll(DeclRefMatcher)), *CodeContext,
                      *Context));
  }

  void getReinits(const Stmt *Block, const Decl *Variable,
                  llvm::SmallPtrSetImpl<const Stmt *> *Stmts,
                  llvm::SmallPtrSetImpl<const DeclRefExpr *> *DeclRefs) {

    auto DeclRefMatcher =
        declRefExpr(hasDeclaration(equalsNode(Variable))).bind("declref");

    // Matches different types of reinitialization.
    auto ReinitMatcher =
        stmt(binaryOperation(hasOperatorName("="), hasLHS(DeclRefMatcher)))
            .bind("reinit");

    Stmts->clear();
    DeclRefs->clear();

    SmallVector<BoundNodes, 1> Matches =
        match(findAll(ReinitMatcher), *Block, *Context);

    for (const auto &Match : Matches) {
      const auto *TheStmt = Match.getNodeAs<Stmt>("reinit");
      const auto *TheDeclRef = Match.getNodeAs<DeclRefExpr>("declref");
      Stmts->insert(TheStmt);
      DeclRefs->insert(TheDeclRef);
    }
  }

  void getUsesAndReinits(const Stmt *Block, const ValueDecl *Variable,
                         llvm::SmallVectorImpl<const DeclRefExpr *> *Uses,
                         llvm::SmallPtrSetImpl<const Stmt *> *Reinits) {

    llvm::SmallPtrSet<const DeclRefExpr *, 1> DeclRefs;
    llvm::SmallPtrSet<const DeclRefExpr *, 1> ReinitDeclRefs;

    getDeclRefs(Block, Variable, &DeclRefs);
    getReinits(Block, Variable, Reinits, &ReinitDeclRefs);

    // All references to the variable that aren't reinitializations are uses.
    Uses->clear();
    for (const DeclRefExpr *DeclRef : DeclRefs) {
      if (!ReinitDeclRefs.count(DeclRef))
        Uses->push_back(DeclRef);
    }

    // Sort the uses by their occurrence in the source code.
    llvm::sort(*Uses, [](const DeclRefExpr *D1, const DeclRefExpr *D2) {
      return D1->getExprLoc() < D2->getExprLoc();
    });
  }

protected:
  ASTContext *Context;
  std::unique_ptr<ExprSequence> Sequence;
  std::unique_ptr<StmtToBlockMap> BlockMap;
  llvm::SmallPtrSet<const CFGBlock *, 8> Visited;
};

    for (const DeclRefExpr *DeclRef : Uses) {
      const CFGBlock *RefBlock = BlockMap->blockContainingStmt(DeclRef);
      if (!RefBlock)
        continue;

      if (0 == Reinits.size()) {
        continue;
      }
      bool HaveDom = false;

      for (const Stmt *Assgin : Reinits) {
        const CFGBlock *AssBlock = BlockMap->blockContainingStmt(Assgin);
        if (!AssBlock)
          continue;
        if (AssBlock != RefBlock) {
          if (Dom.dominates(AssBlock, RefBlock)) {
            HaveDom = true;
          }

        } else {
          if (!Sequence->potentiallyAfter(Assgin, DeclRef)) {
            HaveDom = true;
          }
        }
      }

      if (!HaveDom) {
        DeclRef->dump();
      }
    }
文档更新时间: 2024-03-11 02:46   作者:suglow