зеркало из https://github.com/microsoft/clang-1.git
Move the handling of DeclStmt from GRExprEngine to BasicStoreManager.
git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@55144 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
Родитель
dbc933701d
Коммит
bbe8ff48be
|
@ -310,7 +310,10 @@ public:
|
|||
LiveVariables& getLiveVariables() { return Liveness; }
|
||||
|
||||
typedef StoreManager::DeadSymbolsTy DeadSymbolsTy;
|
||||
|
||||
|
||||
const GRState* AddDecl(const GRState* St, const VarDecl* VD, Expr* Ex,
|
||||
unsigned Count);
|
||||
|
||||
const GRState* RemoveDeadBindings(const GRState* St, Stmt* Loc,
|
||||
const LiveVariables& Liveness,
|
||||
DeadSymbolsTy& DeadSyms);
|
||||
|
|
|
@ -44,7 +44,11 @@ public:
|
|||
const LiveVariables& Live,
|
||||
DeclRootsTy& DRoots, LiveSymbolsTy& LSymbols,
|
||||
DeadSymbolsTy& DSymbols) = 0;
|
||||
|
||||
|
||||
virtual Store AddDecl(Store store, BasicValueFactory& BasicVals,
|
||||
SymbolManager& SymMgr, const VarDecl* VD, Expr* Ex,
|
||||
RVal InitVal = UndefinedVal(), unsigned Count = 0) = 0;
|
||||
|
||||
virtual void print(Store store, std::ostream& Out,
|
||||
const char* nl, const char *sep) = 0;
|
||||
};
|
||||
|
|
|
@ -40,7 +40,11 @@ public:
|
|||
const LiveVariables& Live,
|
||||
DeclRootsTy& DRoots, LiveSymbolsTy& LSymbols,
|
||||
DeadSymbolsTy& DSymbols);
|
||||
|
||||
|
||||
virtual Store AddDecl(Store store, BasicValueFactory& BasicVals,
|
||||
SymbolManager& SymMgr, const VarDecl* VD, Expr* Ex,
|
||||
RVal InitVal = UndefinedVal(), unsigned Count = 0);
|
||||
|
||||
static inline VarBindingsTy GetVarBindings(Store store) {
|
||||
return VarBindingsTy(static_cast<const VarBindingsTy::TreeTy*>(store));
|
||||
}
|
||||
|
@ -239,6 +243,69 @@ Store BasicStoreManager::getInitialStore(GRStateManager& StateMgr) {
|
|||
return St;
|
||||
}
|
||||
|
||||
Store BasicStoreManager::AddDecl(Store store, BasicValueFactory& BasicVals,
|
||||
SymbolManager& SymMgr, const VarDecl* VD,
|
||||
Expr* Ex, RVal InitVal, unsigned Count) {
|
||||
// BasicStore does not model arrays and structs.
|
||||
if (VD->getType()->isArrayType() || VD->getType()->isStructureType())
|
||||
return store;
|
||||
|
||||
if (VD->hasGlobalStorage()) {
|
||||
// Handle variables with global storage: extern, static, PrivateExtern.
|
||||
|
||||
// FIXME:: static variables may have an initializer, but the second time a
|
||||
// function is called those values may not be current. Currently, a function
|
||||
// will not be called more than once.
|
||||
|
||||
// Static global variables should not be visited here.
|
||||
assert(!(VD->getStorageClass() == VarDecl::Static &&
|
||||
VD->isFileVarDecl()));
|
||||
|
||||
// Process static variables.
|
||||
if (VD->getStorageClass() == VarDecl::Static) {
|
||||
// C99: 6.7.8 Initialization
|
||||
// If an object that has static storage duration is not initialized
|
||||
// explicitly, then:
|
||||
// —if it has pointer type, it is initialized to a null pointer;
|
||||
// —if it has arithmetic type, it is initialized to (positive or
|
||||
// unsigned) zero;
|
||||
if (!Ex) {
|
||||
QualType T = VD->getType();
|
||||
if (LVal::IsLValType(T))
|
||||
store = SetRVal(store, lval::DeclVal(VD),
|
||||
lval::ConcreteInt(BasicVals.getValue(0, T)));
|
||||
else if (T->isIntegerType())
|
||||
store = SetRVal(store, lval::DeclVal(VD),
|
||||
nonlval::ConcreteInt(BasicVals.getValue(0, T)));
|
||||
else {
|
||||
// assert(0 && "ignore other types of variables");
|
||||
}
|
||||
} else {
|
||||
store = SetRVal(store, lval::DeclVal(VD), InitVal);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
// Process local scalar variables.
|
||||
QualType T = VD->getType();
|
||||
if (LVal::IsLValType(T) || T->isIntegerType()) {
|
||||
RVal V = Ex ? InitVal : UndefinedVal();
|
||||
|
||||
if (Ex && InitVal.isUnknown()) {
|
||||
// EXPERIMENTAL: "Conjured" symbols.
|
||||
SymbolID Sym = SymMgr.getConjuredSymbol(Ex, Count);
|
||||
|
||||
V = LVal::IsLValType(Ex->getType())
|
||||
? cast<RVal>(lval::SymbolVal(Sym))
|
||||
: cast<RVal>(nonlval::SymbolVal(Sym));
|
||||
}
|
||||
|
||||
store = SetRVal(store, lval::DeclVal(VD), V);
|
||||
}
|
||||
}
|
||||
|
||||
return store;
|
||||
}
|
||||
|
||||
void BasicStoreManager::print(Store store, std::ostream& Out,
|
||||
const char* nl, const char *sep) {
|
||||
|
||||
|
|
|
@ -1484,76 +1484,9 @@ void GRExprEngine::VisitDeclStmtAux(DeclStmt* DS, ScopedDecl* D,
|
|||
if (Tmp.empty()) Tmp.Add(Pred);
|
||||
|
||||
for (NodeSet::iterator I=Tmp.begin(), E=Tmp.end(); I!=E; ++I) {
|
||||
|
||||
const GRState* St = GetState(*I);
|
||||
|
||||
if (!Ex && VD->hasGlobalStorage()) {
|
||||
|
||||
// Handle variables with global storage and no initializers.
|
||||
|
||||
// FIXME: static variables may have an initializer, but the second
|
||||
// time a function is called those values may not be current.
|
||||
|
||||
|
||||
// In this context, Static => Local variable.
|
||||
|
||||
assert (!VD->getStorageClass() == VarDecl::Static ||
|
||||
!VD->isFileVarDecl());
|
||||
|
||||
// If there is no initializer, set the value of the
|
||||
// variable to "Undefined".
|
||||
|
||||
if (VD->getStorageClass() == VarDecl::Static) {
|
||||
|
||||
// C99: 6.7.8 Initialization
|
||||
// If an object that has static storage duration is not initialized
|
||||
// explicitly, then:
|
||||
// —if it has pointer type, it is initialized to a null pointer;
|
||||
// —if it has arithmetic type, it is initialized to (positive or
|
||||
// unsigned) zero;
|
||||
|
||||
// FIXME: Handle structs. Now we treat their values as unknown.
|
||||
|
||||
QualType T = VD->getType();
|
||||
|
||||
if (LVal::IsLValType(T))
|
||||
St = SetRVal(St, lval::DeclVal(VD),
|
||||
lval::ConcreteInt(getBasicVals().getValue(0, T)));
|
||||
else if (T->isIntegerType())
|
||||
St = SetRVal(St, lval::DeclVal(VD),
|
||||
nonlval::ConcreteInt(getBasicVals().getValue(0, T)));
|
||||
|
||||
// FIXME: Handle structs. Now we treat them as unknown. What
|
||||
// we need to do is treat their members as unknown.
|
||||
}
|
||||
}
|
||||
else {
|
||||
|
||||
// FIXME: Handle structs. Now we treat them as unknown. What
|
||||
// we need to do is treat their members as unknown.
|
||||
|
||||
QualType T = VD->getType();
|
||||
|
||||
if (LVal::IsLValType(T) || T->isIntegerType()) {
|
||||
|
||||
RVal V = Ex ? GetRVal(St, Ex) : UndefinedVal();
|
||||
|
||||
if (Ex && V.isUnknown()) {
|
||||
|
||||
// EXPERIMENTAL: "Conjured" symbols.
|
||||
|
||||
unsigned Count = Builder->getCurrentBlockCount();
|
||||
SymbolID Sym = SymMgr.getConjuredSymbol(Ex, Count);
|
||||
|
||||
V = LVal::IsLValType(Ex->getType())
|
||||
? cast<RVal>(lval::SymbolVal(Sym))
|
||||
: cast<RVal>(nonlval::SymbolVal(Sym));
|
||||
}
|
||||
|
||||
St = SetRVal(St, lval::DeclVal(VD), V);
|
||||
}
|
||||
}
|
||||
|
||||
St = StateMgr.AddDecl(St, VD, Ex, Builder->getCurrentBlockCount());
|
||||
|
||||
// Create a new node. We don't really need to create a new NodeSet
|
||||
// here, but it simplifies things and doesn't cost much.
|
||||
NodeSet Tmp2;
|
||||
|
|
|
@ -142,6 +142,24 @@ const GRState* GRStateManager::SetRVal(const GRState* St, LVal LV,
|
|||
return getPersistentState(NewSt);
|
||||
}
|
||||
|
||||
const GRState* GRStateManager::AddDecl(const GRState* St, const VarDecl* VD,
|
||||
Expr* Ex, unsigned Count) {
|
||||
Store OldStore = St->getStore();
|
||||
Store NewStore;
|
||||
|
||||
if (Ex)
|
||||
NewStore = StMgr->AddDecl(OldStore, BasicVals, SymMgr, VD, Ex,
|
||||
GetRVal(St, Ex), Count);
|
||||
else
|
||||
NewStore = StMgr->AddDecl(OldStore, BasicVals, SymMgr, VD, Ex);
|
||||
|
||||
if (NewStore == OldStore)
|
||||
return St;
|
||||
GRState NewSt = *St;
|
||||
NewSt.St = NewStore;
|
||||
return getPersistentState(NewSt);
|
||||
}
|
||||
|
||||
const GRState* GRStateManager::Unbind(const GRState* St, LVal LV) {
|
||||
Store OldStore = St->getStore();
|
||||
Store NewStore = StMgr->Remove(OldStore, LV);
|
||||
|
|
Загрузка…
Ссылка в новой задаче