diff options
Diffstat (limited to 'lib/Analysis')
24 files changed, 1184 insertions, 1150 deletions
diff --git a/lib/Analysis/BasicConstraintManager.cpp b/lib/Analysis/BasicConstraintManager.cpp index b272214..ffa8a86 100644 --- a/lib/Analysis/BasicConstraintManager.cpp +++ b/lib/Analysis/BasicConstraintManager.cpp @@ -51,39 +51,39 @@ class VISIBILITY_HIDDEN BasicConstraintManager GRState::IntSetTy::Factory ISetFactory; public: BasicConstraintManager(GRStateManager& statemgr) - : SimpleConstraintManager(statemgr), ISetFactory(statemgr.getAllocator()) {} + : ISetFactory(statemgr.getAllocator()) {} - const GRState* AssumeSymNE(const GRState* St, SymbolRef sym, - const llvm::APSInt& V, bool& isFeasible); + const GRState* AssumeSymNE(const GRState* state, SymbolRef sym, + const llvm::APSInt& V); - const GRState* AssumeSymEQ(const GRState* St, SymbolRef sym, - const llvm::APSInt& V, bool& isFeasible); + const GRState* AssumeSymEQ(const GRState* state, SymbolRef sym, + const llvm::APSInt& V); - const GRState* AssumeSymLT(const GRState* St, SymbolRef sym, - const llvm::APSInt& V, bool& isFeasible); + const GRState* AssumeSymLT(const GRState* state, SymbolRef sym, + const llvm::APSInt& V); - const GRState* AssumeSymGT(const GRState* St, SymbolRef sym, - const llvm::APSInt& V, bool& isFeasible); + const GRState* AssumeSymGT(const GRState* state, SymbolRef sym, + const llvm::APSInt& V); - const GRState* AssumeSymGE(const GRState* St, SymbolRef sym, - const llvm::APSInt& V, bool& isFeasible); + const GRState* AssumeSymGE(const GRState* state, SymbolRef sym, + const llvm::APSInt& V); - const GRState* AssumeSymLE(const GRState* St, SymbolRef sym, - const llvm::APSInt& V, bool& isFeasible); + const GRState* AssumeSymLE(const GRState* state, SymbolRef sym, + const llvm::APSInt& V); - const GRState* AddEQ(const GRState* St, SymbolRef sym, const llvm::APSInt& V); + const GRState* AddEQ(const GRState* state, SymbolRef sym, const llvm::APSInt& V); - const GRState* AddNE(const GRState* St, SymbolRef sym, const llvm::APSInt& V); + const GRState* AddNE(const GRState* state, SymbolRef sym, const llvm::APSInt& V); - const llvm::APSInt* getSymVal(const GRState* St, SymbolRef sym) const; - bool isNotEqual(const GRState* St, SymbolRef sym, const llvm::APSInt& V) + const llvm::APSInt* getSymVal(const GRState* state, SymbolRef sym) const; + bool isNotEqual(const GRState* state, SymbolRef sym, const llvm::APSInt& V) const; - bool isEqual(const GRState* St, SymbolRef sym, const llvm::APSInt& V) + bool isEqual(const GRState* state, SymbolRef sym, const llvm::APSInt& V) const; - const GRState* RemoveDeadBindings(const GRState* St, SymbolReaper& SymReaper); + const GRState* RemoveDeadBindings(const GRState* state, SymbolReaper& SymReaper); - void print(const GRState* St, std::ostream& Out, + void print(const GRState* state, std::ostream& Out, const char* nl, const char *sep); }; @@ -95,87 +95,77 @@ ConstraintManager* clang::CreateBasicConstraintManager(GRStateManager& StateMgr) } const GRState* -BasicConstraintManager::AssumeSymNE(const GRState* St, SymbolRef sym, - const llvm::APSInt& V, bool& isFeasible) { +BasicConstraintManager::AssumeSymNE(const GRState *state, SymbolRef sym, + const llvm::APSInt& V) { // First, determine if sym == X, where X != V. - if (const llvm::APSInt* X = getSymVal(St, sym)) { - isFeasible = (*X != V); - return St; + if (const llvm::APSInt* X = getSymVal(state, sym)) { + bool isFeasible = (*X != V); + return isFeasible ? state : NULL; } // Second, determine if sym != V. - if (isNotEqual(St, sym, V)) { - isFeasible = true; - return St; - } + if (isNotEqual(state, sym, V)) + return state; // If we reach here, sym is not a constant and we don't know if it is != V. // Make that assumption. - isFeasible = true; - return AddNE(St, sym, V); + return AddNE(state, sym, V); } -const GRState* -BasicConstraintManager::AssumeSymEQ(const GRState* St, SymbolRef sym, - const llvm::APSInt& V, bool& isFeasible) { +const GRState *BasicConstraintManager::AssumeSymEQ(const GRState *state, + SymbolRef sym, + const llvm::APSInt &V) { // First, determine if sym == X, where X != V. - if (const llvm::APSInt* X = getSymVal(St, sym)) { - isFeasible = *X == V; - return St; + if (const llvm::APSInt* X = getSymVal(state, sym)) { + bool isFeasible = *X == V; + return isFeasible ? state : NULL; } // Second, determine if sym != V. - if (isNotEqual(St, sym, V)) { - isFeasible = false; - return St; - } + if (isNotEqual(state, sym, V)) + return NULL; // If we reach here, sym is not a constant and we don't know if it is == V. // Make that assumption. - - isFeasible = true; - return AddEQ(St, sym, V); + return AddEQ(state, sym, V); } // These logic will be handled in another ConstraintManager. -const GRState* -BasicConstraintManager::AssumeSymLT(const GRState* St, SymbolRef sym, - const llvm::APSInt& V, bool& isFeasible) { - +const GRState *BasicConstraintManager::AssumeSymLT(const GRState *state, + SymbolRef sym, + const llvm::APSInt& V) { // Is 'V' the smallest possible value? if (V == llvm::APSInt::getMinValue(V.getBitWidth(), V.isUnsigned())) { // sym cannot be any value less than 'V'. This path is infeasible. - isFeasible = false; - return St; + return NULL; } // FIXME: For now have assuming x < y be the same as assuming sym != V; - return AssumeSymNE(St, sym, V, isFeasible); + return AssumeSymNE(state, sym, V); } -const GRState* -BasicConstraintManager::AssumeSymGT(const GRState* St, SymbolRef sym, - const llvm::APSInt& V, bool& isFeasible) { +const GRState *BasicConstraintManager::AssumeSymGT(const GRState *state, + SymbolRef sym, + const llvm::APSInt& V) { // Is 'V' the largest possible value? if (V == llvm::APSInt::getMaxValue(V.getBitWidth(), V.isUnsigned())) { // sym cannot be any value greater than 'V'. This path is infeasible. - isFeasible = false; - return St; + return NULL; } // FIXME: For now have assuming x > y be the same as assuming sym != V; - return AssumeSymNE(St, sym, V, isFeasible); + return AssumeSymNE(state, sym, V); } -const GRState* -BasicConstraintManager::AssumeSymGE(const GRState* St, SymbolRef sym, - const llvm::APSInt& V, bool& isFeasible) { +const GRState *BasicConstraintManager::AssumeSymGE(const GRState *state, + SymbolRef sym, + const llvm::APSInt &V) { // Reject a path if the value of sym is a constant X and !(X >= V). - if (const llvm::APSInt* X = getSymVal(St, sym)) { - isFeasible = *X >= V; - return St; + if (const llvm::APSInt *X = getSymVal(state, sym)) { + bool isFeasible = *X >= V; + return isFeasible ? state : NULL; } // Sym is not a constant, but it is worth looking to see if V is the @@ -183,28 +173,25 @@ BasicConstraintManager::AssumeSymGE(const GRState* St, SymbolRef sym, if (V == llvm::APSInt::getMaxValue(V.getBitWidth(), V.isUnsigned())) { // If we know that sym != V, then this condition is infeasible since // there is no other value greater than V. - isFeasible = !isNotEqual(St, sym, V); + bool isFeasible = !isNotEqual(state, sym, V); // If the path is still feasible then as a consequence we know that // 'sym == V' because we cannot have 'sym > V' (no larger values). // Add this constraint. - if (isFeasible) - return AddEQ(St, sym, V); + return isFeasible ? AddEQ(state, sym, V) : NULL; } - else - isFeasible = true; - return St; + return state; } const GRState* -BasicConstraintManager::AssumeSymLE(const GRState* St, SymbolRef sym, - const llvm::APSInt& V, bool& isFeasible) { +BasicConstraintManager::AssumeSymLE(const GRState* state, SymbolRef sym, + const llvm::APSInt& V) { // Reject a path if the value of sym is a constant X and !(X <= V). - if (const llvm::APSInt* X = getSymVal(St, sym)) { - isFeasible = *X <= V; - return St; + if (const llvm::APSInt* X = getSymVal(state, sym)) { + bool isFeasible = *X <= V; + return isFeasible ? state : NULL; } // Sym is not a constant, but it is worth looking to see if V is the @@ -212,64 +199,57 @@ BasicConstraintManager::AssumeSymLE(const GRState* St, SymbolRef sym, if (V == llvm::APSInt::getMinValue(V.getBitWidth(), V.isUnsigned())) { // If we know that sym != V, then this condition is infeasible since // there is no other value less than V. - isFeasible = !isNotEqual(St, sym, V); + bool isFeasible = !isNotEqual(state, sym, V); // If the path is still feasible then as a consequence we know that // 'sym == V' because we cannot have 'sym < V' (no smaller values). // Add this constraint. - if (isFeasible) - return AddEQ(St, sym, V); + return isFeasible ? AddEQ(state, sym, V) : NULL; } - else - isFeasible = true; - return St; + return state; } -const GRState* BasicConstraintManager::AddEQ(const GRState* St, SymbolRef sym, +const GRState* BasicConstraintManager::AddEQ(const GRState* state, SymbolRef sym, const llvm::APSInt& V) { // Create a new state with the old binding replaced. - GRStateRef state(St, StateMgr); - return state.set<ConstEq>(sym, &V); + return state->set<ConstEq>(sym, &V); } -const GRState* BasicConstraintManager::AddNE(const GRState* St, SymbolRef sym, +const GRState* BasicConstraintManager::AddNE(const GRState* state, SymbolRef sym, const llvm::APSInt& V) { - GRStateRef state(St, StateMgr); - // First, retrieve the NE-set associated with the given symbol. - ConstNotEqTy::data_type* T = state.get<ConstNotEq>(sym); + ConstNotEqTy::data_type* T = state->get<ConstNotEq>(sym); GRState::IntSetTy S = T ? *T : ISetFactory.GetEmptySet(); - // Now add V to the NE set. S = ISetFactory.Add(S, &V); // Create a new state with the old binding replaced. - return state.set<ConstNotEq>(sym, S); + return state->set<ConstNotEq>(sym, S); } -const llvm::APSInt* BasicConstraintManager::getSymVal(const GRState* St, +const llvm::APSInt* BasicConstraintManager::getSymVal(const GRState* state, SymbolRef sym) const { - const ConstEqTy::data_type* T = St->get<ConstEq>(sym); + const ConstEqTy::data_type* T = state->get<ConstEq>(sym); return T ? *T : NULL; } -bool BasicConstraintManager::isNotEqual(const GRState* St, SymbolRef sym, +bool BasicConstraintManager::isNotEqual(const GRState* state, SymbolRef sym, const llvm::APSInt& V) const { // Retrieve the NE-set associated with the given symbol. - const ConstNotEqTy::data_type* T = St->get<ConstNotEq>(sym); + const ConstNotEqTy::data_type* T = state->get<ConstNotEq>(sym); // See if V is present in the NE-set. return T ? T->contains(&V) : false; } -bool BasicConstraintManager::isEqual(const GRState* St, SymbolRef sym, +bool BasicConstraintManager::isEqual(const GRState* state, SymbolRef sym, const llvm::APSInt& V) const { // Retrieve the EQ-set associated with the given symbol. - const ConstEqTy::data_type* T = St->get<ConstEq>(sym); + const ConstEqTy::data_type* T = state->get<ConstEq>(sym); // See if V is present in the EQ-set. return T ? **T == V : false; } @@ -277,35 +257,34 @@ bool BasicConstraintManager::isEqual(const GRState* St, SymbolRef sym, /// Scan all symbols referenced by the constraints. If the symbol is not alive /// as marked in LSymbols, mark it as dead in DSymbols. const GRState* -BasicConstraintManager::RemoveDeadBindings(const GRState* St, +BasicConstraintManager::RemoveDeadBindings(const GRState* state, SymbolReaper& SymReaper) { - GRStateRef state(St, StateMgr); - ConstEqTy CE = state.get<ConstEq>(); - ConstEqTy::Factory& CEFactory = state.get_context<ConstEq>(); + ConstEqTy CE = state->get<ConstEq>(); + ConstEqTy::Factory& CEFactory = state->get_context<ConstEq>(); for (ConstEqTy::iterator I = CE.begin(), E = CE.end(); I!=E; ++I) { SymbolRef sym = I.getKey(); if (SymReaper.maybeDead(sym)) CE = CEFactory.Remove(CE, sym); } - state = state.set<ConstEq>(CE); + state = state->set<ConstEq>(CE); - ConstNotEqTy CNE = state.get<ConstNotEq>(); - ConstNotEqTy::Factory& CNEFactory = state.get_context<ConstNotEq>(); + ConstNotEqTy CNE = state->get<ConstNotEq>(); + ConstNotEqTy::Factory& CNEFactory = state->get_context<ConstNotEq>(); for (ConstNotEqTy::iterator I = CNE.begin(), E = CNE.end(); I != E; ++I) { SymbolRef sym = I.getKey(); if (SymReaper.maybeDead(sym)) CNE = CNEFactory.Remove(CNE, sym); } - return state.set<ConstNotEq>(CNE); + return state->set<ConstNotEq>(CNE); } -void BasicConstraintManager::print(const GRState* St, std::ostream& Out, +void BasicConstraintManager::print(const GRState* state, std::ostream& Out, const char* nl, const char *sep) { // Print equality constraints. - ConstEqTy CE = St->get<ConstEq>(); + ConstEqTy CE = state->get<ConstEq>(); if (!CE.isEmpty()) { Out << nl << sep << "'==' constraints:"; @@ -319,7 +298,7 @@ void BasicConstraintManager::print(const GRState* St, std::ostream& Out, // Print != constraints. - ConstNotEqTy CNE = St->get<ConstNotEq>(); + ConstNotEqTy CNE = state->get<ConstNotEq>(); if (!CNE.isEmpty()) { Out << nl << sep << "'!=' constraints:"; diff --git a/lib/Analysis/BasicObjCFoundationChecks.cpp b/lib/Analysis/BasicObjCFoundationChecks.cpp index 98e9551..aa85769 100644 --- a/lib/Analysis/BasicObjCFoundationChecks.cpp +++ b/lib/Analysis/BasicObjCFoundationChecks.cpp @@ -66,9 +66,6 @@ class VISIBILITY_HIDDEN BasicObjCFoundationChecks : public GRSimpleAPICheck { APIMisuse *BT; BugReporter& BR; ASTContext &Ctx; - GRStateManager* VMgr; - - SVal GetSVal(const GRState* St, Expr* E) { return VMgr->GetSVal(St, E); } bool isNSString(ObjCInterfaceType* T, const char* suffix); bool AuditNSString(NodeTy* N, ObjCMessageExpr* ME); @@ -79,9 +76,8 @@ class VISIBILITY_HIDDEN BasicObjCFoundationChecks : public GRSimpleAPICheck { bool CheckNilArg(NodeTy* N, unsigned Arg); public: - BasicObjCFoundationChecks(ASTContext& ctx, GRStateManager* vmgr, - BugReporter& br) - : BT(0), BR(br), Ctx(ctx), VMgr(vmgr) {} + BasicObjCFoundationChecks(ASTContext& ctx, BugReporter& br) + : BT(0), BR(br), Ctx(ctx) {} bool Audit(ExplodedNode<GRState>* N, GRStateManager&); @@ -106,10 +102,8 @@ private: GRSimpleAPICheck* -clang::CreateBasicObjCFoundationChecks(ASTContext& Ctx, - GRStateManager* VMgr, BugReporter& BR) { - - return new BasicObjCFoundationChecks(Ctx, VMgr, BR); +clang::CreateBasicObjCFoundationChecks(ASTContext& Ctx, BugReporter& BR) { + return new BasicObjCFoundationChecks(Ctx, BR); } @@ -157,7 +151,7 @@ bool BasicObjCFoundationChecks::CheckNilArg(NodeTy* N, unsigned Arg) { Expr * E = ME->getArg(Arg); - if (isNil(GetSVal(N->getState(), E))) { + if (isNil(N->getState()->getSVal(E))) { WarnNilArg(N, ME, Arg); return true; } @@ -259,14 +253,11 @@ class VISIBILITY_HIDDEN AuditCFNumberCreate : public GRSimpleAPICheck { // approach makes this class more stateless. ASTContext& Ctx; IdentifierInfo* II; - GRStateManager* VMgr; BugReporter& BR; - - SVal GetSVal(const GRState* St, Expr* E) { return VMgr->GetSVal(St, E); } - + public: - AuditCFNumberCreate(ASTContext& ctx, GRStateManager* vmgr, BugReporter& br) - : BT(0), Ctx(ctx), II(&Ctx.Idents.get("CFNumberCreate")), VMgr(vmgr), BR(br){} + AuditCFNumberCreate(ASTContext& ctx, BugReporter& br) + : BT(0), Ctx(ctx), II(&Ctx.Idents.get("CFNumberCreate")), BR(br){} ~AuditCFNumberCreate() {} @@ -374,14 +365,14 @@ static const char* GetCFNumberTypeStr(uint64_t i) { bool AuditCFNumberCreate::Audit(ExplodedNode<GRState>* N,GRStateManager&){ CallExpr* CE = cast<CallExpr>(cast<PostStmt>(N->getLocation()).getStmt()); Expr* Callee = CE->getCallee(); - SVal CallV = GetSVal(N->getState(), Callee); + SVal CallV = N->getState()->getSVal(Callee); const FunctionDecl* FD = CallV.getAsFunctionDecl(); if (!FD || FD->getIdentifier() != II || CE->getNumArgs()!=3) return false; // Get the value of the "theType" argument. - SVal TheTypeVal = GetSVal(N->getState(), CE->getArg(1)); + SVal TheTypeVal = N->getState()->getSVal(CE->getArg(1)); // FIXME: We really should allow ranges of valid theType values, and // bifurcate the state appropriately. @@ -400,7 +391,7 @@ bool AuditCFNumberCreate::Audit(ExplodedNode<GRState>* N,GRStateManager&){ // Look at the value of the integer being passed by reference. Essentially // we want to catch cases where the value passed in is not equal to the // size of the type being created. - SVal TheValueExpr = GetSVal(N->getState(), CE->getArg(2)); + SVal TheValueExpr = N->getState()->getSVal(CE->getArg(2)); // FIXME: Eventually we should handle arbitrary locations. We can do this // by having an enhanced memory model that does low-level typing. @@ -469,9 +460,8 @@ void AuditCFNumberCreate::AddError(const TypedRegion* R, Expr* Ex, } GRSimpleAPICheck* -clang::CreateAuditCFNumberCreate(ASTContext& Ctx, - GRStateManager* VMgr, BugReporter& BR) { - return new AuditCFNumberCreate(Ctx, VMgr, BR); +clang::CreateAuditCFNumberCreate(ASTContext& Ctx, BugReporter& BR) { + return new AuditCFNumberCreate(Ctx, BR); } //===----------------------------------------------------------------------===// @@ -479,13 +469,12 @@ clang::CreateAuditCFNumberCreate(ASTContext& Ctx, void clang::RegisterAppleChecks(GRExprEngine& Eng) { ASTContext& Ctx = Eng.getContext(); - GRStateManager* VMgr = &Eng.getStateManager(); BugReporter &BR = Eng.getBugReporter(); - Eng.AddCheck(CreateBasicObjCFoundationChecks(Ctx, VMgr, BR), + Eng.AddCheck(CreateBasicObjCFoundationChecks(Ctx, BR), Stmt::ObjCMessageExprClass); - Eng.AddCheck(CreateAuditCFNumberCreate(Ctx, VMgr, BR), + Eng.AddCheck(CreateAuditCFNumberCreate(Ctx, BR), Stmt::CallExprClass); RegisterNSErrorChecks(BR, Eng); diff --git a/lib/Analysis/BasicObjCFoundationChecks.h b/lib/Analysis/BasicObjCFoundationChecks.h index 6c594ea..5c9701e 100644 --- a/lib/Analysis/BasicObjCFoundationChecks.h +++ b/lib/Analysis/BasicObjCFoundationChecks.h @@ -33,11 +33,9 @@ class BugReporter; class GRExprEngine; GRSimpleAPICheck* CreateBasicObjCFoundationChecks(ASTContext& Ctx, - GRStateManager* VMgr, BugReporter& BR); GRSimpleAPICheck* CreateAuditCFNumberCreate(ASTContext& Ctx, - GRStateManager* VMgr, BugReporter& BR); void RegisterNSErrorChecks(BugReporter& BR, GRExprEngine &Eng); diff --git a/lib/Analysis/BasicStore.cpp b/lib/Analysis/BasicStore.cpp index 2dd46c3..fcb405d 100644 --- a/lib/Analysis/BasicStore.cpp +++ b/lib/Analysis/BasicStore.cpp @@ -45,15 +45,14 @@ public: ~BasicStoreManager() {} - SubRegionMap* getSubRegionMap(const GRState *state) { + SubRegionMap *getSubRegionMap(const GRState *state) { return new BasicStoreSubRegionMap(); } SVal Retrieve(const GRState *state, Loc loc, QualType T = QualType()); - const GRState* Bind(const GRState* St, Loc L, SVal V) { - Store store = BindInternal(St->getStore(), L, V); - return StateMgr.MakeStateWithStore(St, store); + const GRState *Bind(const GRState *state, Loc L, SVal V) { + return state->makeWithStore(BindInternal(state->getStore(), L, V)); } Store scanForIvars(Stmt *B, const Decl* SelfDecl, Store St); @@ -67,19 +66,19 @@ public: return Loc::MakeVal(MRMgr.getVarRegion(VD)); } - const GRState* BindCompoundLiteral(const GRState* St, - const CompoundLiteralExpr* CL, - SVal V) { - return St; + const GRState *BindCompoundLiteral(const GRState *state, + const CompoundLiteralExpr* cl, + SVal val) { + return state; } - SVal getLValueVar(const GRState* St, const VarDecl* VD); - SVal getLValueString(const GRState* St, const StringLiteral* S); - SVal getLValueCompoundLiteral(const GRState* St, + SVal getLValueVar(const GRState *state, const VarDecl* VD); + SVal getLValueString(const GRState *state, const StringLiteral* S); + SVal getLValueCompoundLiteral(const GRState *state, const CompoundLiteralExpr* CL); - SVal getLValueIvar(const GRState* St, const ObjCIvarDecl* D, SVal Base); - SVal getLValueField(const GRState* St, SVal Base, const FieldDecl* D); - SVal getLValueElement(const GRState* St, QualType elementType, + SVal getLValueIvar(const GRState *state, const ObjCIvarDecl* D, SVal Base); + SVal getLValueField(const GRState *state, SVal Base, const FieldDecl* D); + SVal getLValueElement(const GRState *state, QualType elementType, SVal Base, SVal Offset); /// ArrayToPointer - Used by GRExprEngine::VistCast to handle implicit @@ -92,23 +91,19 @@ public: const MemRegion* getSelfRegion(Store) { return SelfRegion; } /// RemoveDeadBindings - Scans a BasicStore of 'state' for dead values. - /// It returns a new Store with these values removed, and populates LSymbols - /// and DSymbols with the known set of live and dead symbols respectively. - Store - RemoveDeadBindings(const GRState* state, Stmt* Loc, + /// It returns a new Store with these values removed. + Store RemoveDeadBindings(const GRState *state, Stmt* Loc, SymbolReaper& SymReaper, llvm::SmallVectorImpl<const MemRegion*>& RegionRoots); void iterBindings(Store store, BindingsHandler& f); - const GRState* BindDecl(const GRState* St, const VarDecl* VD, SVal InitVal) { - Store store = BindDeclInternal(St->getStore(), VD, &InitVal); - return StateMgr.MakeStateWithStore(St, store); + const GRState *BindDecl(const GRState *state, const VarDecl* VD, SVal InitVal) { + return state->makeWithStore(BindDeclInternal(state->getStore(),VD, &InitVal)); } - const GRState* BindDeclWithNoInit(const GRState* St, const VarDecl* VD) { - Store store = BindDeclInternal(St->getStore(), VD, 0); - return StateMgr.MakeStateWithStore(St, store); + const GRState *BindDeclWithNoInit(const GRState *state, const VarDecl* VD) { + return state->makeWithStore(BindDeclInternal(state->getStore(), VD, 0)); } Store BindDeclInternal(Store store, const VarDecl* VD, SVal* InitVal); @@ -130,21 +125,21 @@ StoreManager* clang::CreateBasicStoreManager(GRStateManager& StMgr) { return new BasicStoreManager(StMgr); } -SVal BasicStoreManager::getLValueVar(const GRState* St, const VarDecl* VD) { +SVal BasicStoreManager::getLValueVar(const GRState *state, const VarDecl* VD) { return Loc::MakeVal(MRMgr.getVarRegion(VD)); } -SVal BasicStoreManager::getLValueString(const GRState* St, +SVal BasicStoreManager::getLValueString(const GRState *state, const StringLiteral* S) { return Loc::MakeVal(MRMgr.getStringRegion(S)); } -SVal BasicStoreManager::getLValueCompoundLiteral(const GRState* St, +SVal BasicStoreManager::getLValueCompoundLiteral(const GRState *state, const CompoundLiteralExpr* CL){ return Loc::MakeVal(MRMgr.getCompoundLiteralRegion(CL)); } -SVal BasicStoreManager::getLValueIvar(const GRState* St, const ObjCIvarDecl* D, +SVal BasicStoreManager::getLValueIvar(const GRState *state, const ObjCIvarDecl* D, SVal Base) { if (Base.isUnknownOrUndef()) @@ -162,7 +157,7 @@ SVal BasicStoreManager::getLValueIvar(const GRState* St, const ObjCIvarDecl* D, return UnknownVal(); } -SVal BasicStoreManager::getLValueField(const GRState* St, SVal Base, +SVal BasicStoreManager::getLValueField(const GRState *state, SVal Base, const FieldDecl* D) { if (Base.isUnknownOrUndef()) @@ -194,7 +189,7 @@ SVal BasicStoreManager::getLValueField(const GRState* St, SVal Base, return Loc::MakeVal(MRMgr.getFieldRegion(D, BaseR)); } -SVal BasicStoreManager::getLValueElement(const GRState* St, +SVal BasicStoreManager::getLValueElement(const GRState *state, QualType elementType, SVal Base, SVal Offset) { @@ -248,7 +243,7 @@ SVal BasicStoreManager::getLValueElement(const GRState* St, if (BaseR) return Loc::MakeVal(MRMgr.getElementRegion(elementType, UnknownVal(), - BaseR)); + BaseR, getContext())); else return UnknownVal(); } @@ -274,7 +269,7 @@ static bool isHigherOrderRawPtr(QualType T, ASTContext &C) { } } -SVal BasicStoreManager::Retrieve(const GRState* state, Loc loc, QualType T) { +SVal BasicStoreManager::Retrieve(const GRState *state, Loc loc, QualType T) { if (isa<UnknownVal>(loc)) return UnknownVal(); @@ -390,7 +385,7 @@ Store BasicStoreManager::Remove(Store store, Loc loc) { } Store -BasicStoreManager::RemoveDeadBindings(const GRState* state, Stmt* Loc, +BasicStoreManager::RemoveDeadBindings(const GRState *state, Stmt* Loc, SymbolReaper& SymReaper, llvm::SmallVectorImpl<const MemRegion*>& RegionRoots) { diff --git a/lib/Analysis/BugReporter.cpp b/lib/Analysis/BugReporter.cpp index 32998e1..5dbbfc3 100644 --- a/lib/Analysis/BugReporter.cpp +++ b/lib/Analysis/BugReporter.cpp @@ -336,7 +336,7 @@ GetMostRecentVarDeclBinding(const ExplodedNode<GRState>* N, if (!DR) continue; - SVal Y = VMgr.GetSVal(N->getState(), DR); + SVal Y = N->getState()->getSVal(DR); if (X != Y) continue; diff --git a/lib/Analysis/CFRefCount.cpp b/lib/Analysis/CFRefCount.cpp index f5ca322..c58ceb4 100644 --- a/lib/Analysis/CFRefCount.cpp +++ b/lib/Analysis/CFRefCount.cpp @@ -971,8 +971,12 @@ RetainSummary* RetainSummaryManager::getSummary(FunctionDecl* FD) { // FIXME: This should all be refactored into a chain of "summary lookup" // filters. + assert (ScratchArgs.isEmpty()); + switch (strlen(FName)) { default: break; + + case 17: // Handle: id NSMakeCollectable(CFTypeRef) if (!memcmp(FName, "NSMakeCollectable", 17)) { @@ -980,13 +984,55 @@ RetainSummary* RetainSummaryManager::getSummary(FunctionDecl* FD) { ? getUnarySummary(FT, cfmakecollectable) : getPersistentStopSummary(); } + else if (!memcmp(FName, "IOBSDNameMatching", 17) || + !memcmp(FName, "IOServiceMatching", 17)) { + // Part of <rdar://problem/6961230>. (IOKit) + // This should be addressed using a API table. + S = getPersistentSummary(RetEffect::MakeOwned(RetEffect::CF, true), + DoNothing, DoNothing); + } break; - + + case 21: + if (!memcmp(FName, "IOServiceNameMatching", 21)) { + // Part of <rdar://problem/6961230>. (IOKit) + // This should be addressed using a API table. + S = getPersistentSummary(RetEffect::MakeOwned(RetEffect::CF, true), + DoNothing, DoNothing); + } + break; + + case 24: + if (!memcmp(FName, "IOServiceAddNotification", 24)) { + // Part of <rdar://problem/6961230>. (IOKit) + // This should be addressed using a API table. + ScratchArgs = AF.Add(ScratchArgs, 2, DecRef); + S = getPersistentSummary(RetEffect::MakeNoRet(), DoNothing, DoNothing); + } + break; + + case 25: + if (!memcmp(FName, "IORegistryEntryIDMatching", 25)) { + // Part of <rdar://problem/6961230>. (IOKit) + // This should be addressed using a API table. + S = getPersistentSummary(RetEffect::MakeOwned(RetEffect::CF, true), + DoNothing, DoNothing); + } + break; + + case 26: + if (!memcmp(FName, "IOOpenFirmwarePathMatching", 26)) { + // Part of <rdar://problem/6961230>. (IOKit) + // This should be addressed using a API table. + S = getPersistentSummary(RetEffect::MakeOwned(RetEffect::CF, true), + DoNothing, DoNothing); + } + break; + case 27: if (!memcmp(FName, "IOServiceGetMatchingService", 27)) { // Part of <rdar://problem/6961230>. // This should be addressed using a API table. - assert (ScratchArgs.isEmpty()); ScratchArgs = AF.Add(ScratchArgs, 1, DecRef); S = getPersistentSummary(RetEffect::MakeNoRet(), DoNothing, DoNothing); } @@ -997,11 +1043,19 @@ RetainSummary* RetainSummaryManager::getSummary(FunctionDecl* FD) { // FIXES: <rdar://problem/6326900> // This should be addressed using a API table. This strcmp is also // a little gross, but there is no need to super optimize here. - assert (ScratchArgs.isEmpty()); ScratchArgs = AF.Add(ScratchArgs, 1, DecRef); S = getPersistentSummary(RetEffect::MakeNoRet(), DoNothing, DoNothing); } break; + + case 32: + if (!memcmp(FName, "IOServiceAddMatchingNotification", 32)) { + // Part of <rdar://problem/6961230>. + // This should be addressed using a API table. + ScratchArgs = AF.Add(ScratchArgs, 2, DecRef); + S = getPersistentSummary(RetEffect::MakeNoRet(), DoNothing, DoNothing); + } + break; } // Did we get a summary? @@ -1195,15 +1249,15 @@ RetainSummaryManager::updateSummaryFromAnnotations(RetainSummary &Summ, // Determine if there is a special return effect for this method. if (isTrackedObjCObjectType(RetTy)) { - if (FD->getAttr<NSReturnsRetainedAttr>()) { + if (FD->getAttr<NSReturnsRetainedAttr>(Ctx)) { Summ.setRetEffect(ObjCAllocRetE); } - else if (FD->getAttr<CFReturnsRetainedAttr>()) { + else if (FD->getAttr<CFReturnsRetainedAttr>(Ctx)) { Summ.setRetEffect(RetEffect::MakeOwned(RetEffect::CF, true)); } } else if (RetTy->getAsPointerType()) { - if (FD->getAttr<CFReturnsRetainedAttr>()) { + if (FD->getAttr<CFReturnsRetainedAttr>(Ctx)) { Summ.setRetEffect(RetEffect::MakeOwned(RetEffect::CF, true)); } } @@ -1217,10 +1271,10 @@ RetainSummaryManager::updateSummaryFromAnnotations(RetainSummary &Summ, // Determine if there is a special return effect for this method. if (isTrackedObjCObjectType(MD->getResultType())) { - if (MD->getAttr<NSReturnsRetainedAttr>()) { + if (MD->getAttr<NSReturnsRetainedAttr>(Ctx)) { Summ.setRetEffect(ObjCAllocRetE); } - else if (MD->getAttr<CFReturnsRetainedAttr>()) { + else if (MD->getAttr<CFReturnsRetainedAttr>(Ctx)) { Summ.setRetEffect(RetEffect::MakeOwned(RetEffect::CF, true)); } } @@ -1485,11 +1539,14 @@ void RetainSummaryManager::InitializeMethodSummaries() { addInstMethSummary("QCView", AllocSumm, "createSnapshotImageOfType", NULL); - // Create summaries for CIContext, 'createCGImage'. + // Create summaries for CIContext, 'createCGImage' and + // 'createCGLayerWithSize'. addInstMethSummary("CIContext", AllocSumm, "createCGImage", "fromRect", NULL); addInstMethSummary("CIContext", AllocSumm, - "createCGImage", "fromRect", "format", "colorSpace", NULL); + "createCGImage", "fromRect", "format", "colorSpace", NULL); + addInstMethSummary("CIContext", AllocSumm, "createCGLayerWithSize", + "info", NULL); } //===----------------------------------------------------------------------===// @@ -1747,11 +1804,11 @@ static SymbolRef GetCurrentAutoreleasePool(const GRState* state) { return stack.isEmpty() ? SymbolRef() : stack.getHead(); } -static GRStateRef SendAutorelease(GRStateRef state, ARCounts::Factory &F, - SymbolRef sym) { +static const GRState * SendAutorelease(const GRState *state, + ARCounts::Factory &F, SymbolRef sym) { SymbolRef pool = GetCurrentAutoreleasePool(state); - const ARCounts *cnts = state.get<AutoreleasePoolContents>(pool); + const ARCounts *cnts = state->get<AutoreleasePoolContents>(pool); ARCounts newCnts(0); if (cnts) { @@ -1761,7 +1818,7 @@ static GRStateRef SendAutorelease(GRStateRef state, ARCounts::Factory &F, else newCnts = F.Add(F.GetEmptyMap(), sym, 1); - return state.set<AutoreleasePoolContents>(pool, newCnts); + return state->set<AutoreleasePoolContents>(pool, newCnts); } //===----------------------------------------------------------------------===// @@ -1794,7 +1851,7 @@ private: BugType *returnNotOwnedForOwned; BugReporter *BR; - GRStateRef Update(GRStateRef state, SymbolRef sym, RefVal V, ArgEffect E, + const GRState * Update(const GRState * state, SymbolRef sym, RefVal V, ArgEffect E, RefVal::Kind& hasErr); void ProcessNonLeakError(ExplodedNodeSet<GRState>& Dst, @@ -1804,10 +1861,10 @@ private: const GRState* St, RefVal::Kind hasErr, SymbolRef Sym); - GRStateRef HandleSymbolDeath(GRStateRef state, SymbolRef sid, RefVal V, + const GRState * HandleSymbolDeath(const GRState * state, SymbolRef sid, RefVal V, llvm::SmallVectorImpl<SymbolRef> &Leaked); - ExplodedNode<GRState>* ProcessLeaks(GRStateRef state, + ExplodedNode<GRState>* ProcessLeaks(const GRState * state, llvm::SmallVectorImpl<SymbolRef> &Leaked, GenericNodeBuilder &Builder, GRExprEngine &Eng, @@ -1882,8 +1939,8 @@ public: Stmt* S, const GRState* state, SymbolReaper& SymReaper); - std::pair<ExplodedNode<GRState>*, GRStateRef> - HandleAutoreleaseCounts(GRStateRef state, GenericNodeBuilder Bd, + std::pair<ExplodedNode<GRState>*, const GRState *> + HandleAutoreleaseCounts(const GRState * state, GenericNodeBuilder Bd, ExplodedNode<GRState>* Pred, GRExprEngine &Eng, SymbolRef Sym, RefVal V, bool &stop); // Return statements. @@ -1896,9 +1953,8 @@ public: // Assumptions. - virtual const GRState* EvalAssume(GRStateManager& VMgr, - const GRState* St, SVal Cond, - bool Assumption, bool& isFeasible); + virtual const GRState *EvalAssume(const GRState* state, SVal condition, + bool assumption); }; } // end anonymous namespace @@ -2226,15 +2282,14 @@ PathDiagnosticPiece* CFRefReport::VisitNode(const ExplodedNode<GRState>* N, return NULL; // Check if the type state has changed. - GRStateManager &StMgr = BRC.getStateManager(); - GRStateRef PrevSt(PrevN->getState(), StMgr); - GRStateRef CurrSt(N->getState(), StMgr); + const GRState *PrevSt = PrevN->getState(); + const GRState *CurrSt = N->getState(); - const RefVal* CurrT = CurrSt.get<RefBindings>(Sym); + const RefVal* CurrT = CurrSt->get<RefBindings>(Sym); if (!CurrT) return NULL; - const RefVal& CurrV = *CurrT; - const RefVal* PrevT = PrevSt.get<RefBindings>(Sym); + const RefVal &CurrV = *CurrT; + const RefVal *PrevT = PrevSt->get<RefBindings>(Sym); // Create a string buffer to constain all the useful things we want // to tell the user. @@ -2248,7 +2303,7 @@ PathDiagnosticPiece* CFRefReport::VisitNode(const ExplodedNode<GRState>* N, if (CallExpr *CE = dyn_cast<CallExpr>(S)) { // Get the name of the callee (if it is available). - SVal X = CurrSt.GetSValAsScalarOrLoc(CE->getCallee()); + SVal X = CurrSt->getSValAsScalarOrLoc(CE->getCallee()); if (const FunctionDecl* FD = X.getAsFunctionDecl()) os << "Call to function '" << FD->getNameAsString() <<'\''; else @@ -2305,7 +2360,7 @@ PathDiagnosticPiece* CFRefReport::VisitNode(const ExplodedNode<GRState>* N, // Retrieve the value of the argument. Is it the symbol // we are interested in? - if (CurrSt.GetSValAsScalarOrLoc(*AI).getAsLocSymbol() != Sym) + if (CurrSt->getSValAsScalarOrLoc(*AI).getAsLocSymbol() != Sym) continue; // We have an argument. Get the effect! @@ -2314,7 +2369,7 @@ PathDiagnosticPiece* CFRefReport::VisitNode(const ExplodedNode<GRState>* N, } else if (ObjCMessageExpr *ME = dyn_cast<ObjCMessageExpr>(S)) { if (Expr *receiver = ME->getReceiver()) - if (CurrSt.GetSValAsScalarOrLoc(receiver).getAsLocSymbol() == Sym) { + if (CurrSt->getSValAsScalarOrLoc(receiver).getAsLocSymbol() == Sym) { // The symbol we are tracking is the receiver. AEffects.push_back(Summ->getReceiverEffect()); } @@ -2342,7 +2397,7 @@ PathDiagnosticPiece* CFRefReport::VisitNode(const ExplodedNode<GRState>* N, if (contains(AEffects, MakeCollectable)) { // Get the name of the function. Stmt* S = cast<PostStmt>(N->getLocation()).getStmt(); - SVal X = CurrSt.GetSValAsScalarOrLoc(cast<CallExpr>(S)->getCallee()); + SVal X = CurrSt->getSValAsScalarOrLoc(cast<CallExpr>(S)->getCallee()); const FunctionDecl* FD = X.getAsFunctionDecl(); const std::string& FName = FD->getNameAsString(); @@ -2453,7 +2508,7 @@ PathDiagnosticPiece* CFRefReport::VisitNode(const ExplodedNode<GRState>* N, // to Sym. for (Stmt::child_iterator I = S->child_begin(), E = S->child_end(); I!=E; ++I) if (Expr* Exp = dyn_cast_or_null<Expr>(*I)) - if (CurrSt.GetSValAsScalarOrLoc(Exp).getAsLocSymbol() == Sym) { + if (CurrSt->getSValAsScalarOrLoc(Exp).getAsLocSymbol() == Sym) { P->addRange(Exp->getSourceRange()); break; } @@ -2705,7 +2760,7 @@ void CFRefCount::EvalSummary(ExplodedNodeSet<GRState>& Dst, // Get the state. GRStateManager& StateMgr = Eng.getStateManager(); - GRStateRef state(Builder.GetState(Pred), StateMgr); + const GRState *state = Builder.GetState(Pred); ASTContext& Ctx = StateMgr.getContext(); ValueManager &ValMgr = Eng.getValueManager(); @@ -2716,11 +2771,11 @@ void CFRefCount::EvalSummary(ExplodedNodeSet<GRState>& Dst, SymbolRef ErrorSym = 0; for (ExprIterator I = arg_beg; I != arg_end; ++I, ++idx) { - SVal V = state.GetSValAsScalarOrLoc(*I); + SVal V = state->getSValAsScalarOrLoc(*I); SymbolRef Sym = V.getAsLocSymbol(); if (Sym) - if (RefBindings::data_type* T = state.get<RefBindings>(Sym)) { + if (RefBindings::data_type* T = state->get<RefBindings>(Sym)) { state = Update(state, Sym, *T, Summ.getArg(idx), hasErr); if (hasErr) { ErrorExpr = *I; @@ -2775,10 +2830,10 @@ void CFRefCount::EvalSummary(ExplodedNodeSet<GRState>& Dst, } // Is the invalidated variable something that we were tracking? - SymbolRef Sym = state.GetSValAsScalarOrLoc(R).getAsLocSymbol(); + SymbolRef Sym = state->getSValAsScalarOrLoc(R).getAsLocSymbol(); // Remove any existing reference-count binding. - if (Sym) 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. @@ -2788,7 +2843,7 @@ void CFRefCount::EvalSummary(ExplodedNodeSet<GRState>& Dst, if (Loc::IsLocType(T) || (T->isIntegerType() && T->isScalarType())){ ValueManager &ValMgr = Eng.getValueManager(); SVal V = ValMgr.getConjuredSymbolVal(*I, T, Count); - state = state.BindLoc(Loc::MakeVal(R), V); + state = state->bindLoc(Loc::MakeVal(R), V); } else if (const RecordType *RT = T->getAsStructureType()) { // Handle structs in a not so awesome way. Here we just @@ -2802,7 +2857,8 @@ void CFRefCount::EvalSummary(ExplodedNodeSet<GRState>& Dst, if (!RD) continue; - MemRegionManager &MRMgr = state.getManager().getRegionManager(); + MemRegionManager &MRMgr = + state->getStateManager().getRegionManager(); // Iterate through the fields and construct new symbols. for (RecordDecl::field_iterator FI=RD->field_begin(Ctx), @@ -2817,7 +2873,7 @@ void CFRefCount::EvalSummary(ExplodedNodeSet<GRState>& Dst, const FieldRegion* FR = MRMgr.getFieldRegion(FD, R); SVal V = ValMgr.getConjuredSymbolVal(*I, FT, Count); - state = state.BindLoc(Loc::MakeVal(FR), V); + state = state->bindLoc(Loc::MakeVal(FR), V); } } } else if (const ArrayType *AT = Ctx.getAsArrayType(T)) { @@ -2825,31 +2881,30 @@ void CFRefCount::EvalSummary(ExplodedNodeSet<GRState>& Dst, StoreManager& StoreMgr = Eng.getStateManager().getStoreManager(); SVal V = ValMgr.getConjuredSymbolVal(*I, AT->getElementType(), Count); - state = GRStateRef(StoreMgr.setDefaultValue(state, R, V), - StateMgr); + state = StoreMgr.setDefaultValue(state, R, V); } else { // Just blast away other values. - state = state.BindLoc(*MR, UnknownVal()); + state = state->bindLoc(*MR, UnknownVal()); } } } else - state = state.BindLoc(*MR, UnknownVal()); + state = state->bindLoc(*MR, UnknownVal()); } else { // Nuke all other arguments passed by reference. - state = state.Unbind(cast<Loc>(V)); + state = state->unbindLoc(cast<Loc>(V)); } } else if (isa<nonloc::LocAsInteger>(V)) - state = state.Unbind(cast<nonloc::LocAsInteger>(V).getLoc()); + state = state->unbindLoc(cast<nonloc::LocAsInteger>(V).getLoc()); } // Evaluate the effect on the message receiver. if (!ErrorExpr && Receiver) { - SymbolRef Sym = state.GetSValAsScalarOrLoc(Receiver).getAsLocSymbol(); + SymbolRef Sym = state->getSValAsScalarOrLoc(Receiver).getAsLocSymbol(); if (Sym) { - if (const RefVal* T = state.get<RefBindings>(Sym)) { + if (const RefVal* T = state->get<RefBindings>(Sym)) { state = Update(state, Sym, *T, Summ.getReceiverEffect(), hasErr); if (hasErr) { ErrorExpr = Receiver; @@ -2871,10 +2926,10 @@ void CFRefCount::EvalSummary(ExplodedNodeSet<GRState>& Dst, if (RE.getKind() == RetEffect::OwnedWhenTrackedReceiver) { assert(Receiver); - SVal V = state.GetSValAsScalarOrLoc(Receiver); + SVal V = state->getSValAsScalarOrLoc(Receiver); bool found = false; if (SymbolRef Sym = V.getAsLocSymbol()) - if (state.get<RefBindings>(Sym)) { + if (state->get<RefBindings>(Sym)) { found = true; RE = Summaries.getObjAllocRetEffect(); } @@ -2902,7 +2957,7 @@ void CFRefCount::EvalSummary(ExplodedNodeSet<GRState>& Dst, unsigned Count = Builder.getCurrentBlockCount(); ValueManager &ValMgr = Eng.getValueManager(); SVal X = ValMgr.getConjuredSymbolVal(Ex, T, Count); - state = state.BindExpr(Ex, X, false); + state = state->bindExpr(Ex, X, false); } break; @@ -2912,15 +2967,15 @@ void CFRefCount::EvalSummary(ExplodedNodeSet<GRState>& Dst, unsigned idx = RE.getIndex(); assert (arg_end >= arg_beg); assert (idx < (unsigned) (arg_end - arg_beg)); - SVal V = state.GetSValAsScalarOrLoc(*(arg_beg+idx)); - state = state.BindExpr(Ex, V, false); + SVal V = state->getSValAsScalarOrLoc(*(arg_beg+idx)); + state = state->bindExpr(Ex, V, false); break; } case RetEffect::ReceiverAlias: { assert (Receiver); - SVal V = state.GetSValAsScalarOrLoc(Receiver); - state = state.BindExpr(Ex, V, false); + SVal V = state->getSValAsScalarOrLoc(Receiver); + state = state->bindExpr(Ex, V, false); break; } @@ -2930,9 +2985,9 @@ void CFRefCount::EvalSummary(ExplodedNodeSet<GRState>& Dst, ValueManager &ValMgr = Eng.getValueManager(); SymbolRef Sym = ValMgr.getConjuredSymbol(Ex, Count); QualType RetT = GetReturnType(Ex, ValMgr.getContext()); - state = state.set<RefBindings>(Sym, RefVal::makeOwned(RE.getObjKind(), + state = state->set<RefBindings>(Sym, RefVal::makeOwned(RE.getObjKind(), RetT)); - state = state.BindExpr(Ex, ValMgr.makeRegionVal(Sym), false); + state = state->bindExpr(Ex, ValMgr.makeRegionVal(Sym), false); // FIXME: Add a flag to the checker where allocations are assumed to // *not fail. @@ -2953,9 +3008,9 @@ void CFRefCount::EvalSummary(ExplodedNodeSet<GRState>& Dst, ValueManager &ValMgr = Eng.getValueManager(); SymbolRef Sym = ValMgr.getConjuredSymbol(Ex, Count); QualType RetT = GetReturnType(Ex, ValMgr.getContext()); - state = state.set<RefBindings>(Sym, RefVal::makeNotOwned(RE.getObjKind(), + state = state->set<RefBindings>(Sym, RefVal::makeNotOwned(RE.getObjKind(), RetT)); - state = state.BindExpr(Ex, ValMgr.makeRegionVal(Sym), false); + state = state->bindExpr(Ex, ValMgr.makeRegionVal(Sym), false); break; } } @@ -3001,7 +3056,7 @@ void CFRefCount::EvalObjCMessageExpr(ExplodedNodeSet<GRState>& Dst, // FIXME: Is this really working as expected? There are cases where // we just use the 'ID' from the message expression. const GRState* St = Builder.GetState(Pred); - SVal V = Eng.getStateManager().GetSValAsScalarOrLoc(St, Receiver); + SVal V = St->getSValAsScalarOrLoc(Receiver); SymbolRef Sym = V.getAsLocSymbol(); if (Sym) { @@ -3034,7 +3089,7 @@ void CFRefCount::EvalObjCMessageExpr(ExplodedNodeSet<GRState>& Dst, // This is a hack. When we have full-IP this should be removed. if (isa<ObjCMethodDecl>(&Eng.getGraph().getCodeDecl())) { if (Expr* Receiver = ME->getReceiver()) { - SVal X = Eng.getStateManager().GetSValAsScalarOrLoc(St, Receiver); + SVal X = St->getSValAsScalarOrLoc(Receiver); if (loc::MemRegionVal* L = dyn_cast<loc::MemRegionVal>(&X)) if (L->getRegion() == Eng.getStateManager().getSelfRegion(St)) { // Update the summary to make the default argument effect @@ -3057,17 +3112,15 @@ void CFRefCount::EvalObjCMessageExpr(ExplodedNodeSet<GRState>& Dst, namespace { class VISIBILITY_HIDDEN StopTrackingCallback : public SymbolVisitor { - GRStateRef state; + const GRState *state; public: - StopTrackingCallback(GRStateRef st) : state(st) {} - GRStateRef getState() { return state; } + StopTrackingCallback(const GRState *st) : state(st) {} + const GRState *getState() const { return state; } bool VisitSymbol(SymbolRef sym) { - state = state.remove<RefBindings>(sym); + state = state->remove<RefBindings>(sym); return true; } - - const GRState* getState() const { return state.getState(); } }; } // end anonymous namespace @@ -3082,7 +3135,7 @@ void CFRefCount::EvalBind(GRStmtNodeBuilderRef& B, SVal location, SVal val) { // (2) we are binding to a memregion that does not have stack storage // (3) we are binding to a memregion with stack storage that the store // does not understand. - GRStateRef state = B.getState(); + const GRState *state = B.getState(); if (!isa<loc::MemRegionVal>(location)) escapes = true; @@ -3094,7 +3147,7 @@ void CFRefCount::EvalBind(GRStmtNodeBuilderRef& B, SVal location, SVal val) { // To test (3), generate a new state with the binding removed. If it is // the same state, then it escapes (since the store cannot represent // the binding). - escapes = (state == (state.BindLoc(cast<Loc>(location), UnknownVal()))); + escapes = (state == (state->bindLoc(cast<Loc>(location), UnknownVal()))); } } @@ -3106,10 +3159,9 @@ void CFRefCount::EvalBind(GRStmtNodeBuilderRef& B, SVal location, SVal val) { // Otherwise, find all symbols referenced by 'val' that we are tracking // and stop tracking them. - B.MakeNode(state.scanReachableSymbols<StopTrackingCallback>(val).getState()); + B.MakeNode(state->scanReachableSymbols<StopTrackingCallback>(val).getState()); } - // Return statements. void CFRefCount::EvalReturn(ExplodedNodeSet<GRState>& Dst, @@ -3122,14 +3174,14 @@ void CFRefCount::EvalReturn(ExplodedNodeSet<GRState>& Dst, if (!RetE) return; - GRStateRef state(Builder.GetState(Pred), Eng.getStateManager()); - SymbolRef Sym = state.GetSValAsScalarOrLoc(RetE).getAsLocSymbol(); + const GRState *state = Builder.GetState(Pred); + SymbolRef Sym = state->getSValAsScalarOrLoc(RetE).getAsLocSymbol(); if (!Sym) return; // Get the reference count binding (if any). - const RefVal* T = state.get<RefBindings>(Sym); + const RefVal* T = state->get<RefBindings>(Sym); if (!T) return; @@ -3163,7 +3215,7 @@ void CFRefCount::EvalReturn(ExplodedNodeSet<GRState>& Dst, } // Update the binding. - state = state.set<RefBindings>(Sym, X); + state = state->set<RefBindings>(Sym, X); Pred = Builder.MakeNode(Dst, S, Pred, state); // Did we cache out? @@ -3182,7 +3234,7 @@ void CFRefCount::EvalReturn(ExplodedNodeSet<GRState>& Dst, return; // Get the updated binding. - T = state.get<RefBindings>(Sym); + T = state->get<RefBindings>(Sym); assert(T); X = *T; @@ -3217,7 +3269,7 @@ void CFRefCount::EvalReturn(ExplodedNodeSet<GRState>& Dst, if (hasError) { // Generate an error node. static int ReturnOwnLeakTag = 0; - state = state.set<RefBindings>(Sym, X); + state = state->set<RefBindings>(Sym, X); ExplodedNode<GRState> *N = Builder.generateNode(PostStmt(S, &ReturnOwnLeakTag), state, Pred); if (N) { @@ -3238,7 +3290,7 @@ void CFRefCount::EvalReturn(ExplodedNodeSet<GRState>& Dst, // owned object. static int ReturnNotOwnedForOwnedTag = 0; - state = state.set<RefBindings>(Sym, X ^ RefVal::ErrorReturnedNotOwned); + state = state->set<RefBindings>(Sym, X ^ RefVal::ErrorReturnedNotOwned); if (ExplodedNode<GRState> *N = Builder.generateNode(PostStmt(S, &ReturnNotOwnedForOwnedTag), state, Pred)) { @@ -3254,10 +3306,8 @@ void CFRefCount::EvalReturn(ExplodedNodeSet<GRState>& Dst, // Assumptions. -const GRState* CFRefCount::EvalAssume(GRStateManager& VMgr, - const GRState* St, - SVal Cond, bool Assumption, - bool& isFeasible) { +const GRState* CFRefCount::EvalAssume(const GRState *state, + SVal Cond, bool Assumption) { // FIXME: We may add to the interface of EvalAssume the list of symbols // whose assumptions have changed. For now we just iterate through the @@ -3265,32 +3315,30 @@ const GRState* CFRefCount::EvalAssume(GRStateManager& VMgr, // too bad since the number of symbols we will track in practice are // probably small and EvalAssume is only called at branches and a few // other places. - RefBindings B = St->get<RefBindings>(); + RefBindings B = state->get<RefBindings>(); if (B.isEmpty()) - return St; + return state; - bool changed = false; - - GRStateRef state(St, VMgr); - RefBindings::Factory& RefBFactory = state.get_context<RefBindings>(); + bool changed = false; + RefBindings::Factory& RefBFactory = state->get_context<RefBindings>(); for (RefBindings::iterator I=B.begin(), E=B.end(); I!=E; ++I) { // Check if the symbol is null (or equal to any constant). // If this is the case, stop tracking the symbol. - if (VMgr.getSymVal(St, I.getKey())) { + if (state->getSymVal(I.getKey())) { changed = true; B = RefBFactory.Remove(B, I.getKey()); } } if (changed) - state = state.set<RefBindings>(B); + state = state->set<RefBindings>(B); return state; } -GRStateRef CFRefCount::Update(GRStateRef state, SymbolRef sym, +const GRState * CFRefCount::Update(const GRState * state, SymbolRef sym, RefVal V, ArgEffect E, RefVal::Kind& hasErr) { @@ -3308,7 +3356,7 @@ GRStateRef CFRefCount::Update(GRStateRef state, SymbolRef sym, if (!isGCEnabled() && V.getKind() == RefVal::Released) { V = V ^ RefVal::ErrorUseAfterRelease; hasErr = V.getKind(); - return state.set<RefBindings>(sym, V); + return state->set<RefBindings>(sym, V); } switch (E) { @@ -3330,7 +3378,7 @@ GRStateRef CFRefCount::Update(GRStateRef state, SymbolRef sym, // The object immediately transitions to the released state. V = V ^ RefVal::Released; V.clearCounts(); - return state.set<RefBindings>(sym, V); + return state->set<RefBindings>(sym, V); case RefVal::NotOwned: V = V ^ RefVal::ErrorDeallocNotOwned; hasErr = V.getKind(); @@ -3340,7 +3388,7 @@ GRStateRef CFRefCount::Update(GRStateRef state, SymbolRef sym, case NewAutoreleasePool: assert(!isGCEnabled()); - return state.add<AutoreleaseStack>(sym); + return state->add<AutoreleaseStack>(sym); case MayEscape: if (V.getKind() == RefVal::Owned) { @@ -3364,7 +3412,7 @@ GRStateRef CFRefCount::Update(GRStateRef state, SymbolRef sym, break; case StopTracking: - return state.remove<RefBindings>(sym); + return state->remove<RefBindings>(sym); case IncRef: switch (V.getKind()) { @@ -3416,15 +3464,15 @@ GRStateRef CFRefCount::Update(GRStateRef state, SymbolRef sym, } break; } - return state.set<RefBindings>(sym, V); + return state->set<RefBindings>(sym, V); } //===----------------------------------------------------------------------===// // Handle dead symbols and end-of-path. //===----------------------------------------------------------------------===// -std::pair<ExplodedNode<GRState>*, GRStateRef> -CFRefCount::HandleAutoreleaseCounts(GRStateRef state, GenericNodeBuilder Bd, +std::pair<ExplodedNode<GRState>*, const GRState *> +CFRefCount::HandleAutoreleaseCounts(const GRState * state, GenericNodeBuilder Bd, ExplodedNode<GRState>* Pred, GRExprEngine &Eng, SymbolRef Sym, RefVal V, bool &stop) { @@ -3456,7 +3504,7 @@ CFRefCount::HandleAutoreleaseCounts(GRStateRef state, GenericNodeBuilder Bd, V.setCount(Cnt - ACnt); V.setAutoreleaseCount(0); } - state = state.set<RefBindings>(Sym, V); + state = state->set<RefBindings>(Sym, V); ExplodedNode<GRState> *N = Bd.MakeNode(state, Pred); stop = (N == 0); return std::make_pair(N, state); @@ -3466,7 +3514,7 @@ CFRefCount::HandleAutoreleaseCounts(GRStateRef state, GenericNodeBuilder Bd, // Emit hard error. stop = true; V = V ^ RefVal::ErrorOverAutorelease; - state = state.set<RefBindings>(Sym, V); + state = state->set<RefBindings>(Sym, V); if (ExplodedNode<GRState> *N = Bd.MakeNode(state, Pred)) { N->markAsSink(); @@ -3492,22 +3540,22 @@ CFRefCount::HandleAutoreleaseCounts(GRStateRef state, GenericNodeBuilder Bd, return std::make_pair((ExplodedNode<GRState>*)0, state); } -GRStateRef -CFRefCount::HandleSymbolDeath(GRStateRef state, SymbolRef sid, RefVal V, +const GRState * +CFRefCount::HandleSymbolDeath(const GRState * state, SymbolRef sid, RefVal V, llvm::SmallVectorImpl<SymbolRef> &Leaked) { bool hasLeak = V.isOwned() || ((V.isNotOwned() || V.isReturnedOwned()) && V.getCount() > 0); if (!hasLeak) - return state.remove<RefBindings>(sid); + return state->remove<RefBindings>(sid); Leaked.push_back(sid); - return state.set<RefBindings>(sid, V ^ RefVal::ErrorLeak); + return state->set<RefBindings>(sid, V ^ RefVal::ErrorLeak); } ExplodedNode<GRState>* -CFRefCount::ProcessLeaks(GRStateRef state, +CFRefCount::ProcessLeaks(const GRState * state, llvm::SmallVectorImpl<SymbolRef> &Leaked, GenericNodeBuilder &Builder, GRExprEngine& Eng, @@ -3537,9 +3585,9 @@ CFRefCount::ProcessLeaks(GRStateRef state, void CFRefCount::EvalEndPath(GRExprEngine& Eng, GREndPathNodeBuilder<GRState>& Builder) { - GRStateRef state(Builder.getState(), Eng.getStateManager()); + const GRState *state = Builder.getState(); GenericNodeBuilder Bd(Builder); - RefBindings B = state.get<RefBindings>(); + RefBindings B = state->get<RefBindings>(); ExplodedNode<GRState> *Pred = 0; for (RefBindings::iterator I = B.begin(), E = B.end(); I != E; ++I) { @@ -3552,7 +3600,7 @@ void CFRefCount::EvalEndPath(GRExprEngine& Eng, return; } - B = state.get<RefBindings>(); + B = state->get<RefBindings>(); llvm::SmallVector<SymbolRef, 10> Leaked; for (RefBindings::iterator I = B.begin(), E = B.end(); I != E; ++I) @@ -3566,11 +3614,10 @@ void CFRefCount::EvalDeadSymbols(ExplodedNodeSet<GRState>& Dst, GRStmtNodeBuilder<GRState>& Builder, ExplodedNode<GRState>* Pred, Stmt* S, - const GRState* St, + const GRState* state, SymbolReaper& SymReaper) { - GRStateRef state(St, Eng.getStateManager()); - RefBindings B = state.get<RefBindings>(); + RefBindings B = state->get<RefBindings>(); // Update counts from autorelease pools for (SymbolReaper::dead_iterator I = SymReaper.dead_begin(), @@ -3588,7 +3635,7 @@ void CFRefCount::EvalDeadSymbols(ExplodedNodeSet<GRState>& Dst, } } - B = state.get<RefBindings>(); + B = state->get<RefBindings>(); llvm::SmallVector<SymbolRef, 10> Leaked; for (SymbolReaper::dead_iterator I = SymReaper.dead_begin(), @@ -3608,12 +3655,12 @@ void CFRefCount::EvalDeadSymbols(ExplodedNodeSet<GRState>& Dst, return; // Now generate a new node that nukes the old bindings. - RefBindings::Factory& F = state.get_context<RefBindings>(); + RefBindings::Factory& F = state->get_context<RefBindings>(); for (SymbolReaper::dead_iterator I = SymReaper.dead_begin(), E = SymReaper.dead_end(); I!=E; ++I) B = F.Remove(B, *I); - state = state.set<RefBindings>(B); + state = state->set<RefBindings>(B); Builder.MakeNode(Dst, S, Pred, state); } diff --git a/lib/Analysis/CheckDeadStores.cpp b/lib/Analysis/CheckDeadStores.cpp index 69433d6..0f61a5e 100644 --- a/lib/Analysis/CheckDeadStores.cpp +++ b/lib/Analysis/CheckDeadStores.cpp @@ -85,7 +85,7 @@ public: const LiveVariables::AnalysisDataTy& AD, const LiveVariables::ValTy& Live) { - if (VD->hasLocalStorage() && !Live(VD, AD) && !VD->getAttr<UnusedAttr>()) + if (VD->hasLocalStorage() && !Live(VD, AD) && !VD->getAttr<UnusedAttr>(Ctx)) Report(VD, dsk, Ex->getSourceRange().getBegin(), Val->getSourceRange()); } @@ -190,7 +190,7 @@ public: // A dead initialization is a variable that is dead after it // is initialized. We don't flag warnings for those variables // marked 'unused'. - if (!Live(V, AD) && V->getAttr<UnusedAttr>() == 0) { + if (!Live(V, AD) && V->getAttr<UnusedAttr>(Ctx) == 0) { // Special case: check for initializations with constants. // // e.g. : int x = 0; diff --git a/lib/Analysis/CheckNSError.cpp b/lib/Analysis/CheckNSError.cpp index ff9da0f..c91442b 100644 --- a/lib/Analysis/CheckNSError.cpp +++ b/lib/Analysis/CheckNSError.cpp @@ -41,7 +41,7 @@ class VISIBILITY_HIDDEN NSErrorCheck : public BugType { bool CheckNSErrorArgument(QualType ArgTy); bool CheckCFErrorArgument(QualType ArgTy); - void CheckParamDeref(VarDecl* V, GRStateRef state, BugReporter& BR); + void CheckParamDeref(VarDecl* V, const GRState *state, BugReporter& BR); void EmitRetTyWarning(BugReporter& BR, Decl& CodeDecl); @@ -94,8 +94,7 @@ void NSErrorCheck::FlushReports(BugReporter& BR) { // Scan the parameters for an implicit null dereference. for (llvm::SmallVectorImpl<VarDecl*>::iterator I=ErrorParams.begin(), E=ErrorParams.end(); I!=E; ++I) - CheckParamDeref(*I, GRStateRef((*RI)->getState(),Eng.getStateManager()), - BR); + CheckParamDeref(*I, (*RI)->getState(), BR); } } @@ -186,13 +185,13 @@ bool NSErrorCheck::CheckCFErrorArgument(QualType ArgTy) { return TT->getDecl()->getIdentifier() == II; } -void NSErrorCheck::CheckParamDeref(VarDecl* Param, GRStateRef rootState, +void NSErrorCheck::CheckParamDeref(VarDecl* Param, const GRState *rootState, BugReporter& BR) { - SVal ParamL = rootState.GetLValue(Param); + SVal ParamL = rootState->getLValue(Param); const MemRegion* ParamR = cast<loc::MemRegionVal>(ParamL).getRegionAs<VarRegion>(); assert (ParamR && "Parameters always have VarRegions."); - SVal ParamSVal = rootState.GetSVal(ParamR); + SVal ParamSVal = rootState->getSVal(ParamR); // FIXME: For now assume that ParamSVal is symbolic. We need to generalize // this later. @@ -204,8 +203,8 @@ void NSErrorCheck::CheckParamDeref(VarDecl* Param, GRStateRef rootState, for (GRExprEngine::null_deref_iterator I=Eng.implicit_null_derefs_begin(), E=Eng.implicit_null_derefs_end(); I!=E; ++I) { - GRStateRef state = GRStateRef((*I)->getState(), Eng.getStateManager()); - const SVal* X = state.get<GRState::NullDerefTag>(); + const GRState *state = (*I)->getState(); + const SVal* X = state->get<GRState::NullDerefTag>(); if (!X || X->getAsSymbol() != ParamSym) continue; diff --git a/lib/Analysis/CheckObjCDealloc.cpp b/lib/Analysis/CheckObjCDealloc.cpp index f50d7a1..2ba7d86 100644 --- a/lib/Analysis/CheckObjCDealloc.cpp +++ b/lib/Analysis/CheckObjCDealloc.cpp @@ -109,7 +109,7 @@ void clang::CheckObjCDealloc(ObjCImplementationDecl* D, QualType T = ID->getType(); if (!Ctx.isObjCObjectPointerType(T) || - ID->getAttr<IBOutletAttr>()) // Skip IBOutlets. + ID->getAttr<IBOutletAttr>(Ctx)) // Skip IBOutlets. continue; containsPointerIvar = true; diff --git a/lib/Analysis/CheckObjCUnusedIVars.cpp b/lib/Analysis/CheckObjCUnusedIVars.cpp index 7979f9c..92c50e2 100644 --- a/lib/Analysis/CheckObjCUnusedIVars.cpp +++ b/lib/Analysis/CheckObjCUnusedIVars.cpp @@ -74,7 +74,7 @@ void clang::CheckObjCUnusedIvar(ObjCImplementationDecl* D, BugReporter& BR) { continue; // Skip IB Outlets. - if (ID->getAttr<IBOutletAttr>()) + if (ID->getAttr<IBOutletAttr>(Ctx)) continue; M[ID] = Unused; diff --git a/lib/Analysis/Environment.cpp b/lib/Analysis/Environment.cpp index 2bc071a..7ada6d8 100644 --- a/lib/Analysis/Environment.cpp +++ b/lib/Analysis/Environment.cpp @@ -18,7 +18,7 @@ using namespace clang; -SVal Environment::GetSVal(Stmt* E, BasicValueFactory& BasicVals) const { +SVal Environment::GetSVal(const Stmt *E, BasicValueFactory& BasicVals) const { for (;;) { @@ -34,7 +34,7 @@ SVal Environment::GetSVal(Stmt* E, BasicValueFactory& BasicVals) const { continue; case Stmt::CharacterLiteralClass: { - CharacterLiteral* C = cast<CharacterLiteral>(E); + const CharacterLiteral* C = cast<CharacterLiteral>(E); return NonLoc::MakeVal(BasicVals, C->getValue(), C->getType()); } @@ -48,7 +48,7 @@ SVal Environment::GetSVal(Stmt* E, BasicValueFactory& BasicVals) const { case Stmt::ImplicitCastExprClass: case Stmt::CStyleCastExprClass: { - CastExpr* C = cast<CastExpr>(E); + const CastExpr* C = cast<CastExpr>(E); QualType CT = C->getType(); if (CT->isVoidType()) @@ -69,7 +69,8 @@ SVal Environment::GetSVal(Stmt* E, BasicValueFactory& BasicVals) const { return LookupExpr(E); } -SVal Environment::GetBlkExprSVal(Stmt* E, BasicValueFactory& BasicVals) const { +SVal Environment::GetBlkExprSVal(const Stmt *E, + BasicValueFactory& BasicVals) const { while (1) { switch (E->getStmtClass()) { @@ -78,7 +79,7 @@ SVal Environment::GetBlkExprSVal(Stmt* E, BasicValueFactory& BasicVals) const { continue; case Stmt::CharacterLiteralClass: { - CharacterLiteral* C = cast<CharacterLiteral>(E); + const CharacterLiteral* C = cast<CharacterLiteral>(E); return NonLoc::MakeVal(BasicVals, C->getValue(), C->getType()); } @@ -92,8 +93,9 @@ SVal Environment::GetBlkExprSVal(Stmt* E, BasicValueFactory& BasicVals) const { } } -Environment EnvironmentManager::BindExpr(const Environment& Env, Stmt* E,SVal V, - bool isBlkExpr, bool Invalidate) { +Environment EnvironmentManager::BindExpr(const Environment& Env, const Stmt* E, + SVal V, bool isBlkExpr, + bool Invalidate) { assert (E); if (V.isUnknown()) { @@ -136,7 +138,7 @@ EnvironmentManager::RemoveDeadBindings(Environment Env, Stmt* Loc, // Iterate over the block-expr bindings. for (Environment::beb_iterator I = Env.beb_begin(), E = Env.beb_end(); I != E; ++I) { - Stmt* BlkExpr = I.getKey(); + const Stmt *BlkExpr = I.getKey(); if (SymReaper.isLive(Loc, BlkExpr)) { SVal X = I.getData(); @@ -147,7 +149,7 @@ EnvironmentManager::RemoveDeadBindings(Environment Env, Stmt* Loc, // Mark all symbols in the block expr's value live. MarkLiveCallback cb(SymReaper); - StateMgr.scanReachableSymbols(X, state, cb); + state->scanReachableSymbols(X, cb); } else { // The block expr is dead. SVal X = I.getData(); diff --git a/lib/Analysis/GRExprEngine.cpp b/lib/Analysis/GRExprEngine.cpp index 7a8fef5..87432d4 100644 --- a/lib/Analysis/GRExprEngine.cpp +++ b/lib/Analysis/GRExprEngine.cpp @@ -177,14 +177,13 @@ const GRState* GRExprEngine::getInitialState() { QualType T = PD->getType(); if (T->isIntegerType()) if (const MemRegion *R = StateMgr.getRegion(PD)) { - SVal V = GetSVal(state, loc::MemRegionVal(R)); + SVal V = state->getSVal(loc::MemRegionVal(R)); SVal Constraint = EvalBinOp(state, BinaryOperator::GT, V, ValMgr.makeZeroVal(T), getContext().IntTy); - bool isFeasible = false; - const GRState *newState = Assume(state, Constraint, true, - isFeasible); - if (newState) state = newState; + + if (const GRState *newState = state->assume(Constraint, true)) + state = newState; } } @@ -310,7 +309,7 @@ void GRExprEngine::Visit(Stmt* S, NodeTy* Pred, NodeSet& Dst) { } else if (B->getOpcode() == BinaryOperator::Comma) { const GRState* state = GetState(Pred); - MakeNode(Dst, B, Pred, BindExpr(state, B, GetSVal(state, B->getRHS()))); + MakeNode(Dst, B, Pred, state->bindExpr(B, state->getSVal(B->getRHS()))); break; } @@ -426,7 +425,7 @@ void GRExprEngine::Visit(Stmt* S, NodeTy* Pred, NodeSet& Dst) { if (Expr* LastExpr = dyn_cast<Expr>(*SE->getSubStmt()->body_rbegin())) { const GRState* state = GetState(Pred); - MakeNode(Dst, SE, Pred, BindExpr(state, SE, GetSVal(state, LastExpr))); + MakeNode(Dst, SE, Pred, state->bindExpr(SE, state->getSVal(LastExpr))); } else Dst.Add(Pred); @@ -506,8 +505,8 @@ void GRExprEngine::VisitLValue(Expr* Ex, NodeTy* Pred, NodeSet& Dst) { case Stmt::StringLiteralClass: { const GRState* state = GetState(Pred); - SVal V = StateMgr.GetLValue(state, cast<StringLiteral>(Ex)); - MakeNode(Dst, Ex, Pred, BindExpr(state, Ex, V)); + SVal V = state->getLValue(cast<StringLiteral>(Ex)); + MakeNode(Dst, Ex, Pred, state->bindExpr(Ex, V)); return; } @@ -579,7 +578,7 @@ const GRState* GRExprEngine::MarkBranch(const GRState* state, (Op == BinaryOperator::LOr && !branchTaken) ? B->getRHS() : B->getLHS(); - return BindBlkExpr(state, B, UndefinedVal(Ex)); + return state->bindBlkExpr(B, UndefinedVal(Ex)); } case Stmt::ConditionalOperatorClass: { // ?: @@ -596,7 +595,7 @@ const GRState* GRExprEngine::MarkBranch(const GRState* state, else Ex = C->getRHS(); - return BindBlkExpr(state, C, UndefinedVal(Ex)); + return state->bindBlkExpr(C, UndefinedVal(Ex)); } case Stmt::ChooseExprClass: { // ?: @@ -604,7 +603,7 @@ const GRState* GRExprEngine::MarkBranch(const GRState* state, ChooseExpr* C = cast<ChooseExpr>(Terminator); Expr* Ex = branchTaken ? C->getLHS() : C->getRHS(); - return BindBlkExpr(state, C, UndefinedVal(Ex)); + return state->bindBlkExpr(C, UndefinedVal(Ex)); } } } @@ -645,7 +644,7 @@ static SVal RecoverCastedSymbol(GRStateManager& StateMgr, const GRState* state, if (!bitsInit || !T->isIntegerType() || Ctx.getTypeSize(T) > bits) return UnknownVal(); - return StateMgr.GetSVal(state, Ex); + return state->getSVal(Ex); } void GRExprEngine::ProcessBranch(Stmt* Condition, Stmt* Term, @@ -665,7 +664,7 @@ void GRExprEngine::ProcessBranch(Stmt* Condition, Stmt* Term, Condition->getLocStart(), "Error evaluating branch"); - SVal V = GetSVal(PrevState, Condition); + SVal V = PrevState->getSVal(Condition); switch (V.getBaseKind()) { default: @@ -708,21 +707,13 @@ void GRExprEngine::ProcessBranch(Stmt* Condition, Stmt* Term, } // Process the true branch. - - bool isFeasible = false; - const GRState* state = Assume(PrevState, V, true, isFeasible); - - if (isFeasible) + if (const GRState *state = PrevState->assume(V, true)) builder.generateNode(MarkBranch(state, Term, true), true); else builder.markInfeasible(true); // Process the false branch. - - isFeasible = false; - state = Assume(PrevState, V, false, isFeasible); - - if (isFeasible) + if (const GRState *state = PrevState->assume(V, false)) builder.generateNode(MarkBranch(state, Term, false), false); else builder.markInfeasible(false); @@ -732,8 +723,8 @@ void GRExprEngine::ProcessBranch(Stmt* Condition, Stmt* Term, /// nodes by processing the 'effects' of a computed goto jump. void GRExprEngine::ProcessIndirectGoto(IndirectGotoNodeBuilder& builder) { - const GRState* state = builder.getState(); - SVal V = GetSVal(state, builder.getTarget()); + const GRState *state = builder.getState(); + SVal V = state->getSVal(builder.getTarget()); // Three possibilities: // @@ -779,18 +770,16 @@ void GRExprEngine::VisitGuardedExpr(Expr* Ex, Expr* L, Expr* R, assert (Ex == CurrentStmt && getCFG().isBlkExpr(Ex)); const GRState* state = GetState(Pred); - SVal X = GetBlkExprSVal(state, Ex); + SVal X = state->getBlkExprSVal(Ex); assert (X.isUndef()); - Expr* SE = (Expr*) cast<UndefinedVal>(X).getData(); - - assert (SE); - - X = GetBlkExprSVal(state, SE); + Expr *SE = (Expr*) cast<UndefinedVal>(X).getData(); + assert(SE); + X = state->getBlkExprSVal(SE); // Make sure that we invalidate the previous binding. - MakeNode(Dst, Ex, Pred, StateMgr.BindExpr(state, Ex, X, true, true)); + MakeNode(Dst, Ex, Pred, state->bindExpr(Ex, X, true, true)); } /// ProcessSwitch - Called by GRCoreEngine. Used to generate successor @@ -799,7 +788,7 @@ void GRExprEngine::ProcessSwitch(SwitchNodeBuilder& builder) { typedef SwitchNodeBuilder::iterator iterator; const GRState* state = builder.getState(); Expr* CondE = builder.getCondition(); - SVal CondV = GetSVal(state, CondE); + SVal CondV = state->getSVal(CondE); if (CondV.isUndef()) { NodeTy* N = builder.generateDefaultCaseNode(state, true); @@ -808,7 +797,7 @@ void GRExprEngine::ProcessSwitch(SwitchNodeBuilder& builder) { } const GRState* DefaultSt = state; - bool DefaultFeasible = false; + bool defaultIsFeasible = false; for (iterator I = builder.begin(), EI = builder.end(); I != EI; ++I) { CaseStmt* Case = cast<CaseStmt>(I.getCase()); @@ -846,11 +835,8 @@ void GRExprEngine::ProcessSwitch(SwitchNodeBuilder& builder) { getContext().IntTy); // Now "assume" that the case matches. - bool isFeasible = false; - const GRState* StNew = Assume(state, Res, true, isFeasible); - - if (isFeasible) { - builder.generateCaseStmtNode(I, StNew); + if (const GRState* stateNew = state->assume(Res, true)) { + builder.generateCaseStmtNode(I, stateNew); // If CondV evaluates to a constant, then we know that this // is the *only* case that we can take, so stop evaluating the @@ -861,13 +847,9 @@ void GRExprEngine::ProcessSwitch(SwitchNodeBuilder& builder) { // Now "assume" that the case doesn't match. Add this state // to the default state (if it is feasible). - - isFeasible = false; - StNew = Assume(DefaultSt, Res, false, isFeasible); - - if (isFeasible) { - DefaultFeasible = true; - DefaultSt = StNew; + if (const GRState *stateNew = DefaultSt->assume(Res, false)) { + defaultIsFeasible = true; + DefaultSt = stateNew; } // Concretize the next value in the range. @@ -882,7 +864,7 @@ void GRExprEngine::ProcessSwitch(SwitchNodeBuilder& builder) { // If we reach here, than we know that the default branch is // possible. - if (DefaultFeasible) builder.generateDefaultCaseNode(DefaultSt); + if (defaultIsFeasible) builder.generateDefaultCaseNode(DefaultSt); } //===----------------------------------------------------------------------===// @@ -892,28 +874,27 @@ void GRExprEngine::ProcessSwitch(SwitchNodeBuilder& builder) { void GRExprEngine::VisitLogicalExpr(BinaryOperator* B, NodeTy* Pred, NodeSet& Dst) { - assert (B->getOpcode() == BinaryOperator::LAnd || - B->getOpcode() == BinaryOperator::LOr); + assert(B->getOpcode() == BinaryOperator::LAnd || + B->getOpcode() == BinaryOperator::LOr); - assert (B == CurrentStmt && getCFG().isBlkExpr(B)); + assert(B == CurrentStmt && getCFG().isBlkExpr(B)); const GRState* state = GetState(Pred); - SVal X = GetBlkExprSVal(state, B); - - assert (X.isUndef()); + SVal X = state->getBlkExprSVal(B); + assert(X.isUndef()); Expr* Ex = (Expr*) cast<UndefinedVal>(X).getData(); - assert (Ex); + assert(Ex); if (Ex == B->getRHS()) { - X = GetBlkExprSVal(state, Ex); + X = state->getBlkExprSVal(Ex); // Handle undefined values. if (X.isUndef()) { - MakeNode(Dst, B, Pred, BindBlkExpr(state, B, X)); + MakeNode(Dst, B, Pred, state->bindBlkExpr(B, X)); return; } @@ -922,29 +903,19 @@ void GRExprEngine::VisitLogicalExpr(BinaryOperator* B, NodeTy* Pred, // or 1. Alternatively, we could take a lazy approach, and calculate this // value later when necessary. We don't have the machinery in place for // this right now, and since most logical expressions are used for branches, - // the payoff is not likely to be large. Instead, we do eager evaluation. - - bool isFeasible = false; - const GRState* NewState = Assume(state, X, true, isFeasible); - - if (isFeasible) - MakeNode(Dst, B, Pred, - BindBlkExpr(NewState, B, MakeConstantVal(1U, B))); + // the payoff is not likely to be large. Instead, we do eager evaluation. + if (const GRState *newState = state->assume(X, true)) + MakeNode(Dst, B, Pred, newState->bindBlkExpr(B, MakeConstantVal(1U, B))); - isFeasible = false; - NewState = Assume(state, X, false, isFeasible); - - if (isFeasible) - MakeNode(Dst, B, Pred, - BindBlkExpr(NewState, B, MakeConstantVal(0U, B))); + if (const GRState *newState = state->assume(X, false)) + MakeNode(Dst, B, Pred, newState->bindBlkExpr(B, MakeConstantVal(0U, B))); } else { // We took the LHS expression. Depending on whether we are '&&' or // '||' we know what the value of the expression is via properties of // the short-circuiting. - X = MakeConstantVal( B->getOpcode() == BinaryOperator::LAnd ? 0U : 1U, B); - MakeNode(Dst, B, Pred, BindBlkExpr(state, B, X)); + MakeNode(Dst, B, Pred, state->bindBlkExpr(B, X)); } } @@ -961,10 +932,10 @@ void GRExprEngine::VisitDeclRefExpr(DeclRefExpr* Ex, NodeTy* Pred, NodeSet& Dst, if (const VarDecl* VD = dyn_cast<VarDecl>(D)) { - SVal V = StateMgr.GetLValue(state, VD); + SVal V = state->getLValue(VD); if (asLValue) - MakeNode(Dst, Ex, Pred, BindExpr(state, Ex, V), + MakeNode(Dst, Ex, Pred, state->bindExpr(Ex, V), ProgramPoint::PostLValueKind); else EvalLoad(Dst, Ex, Pred, state, V); @@ -975,13 +946,13 @@ void GRExprEngine::VisitDeclRefExpr(DeclRefExpr* Ex, NodeTy* Pred, NodeSet& Dst, BasicValueFactory& BasicVals = StateMgr.getBasicVals(); SVal V = nonloc::ConcreteInt(BasicVals.getValue(ED->getInitVal())); - MakeNode(Dst, Ex, Pred, BindExpr(state, Ex, V)); + MakeNode(Dst, Ex, Pred, state->bindExpr(Ex, V)); return; } else if (const FunctionDecl* FD = dyn_cast<FunctionDecl>(D)) { assert(asLValue); SVal V = ValMgr.getFunctionPointer(FD); - MakeNode(Dst, Ex, Pred, BindExpr(state, Ex, V), + MakeNode(Dst, Ex, Pred, state->bindExpr(Ex, V), ProgramPoint::PostLValueKind); return; } @@ -1014,12 +985,11 @@ void GRExprEngine::VisitArraySubscriptExpr(ArraySubscriptExpr* A, NodeTy* Pred, for (NodeSet::iterator I2=Tmp2.begin(), E2=Tmp2.end(); I2!=E2; ++I2) { const GRState* state = GetState(*I2); - SVal V = StateMgr.GetLValue(state, A->getType(), - GetSVal(state, Base), - GetSVal(state, Idx)); + SVal V = state->getLValue(A->getType(), state->getSVal(Base), + state->getSVal(Idx)); if (asLValue) - MakeNode(Dst, A, *I2, BindExpr(state, A, V), + MakeNode(Dst, A, *I2, state->bindExpr(A, V), ProgramPoint::PostLValueKind); else EvalLoad(Dst, A, *I2, state, V); @@ -1048,10 +1018,10 @@ void GRExprEngine::VisitMemberExpr(MemberExpr* M, NodeTy* Pred, // FIXME: Should we insert some assumption logic in here to determine // if "Base" is a valid piece of memory? Before we put this assumption // later when using FieldOffset lvals (which we no longer have). - SVal L = StateMgr.GetLValue(state, GetSVal(state, Base), Field); + SVal L = state->getLValue(state->getSVal(Base), Field); if (asLValue) - MakeNode(Dst, M, *I, BindExpr(state, M, L), + MakeNode(Dst, M, *I, state->bindExpr(M, L), ProgramPoint::PostLValueKind); else EvalLoad(Dst, M, *I, state, L); @@ -1135,11 +1105,11 @@ void GRExprEngine::EvalLoad(NodeSet& Dst, Expr* Ex, NodeTy* Pred, if (location.isUnknown()) { // This is important. We must nuke the old binding. - MakeNode(Dst, Ex, Pred, BindExpr(state, Ex, UnknownVal()), K, tag); + MakeNode(Dst, Ex, Pred, state->bindExpr(Ex, UnknownVal()), K, tag); } else { - SVal V = GetSVal(state, cast<Loc>(location), Ex->getType()); - MakeNode(Dst, Ex, Pred, BindExpr(state, Ex, V), K, tag); + SVal V = state->getSVal(cast<Loc>(location), Ex->getType()); + MakeNode(Dst, Ex, Pred, state->bindExpr(Ex, V), K, tag); } } @@ -1189,19 +1159,15 @@ GRExprEngine::NodeTy* GRExprEngine::EvalLocation(Stmt* Ex, NodeTy* Pred, Loc LV = cast<Loc>(location); // "Assume" that the pointer is not NULL. - bool isFeasibleNotNull = false; - const GRState* StNotNull = Assume(state, LV, true, isFeasibleNotNull); + const GRState *StNotNull = state->assume(LV, true); // "Assume" that the pointer is NULL. - bool isFeasibleNull = false; - GRStateRef StNull = GRStateRef(Assume(state, LV, false, isFeasibleNull), - getStateManager()); + const GRState *StNull = state->assume(LV, false); - if (isFeasibleNull) { - + if (StNull) { // Use the Generic Data Map to mark in the state what lval was null. const SVal* PersistentLV = getBasicVals().getPersistentSVal(LV); - StNull = StNull.set<GRState::NullDerefTag>(PersistentLV); + StNull = StNull->set<GRState::NullDerefTag>(PersistentLV); // We don't use "MakeNode" here because the node will be a sink // and we have no intention of processing it later. @@ -1209,17 +1175,15 @@ GRExprEngine::NodeTy* GRExprEngine::EvalLocation(Stmt* Ex, NodeTy* Pred, Builder->generateNode(Ex, StNull, Pred, ProgramPoint::PostNullCheckFailedKind); - if (NullNode) { - - NullNode->markAsSink(); - - if (isFeasibleNotNull) ImplicitNullDeref.insert(NullNode); + if (NullNode) { + NullNode->markAsSink(); + if (StNotNull) ImplicitNullDeref.insert(NullNode); else ExplicitNullDeref.insert(NullNode); } } - if (!isFeasibleNotNull) - return 0; + if (!StNotNull) + return NULL; // Check for out-of-bound array access. if (isa<loc::MemRegionVal>(LV)) { @@ -1231,15 +1195,12 @@ GRExprEngine::NodeTy* GRExprEngine::EvalLocation(Stmt* Ex, NodeTy* Pred, SVal NumElements = getStoreManager().getSizeInElements(StNotNull, ER->getSuperRegion()); - bool isFeasibleInBound = false; - const GRState* StInBound = AssumeInBound(StNotNull, Idx, NumElements, - true, isFeasibleInBound); - - bool isFeasibleOutBound = false; - const GRState* StOutBound = AssumeInBound(StNotNull, Idx, NumElements, - false, isFeasibleOutBound); + const GRState * StInBound = StNotNull->assumeInBound(Idx, NumElements, + true); + const GRState* StOutBound = StNotNull->assumeInBound(Idx, NumElements, + false); - if (isFeasibleOutBound) { + if (StOutBound) { // Report warning. Make sink node manually. NodeTy* OOBNode = Builder->generateNode(Ex, StOutBound, Pred, @@ -1248,16 +1209,16 @@ GRExprEngine::NodeTy* GRExprEngine::EvalLocation(Stmt* Ex, NodeTy* Pred, if (OOBNode) { OOBNode->markAsSink(); - if (isFeasibleInBound) + if (StInBound) ImplicitOOBMemAccesses.insert(OOBNode); else ExplicitOOBMemAccesses.insert(OOBNode); } } - if (!isFeasibleInBound) - return 0; - + if (!StInBound) + return NULL; + StNotNull = StInBound; } } @@ -1319,10 +1280,9 @@ static bool EvalOSAtomicCompareAndSwap(ExplodedNodeSet<GRState>& Dst, const void *OSAtomicStoreTag = &magic_store; // Load 'theValue'. - GRStateManager &StateMgr = Engine.getStateManager(); const GRState *state = Pred->getState(); ExplodedNodeSet<GRState> Tmp; - SVal location = StateMgr.GetSVal(state, theValueExpr); + SVal location = state->getSVal(theValueExpr); Engine.EvalLoad(Tmp, theValueExpr, Pred, state, location, OSAtomicLoadTag); for (ExplodedNodeSet<GRState>::iterator I = Tmp.begin(), E = Tmp.end(); @@ -1330,24 +1290,22 @@ static bool EvalOSAtomicCompareAndSwap(ExplodedNodeSet<GRState>& Dst, ExplodedNode<GRState> *N = *I; const GRState *stateLoad = N->getState(); - SVal theValueVal = StateMgr.GetSVal(stateLoad, theValueExpr); - SVal oldValueVal = StateMgr.GetSVal(stateLoad, oldValueExpr); + SVal theValueVal = stateLoad->getSVal(theValueExpr); + SVal oldValueVal = stateLoad->getSVal(oldValueExpr); // Perform the comparison. SVal Cmp = Engine.EvalBinOp(stateLoad, BinaryOperator::EQ, theValueVal, oldValueVal, Engine.getContext().IntTy); - bool isFeasible = false; - const GRState *stateEqual = StateMgr.Assume(stateLoad, Cmp, true, - isFeasible); + + const GRState *stateEqual = stateLoad->assume(Cmp, true); // Were they equal? - if (isFeasible) { + if (stateEqual) { // Perform the store. ExplodedNodeSet<GRState> TmpStore; Engine.EvalStore(TmpStore, theValueExpr, N, stateEqual, location, - StateMgr.GetSVal(stateEqual, newValueExpr), - OSAtomicStoreTag); + stateEqual->getSVal(newValueExpr), OSAtomicStoreTag); // Now bind the result of the comparison. for (ExplodedNodeSet<GRState>::iterator I2 = TmpStore.begin(), @@ -1355,18 +1313,14 @@ static bool EvalOSAtomicCompareAndSwap(ExplodedNodeSet<GRState>& Dst, ExplodedNode<GRState> *predNew = *I2; const GRState *stateNew = predNew->getState(); SVal Res = Engine.getValueManager().makeTruthVal(true, CE->getType()); - Engine.MakeNode(Dst, CE, predNew, Engine.BindExpr(stateNew, CE, Res)); + Engine.MakeNode(Dst, CE, predNew, stateNew->bindExpr(CE, Res)); } } // Were they not equal? - isFeasible = false; - const GRState *stateNotEqual = StateMgr.Assume(stateLoad, Cmp, false, - isFeasible); - - if (isFeasible) { + if (const GRState *stateNotEqual = stateLoad->assume(Cmp, false)) { SVal Res = Engine.getValueManager().makeTruthVal(false, CE->getType()); - Engine.MakeNode(Dst, CE, N, Engine.BindExpr(stateNotEqual, CE, Res)); + Engine.MakeNode(Dst, CE, N, stateNotEqual->bindExpr(CE, Res)); } } @@ -1460,7 +1414,7 @@ void GRExprEngine::VisitCallRec(CallExpr* CE, NodeTy* Pred, for (NodeSet::iterator DI = DstTmp.begin(), DE = DstTmp.end(); DI!=DE; ++DI) { const GRState* state = GetState(*DI); - SVal L = GetSVal(state, Callee); + SVal L = state->getSVal(Callee); // FIXME: Add support for symbolic function calls (calls involving // function pointer values that are symbolic). @@ -1483,7 +1437,8 @@ void GRExprEngine::VisitCallRec(CallExpr* CE, NodeTy* Pred, SaveAndRestore<bool> OldSink(Builder->BuildSinks); const FunctionDecl* FD = L.getAsFunctionDecl(); if (FD) { - if (FD->getAttr<NoReturnAttr>() || FD->getAttr<AnalyzerNoReturnAttr>()) + if (FD->getAttr<NoReturnAttr>(getContext()) || + FD->getAttr<AnalyzerNoReturnAttr>(getContext())) Builder->BuildSinks = true; else { // HACK: Some functions are not marked noreturn, and don't return. @@ -1504,7 +1459,7 @@ void GRExprEngine::VisitCallRec(CallExpr* CE, NodeTy* Pred, if (!memcmp(s, "panic", 5)) Builder->BuildSinks = true; else if (!memcmp(s, "error", 5)) { if (CE->getNumArgs() > 0) { - SVal X = GetSVal(state, *CE->arg_begin()); + SVal X = state->getSVal(*CE->arg_begin()); // FIXME: use Assume to inspect the possible symbolic value of // X. Also check the specific signature of error(). nonloc::ConcreteInt* CI = dyn_cast<nonloc::ConcreteInt>(&X); @@ -1571,8 +1526,8 @@ void GRExprEngine::VisitCallRec(CallExpr* CE, NodeTy* Pred, case Builtin::BI__builtin_expect: { // For __builtin_expect, just return the value of the subexpression. assert (CE->arg_begin() != CE->arg_end()); - SVal X = GetSVal(state, *(CE->arg_begin())); - MakeNode(Dst, CE, *DI, BindExpr(state, CE, X)); + SVal X = state->getSVal(*(CE->arg_begin())); + MakeNode(Dst, CE, *DI, state->bindExpr(CE, X)); continue; } @@ -1585,10 +1540,10 @@ void GRExprEngine::VisitCallRec(CallExpr* CE, NodeTy* Pred, // Set the extent of the region in bytes. This enables us to use the // SVal of the argument directly. If we save the extent in bits, we // cannot represent values like symbol*8. - SVal Extent = GetSVal(state, *(CE->arg_begin())); + SVal Extent = state->getSVal(*(CE->arg_begin())); state = getStoreManager().setExtent(state, R, Extent); - MakeNode(Dst, CE, *DI, BindExpr(state, CE, loc::MemRegionVal(R))); + MakeNode(Dst, CE, *DI, state->bindExpr(CE, loc::MemRegionVal(R))); continue; } @@ -1604,7 +1559,7 @@ void GRExprEngine::VisitCallRec(CallExpr* CE, NodeTy* Pred, for (CallExpr::arg_iterator I = CE->arg_begin(), E = CE->arg_end(); I != E; ++I) { - if (GetSVal(GetState(*DI), *I).isUndef()) { + if (GetState(*DI)->getSVal(*I).isUndef()) { NodeTy* N = Builder->generateNode(CE, GetState(*DI), *DI); if (N) { @@ -1656,22 +1611,18 @@ void GRExprEngine::EvalEagerlyAssume(NodeSet &Dst, NodeSet &Src, Expr *Ex) { } const GRState* state = Pred->getState(); - SVal V = GetSVal(state, Ex); + SVal V = state->getSVal(Ex); if (isa<nonloc::SymExprVal>(V)) { // First assume that the condition is true. - bool isFeasible = false; - const GRState *stateTrue = Assume(state, V, true, isFeasible); - if (isFeasible) { - stateTrue = BindExpr(stateTrue, Ex, MakeConstantVal(1U, Ex)); + if (const GRState *stateTrue = state->assume(V, true)) { + stateTrue = stateTrue->bindExpr(Ex, MakeConstantVal(1U, Ex)); Dst.Add(Builder->generateNode(PostStmtCustom(Ex, &EagerlyAssumeTag), stateTrue, Pred)); } // Next, assume that the condition is false. - isFeasible = false; - const GRState *stateFalse = Assume(state, V, false, isFeasible); - if (isFeasible) { - stateFalse = BindExpr(stateFalse, Ex, MakeConstantVal(0U, Ex)); + if (const GRState *stateFalse = state->assume(V, false)) { + stateFalse = stateFalse->bindExpr(Ex, MakeConstantVal(0U, Ex)); Dst.Add(Builder->generateNode(PostStmtCustom(Ex, &EagerlyAssumeTag), stateFalse, Pred)); } @@ -1695,11 +1646,11 @@ void GRExprEngine::VisitObjCIvarRefExpr(ObjCIvarRefExpr* Ex, for (NodeSet::iterator I=Tmp.begin(), E=Tmp.end(); I!=E; ++I) { const GRState* state = GetState(*I); - SVal BaseVal = GetSVal(state, Base); - SVal location = StateMgr.GetLValue(state, Ex->getDecl(), BaseVal); + SVal BaseVal = state->getSVal(Base); + SVal location = state->getLValue(Ex->getDecl(), BaseVal); if (asLValue) - MakeNode(Dst, Ex, *I, BindExpr(state, Ex, location)); + MakeNode(Dst, Ex, *I, state->bindExpr(Ex, location)); else EvalLoad(Dst, Ex, *I, state, location); } @@ -1743,7 +1694,7 @@ void GRExprEngine::VisitObjCForCollectionStmt(ObjCForCollectionStmt* S, if (DeclStmt* DS = dyn_cast<DeclStmt>(elem)) { VarDecl* ElemD = cast<VarDecl>(DS->getSingleDecl()); assert (ElemD->getInit() == 0); - ElementV = getStateManager().GetLValue(GetState(Pred), ElemD); + ElementV = GetState(Pred)->getLValue(ElemD); VisitObjCForCollectionStmtAux(S, Pred, Dst, ElementV); return; } @@ -1753,7 +1704,7 @@ void GRExprEngine::VisitObjCForCollectionStmt(ObjCForCollectionStmt* S, for (NodeSet::iterator I = Tmp.begin(), E = Tmp.end(); I!=E; ++I) { const GRState* state = GetState(*I); - VisitObjCForCollectionStmtAux(S, *I, Dst, GetSVal(state, elem)); + VisitObjCForCollectionStmtAux(S, *I, Dst, state->getSVal(elem)); } } @@ -1771,16 +1722,16 @@ void GRExprEngine::VisitObjCForCollectionStmtAux(ObjCForCollectionStmt* S, if (!Pred) return; - GRStateRef state = GRStateRef(GetState(Pred), getStateManager()); + const GRState *state = GetState(Pred); // Handle the case where the container still has elements. QualType IntTy = getContext().IntTy; SVal TrueV = NonLoc::MakeVal(getBasicVals(), 1, IntTy); - GRStateRef hasElems = state.BindExpr(S, TrueV); + const GRState *hasElems = state->bindExpr(S, TrueV); // Handle the case where the container has no elements. SVal FalseV = NonLoc::MakeVal(getBasicVals(), 0, IntTy); - GRStateRef noElems = state.BindExpr(S, FalseV); + const GRState *noElems = state->bindExpr(S, FalseV); if (loc::MemRegionVal* MV = dyn_cast<loc::MemRegionVal>(&ElementV)) if (const TypedRegion* R = dyn_cast<TypedRegion>(MV->getRegion())) { @@ -1792,11 +1743,11 @@ void GRExprEngine::VisitObjCForCollectionStmtAux(ObjCForCollectionStmt* S, unsigned Count = Builder->getCurrentBlockCount(); SymbolRef Sym = SymMgr.getConjuredSymbol(elem, T, Count); SVal V = Loc::MakeVal(getStoreManager().getRegionManager().getSymbolicRegion(Sym)); - hasElems = hasElems.BindLoc(ElementV, V); + hasElems = hasElems->bindLoc(ElementV, V); // Bind the location to 'nil' on the false branch. SVal nilV = loc::ConcreteInt(getBasicVals().getValue(0, T)); - noElems = noElems.BindLoc(ElementV, nilV); + noElems = noElems->bindLoc(ElementV, nilV); } // Create the new nodes. @@ -1858,7 +1809,7 @@ void GRExprEngine::VisitObjCMessageExprDispatchHelper(ObjCMessageExpr* ME, if (Expr* Receiver = ME->getReceiver()) { - SVal L = GetSVal(state, Receiver); + SVal L = state->getSVal(Receiver); // Check for undefined control-flow. if (L.isUndef()) { @@ -1873,14 +1824,12 @@ void GRExprEngine::VisitObjCMessageExprDispatchHelper(ObjCMessageExpr* ME, } // "Assume" that the receiver is not NULL. - bool isFeasibleNotNull = false; - const GRState *StNotNull = Assume(state, L, true, isFeasibleNotNull); + const GRState *StNotNull = state->assume(L, true); // "Assume" that the receiver is NULL. - bool isFeasibleNull = false; - const GRState *StNull = Assume(state, L, false, isFeasibleNull); + const GRState *StNull = state->assume(L, false); - if (isFeasibleNull) { + if (StNull) { QualType RetTy = ME->getType(); // Check if the receiver was nil and the return value a struct. @@ -1894,7 +1843,7 @@ void GRExprEngine::VisitObjCMessageExprDispatchHelper(ObjCMessageExpr* ME, // garbage. if (NodeTy* N = Builder->generateNode(ME, StNull, Pred)) { N->markAsSink(); - if (isFeasibleNotNull) + if (StNotNull) NilReceiverStructRetImplicit.insert(N); else NilReceiverStructRetExplicit.insert(N); @@ -1913,13 +1862,13 @@ void GRExprEngine::VisitObjCMessageExprDispatchHelper(ObjCMessageExpr* ME, if(voidPtrSize < returnTypeSize) { if (NodeTy* N = Builder->generateNode(ME, StNull, Pred)) { N->markAsSink(); - if(isFeasibleNotNull) + if(StNotNull) NilReceiverLargerThanVoidPtrRetImplicit.insert(N); else NilReceiverLargerThanVoidPtrRetExplicit.insert(N); } } - else if (!isFeasibleNotNull) { + else if (!StNotNull) { // Handle the safe cases where the return value is 0 if the // receiver is nil. // @@ -1934,7 +1883,7 @@ void GRExprEngine::VisitObjCMessageExprDispatchHelper(ObjCMessageExpr* ME, // of this case unless we have *a lot* more knowledge. // SVal V = ValMgr.makeZeroVal(ME->getType()); - MakeNode(Dst, ME, Pred, BindExpr(StNull, ME, V)); + MakeNode(Dst, ME, Pred, StNull->bindExpr(ME, V)); return; } } @@ -2004,7 +1953,7 @@ void GRExprEngine::VisitObjCMessageExprDispatchHelper(ObjCMessageExpr* ME, for (ObjCMessageExpr::arg_iterator I = ME->arg_begin(), E = ME->arg_end(); I != E; ++I) { - if (GetSVal(state, *I).isUndef()) { + if (state->getSVal(*I).isUndef()) { // Generate an error node for passing an uninitialized/undefined value // as an argument to a message expression. This node is a sink. @@ -2053,11 +2002,11 @@ void GRExprEngine::VisitCastPointerToInteger(SVal V, const GRState* state, // FIXME: Determine if the number of bits of the target type is // equal or exceeds the number of bits to store the pointer value. // If not, flag an error. - MakeNode(Dst, CastE, Pred, BindExpr(state, CastE, EvalCast(cast<Loc>(V), + MakeNode(Dst, CastE, Pred, state->bindExpr(CastE, EvalCast(cast<Loc>(V), CastE->getType()))); } else - MakeNode(Dst, CastE, Pred, BindExpr(state, CastE, V)); + MakeNode(Dst, CastE, Pred, state->bindExpr(CastE, V)); } @@ -2089,7 +2038,7 @@ void GRExprEngine::VisitCast(Expr* CastE, Expr* Ex, NodeTy* Pred, NodeSet& Dst){ for (NodeSet::iterator I1 = S1.begin(), E1 = S1.end(); I1 != E1; ++I1) { NodeTy* N = *I1; const GRState* state = GetState(N); - SVal V = GetSVal(state, Ex); + SVal V = state->getSVal(Ex); ASTContext& C = getContext(); // Unknown? @@ -2118,7 +2067,7 @@ void GRExprEngine::VisitCast(Expr* CastE, Expr* Ex, NodeTy* Pred, NodeSet& Dst){ if (nonloc::LocAsInteger *LV = dyn_cast<nonloc::LocAsInteger>(&V)) { // Just unpackage the lval and return it. V = LV->getLoc(); - MakeNode(Dst, CastE, N, BindExpr(state, CastE, V)); + MakeNode(Dst, CastE, N, state->bindExpr(CastE, V)); continue; } @@ -2190,18 +2139,18 @@ void GRExprEngine::VisitCast(Expr* CastE, Expr* Ex, NodeTy* Pred, NodeSet& Dst){ if (R) { V = loc::MemRegionVal(R); } else { V = UnknownVal(); } // Generate the new node in the ExplodedGraph. - MakeNode(Dst, CastE, N, BindExpr(Res.getState(), CastE, V)); + MakeNode(Dst, CastE, N, Res.getState()->bindExpr(CastE, V)); continue; } // All other cases. DispatchCast: { - MakeNode(Dst, CastE, N, BindExpr(state, CastE, - EvalCast(V, CastE->getType()))); + MakeNode(Dst, CastE, N, state->bindExpr(CastE, + EvalCast(V, CastE->getType()))); continue; } PassThrough: { - MakeNode(Dst, CastE, N, BindExpr(state, CastE, V)); + MakeNode(Dst, CastE, N, state->bindExpr(CastE, V)); } } } @@ -2215,13 +2164,13 @@ void GRExprEngine::VisitCompoundLiteralExpr(CompoundLiteralExpr* CL, for (NodeSet::iterator I = Tmp.begin(), EI = Tmp.end(); I!=EI; ++I) { const GRState* state = GetState(*I); - SVal ILV = GetSVal(state, ILE); - state = StateMgr.BindCompoundLiteral(state, CL, ILV); + SVal ILV = state->getSVal(ILE); + state = state->bindCompoundLiteral(CL, ILV); if (asLValue) - MakeNode(Dst, CL, *I, BindExpr(state, CL, StateMgr.GetLValue(state, CL))); + MakeNode(Dst, CL, *I, state->bindExpr(CL, state->getLValue(CL))); else - MakeNode(Dst, CL, *I, BindExpr(state, CL, ILV)); + MakeNode(Dst, CL, *I, state->bindExpr(CL, ILV)); } } @@ -2256,7 +2205,7 @@ void GRExprEngine::VisitDeclStmt(DeclStmt* DS, NodeTy* Pred, NodeSet& Dst) { // FIXME: Handle multi-dimensional VLAs. Expr* SE = VLA->getSizeExpr(); - SVal Size = GetSVal(state, SE); + SVal Size = state->getSVal(SE); if (Size.isUndef()) { if (NodeTy* N = Builder->generateNode(DS, state, Pred)) { @@ -2266,27 +2215,26 @@ void GRExprEngine::VisitDeclStmt(DeclStmt* DS, NodeTy* Pred, NodeSet& Dst) { continue; } - bool isFeasibleZero = false; - const GRState* ZeroSt = Assume(state, Size, false, isFeasibleZero); + const GRState* zeroState = state->assume(Size, false); + state = state->assume(Size, true); - bool isFeasibleNotZero = false; - state = Assume(state, Size, true, isFeasibleNotZero); - - if (isFeasibleZero) { - if (NodeTy* N = Builder->generateNode(DS, ZeroSt, Pred)) { + if (zeroState) { + if (NodeTy* N = Builder->generateNode(DS, zeroState, Pred)) { N->markAsSink(); - if (isFeasibleNotZero) ImplicitBadSizedVLA.insert(N); - else ExplicitBadSizedVLA.insert(N); + if (state) + ImplicitBadSizedVLA.insert(N); + else + ExplicitBadSizedVLA.insert(N); } } - if (!isFeasibleNotZero) + if (!state) continue; } // Decls without InitExpr are not initialized explicitly. if (InitEx) { - SVal InitVal = GetSVal(state, InitEx); + SVal InitVal = state->getSVal(InitEx); QualType T = VD->getType(); // Recover some path-sensitivity if a scalar value evaluated to @@ -2343,7 +2291,7 @@ void GRExprEngine::VisitInitListExpr(InitListExpr* E, NodeTy* Pred, // e.g: static int* myArray[] = {}; if (NumInitElements == 0) { SVal V = NonLoc::MakeCompoundVal(T, StartVals, getBasicVals()); - MakeNode(Dst, E, Pred, BindExpr(state, E, V)); + MakeNode(Dst, E, Pred, state->bindExpr(E, V)); return; } @@ -2366,7 +2314,7 @@ void GRExprEngine::VisitInitListExpr(InitListExpr* E, NodeTy* Pred, for (NodeSet::iterator NI=Tmp.begin(), NE=Tmp.end(); NI!=NE; ++NI) { // Get the last initializer value. state = GetState(*NI); - SVal InitV = GetSVal(state, cast<Expr>(*X.Itr)); + SVal InitV = state->getSVal(cast<Expr>(*X.Itr)); // Construct the new list of values by prepending the new value to // the already constructed list. @@ -2378,7 +2326,7 @@ void GRExprEngine::VisitInitListExpr(InitListExpr* E, NodeTy* Pred, SVal V = NonLoc::MakeCompoundVal(T, NewVals, getBasicVals()); // Make final state and node. - MakeNode(Dst, E, *NI, BindExpr(state, E, V)); + MakeNode(Dst, E, *NI, state->bindExpr(E, V)); } else { // Still some initializer values to go. Push them onto the worklist. @@ -2404,7 +2352,7 @@ void GRExprEngine::VisitInitListExpr(InitListExpr* E, NodeTy* Pred, Visit(Init, Pred, Tmp); for (NodeSet::iterator I = Tmp.begin(), EI = Tmp.end(); I != EI; ++I) { state = GetState(*I); - MakeNode(Dst, E, *I, BindExpr(state, E, GetSVal(state, Init))); + MakeNode(Dst, E, *I, state->bindExpr(E, state->getSVal(Init))); } return; } @@ -2445,8 +2393,8 @@ void GRExprEngine::VisitSizeOfAlignOfExpr(SizeOfAlignOfExpr* Ex, amt = getContext().getTypeAlign(T) / 8; MakeNode(Dst, Ex, Pred, - BindExpr(GetState(Pred), Ex, - NonLoc::MakeVal(getBasicVals(), amt, Ex->getType()))); + GetState(Pred)->bindExpr(Ex, NonLoc::MakeVal(getBasicVals(), amt, + Ex->getType()))); } @@ -2467,10 +2415,10 @@ void GRExprEngine::VisitUnaryOperator(UnaryOperator* U, NodeTy* Pred, for (NodeSet::iterator I=Tmp.begin(), E=Tmp.end(); I!=E; ++I) { const GRState* state = GetState(*I); - SVal location = GetSVal(state, Ex); + SVal location = state->getSVal(Ex); if (asLValue) - MakeNode(Dst, U, *I, BindExpr(state, U, location), + MakeNode(Dst, U, *I, state->bindExpr(U, location), ProgramPoint::PostLValueKind); else EvalLoad(Dst, U, *I, state, location); @@ -2497,7 +2445,7 @@ void GRExprEngine::VisitUnaryOperator(UnaryOperator* U, NodeTy* Pred, // For all other types, UnaryOperator::Real is an identity operation. assert (U->getType() == Ex->getType()); const GRState* state = GetState(*I); - MakeNode(Dst, U, *I, BindExpr(state, U, GetSVal(state, Ex))); + MakeNode(Dst, U, *I, state->bindExpr(U, state->getSVal(Ex))); } return; @@ -2521,7 +2469,7 @@ void GRExprEngine::VisitUnaryOperator(UnaryOperator* U, NodeTy* Pred, assert (Ex->getType()->isIntegerType()); const GRState* state = GetState(*I); SVal X = NonLoc::MakeVal(getBasicVals(), 0, Ex->getType()); - MakeNode(Dst, U, *I, BindExpr(state, U, X)); + MakeNode(Dst, U, *I, state->bindExpr(U, X)); } return; @@ -2546,7 +2494,7 @@ void GRExprEngine::VisitUnaryOperator(UnaryOperator* U, NodeTy* Pred, for (NodeSet::iterator I=Tmp.begin(), E=Tmp.end(); I!=E; ++I) { const GRState* state = GetState(*I); - MakeNode(Dst, U, *I, BindExpr(state, U, GetSVal(state, Ex))); + MakeNode(Dst, U, *I, state->bindExpr(U, state->getSVal(Ex))); } return; @@ -2561,8 +2509,8 @@ void GRExprEngine::VisitUnaryOperator(UnaryOperator* U, NodeTy* Pred, for (NodeSet::iterator I=Tmp.begin(), E=Tmp.end(); I!=E; ++I) { const GRState* state = GetState(*I); - SVal V = GetSVal(state, Ex); - state = BindExpr(state, U, V); + SVal V = state->getSVal(Ex); + state = state->bindExpr(U, V); MakeNode(Dst, U, *I, state); } @@ -2582,10 +2530,10 @@ void GRExprEngine::VisitUnaryOperator(UnaryOperator* U, NodeTy* Pred, const GRState* state = GetState(*I); // Get the value of the subexpression. - SVal V = GetSVal(state, Ex); + SVal V = state->getSVal(Ex); if (V.isUnknownOrUndef()) { - MakeNode(Dst, U, *I, BindExpr(state, U, V)); + MakeNode(Dst, U, *I, state->bindExpr(U, V)); continue; } @@ -2607,12 +2555,12 @@ void GRExprEngine::VisitUnaryOperator(UnaryOperator* U, NodeTy* Pred, case UnaryOperator::Not: // FIXME: Do we need to handle promotions? - state = BindExpr(state, U, EvalComplement(cast<NonLoc>(V))); + state = state->bindExpr(U, EvalComplement(cast<NonLoc>(V))); break; case UnaryOperator::Minus: // FIXME: Do we need to handle promotions? - state = BindExpr(state, U, EvalMinus(U, cast<NonLoc>(V))); + state = state->bindExpr(U, EvalMinus(U, cast<NonLoc>(V))); break; case UnaryOperator::LNot: @@ -2626,7 +2574,7 @@ void GRExprEngine::VisitUnaryOperator(UnaryOperator* U, NodeTy* Pred, Loc X = Loc::MakeNull(getBasicVals()); SVal Result = EvalBinOp(state,BinaryOperator::EQ, cast<Loc>(V), X, U->getType()); - state = BindExpr(state, U, Result); + state = state->bindExpr(U, Result); } else { nonloc::ConcreteInt X(getBasicVals().getValue(0, Ex->getType())); @@ -2660,7 +2608,7 @@ void GRExprEngine::VisitUnaryOperator(UnaryOperator* U, NodeTy* Pred, for (NodeSet::iterator I = Tmp.begin(), E = Tmp.end(); I!=E; ++I) { const GRState* state = GetState(*I); - SVal V1 = GetSVal(state, Ex); + SVal V1 = state->getSVal(Ex); // Perform a load. NodeSet Tmp2; @@ -2669,11 +2617,11 @@ void GRExprEngine::VisitUnaryOperator(UnaryOperator* U, NodeTy* Pred, for (NodeSet::iterator I2 = Tmp2.begin(), E2 = Tmp2.end(); I2!=E2; ++I2) { state = GetState(*I2); - SVal V2 = GetSVal(state, Ex); + SVal V2 = state->getSVal(Ex); // Propagate unknown and undefined values. if (V2.isUnknownOrUndef()) { - MakeNode(Dst, U, *I2, BindExpr(state, U, V2)); + MakeNode(Dst, U, *I2, state->bindExpr(U, V2)); continue; } @@ -2697,23 +2645,20 @@ void GRExprEngine::VisitUnaryOperator(UnaryOperator* U, NodeTy* Pred, ValMgr.makeZeroVal(U->getType()), getContext().IntTy); - bool isFeasible = false; - Assume(state, Constraint, true, isFeasible); - if (!isFeasible) { + if (!state->assume(Constraint, true)) { // It isn't feasible for the original value to be null. // Propagate this constraint. Constraint = EvalBinOp(state, BinaryOperator::EQ, Result, ValMgr.makeZeroVal(U->getType()), getContext().IntTy); - bool isFeasible = false; - state = Assume(state, Constraint, false, isFeasible); - assert(isFeasible && state); + state = state->assume(Constraint, false); + assert(state); } } } - state = BindExpr(state, U, U->isPostfix() ? V2 : Result); + state = state->bindExpr(U, U->isPostfix() ? V2 : Result); // Perform the store. EvalStore(Dst, U, *I2, state, V1, Result); @@ -2761,11 +2706,11 @@ void GRExprEngine::VisitAsmStmtHelperInputs(AsmStmt* A, for (AsmStmt::outputs_iterator OI = A->begin_outputs(), OE = A->end_outputs(); OI != OE; ++OI) { - SVal X = GetSVal(state, *OI); + SVal X = state->getSVal(*OI); assert (!isa<NonLoc>(X)); // Should be an Lval, or unknown, undef. if (isa<Loc>(X)) - state = BindLoc(state, cast<Loc>(X), UnknownVal()); + state = state->bindLoc(cast<Loc>(X), UnknownVal()); } MakeNode(Dst, A, Pred, state); @@ -2810,7 +2755,7 @@ void GRExprEngine::VisitReturnStmt(ReturnStmt* S, NodeTy* Pred, NodeSet& Dst) { Visit(R, Pred, Tmp); for (NodeSet::iterator I = Tmp.begin(), E = Tmp.end(); I != E; ++I) { - SVal X = GetSVal((*I)->getState(), R); + SVal X = (*I)->getState()->getSVal(R); // Check if we return the address of a stack variable. if (isa<loc::MemRegionVal>(X)) { @@ -2861,29 +2806,24 @@ const GRState* GRExprEngine::CheckDivideZero(Expr* Ex, const GRState* state, // Check for divide/remainder-by-zero. // First, "assume" that the denominator is 0 or undefined. - - bool isFeasibleZero = false; - const GRState* ZeroSt = Assume(state, Denom, false, isFeasibleZero); + const GRState* zeroState = state->assume(Denom, false); // Second, "assume" that the denominator cannot be 0. + state = state->assume(Denom, true); - bool isFeasibleNotZero = false; - state = Assume(state, Denom, true, isFeasibleNotZero); - - // Create the node for the divide-by-zero (if it occurred). - - if (isFeasibleZero) - if (NodeTy* DivZeroNode = Builder->generateNode(Ex, ZeroSt, Pred)) { + // Create the node for the divide-by-zero (if it occurred). + if (zeroState) + if (NodeTy* DivZeroNode = Builder->generateNode(Ex, zeroState, Pred)) { DivZeroNode->markAsSink(); - if (isFeasibleNotZero) + if (state) ImplicitBadDivides.insert(DivZeroNode); else ExplicitBadDivides.insert(DivZeroNode); } - return isFeasibleNotZero ? state : 0; + return state; } void GRExprEngine::VisitBinaryOperator(BinaryOperator* B, @@ -2907,7 +2847,7 @@ void GRExprEngine::VisitBinaryOperator(BinaryOperator* B, for (NodeSet::iterator I1=Tmp1.begin(), E1=Tmp1.end(); I1 != E1; ++I1) { - SVal LeftV = GetSVal((*I1)->getState(), LHS); + SVal LeftV = (*I1)->getState()->getSVal(LHS); // Process the RHS. @@ -2921,7 +2861,7 @@ void GRExprEngine::VisitBinaryOperator(BinaryOperator* B, const GRState* state = GetState(*I2); const GRState* OldSt = state; - SVal RightV = GetSVal(state, RHS); + SVal RightV = state->getSVal(RHS); BinaryOperator::Opcode Op = B->getOpcode(); switch (Op) { @@ -2942,7 +2882,7 @@ void GRExprEngine::VisitBinaryOperator(BinaryOperator* B, // Simulate the effects of a "store": bind the value of the RHS // to the L-Value represented by the LHS. - EvalStore(Dst, B, LHS, *I2, BindExpr(state, B, RightV), LeftV, + EvalStore(Dst, B, LHS, *I2, state->bindExpr(B, RightV), LeftV, RightV); continue; } @@ -2996,7 +2936,7 @@ void GRExprEngine::VisitBinaryOperator(BinaryOperator* B, // Otherwise, create a new node. - MakeNode(Dst, B, *I2, BindExpr(state, B, Result)); + MakeNode(Dst, B, *I2, state->bindExpr(B, Result)); continue; } } @@ -3021,13 +2961,13 @@ void GRExprEngine::VisitBinaryOperator(BinaryOperator* B, // Perform a load (the LHS). This performs the checks for // null dereferences, and so on. NodeSet Tmp3; - SVal location = GetSVal(state, LHS); + SVal location = state->getSVal(LHS); EvalLoad(Tmp3, LHS, *I2, state, location); for (NodeSet::iterator I3=Tmp3.begin(), E3=Tmp3.end(); I3!=E3; ++I3) { state = GetState(*I3); - SVal V = GetSVal(state, LHS); + SVal V = state->getSVal(LHS); // Check for divide-by-zero. if ((Op == BinaryOperator::Div || Op == BinaryOperator::Rem) @@ -3044,13 +2984,13 @@ void GRExprEngine::VisitBinaryOperator(BinaryOperator* B, // Propagate undefined values (left-side). if (V.isUndef()) { - EvalStore(Dst, B, LHS, *I3, BindExpr(state, B, V), location, V); + EvalStore(Dst, B, LHS, *I3, state->bindExpr(B, V), location, V); continue; } // Propagate unknown values (left and right-side). if (RightV.isUnknown() || V.isUnknown()) { - EvalStore(Dst, B, LHS, *I3, BindExpr(state, B, UnknownVal()), + EvalStore(Dst, B, LHS, *I3, state->bindExpr(B, UnknownVal()), location, UnknownVal()); continue; } @@ -3076,7 +3016,7 @@ void GRExprEngine::VisitBinaryOperator(BinaryOperator* B, // Evaluate operands and promote to result type. if (RightV.isUndef()) { // Propagate undefined values (right-side). - EvalStore(Dst, B, LHS, *I3, BindExpr(state, B, RightV), location, + EvalStore(Dst, B, LHS, *I3, state->bindExpr(B, RightV), location, RightV); continue; } @@ -3120,7 +3060,7 @@ void GRExprEngine::VisitBinaryOperator(BinaryOperator* B, LHSVal = (LTy == CTy) ? Result : EvalCast(Result,LTy); } - EvalStore(Dst, B, LHS, *I3, BindExpr(state, B, Result), location, + EvalStore(Dst, B, LHS, *I3, state->bindExpr(B, Result), location, LHSVal); } } @@ -3353,8 +3293,8 @@ struct VISIBILITY_HIDDEN DOTGraphTraits<GRExprEngine::NodeTy*> : Out << "\\|StateID: " << (void*) N->getState() << "\\|"; - GRStateRef state(N->getState(), GraphPrintCheckerState->getStateManager()); - state.printDOT(Out); + const GRState *state = N->getState(); + state->printDOT(Out); Out << "\\l"; return Out.str(); diff --git a/lib/Analysis/GRExprEngineInternalChecks.cpp b/lib/Analysis/GRExprEngineInternalChecks.cpp index 9aea124..7f7270d 100644 --- a/lib/Analysis/GRExprEngineInternalChecks.cpp +++ b/lib/Analysis/GRExprEngineInternalChecks.cpp @@ -347,9 +347,7 @@ public: assert (E && "Return expression cannot be NULL"); // Get the value associated with E. - loc::MemRegionVal V = - cast<loc::MemRegionVal>(Eng.getStateManager().GetSVal(N->getState(), - E)); + loc::MemRegionVal V = cast<loc::MemRegionVal>(N->getState()->getSVal(E)); // Generate a report for this bug. std::string buf; @@ -427,7 +425,7 @@ class VISIBILITY_HIDDEN UndefBranch : public BuiltinBug { return Ex; } - bool MatchesCriteria(Expr* Ex) { return VM.GetSVal(St, Ex).isUndef(); } + bool MatchesCriteria(Expr* Ex) { return St->getSVal(Ex).isUndef(); } }; public: @@ -519,8 +517,7 @@ public: "variable-length array (VLA) '" << VD->getNameAsString() << "' evaluates to "; - bool isUndefined = Eng.getStateManager().GetSVal(N->getState(), - SizeExpr).isUndef(); + bool isUndefined = N->getState()->getSVal(SizeExpr).isUndef(); if (isUndefined) os << "an undefined or garbage value."; @@ -563,13 +560,13 @@ public: CallExpr* CE = cast<CallExpr>(cast<PostStmt>(N->getLocation()).getStmt()); const GRState* state = N->getState(); - SVal X = VMgr.GetSVal(state, CE->getCallee()); + SVal X = state->getSVal(CE->getCallee()); const FunctionDecl* FD = X.getAsFunctionDecl(); if (!FD) return false; - const NonNullAttr* Att = FD->getAttr<NonNullAttr>(); + const NonNullAttr* Att = FD->getAttr<NonNullAttr>(BR.getContext()); if (!Att) return false; @@ -819,24 +816,15 @@ public: // Check if in the previous state it was feasible for this constraint // to *not* be true. - - GRStateManager &StateMgr = BRC.getStateManager(); - bool isFeasible = false; - if (StateMgr.Assume(PrevN->getState(), Constraint, !Assumption, - isFeasible)) { - assert(isFeasible); // Eventually we don't need 'isFeasible'. + if (PrevN->getState()->assume(Constraint, !Assumption)) { isSatisfied = true; // As a sanity check, make sure that the negation of the constraint // was infeasible in the current state. If it is feasible, we somehow // missed the transition point. - isFeasible = false; - if (StateMgr.Assume(N->getState(), Constraint, !Assumption, - isFeasible)) { - assert(isFeasible); + if (N->getState()->assume(Constraint, !Assumption)) return NULL; - } // We found the transition point for the constraint. We now need to // pretty-print the constraint. (work-in-progress) @@ -897,7 +885,7 @@ static void registerTrackNullOrUndefValue(BugReporterContext& BRC, StateMgr.getRegionManager().getVarRegion(VD); // What did we load? - SVal V = StateMgr.GetSVal(state, S); + SVal V = state->getSVal(S); if (isa<loc::ConcreteInt>(V) || isa<nonloc::ConcreteInt>(V) || V.isUndef()) { @@ -906,7 +894,7 @@ static void registerTrackNullOrUndefValue(BugReporterContext& BRC, } } - SVal V = StateMgr.GetSValAsScalarOrLoc(state, S); + SVal V = state->getSValAsScalarOrLoc(S); // Uncomment this to find cases where we aren't properly getting the // base value that was dereferenced. diff --git a/lib/Analysis/GRSimpleVals.cpp b/lib/Analysis/GRSimpleVals.cpp index e1c4848..7e54f1a 100644 --- a/lib/Analysis/GRSimpleVals.cpp +++ b/lib/Analysis/GRSimpleVals.cpp @@ -363,11 +363,13 @@ void GRSimpleVals::EvalCall(ExplodedNodeSet<GRState>& Dst, for (CallExpr::arg_iterator I = CE->arg_begin(), E = CE->arg_end(); I != E; ++I) { - SVal V = StateMgr.GetSVal(St, *I); + SVal V = St->getSVal(*I); - if (isa<loc::MemRegionVal>(V)) - St = StateMgr.BindLoc(St, cast<Loc>(V), UnknownVal()); - else if (isa<nonloc::LocAsInteger>(V)) + if (isa<loc::MemRegionVal>(V)) { + const MemRegion *R = cast<loc::MemRegionVal>(V).getRegion(); + if (R->isBoundable(Eng.getContext())) + St = StateMgr.BindLoc(St, cast<Loc>(V), UnknownVal()); + } else if (isa<nonloc::LocAsInteger>(V)) St = StateMgr.BindLoc(St, cast<nonloc::LocAsInteger>(V).getLoc(), UnknownVal()); @@ -380,7 +382,7 @@ void GRSimpleVals::EvalCall(ExplodedNodeSet<GRState>& Dst, if (Loc::IsLocType(T) || (T->isIntegerType() && T->isScalarType())) { unsigned Count = Builder.getCurrentBlockCount(); SVal X = Eng.getValueManager().getConjuredSymbolVal(CE, Count); - St = StateMgr.BindExpr(St, CE, X, Eng.getCFG().isBlkExpr(CE), false); + St = St->bindExpr(CE, X, Eng.getCFG().isBlkExpr(CE), false); } Builder.MakeNode(Dst, CE, Pred, St); @@ -398,18 +400,16 @@ void GRSimpleVals::EvalObjCMessageExpr(ExplodedNodeSet<GRState>& Dst, // The basic transfer function logic for message expressions does nothing. - // We just invalidate all arguments passed in by references. - - GRStateManager& StateMgr = Eng.getStateManager(); - const GRState* St = Builder.GetState(Pred); + // We just invalidate all arguments passed in by references. + const GRState *St = Builder.GetState(Pred); for (ObjCMessageExpr::arg_iterator I = ME->arg_begin(), E = ME->arg_end(); I != E; ++I) { - SVal V = StateMgr.GetSVal(St, *I); + SVal V = St->getSVal(*I); if (isa<Loc>(V)) - St = StateMgr.BindLoc(St, cast<Loc>(V), UnknownVal()); + St = St->bindLoc(cast<Loc>(V), UnknownVal()); } Builder.MakeNode(Dst, ME, Pred, St); diff --git a/lib/Analysis/GRState.cpp b/lib/Analysis/GRState.cpp index e0e478c..aeb1c04 100644 --- a/lib/Analysis/GRState.cpp +++ b/lib/Analysis/GRState.cpp @@ -69,8 +69,7 @@ const GRState* GRStateManager::Unbind(const GRState* St, Loc LV) { } const GRState* GRStateManager::getInitialState() { - - GRState StateImpl(EnvMgr.getInitialEnvironment(), + GRState StateImpl(this, EnvMgr.getInitialEnvironment(), StoreMgr->getInitialStore(), GDMFactory.GetEmptyMap()); @@ -92,25 +91,19 @@ const GRState* GRStateManager::getPersistentState(GRState& State) { return I; } -const GRState* GRStateManager::MakeStateWithStore(const GRState* St, - Store store) { - GRState NewSt = *St; +const GRState* GRState::makeWithStore(Store store) const { + GRState NewSt = *this; NewSt.St = store; - return getPersistentState(NewSt); + return Mgr->getPersistentState(NewSt); } - //===----------------------------------------------------------------------===// // State pretty-printing. //===----------------------------------------------------------------------===// -void GRState::print(std::ostream& Out, StoreManager& StoreMgr, - ConstraintManager& ConstraintMgr, - Printer** Beg, Printer** End, - const char* nl, const char* sep) const { - +void GRState::print(std::ostream& Out, const char* nl, const char* sep) const { // Print the store. - StoreMgr.print(getStore(), Out, nl, sep); + Mgr->getStoreManager().print(getStore(), Out, nl, sep); // Print Subexpression bindings. bool isFirst = true; @@ -150,24 +143,21 @@ void GRState::print(std::ostream& Out, StoreManager& StoreMgr, I.getData().print(Out); } - ConstraintMgr.print(this, Out, nl, sep); + Mgr->getConstraintManager().print(this, Out, nl, sep); - // Print checker-specific data. - for ( ; Beg != End ; ++Beg) (*Beg)->Print(Out, this, nl, sep); + // Print checker-specific data. + for (std::vector<Printer*>::iterator I = Mgr->Printers.begin(), + E = Mgr->Printers.end(); I != E; ++I) { + (*I)->Print(Out, this, nl, sep); + } } -void GRStateRef::printDOT(std::ostream& Out) const { +void GRState::printDOT(std::ostream& Out) const { print(Out, "\\l", "\\|"); } -void GRStateRef::printStdErr() const { +void GRState::printStdErr() const { print(*llvm::cerr); -} - -void GRStateRef::print(std::ostream& Out, const char* nl, const char* sep)const{ - GRState::Printer **beg = Mgr->Printers.empty() ? 0 : &Mgr->Printers[0]; - GRState::Printer **end = !beg ? 0 : beg + Mgr->Printers.size(); - St->print(Out, *Mgr->StoreMgr, *Mgr->ConstraintMgr, beg, end, nl, sep); } //===----------------------------------------------------------------------===// @@ -213,13 +203,13 @@ class VISIBILITY_HIDDEN ScanReachableSymbols : public SubRegionMap::Visitor { typedef llvm::DenseSet<const MemRegion*> VisitedRegionsTy; VisitedRegionsTy visited; - GRStateRef state; + const GRState *state; SymbolVisitor &visitor; llvm::OwningPtr<SubRegionMap> SRM; public: - ScanReachableSymbols(GRStateManager* sm, const GRState *st, SymbolVisitor& v) - : state(st, *sm), visitor(v) {} + ScanReachableSymbols(const GRState *st, SymbolVisitor& v) + : state(st), visitor(v) {} bool scan(nonloc::CompoundVal val); bool scan(SVal val); @@ -270,19 +260,18 @@ bool ScanReachableSymbols::scan(const MemRegion *R) { return false; // Now look at the binding to this region (if any). - if (!scan(state.GetSValAsScalarOrLoc(R))) + if (!scan(state->getSValAsScalarOrLoc(R))) return false; // Now look at the subregions. if (!SRM.get()) - SRM.reset(state.getManager().getStoreManager().getSubRegionMap(state)); + SRM.reset(state->getStateManager().getStoreManager().getSubRegionMap(state)); return SRM->iterSubRegions(R, *this); } -bool GRStateManager::scanReachableSymbols(SVal val, const GRState* state, - SymbolVisitor& visitor) { - ScanReachableSymbols S(this, state, visitor); +bool GRState::scanReachableSymbols(SVal val, SymbolVisitor& visitor) const { + ScanReachableSymbols S(this, visitor); return S.scan(val); } diff --git a/lib/Analysis/GRTransferFuncs.cpp b/lib/Analysis/GRTransferFuncs.cpp index 69c09d9..3c14ee9 100644 --- a/lib/Analysis/GRTransferFuncs.cpp +++ b/lib/Analysis/GRTransferFuncs.cpp @@ -23,6 +23,5 @@ void GRTransferFuncs::EvalBinOpNN(GRStateSet& OStates, BinaryOperator::Opcode Op, NonLoc L, NonLoc R, QualType T) { - OStates.Add(Eng.getStateManager().BindExpr(St, Ex, - DetermEvalBinOpNN(Eng, Op, L, R, T))); + OStates.Add(St->bindExpr(Ex, DetermEvalBinOpNN(Eng, Op, L, R, T))); } diff --git a/lib/Analysis/MemRegion.cpp b/lib/Analysis/MemRegion.cpp index 9f066f4..9e11a26 100644 --- a/lib/Analysis/MemRegion.cpp +++ b/lib/Analysis/MemRegion.cpp @@ -296,10 +296,12 @@ MemRegionManager::getCompoundLiteralRegion(const CompoundLiteralExpr* CL) { ElementRegion* MemRegionManager::getElementRegion(QualType elementType, SVal Idx, - const MemRegion* superRegion){ + const MemRegion* superRegion, ASTContext& Ctx){ + + QualType T = Ctx.getCanonicalType(elementType); llvm::FoldingSetNodeID ID; - ElementRegion::ProfileRegion(ID, elementType, Idx, superRegion); + ElementRegion::ProfileRegion(ID, T, Idx, superRegion); void* InsertPos; MemRegion* data = Regions.FindNodeOrInsertPos(ID, InsertPos); @@ -307,7 +309,7 @@ MemRegionManager::getElementRegion(QualType elementType, SVal Idx, if (!R) { R = (ElementRegion*) A.Allocate<ElementRegion>(); - new (R) ElementRegion(elementType, Idx, superRegion); + new (R) ElementRegion(T, Idx, superRegion); Regions.InsertNode(R, InsertPos); } diff --git a/lib/Analysis/RangeConstraintManager.cpp b/lib/Analysis/RangeConstraintManager.cpp index f6ac2b9..73c68bc 100644 --- a/lib/Analysis/RangeConstraintManager.cpp +++ b/lib/Analysis/RangeConstraintManager.cpp @@ -233,28 +233,27 @@ struct GRStateTrait<ConstraintRange> namespace { class VISIBILITY_HIDDEN RangeConstraintManager : public SimpleConstraintManager{ - RangeSet GetRange(GRStateRef state, SymbolRef sym); + RangeSet GetRange(const GRState *state, SymbolRef sym); public: - RangeConstraintManager(GRStateManager& statemgr) - : SimpleConstraintManager(statemgr) {} + RangeConstraintManager() {} const GRState* AssumeSymNE(const GRState* St, SymbolRef sym, - const llvm::APSInt& V, bool& isFeasible); + const llvm::APSInt& V); const GRState* AssumeSymEQ(const GRState* St, SymbolRef sym, - const llvm::APSInt& V, bool& isFeasible); + const llvm::APSInt& V); const GRState* AssumeSymLT(const GRState* St, SymbolRef sym, - const llvm::APSInt& V, bool& isFeasible); + const llvm::APSInt& V); const GRState* AssumeSymGT(const GRState* St, SymbolRef sym, - const llvm::APSInt& V, bool& isFeasible); + const llvm::APSInt& V); const GRState* AssumeSymGE(const GRState* St, SymbolRef sym, - const llvm::APSInt& V, bool& isFeasible); + const llvm::APSInt& V); const GRState* AssumeSymLE(const GRState* St, SymbolRef sym, - const llvm::APSInt& V, bool& isFeasible); + const llvm::APSInt& V); const llvm::APSInt* getSymVal(const GRState* St, SymbolRef sym) const; @@ -275,9 +274,8 @@ private: } // end anonymous namespace -ConstraintManager* clang::CreateRangeConstraintManager(GRStateManager& StateMgr) -{ - return new RangeConstraintManager(StateMgr); +ConstraintManager* clang::CreateRangeConstraintManager(GRStateManager&) { + return new RangeConstraintManager(); } const llvm::APSInt* RangeConstraintManager::getSymVal(const GRState* St, @@ -289,12 +287,11 @@ const llvm::APSInt* RangeConstraintManager::getSymVal(const GRState* St, /// Scan all symbols referenced by the constraints. If the symbol is not alive /// as marked in LSymbols, mark it as dead in DSymbols. const GRState* -RangeConstraintManager::RemoveDeadBindings(const GRState* St, +RangeConstraintManager::RemoveDeadBindings(const GRState* state, SymbolReaper& SymReaper) { - GRStateRef state(St, StateMgr); - ConstraintRangeTy CR = state.get<ConstraintRange>(); - ConstraintRangeTy::Factory& CRFactory = state.get_context<ConstraintRange>(); + ConstraintRangeTy CR = state->get<ConstraintRange>(); + ConstraintRangeTy::Factory& CRFactory = state->get_context<ConstraintRange>(); for (ConstraintRangeTy::iterator I = CR.begin(), E = CR.end(); I != E; ++I) { SymbolRef sym = I.getKey(); @@ -302,7 +299,7 @@ RangeConstraintManager::RemoveDeadBindings(const GRState* St, CR = CRFactory.Remove(CR, sym); } - return state.set<ConstraintRange>(CR); + return state->set<ConstraintRange>(CR); } //===------------------------------------------------------------------------=== @@ -310,14 +307,14 @@ RangeConstraintManager::RemoveDeadBindings(const GRState* St, //===------------------------------------------------------------------------===/ RangeSet -RangeConstraintManager::GetRange(GRStateRef state, SymbolRef sym) { - if (ConstraintRangeTy::data_type* V = state.get<ConstraintRange>(sym)) +RangeConstraintManager::GetRange(const GRState *state, SymbolRef sym) { + if (ConstraintRangeTy::data_type* V = state->get<ConstraintRange>(sym)) return *V; // Lazily generate a new RangeSet representing all possible values for the // given symbol type. - QualType T = state.getSymbolManager().getType(sym); - BasicValueFactory& BV = state.getBasicVals(); + QualType T = state->getSymbolManager().getType(sym); + BasicValueFactory& BV = state->getBasicVals(); return RangeSet(F, BV.getMinValue(T), BV.getMaxValue(T)); } @@ -327,12 +324,10 @@ RangeConstraintManager::GetRange(GRStateRef state, SymbolRef sym) { #define AssumeX(OP)\ const GRState*\ -RangeConstraintManager::AssumeSym ## OP(const GRState* St, SymbolRef sym,\ - const llvm::APSInt& V, bool& isFeasible){\ - GRStateRef state(St, StateMgr);\ - const RangeSet& R = GetRange(state, sym).Add##OP(state.getBasicVals(), F, V);\ - isFeasible = !R.isEmpty();\ - return isFeasible ? state.set<ConstraintRange>(sym, R).getState() : 0;\ +RangeConstraintManager::AssumeSym ## OP(const GRState* state, SymbolRef sym,\ + const llvm::APSInt& V){\ + const RangeSet& R = GetRange(state, sym).Add##OP(state->getBasicVals(), F, V);\ + return !R.isEmpty() ? state->set<ConstraintRange>(sym, R) : NULL;\ } AssumeX(EQ) diff --git a/lib/Analysis/RegionStore.cpp b/lib/Analysis/RegionStore.cpp index eae3aef..5f2b8f8 100644 --- a/lib/Analysis/RegionStore.cpp +++ b/lib/Analysis/RegionStore.cpp @@ -31,6 +31,32 @@ using namespace clang; typedef llvm::ImmutableMap<const MemRegion*, SVal> RegionBindingsTy; //===----------------------------------------------------------------------===// +// Fine-grained control of RegionStoreManager. +//===----------------------------------------------------------------------===// + +namespace { +struct VISIBILITY_HIDDEN minimal_features_tag {}; +struct VISIBILITY_HIDDEN maximal_features_tag {}; + +class VISIBILITY_HIDDEN RegionStoreFeatures { + bool SupportsFields; + bool SupportsRemaining; + +public: + RegionStoreFeatures(minimal_features_tag) : + SupportsFields(false), SupportsRemaining(false) {} + + RegionStoreFeatures(maximal_features_tag) : + SupportsFields(true), SupportsRemaining(false) {} + + void enableFields(bool t) { SupportsFields = t; } + + bool supportsFields() const { return SupportsFields; } + bool supportsRemaining() const { return SupportsRemaining; } +}; +} + +//===----------------------------------------------------------------------===// // Region "Views" //===----------------------------------------------------------------------===// // @@ -151,6 +177,7 @@ public: }; class VISIBILITY_HIDDEN RegionStoreManager : public StoreManager { + const RegionStoreFeatures Features; RegionBindingsTy::Factory RBFactory; RegionViews::Factory RVFactory; @@ -158,8 +185,9 @@ class VISIBILITY_HIDDEN RegionStoreManager : public StoreManager { const ImplicitParamDecl *SelfDecl; public: - RegionStoreManager(GRStateManager& mgr) + RegionStoreManager(GRStateManager& mgr, const RegionStoreFeatures &f) : StoreManager(mgr), + Features(f), RBFactory(mgr.getAllocator()), RVFactory(mgr.getAllocator()), SelfRegion(0), SelfDecl(0) { @@ -172,36 +200,32 @@ public: SubRegionMap* getSubRegionMap(const GRState *state); - const GRState* BindCompoundLiteral(const GRState* St, - const CompoundLiteralExpr* CL, SVal V); - /// getLValueString - Returns an SVal representing the lvalue of a /// StringLiteral. Within RegionStore a StringLiteral has an /// associated StringRegion, and the lvalue of a StringLiteral is /// the lvalue of that region. - SVal getLValueString(const GRState* St, const StringLiteral* S); + SVal getLValueString(const GRState *state, const StringLiteral* S); /// getLValueCompoundLiteral - Returns an SVal representing the /// lvalue of a compound literal. Within RegionStore a compound /// literal has an associated region, and the lvalue of the /// compound literal is the lvalue of that region. - SVal getLValueCompoundLiteral(const GRState* St, const CompoundLiteralExpr*); + SVal getLValueCompoundLiteral(const GRState *state, const CompoundLiteralExpr*); /// getLValueVar - Returns an SVal that represents the lvalue of a /// variable. Within RegionStore a variable has an associated /// VarRegion, and the lvalue of the variable is the lvalue of that region. - SVal getLValueVar(const GRState* St, const VarDecl* VD); + SVal getLValueVar(const GRState *state, const VarDecl* VD); - SVal getLValueIvar(const GRState* St, const ObjCIvarDecl* D, SVal Base); + SVal getLValueIvar(const GRState *state, const ObjCIvarDecl* D, SVal Base); - SVal getLValueField(const GRState* St, SVal Base, const FieldDecl* D); + SVal getLValueField(const GRState *state, SVal Base, const FieldDecl* D); - SVal getLValueFieldOrIvar(const GRState* St, SVal Base, const Decl* D); + SVal getLValueFieldOrIvar(const GRState *state, SVal Base, const Decl* D); - SVal getLValueElement(const GRState* St, QualType elementType, + SVal getLValueElement(const GRState *state, QualType elementType, SVal Base, SVal Offset); - SVal getSizeInElements(const GRState* St, const MemRegion* R); /// ArrayToPointer - Emulates the "decay" of an array to a pointer /// type. 'Array' represents the lvalue of the array being decayed @@ -211,27 +235,13 @@ public: /// casts from arrays to pointers. SVal ArrayToPointer(Loc Array); - CastResult CastRegion(const GRState* state, const MemRegion* R, + CastResult CastRegion(const GRState *state, const MemRegion* R, QualType CastToTy); - SVal EvalBinOp(const GRState *state,BinaryOperator::Opcode Op,Loc L,NonLoc R); + SVal EvalBinOp(const GRState *state, BinaryOperator::Opcode Op,Loc L,NonLoc R); - /// The high level logic for this method is this: - /// Retrieve (L) - /// if L has binding - /// return L's binding - /// else if L is in killset - /// return unknown - /// else - /// if L is on stack or heap - /// return undefined - /// else - /// return symbolic - SVal Retrieve(const GRState* state, Loc L, QualType T = QualType()); - const GRState* Bind(const GRState* St, Loc LV, SVal V); - Store Remove(Store store, Loc LV); Store getInitialStore() { return RBFactory.GetEmptyMap().getRoot(); } @@ -251,65 +261,130 @@ public: return SelfRegion; } - /// RemoveDeadBindings - Scans the RegionStore of 'state' for dead values. - /// It returns a new Store with these values removed, and populates LSymbols - // and DSymbols with the known set of live and dead symbols respectively. - Store RemoveDeadBindings(const GRState* state, Stmt* Loc, - SymbolReaper& SymReaper, - llvm::SmallVectorImpl<const MemRegion*>& RegionRoots); - const GRState* BindDecl(const GRState* St, const VarDecl* VD, SVal InitVal); + + //===-------------------------------------------------------------------===// + // Binding values to regions. + //===-------------------------------------------------------------------===// - const GRState* BindDeclWithNoInit(const GRState* St, const VarDecl* VD) { - return St; - } + const GRState *Bind(const GRState *state, Loc LV, SVal V); - const GRState* setExtent(const GRState* St, const MemRegion* R, SVal Extent); - const GRState* setCastType(const GRState* St, const MemRegion* R, QualType T); + const GRState *BindCompoundLiteral(const GRState *state, + const CompoundLiteralExpr* CL, SVal V); + + const GRState *BindDecl(const GRState *state, const VarDecl* VD, SVal InitVal); - static inline RegionBindingsTy GetRegionBindings(Store store) { - return RegionBindingsTy(static_cast<const RegionBindingsTy::TreeTy*>(store)); + const GRState *BindDeclWithNoInit(const GRState *state, const VarDecl* VD) { + return state; } - void print(Store store, std::ostream& Out, const char* nl, const char *sep); + /// BindStruct - Bind a compound value to a structure. + const GRState *BindStruct(const GRState *, const TypedRegion* R, SVal V); + + const GRState *BindArray(const GRState *state, const TypedRegion* R, SVal V); + + /// KillStruct - Set the entire struct to unknown. + const GRState *KillStruct(const GRState *state, const TypedRegion* R); - void iterBindings(Store store, BindingsHandler& f) { - // FIXME: Implement. - } - const GRState* setDefaultValue(const GRState* St, const MemRegion* R, SVal V); -private: - const GRState* BindArray(const GRState* St, const TypedRegion* R, SVal V); + const GRState *setDefaultValue(const GRState *state, const MemRegion* R, SVal V); + Store Remove(Store store, Loc LV); + + //===------------------------------------------------------------------===// + // Loading values from regions. + //===------------------------------------------------------------------===// + + /// The high level logic for this method is this: + /// Retrieve (L) + /// if L has binding + /// return L's binding + /// else if L is in killset + /// return unknown + /// else + /// if L is on stack or heap + /// return undefined + /// else + /// return symbolic + SVal Retrieve(const GRState *state, Loc L, QualType T = QualType()); + /// Retrieve the values in a struct and return a CompoundVal, used when doing /// struct copy: /// struct s x, y; /// x = y; /// y's value is retrieved by this method. - SVal RetrieveStruct(const GRState* St, const TypedRegion* R); + SVal RetrieveStruct(const GRState *St, const TypedRegion* R); + + SVal RetrieveArray(const GRState *St, const TypedRegion* R); - SVal RetrieveArray(const GRState* St, const TypedRegion* R); + //===------------------------------------------------------------------===// + // State pruning. + //===------------------------------------------------------------------===// + + /// RemoveDeadBindings - Scans the RegionStore of 'state' for dead values. + /// It returns a new Store with these values removed. + Store RemoveDeadBindings(const GRState *state, Stmt* Loc, SymbolReaper& SymReaper, + llvm::SmallVectorImpl<const MemRegion*>& RegionRoots); - const GRState* BindStruct(const GRState* St, const TypedRegion* R, SVal V); + //===------------------------------------------------------------------===// + // Region "extents". + //===------------------------------------------------------------------===// + + const GRState *setExtent(const GRState *state, const MemRegion* R, SVal Extent); + SVal getSizeInElements(const GRState *state, const MemRegion* R); - /// KillStruct - Set the entire struct to unknown. - const GRState* KillStruct(const GRState* St, const TypedRegion* R); + //===------------------------------------------------------------------===// + // Region "views". + //===------------------------------------------------------------------===// + + const GRState *AddRegionView(const GRState *state, const MemRegion* View, + const MemRegion* Base); + + const GRState *RemoveRegionView(const GRState *state, const MemRegion* View, + const MemRegion* Base); + //===------------------------------------------------------------------===// // Utility methods. - BasicValueFactory& getBasicVals() { return StateMgr.getBasicVals(); } - ASTContext& getContext() { return StateMgr.getContext(); } + //===------------------------------------------------------------------===// + + const GRState *setCastType(const GRState *state, const MemRegion* R, QualType T); - SymbolManager& getSymbolManager() { return StateMgr.getSymbolManager(); } + static inline RegionBindingsTy GetRegionBindings(Store store) { + return RegionBindingsTy(static_cast<const RegionBindingsTy::TreeTy*>(store)); + } - const GRState* AddRegionView(const GRState* St, - const MemRegion* View, const MemRegion* Base); - const GRState* RemoveRegionView(const GRState* St, - const MemRegion* View, const MemRegion* Base); + void print(Store store, std::ostream& Out, const char* nl, const char *sep); + + void iterBindings(Store store, BindingsHandler& f) { + // FIXME: Implement. + } + + // FIXME: Remove. + BasicValueFactory& getBasicVals() { + return StateMgr.getBasicVals(); + } + + // FIXME: Remove. + ASTContext& getContext() { return StateMgr.getContext(); } + + // FIXME: Use ValueManager? + SymbolManager& getSymbolManager() { return StateMgr.getSymbolManager(); } }; } // end anonymous namespace -StoreManager* clang::CreateRegionStoreManager(GRStateManager& StMgr) { - return new RegionStoreManager(StMgr); +//===----------------------------------------------------------------------===// +// RegionStore creation. +//===----------------------------------------------------------------------===// + +StoreManager *clang::CreateRegionStoreManager(GRStateManager& StMgr) { + RegionStoreFeatures F = maximal_features_tag(); + return new RegionStoreManager(StMgr, F); +} + +StoreManager *clang::CreateFieldsOnlyRegionStoreManager(GRStateManager &StMgr) { + RegionStoreFeatures F = minimal_features_tag(); + F.enableFields(true); + return new RegionStoreManager(StMgr, F); } SubRegionMap* RegionStoreManager::getSubRegionMap(const GRState *state) { @@ -324,11 +399,15 @@ SubRegionMap* RegionStoreManager::getSubRegionMap(const GRState *state) { return M; } +//===----------------------------------------------------------------------===// +// getLValueXXX methods. +//===----------------------------------------------------------------------===// + /// getLValueString - Returns an SVal representing the lvalue of a /// StringLiteral. Within RegionStore a StringLiteral has an /// associated StringRegion, and the lvalue of a StringLiteral is the /// lvalue of that region. -SVal RegionStoreManager::getLValueString(const GRState* St, +SVal RegionStoreManager::getLValueString(const GRState *St, const StringLiteral* S) { return loc::MemRegionVal(MRMgr.getStringRegion(S)); } @@ -336,7 +415,7 @@ SVal RegionStoreManager::getLValueString(const GRState* St, /// getLValueVar - Returns an SVal that represents the lvalue of a /// variable. Within RegionStore a variable has an associated /// VarRegion, and the lvalue of the variable is the lvalue of that region. -SVal RegionStoreManager::getLValueVar(const GRState* St, const VarDecl* VD) { +SVal RegionStoreManager::getLValueVar(const GRState *St, const VarDecl* VD) { return loc::MemRegionVal(MRMgr.getVarRegion(VD)); } @@ -345,22 +424,22 @@ SVal RegionStoreManager::getLValueVar(const GRState* St, const VarDecl* VD) { /// has an associated region, and the lvalue of the compound literal /// is the lvalue of that region. SVal -RegionStoreManager::getLValueCompoundLiteral(const GRState* St, +RegionStoreManager::getLValueCompoundLiteral(const GRState *St, const CompoundLiteralExpr* CL) { return loc::MemRegionVal(MRMgr.getCompoundLiteralRegion(CL)); } -SVal RegionStoreManager::getLValueIvar(const GRState* St, const ObjCIvarDecl* D, +SVal RegionStoreManager::getLValueIvar(const GRState *St, const ObjCIvarDecl* D, SVal Base) { return getLValueFieldOrIvar(St, Base, D); } -SVal RegionStoreManager::getLValueField(const GRState* St, SVal Base, +SVal RegionStoreManager::getLValueField(const GRState *St, SVal Base, const FieldDecl* D) { return getLValueFieldOrIvar(St, Base, D); } -SVal RegionStoreManager::getLValueFieldOrIvar(const GRState* St, SVal Base, +SVal RegionStoreManager::getLValueFieldOrIvar(const GRState *St, SVal Base, const Decl* D) { if (Base.isUnknownOrUndef()) return Base; @@ -397,7 +476,7 @@ SVal RegionStoreManager::getLValueFieldOrIvar(const GRState* St, SVal Base, return loc::MemRegionVal(MRMgr.getFieldRegion(cast<FieldDecl>(D), BaseR)); } -SVal RegionStoreManager::getLValueElement(const GRState* St, +SVal RegionStoreManager::getLValueElement(const GRState *St, QualType elementType, SVal Base, SVal Offset) { @@ -438,7 +517,7 @@ SVal RegionStoreManager::getLValueElement(const GRState* St, } } return loc::MemRegionVal(MRMgr.getElementRegion(elementType, Offset, - BaseRegion)); + BaseRegion, getContext())); } SVal BaseIdx = ElemR->getIndex(); @@ -473,10 +552,15 @@ SVal RegionStoreManager::getLValueElement(const GRState* St, else NewIdx = nonloc::ConcreteInt(getBasicVals().getValue(BaseIdxI + OffI)); - return loc::MemRegionVal(MRMgr.getElementRegion(elementType, NewIdx, ArrayR)); + return loc::MemRegionVal(MRMgr.getElementRegion(elementType, NewIdx, ArrayR, + getContext())); } -SVal RegionStoreManager::getSizeInElements(const GRState* St, +//===----------------------------------------------------------------------===// +// Extents for regions. +//===----------------------------------------------------------------------===// + +SVal RegionStoreManager::getSizeInElements(const GRState *state, const MemRegion* R) { if (const VarRegion* VR = dyn_cast<VarRegion>(R)) { // Get the type of the variable. @@ -491,8 +575,7 @@ SVal RegionStoreManager::getSizeInElements(const GRState* St, return NonLoc::MakeVal(getBasicVals(), CAT->getSize(), false); } - GRStateRef state(St, StateMgr); - const QualType* CastTy = state.get<RegionCasts>(VR); + const QualType* CastTy = state->get<RegionCasts>(VR); // If the VarRegion is cast to other type, compute the size with respect to // that type. @@ -501,6 +584,7 @@ SVal RegionStoreManager::getSizeInElements(const GRState* St, QualType VarTy = VR->getValueType(getContext()); uint64_t EleSize = getContext().getTypeSize(EleTy); uint64_t VarSize = getContext().getTypeSize(VarTy); + assert(VarSize != 0); return NonLoc::MakeIntVal(getBasicVals(), VarSize / EleSize, false); } @@ -538,6 +622,16 @@ SVal RegionStoreManager::getSizeInElements(const GRState* St, return UnknownVal(); } +const GRState *RegionStoreManager::setExtent(const GRState *state, + const MemRegion *region, + SVal extent) { + return state->set<RegionExtents>(region, extent); +} + +//===----------------------------------------------------------------------===// +// Location and region casting. +//===----------------------------------------------------------------------===// + /// ArrayToPointer - Emulates the "decay" of an array to a pointer /// type. 'Array' represents the lvalue of the array being decayed /// to a pointer, and the returned SVal represents the decayed @@ -560,13 +654,13 @@ SVal RegionStoreManager::ArrayToPointer(Loc Array) { T = AT->getElementType(); nonloc::ConcreteInt Idx(getBasicVals().getZeroWithPtrWidth(false)); - ElementRegion* ER = MRMgr.getElementRegion(T, Idx, ArrayR); + ElementRegion* ER = MRMgr.getElementRegion(T, Idx, ArrayR, getContext()); return loc::MemRegionVal(ER); } RegionStoreManager::CastResult -RegionStoreManager::CastRegion(const GRState* state, const MemRegion* R, +RegionStoreManager::CastRegion(const GRState *state, const MemRegion* R, QualType CastToTy) { ASTContext& Ctx = StateMgr.getContext(); @@ -575,7 +669,7 @@ RegionStoreManager::CastRegion(const GRState* state, const MemRegion* R, QualType ToTy = Ctx.getCanonicalType(CastToTy); // Check cast to ObjCQualifiedID type. - if (isa<ObjCQualifiedIdType>(ToTy)) { + if (ToTy->isObjCQualifiedIdType()) { // FIXME: Record the type information aside. return CastResult(state, R); } @@ -617,15 +711,18 @@ RegionStoreManager::CastRegion(const GRState* state, const MemRegion* R, uint64_t ObjTySize = getContext().getTypeSize(ObjTy); if ((PointeeTySize > 0 && PointeeTySize < ObjTySize) || - (ObjTy->isAggregateType() && PointeeTy->isScalarType())) { + (ObjTy->isAggregateType() && PointeeTy->isScalarType()) || + ObjTySize == 0 /* R has 'void*' type. */) { // Record the cast type of the region. state = setCastType(state, R, ToTy); SVal Idx = ValMgr.makeZeroArrayIndex(); - ElementRegion* ER = MRMgr.getElementRegion(PointeeTy, Idx, R); + ElementRegion* ER = MRMgr.getElementRegion(PointeeTy, Idx,R,getContext()); return CastResult(state, ER); - } else + } else { + state = setCastType(state, R, ToTy); return CastResult(state, R); + } } if (isa<ObjCObjectRegion>(R)) { @@ -636,6 +733,10 @@ RegionStoreManager::CastRegion(const GRState* state, const MemRegion* R, return 0; } +//===----------------------------------------------------------------------===// +// Pointer arithmetic. +//===----------------------------------------------------------------------===// + SVal RegionStoreManager::EvalBinOp(const GRState *state, BinaryOperator::Opcode Op, Loc L, NonLoc R) { // Assume the base location is MemRegionVal. @@ -648,26 +749,37 @@ SVal RegionStoreManager::EvalBinOp(const GRState *state, // If the operand is a symbolic or alloca region, create the first element // region on it. if (const SymbolicRegion *SR = dyn_cast<SymbolicRegion>(MR)) { - // Get symbol's type. It should be a pointer type. - SymbolRef Sym = SR->getSymbol(); - QualType T = Sym->getType(getContext()); + QualType T; + // If the SymbolicRegion was cast to another type, use that type. + if (const QualType *t = state->get<RegionCasts>(SR)) { + T = *t; + } else { + // Otherwise use the symbol's type. + SymbolRef Sym = SR->getSymbol(); + T = Sym->getType(getContext()); + } QualType EleTy = T->getAsPointerType()->getPointeeType(); SVal ZeroIdx = ValMgr.makeZeroArrayIndex(); - ER = MRMgr.getElementRegion(EleTy, ZeroIdx, SR); + ER = MRMgr.getElementRegion(EleTy, ZeroIdx, SR, getContext()); } else if (const AllocaRegion *AR = dyn_cast<AllocaRegion>(MR)) { // Get the alloca region's current cast type. - GRStateRef StRef(state, StateMgr); - GRStateTrait<RegionCasts>::lookup_type T = StRef.get<RegionCasts>(AR); + + GRStateTrait<RegionCasts>::lookup_type T = state->get<RegionCasts>(AR); assert(T && "alloca region has no type."); QualType EleTy = cast<PointerType>(T->getTypePtr())->getPointeeType(); SVal ZeroIdx = ValMgr.makeZeroArrayIndex(); - ER = MRMgr.getElementRegion(EleTy, ZeroIdx, AR); + ER = MRMgr.getElementRegion(EleTy, ZeroIdx, AR, getContext()); } - else + else if (isa<FieldRegion>(MR)) { + // Not track pointer arithmetic on struct fields. + return UnknownVal(); + } + else { ER = cast<ElementRegion>(MR); + } SVal Idx = ER->getIndex(); @@ -686,7 +798,8 @@ SVal RegionStoreManager::EvalBinOp(const GRState *state, Offset->getValue())); SVal NewIdx = Base->EvalBinOp(getBasicVals(), Op, OffConverted); const MemRegion* NewER = - MRMgr.getElementRegion(ER->getElementType(), NewIdx,ER->getSuperRegion()); + MRMgr.getElementRegion(ER->getElementType(), NewIdx,ER->getSuperRegion(), + getContext()); return Loc::MakeVal(NewER); } @@ -694,7 +807,12 @@ SVal RegionStoreManager::EvalBinOp(const GRState *state, return UnknownVal(); } -SVal RegionStoreManager::Retrieve(const GRState* St, Loc L, QualType T) { +//===----------------------------------------------------------------------===// +// Loading values from regions. +//===----------------------------------------------------------------------===// + +SVal RegionStoreManager::Retrieve(const GRState *state, Loc L, QualType T) { + assert(!isa<UnknownVal>(L) && "location unknown"); assert(!isa<UndefinedVal>(L) && "location undefined"); @@ -703,7 +821,7 @@ SVal RegionStoreManager::Retrieve(const GRState* St, Loc L, QualType T) { if (isa<loc::ConcreteInt>(L)) return UndefinedVal(); - const MemRegion* MR = cast<loc::MemRegionVal>(L).getRegion(); + const MemRegion *MR = cast<loc::MemRegionVal>(L).getRegion(); // FIXME: return symbolic value for these cases. // Example: @@ -716,7 +834,7 @@ SVal RegionStoreManager::Retrieve(const GRState* St, Loc L, QualType T) { // FIXME: Perhaps this method should just take a 'const MemRegion*' argument // instead of 'Loc', and have the other Loc cases handled at a higher level. - const TypedRegion* R = cast<TypedRegion>(MR); + const TypedRegion *R = cast<TypedRegion>(MR); assert(R && "bad region"); // FIXME: We should eventually handle funny addressing. e.g.: @@ -731,26 +849,24 @@ SVal RegionStoreManager::Retrieve(const GRState* St, Loc L, QualType T) { QualType RTy = R->getValueType(getContext()); if (RTy->isStructureType()) - return RetrieveStruct(St, R); + return RetrieveStruct(state, R); if (RTy->isArrayType()) - return RetrieveArray(St, R); + return RetrieveArray(state, R); // FIXME: handle Vector types. if (RTy->isVectorType()) return UnknownVal(); - RegionBindingsTy B = GetRegionBindings(St->getStore()); + RegionBindingsTy B = GetRegionBindings(state->getStore()); RegionBindingsTy::data_type* V = B.lookup(R); // Check if the region has a binding. if (V) return *V; - GRStateRef state(St, StateMgr); - // Check if the region is in killset. - if (state.contains<RegionKills>(R)) + if (state->contains<RegionKills>(R)) return UnknownVal(); // Check if the region is an element region of a string literal. @@ -775,7 +891,7 @@ SVal RegionStoreManager::Retrieve(const GRState* St, Loc L, QualType T) { if (isa<ElementRegion>(R) || isa<FieldRegion>(R)) { const MemRegion* SuperR = cast<SubRegion>(R)->getSuperRegion(); GRStateTrait<RegionDefaultValue>::lookup_type D = - state.get<RegionDefaultValue>(SuperR); + state->get<RegionDefaultValue>(SuperR); if (D) { // If the default value is symbolic, we need to create a new symbol. if (D->hasConjuredSymbol()) @@ -829,14 +945,22 @@ SVal RegionStoreManager::Retrieve(const GRState* St, Loc L, QualType T) { return UndefinedVal(); } + // If the region is already cast to another type, use that type to create the + // symbol value. + if (const QualType *p = state->get<RegionCasts>(R)) { + QualType T = *p; + RTy = T->getAsPointerType()->getPointeeType(); + } + // All other integer values are symbolic. if (Loc::IsLocType(RTy) || RTy->isIntegerType()) - return ValMgr.getRegionValueSymbolVal(R); + return ValMgr.getRegionValueSymbolVal(R, RTy); else return UnknownVal(); } -SVal RegionStoreManager::RetrieveStruct(const GRState* St,const TypedRegion* R){ +SVal RegionStoreManager::RetrieveStruct(const GRState *state, + const TypedRegion* R){ QualType T = R->getValueType(getContext()); assert(T->isStructureType()); @@ -846,6 +970,8 @@ SVal RegionStoreManager::RetrieveStruct(const GRState* St,const TypedRegion* R){ llvm::ImmutableList<SVal> StructVal = getBasicVals().getEmptySValList(); + // FIXME: We shouldn't use a std::vector. If RecordDecl doesn't have a + // reverse iterator, we should implement one. std::vector<FieldDecl *> Fields(RD->field_begin(getContext()), RD->field_end(getContext())); @@ -854,14 +980,16 @@ SVal RegionStoreManager::RetrieveStruct(const GRState* St,const TypedRegion* R){ Field != FieldEnd; ++Field) { FieldRegion* FR = MRMgr.getFieldRegion(*Field, R); QualType FTy = (*Field)->getType(); - SVal FieldValue = Retrieve(St, loc::MemRegionVal(FR), FTy); + SVal FieldValue = Retrieve(state, loc::MemRegionVal(FR), FTy); StructVal = getBasicVals().consVals(FieldValue, StructVal); } return NonLoc::MakeCompoundVal(T, StructVal, getBasicVals()); } -SVal RegionStoreManager::RetrieveArray(const GRState* St, const TypedRegion* R){ +SVal RegionStoreManager::RetrieveArray(const GRState *state, + const TypedRegion * R) { + QualType T = R->getValueType(getContext()); ConstantArrayType* CAT = cast<ConstantArrayType>(T.getTypePtr()); @@ -871,41 +999,19 @@ SVal RegionStoreManager::RetrieveArray(const GRState* St, const TypedRegion* R){ for (; i < Size; ++i) { SVal Idx = NonLoc::MakeVal(getBasicVals(), i); - ElementRegion* ER = MRMgr.getElementRegion(CAT->getElementType(), Idx, R); + ElementRegion* ER = MRMgr.getElementRegion(CAT->getElementType(), Idx, R, + getContext()); QualType ETy = ER->getElementType(); - SVal ElementVal = Retrieve(St, loc::MemRegionVal(ER), ETy); + SVal ElementVal = Retrieve(state, loc::MemRegionVal(ER), ETy); ArrayVal = getBasicVals().consVals(ElementVal, ArrayVal); } return NonLoc::MakeCompoundVal(T, ArrayVal, getBasicVals()); } -const GRState* RegionStoreManager::Bind(const GRState* St, Loc L, SVal V) { - // If we get here, the location should be a region. - const MemRegion* R = cast<loc::MemRegionVal>(L).getRegion(); - assert(R); - - // Check if the region is a struct region. - if (const TypedRegion* TR = dyn_cast<TypedRegion>(R)) - if (TR->getValueType(getContext())->isStructureType()) - return BindStruct(St, TR, V); - - Store store = St->getStore(); - RegionBindingsTy B = GetRegionBindings(store); - - if (V.isUnknown()) { - // Remove the binding. - store = RBFactory.Remove(B, R).getRoot(); - - // Add the region to the killset. - GRStateRef state(St, StateMgr); - St = state.add<RegionKills>(R); - } - else - store = RBFactory.Add(B, R, V).getRoot(); - - return StateMgr.MakeStateWithStore(St, store); -} +//===----------------------------------------------------------------------===// +// Binding values to regions. +//===----------------------------------------------------------------------===// Store RegionStoreManager::Remove(Store store, Loc L) { const MemRegion* R = 0; @@ -921,34 +1027,235 @@ Store RegionStoreManager::Remove(Store store, Loc L) { return store; } -const GRState* RegionStoreManager::BindDecl(const GRState* St, +const GRState *RegionStoreManager::Bind(const GRState *state, Loc L, SVal V) { + // If we get here, the location should be a region. + const MemRegion* R = cast<loc::MemRegionVal>(L).getRegion(); + + // Check if the region is a struct region. + if (const TypedRegion* TR = dyn_cast<TypedRegion>(R)) + if (TR->getValueType(getContext())->isStructureType()) + return BindStruct(state, TR, V); + + RegionBindingsTy B = GetRegionBindings(state->getStore()); + + if (V.isUnknown()) { + B = RBFactory.Remove(B, R); // Remove the binding. + state = state->add<RegionKills>(R); // Add the region to the killset. + } + else + B = RBFactory.Add(B, R, V); + + return state->makeWithStore(B.getRoot()); +} + +const GRState *RegionStoreManager::BindDecl(const GRState *state, const VarDecl* VD, SVal InitVal) { QualType T = VD->getType(); VarRegion* VR = MRMgr.getVarRegion(VD); if (T->isArrayType()) - return BindArray(St, VR, InitVal); + return BindArray(state, VR, InitVal); if (T->isStructureType()) - return BindStruct(St, VR, InitVal); + return BindStruct(state, VR, InitVal); - return Bind(St, Loc::MakeVal(VR), InitVal); + return Bind(state, Loc::MakeVal(VR), InitVal); } // FIXME: this method should be merged into Bind(). -const GRState* -RegionStoreManager::BindCompoundLiteral(const GRState* St, - const CompoundLiteralExpr* CL, SVal V) { +const GRState * +RegionStoreManager::BindCompoundLiteral(const GRState *state, + const CompoundLiteralExpr* CL, + SVal V) { + CompoundLiteralRegion* R = MRMgr.getCompoundLiteralRegion(CL); - return Bind(St, loc::MemRegionVal(R), V); + return Bind(state, loc::MemRegionVal(R), V); } -const GRState* RegionStoreManager::setExtent(const GRState* St, - const MemRegion* R, SVal Extent) { - GRStateRef state(St, StateMgr); - return state.set<RegionExtents>(R, Extent); +const GRState *RegionStoreManager::BindArray(const GRState *state, + const TypedRegion* R, + SVal Init) { + + QualType T = R->getValueType(getContext()); + assert(T->isArrayType()); + + // When we are binding the whole array, it always has default value 0. + state = state->set<RegionDefaultValue>(R, NonLoc::MakeIntVal(getBasicVals(), + 0, false)); + + ConstantArrayType* CAT = cast<ConstantArrayType>(T.getTypePtr()); + + llvm::APSInt Size(CAT->getSize(), false); + llvm::APSInt i = getBasicVals().getValue(0, Size.getBitWidth(), + Size.isUnsigned()); + + // Check if the init expr is a StringLiteral. + if (isa<loc::MemRegionVal>(Init)) { + const MemRegion* InitR = cast<loc::MemRegionVal>(Init).getRegion(); + const StringLiteral* S = cast<StringRegion>(InitR)->getStringLiteral(); + const char* str = S->getStrData(); + unsigned len = S->getByteLength(); + unsigned j = 0; + + // Copy bytes from the string literal into the target array. Trailing bytes + // in the array that are not covered by the string literal are initialized + // to zero. + for (; i < Size; ++i, ++j) { + if (j >= len) + break; + + SVal Idx = NonLoc::MakeVal(getBasicVals(), i); + ElementRegion* ER = + MRMgr.getElementRegion(cast<ArrayType>(T)->getElementType(), + Idx, R, getContext()); + + SVal V = NonLoc::MakeVal(getBasicVals(), str[j], sizeof(char)*8, true); + state = Bind(state, loc::MemRegionVal(ER), V); + } + + return state; + } + + nonloc::CompoundVal& CV = cast<nonloc::CompoundVal>(Init); + nonloc::CompoundVal::iterator VI = CV.begin(), VE = CV.end(); + + for (; i < Size; ++i, ++VI) { + // The init list might be shorter than the array decl. + if (VI == VE) + break; + + SVal Idx = NonLoc::MakeVal(getBasicVals(), i); + ElementRegion* ER = + MRMgr.getElementRegion(cast<ArrayType>(T)->getElementType(), + Idx, R, getContext()); + + if (CAT->getElementType()->isStructureType()) + state = BindStruct(state, ER, *VI); + else + state = Bind(state, Loc::MakeVal(ER), *VI); + } + + return state; } +const GRState * +RegionStoreManager::BindStruct(const GRState *state, const TypedRegion* R, + SVal V) { + + if (!Features.supportsFields()) + return state; + + QualType T = R->getValueType(getContext()); + assert(T->isStructureType()); + + const RecordType* RT = T->getAsRecordType(); + RecordDecl* RD = RT->getDecl(); + + if (!RD->isDefinition()) + return state; + + // We may get non-CompoundVal accidentally due to imprecise cast logic. + // Ignore them and kill the field values. + if (V.isUnknown() || !isa<nonloc::CompoundVal>(V)) + return KillStruct(state, R); + + nonloc::CompoundVal& CV = cast<nonloc::CompoundVal>(V); + nonloc::CompoundVal::iterator VI = CV.begin(), VE = CV.end(); + + for (RecordDecl::field_iterator FI = RD->field_begin(getContext()), + FE = RD->field_end(getContext()); + FI != FE; ++FI, ++VI) { + + // There may be fewer values than fields only when we are initializing a + // struct decl. In this case, mark the region as having default value. + if (VI == VE) { + const NonLoc& Idx = NonLoc::MakeIntVal(getBasicVals(), 0, false); + state = state->set<RegionDefaultValue>(R, Idx); + break; + } + + QualType FTy = (*FI)->getType(); + FieldRegion* FR = MRMgr.getFieldRegion(*FI, R); + + if (Loc::IsLocType(FTy) || FTy->isIntegerType()) + state = Bind(state, Loc::MakeVal(FR), *VI); + else if (FTy->isArrayType()) + state = BindArray(state, FR, *VI); + else if (FTy->isStructureType()) + state = BindStruct(state, FR, *VI); + } + + return state; +} + +const GRState *RegionStoreManager::KillStruct(const GRState *state, + const TypedRegion* R){ + + // (1) Kill the struct region because it is assigned "unknown". + // (2) Set the default value of the struct region to "unknown". + state = state->add<RegionKills>(R)->set<RegionDefaultValue>(R, UnknownVal()); + Store store = state->getStore(); + RegionBindingsTy B = GetRegionBindings(store); + + // Remove all bindings for the subregions of the struct. + for (RegionBindingsTy::iterator I = B.begin(), E = B.end(); I != E; ++I) { + const MemRegion* R = I.getKey(); + if (const SubRegion* subRegion = dyn_cast<SubRegion>(R)) + if (subRegion->isSubRegionOf(R)) + store = Remove(store, Loc::MakeVal(subRegion)); + // FIXME: Maybe we should also remove the bindings for the "views" of the + // subregions. + } + + return state->makeWithStore(store); +} + +//===----------------------------------------------------------------------===// +// Region views. +//===----------------------------------------------------------------------===// + +const GRState *RegionStoreManager::AddRegionView(const GRState *state, + const MemRegion* View, + const MemRegion* Base) { + + // First, retrieve the region view of the base region. + const RegionViews* d = state->get<RegionViewMap>(Base); + RegionViews L = d ? *d : RVFactory.GetEmptySet(); + + // Now add View to the region view. + L = RVFactory.Add(L, View); + + // Create a new state with the new region view. + return state->set<RegionViewMap>(Base, L); +} + +const GRState *RegionStoreManager::RemoveRegionView(const GRState *state, + const MemRegion* View, + const MemRegion* Base) { + // Retrieve the region view of the base region. + const RegionViews* d = state->get<RegionViewMap>(Base); + + // If the base region has no view, return. + if (!d) + return state; + + // Remove the view. + return state->set<RegionViewMap>(Base, RVFactory.Remove(*d, View)); +} + +const GRState *RegionStoreManager::setCastType(const GRState *state, + const MemRegion* R, QualType T) { + return state->set<RegionCasts>(R, T); +} + +const GRState *RegionStoreManager::setDefaultValue(const GRState *state, + const MemRegion* R, SVal V) { + return state->set<RegionDefaultValue>(R, V); +} + +//===----------------------------------------------------------------------===// +// State pruning. +//===----------------------------------------------------------------------===// static void UpdateLiveSymbols(SVal X, SymbolReaper& SymReaper) { if (loc::MemRegionVal *XR = dyn_cast<loc::MemRegionVal>(&X)) { @@ -975,11 +1282,10 @@ static void UpdateLiveSymbols(SVal X, SymbolReaper& SymReaper) { SymReaper.markLive(*SI); } -Store RegionStoreManager::RemoveDeadBindings(const GRState* state, Stmt* Loc, +Store RegionStoreManager::RemoveDeadBindings(const GRState *state, Stmt* Loc, SymbolReaper& SymReaper, llvm::SmallVectorImpl<const MemRegion*>& RegionRoots) -{ - +{ Store store = state->getStore(); RegionBindingsTy B = GetRegionBindings(store); @@ -1002,18 +1308,17 @@ Store RegionStoreManager::RemoveDeadBindings(const GRState* state, Stmt* Loc, // Do a pass over the regions in the store. For VarRegions we check if // the variable is still live and if so add it to the list of live roots. - // For other regions we populate our region backmap. - + // For other regions we populate our region backmap. llvm::SmallVector<const MemRegion*, 10> IntermediateRoots; - + for (RegionBindingsTy::iterator I = B.begin(), E = B.end(); I != E; ++I) { IntermediateRoots.push_back(I.getKey()); } - + while (!IntermediateRoots.empty()) { const MemRegion* R = IntermediateRoots.back(); IntermediateRoots.pop_back(); - + if (const VarRegion* VR = dyn_cast<VarRegion>(R)) { if (SymReaper.isLive(Loc, VR->getDecl())) RegionRoots.push_back(VR); // This is a live "root". @@ -1025,14 +1330,14 @@ Store RegionStoreManager::RemoveDeadBindings(const GRState* state, Stmt* Loc, else { // Get the super region for R. const MemRegion* SuperR = cast<SubRegion>(R)->getSuperRegion(); - + // Get the current set of subregions for SuperR. const SubRegionsTy* SRptr = SubRegMap.lookup(SuperR); SubRegionsTy SRs = SRptr ? *SRptr : SubRegF.GetEmptySet(); - + // Add R to the subregions of SuperR. SubRegMap = SubRegMapF.Add(SubRegMap, SuperR, SubRegF.Add(SRs, R)); - + // Super region may be VarRegion or subregion of another VarRegion. Add it // to the work list. if (isa<SubRegion>(SuperR)) @@ -1048,10 +1353,10 @@ Store RegionStoreManager::RemoveDeadBindings(const GRState* state, Stmt* Loc, // Dequeue the next region on the worklist. const MemRegion* R = RegionRoots.back(); RegionRoots.pop_back(); - + // Check if we have already processed this region. if (Marked.count(R)) continue; - + // Mark this region as processed. This is needed for termination in case // a region is referenced more than once. Marked.insert(R); @@ -1060,13 +1365,13 @@ Store RegionStoreManager::RemoveDeadBindings(const GRState* state, Stmt* Loc, // should continue to track that symbol. if (const SymbolicRegion* SymR = dyn_cast<SymbolicRegion>(R)) SymReaper.markLive(SymR->getSymbol()); - + // Get the data binding for R (if any). RegionBindingsTy::data_type* Xptr = B.lookup(R); if (Xptr) { SVal X = *Xptr; UpdateLiveSymbols(X, SymReaper); // Update the set of live symbols. - + // If X is a region, then add it the RegionRoots. if (loc::MemRegionVal* RegionX = dyn_cast<loc::MemRegionVal>(&X)) RegionRoots.push_back(RegionX->getRegion()); @@ -1094,11 +1399,11 @@ Store RegionStoreManager::RemoveDeadBindings(const GRState* state, Stmt* Loc, // Remove this dead region from the store. store = Remove(store, Loc::MakeVal(R)); - + // Mark all non-live symbols that this region references as dead. if (const SymbolicRegion* SymR = dyn_cast<SymbolicRegion>(R)) SymReaper.maybeDead(SymR->getSymbol()); - + SVal X = I.getData(); SVal::symbol_iterator SI = X.symbol_begin(), SE = X.symbol_end(); for (; SI != SE; ++SI) SymReaper.maybeDead(*SI); @@ -1107,203 +1412,18 @@ Store RegionStoreManager::RemoveDeadBindings(const GRState* state, Stmt* Loc, return store; } +//===----------------------------------------------------------------------===// +// Utility methods. +//===----------------------------------------------------------------------===// + void RegionStoreManager::print(Store store, std::ostream& Out, const char* nl, const char *sep) { llvm::raw_os_ostream OS(Out); RegionBindingsTy B = GetRegionBindings(store); OS << "Store:" << nl; - + for (RegionBindingsTy::iterator I = B.begin(), E = B.end(); I != E; ++I) { OS << ' '; I.getKey()->print(OS); OS << " : "; I.getData().print(OS); OS << nl; } } - -const GRState* RegionStoreManager::BindArray(const GRState* St, - const TypedRegion* R, SVal Init) { - QualType T = R->getValueType(getContext()); - assert(T->isArrayType()); - - // When we are binding the whole array, it always has default value 0. - GRStateRef state(St, StateMgr); - St = state.set<RegionDefaultValue>(R, NonLoc::MakeIntVal(getBasicVals(), 0, - false)); - - ConstantArrayType* CAT = cast<ConstantArrayType>(T.getTypePtr()); - - llvm::APSInt Size(CAT->getSize(), false); - llvm::APSInt i = getBasicVals().getValue(0, Size.getBitWidth(), - Size.isUnsigned()); - - // Check if the init expr is a StringLiteral. - if (isa<loc::MemRegionVal>(Init)) { - const MemRegion* InitR = cast<loc::MemRegionVal>(Init).getRegion(); - const StringLiteral* S = cast<StringRegion>(InitR)->getStringLiteral(); - const char* str = S->getStrData(); - unsigned len = S->getByteLength(); - unsigned j = 0; - - // Copy bytes from the string literal into the target array. Trailing bytes - // in the array that are not covered by the string literal are initialized - // to zero. - for (; i < Size; ++i, ++j) { - if (j >= len) - break; - - SVal Idx = NonLoc::MakeVal(getBasicVals(), i); - ElementRegion* ER = - MRMgr.getElementRegion(cast<ArrayType>(T)->getElementType(), - Idx, R); - - SVal V = NonLoc::MakeVal(getBasicVals(), str[j], sizeof(char)*8, true); - St = Bind(St, loc::MemRegionVal(ER), V); - } - - return St; - } - - nonloc::CompoundVal& CV = cast<nonloc::CompoundVal>(Init); - nonloc::CompoundVal::iterator VI = CV.begin(), VE = CV.end(); - - for (; i < Size; ++i, ++VI) { - // The init list might be shorter than the array decl. - if (VI == VE) - break; - - SVal Idx = NonLoc::MakeVal(getBasicVals(), i); - ElementRegion* ER = - MRMgr.getElementRegion(cast<ArrayType>(T)->getElementType(), - Idx, R); - - if (CAT->getElementType()->isStructureType()) - St = BindStruct(St, ER, *VI); - else - St = Bind(St, Loc::MakeVal(ER), *VI); - } - - return St; -} - -const GRState* -RegionStoreManager::BindStruct(const GRState* St, const TypedRegion* R, SVal V){ - QualType T = R->getValueType(getContext()); - assert(T->isStructureType()); - - const RecordType* RT = T->getAsRecordType(); - RecordDecl* RD = RT->getDecl(); - - if (!RD->isDefinition()) - return St; - - if (V.isUnknown()) - return KillStruct(St, R); - - // We may get non-CompoundVal accidentally due to imprecise cast logic. Ignore - // them and make struct unknown. - if (!isa<nonloc::CompoundVal>(V)) - return KillStruct(St, R); - - nonloc::CompoundVal& CV = cast<nonloc::CompoundVal>(V); - nonloc::CompoundVal::iterator VI = CV.begin(), VE = CV.end(); - RecordDecl::field_iterator FI = RD->field_begin(getContext()), - FE = RD->field_end(getContext()); - - for (; FI != FE; ++FI, ++VI) { - - // There may be fewer values than fields only when we are initializing a - // struct decl. In this case, mark the region as having default value. - if (VI == VE) { - GRStateRef state(St, StateMgr); - const NonLoc& Idx = NonLoc::MakeIntVal(getBasicVals(), 0, false); - St = state.set<RegionDefaultValue>(R, Idx); - break; - } - - QualType FTy = (*FI)->getType(); - FieldRegion* FR = MRMgr.getFieldRegion(*FI, R); - - if (Loc::IsLocType(FTy) || FTy->isIntegerType()) - St = Bind(St, Loc::MakeVal(FR), *VI); - - else if (FTy->isArrayType()) - St = BindArray(St, FR, *VI); - - else if (FTy->isStructureType()) - St = BindStruct(St, FR, *VI); - } - - return St; -} - -const GRState* RegionStoreManager::KillStruct(const GRState* St, - const TypedRegion* R){ - GRStateRef state(St, StateMgr); - - // Kill the struct region because it is assigned "unknown". - St = state.add<RegionKills>(R); - - // Set the default value of the struct region to "unknown". - St = state.set<RegionDefaultValue>(R, UnknownVal()); - - Store store = St->getStore(); - RegionBindingsTy B = GetRegionBindings(store); - - // Remove all bindings for the subregions of the struct. - for (RegionBindingsTy::iterator I = B.begin(), E = B.end(); I != E; ++I) { - const MemRegion* r = I.getKey(); - if (const SubRegion* sr = dyn_cast<SubRegion>(r)) - if (sr->isSubRegionOf(R)) - store = Remove(store, Loc::MakeVal(sr)); - // FIXME: Maybe we should also remove the bindings for the "views" of the - // subregions. - } - - return StateMgr.MakeStateWithStore(St, store); -} - -const GRState* RegionStoreManager::AddRegionView(const GRState* St, - const MemRegion* View, - const MemRegion* Base) { - GRStateRef state(St, StateMgr); - - // First, retrieve the region view of the base region. - const RegionViews* d = state.get<RegionViewMap>(Base); - RegionViews L = d ? *d : RVFactory.GetEmptySet(); - - // Now add View to the region view. - L = RVFactory.Add(L, View); - - // Create a new state with the new region view. - return state.set<RegionViewMap>(Base, L); -} - -const GRState* RegionStoreManager::RemoveRegionView(const GRState* St, - const MemRegion* View, - const MemRegion* Base) { - GRStateRef state(St, StateMgr); - - // Retrieve the region view of the base region. - const RegionViews* d = state.get<RegionViewMap>(Base); - - // If the base region has no view, return. - if (!d) - return St; - - // Remove the view. - RegionViews V = *d; - V = RVFactory.Remove(V, View); - - return state.set<RegionViewMap>(Base, V); -} - -const GRState* RegionStoreManager::setCastType(const GRState* St, - const MemRegion* R, QualType T) { - GRStateRef state(St, StateMgr); - return state.set<RegionCasts>(R, T); -} - -const GRState* RegionStoreManager::setDefaultValue(const GRState* St, - const MemRegion* R, SVal V) { - GRStateRef state(St, StateMgr); - return state.set<RegionDefaultValue>(R, V); -} diff --git a/lib/Analysis/SVals.cpp b/lib/Analysis/SVals.cpp index e19b168..77c3c8f 100644 --- a/lib/Analysis/SVals.cpp +++ b/lib/Analysis/SVals.cpp @@ -294,7 +294,7 @@ NonLoc NonLoc::MakeVal(BasicValueFactory& BasicVals, uint64_t X, QualType T) { return nonloc::ConcreteInt(BasicVals.getValue(X, T)); } -NonLoc NonLoc::MakeVal(BasicValueFactory& BasicVals, IntegerLiteral* I) { +NonLoc NonLoc::MakeVal(BasicValueFactory& BasicVals, const IntegerLiteral* I) { return nonloc::ConcreteInt(BasicVals.getValue(APSInt(I->getValue(), I->getType()->isUnsignedIntegerType()))); @@ -322,11 +322,12 @@ NonLoc NonLoc::MakeCompoundVal(QualType T, llvm::ImmutableList<SVal> Vals, return nonloc::CompoundVal(BasicVals.getCompoundValData(T, Vals)); } -SVal ValueManager::getRegionValueSymbolVal(const MemRegion* R) { - SymbolRef sym = SymMgr.getRegionValueSymbol(R); +SVal ValueManager::getRegionValueSymbolVal(const MemRegion* R, QualType T) { + SymbolRef sym = SymMgr.getRegionValueSymbol(R, T); if (const TypedRegion* TR = dyn_cast<TypedRegion>(R)) { - QualType T = TR->getValueType(SymMgr.getContext()); + if (T.isNull()) + T = TR->getValueType(SymMgr.getContext()); // If T is of function pointer type, create a CodeTextRegion wrapping a // symbol. @@ -401,7 +402,9 @@ nonloc::LocAsInteger nonloc::LocAsInteger::Make(BasicValueFactory& Vals, Loc V, Loc Loc::MakeVal(const MemRegion* R) { return loc::MemRegionVal(R); } -Loc Loc::MakeVal(AddrLabelExpr* E) { return loc::GotoLabel(E->getLabel()); } +Loc Loc::MakeVal(const AddrLabelExpr *E) { + return loc::GotoLabel(E->getLabel()); +} Loc Loc::MakeNull(BasicValueFactory &BasicVals) { return loc::ConcreteInt(BasicVals.getZeroWithPtrWidth()); diff --git a/lib/Analysis/SimpleConstraintManager.cpp b/lib/Analysis/SimpleConstraintManager.cpp index f79dba0..82801eb 100644 --- a/lib/Analysis/SimpleConstraintManager.cpp +++ b/lib/Analysis/SimpleConstraintManager.cpp @@ -55,60 +55,55 @@ bool SimpleConstraintManager::canReasonAbout(SVal X) const { return true; } -const GRState* -SimpleConstraintManager::Assume(const GRState* St, SVal Cond, bool Assumption, - bool& isFeasible) { +const GRState *SimpleConstraintManager::Assume(const GRState *state, + SVal Cond, bool Assumption) { if (Cond.isUnknown()) { - isFeasible = true; - return St; + return state; } if (isa<NonLoc>(Cond)) - return Assume(St, cast<NonLoc>(Cond), Assumption, isFeasible); + return Assume(state, cast<NonLoc>(Cond), Assumption); else - return Assume(St, cast<Loc>(Cond), Assumption, isFeasible); + return Assume(state, cast<Loc>(Cond), Assumption); } -const GRState* -SimpleConstraintManager::Assume(const GRState* St, Loc Cond, bool Assumption, - bool& isFeasible) { - St = AssumeAux(St, Cond, Assumption, isFeasible); - - if (!isFeasible) - return St; - +const GRState *SimpleConstraintManager::Assume(const GRState *state, Loc Cond, + bool Assumption) { + + state = AssumeAux(state, Cond, Assumption); + // EvalAssume is used to call into the GRTransferFunction object to perform // any checker-specific update of the state based on this assumption being - // true or false. - return StateMgr.getTransferFuncs().EvalAssume(StateMgr, St, Cond, Assumption, - isFeasible); + // true or false. + return state ? state->getTransferFuncs().EvalAssume(state, Cond, Assumption) + : NULL; } -const GRState* -SimpleConstraintManager::AssumeAux(const GRState* St, Loc Cond, bool Assumption, - bool& isFeasible) { - BasicValueFactory& BasicVals = StateMgr.getBasicVals(); +const GRState *SimpleConstraintManager::AssumeAux(const GRState *state, + Loc Cond, bool Assumption) { + + BasicValueFactory &BasicVals = state->getBasicVals(); switch (Cond.getSubKind()) { default: assert (false && "'Assume' not implemented for this Loc."); - return St; + return state; case loc::MemRegionKind: { // FIXME: Should this go into the storemanager? - const MemRegion* R = cast<loc::MemRegionVal>(Cond).getRegion(); - const SubRegion* SubR = dyn_cast<SubRegion>(R); + const MemRegion *R = cast<loc::MemRegionVal>(Cond).getRegion(); + const SubRegion *SubR = dyn_cast<SubRegion>(R); while (SubR) { // FIXME: now we only find the first symbolic region. - if (const SymbolicRegion* SymR = dyn_cast<SymbolicRegion>(SubR)) { + if (const SymbolicRegion *SymR = dyn_cast<SymbolicRegion>(SubR)) { if (Assumption) - return AssumeSymNE(St, SymR->getSymbol(), - BasicVals.getZeroWithPtrWidth(), isFeasible); + return AssumeSymNE(state, SymR->getSymbol(), + BasicVals.getZeroWithPtrWidth()); else - return AssumeSymEQ(St, SymR->getSymbol(), - BasicVals.getZeroWithPtrWidth(), isFeasible); + return AssumeSymEQ(state, SymR->getSymbol(), + BasicVals.getZeroWithPtrWidth()); } SubR = dyn_cast<SubRegion>(SubR->getSuperRegion()); } @@ -117,43 +112,42 @@ SimpleConstraintManager::AssumeAux(const GRState* St, Loc Cond, bool Assumption, } case loc::GotoLabelKind: - isFeasible = Assumption; - return St; + return Assumption ? state : NULL; case loc::ConcreteIntKind: { - bool b = cast<loc::ConcreteInt>(Cond).getValue() != 0; - isFeasible = b ? Assumption : !Assumption; - return St; + bool b = cast<loc::ConcreteInt>(Cond).getValue() != 0; + bool isFeasible = b ? Assumption : !Assumption; + return isFeasible ? state : NULL; } } // end switch } -const GRState* -SimpleConstraintManager::Assume(const GRState* St, NonLoc Cond, bool Assumption, - bool& isFeasible) { - St = AssumeAux(St, Cond, Assumption, isFeasible); - - if (!isFeasible) - return St; - +const GRState *SimpleConstraintManager::Assume(const GRState *state, + NonLoc Cond, + bool Assumption) { + + state = AssumeAux(state, Cond, Assumption); + // EvalAssume is used to call into the GRTransferFunction object to perform // any checker-specific update of the state based on this assumption being - // true or false. - return StateMgr.getTransferFuncs().EvalAssume(StateMgr, St, Cond, Assumption, - isFeasible); + // true or false. + return state ? state->getTransferFuncs().EvalAssume(state, Cond, Assumption) + : NULL; } -const GRState* -SimpleConstraintManager::AssumeAux(const GRState* St,NonLoc Cond, - bool Assumption, bool& isFeasible) { +const GRState *SimpleConstraintManager::AssumeAux(const GRState *state, + NonLoc Cond, + bool Assumption) { + // We cannot reason about SymIntExpr and SymSymExpr. if (!canReasonAbout(Cond)) { - isFeasible = true; - return St; + // Just return the current state indicating that the path is feasible. + // This may be an over-approximation of what is possible. + return state; } - BasicValueFactory& BasicVals = StateMgr.getBasicVals(); - SymbolManager& SymMgr = StateMgr.getSymbolManager(); + BasicValueFactory &BasicVals = state->getBasicVals(); + SymbolManager &SymMgr = state->getSymbolManager(); switch (Cond.getSubKind()) { default: @@ -162,38 +156,38 @@ SimpleConstraintManager::AssumeAux(const GRState* St,NonLoc Cond, case nonloc::SymbolValKind: { nonloc::SymbolVal& SV = cast<nonloc::SymbolVal>(Cond); SymbolRef sym = SV.getSymbol(); - QualType T = SymMgr.getType(sym); - - if (Assumption) - return AssumeSymNE(St, sym, BasicVals.getValue(0, T), isFeasible); - else - return AssumeSymEQ(St, sym, BasicVals.getValue(0, T), isFeasible); + QualType T = SymMgr.getType(sym); + const llvm::APSInt &zero = BasicVals.getValue(0, T); + + return Assumption ? AssumeSymNE(state, sym, zero) + : AssumeSymEQ(state, sym, zero); } 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); + return AssumeSymInt(state, Assumption, SE); - isFeasible = true; - return St; + // For all other symbolic expressions, over-approximate and consider + // the constraint feasible. + return state; } case nonloc::ConcreteIntKind: { bool b = cast<nonloc::ConcreteInt>(Cond).getValue() != 0; - isFeasible = b ? Assumption : !Assumption; - return St; + bool isFeasible = b ? Assumption : !Assumption; + return isFeasible ? state : NULL; } case nonloc::LocAsIntegerKind: - return AssumeAux(St, cast<nonloc::LocAsInteger>(Cond).getLoc(), - Assumption, isFeasible); + return AssumeAux(state, cast<nonloc::LocAsInteger>(Cond).getLoc(), + Assumption); } // end switch } -const GRState* -SimpleConstraintManager::AssumeSymInt(const GRState* St, bool Assumption, - const SymIntExpr *SE, bool& isFeasible) { +const GRState *SimpleConstraintManager::AssumeSymInt(const GRState *state, + bool Assumption, + const SymIntExpr *SE) { // Here we assume that LHS is a symbol. This is consistent with the @@ -203,47 +197,44 @@ SimpleConstraintManager::AssumeSymInt(const GRState* St, bool Assumption, switch (SE->getOpcode()) { default: - // No logic yet for other operators. - isFeasible = true; - return St; + // No logic yet for other operators. Assume the constraint is feasible. + return state; case BinaryOperator::EQ: - return Assumption ? AssumeSymEQ(St, Sym, Int, isFeasible) - : AssumeSymNE(St, Sym, Int, isFeasible); + return Assumption ? AssumeSymEQ(state, Sym, Int) + : AssumeSymNE(state, Sym, Int); case BinaryOperator::NE: - return Assumption ? AssumeSymNE(St, Sym, Int, isFeasible) - : AssumeSymEQ(St, Sym, Int, isFeasible); - + return Assumption ? AssumeSymNE(state, Sym, Int) + : AssumeSymEQ(state, Sym, Int); case BinaryOperator::GT: - return Assumption ? AssumeSymGT(St, Sym, Int, isFeasible) - : AssumeSymLE(St, Sym, Int, isFeasible); + return Assumption ? AssumeSymGT(state, Sym, Int) + : AssumeSymLE(state, Sym, Int); case BinaryOperator::GE: - return Assumption ? AssumeSymGE(St, Sym, Int, isFeasible) - : AssumeSymLT(St, Sym, Int, isFeasible); + return Assumption ? AssumeSymGE(state, Sym, Int) + : AssumeSymLT(state, Sym, Int); case BinaryOperator::LT: - return Assumption ? AssumeSymLT(St, Sym, Int, isFeasible) - : AssumeSymGE(St, Sym, Int, isFeasible); + return Assumption ? AssumeSymLT(state, Sym, Int) + : AssumeSymGE(state, Sym, Int); case BinaryOperator::LE: - return Assumption ? AssumeSymLE(St, Sym, Int, isFeasible) - : AssumeSymGT(St, Sym, Int, isFeasible); + return Assumption ? AssumeSymLE(state, Sym, Int) + : AssumeSymGT(state, Sym, Int); } // end switch } -const GRState* -SimpleConstraintManager::AssumeInBound(const GRState* St, SVal Idx, - SVal UpperBound, bool Assumption, - bool& isFeasible) { +const GRState *SimpleConstraintManager::AssumeInBound(const GRState *state, + SVal Idx, + SVal UpperBound, + bool Assumption) { + // Only support ConcreteInt for now. - if (!(isa<nonloc::ConcreteInt>(Idx) && isa<nonloc::ConcreteInt>(UpperBound))){ - isFeasible = true; - return St; - } + if (!(isa<nonloc::ConcreteInt>(Idx) && isa<nonloc::ConcreteInt>(UpperBound))) + return state; - const llvm::APSInt& Zero = getBasicVals().getZeroWithPtrWidth(false); + const llvm::APSInt& Zero = state->getBasicVals().getZeroWithPtrWidth(false); llvm::APSInt IdxV = cast<nonloc::ConcreteInt>(Idx).getValue(); // IdxV might be too narrow. if (IdxV.getBitWidth() < Zero.getBitWidth()) @@ -254,10 +245,8 @@ SimpleConstraintManager::AssumeInBound(const GRState* St, SVal Idx, UBV.extend(Zero.getBitWidth()); bool InBound = (Zero <= IdxV) && (IdxV < UBV); - - isFeasible = Assumption ? InBound : !InBound; - - return St; + bool isFeasible = Assumption ? InBound : !InBound; + return isFeasible ? state : NULL; } } // end of namespace clang diff --git a/lib/Analysis/SimpleConstraintManager.h b/lib/Analysis/SimpleConstraintManager.h index fb41e2f..1e1a10d 100644 --- a/lib/Analysis/SimpleConstraintManager.h +++ b/lib/Analysis/SimpleConstraintManager.h @@ -20,63 +20,59 @@ namespace clang { class SimpleConstraintManager : public ConstraintManager { -protected: - GRStateManager& StateMgr; public: - SimpleConstraintManager(GRStateManager& statemgr) - : StateMgr(statemgr) {} - virtual ~SimpleConstraintManager(); - - bool canReasonAbout(SVal X) const; + SimpleConstraintManager() {} + virtual ~SimpleConstraintManager(); - virtual const GRState* Assume(const GRState* St, SVal Cond, bool Assumption, - bool& isFeasible); - - const GRState* Assume(const GRState* St, Loc Cond, bool Assumption, - bool& isFeasible); + //===------------------------------------------------------------------===// + // Common implementation for the interface provided by ConstraintManager. + //===------------------------------------------------------------------===// - const GRState* AssumeAux(const GRState* St, Loc Cond,bool Assumption, - bool& isFeasible); - - const GRState* Assume(const GRState* St, NonLoc Cond, bool Assumption, - bool& isFeasible); - - const GRState* AssumeAux(const GRState* St, NonLoc Cond, bool Assumption, - bool& isFeasible); + bool canReasonAbout(SVal X) const; - const GRState* AssumeSymInt(const GRState* St, bool Assumption, - const SymIntExpr *SE, bool& isFeasible); + const GRState *Assume(const GRState *state, SVal Cond, bool Assumption); - virtual const GRState* AssumeSymNE(const GRState* St, SymbolRef sym, - const llvm::APSInt& V, - bool& isFeasible) = 0; + const GRState *Assume(const GRState *state, Loc Cond, bool Assumption); - virtual const GRState* AssumeSymEQ(const GRState* St, SymbolRef sym, - const llvm::APSInt& V, - bool& isFeasible) = 0; + const GRState *Assume(const GRState *state, NonLoc Cond, bool Assumption); - virtual const GRState* AssumeSymLT(const GRState* St, SymbolRef sym, - const llvm::APSInt& V, - bool& isFeasible) = 0; + const GRState *AssumeSymInt(const GRState *state, bool Assumption, + const SymIntExpr *SE); + + const GRState *AssumeInBound(const GRState *state, SVal Idx, SVal UpperBound, + bool Assumption); + +protected: + + //===------------------------------------------------------------------===// + // Interface that subclasses must implement. + //===------------------------------------------------------------------===// + + virtual const GRState *AssumeSymNE(const GRState *state, SymbolRef sym, + const llvm::APSInt& V) = 0; - virtual const GRState* AssumeSymGT(const GRState* St, SymbolRef sym, - const llvm::APSInt& V, - bool& isFeasible) = 0; + virtual const GRState *AssumeSymEQ(const GRState *state, SymbolRef sym, + const llvm::APSInt& V) = 0; - virtual const GRState* AssumeSymLE(const GRState* St, SymbolRef sym, - const llvm::APSInt& V, - bool& isFeasible) = 0; + virtual const GRState *AssumeSymLT(const GRState *state, SymbolRef sym, + const llvm::APSInt& V) = 0; - virtual const GRState* AssumeSymGE(const GRState* St, SymbolRef sym, - const llvm::APSInt& V, - bool& isFeasible) = 0; + virtual const GRState *AssumeSymGT(const GRState *state, SymbolRef sym, + const llvm::APSInt& V) = 0; - const GRState* AssumeInBound(const GRState* St, SVal Idx, SVal UpperBound, - bool Assumption, bool& isFeasible); + virtual const GRState *AssumeSymLE(const GRState *state, SymbolRef sym, + const llvm::APSInt& V) = 0; -private: - BasicValueFactory& getBasicVals() { return StateMgr.getBasicVals(); } - SymbolManager& getSymbolManager() const { return StateMgr.getSymbolManager(); } + virtual const GRState *AssumeSymGE(const GRState *state, SymbolRef sym, + const llvm::APSInt& V) = 0; + + //===------------------------------------------------------------------===// + // Internal implementation. + //===------------------------------------------------------------------===// + + const GRState *AssumeAux(const GRState *state, Loc Cond,bool Assumption); + + const GRState *AssumeAux(const GRState *state, NonLoc Cond, bool Assumption); }; } // end clang namespace diff --git a/lib/Analysis/Store.cpp b/lib/Analysis/Store.cpp index 13326ab..5aa756e 100644 --- a/lib/Analysis/Store.cpp +++ b/lib/Analysis/Store.cpp @@ -90,7 +90,8 @@ StoreManager::CastRegion(const GRState* state, const MemRegion* R, // FIXME: Is this the right thing to do in all cases? const TypedRegion *Base = isa<ElementRegion>(TR) ? cast<TypedRegion>(TR->getSuperRegion()) : TR; - ElementRegion* ER = MRMgr.getElementRegion(Pointee, Idx, Base); + ElementRegion* ER = MRMgr.getElementRegion(Pointee, Idx, Base, + StateMgr.getContext()); return CastResult(state, ER); } } diff --git a/lib/Analysis/SymbolManager.cpp b/lib/Analysis/SymbolManager.cpp index 5c885cd..4e38a34 100644 --- a/lib/Analysis/SymbolManager.cpp +++ b/lib/Analysis/SymbolManager.cpp @@ -92,14 +92,14 @@ std::ostream& std::operator<<(std::ostream& os, const SymExpr *SE) { } const SymbolRegionValue* -SymbolManager::getRegionValueSymbol(const MemRegion* R) { +SymbolManager::getRegionValueSymbol(const MemRegion* R, QualType T) { llvm::FoldingSetNodeID profile; - SymbolRegionValue::Profile(profile, R); + SymbolRegionValue::Profile(profile, R, T); void* InsertPos; SymExpr *SD = DataSet.FindNodeOrInsertPos(profile, InsertPos); if (!SD) { SD = (SymExpr*) BPAlloc.Allocate<SymbolRegionValue>(); - new (SD) SymbolRegionValue(SymbolCounter, R); + new (SD) SymbolRegionValue(SymbolCounter, R, T); DataSet.InsertNode(SD, InsertPos); ++SymbolCounter; } @@ -166,6 +166,9 @@ QualType SymbolConjured::getType(ASTContext&) const { } QualType SymbolRegionValue::getType(ASTContext& C) const { + if (!T.isNull()) + return T; + if (const TypedRegion* TR = dyn_cast<TypedRegion>(R)) return TR->getValueType(C); |