From 90e1481ef15ec75e3503e0c6e5effad5bd639f01 Mon Sep 17 00:00:00 2001 From: Ted Kremenek Date: Thu, 14 Feb 2008 23:25:54 +0000 Subject: [PATCH] Added "symbol iterators" for RValues, allowing easy iteration over the symbols referenced by an RValue, instead of having to query the type of the RValue. Modified ValueState::RemoveDeadBindings to also prune dead symbols. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@47142 91177308-0d34-0410-b5e6-96231b3b80d8 --- Analysis/RValues.cpp | 26 ++++++++++++++- Analysis/ValueState.cpp | 32 ++++++++++++++++--- Analysis/ValueState.h | 8 +++++ .../clang/Analysis/PathSensitive/RValues.h | 26 +++++++-------- 4 files changed, 73 insertions(+), 19 deletions(-) diff --git a/Analysis/RValues.cpp b/Analysis/RValues.cpp index 8d16f12d32..8eb607c9e5 100644 --- a/Analysis/RValues.cpp +++ b/Analysis/RValues.cpp @@ -123,8 +123,32 @@ ValueManager::getConstraint(SymbolID sym, BinaryOperator::Opcode Op, return *C; } +//===----------------------------------------------------------------------===// +// Symbol Iteration. +//===----------------------------------------------------------------------===// + +RValue::symbol_iterator RValue::symbol_begin() const { + if (isa(this)) { + if (isa(this)) + return (symbol_iterator) (&Data); + } + else { + if (isa(this)) + return (symbol_iterator) (&Data); + else if (isa(this)) { + const SymIntConstraint& C = + cast(this)->getConstraint(); + return (symbol_iterator) &C.getSymbol(); + } + } + + return NULL; +} - +RValue::symbol_iterator RValue::symbol_end() const { + symbol_iterator X = symbol_begin(); + return X ? X+1 : NULL; +} //===----------------------------------------------------------------------===// // Transfer function dispatch for Non-LValues. diff --git a/Analysis/ValueState.cpp b/Analysis/ValueState.cpp index c74c876b51..27818efa34 100644 --- a/Analysis/ValueState.cpp +++ b/Analysis/ValueState.cpp @@ -12,6 +12,7 @@ //===----------------------------------------------------------------------===// #include "ValueState.h" +#include "llvm/ADT/SmallSet.h" using namespace clang; @@ -43,6 +44,8 @@ ValueStateManager::RemoveDeadBindings(ValueState St, Stmt* Loc, // for optimum performance. llvm::SmallVector WList; + llvm::SmallPtrSet Marked; + llvm::SmallSet MarkedSymbols; ValueStateImpl NewSt = *St; @@ -55,10 +58,16 @@ ValueStateManager::RemoveDeadBindings(ValueState St, Stmt* Loc, Expr* BlkExpr = I.getKey(); if (Liveness.isLive(Loc, BlkExpr)) { - if (isa(I.getData())) { - lval::DeclVal LV = cast(I.getData()); + RValue X = I.getData(); + + if (isa(X)) { + lval::DeclVal LV = cast(X); WList.push_back(LV.getDecl()); } + + for (RValue::symbol_iterator SI=X.symbol_begin(), SE=X.symbol_end(); + SI != SE; ++SI) + MarkedSymbols.insert(*SI); } else NewSt.BlockExprBindings = Remove(NewSt, BlkExpr); @@ -70,8 +79,7 @@ ValueStateManager::RemoveDeadBindings(ValueState St, Stmt* Loc, for (ValueState::vb_iterator I = St.vb_begin(), E = St.vb_end(); I!=E ; ++I) if (Liveness.isLive(Loc, I.getKey())) WList.push_back(I.getKey()); - - llvm::SmallPtrSet Marked; + while (!WList.empty()) { ValueDecl* V = WList.back(); @@ -83,7 +91,11 @@ ValueStateManager::RemoveDeadBindings(ValueState St, Stmt* Loc, Marked.insert(V); if (V->getType()->isPointerType()) { - const LValue& LV = cast(GetValue(St, lval::DeclVal(V))); + const LValue& LV = cast(GetValue(St, lval::DeclVal(V))); + + for (RValue::symbol_iterator SI=LV.symbol_begin(), SE=LV.symbol_end(); + SI != SE; ++SI) + MarkedSymbols.insert(*SI); if (!isa(LV)) continue; @@ -93,10 +105,20 @@ ValueStateManager::RemoveDeadBindings(ValueState St, Stmt* Loc, } } + // Remove dead variable bindings. for (ValueState::vb_iterator I = St.vb_begin(), E = St.vb_end(); I!=E ; ++I) if (!Marked.count(I.getKey())) NewSt.VarBindings = Remove(NewSt, I.getKey()); + // Remove dead symbols. + for (ValueState::ce_iterator I = St.ce_begin(), E=St.ce_end(); I!=E; ++I) + if (!MarkedSymbols.count(I.getKey())) + NewSt.ConstantEq = CEFactory.Remove(NewSt.ConstantEq, I.getKey()); + + for (ValueState::cne_iterator I = St.cne_begin(), E=St.cne_end(); I!=E; ++I) + if (!MarkedSymbols.count(I.getKey())) + NewSt.ConstantNotEq = CNEFactory.Remove(NewSt.ConstantNotEq, I.getKey()); + return getPersistentState(NewSt); } diff --git a/Analysis/ValueState.h b/Analysis/ValueState.h index c0bc81deda..38c34cb84a 100644 --- a/Analysis/ValueState.h +++ b/Analysis/ValueState.h @@ -153,6 +153,14 @@ public: beb_iterator beb_begin() const { return Data->BlockExprBindings.begin(); } beb_iterator beb_end() const { return Data->BlockExprBindings.end(); } + typedef ConstantNotEqTy::iterator cne_iterator; + cne_iterator cne_begin() const { return Data->ConstantNotEq.begin(); } + cne_iterator cne_end() const { return Data->ConstantNotEq.end(); } + + typedef ConstantEqTy::iterator ce_iterator; + ce_iterator ce_begin() const { return Data->ConstantEq.begin(); } + ce_iterator ce_end() const { return Data->ConstantEq.end(); } + // Profiling and equality testing. bool operator==(const ValueState& RHS) const { diff --git a/include/clang/Analysis/PathSensitive/RValues.h b/include/clang/Analysis/PathSensitive/RValues.h index 3eb08ff37e..acf841170d 100644 --- a/include/clang/Analysis/PathSensitive/RValues.h +++ b/include/clang/Analysis/PathSensitive/RValues.h @@ -137,7 +137,7 @@ public: Op(op), Val(V) {} BinaryOperator::Opcode getOpcode() const { return Op; } - SymbolID getSymbol() const { return Symbol; } + const SymbolID& getSymbol() const { return Symbol; } const llvm::APSInt& getInt() const { return Val; } static inline void Profile(llvm::FoldingSetNodeID& ID, @@ -249,7 +249,7 @@ public: enum { BaseBits = 2, BaseMask = 0x3 }; -private: +protected: void* Data; unsigned Kind; @@ -261,10 +261,6 @@ protected: explicit RValue(BaseKind k) : Data(0), Kind(k) {} - void* getRawPtr() const { - return reinterpret_cast(Data); - } - public: ~RValue() {}; @@ -293,6 +289,10 @@ public: void print(std::ostream& OS) const; void print() const; + typedef const SymbolID* symbol_iterator; + symbol_iterator symbol_begin() const; + symbol_iterator symbol_end() const; + // Implement isa support. static inline bool classof(const RValue*) { return true; } }; @@ -374,7 +374,7 @@ namespace nonlval { reinterpret_cast((uintptr_t) SymID)) {} SymbolID getSymbol() const { - return (SymbolID) reinterpret_cast(getRawPtr()); + return (SymbolID) reinterpret_cast(Data); } static inline bool classof(const RValue* V) { @@ -388,7 +388,7 @@ namespace nonlval { : NonLValue(SymIntConstraintValKind, reinterpret_cast(&C)) {} const SymIntConstraint& getConstraint() const { - return *reinterpret_cast(getRawPtr()); + return *reinterpret_cast(Data); } static inline bool classof(const RValue* V) { @@ -401,7 +401,7 @@ namespace nonlval { ConcreteInt(const llvm::APSInt& V) : NonLValue(ConcreteIntKind, &V) {} const llvm::APSInt& getValue() const { - return *static_cast(getRawPtr()); + return *static_cast(Data); } // Transfer functions for binary/unary operations on ConcreteInts. @@ -442,7 +442,7 @@ namespace lval { : LValue(SymbolValKind, reinterpret_cast((uintptr_t) SymID)) {} SymbolID getSymbol() const { - return (SymbolID) reinterpret_cast(getRawPtr()); + return (SymbolID) reinterpret_cast(Data); } static inline bool classof(const RValue* V) { @@ -459,7 +459,7 @@ namespace lval { GotoLabel(LabelStmt* Label) : LValue(GotoLabelKind, Label) {} LabelStmt* getLabel() const { - return static_cast(getRawPtr()); + return static_cast(Data); } static inline bool classof(const RValue* V) { @@ -477,7 +477,7 @@ namespace lval { DeclVal(const ValueDecl* vd) : LValue(DeclValKind,vd) {} ValueDecl* getDecl() const { - return static_cast(getRawPtr()); + return static_cast(Data); } inline bool operator==(const DeclVal& R) const { @@ -503,7 +503,7 @@ namespace lval { ConcreteInt(const llvm::APSInt& V) : LValue(ConcreteIntKind, &V) {} const llvm::APSInt& getValue() const { - return *static_cast(getRawPtr()); + return *static_cast(Data); } -- 2.40.0