diff options
Diffstat (limited to 'clang/lib')
-rw-r--r-- | clang/lib/Analysis/BasicStore.cpp | 7 | ||||
-rw-r--r-- | clang/lib/Analysis/BasicValueFactory.cpp | 19 | ||||
-rw-r--r-- | clang/lib/Analysis/BugReporter.cpp | 6 | ||||
-rw-r--r-- | clang/lib/Analysis/CFRefCount.cpp | 20 | ||||
-rw-r--r-- | clang/lib/Analysis/GRExprEngine.cpp | 34 | ||||
-rw-r--r-- | clang/lib/Analysis/GRSimpleVals.cpp | 111 | ||||
-rw-r--r-- | clang/lib/Analysis/GRSimpleVals.h | 2 | ||||
-rw-r--r-- | clang/lib/Analysis/GRTransferFuncs.cpp | 5 | ||||
-rw-r--r-- | clang/lib/Analysis/MemRegion.cpp | 14 | ||||
-rw-r--r-- | clang/lib/Analysis/RegionStore.cpp | 14 | ||||
-rw-r--r-- | clang/lib/Analysis/SVals.cpp | 216 | ||||
-rw-r--r-- | clang/lib/Analysis/SimpleConstraintManager.cpp | 94 | ||||
-rw-r--r-- | clang/lib/Analysis/SimpleConstraintManager.h | 2 | ||||
-rw-r--r-- | clang/lib/Analysis/SymbolManager.cpp | 195 |
14 files changed, 390 insertions, 349 deletions
diff --git a/clang/lib/Analysis/BasicStore.cpp b/clang/lib/Analysis/BasicStore.cpp index 01260480d19..8c5b71f2341 100644 --- a/clang/lib/Analysis/BasicStore.cpp +++ b/clang/lib/Analysis/BasicStore.cpp @@ -197,8 +197,8 @@ SVal BasicStoreManager::getLValueField(const GRState* St, SVal Base, switch(BaseL.getSubKind()) { case loc::SymbolValKind: - BaseR = MRMgr.getSymbolicRegion(cast<loc::SymbolVal>(&BaseL)->getSymbol(), - StateMgr.getSymbolManager()); + BaseR = + MRMgr.getSymbolicRegion(cast<loc::SymbolVal>(&BaseL)->getSymbol()); break; case loc::GotoLabelKind: @@ -243,8 +243,7 @@ SVal BasicStoreManager::getLValueElement(const GRState* St, SVal Base, // Create a region to represent this symbol. // FIXME: In the future we may just use symbolic regions instead of // SymbolVals to reason about symbolic memory chunks. - const MemRegion* SymR = MRMgr.getSymbolicRegion(Sym, - StateMgr.getSymbolManager()); + const MemRegion* SymR = MRMgr.getSymbolicRegion(Sym); // Layered a typed region on top of this. QualType T = StateMgr.getSymbolManager().getType(Sym); BaseR = MRMgr.getTypedViewRegion(T, SymR); diff --git a/clang/lib/Analysis/BasicValueFactory.cpp b/clang/lib/Analysis/BasicValueFactory.cpp index 6ceab93b086..72ad0a5ed8f 100644 --- a/clang/lib/Analysis/BasicValueFactory.cpp +++ b/clang/lib/Analysis/BasicValueFactory.cpp @@ -97,25 +97,6 @@ const llvm::APSInt& BasicValueFactory::getValue(uint64_t X, QualType T) { return getValue(V); } -const SymIntConstraint& -BasicValueFactory::getConstraint(SymbolRef sym, BinaryOperator::Opcode Op, - const llvm::APSInt& V) { - - llvm::FoldingSetNodeID ID; - SymIntConstraint::Profile(ID, sym, Op, V); - void* InsertPos; - - SymIntConstraint* C = SymIntCSet.FindNodeOrInsertPos(ID, InsertPos); - - if (!C) { - C = (SymIntConstraint*) BPAlloc.Allocate<SymIntConstraint>(); - new (C) SymIntConstraint(sym, Op, V); - SymIntCSet.InsertNode(C, InsertPos); - } - - return *C; -} - const CompoundValData* BasicValueFactory::getCompoundValData(QualType T, llvm::ImmutableList<SVal> Vals) { diff --git a/clang/lib/Analysis/BugReporter.cpp b/clang/lib/Analysis/BugReporter.cpp index ffa1593fd56..6807c9f08e0 100644 --- a/clang/lib/Analysis/BugReporter.cpp +++ b/clang/lib/Analysis/BugReporter.cpp @@ -443,7 +443,7 @@ public: bool HandleBinding(StoreManager& SMgr, Store store, const MemRegion* R, SVal V) { - SymbolRef ScanSym; + SymbolRef ScanSym = 0; if (loc::SymbolVal* SV = dyn_cast<loc::SymbolVal>(&V)) ScanSym = SV->getSymbol(); @@ -545,7 +545,7 @@ public: bool HandleBinding(StoreManager& SMgr, Store store, const MemRegion* R, SVal V) { - SymbolRef ScanSym; + SymbolRef ScanSym = 0; if (loc::SymbolVal* SV = dyn_cast<loc::SymbolVal>(&V)) ScanSym = SV->getSymbol(); @@ -554,7 +554,7 @@ public: else return true; - assert (ScanSym.isValid()); + assert (ScanSym); if (!BR.isNotable(ScanSym)) return true; diff --git a/clang/lib/Analysis/CFRefCount.cpp b/clang/lib/Analysis/CFRefCount.cpp index be1d794252c..6e43ec5fafb 100644 --- a/clang/lib/Analysis/CFRefCount.cpp +++ b/clang/lib/Analysis/CFRefCount.cpp @@ -1591,8 +1591,8 @@ public: static void PrintPool(std::ostream &Out, SymbolRef Sym, const GRState *state) { Out << ' '; - if (Sym.isValid()) - Out << Sym; + if (Sym) + Out << Sym->getSymbolID(); else Out << "<pool>"; Out << ":{"; @@ -1705,7 +1705,7 @@ void CFRefCount::EvalSummary(ExplodedNodeSet<GRState>& Dst, SVal V = state.GetSValAsScalarOrLoc(*I); SymbolRef Sym = V.getAsLocSymbol(); - if (Sym.isValid()) + if (Sym) if (RefBindings::data_type* T = state.get<RefBindings>(Sym)) { state = Update(state, Sym, *T, GetArgE(Summ, idx), hasErr); if (hasErr) { @@ -1746,7 +1746,7 @@ void CFRefCount::EvalSummary(ExplodedNodeSet<GRState>& Dst, SymbolRef Sym = state.GetSValAsScalarOrLoc(R).getAsLocSymbol(); // Remove any existing reference-count binding. - if (Sym.isValid()) state = state.remove<RefBindings>(Sym); + if (Sym) state = state.remove<RefBindings>(Sym); if (R->isBoundable(Ctx)) { // Set the value of the variable to be a conjured symbol. @@ -1833,7 +1833,7 @@ void CFRefCount::EvalSummary(ExplodedNodeSet<GRState>& Dst, // Evaluate the effect on the message receiver. if (!ErrorExpr && Receiver) { SymbolRef Sym = state.GetSValAsScalarOrLoc(Receiver).getAsLocSymbol(); - if (Sym.isValid()) { + if (Sym) { if (const RefVal* T = state.get<RefBindings>(Sym)) { state = Update(state, Sym, *T, GetReceiverE(Summ), hasErr); if (hasErr) { @@ -1977,7 +1977,7 @@ void CFRefCount::EvalObjCMessageExpr(ExplodedNodeSet<GRState>& Dst, SVal V = Eng.getStateManager().GetSValAsScalarOrLoc(St, Receiver); SymbolRef Sym = V.getAsLocSymbol(); - if (Sym.isValid()) { + if (Sym) { if (const RefVal* T = St->get<RefBindings>(Sym)) { QualType Ty = T->getType(); @@ -2127,7 +2127,7 @@ void CFRefCount::EvalReturn(ExplodedNodeSet<GRState>& Dst, GRStateRef state(Builder.GetState(Pred), Eng.getStateManager()); SymbolRef Sym = state.GetSValAsScalarOrLoc(RetE).getAsLocSymbol(); - if (!Sym.isValid()) + if (!Sym) return; // Get the reference count binding (if any). @@ -2824,9 +2824,9 @@ class VISIBILITY_HIDDEN FindUniqueBinding : bool HandleBinding(StoreManager& SMgr, Store store, const MemRegion* R, SVal val) { - SymbolRef SymV = val.getAsSymbol(); - - if (!SymV.isValid() || SymV != Sym) + + SymbolRef SymV = val.getAsSymbol(); + if (!SymV || SymV != Sym) return true; if (Binding) { diff --git a/clang/lib/Analysis/GRExprEngine.cpp b/clang/lib/Analysis/GRExprEngine.cpp index 80467ebb273..2f3f0bf5ccb 100644 --- a/clang/lib/Analysis/GRExprEngine.cpp +++ b/clang/lib/Analysis/GRExprEngine.cpp @@ -782,7 +782,8 @@ void GRExprEngine::ProcessSwitch(SwitchNodeBuilder& builder) { do { nonloc::ConcreteInt CaseVal(getBasicVals().getValue(V1.Val.getInt())); - SVal Res = EvalBinOp(BinaryOperator::EQ, CondV, CaseVal); + SVal Res = EvalBinOp(BinaryOperator::EQ, CondV, CaseVal, + getContext().IntTy); // Now "assume" that the case matches. bool isFeasible = false; @@ -1449,7 +1450,7 @@ void GRExprEngine::EvalEagerlyAssume(NodeSet &Dst, NodeSet &Src, Expr *Ex) { const GRState* state = Pred->getState(); SVal V = GetSVal(state, Ex); - if (isa<nonloc::SymIntConstraintVal>(V)) { + if (isa<nonloc::SymExprVal>(V)) { // First assume that the condition is true. bool isFeasible = false; const GRState *stateTrue = Assume(state, V, true, isFeasible); @@ -1940,8 +1941,7 @@ void GRExprEngine::VisitCast(Expr* CastE, Expr* Ex, NodeTy* Pred, NodeSet& Dst){ } StoreManager& StoreMgr = getStoreManager(); - const MemRegion* R = - StoreMgr.getRegionManager().getSymbolicRegion(Sym, getSymbolManager()); + const MemRegion* R = StoreMgr.getRegionManager().getSymbolicRegion(Sym); // Delegate to store manager to get the result of casting a region // to a different type. @@ -2394,7 +2394,8 @@ void GRExprEngine::VisitUnaryOperator(UnaryOperator* U, NodeTy* Pred, if (isa<Loc>(V)) { loc::ConcreteInt X(getBasicVals().getZeroWithPtrWidth()); - SVal Result = EvalBinOp(BinaryOperator::EQ, cast<Loc>(V), X); + SVal Result = EvalBinOp(BinaryOperator::EQ, cast<Loc>(V), X, + U->getType()); state = BindExpr(state, U, Result); } else { @@ -2403,7 +2404,8 @@ void GRExprEngine::VisitUnaryOperator(UnaryOperator* U, NodeTy* Pred, SVal Result = EvalBinOp(BinaryOperator::EQ, cast<NonLoc>(V), X); state = SetSVal(state, U, Result); #else - EvalBinOp(Dst, U, BinaryOperator::EQ, cast<NonLoc>(V), X, *I); + EvalBinOp(Dst, U, BinaryOperator::EQ, cast<NonLoc>(V), X, *I, + U->getType()); continue; #endif } @@ -2449,7 +2451,7 @@ void GRExprEngine::VisitUnaryOperator(UnaryOperator* U, NodeTy* Pred, BinaryOperator::Opcode Op = U->isIncrementOp() ? BinaryOperator::Add : BinaryOperator::Sub; - SVal Result = EvalBinOp(Op, V2, MakeConstantVal(1U, U)); + SVal Result = EvalBinOp(Op, V2, MakeConstantVal(1U, U), U->getType()); // Conjure a new symbol if necessary to recover precision. if (Result.isUnknown() || !getConstraintManager().canReasonAbout(Result)) @@ -2643,7 +2645,6 @@ void GRExprEngine::VisitBinaryOperator(BinaryOperator* B, return; } - if (B->isAssignmentOp()) VisitLValue(LHS, Pred, Tmp1); else @@ -2716,7 +2717,7 @@ void GRExprEngine::VisitBinaryOperator(BinaryOperator* B, // Process non-assignements except commas or short-circuited // logical expressions (LAnd and LOr). - SVal Result = EvalBinOp(Op, LeftV, RightV); + SVal Result = EvalBinOp(Op, LeftV, RightV, B->getType()); if (Result.isUnknown()) { if (OldSt != state) { @@ -2828,7 +2829,7 @@ void GRExprEngine::VisitBinaryOperator(BinaryOperator* B, } // Compute the result of the operation. - SVal Result = EvalCast(EvalBinOp(Op, V, RightV), B->getType()); + SVal Result = EvalCast(EvalBinOp(Op, V, RightV, CTy), B->getType()); if (Result.isUndef()) { // The operands were not undefined, but the result is undefined. @@ -2882,10 +2883,10 @@ void GRExprEngine::VisitBinaryOperator(BinaryOperator* B, void GRExprEngine::EvalBinOp(ExplodedNodeSet<GRState>& Dst, Expr* Ex, BinaryOperator::Opcode Op, NonLoc L, NonLoc R, - ExplodedNode<GRState>* Pred) { + ExplodedNode<GRState>* Pred, QualType T) { GRStateSet OStates; - EvalBinOp(OStates, GetState(Pred), Ex, Op, L, R); + EvalBinOp(OStates, GetState(Pred), Ex, Op, L, R, T); for (GRStateSet::iterator I=OStates.begin(), E=OStates.end(); I!=E; ++I) MakeNode(Dst, Ex, Pred, *I); @@ -2893,13 +2894,14 @@ void GRExprEngine::EvalBinOp(ExplodedNodeSet<GRState>& Dst, Expr* Ex, void GRExprEngine::EvalBinOp(GRStateSet& OStates, const GRState* state, Expr* Ex, BinaryOperator::Opcode Op, - NonLoc L, NonLoc R) { + NonLoc L, NonLoc R, QualType T) { GRStateSet::AutoPopulate AP(OStates, state); - if (R.isValid()) getTF().EvalBinOpNN(OStates, *this, state, Ex, Op, L, R); + if (R.isValid()) getTF().EvalBinOpNN(OStates, *this, state, Ex, Op, L, R, T); } -SVal GRExprEngine::EvalBinOp(BinaryOperator::Opcode Op, SVal L, SVal R) { +SVal GRExprEngine::EvalBinOp(BinaryOperator::Opcode Op, SVal L, SVal R, + QualType T) { if (L.isUndef() || R.isUndef()) return UndefinedVal(); @@ -2926,7 +2928,7 @@ SVal GRExprEngine::EvalBinOp(BinaryOperator::Opcode Op, SVal L, SVal R) { } else return getTF().DetermEvalBinOpNN(*this, Op, cast<NonLoc>(L), - cast<NonLoc>(R)); + cast<NonLoc>(R), T); } //===----------------------------------------------------------------------===// diff --git a/clang/lib/Analysis/GRSimpleVals.cpp b/clang/lib/Analysis/GRSimpleVals.cpp index 22ccd7b8aa9..3bd51ecd72c 100644 --- a/clang/lib/Analysis/GRSimpleVals.cpp +++ b/clang/lib/Analysis/GRSimpleVals.cpp @@ -131,7 +131,8 @@ static unsigned char LNotOpMap[] = { SVal GRSimpleVals::DetermEvalBinOpNN(GRExprEngine& Eng, BinaryOperator::Opcode Op, - NonLoc L, NonLoc R) { + NonLoc L, NonLoc R, + QualType T) { BasicValueFactory& BasicVals = Eng.getBasicVals(); unsigned subkind = L.getSubKind(); @@ -173,34 +174,35 @@ SVal GRSimpleVals::DetermEvalBinOpNN(GRExprEngine& Eng, } } - case nonloc::SymIntConstraintValKind: { - + case nonloc::SymExprValKind: { // Logical not? if (!(Op == BinaryOperator::EQ && R.isZeroConstant())) return UnknownVal(); - - const SymIntConstraint& C = - cast<nonloc::SymIntConstraintVal>(L).getConstraint(); - - BinaryOperator::Opcode Opc = C.getOpcode(); - - if (Opc < BinaryOperator::LT || Opc > BinaryOperator::NE) - return UnknownVal(); - // For comparison operators, translate the constraint by - // changing the opcode. + const SymExpr &SE=*cast<nonloc::SymExprVal>(L).getSymbolicExpression(); - int idx = (unsigned) Opc - (unsigned) BinaryOperator::LT; + // Only handle ($sym op constant) for now. + if (const SymIntExpr *E = dyn_cast<SymIntExpr>(&SE)) { + BinaryOperator::Opcode Opc = E->getOpcode(); - assert (idx >= 0 && - (unsigned) idx < sizeof(LNotOpMap)/sizeof(unsigned char)); + if (Opc < BinaryOperator::LT || Opc > BinaryOperator::NE) + return UnknownVal(); + + // For comparison operators, translate the constraint by + // changing the opcode. + int idx = (unsigned) Opc - (unsigned) BinaryOperator::LT; - Opc = (BinaryOperator::Opcode) LNotOpMap[idx]; + assert (idx >= 0 && + (unsigned) idx < sizeof(LNotOpMap)/sizeof(unsigned char)); - const SymIntConstraint& CNew = - BasicVals.getConstraint(C.getSymbol(), Opc, C.getInt()); + Opc = (BinaryOperator::Opcode) LNotOpMap[idx]; + assert(E->getType(Eng.getContext()) == T); + E = Eng.getSymbolManager().getSymIntExpr(E->getLHS(), Opc, + E->getRHS(), T); + return nonloc::SymExprVal(E); + } - return nonloc::SymIntConstraintVal(CNew); + return UnknownVal(); } case nonloc::ConcreteIntKind: @@ -231,14 +233,18 @@ SVal GRSimpleVals::DetermEvalBinOpNN(GRExprEngine& Eng, case nonloc::SymbolValKind: if (isa<nonloc::ConcreteInt>(R)) { if (Op >= BinaryOperator::LT && Op <= BinaryOperator::NE) { - const SymIntConstraint& C = - BasicVals.getConstraint(cast<nonloc::SymbolVal>(L).getSymbol(), - Op, cast<nonloc::ConcreteInt>(R).getValue()); - return nonloc::SymIntConstraintVal(C); + const SymIntExpr *SE = + Eng.getSymbolManager().getSymIntExpr( + cast<nonloc::SymbolVal>(L).getSymbol(), Op, + cast<nonloc::ConcreteInt>(R).getValue(),T); + + + return nonloc::SymExprVal(SE); } else { return NonLoc::MakeVal(Eng.getSymbolManager(), cast<nonloc::SymbolVal>(L).getSymbol(), - Op, cast<nonloc::ConcreteInt>(R).getValue()); + Op, cast<nonloc::ConcreteInt>(R).getValue(), + T); } } else @@ -308,25 +314,28 @@ TryAgain: } else if (isa<loc::SymbolVal>(R)) { - const SymIntConstraint& C = - BasicVals.getConstraint(cast<loc::SymbolVal>(R).getSymbol(), - BinaryOperator::EQ, - cast<loc::ConcreteInt>(L).getValue()); + const SymIntExpr *SE = + Eng.getSymbolManager().getSymIntExpr(cast<loc::SymbolVal>(R).getSymbol(), + BinaryOperator::EQ, + cast<loc::ConcreteInt>(L).getValue(), + Eng.getContext().IntTy); - return nonloc::SymIntConstraintVal(C); + return nonloc::SymExprVal(SE); } break; case loc::SymbolValKind: { - if (isa<loc::ConcreteInt>(R)) { - const SymIntConstraint& C = - BasicVals.getConstraint(cast<loc::SymbolVal>(L).getSymbol(), - BinaryOperator::EQ, - cast<loc::ConcreteInt>(R).getValue()); + if (isa<loc::ConcreteInt>(R)) { + const SymIntExpr *SE = + Eng.getSymbolManager().getSymIntExpr( + cast<loc::SymbolVal>(L).getSymbol(), + BinaryOperator::EQ, + cast<loc::ConcreteInt>(R).getValue(), + Eng.getContext().IntTy); - return nonloc::SymIntConstraintVal(C); + return nonloc::SymExprVal(SE); } // FIXME: Implement == for lval Symbols. This is mainly useful @@ -378,25 +387,27 @@ TryAgain: return NonLoc::MakeIntTruthVal(BasicVals, b); } - else if (isa<loc::SymbolVal>(R)) { - const SymIntConstraint& C = - BasicVals.getConstraint(cast<loc::SymbolVal>(R).getSymbol(), - BinaryOperator::NE, - cast<loc::ConcreteInt>(L).getValue()); - - return nonloc::SymIntConstraintVal(C); + else if (isa<loc::SymbolVal>(R)) { + const SymIntExpr * SE = + Eng.getSymbolManager().getSymIntExpr( + cast<loc::SymbolVal>(R).getSymbol(), + BinaryOperator::NE, + cast<loc::ConcreteInt>(L).getValue(), + Eng.getContext().IntTy); + return nonloc::SymExprVal(SE); } break; case loc::SymbolValKind: { - if (isa<loc::ConcreteInt>(R)) { - const SymIntConstraint& C = - BasicVals.getConstraint(cast<loc::SymbolVal>(L).getSymbol(), - BinaryOperator::NE, - cast<loc::ConcreteInt>(R).getValue()); - - return nonloc::SymIntConstraintVal(C); + if (isa<loc::ConcreteInt>(R)) { + const SymIntExpr *SE = + Eng.getSymbolManager().getSymIntExpr( + cast<loc::SymbolVal>(L).getSymbol(), + BinaryOperator::NE, + cast<loc::ConcreteInt>(R).getValue(), + Eng.getContext().IntTy); + return nonloc::SymExprVal(SE); } // FIXME: Implement != for lval Symbols. This is mainly useful diff --git a/clang/lib/Analysis/GRSimpleVals.h b/clang/lib/Analysis/GRSimpleVals.h index 6848ced2be7..efe7c631ab2 100644 --- a/clang/lib/Analysis/GRSimpleVals.h +++ b/clang/lib/Analysis/GRSimpleVals.h @@ -29,7 +29,7 @@ protected: virtual SVal DetermEvalBinOpNN(GRExprEngine& Eng, BinaryOperator::Opcode Op, - NonLoc L, NonLoc R); + NonLoc L, NonLoc R, QualType T); public: GRSimpleVals() {} diff --git a/clang/lib/Analysis/GRTransferFuncs.cpp b/clang/lib/Analysis/GRTransferFuncs.cpp index c08bd8f0b19..69c09d9a2ec 100644 --- a/clang/lib/Analysis/GRTransferFuncs.cpp +++ b/clang/lib/Analysis/GRTransferFuncs.cpp @@ -21,7 +21,8 @@ void GRTransferFuncs::EvalBinOpNN(GRStateSet& OStates, GRExprEngine& Eng, const GRState *St, Expr* Ex, BinaryOperator::Opcode Op, - NonLoc L, NonLoc R) { + NonLoc L, NonLoc R, QualType T) { - OStates.Add(Eng.getStateManager().BindExpr(St, Ex, DetermEvalBinOpNN(Eng, Op, L, R))); + OStates.Add(Eng.getStateManager().BindExpr(St, Ex, + DetermEvalBinOpNN(Eng, Op, L, R, T))); } diff --git a/clang/lib/Analysis/MemRegion.cpp b/clang/lib/Analysis/MemRegion.cpp index 5bfc989eb80..738e8c67d69 100644 --- a/clang/lib/Analysis/MemRegion.cpp +++ b/clang/lib/Analysis/MemRegion.cpp @@ -112,10 +112,8 @@ void ElementRegion::Profile(llvm::FoldingSetNodeID& ID) const { //===----------------------------------------------------------------------===// QualType SymbolicRegion::getRValueType(ASTContext& C) const { - const SymbolData& data = SymMgr.getSymbolData(sym); - // Get the type of the symbol. - QualType T = data.getType(C); + QualType T = sym->getType(C); if (const PointerType* PTy = T->getAsPointerType()) return PTy->getPointeeType(); @@ -132,8 +130,7 @@ QualType SymbolicRegion::getRValueType(ASTContext& C) const { } QualType SymbolicRegion::getLValueType(ASTContext& C) const { - const SymbolData& data = SymMgr.getSymbolData(sym); - return data.getType(C); + return sym->getType(C); } QualType ElementRegion::getRValueType(ASTContext& C) const { @@ -332,12 +329,9 @@ MemRegionManager::getElementRegion(SVal Idx, const TypedRegion* superRegion){ } /// getSymbolicRegion - Retrieve or create a "symbolic" memory region. -SymbolicRegion* MemRegionManager::getSymbolicRegion(const SymbolRef sym, - const SymbolManager& mgr) { - +SymbolicRegion* MemRegionManager::getSymbolicRegion(SymbolRef sym) { llvm::FoldingSetNodeID ID; SymbolicRegion::ProfileRegion(ID, sym); - void* InsertPos; MemRegion* data = Regions.FindNodeOrInsertPos(ID, InsertPos); SymbolicRegion* R = cast_or_null<SymbolicRegion>(data); @@ -345,7 +339,7 @@ SymbolicRegion* MemRegionManager::getSymbolicRegion(const SymbolRef sym, if (!R) { R = (SymbolicRegion*) A.Allocate<SymbolicRegion>(); // SymbolicRegion's storage class is usually unknown. - new (R) SymbolicRegion(sym, mgr, getUnknownRegion()); + new (R) SymbolicRegion(sym, getUnknownRegion()); Regions.InsertNode(R, InsertPos); } diff --git a/clang/lib/Analysis/RegionStore.cpp b/clang/lib/Analysis/RegionStore.cpp index 78dda87392d..f23369c8e11 100644 --- a/clang/lib/Analysis/RegionStore.cpp +++ b/clang/lib/Analysis/RegionStore.cpp @@ -367,8 +367,7 @@ SVal RegionStoreManager::getLValueFieldOrIvar(const GRState* St, SVal Base, break; case loc::SymbolValKind: - BaseR = MRMgr.getSymbolicRegion(cast<loc::SymbolVal>(&BaseL)->getSymbol(), - StateMgr.getSymbolManager()); + BaseR = MRMgr.getSymbolicRegion(cast<loc::SymbolVal>(&BaseL)->getSymbol()); break; case loc::GotoLabelKind: @@ -412,11 +411,9 @@ SVal RegionStoreManager::getLValueElement(const GRState* St, const TypedRegion* BaseRegion = 0; - if (isa<loc::SymbolVal>(Base)) - BaseRegion = MRMgr.getSymbolicRegion(cast<loc::SymbolVal>(Base).getSymbol(), - StateMgr.getSymbolManager()); - else - BaseRegion = cast<TypedRegion>(cast<loc::MemRegionVal>(Base).getRegion()); + BaseRegion = isa<loc::SymbolVal>(Base) + ? MRMgr.getSymbolicRegion(cast<loc::SymbolVal>(Base).getSymbol()) + : cast<TypedRegion>(cast<loc::MemRegionVal>(Base).getRegion()); // Pointer of any type can be cast and used as array base. const ElementRegion *ElemR = dyn_cast<ElementRegion>(BaseRegion); @@ -862,8 +859,7 @@ Store RegionStoreManager::Remove(Store store, Loc L) { if (isa<loc::MemRegionVal>(L)) R = cast<loc::MemRegionVal>(L).getRegion(); else if (isa<loc::SymbolVal>(L)) - R = MRMgr.getSymbolicRegion(cast<loc::SymbolVal>(L).getSymbol(), - StateMgr.getSymbolManager()); + R = MRMgr.getSymbolicRegion(cast<loc::SymbolVal>(L).getSymbol()); if (R) { RegionBindingsTy B = GetRegionBindings(store); diff --git a/clang/lib/Analysis/SVals.cpp b/clang/lib/Analysis/SVals.cpp index 0f345602a22..9225f994d3f 100644 --- a/clang/lib/Analysis/SVals.cpp +++ b/clang/lib/Analysis/SVals.cpp @@ -22,37 +22,13 @@ using llvm::cast; using llvm::APSInt; //===----------------------------------------------------------------------===// -// Symbol Iteration. +// Symbol iteration within an SVal. //===----------------------------------------------------------------------===// -SVal::symbol_iterator SVal::symbol_begin() const { - // FIXME: This is a rat's nest. Cleanup. - - if (isa<loc::SymbolVal>(this)) - return symbol_iterator(SymbolRef((uintptr_t)Data)); - else if (isa<nonloc::SymbolVal>(this)) - return symbol_iterator(SymbolRef((uintptr_t)Data)); - else if (isa<nonloc::SymIntConstraintVal>(this)) { - const SymIntConstraint& C = - cast<nonloc::SymIntConstraintVal>(this)->getConstraint(); - return symbol_iterator(C.getSymbol()); - } - else if (isa<nonloc::LocAsInteger>(this)) { - const nonloc::LocAsInteger& V = cast<nonloc::LocAsInteger>(*this); - return V.getPersistentLoc().symbol_begin(); - } - else if (isa<loc::MemRegionVal>(this)) { - const MemRegion* R = cast<loc::MemRegionVal>(this)->getRegion(); - if (const SymbolicRegion* S = dyn_cast<SymbolicRegion>(R)) - return symbol_iterator(S->getSymbol()); - } - - return symbol_iterator(); -} -SVal::symbol_iterator SVal::symbol_end() const { - return symbol_iterator(); -} +//===----------------------------------------------------------------------===// +// Utility methods. +//===----------------------------------------------------------------------===// /// getAsLocSymbol - If this SVal is a location (subclasses Loc) and /// wraps a symbol, return that SymbolRef. Otherwise return a SymbolRef @@ -78,7 +54,7 @@ SymbolRef SVal::getAsLocSymbol() const { } } - return SymbolRef(); + return 0; } /// getAsSymbol - If this Sval wraps a symbol return that SymbolRef. @@ -87,9 +63,66 @@ SymbolRef SVal::getAsSymbol() const { if (const nonloc::SymbolVal *X = dyn_cast<nonloc::SymbolVal>(this)) return X->getSymbol(); + if (const nonloc::SymExprVal *X = dyn_cast<nonloc::SymExprVal>(this)) + if (SymbolRef Y = dyn_cast<SymbolData>(X->getSymbolicExpression())) + return Y; + return getAsLocSymbol(); } +/// getAsSymbolicExpression - If this Sval wraps a symbolic expression then +/// return that expression. Otherwise return NULL. +const SymExpr *SVal::getAsSymbolicExpression() const { + if (const nonloc::SymExprVal *X = dyn_cast<nonloc::SymExprVal>(this)) + return X->getSymbolicExpression(); + + return getAsSymbol(); +} + +bool SVal::symbol_iterator::operator==(const symbol_iterator &X) const { + return itr == X.itr; +} + +bool SVal::symbol_iterator::operator!=(const symbol_iterator &X) const { + return itr != X.itr; +} + +SVal::symbol_iterator::symbol_iterator(const SymExpr *SE) { + itr.push_back(SE); + while (!isa<SymbolData>(itr.back())) expand(); +} + +SVal::symbol_iterator& SVal::symbol_iterator::operator++() { + assert(!itr.empty() && "attempting to iterate on an 'end' iterator"); + assert(isa<SymbolData>(itr.back())); + itr.pop_back(); + if (!itr.empty()) + while (!isa<SymbolData>(itr.back())) expand(); + return *this; +} + +SymbolRef SVal::symbol_iterator::operator*() { + assert(!itr.empty() && "attempting to dereference an 'end' iterator"); + return cast<SymbolData>(itr.back()); +} + +void SVal::symbol_iterator::expand() { + const SymExpr *SE = itr.back(); + itr.pop_back(); + + if (const SymIntExpr *SIE = dyn_cast<SymIntExpr>(SE)) { + itr.push_back(SIE->getLHS()); + return; + } + else if (const SymSymExpr *SSE = dyn_cast<SymSymExpr>(SE)) { + itr.push_back(SSE->getLHS()); + itr.push_back(SSE->getRHS()); + return; + } + + assert(false && "unhandled expansion case"); +} + //===----------------------------------------------------------------------===// // Other Iterators. //===----------------------------------------------------------------------===// @@ -168,7 +201,7 @@ SVal loc::ConcreteInt::EvalBinOp(BasicValueFactory& BasicVals, return UndefinedVal(); } -NonLoc Loc::EQ(BasicValueFactory& BasicVals, const Loc& R) const { +NonLoc Loc::EQ(SymbolManager& SymMgr, const Loc& R) const { switch (getSubKind()) { default: @@ -180,49 +213,48 @@ NonLoc Loc::EQ(BasicValueFactory& BasicVals, const Loc& R) const { bool b = cast<loc::ConcreteInt>(this)->getValue() == cast<loc::ConcreteInt>(R).getValue(); - return NonLoc::MakeIntTruthVal(BasicVals, b); + return NonLoc::MakeIntTruthVal(SymMgr.getBasicVals(), b); } else if (isa<loc::SymbolVal>(R)) { - - const SymIntConstraint& C = - BasicVals.getConstraint(cast<loc::SymbolVal>(R).getSymbol(), + const SymIntExpr *SE = + SymMgr.getSymIntExpr(cast<loc::SymbolVal>(R).getSymbol(), BinaryOperator::EQ, - cast<loc::ConcreteInt>(this)->getValue()); + cast<loc::ConcreteInt>(this)->getValue(), + SymMgr.getContext().IntTy); - return nonloc::SymIntConstraintVal(C); + return nonloc::SymExprVal(SE); } break; case loc::SymbolValKind: { if (isa<loc::ConcreteInt>(R)) { - - const SymIntConstraint& C = - BasicVals.getConstraint(cast<loc::SymbolVal>(this)->getSymbol(), + const SymIntExpr *SE = + SymMgr.getSymIntExpr(cast<loc::SymbolVal>(this)->getSymbol(), BinaryOperator::EQ, - cast<loc::ConcreteInt>(R).getValue()); + cast<loc::ConcreteInt>(R).getValue(), + SymMgr.getContext().IntTy); - return nonloc::SymIntConstraintVal(C); + return nonloc::SymExprVal(SE); } - - assert (!isa<loc::SymbolVal>(R) && "FIXME: Implement unification."); - + + assert (!isa<loc::SymbolVal>(R) && "FIXME: Implement unification."); break; } case loc::MemRegionKind: if (isa<loc::MemRegionVal>(R)) { bool b = cast<loc::MemRegionVal>(*this) == cast<loc::MemRegionVal>(R); - return NonLoc::MakeIntTruthVal(BasicVals, b); + return NonLoc::MakeIntTruthVal(SymMgr.getBasicVals(), b); } break; } - return NonLoc::MakeIntTruthVal(BasicVals, false); + return NonLoc::MakeIntTruthVal(SymMgr.getBasicVals(), false); } -NonLoc Loc::NE(BasicValueFactory& BasicVals, const Loc& R) const { +NonLoc Loc::NE(SymbolManager& SymMgr, const Loc& R) const { switch (getSubKind()) { default: assert(false && "NE not implemented for this Loc."); @@ -233,46 +265,43 @@ NonLoc Loc::NE(BasicValueFactory& BasicVals, const Loc& R) const { bool b = cast<loc::ConcreteInt>(this)->getValue() != cast<loc::ConcreteInt>(R).getValue(); - return NonLoc::MakeIntTruthVal(BasicVals, b); + return NonLoc::MakeIntTruthVal(SymMgr.getBasicVals(), b); } else if (isa<loc::SymbolVal>(R)) { - - const SymIntConstraint& C = - BasicVals.getConstraint(cast<loc::SymbolVal>(R).getSymbol(), - BinaryOperator::NE, - cast<loc::ConcreteInt>(this)->getValue()); - - return nonloc::SymIntConstraintVal(C); + const SymIntExpr *SE = + SymMgr.getSymIntExpr(cast<loc::SymbolVal>(R).getSymbol(), + BinaryOperator::NE, + cast<loc::ConcreteInt>(this)->getValue(), + SymMgr.getContext().IntTy); + return nonloc::SymExprVal(SE); } - break; case loc::SymbolValKind: { if (isa<loc::ConcreteInt>(R)) { + const SymIntExpr *SE = + SymMgr.getSymIntExpr(cast<loc::SymbolVal>(this)->getSymbol(), + BinaryOperator::NE, + cast<loc::ConcreteInt>(R).getValue(), + SymMgr.getContext().IntTy); - const SymIntConstraint& C = - BasicVals.getConstraint(cast<loc::SymbolVal>(this)->getSymbol(), - BinaryOperator::NE, - cast<loc::ConcreteInt>(R).getValue()); - - return nonloc::SymIntConstraintVal(C); + return nonloc::SymExprVal(SE); } assert (!isa<loc::SymbolVal>(R) && "FIXME: Implement sym !=."); - break; } case loc::MemRegionKind: if (isa<loc::MemRegionVal>(R)) { bool b = cast<loc::MemRegionVal>(*this)==cast<loc::MemRegionVal>(R); - return NonLoc::MakeIntTruthVal(BasicVals, b); + return NonLoc::MakeIntTruthVal(SymMgr.getBasicVals(), b); } break; } - return NonLoc::MakeIntTruthVal(BasicVals, true); + return NonLoc::MakeIntTruthVal(SymMgr.getBasicVals(), true); } //===----------------------------------------------------------------------===// @@ -283,21 +312,21 @@ NonLoc NonLoc::MakeVal(SymbolRef sym) { return nonloc::SymbolVal(sym); } -NonLoc NonLoc::MakeVal(SymbolManager& SymMgr, SymbolRef lhs, - BinaryOperator::Opcode op, const APSInt& v) { +NonLoc NonLoc::MakeVal(SymbolManager& SymMgr, const SymExpr *lhs, + BinaryOperator::Opcode op, const APSInt& v, QualType T) { // The Environment ensures we always get a persistent APSInt in // BasicValueFactory, so we don't need to get the APSInt from // BasicValueFactory again. - - SymbolRef sym = SymMgr.getSymIntExpr(lhs, op, v, SymMgr.getType(lhs)); - return nonloc::SymbolVal(sym); + assert(!Loc::IsLocType(T)); + return nonloc::SymExprVal(SymMgr.getSymIntExpr(lhs, op, v, T)); } -NonLoc NonLoc::MakeVal(SymbolManager& SymMgr, SymbolRef lhs, - BinaryOperator::Opcode op, SymbolRef rhs) { +NonLoc NonLoc::MakeVal(SymbolManager& SymMgr, const SymExpr *lhs, + BinaryOperator::Opcode op, const SymExpr *rhs, +QualType T) { assert(SymMgr.getType(lhs) == SymMgr.getType(rhs)); - SymbolRef sym = SymMgr.getSymSymExpr(lhs, op, rhs, SymMgr.getType(lhs)); - return nonloc::SymbolVal(sym); + assert(!Loc::IsLocType(T)); + return nonloc::SymExprVal(SymMgr.getSymSymExpr(lhs, op, rhs, T)); } NonLoc NonLoc::MakeIntVal(BasicValueFactory& BasicVals, uint64_t X, @@ -419,30 +448,6 @@ void SVal::print(llvm::raw_ostream& Out) const { } } -static void printOpcode(llvm::raw_ostream& Out, BinaryOperator::Opcode Op) { - - switch (Op) { - case BinaryOperator::Mul: Out << '*' ; break; - case BinaryOperator::Div: Out << '/' ; break; - case BinaryOperator::Rem: Out << '%' ; break; - case BinaryOperator::Add: Out << '+' ; break; - case BinaryOperator::Sub: Out << '-' ; break; - case BinaryOperator::Shl: Out << "<<" ; break; - case BinaryOperator::Shr: Out << ">>" ; break; - case BinaryOperator::LT: Out << "<" ; break; - case BinaryOperator::GT: Out << '>' ; break; - case BinaryOperator::LE: Out << "<=" ; break; - case BinaryOperator::GE: Out << ">=" ; break; - case BinaryOperator::EQ: Out << "==" ; break; - case BinaryOperator::NE: Out << "!=" ; break; - case BinaryOperator::And: Out << '&' ; break; - case BinaryOperator::Xor: Out << '^' ; break; - case BinaryOperator::Or: Out << '|' ; break; - - default: assert(false && "Not yet implemented."); - } -} - void NonLoc::print(llvm::raw_ostream& Out) const { switch (getSubKind()) { @@ -459,17 +464,10 @@ void NonLoc::print(llvm::raw_ostream& Out) const { Out << '$' << cast<nonloc::SymbolVal>(this)->getSymbol(); break; - case nonloc::SymIntConstraintValKind: { - const nonloc::SymIntConstraintVal& C = - *cast<nonloc::SymIntConstraintVal>(this); - - Out << '$' << C.getConstraint().getSymbol() << ' '; - printOpcode(Out, C.getConstraint().getOpcode()); - Out << ' ' << C.getConstraint().getInt().getZExtValue(); - - if (C.getConstraint().getInt().isUnsigned()) - Out << 'U'; - + case nonloc::SymExprValKind: { + const nonloc::SymExprVal& C = *cast<nonloc::SymExprVal>(this); + const SymExpr *SE = C.getSymbolicExpression(); + Out << SE; break; } diff --git a/clang/lib/Analysis/SimpleConstraintManager.cpp b/clang/lib/Analysis/SimpleConstraintManager.cpp index 50552c11440..904479c4c3a 100644 --- a/clang/lib/Analysis/SimpleConstraintManager.cpp +++ b/clang/lib/Analysis/SimpleConstraintManager.cpp @@ -21,11 +21,35 @@ namespace clang { SimpleConstraintManager::~SimpleConstraintManager() {} bool SimpleConstraintManager::canReasonAbout(SVal X) const { - if (nonloc::SymbolVal* SymVal = dyn_cast<nonloc::SymbolVal>(&X)) { - const SymbolData& data - = getSymbolManager().getSymbolData(SymVal->getSymbol()); - return !(data.getKind() == SymbolData::SymIntKind || - data.getKind() == SymbolData::SymSymKind ); + if (nonloc::SymExprVal *SymVal = dyn_cast<nonloc::SymExprVal>(&X)) { + const SymExpr *SE = SymVal->getSymbolicExpression(); + + if (isa<SymbolData>(SE)) + return true; + + if (const SymIntExpr *SIE = dyn_cast<SymIntExpr>(SE)) { + switch (SIE->getOpcode()) { + // We don't reason yet about bitwise-constraints on symbolic values. + case BinaryOperator::And: + case BinaryOperator::Or: + case BinaryOperator::Xor: + return false; + // We don't reason yet about arithmetic constraints on symbolic values. + case BinaryOperator::Mul: + case BinaryOperator::Div: + case BinaryOperator::Rem: + case BinaryOperator::Add: + case BinaryOperator::Sub: + case BinaryOperator::Shl: + case BinaryOperator::Shr: + return false; + // All other cases. + default: + return true; + } + } + + return false; } return true; @@ -150,11 +174,14 @@ SimpleConstraintManager::AssumeAux(const GRState* St,NonLoc Cond, return AssumeSymEQ(St, sym, BasicVals.getValue(0, T), isFeasible); } - case nonloc::SymIntConstraintValKind: - return - AssumeSymInt(St, Assumption, - cast<nonloc::SymIntConstraintVal>(Cond).getConstraint(), - isFeasible); + case nonloc::SymExprValKind: { + nonloc::SymExprVal V = cast<nonloc::SymExprVal>(Cond); + if (const SymIntExpr *SE = dyn_cast<SymIntExpr>(V.getSymbolicExpression())) + return AssumeSymInt(St, Assumption, SE, isFeasible); + + isFeasible = true; + return St; + } case nonloc::ConcreteIntKind: { bool b = cast<nonloc::ConcreteInt>(Cond).getValue() != 0; @@ -170,50 +197,43 @@ SimpleConstraintManager::AssumeAux(const GRState* St,NonLoc Cond, const GRState* SimpleConstraintManager::AssumeSymInt(const GRState* St, bool Assumption, - const SymIntConstraint& C, - bool& isFeasible) { + const SymIntExpr *SE, bool& isFeasible) { + - switch (C.getOpcode()) { + // Here we assume that LHS is a symbol. This is consistent with the + // rest of the constraint manager logic. + SymbolRef Sym = cast<SymbolData>(SE->getLHS()); + const llvm::APSInt &Int = SE->getRHS(); + + switch (SE->getOpcode()) { default: // No logic yet for other operators. isFeasible = true; return St; case BinaryOperator::EQ: - if (Assumption) - return AssumeSymEQ(St, C.getSymbol(), C.getInt(), isFeasible); - else - return AssumeSymNE(St, C.getSymbol(), C.getInt(), isFeasible); + return Assumption ? AssumeSymEQ(St, Sym, Int, isFeasible) + : AssumeSymNE(St, Sym, Int, isFeasible); case BinaryOperator::NE: - if (Assumption) - return AssumeSymNE(St, C.getSymbol(), C.getInt(), isFeasible); - else - return AssumeSymEQ(St, C.getSymbol(), C.getInt(), isFeasible); + return Assumption ? AssumeSymNE(St, Sym, Int, isFeasible) + : AssumeSymEQ(St, Sym, Int, isFeasible); case BinaryOperator::GT: - if (Assumption) - return AssumeSymGT(St, C.getSymbol(), C.getInt(), isFeasible); - else - return AssumeSymLE(St, C.getSymbol(), C.getInt(), isFeasible); + return Assumption ? AssumeSymGT(St, Sym, Int, isFeasible) + : AssumeSymLE(St, Sym, Int, isFeasible); case BinaryOperator::GE: - if (Assumption) - return AssumeSymGE(St, C.getSymbol(), C.getInt(), isFeasible); - else - return AssumeSymLT(St, C.getSymbol(), C.getInt(), isFeasible); + return Assumption ? AssumeSymGE(St, Sym, Int, isFeasible) + : AssumeSymLT(St, Sym, Int, isFeasible); case BinaryOperator::LT: - if (Assumption) - return AssumeSymLT(St, C.getSymbol(), C.getInt(), isFeasible); - else - return AssumeSymGE(St, C.getSymbol(), C.getInt(), isFeasible); + return Assumption ? AssumeSymLT(St, Sym, Int, isFeasible) + : AssumeSymGE(St, Sym, Int, isFeasible); case BinaryOperator::LE: - if (Assumption) - return AssumeSymLE(St, C.getSymbol(), C.getInt(), isFeasible); - else - return AssumeSymGT(St, C.getSymbol(), C.getInt(), isFeasible); + return Assumption ? AssumeSymLE(St, Sym, Int, isFeasible) + : AssumeSymGT(St, Sym, Int, isFeasible); } // end switch } diff --git a/clang/lib/Analysis/SimpleConstraintManager.h b/clang/lib/Analysis/SimpleConstraintManager.h index 8195c8ed36e..fb41e2f1dab 100644 --- a/clang/lib/Analysis/SimpleConstraintManager.h +++ b/clang/lib/Analysis/SimpleConstraintManager.h @@ -45,7 +45,7 @@ public: bool& isFeasible); const GRState* AssumeSymInt(const GRState* St, bool Assumption, - const SymIntConstraint& C, bool& isFeasible); + const SymIntExpr *SE, bool& isFeasible); virtual const GRState* AssumeSymNE(const GRState* St, SymbolRef sym, const llvm::APSInt& V, diff --git a/clang/lib/Analysis/SymbolManager.cpp b/clang/lib/Analysis/SymbolManager.cpp index 33d6a5722e2..f8e2db72688 100644 --- a/clang/lib/Analysis/SymbolManager.cpp +++ b/clang/lib/Analysis/SymbolManager.cpp @@ -18,110 +18,149 @@ using namespace clang; -llvm::raw_ostream& llvm::operator<<(llvm::raw_ostream& os, - clang::SymbolRef sym) { - if (sym.isValid()) - os << sym.getNumber(); - else - os << "(Invalid)"; +static void print(llvm::raw_ostream& os, const SymExpr *SE); + +static void print(llvm::raw_ostream& os, BinaryOperator::Opcode Op) { + switch (Op) { + default: + assert(false && "operator printing not implemented"); + break; + case BinaryOperator::Mul: os << '*' ; break; + case BinaryOperator::Div: os << '/' ; break; + case BinaryOperator::Rem: os << '%' ; break; + case BinaryOperator::Add: os << '+' ; break; + case BinaryOperator::Sub: os << '-' ; break; + case BinaryOperator::Shl: os << "<<" ; break; + case BinaryOperator::Shr: os << ">>" ; break; + case BinaryOperator::LT: os << "<" ; break; + case BinaryOperator::GT: os << '>' ; break; + case BinaryOperator::LE: os << "<=" ; break; + case BinaryOperator::GE: os << ">=" ; break; + case BinaryOperator::EQ: os << "==" ; break; + case BinaryOperator::NE: os << "!=" ; break; + case BinaryOperator::And: os << '&' ; break; + case BinaryOperator::Xor: os << '^' ; break; + case BinaryOperator::Or: os << '|' ; break; + } +} + +static void print(llvm::raw_ostream& os, const SymIntExpr *SE) { + os << '('; + print(os, SE->getLHS()); + os << ") "; + print(os, SE->getOpcode()); + os << ' ' << SE->getRHS().getZExtValue(); + if (SE->getRHS().isUnsigned()) os << 'U'; +} +static void print(llvm::raw_ostream& os, const SymSymExpr *SE) { + os << '('; + print(os, SE->getLHS()); + os << ") "; + os << '('; + print(os, SE->getRHS()); + os << ')'; +} + +static void print(llvm::raw_ostream& os, const SymExpr *SE) { + switch (SE->getKind()) { + case SymExpr::BEGIN_SYMBOLS: + case SymExpr::RegionRValue: + case SymExpr::ConjuredKind: + case SymExpr::END_SYMBOLS: + os << '$' << cast<SymbolData>(SE)->getSymbolID(); + return; + case SymExpr::SymIntKind: + print(os, cast<SymIntExpr>(SE)); + return; + case SymExpr::SymSymKind: + print(os, cast<SymSymExpr>(SE)); + return; + } +} + + +llvm::raw_ostream& llvm::operator<<(llvm::raw_ostream& os, const SymExpr *SE) { + print(os, SE); return os; } -std::ostream& std::operator<<(std::ostream& os, clang::SymbolRef sym) { - if (sym.isValid()) - os << sym.getNumber(); - else - os << "(Invalid)"; - +std::ostream& std::operator<<(std::ostream& os, const SymExpr *SE) { + llvm::raw_os_ostream O(os); + print(O, SE); return os; } -SymbolRef SymbolManager::getRegionRValueSymbol(const MemRegion* R) { +const SymbolRegionRValue* +SymbolManager::getRegionRValueSymbol(const MemRegion* R) { llvm::FoldingSetNodeID profile; - SymbolRegionRValue::Profile(profile, R); void* InsertPos; - SymbolData* SD = DataSet.FindNodeOrInsertPos(profile, InsertPos); - if (SD) return SD->getSymbol(); + SymExpr *SD = DataSet.FindNodeOrInsertPos(profile, InsertPos); + if (!SD) { + SD = (SymExpr*) BPAlloc.Allocate<SymbolRegionRValue>(); + new (SD) SymbolRegionRValue(SymbolCounter, R); + DataSet.InsertNode(SD, InsertPos); + ++SymbolCounter; + } - SD = (SymbolData*) BPAlloc.Allocate<SymbolRegionRValue>(); - new (SD) SymbolRegionRValue(SymbolCounter, R); - DataSet.InsertNode(SD, InsertPos); - DataMap[SymbolCounter] = SD; - return SymbolCounter++; + return cast<SymbolRegionRValue>(SD); } -SymbolRef SymbolManager::getConjuredSymbol(const Stmt* E, QualType T, - unsigned Count, - const void* SymbolTag) { +const SymbolConjured* +SymbolManager::getConjuredSymbol(const Stmt* E, QualType T, unsigned Count, + const void* SymbolTag) { llvm::FoldingSetNodeID profile; SymbolConjured::Profile(profile, E, T, Count, SymbolTag); - void* InsertPos; - - SymbolData* SD = DataSet.FindNodeOrInsertPos(profile, InsertPos); - - if (SD) - return SD->getSymbol(); - - SD = (SymbolData*) BPAlloc.Allocate<SymbolConjured>(); - new (SD) SymbolConjured(SymbolCounter, E, T, Count, SymbolTag); - - DataSet.InsertNode(SD, InsertPos); - DataMap[SymbolCounter] = SD; + void* InsertPos; + SymExpr *SD = DataSet.FindNodeOrInsertPos(profile, InsertPos); + if (!SD) { + SD = (SymExpr*) BPAlloc.Allocate<SymbolConjured>(); + new (SD) SymbolConjured(SymbolCounter, E, T, Count, SymbolTag); + DataSet.InsertNode(SD, InsertPos); + ++SymbolCounter; + } - return SymbolCounter++; + return cast<SymbolConjured>(SD); } -SymbolRef SymbolManager::getSymIntExpr(SymbolRef lhs,BinaryOperator::Opcode op, - const llvm::APSInt& v, QualType t) { +const SymIntExpr *SymbolManager::getSymIntExpr(const SymExpr *lhs, + BinaryOperator::Opcode op, + const llvm::APSInt& v, + QualType t) { llvm::FoldingSetNodeID ID; SymIntExpr::Profile(ID, lhs, op, v, t); - void* InsertPos; - - SymbolData* data = DataSet.FindNodeOrInsertPos(ID, InsertPos); - - if (data) - return data->getSymbol(); - - data = (SymIntExpr*) BPAlloc.Allocate<SymIntExpr>(); - new (data) SymIntExpr(SymbolCounter, lhs, op, v, t); - - DataSet.InsertNode(data, InsertPos); - DataMap[SymbolCounter] = data; - - return SymbolCounter++; + void *InsertPos; + SymExpr *data = DataSet.FindNodeOrInsertPos(ID, InsertPos); + + if (!data) { + data = (SymIntExpr*) BPAlloc.Allocate<SymIntExpr>(); + new (data) SymIntExpr(lhs, op, v, t); + DataSet.InsertNode(data, InsertPos); + } + + return cast<SymIntExpr>(data); } -SymbolRef SymbolManager::getSymSymExpr(SymbolRef lhs, BinaryOperator::Opcode op, - SymbolRef rhs, QualType t) { +const SymSymExpr *SymbolManager::getSymSymExpr(const SymExpr *lhs, + BinaryOperator::Opcode op, + const SymExpr *rhs, + QualType t) { llvm::FoldingSetNodeID ID; SymSymExpr::Profile(ID, lhs, op, rhs, t); - void* InsertPos; - - SymbolData* data = DataSet.FindNodeOrInsertPos(ID, InsertPos); - - if (data) - return data->getSymbol(); - - data = (SymSymExpr*) BPAlloc.Allocate<SymSymExpr>(); - new (data) SymSymExpr(SymbolCounter, lhs, op, rhs, t); - - DataSet.InsertNode(data, InsertPos); - DataMap[SymbolCounter] = data; - - return SymbolCounter++; -} - - -const SymbolData& SymbolManager::getSymbolData(SymbolRef Sym) const { - DataMapTy::const_iterator I = DataMap.find(Sym); - assert (I != DataMap.end()); - return *I->second; + void *InsertPos; + SymExpr *data = DataSet.FindNodeOrInsertPos(ID, InsertPos); + + if (!data) { + data = (SymSymExpr*) BPAlloc.Allocate<SymSymExpr>(); + new (data) SymSymExpr(lhs, op, rhs, t); + DataSet.InsertNode(data, InsertPos); + } + + return cast<SymSymExpr>(data); } - QualType SymbolConjured::getType(ASTContext&) const { return T; } @@ -158,7 +197,7 @@ bool SymbolReaper::isLive(SymbolRef sym) { // Interogate the symbol. It may derive from an input value to // the analyzed function/method. - return isa<SymbolRegionRValue>(SymMgr.getSymbolData(sym)); + return isa<SymbolRegionRValue>(sym); } SymbolVisitor::~SymbolVisitor() {} |