forked from OSchip/llvm-project
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
This commit is contained in:
parent
2837b9ef6c
commit
bf26368255
|
@ -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);
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -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;
|
||||
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -430,6 +430,10 @@ void GRExprEngine::VisitLValue(Expr* Ex, NodeTy* Pred, NodeSet& Dst) {
|
|||
VisitMemberExpr(cast<MemberExpr>(Ex), Pred, Dst, true);
|
||||
return;
|
||||
|
||||
case Stmt::CompoundLiteralExprClass:
|
||||
VisitCompoundLiteralExpr(cast<CompoundLiteralExpr>(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<InitListExpr>(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<SVal, 10> 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<Expr>(*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.
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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);
|
||||
|
||||
|
|
Loading…
Reference in New Issue