From bf26368255d282aec6f5675152b03b1ff24d9ef7 Mon Sep 17 00:00:00 2001 From: Ted Kremenek Date: Mon, 27 Oct 2008 21:54:31 +0000 Subject: [PATCH] Added preliminary support for CompoundLiterals in the static analyzer: - GRExprEngine::VisitCompoundLiteral... (1) visits the initializer list (generating ExplodedNodes) (2) creates a CompoundMemRegion for the literal (3) creates a new state with the bound literal values using GRStateManager::BindCompoundLiteral - GRStateManager::BindCompoundLiteral simply calls StoreManager::BindCompoundLiteral to get a new store and returns a persistent GRState with that store. - BasicStore::BindCompoundLiteral simply returns the same store, as it doesn't handle field sensitivity - RegionStore::BindCompoundLiteral currently fires an assert (pending discussion of how to best implement mappings for CompoundLiteralRegion). llvm-svn: 58277 --- .../Analysis/PathSensitive/GRExprEngine.h | 4 +++ .../clang/Analysis/PathSensitive/GRState.h | 8 +++++ .../clang/Analysis/PathSensitive/Store.h | 9 +++++ clang/lib/Analysis/BasicStore.cpp | 5 +++ clang/lib/Analysis/GRExprEngine.cpp | 33 +++++++++++++++++++ clang/lib/Analysis/GRState.cpp | 20 +++++++++++ clang/lib/Analysis/RegionStore.cpp | 9 +++++ 7 files changed, 88 insertions(+) diff --git a/clang/include/clang/Analysis/PathSensitive/GRExprEngine.h b/clang/include/clang/Analysis/PathSensitive/GRExprEngine.h index 8c5e6ed4034d..22454810bef8 100644 --- a/clang/include/clang/Analysis/PathSensitive/GRExprEngine.h +++ b/clang/include/clang/Analysis/PathSensitive/GRExprEngine.h @@ -499,6 +499,10 @@ protected: /// VisitCast - Transfer function logic for all casts (implicit and explicit). void VisitCast(Expr* CastE, Expr* Ex, NodeTy* Pred, NodeSet& Dst); + /// VisitCompoundLiteralExpr - Transfer function logic for compound literals. + void VisitCompoundLiteralExpr(CompoundLiteralExpr* CL, NodeTy* Pred, + NodeSet& Dst); + /// VisitDeclRefExpr - Transfer function logic for DeclRefExprs. void VisitDeclRefExpr(DeclRefExpr* DR, NodeTy* Pred, NodeSet& Dst, bool asLValue); diff --git a/clang/include/clang/Analysis/PathSensitive/GRState.h b/clang/include/clang/Analysis/PathSensitive/GRState.h index d9b058ce842e..265d028e8aca 100644 --- a/clang/include/clang/Analysis/PathSensitive/GRState.h +++ b/clang/include/clang/Analysis/PathSensitive/GRState.h @@ -329,6 +329,14 @@ public: const GRState* AddDecl(const GRState* St, const VarDecl* VD, Expr* Ex, unsigned Count); + + /// BindCompoundLiteral - Return the state that has the bindings currently + /// in 'state' plus the bindings for the CompoundLiteral. 'R' is the region + /// for the compound literal and 'BegInit' and 'EndInit' represent an + /// array of initializer values. + const GRState* BindCompoundLiteral(const GRState* state, + const CompoundLiteralRegion* R, + const SVal* BegInit, const SVal* EndInit); const GRState* RemoveDeadBindings(const GRState* St, Stmt* Loc, const LiveVariables& Liveness, diff --git a/clang/include/clang/Analysis/PathSensitive/Store.h b/clang/include/clang/Analysis/PathSensitive/Store.h index 7610c54e1b7d..41464c176fe7 100644 --- a/clang/include/clang/Analysis/PathSensitive/Store.h +++ b/clang/include/clang/Analysis/PathSensitive/Store.h @@ -47,6 +47,15 @@ public: virtual Store Bind(Store St, Loc LV, SVal V) = 0; virtual Store Remove(Store St, Loc LV) = 0; + + /// BindCompoundLiteral - Return the store that has the bindings currently + /// in 'store' plus the bindings for the CompoundLiteral. 'R' is the region + /// for the compound literal and 'BegInit' and 'EndInit' represent an + /// array of initializer values. + virtual Store BindCompoundLiteral(Store store, const CompoundLiteralRegion* R, + const SVal* BegInit, + const SVal* EndInit) = 0; + virtual Store getInitialStore() = 0; virtual MemRegionManager& getRegionManager() = 0; diff --git a/clang/lib/Analysis/BasicStore.cpp b/clang/lib/Analysis/BasicStore.cpp index 88959545028b..05c8523d2dc2 100644 --- a/clang/lib/Analysis/BasicStore.cpp +++ b/clang/lib/Analysis/BasicStore.cpp @@ -46,6 +46,11 @@ public: return loc::MemRegionVal(MRMgr.getVarRegion(VD)); } + Store BindCompoundLiteral(Store store, const CompoundLiteralRegion* R, + const SVal* BegInit, const SVal* EndInit) { + return store; + } + SVal getLValueVar(const GRState* St, const VarDecl* VD); SVal getLValueString(const GRState* St, const StringLiteral* S); SVal getLValueIvar(const GRState* St, const ObjCIvarDecl* D, SVal Base); diff --git a/clang/lib/Analysis/GRExprEngine.cpp b/clang/lib/Analysis/GRExprEngine.cpp index 282a08c21a5c..67dd79a193e4 100644 --- a/clang/lib/Analysis/GRExprEngine.cpp +++ b/clang/lib/Analysis/GRExprEngine.cpp @@ -430,6 +430,10 @@ void GRExprEngine::VisitLValue(Expr* Ex, NodeTy* Pred, NodeSet& Dst) { VisitMemberExpr(cast(Ex), Pred, Dst, true); return; + case Stmt::CompoundLiteralExprClass: + VisitCompoundLiteralExpr(cast(Ex), Pred, Dst); + return; + case Stmt::ObjCPropertyRefExprClass: // FIXME: Property assignments are lvalues, but not really "locations". // e.g.: self.x = something; @@ -1530,6 +1534,35 @@ void GRExprEngine::VisitCast(Expr* CastE, Expr* Ex, NodeTy* Pred, NodeSet& Dst){ } } +void GRExprEngine::VisitCompoundLiteralExpr(CompoundLiteralExpr* CL, + NodeTy* Pred, NodeSet& Dst) { + + // FIXME: Can getInitializer() be NULL? + InitListExpr* ILE = cast(CL->getInitializer()->IgnoreParens()); + NodeSet Tmp; + Visit(ILE, Pred, Tmp); + + for (NodeSet::iterator I = Tmp.begin(), EI = Tmp.end(); I!=EI; ++I) { + // Retrieve the initializer values from the environment and store them + // into a vector that will then be handed off to the Store. + const GRState* St = GetState(*I); + llvm::SmallVector IVals; + IVals.reserve(ILE->getNumInits()); + + for (Stmt::child_iterator J=ILE->child_begin(), EJ=ILE->child_end(); + J!=EJ; ++J) + IVals.push_back(GetSVal(St, cast(*J))); + + const CompoundLiteralRegion* R = + StateMgr.getRegionManager().getCompoundLiteralRegion(CL); + + assert (!IVals.empty() && "Initializer cannot be empty."); + + St = StateMgr.BindCompoundLiteral(St, R, &IVals[0], &IVals[0]+IVals.size()); + MakeNode(Dst, CL, *I, SetSVal(St, CL, loc::MemRegionVal(R))); + } +} + void GRExprEngine::VisitDeclStmt(DeclStmt* DS, NodeTy* Pred, NodeSet& Dst) { // The CFG has one DeclStmt per Decl. diff --git a/clang/lib/Analysis/GRState.cpp b/clang/lib/Analysis/GRState.cpp index 828be2229ff5..03b724779e9d 100644 --- a/clang/lib/Analysis/GRState.cpp +++ b/clang/lib/Analysis/GRState.cpp @@ -92,6 +92,26 @@ const GRState* GRStateManager::AddDecl(const GRState* St, const VarDecl* VD, return getPersistentState(NewSt); } +/// BindCompoundLiteral - Return the store that has the bindings currently +/// in 'store' plus the bindings for the CompoundLiteral. 'R' is the region +/// for the compound literal and 'BegInit' and 'EndInit' represent an +/// array of initializer values. +const GRState* +GRStateManager::BindCompoundLiteral(const GRState* state, + const CompoundLiteralRegion* R, + const SVal* BegInit, const SVal* EndInit) { + + Store oldStore = state->getStore(); + Store newStore = StoreMgr->BindCompoundLiteral(oldStore, R, BegInit, EndInit); + + if (newStore == oldStore) + return state; + + GRState newState = *state; + newState.St = newStore; + return getPersistentState(newState); +} + const GRState* GRStateManager::Unbind(const GRState* St, Loc LV) { Store OldStore = St->getStore(); Store NewStore = StoreMgr->Remove(OldStore, LV); diff --git a/clang/lib/Analysis/RegionStore.cpp b/clang/lib/Analysis/RegionStore.cpp index 6a65919b1ee5..1c73ceae202c 100644 --- a/clang/lib/Analysis/RegionStore.cpp +++ b/clang/lib/Analysis/RegionStore.cpp @@ -45,6 +45,15 @@ public: SVal GetRegionSVal(Store St, const MemRegion* R) { return Retrieve(St, loc::MemRegionVal(R)); } + + Store BindCompoundLiteral(Store store, const CompoundLiteralRegion* R, + const SVal* BegInit, const SVal* EndInit) { + + // FIXME: Let's discuss how we want to do the mapping in RegionStore + // from CompoundLiteralRegion to values. + assert (false && "Not yet implemented."); + return store; + } SVal getLValueString(const GRState* St, const StringLiteral* S);