From: Jordan Rose Date: Wed, 15 May 2013 23:22:55 +0000 (+0000) Subject: Remove unused, awkward CFGStmtVisitor and subclasses. X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=d049b40ef411eee12a735233dbe04fdc42c67e1a;p=clang Remove unused, awkward CFGStmtVisitor and subclasses. This class is a StmtVisitor that distinguishes between block-level and non-block-level statements in a CFG. However, it does so using a hard-coded idea of which statements might be block-level, which probably isn't accurate anymore. The only implementer of the CFGStmtVisitor hierarchy was the analyzer's DeadStoresChecker, and the analyzer creates a linearized CFG anyway (every non-trivial statement is a block-level statement). This also allows us to remove the block-expr map ("BlkExprMap"), which mapped statements to positions in the CFG. Apart from having a helper type that really should have just been Optional, it was only being used to ask /if/ a particular expression was block-level, for traversal purposes in CFGStmtVisitor. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@181945 91177308-0d34-0410-b5e6-96231b3b80d8 --- diff --git a/include/clang/Analysis/CFG.h b/include/clang/Analysis/CFG.h index 01480ed3b4..f4092ed50d 100644 --- a/include/clang/Analysis/CFG.h +++ b/include/clang/Analysis/CFG.h @@ -763,21 +763,6 @@ public: // CFG Introspection. //===--------------------------------------------------------------------===// - struct BlkExprNumTy { - const signed Idx; - explicit BlkExprNumTy(signed idx) : Idx(idx) {} - explicit BlkExprNumTy() : Idx(-1) {} - operator bool() const { return Idx >= 0; } - operator unsigned() const { assert(Idx >=0); return (unsigned) Idx; } - }; - - bool isBlkExpr(const Stmt *S) { return getBlkExprNum(S); } - bool isBlkExpr(const Stmt *S) const { - return const_cast(this)->isBlkExpr(S); - } - BlkExprNumTy getBlkExprNum(const Stmt *S); - unsigned getNumBlkExprs(); - /// getNumBlockIDs - Returns the total number of BlockIDs allocated (which /// start at 0). unsigned getNumBlockIDs() const { return NumBlockIDs; } @@ -800,9 +785,7 @@ public: //===--------------------------------------------------------------------===// CFG() : Entry(NULL), Exit(NULL), IndirectGotoBlock(NULL), NumBlockIDs(0), - BlkExprMap(NULL), Blocks(BlkBVC, 10) {} - - ~CFG(); + Blocks(BlkBVC, 10) {} llvm::BumpPtrAllocator& getAllocator() { return BlkBVC.getAllocator(); @@ -819,11 +802,6 @@ private: // for indirect gotos unsigned NumBlockIDs; - // BlkExprMap - An opaque pointer to prevent inclusion of DenseMap.h. - // It represents a map from Expr* to integers to record the set of - // block-level expressions and their "statement number" in the CFG. - void * BlkExprMap; - BumpVectorContext BlkBVC; CFGBlockListTy Blocks; diff --git a/include/clang/Analysis/Support/BlkExprDeclBitVector.h b/include/clang/Analysis/Support/BlkExprDeclBitVector.h deleted file mode 100644 index 35cc799b13..0000000000 --- a/include/clang/Analysis/Support/BlkExprDeclBitVector.h +++ /dev/null @@ -1,307 +0,0 @@ -// BlkExprDeclBitVector.h - Dataflow types for Bitvector Analysis --*- C++ --*-- -// -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. -// -//===----------------------------------------------------------------------===// -// -// This file provides definition of dataflow types used by analyses such -// as LiveVariables and UninitializedValues. The underlying dataflow values -// are implemented as bitvectors, but the definitions in this file include -// the necessary boilerplate to use with our dataflow framework. -// -//===----------------------------------------------------------------------===// - -#ifndef LLVM_CLANG_STMTDECLBVDVAL_H -#define LLVM_CLANG_STMTDECLBVDVAL_H - -#include "clang/AST/Decl.h" // for Decl* -> NamedDecl* conversion -#include "clang/Analysis/CFG.h" -#include "llvm/ADT/BitVector.h" -#include "llvm/ADT/DenseMap.h" - -namespace clang { - - class Stmt; - class ASTContext; - -struct DeclBitVector_Types { - - class Idx { - unsigned I; - public: - explicit Idx(unsigned i) : I(i) {} - Idx() : I(~0U) {} - - bool isValid() const { - return I != ~0U; - } - operator unsigned() const { - assert (isValid()); - return I; - } - }; - - //===--------------------------------------------------------------------===// - // AnalysisDataTy - Whole-function meta data. - //===--------------------------------------------------------------------===// - - class AnalysisDataTy { - public: - typedef llvm::DenseMap DMapTy; - typedef DMapTy::const_iterator decl_iterator; - - protected: - DMapTy DMap; - unsigned NDecls; - - public: - - AnalysisDataTy() : NDecls(0) {} - virtual ~AnalysisDataTy() {} - - bool isTracked(const NamedDecl *SD) { return DMap.find(SD) != DMap.end(); } - - Idx getIdx(const NamedDecl *SD) const { - DMapTy::const_iterator I = DMap.find(SD); - return I == DMap.end() ? Idx() : Idx(I->second); - } - - unsigned getNumDecls() const { return NDecls; } - - void Register(const NamedDecl *SD) { - if (!isTracked(SD)) DMap[SD] = NDecls++; - } - - decl_iterator begin_decl() const { return DMap.begin(); } - decl_iterator end_decl() const { return DMap.end(); } - }; - - //===--------------------------------------------------------------------===// - // ValTy - Dataflow value. - //===--------------------------------------------------------------------===// - - class ValTy { - llvm::BitVector DeclBV; - public: - - void resetDeclValues(AnalysisDataTy& AD) { - DeclBV.resize(AD.getNumDecls()); - DeclBV.reset(); - } - - void setDeclValues(AnalysisDataTy& AD) { - DeclBV.resize(AD.getNumDecls()); - DeclBV.set(); - } - - void resetValues(AnalysisDataTy& AD) { - resetDeclValues(AD); - } - - bool operator==(const ValTy& RHS) const { - assert (sizesEqual(RHS)); - return DeclBV == RHS.DeclBV; - } - - void copyValues(const ValTy& RHS) { DeclBV = RHS.DeclBV; } - - llvm::BitVector::reference getBit(unsigned i) { - return DeclBV[i]; - } - - bool getBit(unsigned i) const { - return DeclBV[i]; - } - - llvm::BitVector::reference - operator()(const NamedDecl *ND, const AnalysisDataTy& AD) { - return getBit(AD.getIdx(ND)); - } - - bool operator()(const NamedDecl *ND, const AnalysisDataTy& AD) const { - return getBit(AD.getIdx(ND)); - } - - llvm::BitVector::reference getDeclBit(unsigned i) { return DeclBV[i]; } - const llvm::BitVector::reference getDeclBit(unsigned i) const { - return const_cast(DeclBV)[i]; - } - - ValTy& operator|=(const ValTy& RHS) { - assert (sizesEqual(RHS)); - DeclBV |= RHS.DeclBV; - return *this; - } - - ValTy& operator&=(const ValTy& RHS) { - assert (sizesEqual(RHS)); - DeclBV &= RHS.DeclBV; - return *this; - } - - ValTy& OrDeclBits(const ValTy& RHS) { - return operator|=(RHS); - } - - ValTy& AndDeclBits(const ValTy& RHS) { - return operator&=(RHS); - } - - bool sizesEqual(const ValTy& RHS) const { - return DeclBV.size() == RHS.DeclBV.size(); - } - }; - - //===--------------------------------------------------------------------===// - // Some useful merge operations. - //===--------------------------------------------------------------------===// - - struct Union { void operator()(ValTy& Dst, ValTy& Src) { Dst |= Src; } }; - struct Intersect { void operator()(ValTy& Dst, ValTy& Src) { Dst &= Src; } }; -}; - - -struct StmtDeclBitVector_Types { - - //===--------------------------------------------------------------------===// - // AnalysisDataTy - Whole-function meta data. - //===--------------------------------------------------------------------===// - - class AnalysisDataTy : public DeclBitVector_Types::AnalysisDataTy { - ASTContext *ctx; - CFG* cfg; - public: - AnalysisDataTy() : ctx(0), cfg(0) {} - virtual ~AnalysisDataTy() {} - - void setContext(ASTContext &c) { ctx = &c; } - ASTContext &getContext() { - assert(ctx && "ASTContext should not be NULL."); - return *ctx; - } - - void setCFG(CFG& c) { cfg = &c; } - CFG& getCFG() { assert(cfg && "CFG should not be NULL."); return *cfg; } - - bool isTracked(const Stmt *S) { return cfg->isBlkExpr(S); } - using DeclBitVector_Types::AnalysisDataTy::isTracked; - - unsigned getIdx(const Stmt *S) const { - CFG::BlkExprNumTy I = cfg->getBlkExprNum(S); - assert(I && "Stmtession not tracked for bitvector."); - return I; - } - using DeclBitVector_Types::AnalysisDataTy::getIdx; - - unsigned getNumBlkExprs() const { return cfg->getNumBlkExprs(); } - }; - - //===--------------------------------------------------------------------===// - // ValTy - Dataflow value. - //===--------------------------------------------------------------------===// - - class ValTy : public DeclBitVector_Types::ValTy { - llvm::BitVector BlkExprBV; - typedef DeclBitVector_Types::ValTy ParentTy; - - static inline ParentTy& ParentRef(ValTy& X) { - return static_cast(X); - } - - static inline const ParentTy& ParentRef(const ValTy& X) { - return static_cast(X); - } - - public: - - void resetBlkExprValues(AnalysisDataTy& AD) { - BlkExprBV.resize(AD.getNumBlkExprs()); - BlkExprBV.reset(); - } - - void setBlkExprValues(AnalysisDataTy& AD) { - BlkExprBV.resize(AD.getNumBlkExprs()); - BlkExprBV.set(); - } - - void resetValues(AnalysisDataTy& AD) { - resetDeclValues(AD); - resetBlkExprValues(AD); - } - - void setValues(AnalysisDataTy& AD) { - setDeclValues(AD); - setBlkExprValues(AD); - } - - bool operator==(const ValTy& RHS) const { - return ParentRef(*this) == ParentRef(RHS) - && BlkExprBV == RHS.BlkExprBV; - } - - void copyValues(const ValTy& RHS) { - ParentRef(*this).copyValues(ParentRef(RHS)); - BlkExprBV = RHS.BlkExprBV; - } - - llvm::BitVector::reference - operator()(const Stmt *S, const AnalysisDataTy& AD) { - return BlkExprBV[AD.getIdx(S)]; - } - const llvm::BitVector::reference - operator()(const Stmt *S, const AnalysisDataTy& AD) const { - return const_cast(*this)(S,AD); - } - - using DeclBitVector_Types::ValTy::operator(); - - - llvm::BitVector::reference getStmtBit(unsigned i) { return BlkExprBV[i]; } - const llvm::BitVector::reference getStmtBit(unsigned i) const { - return const_cast(BlkExprBV)[i]; - } - - ValTy& OrBlkExprBits(const ValTy& RHS) { - BlkExprBV |= RHS.BlkExprBV; - return *this; - } - - ValTy& AndBlkExprBits(const ValTy& RHS) { - BlkExprBV &= RHS.BlkExprBV; - return *this; - } - - ValTy& operator|=(const ValTy& RHS) { - assert (sizesEqual(RHS)); - ParentRef(*this) |= ParentRef(RHS); - BlkExprBV |= RHS.BlkExprBV; - return *this; - } - - ValTy& operator&=(const ValTy& RHS) { - assert (sizesEqual(RHS)); - ParentRef(*this) &= ParentRef(RHS); - BlkExprBV &= RHS.BlkExprBV; - return *this; - } - - bool sizesEqual(const ValTy& RHS) const { - return ParentRef(*this).sizesEqual(ParentRef(RHS)) - && BlkExprBV.size() == RHS.BlkExprBV.size(); - } - }; - - //===--------------------------------------------------------------------===// - // Some useful merge operations. - //===--------------------------------------------------------------------===// - - struct Union { void operator()(ValTy& Dst, ValTy& Src) { Dst |= Src; } }; - struct Intersect { void operator()(ValTy& Dst, ValTy& Src) { Dst &= Src; } }; - -}; -} // end namespace clang - -#endif diff --git a/include/clang/Analysis/Visitors/CFGRecStmtDeclVisitor.h b/include/clang/Analysis/Visitors/CFGRecStmtDeclVisitor.h deleted file mode 100644 index 2bf3eda070..0000000000 --- a/include/clang/Analysis/Visitors/CFGRecStmtDeclVisitor.h +++ /dev/null @@ -1,107 +0,0 @@ -//= CFGRecStmtDeclVisitor - Recursive visitor of CFG stmts/decls -*- C++ --*-=// -// -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. -// -//===----------------------------------------------------------------------===// -// -// This file implements the template class CFGRecStmtDeclVisitor, which extends -// CFGRecStmtVisitor by implementing (typed) visitation of decls. -// -// FIXME: This may not be fully complete. We currently explore only subtypes -// of ScopedDecl. -//===----------------------------------------------------------------------===// - -#ifndef LLVM_CLANG_ANALYSIS_CFG_REC_STMT_DECL_VISITOR_H -#define LLVM_CLANG_ANALYSIS_CFG_REC_STMT_DECL_VISITOR_H - -#include "clang/AST/Decl.h" -#include "clang/AST/DeclCXX.h" -#include "clang/AST/DeclObjC.h" -#include "clang/Analysis/Visitors/CFGRecStmtVisitor.h" - -#define DISPATCH_CASE(CLASS) \ -case Decl::CLASS: \ -static_cast(this)->Visit##CLASS##Decl( \ - static_cast(D)); \ -break; - -#define DEFAULT_DISPATCH(CLASS) void Visit##CLASS##Decl(CLASS##Decl *D) {} -#define DEFAULT_DISPATCH_VARDECL(CLASS) void Visit##CLASS##Decl(CLASS##Decl *D)\ - { static_cast(this)->VisitVarDecl(D); } - - -namespace clang { -template -class CFGRecStmtDeclVisitor : public CFGRecStmtVisitor { -public: - - void VisitDeclRefExpr(DeclRefExpr *DR) { - static_cast(this)->VisitDecl(DR->getDecl()); - } - - void VisitDeclStmt(DeclStmt *DS) { - for (DeclStmt::decl_iterator DI = DS->decl_begin(), DE = DS->decl_end(); - DI != DE; ++DI) { - Decl *D = *DI; - static_cast(this)->VisitDecl(D); - // Visit the initializer. - if (VarDecl *VD = dyn_cast(D)) - if (Expr *I = VD->getInit()) - static_cast(this)->Visit(I); - } - } - - void VisitDecl(Decl *D) { - switch (D->getKind()) { - DISPATCH_CASE(Function) - DISPATCH_CASE(CXXMethod) - DISPATCH_CASE(Var) - DISPATCH_CASE(ParmVar) // FIXME: (same) - DISPATCH_CASE(ImplicitParam) - DISPATCH_CASE(EnumConstant) - DISPATCH_CASE(Typedef) - DISPATCH_CASE(TypeAlias) - DISPATCH_CASE(Record) // FIXME: Refine. VisitStructDecl? - DISPATCH_CASE(CXXRecord) - DISPATCH_CASE(Enum) - DISPATCH_CASE(Field) - DISPATCH_CASE(UsingDirective) - DISPATCH_CASE(Using) - DISPATCH_CASE(NamespaceAlias) - default: - llvm_unreachable("Subtype of ScopedDecl not handled."); - } - } - - DEFAULT_DISPATCH(Var) - DEFAULT_DISPATCH(Function) - DEFAULT_DISPATCH(CXXMethod) - DEFAULT_DISPATCH_VARDECL(ParmVar) - DEFAULT_DISPATCH(ImplicitParam) - DEFAULT_DISPATCH(EnumConstant) - DEFAULT_DISPATCH(Typedef) - DEFAULT_DISPATCH(TypeAlias) - DEFAULT_DISPATCH(Record) - DEFAULT_DISPATCH(Enum) - DEFAULT_DISPATCH(Field) - DEFAULT_DISPATCH(ObjCInterface) - DEFAULT_DISPATCH(ObjCMethod) - DEFAULT_DISPATCH(ObjCProtocol) - DEFAULT_DISPATCH(ObjCCategory) - DEFAULT_DISPATCH(UsingDirective) - DEFAULT_DISPATCH(Using) - DEFAULT_DISPATCH(NamespaceAlias) - - void VisitCXXRecordDecl(CXXRecordDecl *D) { - static_cast(this)->VisitRecordDecl(D); - } -}; - -} // end namespace clang - -#undef DISPATCH_CASE -#undef DEFAULT_DISPATCH -#endif diff --git a/include/clang/Analysis/Visitors/CFGRecStmtVisitor.h b/include/clang/Analysis/Visitors/CFGRecStmtVisitor.h deleted file mode 100644 index 4d1cabfc5c..0000000000 --- a/include/clang/Analysis/Visitors/CFGRecStmtVisitor.h +++ /dev/null @@ -1,59 +0,0 @@ -//==- CFGRecStmtVisitor - Recursive visitor of CFG statements ---*- C++ --*-==// -// -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. -// -//===----------------------------------------------------------------------===// -// -// This file implements the template class CFGRecStmtVisitor, which extends -// CFGStmtVisitor by implementing a default recursive visit of all statements. -// -//===----------------------------------------------------------------------===// - -#ifndef LLVM_CLANG_ANALYSIS_CFG_REC_STMT_VISITOR_H -#define LLVM_CLANG_ANALYSIS_CFG_REC_STMT_VISITOR_H - -#include "clang/Analysis/Visitors/CFGStmtVisitor.h" - -namespace clang { -template -class CFGRecStmtVisitor : public CFGStmtVisitor { -public: - - void VisitStmt(Stmt *S) { - static_cast< ImplClass* >(this)->VisitChildren(S); - } - - void VisitCompoundStmt(CompoundStmt *S) { - // Do nothing. Everything in a CompoundStmt is inlined - // into the CFG. - } - - void VisitConditionVariableInit(Stmt *S) { - assert(S == this->getCurrentBlkStmt()); - VarDecl *CondVar = 0; - switch (S->getStmtClass()) { -#define CONDVAR_CASE(CLASS) \ -case Stmt::CLASS ## Class:\ -CondVar = cast(S)->getConditionVariable();\ -break; - CONDVAR_CASE(IfStmt) - CONDVAR_CASE(ForStmt) - CONDVAR_CASE(SwitchStmt) - CONDVAR_CASE(WhileStmt) -#undef CONDVAR_CASE - default: - llvm_unreachable("Infeasible"); - } - static_cast(this)->Visit(CondVar->getInit()); - } - - // Defining operator() allows the visitor to be used as a C++ style functor. - void operator()(Stmt *S) { static_cast(this)->BlockStmt_Visit(S);} -}; - -} // end namespace clang - -#endif diff --git a/include/clang/Analysis/Visitors/CFGStmtVisitor.h b/include/clang/Analysis/Visitors/CFGStmtVisitor.h deleted file mode 100644 index b354ba7b16..0000000000 --- a/include/clang/Analysis/Visitors/CFGStmtVisitor.h +++ /dev/null @@ -1,175 +0,0 @@ -//===--- CFGStmtVisitor.h - Visitor for Stmts in a CFG ----------*- C++ -*-===// -// -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. -// -//===----------------------------------------------------------------------===// -// -// This file defines the CFGStmtVisitor interface, which extends -// StmtVisitor. This interface is useful for visiting statements in a CFG -// where some statements have implicit control-flow and thus should -// be treated specially. -// -//===----------------------------------------------------------------------===// - -#ifndef LLVM_CLANG_ANALYSIS_CFGSTMTVISITOR_H -#define LLVM_CLANG_ANALYSIS_CFGSTMTVISITOR_H - -#include "clang/AST/StmtVisitor.h" -#include "clang/Analysis/CFG.h" - -namespace clang { - -#define DISPATCH_CASE(CLASS) \ -case Stmt::CLASS ## Class: return \ -static_cast(this)->BlockStmt_Visit ## CLASS(static_cast(S)); - -#define DEFAULT_BLOCKSTMT_VISIT(CLASS) RetTy BlockStmt_Visit ## CLASS(CLASS *S)\ -{ return\ - static_cast(this)->BlockStmt_VisitImplicitControlFlowExpr(\ - cast(S)); } - -template -class CFGStmtVisitor : public StmtVisitor { - Stmt *CurrentBlkStmt; - - struct NullifyStmt { - Stmt*& S; - - NullifyStmt(Stmt*& s) : S(s) {} - ~NullifyStmt() { S = NULL; } - }; - -public: - CFGStmtVisitor() : CurrentBlkStmt(NULL) {} - - Stmt *getCurrentBlkStmt() const { return CurrentBlkStmt; } - - RetTy Visit(Stmt *S) { - if (S == CurrentBlkStmt || - !static_cast(this)->getCFG().isBlkExpr(S)) - return StmtVisitor::Visit(S); - else - return RetTy(); - } - - /// VisitConditionVariableInit - Handle the initialization of condition - /// variables at branches. Valid statements include IfStmt, ForStmt, - /// WhileStmt, and SwitchStmt. - RetTy VisitConditionVariableInit(Stmt *S) { - return RetTy(); - } - - /// BlockVisit_XXX - Visitor methods for visiting the "root" statements in - /// CFGBlocks. Root statements are the statements that appear explicitly in - /// the list of statements in a CFGBlock. For substatements, or when there - /// is no implementation provided for a BlockStmt_XXX method, we default - /// to using StmtVisitor's Visit method. - RetTy BlockStmt_Visit(Stmt *S) { - CurrentBlkStmt = S; - NullifyStmt cleanup(CurrentBlkStmt); - - switch (S->getStmtClass()) { - case Stmt::IfStmtClass: - case Stmt::ForStmtClass: - case Stmt::WhileStmtClass: - case Stmt::SwitchStmtClass: - return static_cast(this)->VisitConditionVariableInit(S); - - DISPATCH_CASE(StmtExpr) - DISPATCH_CASE(ConditionalOperator) - DISPATCH_CASE(BinaryConditionalOperator) - DISPATCH_CASE(ObjCForCollectionStmt) - DISPATCH_CASE(CXXForRangeStmt) - - case Stmt::BinaryOperatorClass: { - BinaryOperator* B = cast(S); - if (B->isLogicalOp()) - return static_cast(this)->BlockStmt_VisitLogicalOp(B); - else if (B->getOpcode() == BO_Comma) - return static_cast(this)->BlockStmt_VisitComma(B); - // Fall through. - } - - default: - if (isa(S)) - return - static_cast(this)->BlockStmt_VisitExpr(cast(S)); - else - return static_cast(this)->BlockStmt_VisitStmt(S); - } - } - - DEFAULT_BLOCKSTMT_VISIT(StmtExpr) - DEFAULT_BLOCKSTMT_VISIT(ConditionalOperator) - DEFAULT_BLOCKSTMT_VISIT(BinaryConditionalOperator) - - RetTy BlockStmt_VisitObjCForCollectionStmt(ObjCForCollectionStmt *S) { - return static_cast(this)->BlockStmt_VisitStmt(S); - } - - RetTy BlockStmt_VisitCXXForRangeStmt(CXXForRangeStmt *S) { - return static_cast(this)->BlockStmt_VisitStmt(S); - } - - RetTy BlockStmt_VisitImplicitControlFlowExpr(Expr *E) { - return static_cast(this)->BlockStmt_VisitExpr(E); - } - - RetTy BlockStmt_VisitExpr(Expr *E) { - return static_cast(this)->BlockStmt_VisitStmt(E); - } - - RetTy BlockStmt_VisitStmt(Stmt *S) { - return static_cast(this)->Visit(S); - } - - RetTy BlockStmt_VisitLogicalOp(BinaryOperator* B) { - return - static_cast(this)->BlockStmt_VisitImplicitControlFlowExpr(B); - } - - RetTy BlockStmt_VisitComma(BinaryOperator* B) { - return - static_cast(this)->BlockStmt_VisitImplicitControlFlowExpr(B); - } - - //===--------------------------------------------------------------------===// - // Utility methods. Not called by default (but subclasses may use them). - //===--------------------------------------------------------------------===// - - /// VisitChildren: Call "Visit" on each child of S. - void VisitChildren(Stmt *S) { - - switch (S->getStmtClass()) { - default: - break; - - case Stmt::StmtExprClass: { - CompoundStmt *CS = cast(S)->getSubStmt(); - if (CS->body_empty()) return; - static_cast(this)->Visit(CS->body_back()); - return; - } - - case Stmt::BinaryOperatorClass: { - BinaryOperator* B = cast(S); - if (B->getOpcode() != BO_Comma) break; - static_cast(this)->Visit(B->getRHS()); - return; - } - } - - for (Stmt::child_range I = S->children(); I; ++I) - if (*I) static_cast(this)->Visit(*I); - } -}; - -#undef DEFAULT_BLOCKSTMT_VISIT -#undef DISPATCH_CASE - -} // end namespace clang - -#endif diff --git a/lib/Analysis/CFG.cpp b/lib/Analysis/CFG.cpp index 6eb84ce92c..674c01201d 100644 --- a/lib/Analysis/CFG.cpp +++ b/lib/Analysis/CFG.cpp @@ -3399,113 +3399,6 @@ bool CFGImplicitDtor::isNoReturn(ASTContext &astContext) const { return false; } -//===----------------------------------------------------------------------===// -// CFG: Queries for BlkExprs. -//===----------------------------------------------------------------------===// - -namespace { - typedef llvm::DenseMap BlkExprMapTy; -} - -static void FindSubExprAssignments(const Stmt *S, - llvm::SmallPtrSet& Set) { - if (!S) - return; - - for (Stmt::const_child_range I = S->children(); I; ++I) { - const Stmt *child = *I; - if (!child) - continue; - - if (const BinaryOperator* B = dyn_cast(child)) - if (B->isAssignmentOp()) Set.insert(B); - - FindSubExprAssignments(child, Set); - } -} - -static BlkExprMapTy* PopulateBlkExprMap(CFG& cfg) { - BlkExprMapTy* M = new BlkExprMapTy(); - - // Look for assignments that are used as subexpressions. These are the only - // assignments that we want to *possibly* register as a block-level - // expression. Basically, if an assignment occurs both in a subexpression and - // at the block-level, it is a block-level expression. - llvm::SmallPtrSet SubExprAssignments; - - for (CFG::iterator I=cfg.begin(), E=cfg.end(); I != E; ++I) - for (CFGBlock::iterator BI=(*I)->begin(), EI=(*I)->end(); BI != EI; ++BI) - if (Optional S = BI->getAs()) - FindSubExprAssignments(S->getStmt(), SubExprAssignments); - - for (CFG::iterator I=cfg.begin(), E=cfg.end(); I != E; ++I) { - - // Iterate over the statements again on identify the Expr* and Stmt* at the - // block-level that are block-level expressions. - - for (CFGBlock::iterator BI=(*I)->begin(), EI=(*I)->end(); BI != EI; ++BI) { - Optional CS = BI->getAs(); - if (!CS) - continue; - if (const Expr *Exp = dyn_cast(CS->getStmt())) { - assert((Exp->IgnoreParens() == Exp) && "No parens on block-level exps"); - - if (const BinaryOperator* B = dyn_cast(Exp)) { - // Assignment expressions that are not nested within another - // expression are really "statements" whose value is never used by - // another expression. - if (B->isAssignmentOp() && !SubExprAssignments.count(Exp)) - continue; - } else if (const StmtExpr *SE = dyn_cast(Exp)) { - // Special handling for statement expressions. The last statement in - // the statement expression is also a block-level expr. - const CompoundStmt *C = SE->getSubStmt(); - if (!C->body_empty()) { - const Stmt *Last = C->body_back(); - if (const Expr *LastEx = dyn_cast(Last)) - Last = LastEx->IgnoreParens(); - unsigned x = M->size(); - (*M)[Last] = x; - } - } - - unsigned x = M->size(); - (*M)[Exp] = x; - } - } - - // Look at terminators. The condition is a block-level expression. - - Stmt *S = (*I)->getTerminatorCondition(); - - if (S && M->find(S) == M->end()) { - unsigned x = M->size(); - (*M)[S] = x; - } - } - - return M; -} - -CFG::BlkExprNumTy CFG::getBlkExprNum(const Stmt *S) { - assert(S != NULL); - if (!BlkExprMap) { BlkExprMap = (void*) PopulateBlkExprMap(*this); } - - BlkExprMapTy* M = reinterpret_cast(BlkExprMap); - BlkExprMapTy::iterator I = M->find(S); - return (I == M->end()) ? CFG::BlkExprNumTy() : CFG::BlkExprNumTy(I->second); -} - -unsigned CFG::getNumBlkExprs() { - if (const BlkExprMapTy* M = reinterpret_cast(BlkExprMap)) - return M->size(); - - // We assume callers interested in the number of BlkExprs will want - // the map constructed if it doesn't already exist. - BlkExprMap = (void*) PopulateBlkExprMap(*this); - return reinterpret_cast(BlkExprMap)->size(); -} - //===----------------------------------------------------------------------===// // Filtered walking of the CFG. //===----------------------------------------------------------------------===// @@ -3529,14 +3422,6 @@ bool CFGBlock::FilterEdge(const CFGBlock::FilterOptions &F, return false; } -//===----------------------------------------------------------------------===// -// Cleanup: CFG dstor. -//===----------------------------------------------------------------------===// - -CFG::~CFG() { - delete reinterpret_cast(BlkExprMap); -} - //===----------------------------------------------------------------------===// // CFG pretty printing //===----------------------------------------------------------------------===// diff --git a/lib/Analysis/UninitializedValues.cpp b/lib/Analysis/UninitializedValues.cpp index 730aa6ba21..3d155c8174 100644 --- a/lib/Analysis/UninitializedValues.cpp +++ b/lib/Analysis/UninitializedValues.cpp @@ -14,12 +14,12 @@ #include "clang/AST/ASTContext.h" #include "clang/AST/Attr.h" #include "clang/AST/Decl.h" +#include "clang/AST/StmtVisitor.h" #include "clang/Analysis/Analyses/PostOrderCFGView.h" #include "clang/Analysis/Analyses/UninitializedValues.h" #include "clang/Analysis/AnalysisContext.h" #include "clang/Analysis/CFG.h" #include "clang/Analysis/DomainSpecific/ObjCNoReturn.h" -#include "clang/Analysis/Visitors/CFGRecStmtDeclVisitor.h" #include "llvm/ADT/DenseMap.h" #include "llvm/ADT/Optional.h" #include "llvm/ADT/PackedVector.h" diff --git a/lib/StaticAnalyzer/Checkers/DeadStoresChecker.cpp b/lib/StaticAnalyzer/Checkers/DeadStoresChecker.cpp index f336a6e680..7c44c21706 100644 --- a/lib/StaticAnalyzer/Checkers/DeadStoresChecker.cpp +++ b/lib/StaticAnalyzer/Checkers/DeadStoresChecker.cpp @@ -18,7 +18,6 @@ #include "clang/AST/ParentMap.h" #include "clang/AST/RecursiveASTVisitor.h" #include "clang/Analysis/Analyses/LiveVariables.h" -#include "clang/Analysis/Visitors/CFGRecStmtDeclVisitor.h" #include "clang/StaticAnalyzer/Core/BugReporter/BugReporter.h" #include "clang/StaticAnalyzer/Core/Checker.h" #include "clang/StaticAnalyzer/Core/PathSensitive/AnalysisManager.h" @@ -391,26 +390,24 @@ public: //===----------------------------------------------------------------------===// namespace { -class FindEscaped : public CFGRecStmtDeclVisitor{ - CFG *cfg; +class FindEscaped { public: - FindEscaped(CFG *c) : cfg(c) {} - - CFG& getCFG() { return *cfg; } - llvm::SmallPtrSet Escaped; - void VisitUnaryOperator(UnaryOperator* U) { - // Check for '&'. Any VarDecl whose value has its address-taken we - // treat as escaped. - Expr *E = U->getSubExpr()->IgnoreParenCasts(); - if (U->getOpcode() == UO_AddrOf) - if (DeclRefExpr *DR = dyn_cast(E)) - if (VarDecl *VD = dyn_cast(DR->getDecl())) { - Escaped.insert(VD); - return; - } - Visit(E); + void operator()(const Stmt *S) { + // Check for '&'. Any VarDecl whose address has been taken we treat as + // escaped. + // FIXME: What about references? + const UnaryOperator *U = dyn_cast(S); + if (!U) + return; + if (U->getOpcode() != UO_AddrOf) + return; + + const Expr *E = U->getSubExpr()->IgnoreParenCasts(); + if (const DeclRefExpr *DR = dyn_cast(E)) + if (const VarDecl *VD = dyn_cast(DR->getDecl())) + Escaped.insert(VD); } }; } // end anonymous namespace @@ -438,8 +435,8 @@ public: CFG &cfg = *mgr.getCFG(D); AnalysisDeclContext *AC = mgr.getAnalysisDeclContext(D); ParentMap &pmap = mgr.getParentMap(D); - FindEscaped FS(&cfg); - FS.getCFG().VisitBlockStmts(FS); + FindEscaped FS; + cfg.VisitBlockStmts(FS); DeadStoreObs A(cfg, BR.getContext(), BR, AC, pmap, FS.Escaped); L->runOnAllBlocks(A); }