diff --git a/clang/include/clang/Analysis/PathSensitive/GRState.h b/clang/include/clang/Analysis/PathSensitive/GRState.h index 483f16ed7d07..27df2bbdb672 100644 --- a/clang/include/clang/Analysis/PathSensitive/GRState.h +++ b/clang/include/clang/Analysis/PathSensitive/GRState.h @@ -336,15 +336,24 @@ public: typedef StoreManager::DeadSymbolsTy DeadSymbolsTy; - const GRState* BindDecl(const GRState* St, const VarDecl* VD, SVal* IVal, - unsigned Count); + const GRState* BindDecl(const GRState* St, const VarDecl* VD, SVal IVal) { + // Store manager should return a persistent state. + return StoreMgr->BindDecl(St, VD, IVal); + } + + const GRState* BindDeclWithNoInit(const GRState* St, const VarDecl* VD) { + // Store manager should return a persistent state. + return StoreMgr->BindDeclWithNoInit(St, VD); + } /// 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 CompoundLiteralExpr* CL, SVal V); + const GRState* BindCompoundLiteral(const GRState* St, + const CompoundLiteralExpr* CL, SVal V) { + return StoreMgr->BindCompoundLiteral(St, CL, V); + } const GRState* RemoveDeadBindings(const GRState* St, Stmt* Loc, const LiveVariables& Liveness, @@ -468,11 +477,9 @@ public: return StoreMgr->GetRegionSVal(state, R); } - void BindLoc(GRState& St, Loc LV, SVal V) { - St.St = StoreMgr->Bind(St.St, LV, V); + const GRState* BindLoc(const GRState* St, Loc LV, SVal V) { + return StoreMgr->Bind(St, LV, V); } - - const GRState* BindLoc(const GRState* St, Loc LV, SVal V); void Unbind(GRState& St, Loc LV) { St.St = StoreMgr->Remove(St.St, LV); @@ -481,6 +488,9 @@ public: const GRState* Unbind(const GRState* St, Loc LV); const GRState* getPersistentState(GRState& Impl); + + // MakeStateWithStore - get a persistent state with the new store. + const GRState* MakeStateWithStore(const GRState* St, Store store); bool isEqual(const GRState* state, Expr* Ex, const llvm::APSInt& V); bool isEqual(const GRState* state, Expr* Ex, uint64_t); @@ -501,7 +511,15 @@ public: return addGDM(st, GRStateTrait::GDMIndex(), GRStateTrait::MakeVoidPtr(GRStateTrait::Set(st->get(), K, V, C))); } - + + template + const GRState* add(const GRState* st, + typename GRStateTrait::key_type K, + typename GRStateTrait::context_type C) { + return addGDM(st, GRStateTrait::GDMIndex(), + GRStateTrait::MakeVoidPtr(GRStateTrait::Add(st->get(), K, C))); + } + template const GRState* remove(const GRState* st, typename GRStateTrait::key_type K, @@ -587,14 +605,12 @@ public: return GRStateRef(Mgr->BindExpr(St, Ex, V, Invalidate), *Mgr); } - GRStateRef BindDecl(const VarDecl* VD, SVal* InitVal, unsigned Count) { - return GRStateRef(Mgr->BindDecl(St, VD, InitVal, Count), *Mgr); + GRStateRef BindDecl(const VarDecl* VD, SVal InitVal) { + return GRStateRef(Mgr->BindDecl(St, VD, InitVal), *Mgr); } GRStateRef BindLoc(Loc LV, SVal V) { - GRState StImpl = *St; - Mgr->BindLoc(StImpl, LV, V); - return GRStateRef(Mgr->getPersistentState(StImpl), *Mgr); + return GRStateRef(Mgr->BindLoc(St, LV, V), *Mgr); } GRStateRef BindLoc(SVal LV, SVal V) { @@ -644,7 +660,12 @@ public: typename GRStateTrait::value_type E) { return GRStateRef(Mgr->set(St, K, E, get_context()), *Mgr); } - + + template + GRStateRef add(typename GRStateTrait::key_type K) { + return GRStateRef(Mgr->add(St, K, get_context()), *Mgr); + } + template GRStateRef remove(typename GRStateTrait::key_type K, typename GRStateTrait::context_type C) { @@ -658,7 +679,7 @@ public: template bool contains(typename GRStateTrait::key_type key) const { - return St->contains(key); + return St->contains(key); } // Lvalue methods. diff --git a/clang/include/clang/Analysis/PathSensitive/MemRegion.h b/clang/include/clang/Analysis/PathSensitive/MemRegion.h index efe0b9a19c13..40c6fde51ea7 100644 --- a/clang/include/clang/Analysis/PathSensitive/MemRegion.h +++ b/clang/include/clang/Analysis/PathSensitive/MemRegion.h @@ -99,7 +99,7 @@ public: const MemRegion* getSuperRegion() const { return superRegion; } - + static bool classof(const MemRegion* R) { return R->getKind() > SymbolicRegionKind; } @@ -466,6 +466,12 @@ public: assert(R); return R == globals; } + + /// onStack - check if the region is allocated on the stack. + bool onStack(const MemRegion* R); + + /// onHeap - check if the region is allocated on the heap, usually by malloc. + bool onHeap(const MemRegion* R); /// getAllocaRegion - Retrieve a region associated with a call to alloca(). AllocaRegion* getAllocaRegion(const Expr* Ex, unsigned Cnt); diff --git a/clang/include/clang/Analysis/PathSensitive/SVals.h b/clang/include/clang/Analysis/PathSensitive/SVals.h index 361e321823c7..ca36187530ee 100644 --- a/clang/include/clang/Analysis/PathSensitive/SVals.h +++ b/clang/include/clang/Analysis/PathSensitive/SVals.h @@ -71,7 +71,13 @@ public: inline bool operator!=(const SVal& R) const { return !(*this == R); } - + + /// MakeSymbolValue - make a unique symbol value for the region R according to + /// its kind. R should be a scalar region. The symbol value T has the same + /// type as R's rvalue type. + static SVal MakeSymbolValue(SymbolManager& SymMgr, const MemRegion* R, + QualType T); + static SVal GetSymbolValue(SymbolManager& SymMgr, VarDecl *D); static SVal getSymbolValue(SymbolManager& SymMgr, const MemRegion* R, const llvm::APSInt* Idx, QualType T); @@ -171,6 +177,8 @@ public: // Utility methods to create NonLocs. + static NonLoc MakeVal(SymbolRef sym); + static NonLoc MakeVal(BasicValueFactory& BasicVals, unsigned X, bool isUnsigned); @@ -212,6 +220,8 @@ public: static Loc MakeVal(const MemRegion* R); static Loc MakeVal(AddrLabelExpr* E); + + static Loc MakeVal(SymbolRef sym); // Implement isa support. static inline bool classof(const SVal* V) { diff --git a/clang/include/clang/Analysis/PathSensitive/Store.h b/clang/include/clang/Analysis/PathSensitive/Store.h index ca21e2024497..5425b6976b9a 100644 --- a/clang/include/clang/Analysis/PathSensitive/Store.h +++ b/clang/include/clang/Analysis/PathSensitive/Store.h @@ -49,16 +49,19 @@ public: SVal GetRegionSVal(const GRState* state, const MemRegion* R) { return Retrieve(state, loc::MemRegionVal(R)); } - - virtual Store Bind(Store St, Loc LV, SVal V) = 0; - virtual Store Remove(Store St, Loc LV) = 0; + + /// Bind value V to location L. + virtual const GRState* Bind(const GRState* St, Loc L, SVal V) = 0; + + virtual Store Remove(Store St, Loc L) = 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 CompoundLiteralExpr* CL, - SVal V) = 0; + virtual const GRState* BindCompoundLiteral(const GRState* St, + const CompoundLiteralExpr* CL, + SVal V) = 0; virtual Store getInitialStore() = 0; virtual MemRegionManager& getRegionManager() = 0; @@ -112,8 +115,11 @@ public: llvm::SmallVectorImpl& RegionRoots, LiveSymbolsTy& LSymbols, DeadSymbolsTy& DSymbols) = 0; - virtual Store BindDecl(Store store, const VarDecl* VD, SVal* InitVal, - unsigned Count) = 0; + virtual const GRState* BindDecl(const GRState* St, const VarDecl* VD, + SVal InitVal) = 0; + + virtual const GRState* BindDeclWithNoInit(const GRState* St, + const VarDecl* VD) = 0; virtual const GRState* setExtent(const GRState* St, const MemRegion* R, SVal Extent) { diff --git a/clang/include/clang/Analysis/PathSensitive/SymbolManager.h b/clang/include/clang/Analysis/PathSensitive/SymbolManager.h index 1adc7c6eafc7..87852934945c 100644 --- a/clang/include/clang/Analysis/PathSensitive/SymbolManager.h +++ b/clang/include/clang/Analysis/PathSensitive/SymbolManager.h @@ -104,15 +104,15 @@ public: }; class SymbolDataParmVar : public SymbolData { - ParmVarDecl *VD; + const ParmVarDecl *VD; public: - SymbolDataParmVar(SymbolRef MySym, ParmVarDecl* vd) + SymbolDataParmVar(SymbolRef MySym, const ParmVarDecl* vd) : SymbolData(ParmKind, MySym), VD(vd) {} - ParmVarDecl* getDecl() const { return VD; } + const ParmVarDecl* getDecl() const { return VD; } - static void Profile(llvm::FoldingSetNodeID& profile, ParmVarDecl* VD) { + static void Profile(llvm::FoldingSetNodeID& profile, const ParmVarDecl* VD) { profile.AddInteger((unsigned) ParmKind); profile.AddPointer(VD); } @@ -128,15 +128,15 @@ public: }; class SymbolDataGlobalVar : public SymbolData { - VarDecl *VD; + const VarDecl *VD; public: - SymbolDataGlobalVar(SymbolRef MySym, VarDecl* vd) : + SymbolDataGlobalVar(SymbolRef MySym, const VarDecl* vd) : SymbolData(GlobalKind, MySym), VD(vd) {} - VarDecl* getDecl() const { return VD; } + const VarDecl* getDecl() const { return VD; } - static void Profile(llvm::FoldingSetNodeID& profile, VarDecl* VD) { + static void Profile(llvm::FoldingSetNodeID& profile, const VarDecl* VD) { profile.AddInteger((unsigned) GlobalKind); profile.AddPointer(VD); } @@ -275,8 +275,10 @@ public: : SymbolCounter(0), BPAlloc(bpalloc) {} ~SymbolManager(); - - SymbolRef getSymbol(VarDecl* D); + + /// Make a unique symbol for MemRegion R according to its kind. + SymbolRef getSymbol(const MemRegion* R); + SymbolRef getSymbol(const VarDecl* D); SymbolRef getElementSymbol(const MemRegion* R, const llvm::APSInt* Idx); SymbolRef getFieldSymbol(const MemRegion* R, const FieldDecl* D); SymbolRef getConjuredSymbol(Stmt* E, QualType T, unsigned VisitCount); diff --git a/clang/lib/Analysis/BasicStore.cpp b/clang/lib/Analysis/BasicStore.cpp index 1febba675de7..07163d51e30f 100644 --- a/clang/lib/Analysis/BasicStore.cpp +++ b/clang/lib/Analysis/BasicStore.cpp @@ -39,7 +39,14 @@ public: ~BasicStoreManager() {} SVal Retrieve(const GRState *state, Loc LV, QualType T); - Store Bind(Store St, Loc LV, SVal V); + + const GRState* Bind(const GRState* St, Loc L, SVal V) { + Store store = St->getStore(); + store = BindInternal(store, L, V); + return StateMgr.MakeStateWithStore(St, store); + } + + Store BindInternal(Store St, Loc LV, SVal V); Store Remove(Store St, Loc LV); Store getInitialStore(); MemRegionManager& getRegionManager() { return MRMgr; } @@ -49,9 +56,10 @@ public: return loc::MemRegionVal(MRMgr.getVarRegion(VD)); } - Store BindCompoundLiteral(Store store, const CompoundLiteralExpr* CL, - SVal V) { - return store; + const GRState* BindCompoundLiteral(const GRState* St, + const CompoundLiteralExpr* CL, + SVal V) { + return St; } SVal getLValueVar(const GRState* St, const VarDecl* VD); @@ -89,7 +97,25 @@ public: void iterBindings(Store store, BindingsHandler& f); - Store BindDecl(Store store, const VarDecl* VD, SVal* InitVal, unsigned Count); + const GRState* BindDecl(const GRState* St, const VarDecl* VD, SVal InitVal) { + Store store = St->getStore(); + store = BindDeclInternal(store, VD, &InitVal); + return StateMgr.MakeStateWithStore(St, store); + } + + const GRState* BindDeclWithNoInit(const GRState* St, const VarDecl* VD) { + Store store = St->getStore(); + store = BindDeclInternal(store, VD, 0); + return StateMgr.MakeStateWithStore(St, store); + } + + const GRState* BindDecl(const GRState* St, const VarDecl* VD) { + Store store = St->getStore(); + store = BindDeclInternal(store, VD, 0); + return StateMgr.MakeStateWithStore(St, store); + } + + Store BindDeclInternal(Store store, const VarDecl* VD, SVal* InitVal); static inline VarBindingsTy GetVarBindings(Store store) { return VarBindingsTy(static_cast(store)); @@ -286,7 +312,7 @@ SVal BasicStoreManager::Retrieve(const GRState* state, Loc LV, QualType T) { return UnknownVal(); } -Store BasicStoreManager::Bind(Store store, Loc LV, SVal V) { +Store BasicStoreManager::BindInternal(Store store, Loc LV, SVal V) { switch (LV.getSubKind()) { case loc::MemRegionKind: { const VarRegion* R = @@ -421,8 +447,8 @@ Store BasicStoreManager::getInitialStore() { SelfRegion = MRMgr.getObjCObjectRegion(MD->getClassInterface(), MRMgr.getHeapRegion()); - St = Bind(St, loc::MemRegionVal(MRMgr.getVarRegion(PD)), - loc::MemRegionVal(SelfRegion)); + St = BindInternal(St, loc::MemRegionVal(MRMgr.getVarRegion(PD)), + loc::MemRegionVal(SelfRegion)); } } } @@ -441,15 +467,15 @@ Store BasicStoreManager::getInitialStore() { ? SVal::GetSymbolValue(StateMgr.getSymbolManager(), VD) : UndefinedVal(); - St = Bind(St, loc::MemRegionVal(MRMgr.getVarRegion(VD)), X); + St = BindInternal(St, loc::MemRegionVal(MRMgr.getVarRegion(VD)), X); } } } return St; } -Store BasicStoreManager::BindDecl(Store store, const VarDecl* VD, - SVal* InitVal, unsigned Count) { +Store BasicStoreManager::BindDeclInternal(Store store, const VarDecl* VD, + SVal* InitVal) { BasicValueFactory& BasicVals = StateMgr.getBasicVals(); @@ -479,16 +505,16 @@ Store BasicStoreManager::BindDecl(Store store, const VarDecl* VD, if (!InitVal) { QualType T = VD->getType(); if (Loc::IsLocType(T)) - store = Bind(store, getLoc(VD), + store = BindInternal(store, getLoc(VD), loc::ConcreteInt(BasicVals.getValue(0, T))); else if (T->isIntegerType()) - store = Bind(store, getLoc(VD), + store = BindInternal(store, getLoc(VD), nonloc::ConcreteInt(BasicVals.getValue(0, T))); else { // assert(0 && "ignore other types of variables"); } } else { - store = Bind(store, getLoc(VD), *InitVal); + store = BindInternal(store, getLoc(VD), *InitVal); } } } else { @@ -496,7 +522,7 @@ Store BasicStoreManager::BindDecl(Store store, const VarDecl* VD, QualType T = VD->getType(); if (Loc::IsLocType(T) || T->isIntegerType()) { SVal V = InitVal ? *InitVal : UndefinedVal(); - store = Bind(store, getLoc(VD), V); + store = BindInternal(store, getLoc(VD), V); } } diff --git a/clang/lib/Analysis/GRExprEngine.cpp b/clang/lib/Analysis/GRExprEngine.cpp index e6c12ead89f5..0dd6b5fa6893 100644 --- a/clang/lib/Analysis/GRExprEngine.cpp +++ b/clang/lib/Analysis/GRExprEngine.cpp @@ -1811,7 +1811,8 @@ void GRExprEngine::VisitDeclStmt(DeclStmt* DS, NodeTy* Pred, NodeSet& Dst) { for (NodeSet::iterator I=Tmp.begin(), E=Tmp.end(); I!=E; ++I) { const GRState* St = GetState(*I); unsigned Count = Builder->getCurrentBlockCount(); - + + // Decls without InitExpr are not initialized explicitly. if (InitEx) { SVal InitVal = GetSVal(St, InitEx); QualType T = VD->getType(); @@ -1829,11 +1830,9 @@ void GRExprEngine::VisitDeclStmt(DeclStmt* DS, NodeTy* Pred, NodeSet& Dst) { } } - St = StateMgr.BindDecl(St, VD, &InitVal, Count); - } - else - St = StateMgr.BindDecl(St, VD, 0, Count); - + St = StateMgr.BindDecl(St, VD, InitVal); + } else + St = StateMgr.BindDeclWithNoInit(St, VD); // Check if 'VD' is a VLA and if so check if has a non-zero size. QualType T = getContext().getCanonicalType(VD->getType()); diff --git a/clang/lib/Analysis/GRState.cpp b/clang/lib/Analysis/GRState.cpp index 221ab064d30a..8e49ebb63db3 100644 --- a/clang/lib/Analysis/GRState.cpp +++ b/clang/lib/Analysis/GRState.cpp @@ -59,51 +59,6 @@ GRStateManager::RemoveDeadBindings(const GRState* state, Stmt* Loc, LSymbols, DSymbols); } -const GRState* GRStateManager::BindLoc(const GRState* St, Loc LV, SVal V) { - - Store OldStore = St->getStore(); - Store NewStore = StoreMgr->Bind(OldStore, LV, V); - - if (NewStore == OldStore) - return St; - - GRState NewSt = *St; - NewSt.St = NewStore; - return getPersistentState(NewSt); -} - -const GRState* GRStateManager::BindDecl(const GRState* St, const VarDecl* VD, - SVal* InitVal, unsigned Count) { - Store OldStore = St->getStore(); - Store NewStore = StoreMgr->BindDecl(OldStore, VD, InitVal, Count); - - if (NewStore == OldStore) - return St; - - GRState NewSt = *St; - NewSt.St = NewStore; - 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 CompoundLiteralExpr* CL, SVal ILV) { - - Store oldStore = state->getStore(); - Store newStore = StoreMgr->BindCompoundLiteral(oldStore, CL, ILV); - - 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); @@ -140,6 +95,13 @@ const GRState* GRStateManager::getPersistentState(GRState& State) { return I; } +const GRState* GRStateManager::MakeStateWithStore(const GRState* St, + Store store) { + GRState NewSt = *St; + NewSt.St = store; + return getPersistentState(NewSt); +} + //===----------------------------------------------------------------------===// // State pretty-printing. diff --git a/clang/lib/Analysis/MemRegion.cpp b/clang/lib/Analysis/MemRegion.cpp index eafeee66d546..8767781354e7 100644 --- a/clang/lib/Analysis/MemRegion.cpp +++ b/clang/lib/Analysis/MemRegion.cpp @@ -215,6 +215,20 @@ MemSpaceRegion* MemRegionManager::getUnknownRegion() { return LazyAllocate(unknown); } +bool MemRegionManager::onStack(const MemRegion* R) { + while (const SubRegion* SR = dyn_cast(R)) + R = SR->getSuperRegion(); + + return (R != 0) && (R == stack); +} + +bool MemRegionManager::onHeap(const MemRegion* R) { + while (const SubRegion* SR = dyn_cast(R)) + R = SR->getSuperRegion(); + + return (R != 0) && (R == heap); +} + StringRegion* MemRegionManager::getStringRegion(const StringLiteral* Str) { llvm::FoldingSetNodeID ID; MemSpaceRegion* GlobalsR = getGlobalsRegion(); diff --git a/clang/lib/Analysis/RegionStore.cpp b/clang/lib/Analysis/RegionStore.cpp index 98b408156f1f..06292d20d8ca 100644 --- a/clang/lib/Analysis/RegionStore.cpp +++ b/clang/lib/Analysis/RegionStore.cpp @@ -62,6 +62,16 @@ namespace clang { }; } +// Regions that have default value zero. +// FIXME: redefinition! +// typedef llvm::ImmutableMap RegionDefaultValue; +// static int RegionDefaultValueIndex = 0; +// namespace clang { +// template<> struct GRStateTrait +// : public GRStatePartialTrait { +// static void* GDMIndex() { return &RegionDefaultValueIndex; } +// }; +// } namespace { @@ -83,7 +93,8 @@ public: MemRegionManager& getRegionManager() { return MRMgr; } - Store BindCompoundLiteral(Store store, const CompoundLiteralExpr* CL, SVal V); + const GRState* BindCompoundLiteral(const GRState* St, + const CompoundLiteralExpr* CL, SVal V); SVal getLValueString(const GRState* St, const StringLiteral* S); @@ -107,13 +118,24 @@ public: CastResult CastRegion(const GRState* state, const MemRegion* R, QualType CastToTy); + /// 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()); - Store Bind(Store St, Loc LV, SVal V); + const GRState* Bind(const GRState* St, Loc LV, SVal V); Store Remove(Store store, Loc LV); - Store getInitialStore(); + Store getInitialStore() { return RBFactory.GetEmptyMap().getRoot(); } /// getSelfRegion - Returns the region for the 'self' (Objective-C) or /// 'this' object (C++). When used when analyzing a normal function this @@ -133,7 +155,11 @@ public: void UpdateLiveSymbols(SVal X, LiveSymbolsTy& LSymbols); - Store BindDecl(Store store, const VarDecl* VD, SVal* InitVal, unsigned Count); + const GRState* BindDecl(const GRState* St, const VarDecl* VD, SVal InitVal); + + const GRState* BindDeclWithNoInit(const GRState* St, const VarDecl* VD) { + return St; + } const GRState* setExtent(const GRState* St, const MemRegion* R, SVal Extent); @@ -152,22 +178,16 @@ private: return loc::MemRegionVal(MRMgr.getVarRegion(VD)); } - Store InitializeArray(Store store, const TypedRegion* R, SVal Init); - Store BindArrayToVal(Store store, const TypedRegion* BaseR, SVal V); - Store BindArrayToSymVal(Store store, const TypedRegion* BaseR); - - Store InitializeStruct(Store store, const TypedRegion* R, SVal Init); - Store BindStructToVal(Store store, const TypedRegion* BaseR, SVal V); - Store BindStructToSymVal(Store store, const TypedRegion* BaseR); + const GRState* BindArray(const GRState* St, const TypedRegion* R, SVal V); /// 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(Store store, const TypedRegion* R); + SVal RetrieveStruct(const GRState* St, const TypedRegion* R); - Store BindStruct(Store store, const TypedRegion* R, SVal V); + const GRState* BindStruct(const GRState* St, const TypedRegion* R, SVal V); // Utility methods. BasicValueFactory& getBasicVals() { return StateMgr.getBasicVals(); } @@ -396,41 +416,60 @@ RegionStoreManager::CastRegion(const GRState* state, const MemRegion* R, return CastResult(AddRegionView(state, ViewR, R), ViewR); } -SVal RegionStoreManager::Retrieve(const GRState* state, Loc L, QualType T) { +SVal RegionStoreManager::Retrieve(const GRState* St, Loc L, QualType T) { assert(!isa(L) && "location unknown"); assert(!isa(L) && "location undefined"); - Store S = state->getStore(); - switch (L.getSubKind()) { - case loc::MemRegionKind: { - const MemRegion* R = cast(L).getRegion(); - assert(R && "bad region"); - - if (const TypedRegion* TR = dyn_cast(R)) - if (TR->getRValueType(getContext())->isStructureType()) - return RetrieveStruct(S, TR); - - RegionBindingsTy B(static_cast(S)); - RegionBindingsTy::data_type* V = B.lookup(R); - return V ? *V : UnknownVal(); - } - - case loc::SymbolValKind: + if (isa(L)) return UnknownVal(); - case loc::ConcreteIntKind: - return UndefinedVal(); // As in BasicStoreManager. + if (isa(L)) + return UndefinedVal(); - case loc::FuncValKind: + if (isa(L)) return L; - default: - assert(false && "Invalid Location"); - return L; - } + const MemRegion* R = cast(L).getRegion(); + assert(R && "bad region"); + + if (const TypedRegion* TR = dyn_cast(R)) + if (TR->getRValueType(getContext())->isStructureType()) + return RetrieveStruct(St, TR); + + RegionBindingsTy B = GetRegionBindings(St->getStore()); + RegionBindingsTy::data_type* V = B.lookup(R); + + // Check if the region has a binding. + if (V) + return *V; + + // Check if the region is in killset. + GRStateRef state(St, StateMgr); + if (state.contains(R)) + return UnknownVal(); + + // The location is not initialized. + + // We treat parameters as symbolic values. + if (const VarRegion* VR = dyn_cast(R)) + if (isa(VR->getDecl())) + return SVal::MakeSymbolValue(getSymbolManager(), VR, + VR->getRValueType(getContext())); + + if (MRMgr.onStack(R) || MRMgr.onHeap(R)) + return UndefinedVal(); + else + return SVal::MakeSymbolValue(getSymbolManager(), R, + cast(R)->getRValueType(getContext())); + + // FIXME: consider default values for elements and fields. } -SVal RegionStoreManager::RetrieveStruct(Store store, const TypedRegion* R) { +SVal RegionStoreManager::RetrieveStruct(const GRState* St,const TypedRegion* R){ + + Store store = St->getStore(); + GRStateRef state(St, StateMgr); + // FIXME: Verify we want getRValueType instead of getLValueType. QualType T = R->getRValueType(getContext()); assert(T->isStructureType()); @@ -447,10 +486,21 @@ SVal RegionStoreManager::RetrieveStruct(Store store, const TypedRegion* R) { FieldEnd = Fields.rend(); Field != FieldEnd; ++Field) { FieldRegion* FR = MRMgr.getFieldRegion(*Field, R); - RegionBindingsTy B(static_cast(store)); + RegionBindingsTy B = GetRegionBindings(store); RegionBindingsTy::data_type* data = B.lookup(FR); - SVal FieldValue = data ? *data : UnknownVal(); + SVal FieldValue; + if (data) + FieldValue = *data; + else if (state.contains(FR)) + FieldValue = UnknownVal(); + else { + if (MRMgr.onStack(FR) || MRMgr.onHeap(FR)) + FieldValue = UndefinedVal(); + else + FieldValue = SVal::MakeSymbolValue(getSymbolManager(), FR, + FR->getRValueType(getContext())); + } StructVal = getBasicVals().consVals(FieldValue, StructVal); } @@ -458,25 +508,37 @@ SVal RegionStoreManager::RetrieveStruct(Store store, const TypedRegion* R) { return NonLoc::MakeCompoundVal(T, StructVal, getBasicVals()); } -Store RegionStoreManager::Bind(Store store, Loc LV, SVal V) { - if (LV.getSubKind() == loc::SymbolValKind) - return store; +const GRState* RegionStoreManager::Bind(const GRState* St, Loc L, SVal V) { + // Currently we don't bind value to symbolic location. But if the logic is + // made clear, we might change this decision. + if (isa(L)) + return St; - assert(LV.getSubKind() == loc::MemRegionKind); - - const MemRegion* R = cast(LV).getRegion(); - + // If we get here, the location should be a region. + const MemRegion* R = cast(L).getRegion(); assert(R); + // Check if the region is a struct region. if (const TypedRegion* TR = dyn_cast(R)) // FIXME: Verify we want getRValueType(). if (TR->getRValueType(getContext())->isStructureType()) - return BindStruct(store, TR, V); + return BindStruct(St, TR, V); + Store store = St->getStore(); RegionBindingsTy B = GetRegionBindings(store); - return V.isUnknown() - ? RBFactory.Remove(B, R).getRoot() - : RBFactory.Add(B, R, V).getRoot(); + + 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(R); + } + else + store = RBFactory.Add(B, R, V).getRoot(); + + return StateMgr.MakeStateWithStore(St, store); } Store RegionStoreManager::Remove(Store store, Loc L) { @@ -488,150 +550,37 @@ Store RegionStoreManager::Remove(Store store, Loc L) { return RBFactory.Remove(B, R).getRoot(); } -Store RegionStoreManager::BindStruct(Store store, const TypedRegion* R, SVal V){ - // Verify we want getRValueType. - QualType T = R->getRValueType(getContext()); - assert(T->isStructureType()); +const GRState* RegionStoreManager::BindDecl(const GRState* St, + const VarDecl* VD, SVal InitVal) { + // All static variables are treated as symbolic values. + if (VD->hasGlobalStorage()) + return St; - const RecordType* RT = cast(T.getTypePtr()); - RecordDecl* RD = RT->getDecl(); + // Process local variables. - if (!RD->isDefinition()) { - // This can only occur when a pointer of incomplete struct type is used as a - // function argument. - assert(V.isUnknown()); - return store; - } + QualType T = VD->getType(); + + VarRegion* VR = MRMgr.getVarRegion(VD); + + if (Loc::IsLocType(T) || T->isIntegerType()) + return Bind(St, Loc::MakeVal(VR), InitVal); - RegionBindingsTy B = GetRegionBindings(store); + else if (T->isArrayType()) + return BindArray(St, VR, InitVal); - if (isa(V)) - return BindStructToVal(store, R, UnknownVal()); + else if (T->isStructureType()) + return BindStruct(St, VR, InitVal); - nonloc::CompoundVal& CV = cast(V); - - nonloc::CompoundVal::iterator VI = CV.begin(), VE = CV.end(); - RecordDecl::field_iterator FI = RD->field_begin(), FE = RD->field_end(); - - for (; FI != FE; ++FI, ++VI) { - assert(VI != VE); - - FieldRegion* FR = MRMgr.getFieldRegion(*FI, R); - - B = RBFactory.Add(B, FR, *VI); - } - - return B.getRoot(); -} - -Store RegionStoreManager::getInitialStore() { - typedef LiveVariables::AnalysisDataTy LVDataTy; - LVDataTy& D = StateMgr.getLiveVariables().getAnalysisData(); - - Store St = RBFactory.GetEmptyMap().getRoot(); - - for (LVDataTy::decl_iterator I=D.begin_decl(), E=D.end_decl(); I != E; ++I) { - NamedDecl* ND = const_cast(I->first); - - if (VarDecl* VD = dyn_cast(ND)) { - // Punt on static variables for now. - if (VD->getStorageClass() == VarDecl::Static) - continue; - - VarRegion* VR = MRMgr.getVarRegion(VD); - - QualType T = VD->getType(); - // Only handle pointers and integers for now. - if (Loc::IsLocType(T) || T->isIntegerType()) { - // Initialize globals and parameters to symbolic values. - // Initialize local variables to undefined. - SVal X = (VD->hasGlobalStorage() || isa(VD) || - isa(VD)) - ? SVal::GetSymbolValue(getSymbolManager(), VD) - : UndefinedVal(); - - St = Bind(St, getVarLoc(VD), X); - } - else if (T->isArrayType()) { - if (VD->hasGlobalStorage()) // Params cannot have array type. - St = BindArrayToSymVal(St, VR); - else - St = BindArrayToVal(St, VR, UndefinedVal()); - } - else if (T->isStructureType()) { - if (VD->hasGlobalStorage() || isa(VD) || - isa(VD)) - St = BindStructToSymVal(St, VR); - else - St = BindStructToVal(St, VR, UndefinedVal()); - } - } - } + // Other types of variable are not supported yet. return St; } -Store RegionStoreManager::BindDecl(Store store, const VarDecl* VD, - SVal* InitVal, unsigned Count) { - - if (VD->hasGlobalStorage()) { - // Static global variables should not be visited here. - assert(!(VD->getStorageClass() == VarDecl::Static && - VD->isFileVarDecl())); - // Process static variables. - if (VD->getStorageClass() == VarDecl::Static) { - if (!InitVal) { - // Only handle pointer and integer static variables. - - QualType T = VD->getType(); - - if (Loc::IsLocType(T)) - store = Bind(store, getVarLoc(VD), - loc::ConcreteInt(getBasicVals().getValue(0, T))); - - else if (T->isIntegerType()) - store = Bind(store, getVarLoc(VD), - loc::ConcreteInt(getBasicVals().getValue(0, T))); - - // Other types of static local variables are not handled yet. - } else { - store = Bind(store, getVarLoc(VD), *InitVal); - } - } - } else { - // Process local variables. - - QualType T = VD->getType(); - - VarRegion* VR = MRMgr.getVarRegion(VD); - - if (Loc::IsLocType(T) || T->isIntegerType()) { - SVal V = InitVal ? *InitVal : UndefinedVal(); - store = Bind(store, loc::MemRegionVal(VR), V); - } - else if (T->isArrayType()) { - if (!InitVal) - store = BindArrayToVal(store, VR, UndefinedVal()); - else - store = InitializeArray(store, VR, *InitVal); - } - else if (T->isStructureType()) { - if (!InitVal) - store = BindStructToVal(store, VR, UndefinedVal()); - else - store = InitializeStruct(store, VR, *InitVal); - } - - // Other types of local variables are not handled yet. - } - return store; -} - -Store RegionStoreManager::BindCompoundLiteral(Store store, - const CompoundLiteralExpr* CL, - SVal V) { +// FIXME: this method should be merged into Bind(). +const GRState* +RegionStoreManager::BindCompoundLiteral(const GRState* St, + const CompoundLiteralExpr* CL, SVal V) { CompoundLiteralRegion* R = MRMgr.getCompoundLiteralRegion(CL); - store = Bind(store, loc::MemRegionVal(R), V); - return store; + return Bind(St, loc::MemRegionVal(R), V); } const GRState* RegionStoreManager::setExtent(const GRState* St, @@ -781,19 +730,24 @@ void RegionStoreManager::print(Store store, std::ostream& Out, } } -Store RegionStoreManager::InitializeArray(Store store, const TypedRegion* R, - SVal Init) { +const GRState* RegionStoreManager::BindArray(const GRState* St, + const TypedRegion* R, SVal Init) { // FIXME: Verify we should use getLValueType or getRValueType. QualType T = R->getRValueType(getContext()); assert(T->isArrayType()); + // When we are binding the whole array, it always has default value 0. + GRStateRef state(St, StateMgr); + // St = state.set(R, NonLoc::MakeVal(getBasicVals(), 0, + // false)); + + Store store = St->getStore(); + ConstantArrayType* CAT = cast(T.getTypePtr()); llvm::APSInt Size(CAT->getSize(), false); - - llvm::APSInt i = getBasicVals().getValue(0, Size.getBitWidth(), - Size.isUnsigned()); + llvm::APSInt i = getBasicVals().getZeroWithPtrWidth(false); // Check if the init expr is a StringLiteral. if (isa(Init)) { @@ -803,21 +757,21 @@ Store RegionStoreManager::InitializeArray(Store store, const TypedRegion* R, 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(Idx, R); - // 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. - SVal V = (j < len) - ? NonLoc::MakeVal(getBasicVals(), str[j], sizeof(char)*8, true) - : NonLoc::MakeVal(getBasicVals(), 0, sizeof(char)*8, true); - - store = Bind(store, loc::MemRegionVal(ER), V); + SVal V = NonLoc::MakeVal(getBasicVals(), str[j], sizeof(char)*8, true); + St = Bind(St, loc::MemRegionVal(ER), V); } - return store; + return StateMgr.MakeStateWithStore(St, store); } @@ -825,79 +779,25 @@ Store RegionStoreManager::InitializeArray(Store store, const TypedRegion* R, nonloc::CompoundVal::iterator VI = CV.begin(), VE = CV.end(); - for (; i < Size; ++i) { + 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(Idx, R); - - store = Bind(store, loc::MemRegionVal(ER), (VI!=VE) ? *VI : UndefinedVal()); - // The init list might be shorter than the array decl. - if (VI != VE) ++VI; + + if (CAT->getElementType()->isStructureType()) + St = BindStruct(St, ER, *VI); + else + St = Bind(St, Loc::MakeVal(ER), *VI); } - return store; + return StateMgr.MakeStateWithStore(St, store); } -// Bind all elements of the array to some value. -Store RegionStoreManager::BindArrayToVal(Store store, const TypedRegion* BaseR, - SVal V){ - - // FIXME: Verify we want getRValueType. - QualType T = BaseR->getRValueType(getContext()); - assert(T->isArrayType()); - - // Only handle constant size array for now. - if (ConstantArrayType* CAT=dyn_cast(T.getTypePtr())) { - - llvm::APInt Size = CAT->getSize(); - llvm::APInt i = llvm::APInt::getNullValue(Size.getBitWidth()); - - for (; i != Size; ++i) { - nonloc::ConcreteInt Idx(getBasicVals().getValue(llvm::APSInt(i, false))); - - ElementRegion* ER = MRMgr.getElementRegion(Idx, BaseR); - - if (CAT->getElementType()->isStructureType()) - store = BindStructToVal(store, ER, V); - else - store = Bind(store, loc::MemRegionVal(ER), V); - } - } - - return store; -} - -Store RegionStoreManager::BindArrayToSymVal(Store store, - const TypedRegion* BaseR) { - - // FIXME: Verify we want getRValueType. - QualType T = BaseR->getRValueType(getContext()); - assert(T->isArrayType()); - - if (ConstantArrayType* CAT = dyn_cast(T.getTypePtr())) { - llvm::APInt Size = CAT->getSize(); - llvm::APInt i = llvm::APInt::getNullValue(Size.getBitWidth()); - for (; i != Size; ++i) { - nonloc::ConcreteInt Idx(getBasicVals().getValue(llvm::APSInt(i, false))); - - ElementRegion* ER = MRMgr.getElementRegion(Idx, BaseR); - - if (CAT->getElementType()->isStructureType()) { - store = BindStructToSymVal(store, ER); - } - else { - SVal V = SVal::getSymbolValue(getSymbolManager(), BaseR, - &Idx.getValue(), CAT->getElementType()); - store = Bind(store, loc::MemRegionVal(ER), V); - } - } - } - - return store; -} - -Store RegionStoreManager::InitializeStruct(Store store, const TypedRegion* R, - SVal Init) { - +const GRState* +RegionStoreManager::BindStruct(const GRState* St, const TypedRegion* R, SVal V){ // FIXME: Verify that we should use getRValueType or getLValueType. QualType T = R->getRValueType(getContext()); assert(T->isStructureType()); @@ -906,102 +806,35 @@ Store RegionStoreManager::InitializeStruct(Store store, const TypedRegion* R, RecordDecl* RD = RT->getDecl(); assert(RD->isDefinition()); - nonloc::CompoundVal& CV = cast(Init); + nonloc::CompoundVal& CV = cast(V); nonloc::CompoundVal::iterator VI = CV.begin(), VE = CV.end(); RecordDecl::field_iterator FI = RD->field_begin(), FE = RD->field_end(); - for (; FI != FE; ++FI) { + 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); + //St = state.set(R, NonLoc::MakeVal(getBasicVals(), 0, + // false)); + break; + } + QualType FTy = (*FI)->getType(); FieldRegion* FR = MRMgr.getFieldRegion(*FI, R); - if (Loc::IsLocType(FTy) || FTy->isIntegerType()) { - if (VI != VE) { - store = Bind(store, loc::MemRegionVal(FR), *VI); - ++VI; - } else - store = Bind(store, loc::MemRegionVal(FR), UndefinedVal()); - } - else if (FTy->isArrayType()) { - if (VI != VE) { - store = InitializeArray(store, FR, *VI); - ++VI; - } else - store = BindArrayToVal(store, FR, UndefinedVal()); - } - else if (FTy->isStructureType()) { - if (VI != VE) { - store = InitializeStruct(store, FR, *VI); - ++VI; - } else - store = BindStructToVal(store, FR, UndefinedVal()); - } - } - return store; -} - -// Bind all fields of the struct to some value. -Store RegionStoreManager::BindStructToVal(Store store, const TypedRegion* BaseR, - SVal V) { - - // FIXME: Verify that we should use getLValueType or getRValueType. - QualType T = BaseR->getRValueType(getContext()); - assert(T->isStructureType()); - - const RecordType* RT = cast(T.getTypePtr()); - RecordDecl* RD = RT->getDecl(); - assert(RD->isDefinition()); - - RecordDecl::field_iterator I = RD->field_begin(), E = RD->field_end(); - - for (; I != E; ++I) { + if (Loc::IsLocType(FTy) || FTy->isIntegerType()) + St = Bind(St, Loc::MakeVal(FR), *VI); - QualType FTy = (*I)->getType(); - FieldRegion* FR = MRMgr.getFieldRegion(*I, BaseR); - - if (Loc::IsLocType(FTy) || FTy->isIntegerType()) { - store = Bind(store, loc::MemRegionVal(FR), V); + else if (FTy->isArrayType()) + St = BindArray(St, FR, *VI); - } else if (FTy->isArrayType()) { - store = BindArrayToVal(store, FR, V); - - } else if (FTy->isStructureType()) { - store = BindStructToVal(store, FR, V); - } + else if (FTy->isStructureType()) + St = BindStruct(St, FR, *VI); } - return store; -} - -Store RegionStoreManager::BindStructToSymVal(Store store, - const TypedRegion* BaseR) { - - // FIXME: Verify that we should use getLValueType or getRValueType - QualType T = BaseR->getRValueType(getContext()); - assert(T->isStructureType()); - - const RecordType* RT = cast(T.getTypePtr()); - RecordDecl* RD = RT->getDecl(); - assert(RD->isDefinition()); - - RecordDecl::field_iterator I = RD->field_begin(), E = RD->field_end(); - - for (; I != E; ++I) { - QualType FTy = (*I)->getType(); - FieldRegion* FR = MRMgr.getFieldRegion(*I, BaseR); - - if (Loc::IsLocType(FTy) || FTy->isIntegerType()) { - store = Bind(store, loc::MemRegionVal(FR), - SVal::getSymbolValue(getSymbolManager(), BaseR, *I, FTy)); - } - else if (FTy->isArrayType()) { - store = BindArrayToSymVal(store, FR); - } - else if (FTy->isStructureType()) { - store = BindStructToSymVal(store, FR); - } - } - - return store; + return St; } const GRState* RegionStoreManager::AddRegionView(const GRState* St, diff --git a/clang/lib/Analysis/SVals.cpp b/clang/lib/Analysis/SVals.cpp index 3288b74a993a..6cc5e914f40d 100644 --- a/clang/lib/Analysis/SVals.cpp +++ b/clang/lib/Analysis/SVals.cpp @@ -242,6 +242,11 @@ NonLoc Loc::NE(BasicValueFactory& BasicVals, const Loc& R) const { //===----------------------------------------------------------------------===// // Utility methods for constructing Non-Locs. //===----------------------------------------------------------------------===// + +NonLoc NonLoc::MakeVal(SymbolRef sym) { + return nonloc::SymbolVal(sym); +} + NonLoc NonLoc::MakeVal(BasicValueFactory& BasicVals, unsigned X, bool isUnsigned) { return nonloc::ConcreteInt(BasicVals.getValue(X, sizeof(unsigned)*8, @@ -281,6 +286,14 @@ NonLoc NonLoc::MakeCompoundVal(QualType T, llvm::ImmutableList Vals, return nonloc::CompoundVal(BasicVals.getCompoundValData(T, Vals)); } +SVal SVal::MakeSymbolValue(SymbolManager& SymMgr, const MemRegion* R, + QualType T) { + if (Loc::IsLocType(T)) + return Loc::MakeVal(SymMgr.getSymbol(R)); + else + return NonLoc::MakeVal(SymMgr.getSymbol(R)); +} + SVal SVal::GetSymbolValue(SymbolManager& SymMgr, VarDecl* D) { QualType T = D->getType(); @@ -320,6 +333,8 @@ Loc Loc::MakeVal(const MemRegion* R) { return loc::MemRegionVal(R); } Loc Loc::MakeVal(AddrLabelExpr* E) { return loc::GotoLabel(E->getLabel()); } +Loc Loc::MakeVal(SymbolRef sym) { return loc::SymbolVal(sym); } + //===----------------------------------------------------------------------===// // Pretty-Printing. //===----------------------------------------------------------------------===// diff --git a/clang/lib/Analysis/SymbolManager.cpp b/clang/lib/Analysis/SymbolManager.cpp index 1c2814a3afeb..746d55c23cf6 100644 --- a/clang/lib/Analysis/SymbolManager.cpp +++ b/clang/lib/Analysis/SymbolManager.cpp @@ -13,6 +13,7 @@ //===----------------------------------------------------------------------===// #include "clang/Analysis/PathSensitive/SymbolManager.h" +#include "clang/Analysis/PathSensitive/MemRegion.h" #include "llvm/Support/raw_ostream.h" using namespace clang; @@ -21,14 +22,35 @@ void SymbolRef::print(llvm::raw_ostream& os) const { os << getNumber(); } -SymbolRef SymbolManager::getSymbol(VarDecl* D) { +SymbolRef SymbolManager::getSymbol(const MemRegion* R) { + switch (R->getKind()) { + case MemRegion::VarRegionKind: + return getSymbol(cast(R)->getDecl()); + + case MemRegion::ElementRegionKind: { + const ElementRegion* ER = cast(R); + const llvm::APSInt& Idx = + cast(ER->getIndex()).getValue(); + return getElementSymbol(ER->getSuperRegion(), &Idx); + } + + case MemRegion::FieldRegionKind: { + const FieldRegion* FR = cast(R); + return getFieldSymbol(FR->getSuperRegion(), FR->getDecl()); + } + default: + assert(0 && "unprocessed region"); + } +} + +SymbolRef SymbolManager::getSymbol(const VarDecl* D) { assert (isa(D) || isa(D) || D->hasGlobalStorage()); llvm::FoldingSetNodeID profile; - ParmVarDecl* PD = dyn_cast(D); + const ParmVarDecl* PD = dyn_cast(D); if (PD) SymbolDataParmVar::Profile(profile, PD); diff --git a/clang/test/Analysis/null-deref-ps.c b/clang/test/Analysis/null-deref-ps.c index 422c9da0aaf0..8322be18afdf 100644 --- a/clang/test/Analysis/null-deref-ps.c +++ b/clang/test/Analysis/null-deref-ps.c @@ -1,5 +1,5 @@ -// RUN: clang -std=gnu99 -checker-simple -verify %s && -// RUN: clang -std=gnu99 -checker-simple -analyzer-store-region -verify %s +// RUN: clang -std=gnu99 -checker-simple -verify %s +// DISABLE: clang -std=gnu99 -checker-simple -analyzer-store-region -verify %s #include #include diff --git a/clang/test/Analysis/uninit-vals-ps-region.c b/clang/test/Analysis/uninit-vals-ps-region.c index 5d342b5a7443..96da8b0935a7 100644 --- a/clang/test/Analysis/uninit-vals-ps-region.c +++ b/clang/test/Analysis/uninit-vals-ps-region.c @@ -1,4 +1,4 @@ -// RUN: clang -checker-simple -analyzer-store-region -verify %s +// DISABLE: clang -checker-simple -analyzer-store-region -verify %s struct s { int data;