2008-10-08 10:50:44 +08:00
|
|
|
//== RegionStore.cpp - Field-sensitive store model --------------*- C++ -*--==//
|
|
|
|
//
|
|
|
|
// The LLVM Compiler Infrastructure
|
|
|
|
//
|
|
|
|
// This file is distributed under the University of Illinois Open Source
|
|
|
|
// License. See LICENSE.TXT for details.
|
|
|
|
//
|
|
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
//
|
|
|
|
// This file defines a basic region store model. In this model, we do have field
|
|
|
|
// sensitivity. But we assume nothing about the heap shape. So recursive data
|
|
|
|
// structures are largely ignored. Basically we do 1-limiting analysis.
|
|
|
|
// Parameter pointers are assumed with no aliasing. Pointee objects of
|
|
|
|
// parameters are created lazily.
|
|
|
|
//
|
|
|
|
//===----------------------------------------------------------------------===//
|
2010-01-18 16:54:31 +08:00
|
|
|
#include "clang/AST/CharUnits.h"
|
2010-03-16 21:14:16 +08:00
|
|
|
#include "clang/AST/DeclCXX.h"
|
|
|
|
#include "clang/AST/ExprCXX.h"
|
2010-04-10 04:26:58 +08:00
|
|
|
#include "clang/Analysis/Analyses/LiveVariables.h"
|
|
|
|
#include "clang/Analysis/AnalysisContext.h"
|
|
|
|
#include "clang/Basic/TargetInfo.h"
|
2012-01-05 07:54:01 +08:00
|
|
|
#include "clang/StaticAnalyzer/Core/PathSensitive/ObjCMessage.h"
|
2011-08-16 06:09:50 +08:00
|
|
|
#include "clang/StaticAnalyzer/Core/PathSensitive/ProgramState.h"
|
|
|
|
#include "clang/StaticAnalyzer/Core/PathSensitive/ProgramStateTrait.h"
|
2011-02-10 09:03:03 +08:00
|
|
|
#include "clang/StaticAnalyzer/Core/PathSensitive/MemRegion.h"
|
2008-11-16 12:07:26 +08:00
|
|
|
#include "llvm/ADT/ImmutableList.h"
|
2010-04-10 04:26:58 +08:00
|
|
|
#include "llvm/ADT/ImmutableMap.h"
|
|
|
|
#include "llvm/ADT/Optional.h"
|
2008-10-24 14:01:33 +08:00
|
|
|
#include "llvm/Support/raw_ostream.h"
|
2008-10-08 10:50:44 +08:00
|
|
|
|
|
|
|
using namespace clang;
|
2010-12-23 15:20:52 +08:00
|
|
|
using namespace ento;
|
2010-04-10 04:26:58 +08:00
|
|
|
using llvm::Optional;
|
2008-10-08 10:50:44 +08:00
|
|
|
|
2010-01-11 08:07:44 +08:00
|
|
|
//===----------------------------------------------------------------------===//
|
2010-02-03 11:06:46 +08:00
|
|
|
// Representation of binding keys.
|
2010-01-11 08:07:44 +08:00
|
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
|
2009-10-11 16:08:02 +08:00
|
|
|
namespace {
|
2010-02-03 11:06:46 +08:00
|
|
|
class BindingKey {
|
2009-10-11 16:08:02 +08:00
|
|
|
public:
|
2010-02-03 11:06:46 +08:00
|
|
|
enum Kind { Direct = 0x0, Default = 0x1 };
|
2009-10-11 16:08:02 +08:00
|
|
|
private:
|
2010-02-03 11:06:46 +08:00
|
|
|
llvm ::PointerIntPair<const MemRegion*, 1> P;
|
2010-03-10 15:20:03 +08:00
|
|
|
uint64_t Offset;
|
|
|
|
|
2010-02-03 11:06:46 +08:00
|
|
|
explicit BindingKey(const MemRegion *r, uint64_t offset, Kind k)
|
2010-08-16 09:15:17 +08:00
|
|
|
: P(r, (unsigned) k), Offset(offset) {}
|
2009-10-11 16:08:02 +08:00
|
|
|
public:
|
2010-03-10 15:20:03 +08:00
|
|
|
|
2010-02-03 11:06:46 +08:00
|
|
|
bool isDirect() const { return P.getInt() == Direct; }
|
2010-03-10 15:20:03 +08:00
|
|
|
|
2010-02-03 11:06:46 +08:00
|
|
|
const MemRegion *getRegion() const { return P.getPointer(); }
|
|
|
|
uint64_t getOffset() const { return Offset; }
|
2010-03-10 15:20:03 +08:00
|
|
|
|
2009-10-11 16:08:02 +08:00
|
|
|
void Profile(llvm::FoldingSetNodeID& ID) const {
|
2010-02-03 11:06:46 +08:00
|
|
|
ID.AddPointer(P.getOpaqueValue());
|
|
|
|
ID.AddInteger(Offset);
|
2009-10-11 16:08:02 +08:00
|
|
|
}
|
2010-03-10 15:20:03 +08:00
|
|
|
|
2010-02-03 11:06:46 +08:00
|
|
|
static BindingKey Make(const MemRegion *R, Kind k);
|
2010-03-10 15:20:03 +08:00
|
|
|
|
2010-02-03 11:06:46 +08:00
|
|
|
bool operator<(const BindingKey &X) const {
|
|
|
|
if (P.getOpaqueValue() < X.P.getOpaqueValue())
|
|
|
|
return true;
|
|
|
|
if (P.getOpaqueValue() > X.P.getOpaqueValue())
|
|
|
|
return false;
|
|
|
|
return Offset < X.Offset;
|
|
|
|
}
|
2010-03-10 15:20:03 +08:00
|
|
|
|
2010-02-03 11:06:46 +08:00
|
|
|
bool operator==(const BindingKey &X) const {
|
|
|
|
return P.getOpaqueValue() == X.P.getOpaqueValue() &&
|
|
|
|
Offset == X.Offset;
|
2010-01-11 08:07:44 +08:00
|
|
|
}
|
2010-08-16 09:15:17 +08:00
|
|
|
|
2010-08-17 04:53:01 +08:00
|
|
|
bool isValid() const {
|
2010-08-16 09:15:17 +08:00
|
|
|
return getRegion() != NULL;
|
|
|
|
}
|
2010-03-10 15:20:03 +08:00
|
|
|
};
|
2010-01-11 08:07:44 +08:00
|
|
|
} // end anonymous namespace
|
|
|
|
|
2010-08-21 20:24:38 +08:00
|
|
|
BindingKey BindingKey::Make(const MemRegion *R, Kind k) {
|
|
|
|
if (const ElementRegion *ER = dyn_cast<ElementRegion>(R)) {
|
|
|
|
const RegionRawOffset &O = ER->getAsArrayOffset();
|
|
|
|
|
|
|
|
// FIXME: There are some ElementRegions for which we cannot compute
|
|
|
|
// raw offsets yet, including regions with symbolic offsets. These will be
|
|
|
|
// ignored by the store.
|
2011-01-24 09:55:39 +08:00
|
|
|
return BindingKey(O.getRegion(), O.getOffset().getQuantity(), k);
|
2010-08-21 20:24:38 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
return BindingKey(R, 0, k);
|
|
|
|
}
|
|
|
|
|
2010-01-11 08:07:44 +08:00
|
|
|
namespace llvm {
|
2010-03-10 15:20:03 +08:00
|
|
|
static inline
|
2011-08-13 07:37:29 +08:00
|
|
|
raw_ostream &operator<<(raw_ostream &os, BindingKey K) {
|
2010-02-03 11:06:46 +08:00
|
|
|
os << '(' << K.getRegion() << ',' << K.getOffset()
|
|
|
|
<< ',' << (K.isDirect() ? "direct" : "default")
|
|
|
|
<< ')';
|
2010-01-11 08:07:44 +08:00
|
|
|
return os;
|
|
|
|
}
|
|
|
|
} // end llvm namespace
|
|
|
|
|
|
|
|
//===----------------------------------------------------------------------===//
|
2008-11-24 17:44:56 +08:00
|
|
|
// Actual Store type.
|
2010-01-11 08:07:44 +08:00
|
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
|
2010-02-03 11:06:46 +08:00
|
|
|
typedef llvm::ImmutableMap<BindingKey, SVal> RegionBindings;
|
2008-11-24 17:44:56 +08:00
|
|
|
|
2009-06-17 06:36:44 +08:00
|
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
// Fine-grained control of RegionStoreManager.
|
|
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
|
|
|
|
namespace {
|
2009-11-28 14:07:30 +08:00
|
|
|
struct minimal_features_tag {};
|
|
|
|
struct maximal_features_tag {};
|
2009-09-09 23:08:12 +08:00
|
|
|
|
2009-11-28 14:07:30 +08:00
|
|
|
class RegionStoreFeatures {
|
2009-06-17 06:36:44 +08:00
|
|
|
bool SupportsFields;
|
|
|
|
public:
|
|
|
|
RegionStoreFeatures(minimal_features_tag) :
|
2010-08-20 14:06:41 +08:00
|
|
|
SupportsFields(false) {}
|
2009-09-09 23:08:12 +08:00
|
|
|
|
2009-06-17 06:36:44 +08:00
|
|
|
RegionStoreFeatures(maximal_features_tag) :
|
2010-08-20 14:06:41 +08:00
|
|
|
SupportsFields(true) {}
|
2009-09-09 23:08:12 +08:00
|
|
|
|
2009-06-17 06:36:44 +08:00
|
|
|
void enableFields(bool t) { SupportsFields = t; }
|
2009-09-09 23:08:12 +08:00
|
|
|
|
2009-06-17 06:36:44 +08:00
|
|
|
bool supportsFields() const { return SupportsFields; }
|
|
|
|
};
|
|
|
|
}
|
|
|
|
|
2008-12-24 09:05:03 +08:00
|
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
// Main RegionStore logic.
|
|
|
|
//===----------------------------------------------------------------------===//
|
2008-12-04 10:08:27 +08:00
|
|
|
|
2008-10-08 10:50:44 +08:00
|
|
|
namespace {
|
2009-09-09 23:08:12 +08:00
|
|
|
|
2009-11-28 14:07:30 +08:00
|
|
|
class RegionStoreSubRegionMap : public SubRegionMap {
|
2010-02-03 06:38:47 +08:00
|
|
|
public:
|
|
|
|
typedef llvm::ImmutableSet<const MemRegion*> Set;
|
|
|
|
typedef llvm::DenseMap<const MemRegion*, Set> Map;
|
|
|
|
private:
|
|
|
|
Set::Factory F;
|
2009-03-03 09:35:36 +08:00
|
|
|
Map M;
|
|
|
|
public:
|
2009-08-06 03:09:24 +08:00
|
|
|
bool add(const MemRegion* Parent, const MemRegion* SubRegion) {
|
2009-03-03 09:35:36 +08:00
|
|
|
Map::iterator I = M.find(Parent);
|
2009-08-06 03:09:24 +08:00
|
|
|
|
|
|
|
if (I == M.end()) {
|
2010-11-24 08:54:37 +08:00
|
|
|
M.insert(std::make_pair(Parent, F.add(F.getEmptySet(), SubRegion)));
|
2009-08-06 03:09:24 +08:00
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
2010-11-24 08:54:37 +08:00
|
|
|
I->second = F.add(I->second, SubRegion);
|
2009-08-06 03:09:24 +08:00
|
|
|
return false;
|
2009-03-03 09:35:36 +08:00
|
|
|
}
|
2009-09-09 23:08:12 +08:00
|
|
|
|
2011-07-23 18:55:15 +08:00
|
|
|
void process(SmallVectorImpl<const SubRegion*> &WL, const SubRegion *R);
|
2009-09-09 23:08:12 +08:00
|
|
|
|
2009-03-03 09:35:36 +08:00
|
|
|
~RegionStoreSubRegionMap() {}
|
2010-03-10 15:20:03 +08:00
|
|
|
|
2010-02-03 06:38:47 +08:00
|
|
|
const Set *getSubRegions(const MemRegion *Parent) const {
|
|
|
|
Map::const_iterator I = M.find(Parent);
|
|
|
|
return I == M.end() ? NULL : &I->second;
|
|
|
|
}
|
2009-09-09 23:08:12 +08:00
|
|
|
|
2009-03-03 10:51:43 +08:00
|
|
|
bool iterSubRegions(const MemRegion* Parent, Visitor& V) const {
|
2009-11-10 09:17:45 +08:00
|
|
|
Map::const_iterator I = M.find(Parent);
|
2009-03-03 09:35:36 +08:00
|
|
|
|
|
|
|
if (I == M.end())
|
2009-03-03 10:51:43 +08:00
|
|
|
return true;
|
2009-09-09 23:08:12 +08:00
|
|
|
|
2010-02-03 06:38:47 +08:00
|
|
|
Set S = I->second;
|
|
|
|
for (Set::iterator SI=S.begin(),SE=S.end(); SI != SE; ++SI) {
|
2009-03-03 09:35:36 +08:00
|
|
|
if (!V.Visit(Parent, *SI))
|
2009-03-03 10:51:43 +08:00
|
|
|
return false;
|
2009-03-03 09:35:36 +08:00
|
|
|
}
|
2009-09-09 23:08:12 +08:00
|
|
|
|
2009-03-03 10:51:43 +08:00
|
|
|
return true;
|
2009-03-03 09:35:36 +08:00
|
|
|
}
|
2009-09-09 23:08:12 +08:00
|
|
|
};
|
2009-03-03 09:35:36 +08:00
|
|
|
|
2010-08-23 09:37:32 +08:00
|
|
|
void
|
2011-07-23 18:55:15 +08:00
|
|
|
RegionStoreSubRegionMap::process(SmallVectorImpl<const SubRegion*> &WL,
|
2010-08-23 09:37:32 +08:00
|
|
|
const SubRegion *R) {
|
|
|
|
const MemRegion *superR = R->getSuperRegion();
|
|
|
|
if (add(superR, R))
|
|
|
|
if (const SubRegion *sr = dyn_cast<SubRegion>(superR))
|
|
|
|
WL.push_back(sr);
|
|
|
|
}
|
2010-03-10 15:20:03 +08:00
|
|
|
|
2009-11-28 14:07:30 +08:00
|
|
|
class RegionStoreManager : public StoreManager {
|
2009-06-17 06:36:44 +08:00
|
|
|
const RegionStoreFeatures Features;
|
2009-08-06 12:50:20 +08:00
|
|
|
RegionBindings::Factory RBFactory;
|
2010-03-10 15:20:03 +08:00
|
|
|
|
2008-10-08 10:50:44 +08:00
|
|
|
public:
|
2011-08-16 06:09:50 +08:00
|
|
|
RegionStoreManager(ProgramStateManager& mgr, const RegionStoreFeatures &f)
|
2009-07-30 05:43:22 +08:00
|
|
|
: StoreManager(mgr),
|
2009-06-17 06:36:44 +08:00
|
|
|
Features(f),
|
2010-02-04 12:14:49 +08:00
|
|
|
RBFactory(mgr.getAllocator()) {}
|
2008-10-08 10:50:44 +08:00
|
|
|
|
2010-02-05 13:18:47 +08:00
|
|
|
SubRegionMap *getSubRegionMap(Store store) {
|
|
|
|
return getRegionStoreSubRegionMap(store);
|
|
|
|
}
|
2009-09-09 23:08:12 +08:00
|
|
|
|
2009-10-11 16:08:02 +08:00
|
|
|
RegionStoreSubRegionMap *getRegionStoreSubRegionMap(Store store);
|
2009-09-09 23:08:12 +08:00
|
|
|
|
2009-10-11 16:08:02 +08:00
|
|
|
Optional<SVal> getDirectBinding(RegionBindings B, const MemRegion *R);
|
2009-08-07 05:43:54 +08:00
|
|
|
/// getDefaultBinding - Returns an SVal* representing an optional default
|
|
|
|
/// binding associated with a region and its subregions.
|
2009-10-11 16:08:02 +08:00
|
|
|
Optional<SVal> getDefaultBinding(RegionBindings B, const MemRegion *R);
|
2010-03-10 15:20:03 +08:00
|
|
|
|
2009-11-20 04:20:24 +08:00
|
|
|
/// setImplicitDefaultValue - Set the default binding for the provided
|
|
|
|
/// MemRegion to the value implicitly defined for compound literals when
|
2010-03-10 15:20:03 +08:00
|
|
|
/// the value is not specified.
|
2011-02-19 09:59:33 +08:00
|
|
|
StoreRef setImplicitDefaultValue(Store store, const MemRegion *R, QualType T);
|
2009-09-09 23:08:12 +08:00
|
|
|
|
2008-12-24 15:46:32 +08:00
|
|
|
/// 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
|
|
|
|
/// version of that lvalue (i.e., a pointer to the first element of
|
2010-12-23 02:53:44 +08:00
|
|
|
/// the array). This is called by ExprEngine when evaluating
|
2008-12-24 15:46:32 +08:00
|
|
|
/// casts from arrays to pointers.
|
2009-03-30 13:55:46 +08:00
|
|
|
SVal ArrayToPointer(Loc Array);
|
2008-10-24 09:09:32 +08:00
|
|
|
|
2010-11-26 16:21:53 +08:00
|
|
|
/// For DerivedToBase casts, create a CXXBaseObjectRegion and return it.
|
|
|
|
virtual SVal evalDerivedToBase(SVal derived, QualType basePtrType);
|
|
|
|
|
2012-04-11 04:59:00 +08:00
|
|
|
/// \brief Evaluates C++ dynamic_cast cast.
|
|
|
|
/// The callback may result in the following 3 scenarios:
|
|
|
|
/// - Successful cast (ex: derived is subclass of base).
|
|
|
|
/// - Failed cast (ex: derived is definitely not a subclass of base).
|
|
|
|
/// - We don't know (base is a symbolic region and we don't have
|
|
|
|
/// enough info to determine if the cast will succeed at run time).
|
|
|
|
/// The function returns an SVal representing the derived class; it's
|
|
|
|
/// valid only if Failed flag is set to false.
|
|
|
|
virtual SVal evalDynamicCast(SVal base, QualType derivedPtrType,bool &Failed);
|
|
|
|
|
2011-02-19 09:59:33 +08:00
|
|
|
StoreRef getInitialStore(const LocationContext *InitLoc) {
|
|
|
|
return StoreRef(RBFactory.getEmptyMap().getRootWithoutRetain(), *this);
|
2009-08-17 14:19:58 +08:00
|
|
|
}
|
2009-08-22 07:25:54 +08:00
|
|
|
|
2009-06-18 06:02:04 +08:00
|
|
|
//===-------------------------------------------------------------------===//
|
|
|
|
// Binding values to regions.
|
|
|
|
//===-------------------------------------------------------------------===//
|
2012-01-05 07:54:01 +08:00
|
|
|
RegionBindings invalidateGlobalRegion(MemRegion::Kind K,
|
|
|
|
const Expr *Ex,
|
|
|
|
unsigned Count,
|
2012-02-18 07:13:45 +08:00
|
|
|
const LocationContext *LCtx,
|
2012-01-05 07:54:01 +08:00
|
|
|
RegionBindings B,
|
|
|
|
InvalidatedRegions *Invalidated);
|
2008-12-20 14:32:12 +08:00
|
|
|
|
2011-08-28 06:51:26 +08:00
|
|
|
StoreRef invalidateRegions(Store store, ArrayRef<const MemRegion *> Regions,
|
2011-02-19 09:59:33 +08:00
|
|
|
const Expr *E, unsigned Count,
|
2012-02-18 07:13:45 +08:00
|
|
|
const LocationContext *LCtx,
|
2011-05-03 03:42:42 +08:00
|
|
|
InvalidatedSymbols &IS,
|
2012-01-05 07:54:01 +08:00
|
|
|
const CallOrObjCMessage *Call,
|
2011-08-28 06:51:26 +08:00
|
|
|
InvalidatedRegions *Invalidated);
|
2009-09-09 23:08:12 +08:00
|
|
|
|
2010-02-03 11:06:46 +08:00
|
|
|
public: // Made public for helper classes.
|
2010-03-10 15:20:03 +08:00
|
|
|
|
2009-10-11 16:08:02 +08:00
|
|
|
void RemoveSubRegionBindings(RegionBindings &B, const MemRegion *R,
|
2009-08-06 09:20:57 +08:00
|
|
|
RegionStoreSubRegionMap &M);
|
2009-09-09 23:08:12 +08:00
|
|
|
|
2010-11-24 08:54:37 +08:00
|
|
|
RegionBindings addBinding(RegionBindings B, BindingKey K, SVal V);
|
2010-02-03 11:06:46 +08:00
|
|
|
|
2010-11-24 08:54:37 +08:00
|
|
|
RegionBindings addBinding(RegionBindings B, const MemRegion *R,
|
2010-02-03 11:06:46 +08:00
|
|
|
BindingKey::Kind k, SVal V);
|
2010-03-10 15:20:03 +08:00
|
|
|
|
2010-11-24 08:54:37 +08:00
|
|
|
const SVal *lookup(RegionBindings B, BindingKey K);
|
|
|
|
const SVal *lookup(RegionBindings B, const MemRegion *R, BindingKey::Kind k);
|
2010-01-11 08:07:44 +08:00
|
|
|
|
2010-11-24 08:54:37 +08:00
|
|
|
RegionBindings removeBinding(RegionBindings B, BindingKey K);
|
|
|
|
RegionBindings removeBinding(RegionBindings B, const MemRegion *R,
|
2010-02-03 11:06:46 +08:00
|
|
|
BindingKey::Kind k);
|
2010-03-10 15:20:03 +08:00
|
|
|
|
2010-11-24 08:54:37 +08:00
|
|
|
RegionBindings removeBinding(RegionBindings B, const MemRegion *R) {
|
|
|
|
return removeBinding(removeBinding(B, R, BindingKey::Direct), R,
|
|
|
|
BindingKey::Default);
|
2010-03-10 15:20:03 +08:00
|
|
|
}
|
2010-02-03 11:06:46 +08:00
|
|
|
|
|
|
|
public: // Part of public interface to class.
|
|
|
|
|
2011-02-19 09:59:33 +08:00
|
|
|
StoreRef Bind(Store store, Loc LV, SVal V);
|
2008-10-21 13:29:26 +08:00
|
|
|
|
2010-06-01 12:49:26 +08:00
|
|
|
// BindDefault is only used to initialize a region with a default value.
|
2011-02-19 09:59:33 +08:00
|
|
|
StoreRef BindDefault(Store store, const MemRegion *R, SVal V) {
|
2010-06-01 12:49:26 +08:00
|
|
|
RegionBindings B = GetRegionBindings(store);
|
2010-11-24 08:54:37 +08:00
|
|
|
assert(!lookup(B, R, BindingKey::Default));
|
|
|
|
assert(!lookup(B, R, BindingKey::Direct));
|
2012-01-12 10:22:40 +08:00
|
|
|
return StoreRef(addBinding(B, R, BindingKey::Default, V)
|
|
|
|
.getRootWithoutRetain(), *this);
|
2010-06-01 11:01:33 +08:00
|
|
|
}
|
|
|
|
|
2011-08-13 07:37:29 +08:00
|
|
|
StoreRef BindCompoundLiteral(Store store, const CompoundLiteralExpr *CL,
|
2011-02-19 09:59:33 +08:00
|
|
|
const LocationContext *LC, SVal V);
|
2009-09-09 23:08:12 +08:00
|
|
|
|
2011-02-19 09:59:33 +08:00
|
|
|
StoreRef BindDecl(Store store, const VarRegion *VR, SVal InitVal);
|
2008-11-24 17:44:56 +08:00
|
|
|
|
2011-02-19 09:59:33 +08:00
|
|
|
StoreRef BindDeclWithNoInit(Store store, const VarRegion *) {
|
|
|
|
return StoreRef(store, *this);
|
2008-10-08 10:50:44 +08:00
|
|
|
}
|
2008-10-24 09:38:55 +08:00
|
|
|
|
2009-06-18 06:02:04 +08:00
|
|
|
/// BindStruct - Bind a compound value to a structure.
|
2011-08-13 04:02:48 +08:00
|
|
|
StoreRef BindStruct(Store store, const TypedValueRegion* R, SVal V);
|
2009-09-09 23:08:12 +08:00
|
|
|
|
2011-08-13 04:02:48 +08:00
|
|
|
StoreRef BindArray(Store store, const TypedValueRegion* R, SVal V);
|
2009-09-09 23:08:12 +08:00
|
|
|
|
|
|
|
/// KillStruct - Set the entire struct to unknown.
|
2011-02-19 09:59:33 +08:00
|
|
|
StoreRef KillStruct(Store store, const TypedRegion* R, SVal DefaultVal);
|
2008-10-24 09:38:55 +08:00
|
|
|
|
2011-02-19 09:59:33 +08:00
|
|
|
StoreRef Remove(Store store, Loc LV);
|
2010-03-10 15:20:03 +08:00
|
|
|
|
2011-02-19 09:59:33 +08:00
|
|
|
void incrementReferenceCount(Store store) {
|
|
|
|
GetRegionBindings(store).manualRetain();
|
|
|
|
}
|
|
|
|
|
|
|
|
/// If the StoreManager supports it, decrement the reference count of
|
|
|
|
/// the specified Store object. If the reference count hits 0, the memory
|
|
|
|
/// associated with the object is recycled.
|
|
|
|
void decrementReferenceCount(Store store) {
|
|
|
|
GetRegionBindings(store).manualRelease();
|
|
|
|
}
|
2011-07-29 07:07:46 +08:00
|
|
|
|
|
|
|
bool includedInBindings(Store store, const MemRegion *region) const;
|
2009-06-18 06:02:04 +08:00
|
|
|
|
2012-01-12 10:22:40 +08:00
|
|
|
/// \brief Return the value bound to specified location in a given state.
|
|
|
|
///
|
2009-06-18 06:02:04 +08:00
|
|
|
/// The high level logic for this method is this:
|
2012-01-12 10:22:40 +08:00
|
|
|
/// getBinding (L)
|
2009-06-18 06:02:04 +08:00
|
|
|
/// 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
|
2012-01-12 10:22:40 +08:00
|
|
|
SVal getBinding(Store store, Loc L, QualType T = QualType());
|
2009-06-25 12:50:44 +08:00
|
|
|
|
2012-01-12 10:22:40 +08:00
|
|
|
SVal getBindingForElement(Store store, const ElementRegion *R);
|
2009-06-25 13:29:39 +08:00
|
|
|
|
2012-01-12 10:22:40 +08:00
|
|
|
SVal getBindingForField(Store store, const FieldRegion *R);
|
2009-09-09 23:08:12 +08:00
|
|
|
|
2012-01-12 10:22:40 +08:00
|
|
|
SVal getBindingForObjCIvar(Store store, const ObjCIvarRegion *R);
|
2009-09-09 23:08:12 +08:00
|
|
|
|
2012-01-12 10:22:40 +08:00
|
|
|
SVal getBindingForVar(Store store, const VarRegion *R);
|
2009-09-09 23:08:12 +08:00
|
|
|
|
2012-01-12 10:22:40 +08:00
|
|
|
SVal getBindingForLazySymbol(const TypedValueRegion *R);
|
2009-09-09 23:08:12 +08:00
|
|
|
|
2012-01-12 10:22:40 +08:00
|
|
|
SVal getBindingForFieldOrElementCommon(Store store, const TypedValueRegion *R,
|
|
|
|
QualType Ty, const MemRegion *superR);
|
2011-03-17 11:51:51 +08:00
|
|
|
|
2012-01-12 10:22:40 +08:00
|
|
|
SVal getLazyBinding(const MemRegion *lazyBindingRegion,
|
|
|
|
Store lazyBindingStore);
|
2009-09-09 23:08:12 +08:00
|
|
|
|
2012-01-12 10:22:40 +08:00
|
|
|
/// Get bindings for the values in a struct and return a CompoundVal, used
|
|
|
|
/// when doing struct copy:
|
2009-09-09 23:08:12 +08:00
|
|
|
/// struct s x, y;
|
2008-12-04 09:12:41 +08:00
|
|
|
/// x = y;
|
|
|
|
/// y's value is retrieved by this method.
|
2012-01-12 10:22:40 +08:00
|
|
|
SVal getBindingForStruct(Store store, const TypedValueRegion* R);
|
2009-09-09 23:08:12 +08:00
|
|
|
|
2012-01-12 10:22:40 +08:00
|
|
|
SVal getBindingForArray(Store store, const TypedValueRegion* R);
|
2009-09-09 23:08:12 +08:00
|
|
|
|
2010-07-02 04:16:50 +08:00
|
|
|
/// Used to lazily generate derived symbols for bindings that are defined
|
|
|
|
/// implicitly by default bindings in a super region.
|
2012-01-12 10:22:40 +08:00
|
|
|
Optional<SVal> getBindingForDerivedDefaultValue(RegionBindings B,
|
|
|
|
const MemRegion *superR,
|
|
|
|
const TypedValueRegion *R,
|
|
|
|
QualType Ty);
|
2010-07-02 04:16:50 +08:00
|
|
|
|
2009-12-21 14:52:24 +08:00
|
|
|
/// Get the state and region whose binding this region R corresponds to.
|
2010-02-05 10:26:30 +08:00
|
|
|
std::pair<Store, const MemRegion*>
|
2011-04-03 12:09:15 +08:00
|
|
|
GetLazyBinding(RegionBindings B, const MemRegion *R,
|
|
|
|
const MemRegion *originalRegion);
|
2009-09-09 23:08:12 +08:00
|
|
|
|
2011-02-19 09:59:33 +08:00
|
|
|
StoreRef CopyLazyBindings(nonloc::LazyCompoundVal V, Store store,
|
|
|
|
const TypedRegion *R);
|
2008-12-04 09:12:41 +08:00
|
|
|
|
2009-06-18 06:02:04 +08:00
|
|
|
//===------------------------------------------------------------------===//
|
|
|
|
// State pruning.
|
|
|
|
//===------------------------------------------------------------------===//
|
2009-09-09 23:08:12 +08:00
|
|
|
|
2011-01-15 04:34:15 +08:00
|
|
|
/// removeDeadBindings - Scans the RegionStore of 'state' for dead values.
|
2009-06-18 06:02:04 +08:00
|
|
|
/// It returns a new Store with these values removed.
|
2011-02-19 09:59:33 +08:00
|
|
|
StoreRef removeDeadBindings(Store store, const StackFrameContext *LCtx,
|
2011-08-06 08:29:57 +08:00
|
|
|
SymbolReaper& SymReaper);
|
2009-05-03 08:27:40 +08:00
|
|
|
|
2012-01-27 05:29:00 +08:00
|
|
|
StoreRef enterStackFrame(ProgramStateRef state,
|
2012-01-13 03:25:46 +08:00
|
|
|
const LocationContext *callerCtx,
|
|
|
|
const StackFrameContext *calleeCtx);
|
2009-10-13 10:24:55 +08:00
|
|
|
|
2009-06-18 06:02:04 +08:00
|
|
|
//===------------------------------------------------------------------===//
|
|
|
|
// Region "extents".
|
|
|
|
//===------------------------------------------------------------------===//
|
2009-09-09 23:08:12 +08:00
|
|
|
|
2010-07-04 08:00:41 +08:00
|
|
|
// FIXME: This method will soon be eliminated; see the note in Store.h.
|
2012-01-27 05:29:00 +08:00
|
|
|
DefinedOrUnknownSVal getSizeInElements(ProgramStateRef state,
|
2010-01-18 16:54:31 +08:00
|
|
|
const MemRegion* R, QualType EleTy);
|
2008-11-23 12:30:35 +08:00
|
|
|
|
2009-06-18 06:02:04 +08:00
|
|
|
//===------------------------------------------------------------------===//
|
2008-10-31 15:16:08 +08:00
|
|
|
// Utility methods.
|
2009-06-18 06:02:04 +08:00
|
|
|
//===------------------------------------------------------------------===//
|
2009-09-09 23:08:12 +08:00
|
|
|
|
2009-08-06 12:50:20 +08:00
|
|
|
static inline RegionBindings GetRegionBindings(Store store) {
|
2009-10-11 16:08:02 +08:00
|
|
|
return RegionBindings(static_cast<const RegionBindings::TreeTy*>(store));
|
2009-06-18 06:02:04 +08:00
|
|
|
}
|
|
|
|
|
2011-08-13 07:37:29 +08:00
|
|
|
void print(Store store, raw_ostream &Out, const char* nl,
|
2009-06-25 07:06:47 +08:00
|
|
|
const char *sep);
|
2009-05-08 09:33:18 +08:00
|
|
|
|
2009-06-18 06:02:04 +08:00
|
|
|
void iterBindings(Store store, BindingsHandler& f) {
|
2010-06-17 08:24:42 +08:00
|
|
|
RegionBindings B = GetRegionBindings(store);
|
|
|
|
for (RegionBindings::iterator I=B.begin(), E=B.end(); I!=E; ++I) {
|
|
|
|
const BindingKey &K = I.getKey();
|
|
|
|
if (!K.isDirect())
|
|
|
|
continue;
|
|
|
|
if (const SubRegion *R = dyn_cast<SubRegion>(I.getKey().getRegion())) {
|
|
|
|
// FIXME: Possibly incorporate the offset?
|
|
|
|
if (!f.HandleBinding(*this, store, R, I.getData()))
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
}
|
2009-06-18 06:02:04 +08:00
|
|
|
}
|
2008-10-08 10:50:44 +08:00
|
|
|
};
|
|
|
|
|
|
|
|
} // end anonymous namespace
|
|
|
|
|
2009-06-17 06:36:44 +08:00
|
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
// RegionStore creation.
|
|
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
|
2011-08-16 06:09:50 +08:00
|
|
|
StoreManager *ento::CreateRegionStoreManager(ProgramStateManager& StMgr) {
|
2009-06-17 06:36:44 +08:00
|
|
|
RegionStoreFeatures F = maximal_features_tag();
|
|
|
|
return new RegionStoreManager(StMgr, F);
|
|
|
|
}
|
|
|
|
|
2012-01-12 10:22:40 +08:00
|
|
|
StoreManager *
|
|
|
|
ento::CreateFieldsOnlyRegionStoreManager(ProgramStateManager &StMgr) {
|
2009-06-17 06:36:44 +08:00
|
|
|
RegionStoreFeatures F = minimal_features_tag();
|
|
|
|
F.enableFields(true);
|
|
|
|
return new RegionStoreManager(StMgr, F);
|
2008-10-24 09:04:59 +08:00
|
|
|
}
|
|
|
|
|
2009-08-06 09:20:57 +08:00
|
|
|
|
2009-08-01 14:17:29 +08:00
|
|
|
RegionStoreSubRegionMap*
|
2009-10-11 16:08:02 +08:00
|
|
|
RegionStoreManager::getRegionStoreSubRegionMap(Store store) {
|
|
|
|
RegionBindings B = GetRegionBindings(store);
|
2009-03-03 09:35:36 +08:00
|
|
|
RegionStoreSubRegionMap *M = new RegionStoreSubRegionMap();
|
2009-09-09 23:08:12 +08:00
|
|
|
|
2011-07-23 18:55:15 +08:00
|
|
|
SmallVector<const SubRegion*, 10> WL;
|
2009-08-01 14:17:29 +08:00
|
|
|
|
2009-08-06 12:50:20 +08:00
|
|
|
for (RegionBindings::iterator I=B.begin(), E=B.end(); I!=E; ++I)
|
2010-01-11 08:07:44 +08:00
|
|
|
if (const SubRegion *R = dyn_cast<SubRegion>(I.getKey().getRegion()))
|
2009-08-06 09:20:57 +08:00
|
|
|
M->process(WL, R);
|
2009-09-09 23:08:12 +08:00
|
|
|
|
|
|
|
// We also need to record in the subregion map "intermediate" regions that
|
2009-08-01 14:17:29 +08:00
|
|
|
// don't have direct bindings but are super regions of those that do.
|
|
|
|
while (!WL.empty()) {
|
|
|
|
const SubRegion *R = WL.back();
|
|
|
|
WL.pop_back();
|
2009-08-06 09:20:57 +08:00
|
|
|
M->process(WL, R);
|
2009-08-01 14:17:29 +08:00
|
|
|
}
|
|
|
|
|
2009-03-04 03:02:42 +08:00
|
|
|
return M;
|
2009-03-03 09:35:36 +08:00
|
|
|
}
|
2008-12-24 15:46:32 +08:00
|
|
|
|
2010-03-10 15:19:59 +08:00
|
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
// Region Cluster analysis.
|
|
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
|
|
|
|
namespace {
|
2010-03-11 00:32:56 +08:00
|
|
|
template <typename DERIVED>
|
2010-03-10 15:19:59 +08:00
|
|
|
class ClusterAnalysis {
|
|
|
|
protected:
|
|
|
|
typedef BumpVector<BindingKey> RegionCluster;
|
|
|
|
typedef llvm::DenseMap<const MemRegion *, RegionCluster *> ClusterMap;
|
2010-03-11 00:32:56 +08:00
|
|
|
llvm::DenseMap<const RegionCluster*, unsigned> Visited;
|
2011-07-23 18:55:15 +08:00
|
|
|
typedef SmallVector<std::pair<const MemRegion *, RegionCluster*>, 10>
|
2010-03-11 00:32:56 +08:00
|
|
|
WorkList;
|
2010-03-10 15:19:59 +08:00
|
|
|
|
|
|
|
BumpVectorContext BVC;
|
|
|
|
ClusterMap ClusterM;
|
2010-03-11 00:32:56 +08:00
|
|
|
WorkList WL;
|
2010-03-10 15:19:59 +08:00
|
|
|
|
|
|
|
RegionStoreManager &RM;
|
|
|
|
ASTContext &Ctx;
|
2010-12-02 15:49:45 +08:00
|
|
|
SValBuilder &svalBuilder;
|
2010-03-10 15:19:59 +08:00
|
|
|
|
2010-03-11 00:32:56 +08:00
|
|
|
RegionBindings B;
|
2010-10-26 08:06:15 +08:00
|
|
|
|
|
|
|
const bool includeGlobals;
|
2010-03-11 00:32:56 +08:00
|
|
|
|
2010-03-10 15:19:59 +08:00
|
|
|
public:
|
2011-08-16 06:09:50 +08:00
|
|
|
ClusterAnalysis(RegionStoreManager &rm, ProgramStateManager &StateMgr,
|
2010-10-26 08:06:15 +08:00
|
|
|
RegionBindings b, const bool includeGlobals)
|
2010-12-02 15:49:45 +08:00
|
|
|
: RM(rm), Ctx(StateMgr.getContext()),
|
|
|
|
svalBuilder(StateMgr.getSValBuilder()),
|
2010-10-26 08:06:15 +08:00
|
|
|
B(b), includeGlobals(includeGlobals) {}
|
2010-03-11 00:32:56 +08:00
|
|
|
|
|
|
|
RegionBindings getRegionBindings() const { return B; }
|
|
|
|
|
2010-07-02 04:16:50 +08:00
|
|
|
RegionCluster &AddToCluster(BindingKey K) {
|
2010-03-11 00:32:56 +08:00
|
|
|
const MemRegion *R = K.getRegion();
|
|
|
|
const MemRegion *baseR = R->getBaseRegion();
|
|
|
|
RegionCluster &C = getCluster(baseR);
|
|
|
|
C.push_back(K, BVC);
|
|
|
|
static_cast<DERIVED*>(this)->VisitAddedToCluster(baseR, C);
|
2010-07-02 04:16:50 +08:00
|
|
|
return C;
|
2010-03-11 00:32:56 +08:00
|
|
|
}
|
2010-03-10 15:19:59 +08:00
|
|
|
|
2010-03-11 00:32:56 +08:00
|
|
|
bool isVisited(const MemRegion *R) {
|
|
|
|
return (bool) Visited[&getCluster(R->getBaseRegion())];
|
|
|
|
}
|
2010-03-10 15:19:59 +08:00
|
|
|
|
2010-03-11 00:32:56 +08:00
|
|
|
RegionCluster& getCluster(const MemRegion *R) {
|
|
|
|
RegionCluster *&CRef = ClusterM[R];
|
|
|
|
if (!CRef) {
|
|
|
|
void *Mem = BVC.getAllocator().template Allocate<RegionCluster>();
|
|
|
|
CRef = new (Mem) RegionCluster(BVC, 10);
|
|
|
|
}
|
|
|
|
return *CRef;
|
|
|
|
}
|
2010-03-10 15:19:59 +08:00
|
|
|
|
2010-10-26 08:06:15 +08:00
|
|
|
void GenerateClusters() {
|
2010-03-11 00:32:56 +08:00
|
|
|
// Scan the entire set of bindings and make the region clusters.
|
|
|
|
for (RegionBindings::iterator RI = B.begin(), RE = B.end(); RI != RE; ++RI){
|
2010-07-02 04:16:50 +08:00
|
|
|
RegionCluster &C = AddToCluster(RI.getKey());
|
2010-03-11 00:32:56 +08:00
|
|
|
if (const MemRegion *R = RI.getData().getAsRegion()) {
|
|
|
|
// Generate a cluster, but don't add the region to the cluster
|
|
|
|
// if there aren't any bindings.
|
|
|
|
getCluster(R->getBaseRegion());
|
|
|
|
}
|
2010-07-02 04:16:50 +08:00
|
|
|
if (includeGlobals) {
|
|
|
|
const MemRegion *R = RI.getKey().getRegion();
|
|
|
|
if (isa<NonStaticGlobalSpaceRegion>(R->getMemorySpace()))
|
|
|
|
AddToWorkList(R, C);
|
|
|
|
}
|
2010-03-11 00:32:56 +08:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
bool AddToWorkList(const MemRegion *R, RegionCluster &C) {
|
|
|
|
if (unsigned &visited = Visited[&C])
|
|
|
|
return false;
|
|
|
|
else
|
|
|
|
visited = 1;
|
|
|
|
|
|
|
|
WL.push_back(std::make_pair(R, &C));
|
|
|
|
return true;
|
2010-03-10 15:19:59 +08:00
|
|
|
}
|
|
|
|
|
2010-03-11 00:32:56 +08:00
|
|
|
bool AddToWorkList(BindingKey K) {
|
|
|
|
return AddToWorkList(K.getRegion());
|
|
|
|
}
|
|
|
|
|
|
|
|
bool AddToWorkList(const MemRegion *R) {
|
|
|
|
const MemRegion *baseR = R->getBaseRegion();
|
|
|
|
return AddToWorkList(baseR, getCluster(baseR));
|
|
|
|
}
|
|
|
|
|
|
|
|
void RunWorkList() {
|
|
|
|
while (!WL.empty()) {
|
|
|
|
const MemRegion *baseR;
|
|
|
|
RegionCluster *C;
|
|
|
|
llvm::tie(baseR, C) = WL.back();
|
|
|
|
WL.pop_back();
|
|
|
|
|
|
|
|
// First visit the cluster.
|
|
|
|
static_cast<DERIVED*>(this)->VisitCluster(baseR, C->begin(), C->end());
|
|
|
|
|
2010-04-01 08:15:55 +08:00
|
|
|
// Next, visit the base region.
|
|
|
|
static_cast<DERIVED*>(this)->VisitBaseRegion(baseR);
|
2010-03-10 15:19:59 +08:00
|
|
|
}
|
|
|
|
}
|
2010-03-11 00:32:56 +08:00
|
|
|
|
|
|
|
public:
|
|
|
|
void VisitAddedToCluster(const MemRegion *baseR, RegionCluster &C) {}
|
|
|
|
void VisitCluster(const MemRegion *baseR, BindingKey *I, BindingKey *E) {}
|
2010-04-01 08:15:55 +08:00
|
|
|
void VisitBaseRegion(const MemRegion *baseR) {}
|
2010-03-11 00:32:56 +08:00
|
|
|
};
|
2010-03-10 15:19:59 +08:00
|
|
|
}
|
|
|
|
|
2009-07-30 02:16:25 +08:00
|
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
// Binding invalidation.
|
|
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
|
2009-10-11 16:08:02 +08:00
|
|
|
void RegionStoreManager::RemoveSubRegionBindings(RegionBindings &B,
|
|
|
|
const MemRegion *R,
|
|
|
|
RegionStoreSubRegionMap &M) {
|
2010-03-10 15:19:59 +08:00
|
|
|
|
2010-02-03 06:38:47 +08:00
|
|
|
if (const RegionStoreSubRegionMap::Set *S = M.getSubRegions(R))
|
|
|
|
for (RegionStoreSubRegionMap::Set::iterator I = S->begin(), E = S->end();
|
|
|
|
I != E; ++I)
|
|
|
|
RemoveSubRegionBindings(B, *I, M);
|
2010-03-10 15:19:59 +08:00
|
|
|
|
2010-11-24 08:54:37 +08:00
|
|
|
B = removeBinding(B, R);
|
2009-08-01 14:17:29 +08:00
|
|
|
}
|
|
|
|
|
2010-02-03 11:06:46 +08:00
|
|
|
namespace {
|
2011-02-12 03:48:15 +08:00
|
|
|
class invalidateRegionsWorker : public ClusterAnalysis<invalidateRegionsWorker>
|
2010-03-11 00:32:56 +08:00
|
|
|
{
|
|
|
|
const Expr *Ex;
|
|
|
|
unsigned Count;
|
2012-02-18 07:13:45 +08:00
|
|
|
const LocationContext *LCtx;
|
2011-05-03 03:42:42 +08:00
|
|
|
StoreManager::InvalidatedSymbols &IS;
|
2010-08-15 04:44:32 +08:00
|
|
|
StoreManager::InvalidatedRegions *Regions;
|
2010-02-03 11:06:46 +08:00
|
|
|
public:
|
2011-02-12 03:48:15 +08:00
|
|
|
invalidateRegionsWorker(RegionStoreManager &rm,
|
2011-08-16 06:09:50 +08:00
|
|
|
ProgramStateManager &stateMgr,
|
2010-03-11 00:32:56 +08:00
|
|
|
RegionBindings b,
|
|
|
|
const Expr *ex, unsigned count,
|
2012-02-18 07:13:45 +08:00
|
|
|
const LocationContext *lctx,
|
2011-05-03 03:42:42 +08:00
|
|
|
StoreManager::InvalidatedSymbols &is,
|
2010-10-26 08:06:15 +08:00
|
|
|
StoreManager::InvalidatedRegions *r,
|
|
|
|
bool includeGlobals)
|
2011-02-12 03:48:15 +08:00
|
|
|
: ClusterAnalysis<invalidateRegionsWorker>(rm, stateMgr, b, includeGlobals),
|
2012-02-18 07:13:45 +08:00
|
|
|
Ex(ex), Count(count), LCtx(lctx), IS(is), Regions(r) {}
|
2010-03-10 15:19:59 +08:00
|
|
|
|
2010-03-11 00:32:56 +08:00
|
|
|
void VisitCluster(const MemRegion *baseR, BindingKey *I, BindingKey *E);
|
2010-04-01 08:15:55 +08:00
|
|
|
void VisitBaseRegion(const MemRegion *baseR);
|
2010-03-10 15:19:59 +08:00
|
|
|
|
2010-02-03 11:06:46 +08:00
|
|
|
private:
|
2010-02-13 08:54:03 +08:00
|
|
|
void VisitBinding(SVal V);
|
2010-03-10 15:19:59 +08:00
|
|
|
};
|
2010-02-03 12:16:00 +08:00
|
|
|
}
|
|
|
|
|
2011-02-12 03:48:15 +08:00
|
|
|
void invalidateRegionsWorker::VisitBinding(SVal V) {
|
2010-02-13 08:54:03 +08:00
|
|
|
// A symbol? Mark it touched by the invalidation.
|
2011-05-03 03:42:42 +08:00
|
|
|
if (SymbolRef Sym = V.getAsSymbol())
|
|
|
|
IS.insert(Sym);
|
2010-03-10 15:19:59 +08:00
|
|
|
|
2010-02-13 09:52:33 +08:00
|
|
|
if (const MemRegion *R = V.getAsRegion()) {
|
|
|
|
AddToWorkList(R);
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
// Is it a LazyCompoundVal? All references get invalidated as well.
|
|
|
|
if (const nonloc::LazyCompoundVal *LCS =
|
|
|
|
dyn_cast<nonloc::LazyCompoundVal>(&V)) {
|
|
|
|
|
|
|
|
const MemRegion *LazyR = LCS->getRegion();
|
|
|
|
RegionBindings B = RegionStoreManager::GetRegionBindings(LCS->getStore());
|
|
|
|
|
|
|
|
for (RegionBindings::iterator RI = B.begin(), RE = B.end(); RI != RE; ++RI){
|
2010-07-07 07:53:29 +08:00
|
|
|
const SubRegion *baseR = dyn_cast<SubRegion>(RI.getKey().getRegion());
|
|
|
|
if (baseR && baseR->isSubRegionOf(LazyR))
|
2010-02-13 09:52:33 +08:00
|
|
|
VisitBinding(RI.getData());
|
|
|
|
}
|
|
|
|
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2011-02-12 03:48:15 +08:00
|
|
|
void invalidateRegionsWorker::VisitCluster(const MemRegion *baseR,
|
2010-03-11 00:32:56 +08:00
|
|
|
BindingKey *I, BindingKey *E) {
|
|
|
|
for ( ; I != E; ++I) {
|
|
|
|
// Get the old binding. Is it a region? If so, add it to the worklist.
|
|
|
|
const BindingKey &K = *I;
|
2010-11-24 08:54:37 +08:00
|
|
|
if (const SVal *V = RM.lookup(B, K))
|
2010-03-11 00:32:56 +08:00
|
|
|
VisitBinding(*V);
|
2010-03-10 15:19:59 +08:00
|
|
|
|
2010-11-24 08:54:37 +08:00
|
|
|
B = RM.removeBinding(B, K);
|
2010-03-11 00:32:56 +08:00
|
|
|
}
|
|
|
|
}
|
2010-02-03 12:16:00 +08:00
|
|
|
|
2011-02-12 03:48:15 +08:00
|
|
|
void invalidateRegionsWorker::VisitBaseRegion(const MemRegion *baseR) {
|
2011-05-03 03:42:42 +08:00
|
|
|
// Symbolic region? Mark that symbol touched by the invalidation.
|
|
|
|
if (const SymbolicRegion *SR = dyn_cast<SymbolicRegion>(baseR))
|
|
|
|
IS.insert(SR->getSymbol());
|
2010-03-10 15:19:59 +08:00
|
|
|
|
2010-03-11 00:32:56 +08:00
|
|
|
// BlockDataRegion? If so, invalidate captured variables that are passed
|
|
|
|
// by reference.
|
|
|
|
if (const BlockDataRegion *BR = dyn_cast<BlockDataRegion>(baseR)) {
|
|
|
|
for (BlockDataRegion::referenced_vars_iterator
|
|
|
|
BI = BR->referenced_vars_begin(), BE = BR->referenced_vars_end() ;
|
|
|
|
BI != BE; ++BI) {
|
|
|
|
const VarRegion *VR = *BI;
|
|
|
|
const VarDecl *VD = VR->getDecl();
|
|
|
|
if (VD->getAttr<BlocksAttr>() || !VD->hasLocalStorage())
|
|
|
|
AddToWorkList(VR);
|
2010-02-03 12:16:00 +08:00
|
|
|
}
|
2010-03-11 00:32:56 +08:00
|
|
|
return;
|
|
|
|
}
|
2010-03-10 15:19:59 +08:00
|
|
|
|
2010-08-15 04:44:32 +08:00
|
|
|
// Otherwise, we have a normal data region. Record that we touched the region.
|
|
|
|
if (Regions)
|
|
|
|
Regions->push_back(baseR);
|
|
|
|
|
2010-03-11 00:32:56 +08:00
|
|
|
if (isa<AllocaRegion>(baseR) || isa<SymbolicRegion>(baseR)) {
|
|
|
|
// Invalidate the region by setting its default value to
|
|
|
|
// conjured symbol. The type of the symbol is irrelavant.
|
2010-11-24 08:54:37 +08:00
|
|
|
DefinedOrUnknownSVal V =
|
2012-02-18 07:13:45 +08:00
|
|
|
svalBuilder.getConjuredSymbolVal(baseR, Ex, LCtx, Ctx.IntTy, Count);
|
2010-11-24 08:54:37 +08:00
|
|
|
B = RM.addBinding(B, baseR, BindingKey::Default, V);
|
2010-03-11 00:32:56 +08:00
|
|
|
return;
|
|
|
|
}
|
2010-03-10 15:19:59 +08:00
|
|
|
|
2010-03-11 00:32:56 +08:00
|
|
|
if (!baseR->isBoundable())
|
|
|
|
return;
|
2010-03-10 15:19:59 +08:00
|
|
|
|
2011-08-13 04:02:48 +08:00
|
|
|
const TypedValueRegion *TR = cast<TypedValueRegion>(baseR);
|
2010-08-11 14:10:55 +08:00
|
|
|
QualType T = TR->getValueType();
|
2010-03-10 15:19:59 +08:00
|
|
|
|
|
|
|
// Invalidate the binding.
|
2011-04-12 08:44:31 +08:00
|
|
|
if (T->isStructureOrClassType()) {
|
2010-08-21 14:26:59 +08:00
|
|
|
// Invalidate the region by setting its default value to
|
|
|
|
// conjured symbol. The type of the symbol is irrelavant.
|
2011-04-12 08:44:31 +08:00
|
|
|
DefinedOrUnknownSVal V =
|
2012-02-18 07:13:45 +08:00
|
|
|
svalBuilder.getConjuredSymbolVal(baseR, Ex, LCtx, Ctx.IntTy, Count);
|
2010-11-24 08:54:37 +08:00
|
|
|
B = RM.addBinding(B, baseR, BindingKey::Default, V);
|
2010-03-11 00:32:56 +08:00
|
|
|
return;
|
|
|
|
}
|
2010-02-03 12:16:00 +08:00
|
|
|
|
2010-03-11 00:32:56 +08:00
|
|
|
if (const ArrayType *AT = Ctx.getAsArrayType(T)) {
|
2010-02-03 12:16:00 +08:00
|
|
|
// Set the default value of the array to conjured symbol.
|
2010-03-11 00:32:56 +08:00
|
|
|
DefinedOrUnknownSVal V =
|
2012-02-18 07:13:45 +08:00
|
|
|
svalBuilder.getConjuredSymbolVal(baseR, Ex, LCtx,
|
|
|
|
AT->getElementType(), Count);
|
2010-11-24 08:54:37 +08:00
|
|
|
B = RM.addBinding(B, baseR, BindingKey::Default, V);
|
2010-03-11 00:32:56 +08:00
|
|
|
return;
|
2009-07-30 02:16:25 +08:00
|
|
|
}
|
2010-10-26 08:06:17 +08:00
|
|
|
|
|
|
|
if (includeGlobals &&
|
|
|
|
isa<NonStaticGlobalSpaceRegion>(baseR->getMemorySpace())) {
|
|
|
|
// If the region is a global and we are invalidating all globals,
|
|
|
|
// just erase the entry. This causes all globals to be lazily
|
|
|
|
// symbolicated from the same base symbol.
|
2010-11-24 08:54:37 +08:00
|
|
|
B = RM.removeBinding(B, baseR);
|
2010-10-26 08:06:17 +08:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2009-09-09 23:08:12 +08:00
|
|
|
|
2012-02-18 07:13:45 +08:00
|
|
|
DefinedOrUnknownSVal V = svalBuilder.getConjuredSymbolVal(baseR, Ex, LCtx,
|
|
|
|
T,Count);
|
2010-03-11 00:32:56 +08:00
|
|
|
assert(SymbolManager::canSymbolicate(T) || V.isUnknown());
|
2010-11-24 08:54:37 +08:00
|
|
|
B = RM.addBinding(B, baseR, BindingKey::Direct, V);
|
2009-07-30 02:16:25 +08:00
|
|
|
}
|
|
|
|
|
2012-01-05 07:54:01 +08:00
|
|
|
RegionBindings RegionStoreManager::invalidateGlobalRegion(MemRegion::Kind K,
|
|
|
|
const Expr *Ex,
|
|
|
|
unsigned Count,
|
2012-02-18 07:13:45 +08:00
|
|
|
const LocationContext *LCtx,
|
2012-01-05 07:54:01 +08:00
|
|
|
RegionBindings B,
|
|
|
|
InvalidatedRegions *Invalidated) {
|
|
|
|
// Bind the globals memory space to a new symbol that we will use to derive
|
|
|
|
// the bindings for all globals.
|
|
|
|
const GlobalsSpaceRegion *GS = MRMgr.getGlobalsRegion(K);
|
|
|
|
SVal V =
|
2012-02-18 07:13:45 +08:00
|
|
|
svalBuilder.getConjuredSymbolVal(/* SymbolTag = */ (void*) GS, Ex, LCtx,
|
2012-01-05 07:54:01 +08:00
|
|
|
/* symbol type, doesn't matter */ Ctx.IntTy,
|
|
|
|
Count);
|
|
|
|
|
|
|
|
B = removeBinding(B, GS);
|
|
|
|
B = addBinding(B, BindingKey::Make(GS, BindingKey::Default), V);
|
|
|
|
|
|
|
|
// Even if there are no bindings in the global scope, we still need to
|
|
|
|
// record that we touched it.
|
|
|
|
if (Invalidated)
|
|
|
|
Invalidated->push_back(GS);
|
|
|
|
|
|
|
|
return B;
|
|
|
|
}
|
|
|
|
|
2011-02-19 09:59:33 +08:00
|
|
|
StoreRef RegionStoreManager::invalidateRegions(Store store,
|
2011-08-28 06:51:26 +08:00
|
|
|
ArrayRef<const MemRegion *> Regions,
|
2011-02-19 09:59:33 +08:00
|
|
|
const Expr *Ex, unsigned Count,
|
2012-02-18 07:13:45 +08:00
|
|
|
const LocationContext *LCtx,
|
2011-05-03 03:42:42 +08:00
|
|
|
InvalidatedSymbols &IS,
|
2012-01-05 07:54:01 +08:00
|
|
|
const CallOrObjCMessage *Call,
|
2011-08-28 06:51:26 +08:00
|
|
|
InvalidatedRegions *Invalidated) {
|
2011-02-12 03:48:15 +08:00
|
|
|
invalidateRegionsWorker W(*this, StateMgr,
|
2010-03-11 00:32:56 +08:00
|
|
|
RegionStoreManager::GetRegionBindings(store),
|
2012-02-18 07:13:45 +08:00
|
|
|
Ex, Count, LCtx, IS, Invalidated, false);
|
2010-03-11 00:32:56 +08:00
|
|
|
|
|
|
|
// Scan the bindings and generate the clusters.
|
2010-10-26 08:06:15 +08:00
|
|
|
W.GenerateClusters();
|
2010-03-11 00:32:56 +08:00
|
|
|
|
2011-08-28 06:51:26 +08:00
|
|
|
// Add the regions to the worklist.
|
|
|
|
for (ArrayRef<const MemRegion *>::iterator
|
|
|
|
I = Regions.begin(), E = Regions.end(); I != E; ++I)
|
2010-03-11 00:32:56 +08:00
|
|
|
W.AddToWorkList(*I);
|
|
|
|
|
|
|
|
W.RunWorkList();
|
|
|
|
|
|
|
|
// Return the new bindings.
|
2010-07-02 04:16:50 +08:00
|
|
|
RegionBindings B = W.getRegionBindings();
|
|
|
|
|
2012-01-05 07:54:01 +08:00
|
|
|
// For all globals which are not static nor immutable: determine which global
|
|
|
|
// regions should be invalidated and invalidate them.
|
|
|
|
// TODO: This could possibly be more precise with modules.
|
|
|
|
//
|
|
|
|
// System calls invalidate only system globals.
|
|
|
|
if (Call && Call->isInSystemHeader()) {
|
|
|
|
B = invalidateGlobalRegion(MemRegion::GlobalSystemSpaceRegionKind,
|
2012-02-18 07:13:45 +08:00
|
|
|
Ex, Count, LCtx, B, Invalidated);
|
2012-01-05 07:54:01 +08:00
|
|
|
// Internal calls might invalidate both system and internal globals.
|
|
|
|
} else {
|
|
|
|
B = invalidateGlobalRegion(MemRegion::GlobalSystemSpaceRegionKind,
|
2012-02-18 07:13:45 +08:00
|
|
|
Ex, Count, LCtx, B, Invalidated);
|
2012-01-05 07:54:01 +08:00
|
|
|
B = invalidateGlobalRegion(MemRegion::GlobalInternalSpaceRegionKind,
|
2012-02-18 07:13:45 +08:00
|
|
|
Ex, Count, LCtx, B, Invalidated);
|
2010-07-02 04:16:50 +08:00
|
|
|
}
|
|
|
|
|
2011-02-19 09:59:33 +08:00
|
|
|
return StoreRef(B.getRootWithoutRetain(), *this);
|
2010-02-03 11:06:46 +08:00
|
|
|
}
|
2010-03-10 15:20:03 +08:00
|
|
|
|
2009-06-17 06:36:44 +08:00
|
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
// Extents for regions.
|
|
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
|
2012-01-12 10:22:40 +08:00
|
|
|
DefinedOrUnknownSVal
|
2012-01-27 05:29:00 +08:00
|
|
|
RegionStoreManager::getSizeInElements(ProgramStateRef state,
|
2012-01-12 10:22:40 +08:00
|
|
|
const MemRegion *R,
|
|
|
|
QualType EleTy) {
|
2010-12-02 15:49:45 +08:00
|
|
|
SVal Size = cast<SubRegion>(R)->getExtent(svalBuilder);
|
2010-12-02 05:28:31 +08:00
|
|
|
const llvm::APSInt *SizeInt = svalBuilder.getKnownValue(state, Size);
|
2010-07-04 08:00:41 +08:00
|
|
|
if (!SizeInt)
|
|
|
|
return UnknownVal();
|
2009-09-09 23:08:12 +08:00
|
|
|
|
2010-07-04 08:00:41 +08:00
|
|
|
CharUnits RegionSize = CharUnits::fromQuantity(SizeInt->getSExtValue());
|
2010-09-15 07:08:34 +08:00
|
|
|
|
|
|
|
if (Ctx.getAsVariableArrayType(EleTy)) {
|
|
|
|
// FIXME: We need to track extra state to properly record the size
|
|
|
|
// of VLAs. Returning UnknownVal here, however, is a stop-gap so that
|
|
|
|
// we don't have a divide-by-zero below.
|
|
|
|
return UnknownVal();
|
|
|
|
}
|
|
|
|
|
2010-08-15 18:08:38 +08:00
|
|
|
CharUnits EleSize = Ctx.getTypeSizeInChars(EleTy);
|
2009-09-09 23:08:12 +08:00
|
|
|
|
2010-07-04 08:00:41 +08:00
|
|
|
// If a variable is reinterpreted as a type that doesn't fit into a larger
|
|
|
|
// type evenly, round it down.
|
|
|
|
// This is a signed value, since it's used in arithmetic with signed indices.
|
2010-12-02 15:49:45 +08:00
|
|
|
return svalBuilder.makeIntVal(RegionSize / EleSize, false);
|
2008-11-22 21:21:46 +08:00
|
|
|
}
|
|
|
|
|
2009-06-17 06:36:44 +08:00
|
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
// Location and region casting.
|
|
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
|
2008-12-24 15:46:32 +08:00
|
|
|
/// 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
|
|
|
|
/// version of that lvalue (i.e., a pointer to the first element of
|
2010-12-23 02:53:44 +08:00
|
|
|
/// the array). This is called by ExprEngine when evaluating casts
|
2008-12-24 15:46:32 +08:00
|
|
|
/// from arrays to pointers.
|
2009-03-30 13:55:46 +08:00
|
|
|
SVal RegionStoreManager::ArrayToPointer(Loc Array) {
|
2008-12-14 03:24:37 +08:00
|
|
|
if (!isa<loc::MemRegionVal>(Array))
|
|
|
|
return UnknownVal();
|
2009-09-09 23:08:12 +08:00
|
|
|
|
2008-12-14 03:24:37 +08:00
|
|
|
const MemRegion* R = cast<loc::MemRegionVal>(&Array)->getRegion();
|
2011-08-13 04:02:48 +08:00
|
|
|
const TypedValueRegion* ArrayR = dyn_cast<TypedValueRegion>(R);
|
2009-09-09 23:08:12 +08:00
|
|
|
|
2009-01-13 09:03:27 +08:00
|
|
|
if (!ArrayR)
|
2008-12-14 03:24:37 +08:00
|
|
|
return UnknownVal();
|
2009-09-09 23:08:12 +08:00
|
|
|
|
2009-05-09 11:57:34 +08:00
|
|
|
// Strip off typedefs from the ArrayRegion's ValueType.
|
2010-12-10 19:01:00 +08:00
|
|
|
QualType T = ArrayR->getValueType().getDesugaredType(Ctx);
|
2011-01-19 14:33:43 +08:00
|
|
|
const ArrayType *AT = cast<ArrayType>(T);
|
2009-05-04 14:18:28 +08:00
|
|
|
T = AT->getElementType();
|
2009-09-09 23:08:12 +08:00
|
|
|
|
2010-12-02 15:49:45 +08:00
|
|
|
NonLoc ZeroIdx = svalBuilder.makeZeroArrayIndex();
|
2010-08-15 18:08:38 +08:00
|
|
|
return loc::MemRegionVal(MRMgr.getElementRegion(T, ZeroIdx, ArrayR, Ctx));
|
2008-10-24 09:09:32 +08:00
|
|
|
}
|
|
|
|
|
2010-12-22 16:12:57 +08:00
|
|
|
SVal RegionStoreManager::evalDerivedToBase(SVal derived, QualType baseType) {
|
|
|
|
const CXXRecordDecl *baseDecl;
|
|
|
|
if (baseType->isPointerType())
|
|
|
|
baseDecl = baseType->getCXXRecordDeclForPointerType();
|
|
|
|
else
|
|
|
|
baseDecl = baseType->getAsCXXRecordDecl();
|
|
|
|
|
2010-11-26 16:21:53 +08:00
|
|
|
assert(baseDecl && "not a CXXRecordDecl?");
|
2010-12-22 16:12:57 +08:00
|
|
|
|
2010-12-23 20:08:42 +08:00
|
|
|
loc::MemRegionVal *derivedRegVal = dyn_cast<loc::MemRegionVal>(&derived);
|
|
|
|
if (!derivedRegVal)
|
|
|
|
return derived;
|
|
|
|
|
2010-11-26 16:21:53 +08:00
|
|
|
const MemRegion *baseReg =
|
2011-01-13 20:30:12 +08:00
|
|
|
MRMgr.getCXXBaseObjectRegion(baseDecl, derivedRegVal->getRegion());
|
|
|
|
|
2010-11-26 16:21:53 +08:00
|
|
|
return loc::MemRegionVal(baseReg);
|
|
|
|
}
|
2009-03-02 15:52:23 +08:00
|
|
|
|
2012-04-11 04:59:00 +08:00
|
|
|
SVal RegionStoreManager::evalDynamicCast(SVal base, QualType derivedType,
|
|
|
|
bool &Failed) {
|
|
|
|
Failed = false;
|
|
|
|
|
|
|
|
loc::MemRegionVal *baseRegVal = dyn_cast<loc::MemRegionVal>(&base);
|
|
|
|
if (!baseRegVal)
|
|
|
|
return UnknownVal();
|
|
|
|
const MemRegion *BaseRegion = baseRegVal->stripCasts();
|
|
|
|
|
2012-04-11 05:29:03 +08:00
|
|
|
// Assume the derived class is a pointer or a reference to a CXX record.
|
2012-04-11 04:59:00 +08:00
|
|
|
derivedType = derivedType->getPointeeType();
|
|
|
|
assert(!derivedType.isNull());
|
|
|
|
const CXXRecordDecl *DerivedDecl = derivedType->getAsCXXRecordDecl();
|
|
|
|
if (!DerivedDecl && !derivedType->isVoidType())
|
|
|
|
return UnknownVal();
|
|
|
|
|
|
|
|
// Drill down the CXXBaseObject chains, which represent upcasts (casts from
|
|
|
|
// derived to base).
|
|
|
|
const MemRegion *SR = BaseRegion;
|
|
|
|
while (const TypedRegion *TSR = dyn_cast_or_null<TypedRegion>(SR)) {
|
|
|
|
QualType BaseType = TSR->getLocationType()->getPointeeType();
|
|
|
|
assert(!BaseType.isNull());
|
|
|
|
const CXXRecordDecl *SRDecl = BaseType->getAsCXXRecordDecl();
|
|
|
|
if (!SRDecl)
|
|
|
|
return UnknownVal();
|
|
|
|
|
|
|
|
// If found the derived class, the cast succeeds.
|
|
|
|
if (SRDecl == DerivedDecl)
|
|
|
|
return loc::MemRegionVal(TSR);
|
|
|
|
|
|
|
|
// If the region type is a subclass of the derived type.
|
|
|
|
if (!derivedType->isVoidType() && SRDecl->isDerivedFrom(DerivedDecl)) {
|
|
|
|
// This occurs in two cases.
|
|
|
|
// 1) We are processing an upcast.
|
|
|
|
// 2) We are processing a downcast but we jumped directly from the
|
|
|
|
// ancestor to a child of the cast value, so conjure the
|
|
|
|
// appropriate region to represent value (the intermediate node).
|
|
|
|
return loc::MemRegionVal(MRMgr.getCXXBaseObjectRegion(DerivedDecl,
|
|
|
|
BaseRegion));
|
|
|
|
}
|
|
|
|
|
|
|
|
// If super region is not a parent of derived class, the cast definitely
|
|
|
|
// fails.
|
|
|
|
if (!derivedType->isVoidType() &&
|
|
|
|
DerivedDecl->isProvablyNotDerivedFrom(SRDecl)) {
|
|
|
|
Failed = true;
|
|
|
|
return UnknownVal();
|
|
|
|
}
|
|
|
|
|
|
|
|
if (const CXXBaseObjectRegion *R = dyn_cast<CXXBaseObjectRegion>(TSR))
|
|
|
|
// Drill down the chain to get the derived classes.
|
|
|
|
SR = R->getSuperRegion();
|
|
|
|
else {
|
|
|
|
// We reached the bottom of the hierarchy.
|
|
|
|
|
|
|
|
// If this is a cast to void*, return the region.
|
|
|
|
if (derivedType->isVoidType())
|
|
|
|
return loc::MemRegionVal(TSR);
|
|
|
|
|
|
|
|
// We did not find the derived class. We we must be casting the base to
|
|
|
|
// derived, so the cast should fail.
|
|
|
|
Failed = true;
|
|
|
|
return UnknownVal();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return UnknownVal();
|
|
|
|
}
|
|
|
|
|
2009-06-17 06:36:44 +08:00
|
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
// Loading values from regions.
|
|
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
|
2010-03-10 15:20:03 +08:00
|
|
|
Optional<SVal> RegionStoreManager::getDirectBinding(RegionBindings B,
|
2010-05-29 14:23:24 +08:00
|
|
|
const MemRegion *R) {
|
2010-05-29 14:49:04 +08:00
|
|
|
|
2010-11-24 08:54:37 +08:00
|
|
|
if (const SVal *V = lookup(B, R, BindingKey::Direct))
|
2010-05-29 14:49:04 +08:00
|
|
|
return *V;
|
2010-02-03 11:06:46 +08:00
|
|
|
|
2009-10-11 16:08:02 +08:00
|
|
|
return Optional<SVal>();
|
|
|
|
}
|
|
|
|
|
|
|
|
Optional<SVal> RegionStoreManager::getDefaultBinding(RegionBindings B,
|
2009-08-07 05:43:54 +08:00
|
|
|
const MemRegion *R) {
|
|
|
|
if (R->isBoundable())
|
2011-08-13 04:02:48 +08:00
|
|
|
if (const TypedValueRegion *TR = dyn_cast<TypedValueRegion>(R))
|
2010-08-11 14:10:55 +08:00
|
|
|
if (TR->getValueType()->isUnionType())
|
2009-08-07 05:43:54 +08:00
|
|
|
return UnknownVal();
|
|
|
|
|
2010-11-24 08:54:37 +08:00
|
|
|
if (const SVal *V = lookup(B, R, BindingKey::Default))
|
2010-02-03 11:06:46 +08:00
|
|
|
return *V;
|
2009-10-11 16:08:02 +08:00
|
|
|
|
|
|
|
return Optional<SVal>();
|
|
|
|
}
|
|
|
|
|
2012-01-12 10:22:40 +08:00
|
|
|
SVal RegionStoreManager::getBinding(Store store, Loc L, QualType T) {
|
2008-10-21 13:29:26 +08:00
|
|
|
assert(!isa<UnknownVal>(L) && "location unknown");
|
|
|
|
assert(!isa<UndefinedVal>(L) && "location undefined");
|
2010-03-10 15:20:03 +08:00
|
|
|
|
2010-11-12 07:10:10 +08:00
|
|
|
// For access to concrete addresses, return UnknownVal. Checks
|
|
|
|
// for null dereferences (and similar errors) are done by checkers, not
|
|
|
|
// the Store.
|
|
|
|
// FIXME: We can consider lazily symbolicating such memory, but we really
|
|
|
|
// should defer this when we can reason easily about symbolicating arrays
|
|
|
|
// of bytes.
|
|
|
|
if (isa<loc::ConcreteInt>(L)) {
|
|
|
|
return UnknownVal();
|
|
|
|
}
|
2011-01-25 08:04:03 +08:00
|
|
|
if (!isa<loc::MemRegionVal>(L)) {
|
|
|
|
return UnknownVal();
|
|
|
|
}
|
2010-03-10 15:20:03 +08:00
|
|
|
|
2009-06-18 06:02:04 +08:00
|
|
|
const MemRegion *MR = cast<loc::MemRegionVal>(L).getRegion();
|
2009-04-03 15:33:13 +08:00
|
|
|
|
2011-11-30 03:39:29 +08:00
|
|
|
if (isa<AllocaRegion>(MR) ||
|
|
|
|
isa<SymbolicRegion>(MR) ||
|
|
|
|
isa<CodeTextRegion>(MR)) {
|
2010-06-26 02:22:31 +08:00
|
|
|
if (T.isNull()) {
|
2012-01-13 08:56:48 +08:00
|
|
|
if (const TypedRegion *TR = dyn_cast<TypedRegion>(MR))
|
|
|
|
T = TR->getLocationType();
|
|
|
|
else {
|
|
|
|
const SymbolicRegion *SR = cast<SymbolicRegion>(MR);
|
|
|
|
T = SR->getSymbol()->getType(Ctx);
|
|
|
|
}
|
2010-06-26 02:22:31 +08:00
|
|
|
}
|
2010-02-08 16:43:02 +08:00
|
|
|
MR = GetElementZeroRegion(MR, T);
|
2010-06-26 02:22:31 +08:00
|
|
|
}
|
2009-09-09 23:08:12 +08:00
|
|
|
|
2008-12-24 15:46:32 +08:00
|
|
|
// 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.
|
2011-08-13 04:02:48 +08:00
|
|
|
const TypedValueRegion *R = cast<TypedValueRegion>(MR);
|
2010-08-11 14:10:55 +08:00
|
|
|
QualType RTy = R->getValueType();
|
2008-10-21 13:29:26 +08:00
|
|
|
|
2008-12-24 15:46:32 +08:00
|
|
|
// FIXME: We should eventually handle funny addressing. e.g.:
|
|
|
|
//
|
|
|
|
// int x = ...;
|
|
|
|
// int *p = &x;
|
|
|
|
// char *q = (char*) p;
|
|
|
|
// char c = *q; // returns the first byte of 'x'.
|
|
|
|
//
|
|
|
|
// Such funny addressing will occur due to layering of regions.
|
|
|
|
|
2010-04-27 05:31:17 +08:00
|
|
|
if (RTy->isStructureOrClassType())
|
2012-01-12 10:22:40 +08:00
|
|
|
return getBindingForStruct(store, R);
|
2009-09-09 23:08:12 +08:00
|
|
|
|
2009-08-07 05:43:54 +08:00
|
|
|
// FIXME: Handle unions.
|
|
|
|
if (RTy->isUnionType())
|
2010-02-04 10:39:47 +08:00
|
|
|
return UnknownVal();
|
2009-05-03 08:27:40 +08:00
|
|
|
|
|
|
|
if (RTy->isArrayType())
|
2012-01-12 10:22:40 +08:00
|
|
|
return getBindingForArray(store, R);
|
2009-05-03 08:27:40 +08:00
|
|
|
|
2009-03-09 17:15:51 +08:00
|
|
|
// FIXME: handle Vector types.
|
|
|
|
if (RTy->isVectorType())
|
2010-02-04 10:39:47 +08:00
|
|
|
return UnknownVal();
|
2009-06-28 22:16:39 +08:00
|
|
|
|
|
|
|
if (const FieldRegion* FR = dyn_cast<FieldRegion>(R))
|
2012-01-12 10:22:40 +08:00
|
|
|
return CastRetrievedVal(getBindingForField(store, FR), FR, T, false);
|
2010-01-11 10:33:26 +08:00
|
|
|
|
|
|
|
if (const ElementRegion* ER = dyn_cast<ElementRegion>(R)) {
|
|
|
|
// FIXME: Here we actually perform an implicit conversion from the loaded
|
|
|
|
// value to the element type. Eventually we want to compose these values
|
|
|
|
// more intelligently. For example, an 'element' can encompass multiple
|
|
|
|
// bound regions (e.g., several bound bytes), or could be a subset of
|
|
|
|
// a larger value.
|
2012-01-12 10:22:40 +08:00
|
|
|
return CastRetrievedVal(getBindingForElement(store, ER), ER, T, false);
|
2010-03-10 15:20:03 +08:00
|
|
|
}
|
2010-01-11 10:33:26 +08:00
|
|
|
|
|
|
|
if (const ObjCIvarRegion *IVR = dyn_cast<ObjCIvarRegion>(R)) {
|
|
|
|
// FIXME: Here we actually perform an implicit conversion from the loaded
|
|
|
|
// value to the ivar type. What we should model is stores to ivars
|
|
|
|
// that blow past the extent of the ivar. If the address of the ivar is
|
|
|
|
// reinterpretted, it is possible we stored a different value that could
|
|
|
|
// fit within the ivar. Either we need to cast these when storing them
|
|
|
|
// or reinterpret them lazily (as we do here).
|
2012-01-12 10:22:40 +08:00
|
|
|
return CastRetrievedVal(getBindingForObjCIvar(store, IVR), IVR, T, false);
|
2010-01-11 10:33:26 +08:00
|
|
|
}
|
2009-09-09 23:08:12 +08:00
|
|
|
|
2010-01-11 10:33:26 +08:00
|
|
|
if (const VarRegion *VR = dyn_cast<VarRegion>(R)) {
|
|
|
|
// FIXME: Here we actually perform an implicit conversion from the loaded
|
|
|
|
// value to the variable type. What we should model is stores to variables
|
|
|
|
// that blow past the extent of the variable. If the address of the
|
|
|
|
// variable is reinterpretted, it is possible we stored a different value
|
|
|
|
// that could fit within the variable. Either we need to cast these when
|
2010-03-10 15:20:03 +08:00
|
|
|
// storing them or reinterpret them lazily (as we do here).
|
2012-01-12 10:22:40 +08:00
|
|
|
return CastRetrievedVal(getBindingForVar(store, VR), VR, T, false);
|
2010-01-11 10:33:26 +08:00
|
|
|
}
|
2009-07-21 06:58:02 +08:00
|
|
|
|
2010-02-05 11:01:53 +08:00
|
|
|
RegionBindings B = GetRegionBindings(store);
|
2010-11-24 08:54:37 +08:00
|
|
|
const SVal *V = lookup(B, R, BindingKey::Direct);
|
2008-10-21 13:29:26 +08:00
|
|
|
|
2008-12-20 14:32:12 +08:00
|
|
|
// Check if the region has a binding.
|
|
|
|
if (V)
|
2010-02-04 10:39:47 +08:00
|
|
|
return *V;
|
2008-12-24 15:46:32 +08:00
|
|
|
|
|
|
|
// The location does not have a bound value. This means that it has
|
|
|
|
// the value it had upon its creation and/or entry to the analyzed
|
|
|
|
// function/method. These are either symbolic values or 'undefined'.
|
2010-01-05 10:18:06 +08:00
|
|
|
if (R->hasStackNonParametersStorage()) {
|
2008-12-24 15:46:32 +08:00
|
|
|
// All stack variables are considered to have undefined values
|
|
|
|
// upon creation. All heap allocated blocks are considered to
|
|
|
|
// have undefined values as well unless they are explicitly bound
|
|
|
|
// to specific values.
|
2010-02-04 10:39:47 +08:00
|
|
|
return UndefinedVal();
|
2008-12-24 15:46:32 +08:00
|
|
|
}
|
|
|
|
|
2009-07-03 06:16:42 +08:00
|
|
|
// All other values are symbolic.
|
2010-12-02 15:49:45 +08:00
|
|
|
return svalBuilder.getRegionValueSymbolVal(R);
|
2008-10-21 13:29:26 +08:00
|
|
|
}
|
2009-09-09 23:08:12 +08:00
|
|
|
|
2010-02-05 10:26:30 +08:00
|
|
|
std::pair<Store, const MemRegion *>
|
2011-04-03 12:09:15 +08:00
|
|
|
RegionStoreManager::GetLazyBinding(RegionBindings B, const MemRegion *R,
|
|
|
|
const MemRegion *originalRegion) {
|
|
|
|
|
|
|
|
if (originalRegion != R) {
|
|
|
|
if (Optional<SVal> OV = getDefaultBinding(B, R)) {
|
|
|
|
if (const nonloc::LazyCompoundVal *V =
|
|
|
|
dyn_cast<nonloc::LazyCompoundVal>(OV.getPointer()))
|
|
|
|
return std::make_pair(V->getStore(), V->getRegion());
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2009-08-06 09:20:57 +08:00
|
|
|
if (const ElementRegion *ER = dyn_cast<ElementRegion>(R)) {
|
2010-02-05 10:26:30 +08:00
|
|
|
const std::pair<Store, const MemRegion *> &X =
|
2011-04-03 12:09:15 +08:00
|
|
|
GetLazyBinding(B, ER->getSuperRegion(), originalRegion);
|
2009-09-09 23:08:12 +08:00
|
|
|
|
2010-02-10 03:11:53 +08:00
|
|
|
if (X.second)
|
2009-08-06 09:20:57 +08:00
|
|
|
return std::make_pair(X.first,
|
|
|
|
MRMgr.getElementRegionWithSuper(ER, X.second));
|
2009-09-09 23:08:12 +08:00
|
|
|
}
|
2009-08-06 09:20:57 +08:00
|
|
|
else if (const FieldRegion *FR = dyn_cast<FieldRegion>(R)) {
|
2010-02-05 10:26:30 +08:00
|
|
|
const std::pair<Store, const MemRegion *> &X =
|
2011-04-03 12:09:15 +08:00
|
|
|
GetLazyBinding(B, FR->getSuperRegion(), originalRegion);
|
2009-09-09 23:08:12 +08:00
|
|
|
|
2010-02-10 03:11:53 +08:00
|
|
|
if (X.second)
|
2009-08-06 09:20:57 +08:00
|
|
|
return std::make_pair(X.first,
|
|
|
|
MRMgr.getFieldRegionWithSuper(FR, X.second));
|
|
|
|
}
|
2011-01-13 20:30:12 +08:00
|
|
|
// C++ base object region is another kind of region that we should blast
|
|
|
|
// through to look for lazy compound value. It is like a field region.
|
|
|
|
else if (const CXXBaseObjectRegion *baseReg =
|
|
|
|
dyn_cast<CXXBaseObjectRegion>(R)) {
|
|
|
|
const std::pair<Store, const MemRegion *> &X =
|
2011-04-03 12:09:15 +08:00
|
|
|
GetLazyBinding(B, baseReg->getSuperRegion(), originalRegion);
|
2011-01-13 20:30:12 +08:00
|
|
|
|
|
|
|
if (X.second)
|
|
|
|
return std::make_pair(X.first,
|
|
|
|
MRMgr.getCXXBaseObjectRegionWithSuper(baseReg, X.second));
|
|
|
|
}
|
2011-03-17 11:51:51 +08:00
|
|
|
|
2010-03-10 15:20:03 +08:00
|
|
|
// The NULL MemRegion indicates an non-existent lazy binding. A NULL Store is
|
2010-02-10 10:02:10 +08:00
|
|
|
// possible for a valid lazy binding.
|
2010-02-05 10:26:30 +08:00
|
|
|
return std::make_pair((Store) 0, (const MemRegion *) 0);
|
2009-08-06 09:20:57 +08:00
|
|
|
}
|
2008-10-21 13:29:26 +08:00
|
|
|
|
2012-01-12 10:22:40 +08:00
|
|
|
SVal RegionStoreManager::getBindingForElement(Store store,
|
2009-06-25 13:29:39 +08:00
|
|
|
const ElementRegion* R) {
|
|
|
|
// Check if the region has a binding.
|
2010-02-05 10:26:30 +08:00
|
|
|
RegionBindings B = GetRegionBindings(store);
|
2010-03-31 04:30:52 +08:00
|
|
|
if (const Optional<SVal> &V = getDirectBinding(B, R))
|
2009-06-25 13:29:39 +08:00
|
|
|
return *V;
|
|
|
|
|
2009-07-02 07:19:52 +08:00
|
|
|
const MemRegion* superR = R->getSuperRegion();
|
|
|
|
|
2009-06-25 13:29:39 +08:00
|
|
|
// Check if the region is an element region of a string literal.
|
2009-07-02 07:19:52 +08:00
|
|
|
if (const StringRegion *StrR=dyn_cast<StringRegion>(superR)) {
|
2010-03-10 15:20:03 +08:00
|
|
|
// FIXME: Handle loads from strings where the literal is treated as
|
2009-09-30 00:36:48 +08:00
|
|
|
// an integer, e.g., *((unsigned int*)"hello")
|
2010-08-11 14:10:55 +08:00
|
|
|
QualType T = Ctx.getAsArrayType(StrR->getValueType())->getElementType();
|
2009-09-30 00:36:48 +08:00
|
|
|
if (T != Ctx.getCanonicalType(R->getElementType()))
|
|
|
|
return UnknownVal();
|
2010-03-10 15:20:03 +08:00
|
|
|
|
2009-06-25 13:29:39 +08:00
|
|
|
const StringLiteral *Str = StrR->getStringLiteral();
|
|
|
|
SVal Idx = R->getIndex();
|
|
|
|
if (nonloc::ConcreteInt *CI = dyn_cast<nonloc::ConcreteInt>(&Idx)) {
|
|
|
|
int64_t i = CI->getValue().getSExtValue();
|
2011-07-29 07:07:43 +08:00
|
|
|
// Abort on string underrun. This can be possible by arbitrary
|
2012-01-12 10:22:40 +08:00
|
|
|
// clients of getBindingForElement().
|
2011-07-29 07:07:43 +08:00
|
|
|
if (i < 0)
|
|
|
|
return UndefinedVal();
|
2011-11-15 04:05:54 +08:00
|
|
|
int64_t length = Str->getLength();
|
|
|
|
// Technically, only i == length is guaranteed to be null.
|
2010-07-29 14:40:33 +08:00
|
|
|
// However, such overflows should be caught before reaching this point;
|
|
|
|
// the only time such an access would be made is if a string literal was
|
|
|
|
// used to initialize a larger array.
|
2011-11-15 04:05:54 +08:00
|
|
|
char c = (i >= length) ? '\0' : Str->getCodeUnit(i);
|
2010-12-02 15:49:45 +08:00
|
|
|
return svalBuilder.makeIntVal(c, T);
|
2009-06-25 13:29:39 +08:00
|
|
|
}
|
|
|
|
}
|
2010-09-02 07:00:46 +08:00
|
|
|
|
|
|
|
// Check for loads from a code text region. For such loads, just give up.
|
2010-09-02 08:34:30 +08:00
|
|
|
if (isa<CodeTextRegion>(superR))
|
2010-09-02 07:00:46 +08:00
|
|
|
return UnknownVal();
|
2009-09-09 23:08:12 +08:00
|
|
|
|
2010-05-31 09:22:04 +08:00
|
|
|
// Handle the case where we are indexing into a larger scalar object.
|
|
|
|
// For example, this handles:
|
|
|
|
// int x = ...
|
|
|
|
// char *y = &x;
|
|
|
|
// return *y;
|
|
|
|
// FIXME: This is a hack, and doesn't do anything really intelligent yet.
|
2010-08-02 12:56:14 +08:00
|
|
|
const RegionRawOffset &O = R->getAsArrayOffset();
|
2011-05-20 07:37:58 +08:00
|
|
|
|
|
|
|
// If we cannot reason about the offset, return an unknown value.
|
|
|
|
if (!O.getRegion())
|
|
|
|
return UnknownVal();
|
|
|
|
|
2011-08-13 04:02:48 +08:00
|
|
|
if (const TypedValueRegion *baseR =
|
|
|
|
dyn_cast_or_null<TypedValueRegion>(O.getRegion())) {
|
2010-08-11 14:10:55 +08:00
|
|
|
QualType baseT = baseR->getValueType();
|
2010-05-31 09:22:04 +08:00
|
|
|
if (baseT->isScalarType()) {
|
|
|
|
QualType elemT = R->getElementType();
|
|
|
|
if (elemT->isScalarType()) {
|
|
|
|
if (Ctx.getTypeSizeInChars(baseT) >= Ctx.getTypeSizeInChars(elemT)) {
|
|
|
|
if (const Optional<SVal> &V = getDirectBinding(B, superR)) {
|
|
|
|
if (SymbolRef parentSym = V->getAsSymbol())
|
2010-12-02 15:49:45 +08:00
|
|
|
return svalBuilder.getDerivedRegionValueSymbolVal(parentSym, R);
|
2010-07-02 04:16:50 +08:00
|
|
|
|
2010-05-31 09:22:04 +08:00
|
|
|
if (V->isUnknownOrUndef())
|
|
|
|
return *V;
|
|
|
|
// Other cases: give up. We are indexing into a larger object
|
|
|
|
// that has some value, but we don't know how to handle that yet.
|
|
|
|
return UnknownVal();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2009-08-07 06:33:36 +08:00
|
|
|
}
|
2009-06-30 20:32:59 +08:00
|
|
|
}
|
2012-01-12 10:22:40 +08:00
|
|
|
return getBindingForFieldOrElementCommon(store, R, R->getElementType(),
|
|
|
|
superR);
|
2009-06-25 13:29:39 +08:00
|
|
|
}
|
|
|
|
|
2012-01-12 10:22:40 +08:00
|
|
|
SVal RegionStoreManager::getBindingForField(Store store,
|
2009-06-25 12:50:44 +08:00
|
|
|
const FieldRegion* R) {
|
|
|
|
|
|
|
|
// Check if the region has a binding.
|
2010-02-05 10:26:30 +08:00
|
|
|
RegionBindings B = GetRegionBindings(store);
|
2010-03-31 04:30:52 +08:00
|
|
|
if (const Optional<SVal> &V = getDirectBinding(B, R))
|
2009-06-25 12:50:44 +08:00
|
|
|
return *V;
|
|
|
|
|
2010-08-11 14:10:55 +08:00
|
|
|
QualType Ty = R->getValueType();
|
2012-01-12 10:22:40 +08:00
|
|
|
return getBindingForFieldOrElementCommon(store, R, Ty, R->getSuperRegion());
|
2009-08-07 06:33:36 +08:00
|
|
|
}
|
2009-09-09 23:08:12 +08:00
|
|
|
|
2010-07-02 04:16:50 +08:00
|
|
|
Optional<SVal>
|
2012-01-12 10:22:40 +08:00
|
|
|
RegionStoreManager::getBindingForDerivedDefaultValue(RegionBindings B,
|
|
|
|
const MemRegion *superR,
|
|
|
|
const TypedValueRegion *R,
|
|
|
|
QualType Ty) {
|
2010-07-02 04:16:50 +08:00
|
|
|
|
|
|
|
if (const Optional<SVal> &D = getDefaultBinding(B, superR)) {
|
2011-03-17 11:51:51 +08:00
|
|
|
const SVal &val = D.getValue();
|
|
|
|
if (SymbolRef parentSym = val.getAsSymbol())
|
2010-12-02 15:49:45 +08:00
|
|
|
return svalBuilder.getDerivedRegionValueSymbolVal(parentSym, R);
|
2010-07-02 04:16:50 +08:00
|
|
|
|
2011-03-17 11:51:51 +08:00
|
|
|
if (val.isZeroConstant())
|
2010-12-02 15:49:45 +08:00
|
|
|
return svalBuilder.makeZeroVal(Ty);
|
2010-07-02 04:16:50 +08:00
|
|
|
|
2011-03-17 11:51:51 +08:00
|
|
|
if (val.isUnknownOrUndef())
|
|
|
|
return val;
|
|
|
|
|
|
|
|
// Lazy bindings are handled later.
|
|
|
|
if (isa<nonloc::LazyCompoundVal>(val))
|
|
|
|
return Optional<SVal>();
|
2010-07-02 04:16:50 +08:00
|
|
|
|
2011-09-23 13:06:16 +08:00
|
|
|
llvm_unreachable("Unknown default value");
|
2010-07-02 04:16:50 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
return Optional<SVal>();
|
|
|
|
}
|
|
|
|
|
2012-01-12 10:22:40 +08:00
|
|
|
SVal RegionStoreManager::getLazyBinding(const MemRegion *lazyBindingRegion,
|
2011-03-17 11:51:51 +08:00
|
|
|
Store lazyBindingStore) {
|
|
|
|
if (const ElementRegion *ER = dyn_cast<ElementRegion>(lazyBindingRegion))
|
2012-01-12 10:22:40 +08:00
|
|
|
return getBindingForElement(lazyBindingStore, ER);
|
2011-03-17 11:51:51 +08:00
|
|
|
|
2012-01-12 10:22:40 +08:00
|
|
|
return getBindingForField(lazyBindingStore,
|
|
|
|
cast<FieldRegion>(lazyBindingRegion));
|
2011-03-17 11:51:51 +08:00
|
|
|
}
|
|
|
|
|
2012-01-12 10:22:40 +08:00
|
|
|
SVal RegionStoreManager::getBindingForFieldOrElementCommon(Store store,
|
2011-08-13 04:02:48 +08:00
|
|
|
const TypedValueRegion *R,
|
2009-08-07 06:33:36 +08:00
|
|
|
QualType Ty,
|
|
|
|
const MemRegion *superR) {
|
|
|
|
|
2012-01-12 10:22:40 +08:00
|
|
|
// At this point we have already checked in either getBindingForElement or
|
|
|
|
// getBindingForField if 'R' has a direct binding.
|
2010-02-05 10:26:30 +08:00
|
|
|
RegionBindings B = GetRegionBindings(store);
|
2012-04-26 13:08:26 +08:00
|
|
|
|
|
|
|
// Lazy binding?
|
|
|
|
Store lazyBindingStore = NULL;
|
|
|
|
const MemRegion *lazyBindingRegion = NULL;
|
|
|
|
llvm::tie(lazyBindingStore, lazyBindingRegion) = GetLazyBinding(B, R, R);
|
2012-04-03 08:03:34 +08:00
|
|
|
|
2012-04-26 13:08:26 +08:00
|
|
|
if (lazyBindingRegion)
|
|
|
|
return getLazyBinding(lazyBindingRegion, lazyBindingStore);
|
|
|
|
|
2012-04-03 08:03:34 +08:00
|
|
|
// Record whether or not we see a symbolic index. That can completely
|
|
|
|
// be out of scope of our lookup.
|
|
|
|
bool hasSymbolicIndex = false;
|
2009-09-09 23:08:12 +08:00
|
|
|
|
2009-08-01 14:17:29 +08:00
|
|
|
while (superR) {
|
2010-10-26 08:06:17 +08:00
|
|
|
if (const Optional<SVal> &D =
|
2012-01-12 10:22:40 +08:00
|
|
|
getBindingForDerivedDefaultValue(B, superR, R, Ty))
|
2010-07-02 04:16:50 +08:00
|
|
|
return *D;
|
2009-09-09 23:08:12 +08:00
|
|
|
|
2012-04-03 08:03:34 +08:00
|
|
|
if (const ElementRegion *ER = dyn_cast<ElementRegion>(superR)) {
|
|
|
|
NonLoc index = ER->getIndex();
|
|
|
|
if (!index.isConstant())
|
|
|
|
hasSymbolicIndex = true;
|
|
|
|
}
|
|
|
|
|
2009-08-01 14:17:29 +08:00
|
|
|
// If our super region is a field or element itself, walk up the region
|
|
|
|
// hierarchy to see if there is a default value installed in an ancestor.
|
2010-10-26 08:06:17 +08:00
|
|
|
if (const SubRegion *SR = dyn_cast<SubRegion>(superR)) {
|
|
|
|
superR = SR->getSuperRegion();
|
2009-08-01 14:17:29 +08:00
|
|
|
continue;
|
|
|
|
}
|
|
|
|
break;
|
2009-08-06 09:20:57 +08:00
|
|
|
}
|
2009-09-09 23:08:12 +08:00
|
|
|
|
2010-01-05 10:18:06 +08:00
|
|
|
if (R->hasStackNonParametersStorage()) {
|
2012-04-03 08:03:34 +08:00
|
|
|
if (isa<ElementRegion>(R)) {
|
2009-08-07 06:33:36 +08:00
|
|
|
// Currently we don't reason specially about Clang-style vectors. Check
|
|
|
|
// if superR is a vector and if so return Unknown.
|
2011-08-13 04:02:48 +08:00
|
|
|
if (const TypedValueRegion *typedSuperR =
|
|
|
|
dyn_cast<TypedValueRegion>(superR)) {
|
2010-08-11 14:10:55 +08:00
|
|
|
if (typedSuperR->getValueType()->isVectorType())
|
2009-08-07 06:33:36 +08:00
|
|
|
return UnknownVal();
|
2009-09-09 23:08:12 +08:00
|
|
|
}
|
2009-08-07 06:33:36 +08:00
|
|
|
}
|
2009-09-09 23:08:12 +08:00
|
|
|
|
2012-04-03 08:03:34 +08:00
|
|
|
// FIXME: We also need to take ElementRegions with symbolic indexes into
|
|
|
|
// account. This case handles both directly accessing an ElementRegion
|
|
|
|
// with a symbolic offset, but also fields within an element with
|
|
|
|
// a symbolic offset.
|
|
|
|
if (hasSymbolicIndex)
|
|
|
|
return UnknownVal();
|
|
|
|
|
2009-06-25 12:50:44 +08:00
|
|
|
return UndefinedVal();
|
2009-08-07 06:33:36 +08:00
|
|
|
}
|
2009-09-09 23:08:12 +08:00
|
|
|
|
2009-07-03 06:16:42 +08:00
|
|
|
// All other values are symbolic.
|
2010-12-02 15:49:45 +08:00
|
|
|
return svalBuilder.getRegionValueSymbolVal(R);
|
2009-06-25 12:50:44 +08:00
|
|
|
}
|
2009-09-09 23:08:12 +08:00
|
|
|
|
2012-01-12 10:22:40 +08:00
|
|
|
SVal RegionStoreManager::getBindingForObjCIvar(Store store,
|
|
|
|
const ObjCIvarRegion* R) {
|
2009-07-15 14:09:28 +08:00
|
|
|
|
|
|
|
// Check if the region has a binding.
|
2010-02-05 11:01:53 +08:00
|
|
|
RegionBindings B = GetRegionBindings(store);
|
2009-07-15 14:09:28 +08:00
|
|
|
|
2010-03-31 04:30:52 +08:00
|
|
|
if (const Optional<SVal> &V = getDirectBinding(B, R))
|
2009-07-15 14:09:28 +08:00
|
|
|
return *V;
|
2009-09-09 23:08:12 +08:00
|
|
|
|
2009-07-15 14:09:28 +08:00
|
|
|
const MemRegion *superR = R->getSuperRegion();
|
|
|
|
|
2009-10-20 09:20:57 +08:00
|
|
|
// Check if the super region has a default binding.
|
2010-03-31 04:30:52 +08:00
|
|
|
if (const Optional<SVal> &V = getDefaultBinding(B, superR)) {
|
2009-07-15 14:09:28 +08:00
|
|
|
if (SymbolRef parentSym = V->getAsSymbol())
|
2010-12-02 15:49:45 +08:00
|
|
|
return svalBuilder.getDerivedRegionValueSymbolVal(parentSym, R);
|
2009-09-09 23:08:12 +08:00
|
|
|
|
2009-07-15 14:09:28 +08:00
|
|
|
// Other cases: give up.
|
|
|
|
return UnknownVal();
|
|
|
|
}
|
2009-09-09 23:08:12 +08:00
|
|
|
|
2012-01-12 10:22:40 +08:00
|
|
|
return getBindingForLazySymbol(R);
|
2009-07-21 06:58:02 +08:00
|
|
|
}
|
|
|
|
|
2012-01-12 10:22:40 +08:00
|
|
|
SVal RegionStoreManager::getBindingForVar(Store store, const VarRegion *R) {
|
2009-09-09 23:08:12 +08:00
|
|
|
|
2009-07-21 08:12:07 +08:00
|
|
|
// Check if the region has a binding.
|
2010-02-05 11:01:53 +08:00
|
|
|
RegionBindings B = GetRegionBindings(store);
|
2009-09-09 23:08:12 +08:00
|
|
|
|
2010-03-31 04:30:52 +08:00
|
|
|
if (const Optional<SVal> &V = getDirectBinding(B, R))
|
2009-07-21 08:12:07 +08:00
|
|
|
return *V;
|
2009-09-09 23:08:12 +08:00
|
|
|
|
2009-07-21 08:12:07 +08:00
|
|
|
// Lazily derive a value for the VarRegion.
|
|
|
|
const VarDecl *VD = R->getDecl();
|
2010-02-06 11:57:59 +08:00
|
|
|
QualType T = VD->getType();
|
|
|
|
const MemSpaceRegion *MS = R->getMemorySpace();
|
2010-03-10 15:20:03 +08:00
|
|
|
|
|
|
|
if (isa<UnknownSpaceRegion>(MS) ||
|
2010-02-06 11:57:59 +08:00
|
|
|
isa<StackArgumentsSpaceRegion>(MS))
|
2010-12-02 15:49:45 +08:00
|
|
|
return svalBuilder.getRegionValueSymbolVal(R);
|
2009-09-09 23:08:12 +08:00
|
|
|
|
2010-02-06 11:57:59 +08:00
|
|
|
if (isa<GlobalsSpaceRegion>(MS)) {
|
2010-07-02 04:16:50 +08:00
|
|
|
if (isa<NonStaticGlobalSpaceRegion>(MS)) {
|
2010-03-31 04:31:04 +08:00
|
|
|
// Is 'VD' declared constant? If so, retrieve the constant value.
|
|
|
|
QualType CT = Ctx.getCanonicalType(T);
|
|
|
|
if (CT.isConstQualified()) {
|
|
|
|
const Expr *Init = VD->getInit();
|
|
|
|
// Do the null check first, as we want to call 'IgnoreParenCasts'.
|
|
|
|
if (Init)
|
|
|
|
if (const IntegerLiteral *IL =
|
|
|
|
dyn_cast<IntegerLiteral>(Init->IgnoreParenCasts())) {
|
2010-12-02 15:49:45 +08:00
|
|
|
const nonloc::ConcreteInt &V = svalBuilder.makeIntVal(IL);
|
|
|
|
return svalBuilder.evalCast(V, Init->getType(), IL->getType());
|
2010-03-31 04:31:04 +08:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2012-01-12 10:22:40 +08:00
|
|
|
if (const Optional<SVal> &V
|
|
|
|
= getBindingForDerivedDefaultValue(B, MS, R, CT))
|
2010-07-02 04:16:50 +08:00
|
|
|
return V.getValue();
|
|
|
|
|
2010-12-02 15:49:45 +08:00
|
|
|
return svalBuilder.getRegionValueSymbolVal(R);
|
2010-03-31 04:31:04 +08:00
|
|
|
}
|
2009-09-09 23:08:12 +08:00
|
|
|
|
2010-02-06 11:57:59 +08:00
|
|
|
if (T->isIntegerType())
|
2010-12-02 15:49:45 +08:00
|
|
|
return svalBuilder.makeIntVal(0, T);
|
2010-02-06 12:04:46 +08:00
|
|
|
if (T->isPointerType())
|
2010-12-02 15:49:45 +08:00
|
|
|
return svalBuilder.makeNull();
|
2010-02-06 12:04:46 +08:00
|
|
|
|
2010-03-10 15:20:03 +08:00
|
|
|
return UnknownVal();
|
2010-02-06 11:57:59 +08:00
|
|
|
}
|
2010-03-10 15:20:03 +08:00
|
|
|
|
2009-07-21 08:12:07 +08:00
|
|
|
return UndefinedVal();
|
|
|
|
}
|
|
|
|
|
2012-01-12 10:22:40 +08:00
|
|
|
SVal RegionStoreManager::getBindingForLazySymbol(const TypedValueRegion *R) {
|
2009-07-15 14:09:28 +08:00
|
|
|
// All other values are symbolic.
|
2010-12-02 15:49:45 +08:00
|
|
|
return svalBuilder.getRegionValueSymbolVal(R);
|
2009-07-15 14:09:28 +08:00
|
|
|
}
|
|
|
|
|
2012-01-12 10:22:40 +08:00
|
|
|
SVal RegionStoreManager::getBindingForStruct(Store store,
|
2011-08-13 04:02:48 +08:00
|
|
|
const TypedValueRegion* R) {
|
2012-01-16 13:16:03 +08:00
|
|
|
assert(R->getValueType()->isStructureOrClassType());
|
2011-03-09 07:18:00 +08:00
|
|
|
return svalBuilder.makeLazyCompoundVal(StoreRef(store, *this), R);
|
2008-10-31 15:16:08 +08:00
|
|
|
}
|
|
|
|
|
2012-01-12 10:22:40 +08:00
|
|
|
SVal RegionStoreManager::getBindingForArray(Store store,
|
2011-08-13 04:02:48 +08:00
|
|
|
const TypedValueRegion * R) {
|
2010-09-15 07:29:38 +08:00
|
|
|
assert(Ctx.getAsConstantArrayType(R->getValueType()));
|
2011-03-09 07:18:00 +08:00
|
|
|
return svalBuilder.makeLazyCompoundVal(StoreRef(store, *this), R);
|
2009-05-03 08:27:40 +08:00
|
|
|
}
|
|
|
|
|
2011-07-29 07:07:46 +08:00
|
|
|
bool RegionStoreManager::includedInBindings(Store store,
|
|
|
|
const MemRegion *region) const {
|
|
|
|
RegionBindings B = GetRegionBindings(store);
|
|
|
|
region = region->getBaseRegion();
|
|
|
|
|
|
|
|
for (RegionBindings::iterator it = B.begin(), ei = B.end(); it != ei; ++it) {
|
|
|
|
const BindingKey &K = it.getKey();
|
|
|
|
if (region == K.getRegion())
|
|
|
|
return true;
|
|
|
|
const SVal &D = it.getData();
|
|
|
|
if (const MemRegion *r = D.getAsRegion())
|
|
|
|
if (r == region)
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
2009-06-17 06:36:44 +08:00
|
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
// Binding values to regions.
|
|
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
|
2011-02-19 09:59:33 +08:00
|
|
|
StoreRef RegionStoreManager::Remove(Store store, Loc L) {
|
2009-06-17 06:36:44 +08:00
|
|
|
if (isa<loc::MemRegionVal>(L))
|
2010-01-11 10:33:26 +08:00
|
|
|
if (const MemRegion* R = cast<loc::MemRegionVal>(L).getRegion())
|
2011-02-19 09:59:33 +08:00
|
|
|
return StoreRef(removeBinding(GetRegionBindings(store),
|
|
|
|
R).getRootWithoutRetain(),
|
|
|
|
*this);
|
2009-09-09 23:08:12 +08:00
|
|
|
|
2011-02-19 09:59:33 +08:00
|
|
|
return StoreRef(store, *this);
|
2009-06-17 06:36:44 +08:00
|
|
|
}
|
|
|
|
|
2011-02-19 09:59:33 +08:00
|
|
|
StoreRef RegionStoreManager::Bind(Store store, Loc L, SVal V) {
|
2009-06-28 18:16:11 +08:00
|
|
|
if (isa<loc::ConcreteInt>(L))
|
2011-02-19 09:59:33 +08:00
|
|
|
return StoreRef(store, *this);
|
2009-06-28 18:16:11 +08:00
|
|
|
|
2008-12-20 14:32:12 +08:00
|
|
|
// If we get here, the location should be a region.
|
2009-08-01 14:17:29 +08:00
|
|
|
const MemRegion *R = cast<loc::MemRegionVal>(L).getRegion();
|
2009-09-09 23:08:12 +08:00
|
|
|
|
2008-12-20 14:32:12 +08:00
|
|
|
// Check if the region is a struct region.
|
2011-08-13 04:02:48 +08:00
|
|
|
if (const TypedValueRegion* TR = dyn_cast<TypedValueRegion>(R))
|
2010-08-11 14:10:55 +08:00
|
|
|
if (TR->getValueType()->isStructureOrClassType())
|
2010-02-05 13:06:13 +08:00
|
|
|
return BindStruct(store, TR, V);
|
2009-09-09 23:08:12 +08:00
|
|
|
|
2009-08-01 14:17:29 +08:00
|
|
|
if (const ElementRegion *ER = dyn_cast<ElementRegion>(R)) {
|
|
|
|
if (ER->getIndex().isZeroConstant()) {
|
2011-08-13 04:02:48 +08:00
|
|
|
if (const TypedValueRegion *superR =
|
|
|
|
dyn_cast<TypedValueRegion>(ER->getSuperRegion())) {
|
2010-08-11 14:10:55 +08:00
|
|
|
QualType superTy = superR->getValueType();
|
2009-09-22 06:58:52 +08:00
|
|
|
// For now, just invalidate the fields of the struct/union/class.
|
2010-08-21 19:03:37 +08:00
|
|
|
// This is for test rdar_test_7185607 in misc-ps-region-store.m.
|
2009-09-22 06:58:52 +08:00
|
|
|
// FIXME: Precisely handle the fields of the record.
|
2010-08-05 11:28:45 +08:00
|
|
|
if (superTy->isStructureOrClassType())
|
|
|
|
return KillStruct(store, superR, UnknownVal());
|
2009-08-01 14:17:29 +08:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2009-09-24 12:11:44 +08:00
|
|
|
else if (const SymbolicRegion *SR = dyn_cast<SymbolicRegion>(R)) {
|
|
|
|
// Binding directly to a symbolic region should be treated as binding
|
|
|
|
// to element 0.
|
2010-08-15 18:08:38 +08:00
|
|
|
QualType T = SR->getSymbol()->getType(Ctx);
|
2010-03-10 15:20:03 +08:00
|
|
|
|
Add (initial?) static analyzer support for handling C++ references.
This change was a lot bigger than I originally anticipated; among
other things it requires us storing more information in the CFG to
record what block-level expressions need to be evaluated as lvalues.
The big change is that CFGBlocks no longer contain Stmt*'s by
CFGElements. Currently CFGElements just wrap Stmt*, but they also
store a bit indicating whether the block-level expression should be
evalauted as an lvalue. DeclStmts involving the initialization of a
reference require us treating the initialization expression as an
lvalue, even though that information isn't recorded in the AST.
Conceptually this change isn't that complicated, but it required
bubbling up the data through the CFGBuilder, to GRCoreEngine, and
eventually to GRExprEngine.
The addition of CFGElement is also useful for when we want to handle
more control-flow constructs or other data we want to keep in the CFG
that isn't represented well with just a block of statements.
In GRExprEngine, this patch introduces logic for evaluating the
lvalues of references, which currently retrieves the internal "pointer
value" that the reference represents. EvalLoad does a two stage load
to catch null dereferences involving an invalid reference (although
this could possibly be caught earlier during the initialization of a
reference).
Symbols are currently symbolicated using the reference type, instead
of a pointer type, and special handling is required creating
ElementRegions that layer on SymbolicRegions (see the changes to
RegionStoreManager).
Along the way, the DeadStoresChecker also silences warnings involving
dead stores to references. This was the original change I introduced
(which I wrote test cases for) that I realized caused GRExprEngine to
crash.
llvm-svn: 91501
2009-12-16 11:18:58 +08:00
|
|
|
// FIXME: Is this the right way to handle symbols that are references?
|
|
|
|
if (const PointerType *PT = T->getAs<PointerType>())
|
|
|
|
T = PT->getPointeeType();
|
|
|
|
else
|
|
|
|
T = T->getAs<ReferenceType>()->getPointeeType();
|
|
|
|
|
2009-09-24 12:11:44 +08:00
|
|
|
R = GetElementZeroRegion(SR, T);
|
|
|
|
}
|
2009-09-09 23:08:12 +08:00
|
|
|
|
2009-08-01 14:17:29 +08:00
|
|
|
// Perform the binding.
|
2010-02-05 13:06:13 +08:00
|
|
|
RegionBindings B = GetRegionBindings(store);
|
2011-02-19 09:59:33 +08:00
|
|
|
return StoreRef(addBinding(B, R, BindingKey::Direct,
|
|
|
|
V).getRootWithoutRetain(), *this);
|
2008-12-16 10:36:30 +08:00
|
|
|
}
|
|
|
|
|
2011-02-19 09:59:33 +08:00
|
|
|
StoreRef RegionStoreManager::BindDecl(Store store, const VarRegion *VR,
|
|
|
|
SVal InitVal) {
|
2008-10-21 13:29:26 +08:00
|
|
|
|
2009-11-04 08:09:15 +08:00
|
|
|
QualType T = VR->getDecl()->getType();
|
2008-10-21 13:29:26 +08:00
|
|
|
|
2009-01-21 14:57:53 +08:00
|
|
|
if (T->isArrayType())
|
2010-02-05 13:06:13 +08:00
|
|
|
return BindArray(store, VR, InitVal);
|
2010-04-27 05:31:17 +08:00
|
|
|
if (T->isStructureOrClassType())
|
2010-02-05 13:06:13 +08:00
|
|
|
return BindStruct(store, VR, InitVal);
|
2008-10-31 18:24:47 +08:00
|
|
|
|
2010-12-02 15:49:45 +08:00
|
|
|
return Bind(store, svalBuilder.makeLoc(VR), InitVal);
|
2008-10-21 13:29:26 +08:00
|
|
|
}
|
|
|
|
|
2008-12-20 14:32:12 +08:00
|
|
|
// FIXME: this method should be merged into Bind().
|
2011-02-19 09:59:33 +08:00
|
|
|
StoreRef RegionStoreManager::BindCompoundLiteral(Store store,
|
|
|
|
const CompoundLiteralExpr *CL,
|
|
|
|
const LocationContext *LC,
|
|
|
|
SVal V) {
|
2010-02-05 13:06:13 +08:00
|
|
|
return Bind(store, loc::MemRegionVal(MRMgr.getCompoundLiteralRegion(CL, LC)),
|
2009-12-08 06:05:27 +08:00
|
|
|
V);
|
2008-11-07 18:38:33 +08:00
|
|
|
}
|
|
|
|
|
2011-02-19 09:59:33 +08:00
|
|
|
StoreRef RegionStoreManager::setImplicitDefaultValue(Store store,
|
|
|
|
const MemRegion *R,
|
|
|
|
QualType T) {
|
2009-11-20 04:20:24 +08:00
|
|
|
RegionBindings B = GetRegionBindings(store);
|
|
|
|
SVal V;
|
|
|
|
|
2011-02-17 05:13:32 +08:00
|
|
|
if (Loc::isLocType(T))
|
2010-12-02 15:49:45 +08:00
|
|
|
V = svalBuilder.makeNull();
|
2009-11-20 04:20:24 +08:00
|
|
|
else if (T->isIntegerType())
|
2010-12-02 15:49:45 +08:00
|
|
|
V = svalBuilder.makeZeroVal(T);
|
2010-04-27 05:31:17 +08:00
|
|
|
else if (T->isStructureOrClassType() || T->isArrayType()) {
|
2009-11-20 04:20:24 +08:00
|
|
|
// Set the default value to a zero constant when it is a structure
|
|
|
|
// or array. The type doesn't really matter.
|
2010-12-02 15:49:45 +08:00
|
|
|
V = svalBuilder.makeZeroVal(Ctx.IntTy);
|
2009-11-20 04:20:24 +08:00
|
|
|
}
|
|
|
|
else {
|
2011-06-28 04:36:38 +08:00
|
|
|
// We can't represent values of this type, but we still need to set a value
|
|
|
|
// to record that the region has been initialized.
|
|
|
|
// If this assertion ever fires, a new case should be added above -- we
|
|
|
|
// should know how to default-initialize any value we can symbolicate.
|
|
|
|
assert(!SymbolManager::canSymbolicate(T) && "This type is representable");
|
|
|
|
V = UnknownVal();
|
2009-11-20 04:20:24 +08:00
|
|
|
}
|
2010-01-11 08:07:44 +08:00
|
|
|
|
2011-02-19 09:59:33 +08:00
|
|
|
return StoreRef(addBinding(B, R, BindingKey::Default,
|
|
|
|
V).getRootWithoutRetain(), *this);
|
2009-11-20 04:20:24 +08:00
|
|
|
}
|
2010-03-10 15:20:03 +08:00
|
|
|
|
2011-08-13 04:02:48 +08:00
|
|
|
StoreRef RegionStoreManager::BindArray(Store store, const TypedValueRegion* R,
|
2011-02-19 09:59:33 +08:00
|
|
|
SVal Init) {
|
2010-03-10 15:20:03 +08:00
|
|
|
|
2010-08-11 14:10:55 +08:00
|
|
|
const ArrayType *AT =cast<ArrayType>(Ctx.getCanonicalType(R->getValueType()));
|
2010-03-10 15:20:03 +08:00
|
|
|
QualType ElementTy = AT->getElementType();
|
2010-01-27 07:51:00 +08:00
|
|
|
Optional<uint64_t> Size;
|
2010-03-10 15:20:03 +08:00
|
|
|
|
2010-01-27 07:51:00 +08:00
|
|
|
if (const ConstantArrayType* CAT = dyn_cast<ConstantArrayType>(AT))
|
|
|
|
Size = CAT->getSize().getZExtValue();
|
2010-03-10 15:20:03 +08:00
|
|
|
|
2010-07-29 14:40:33 +08:00
|
|
|
// Check if the init expr is a string literal.
|
|
|
|
if (loc::MemRegionVal *MRV = dyn_cast<loc::MemRegionVal>(&Init)) {
|
|
|
|
const StringRegion *S = cast<StringRegion>(MRV->getRegion());
|
2008-12-20 14:32:12 +08:00
|
|
|
|
2010-07-29 14:40:33 +08:00
|
|
|
// Treat the string as a lazy compound value.
|
|
|
|
nonloc::LazyCompoundVal LCV =
|
2011-03-09 07:18:00 +08:00
|
|
|
cast<nonloc::LazyCompoundVal>(svalBuilder.
|
|
|
|
makeLazyCompoundVal(StoreRef(store, *this), S));
|
2010-07-29 14:40:33 +08:00
|
|
|
return CopyLazyBindings(LCV, store, R);
|
2008-11-30 13:49:49 +08:00
|
|
|
}
|
2008-10-31 18:24:47 +08:00
|
|
|
|
2009-08-06 09:20:57 +08:00
|
|
|
// Handle lazy compound values.
|
|
|
|
if (nonloc::LazyCompoundVal *LCV = dyn_cast<nonloc::LazyCompoundVal>(&Init))
|
2010-02-05 13:06:13 +08:00
|
|
|
return CopyLazyBindings(*LCV, store, R);
|
2009-09-09 23:08:12 +08:00
|
|
|
|
|
|
|
// Remaining case: explicit compound values.
|
2010-03-10 15:20:03 +08:00
|
|
|
|
2009-11-20 04:20:24 +08:00
|
|
|
if (Init.isUnknown())
|
2010-03-10 15:20:03 +08:00
|
|
|
return setImplicitDefaultValue(store, R, ElementTy);
|
|
|
|
|
2008-10-31 18:24:47 +08:00
|
|
|
nonloc::CompoundVal& CV = cast<nonloc::CompoundVal>(Init);
|
|
|
|
nonloc::CompoundVal::iterator VI = CV.begin(), VE = CV.end();
|
2009-07-16 09:33:37 +08:00
|
|
|
uint64_t i = 0;
|
2009-09-09 23:08:12 +08:00
|
|
|
|
2011-02-19 09:59:33 +08:00
|
|
|
StoreRef newStore(store, *this);
|
2010-01-27 07:51:00 +08:00
|
|
|
for (; Size.hasValue() ? i < Size.getValue() : true ; ++i, ++VI) {
|
2009-06-23 13:23:38 +08:00
|
|
|
// The init list might be shorter than the array length.
|
2008-12-20 14:32:12 +08:00
|
|
|
if (VI == VE)
|
|
|
|
break;
|
2008-10-24 16:42:28 +08:00
|
|
|
|
2010-12-02 15:49:45 +08:00
|
|
|
const NonLoc &Idx = svalBuilder.makeArrayIndex(i);
|
2010-08-15 18:08:38 +08:00
|
|
|
const ElementRegion *ER = MRMgr.getElementRegion(ElementTy, Idx, R, Ctx);
|
2008-11-19 19:06:24 +08:00
|
|
|
|
2010-04-27 05:31:17 +08:00
|
|
|
if (ElementTy->isStructureOrClassType())
|
2011-02-19 09:59:33 +08:00
|
|
|
newStore = BindStruct(newStore.getStore(), ER, *VI);
|
2010-08-20 09:05:59 +08:00
|
|
|
else if (ElementTy->isArrayType())
|
2011-02-19 09:59:33 +08:00
|
|
|
newStore = BindArray(newStore.getStore(), ER, *VI);
|
2008-12-20 14:32:12 +08:00
|
|
|
else
|
2011-02-19 09:59:33 +08:00
|
|
|
newStore = Bind(newStore.getStore(), svalBuilder.makeLoc(ER), *VI);
|
2008-11-19 19:06:24 +08:00
|
|
|
}
|
|
|
|
|
2009-11-20 04:20:24 +08:00
|
|
|
// If the init list is shorter than the array length, set the
|
|
|
|
// array default value.
|
2010-01-27 07:51:00 +08:00
|
|
|
if (Size.hasValue() && i < Size.getValue())
|
2011-02-19 09:59:33 +08:00
|
|
|
newStore = setImplicitDefaultValue(newStore.getStore(), R, ElementTy);
|
2009-06-23 13:23:38 +08:00
|
|
|
|
2011-02-19 09:59:33 +08:00
|
|
|
return newStore;
|
2008-11-19 19:06:24 +08:00
|
|
|
}
|
|
|
|
|
2011-08-13 04:02:48 +08:00
|
|
|
StoreRef RegionStoreManager::BindStruct(Store store, const TypedValueRegion* R,
|
2011-02-19 09:59:33 +08:00
|
|
|
SVal V) {
|
2009-09-09 23:08:12 +08:00
|
|
|
|
2009-06-18 06:02:04 +08:00
|
|
|
if (!Features.supportsFields())
|
2011-02-19 09:59:33 +08:00
|
|
|
return StoreRef(store, *this);
|
2009-09-09 23:08:12 +08:00
|
|
|
|
2010-08-11 14:10:55 +08:00
|
|
|
QualType T = R->getValueType();
|
2010-04-27 05:31:17 +08:00
|
|
|
assert(T->isStructureOrClassType());
|
2008-10-31 18:53:01 +08:00
|
|
|
|
2009-07-30 05:53:49 +08:00
|
|
|
const RecordType* RT = T->getAs<RecordType>();
|
2011-08-13 07:37:29 +08:00
|
|
|
RecordDecl *RD = RT->getDecl();
|
2009-03-11 17:07:35 +08:00
|
|
|
|
2011-10-07 14:10:15 +08:00
|
|
|
if (!RD->isCompleteDefinition())
|
2011-02-19 09:59:33 +08:00
|
|
|
return StoreRef(store, *this);
|
2008-10-31 18:53:01 +08:00
|
|
|
|
2009-08-06 09:20:57 +08:00
|
|
|
// Handle lazy compound values.
|
2009-10-11 16:08:02 +08:00
|
|
|
if (const nonloc::LazyCompoundVal *LCV=dyn_cast<nonloc::LazyCompoundVal>(&V))
|
2010-02-05 13:06:13 +08:00
|
|
|
return CopyLazyBindings(*LCV, store, R);
|
2009-09-09 23:08:12 +08:00
|
|
|
|
2010-07-29 08:28:47 +08:00
|
|
|
// We may get non-CompoundVal accidentally due to imprecise cast logic or
|
|
|
|
// that we are binding symbolic struct value. Kill the field values, and if
|
|
|
|
// the value is symbolic go and bind it as a "default" binding.
|
2010-08-18 07:29:06 +08:00
|
|
|
if (V.isUnknown() || !isa<nonloc::CompoundVal>(V)) {
|
|
|
|
SVal SV = isa<nonloc::SymbolVal>(V) ? V : UnknownVal();
|
|
|
|
return KillStruct(store, R, SV);
|
|
|
|
}
|
2009-06-11 17:11:27 +08:00
|
|
|
|
2008-12-20 14:32:12 +08:00
|
|
|
nonloc::CompoundVal& CV = cast<nonloc::CompoundVal>(V);
|
2008-10-31 18:53:01 +08:00
|
|
|
nonloc::CompoundVal::iterator VI = CV.begin(), VE = CV.end();
|
2009-06-23 13:43:16 +08:00
|
|
|
|
|
|
|
RecordDecl::field_iterator FI, FE;
|
2011-02-19 09:59:33 +08:00
|
|
|
StoreRef newStore(store, *this);
|
|
|
|
|
2011-11-17 04:29:27 +08:00
|
|
|
for (FI = RD->field_begin(), FE = RD->field_end(); FI != FE; ++FI) {
|
2008-10-31 18:53:01 +08:00
|
|
|
|
2009-06-23 13:43:16 +08:00
|
|
|
if (VI == VE)
|
2008-12-20 14:32:12 +08:00
|
|
|
break;
|
2008-10-31 19:02:48 +08:00
|
|
|
|
2011-11-17 04:29:27 +08:00
|
|
|
// Skip any unnamed bitfields to stay in sync with the initializers.
|
2012-04-30 10:36:29 +08:00
|
|
|
if (FI->isUnnamedBitfield())
|
2011-11-17 04:29:27 +08:00
|
|
|
continue;
|
|
|
|
|
2012-04-30 10:36:29 +08:00
|
|
|
QualType FTy = FI->getType();
|
|
|
|
const FieldRegion* FR = MRMgr.getFieldRegion(&*FI, R);
|
2008-10-31 19:02:48 +08:00
|
|
|
|
2009-09-23 05:19:14 +08:00
|
|
|
if (FTy->isArrayType())
|
2011-02-19 09:59:33 +08:00
|
|
|
newStore = BindArray(newStore.getStore(), FR, *VI);
|
2010-04-27 05:31:17 +08:00
|
|
|
else if (FTy->isStructureOrClassType())
|
2011-02-19 09:59:33 +08:00
|
|
|
newStore = BindStruct(newStore.getStore(), FR, *VI);
|
2009-09-23 05:19:14 +08:00
|
|
|
else
|
2011-02-19 09:59:33 +08:00
|
|
|
newStore = Bind(newStore.getStore(), svalBuilder.makeLoc(FR), *VI);
|
2011-11-17 04:29:27 +08:00
|
|
|
++VI;
|
2008-11-19 19:06:24 +08:00
|
|
|
}
|
|
|
|
|
2009-06-23 13:43:16 +08:00
|
|
|
// There may be fewer values in the initialize list than the fields of struct.
|
2009-10-11 16:08:02 +08:00
|
|
|
if (FI != FE) {
|
2011-02-19 09:59:33 +08:00
|
|
|
RegionBindings B = GetRegionBindings(newStore.getStore());
|
2010-12-02 15:49:45 +08:00
|
|
|
B = addBinding(B, R, BindingKey::Default, svalBuilder.makeIntVal(0, false));
|
2011-02-19 09:59:33 +08:00
|
|
|
newStore = StoreRef(B.getRootWithoutRetain(), *this);
|
2009-10-11 16:08:02 +08:00
|
|
|
}
|
2009-06-23 13:43:16 +08:00
|
|
|
|
2011-02-19 09:59:33 +08:00
|
|
|
return newStore;
|
2008-11-19 19:06:24 +08:00
|
|
|
}
|
|
|
|
|
2011-02-19 09:59:33 +08:00
|
|
|
StoreRef RegionStoreManager::KillStruct(Store store, const TypedRegion* R,
|
2010-07-29 08:28:47 +08:00
|
|
|
SVal DefaultVal) {
|
2011-01-13 14:58:15 +08:00
|
|
|
BindingKey key = BindingKey::Make(R, BindingKey::Default);
|
|
|
|
|
|
|
|
// The BindingKey may be "invalid" if we cannot handle the region binding
|
|
|
|
// explicitly. One example is something like array[index], where index
|
|
|
|
// is a symbolic value. In such cases, we want to invalidate the entire
|
|
|
|
// array, as the index assignment could have been to any element. In
|
|
|
|
// the case of nested symbolic indices, we need to march up the region
|
|
|
|
// hierarchy untile we reach a region whose binding we can reason about.
|
|
|
|
const SubRegion *subReg = R;
|
2011-01-13 20:30:12 +08:00
|
|
|
|
2011-01-13 14:58:15 +08:00
|
|
|
while (!key.isValid()) {
|
|
|
|
if (const SubRegion *tmp = dyn_cast<SubRegion>(subReg->getSuperRegion())) {
|
|
|
|
subReg = tmp;
|
|
|
|
key = BindingKey::Make(tmp, BindingKey::Default);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
// Remove the old bindings, using 'subReg' as the root of all regions
|
|
|
|
// we will invalidate.
|
2009-10-11 16:08:02 +08:00
|
|
|
RegionBindings B = GetRegionBindings(store);
|
2012-02-05 10:12:40 +08:00
|
|
|
OwningPtr<RegionStoreSubRegionMap>
|
2009-10-11 16:08:02 +08:00
|
|
|
SubRegions(getRegionStoreSubRegionMap(store));
|
2011-01-13 14:58:15 +08:00
|
|
|
RemoveSubRegionBindings(B, subReg, *SubRegions);
|
2009-01-13 09:49:57 +08:00
|
|
|
|
2009-06-25 13:52:16 +08:00
|
|
|
// Set the default value of the struct region to "unknown".
|
2011-01-13 14:58:15 +08:00
|
|
|
if (!key.isValid())
|
2011-02-19 09:59:33 +08:00
|
|
|
return StoreRef(B.getRootWithoutRetain(), *this);
|
2011-01-13 14:58:15 +08:00
|
|
|
|
2011-02-19 09:59:33 +08:00
|
|
|
return StoreRef(addBinding(B, key, DefaultVal).getRootWithoutRetain(), *this);
|
2009-01-13 09:49:57 +08:00
|
|
|
}
|
|
|
|
|
2011-02-19 09:59:33 +08:00
|
|
|
StoreRef RegionStoreManager::CopyLazyBindings(nonloc::LazyCompoundVal V,
|
|
|
|
Store store,
|
|
|
|
const TypedRegion *R) {
|
2009-08-06 09:20:57 +08:00
|
|
|
|
|
|
|
// Nuke the old bindings stemming from R.
|
2010-02-05 13:06:13 +08:00
|
|
|
RegionBindings B = GetRegionBindings(store);
|
2009-06-17 06:36:44 +08:00
|
|
|
|
2012-02-05 10:12:40 +08:00
|
|
|
OwningPtr<RegionStoreSubRegionMap>
|
2010-02-05 13:06:13 +08:00
|
|
|
SubRegions(getRegionStoreSubRegionMap(store));
|
2009-08-06 09:20:57 +08:00
|
|
|
|
2009-09-09 23:08:12 +08:00
|
|
|
// B and DVM are updated after the call to RemoveSubRegionBindings.
|
2009-10-11 16:08:02 +08:00
|
|
|
RemoveSubRegionBindings(B, R, *SubRegions.get());
|
2009-09-09 23:08:12 +08:00
|
|
|
|
2009-08-06 09:20:57 +08:00
|
|
|
// Now copy the bindings. This amounts to just binding 'V' to 'R'. This
|
|
|
|
// results in a zero-copy algorithm.
|
2011-03-17 11:51:51 +08:00
|
|
|
return StoreRef(addBinding(B, R, BindingKey::Default,
|
2011-02-19 09:59:33 +08:00
|
|
|
V).getRootWithoutRetain(), *this);
|
2010-01-11 08:07:44 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
// "Raw" retrievals and bindings.
|
|
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
|
2010-01-11 10:33:26 +08:00
|
|
|
|
2010-11-24 08:54:37 +08:00
|
|
|
RegionBindings RegionStoreManager::addBinding(RegionBindings B, BindingKey K,
|
|
|
|
SVal V) {
|
2010-08-17 04:53:01 +08:00
|
|
|
if (!K.isValid())
|
2010-08-16 09:15:17 +08:00
|
|
|
return B;
|
2010-11-24 08:54:37 +08:00
|
|
|
return RBFactory.add(B, K, V);
|
2010-01-11 08:07:44 +08:00
|
|
|
}
|
|
|
|
|
2010-11-24 08:54:37 +08:00
|
|
|
RegionBindings RegionStoreManager::addBinding(RegionBindings B,
|
|
|
|
const MemRegion *R,
|
|
|
|
BindingKey::Kind k, SVal V) {
|
|
|
|
return addBinding(B, BindingKey::Make(R, k), V);
|
2010-01-11 08:07:44 +08:00
|
|
|
}
|
|
|
|
|
2010-11-24 08:54:37 +08:00
|
|
|
const SVal *RegionStoreManager::lookup(RegionBindings B, BindingKey K) {
|
2010-08-17 04:53:01 +08:00
|
|
|
if (!K.isValid())
|
2010-08-16 09:15:17 +08:00
|
|
|
return NULL;
|
2010-01-11 08:07:44 +08:00
|
|
|
return B.lookup(K);
|
|
|
|
}
|
|
|
|
|
2010-11-24 08:54:37 +08:00
|
|
|
const SVal *RegionStoreManager::lookup(RegionBindings B,
|
2010-02-03 11:06:46 +08:00
|
|
|
const MemRegion *R,
|
|
|
|
BindingKey::Kind k) {
|
2010-11-24 08:54:37 +08:00
|
|
|
return lookup(B, BindingKey::Make(R, k));
|
2010-01-11 08:07:44 +08:00
|
|
|
}
|
|
|
|
|
2010-11-24 08:54:37 +08:00
|
|
|
RegionBindings RegionStoreManager::removeBinding(RegionBindings B,
|
|
|
|
BindingKey K) {
|
2010-08-17 04:53:01 +08:00
|
|
|
if (!K.isValid())
|
2010-08-16 09:15:17 +08:00
|
|
|
return B;
|
2010-11-24 08:54:37 +08:00
|
|
|
return RBFactory.remove(B, K);
|
2010-01-11 08:07:44 +08:00
|
|
|
}
|
|
|
|
|
2010-11-24 08:54:37 +08:00
|
|
|
RegionBindings RegionStoreManager::removeBinding(RegionBindings B,
|
|
|
|
const MemRegion *R,
|
|
|
|
BindingKey::Kind k){
|
|
|
|
return removeBinding(B, BindingKey::Make(R, k));
|
2010-01-11 08:07:44 +08:00
|
|
|
}
|
|
|
|
|
2009-06-17 06:36:44 +08:00
|
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
// State pruning.
|
|
|
|
//===----------------------------------------------------------------------===//
|
2010-03-10 15:20:03 +08:00
|
|
|
|
2010-03-11 00:32:56 +08:00
|
|
|
namespace {
|
2011-01-15 04:34:15 +08:00
|
|
|
class removeDeadBindingsWorker :
|
|
|
|
public ClusterAnalysis<removeDeadBindingsWorker> {
|
2011-07-23 18:55:15 +08:00
|
|
|
SmallVector<const SymbolicRegion*, 12> Postponed;
|
2010-03-11 00:32:56 +08:00
|
|
|
SymbolReaper &SymReaper;
|
2010-03-17 11:35:08 +08:00
|
|
|
const StackFrameContext *CurrentLCtx;
|
2010-07-02 04:16:50 +08:00
|
|
|
|
2010-03-11 00:32:56 +08:00
|
|
|
public:
|
2012-01-12 10:22:40 +08:00
|
|
|
removeDeadBindingsWorker(RegionStoreManager &rm,
|
|
|
|
ProgramStateManager &stateMgr,
|
2010-03-11 00:32:56 +08:00
|
|
|
RegionBindings b, SymbolReaper &symReaper,
|
2010-07-02 04:09:55 +08:00
|
|
|
const StackFrameContext *LCtx)
|
2011-01-15 04:34:15 +08:00
|
|
|
: ClusterAnalysis<removeDeadBindingsWorker>(rm, stateMgr, b,
|
2010-10-26 08:06:15 +08:00
|
|
|
/* includeGlobals = */ false),
|
2010-07-02 04:09:55 +08:00
|
|
|
SymReaper(symReaper), CurrentLCtx(LCtx) {}
|
2010-03-11 00:32:56 +08:00
|
|
|
|
|
|
|
// Called by ClusterAnalysis.
|
|
|
|
void VisitAddedToCluster(const MemRegion *baseR, RegionCluster &C);
|
|
|
|
void VisitCluster(const MemRegion *baseR, BindingKey *I, BindingKey *E);
|
|
|
|
|
2010-04-01 08:15:55 +08:00
|
|
|
void VisitBindingKey(BindingKey K);
|
2010-03-11 00:32:56 +08:00
|
|
|
bool UpdatePostponed();
|
|
|
|
void VisitBinding(SVal V);
|
|
|
|
};
|
|
|
|
}
|
2009-09-09 23:08:12 +08:00
|
|
|
|
2011-01-15 04:34:15 +08:00
|
|
|
void removeDeadBindingsWorker::VisitAddedToCluster(const MemRegion *baseR,
|
2010-03-11 00:32:56 +08:00
|
|
|
RegionCluster &C) {
|
2010-03-10 15:20:03 +08:00
|
|
|
|
2010-03-11 00:32:56 +08:00
|
|
|
if (const VarRegion *VR = dyn_cast<VarRegion>(baseR)) {
|
2010-07-02 04:09:55 +08:00
|
|
|
if (SymReaper.isLive(VR))
|
2010-03-11 00:32:56 +08:00
|
|
|
AddToWorkList(baseR, C);
|
2010-03-10 15:20:03 +08:00
|
|
|
|
2010-03-11 00:32:56 +08:00
|
|
|
return;
|
2009-06-17 06:36:44 +08:00
|
|
|
}
|
2010-03-10 15:20:03 +08:00
|
|
|
|
2010-03-11 00:32:56 +08:00
|
|
|
if (const SymbolicRegion *SR = dyn_cast<SymbolicRegion>(baseR)) {
|
|
|
|
if (SymReaper.isLive(SR->getSymbol()))
|
|
|
|
AddToWorkList(SR, C);
|
|
|
|
else
|
|
|
|
Postponed.push_back(SR);
|
2010-03-10 15:20:03 +08:00
|
|
|
|
2010-03-11 00:32:56 +08:00
|
|
|
return;
|
2009-06-17 06:36:44 +08:00
|
|
|
}
|
2010-03-17 11:35:08 +08:00
|
|
|
|
2010-07-02 04:16:50 +08:00
|
|
|
if (isa<NonStaticGlobalSpaceRegion>(baseR)) {
|
|
|
|
AddToWorkList(baseR, C);
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2010-03-17 11:35:08 +08:00
|
|
|
// CXXThisRegion in the current or parent location context is live.
|
|
|
|
if (const CXXThisRegion *TR = dyn_cast<CXXThisRegion>(baseR)) {
|
2010-07-02 04:16:50 +08:00
|
|
|
const StackArgumentsSpaceRegion *StackReg =
|
2010-03-17 11:35:08 +08:00
|
|
|
cast<StackArgumentsSpaceRegion>(TR->getSuperRegion());
|
|
|
|
const StackFrameContext *RegCtx = StackReg->getStackFrame();
|
|
|
|
if (RegCtx == CurrentLCtx || RegCtx->isParentOf(CurrentLCtx))
|
|
|
|
AddToWorkList(TR, C);
|
|
|
|
}
|
2010-03-11 00:32:56 +08:00
|
|
|
}
|
2009-09-09 23:08:12 +08:00
|
|
|
|
2011-01-15 04:34:15 +08:00
|
|
|
void removeDeadBindingsWorker::VisitCluster(const MemRegion *baseR,
|
2010-03-11 00:32:56 +08:00
|
|
|
BindingKey *I, BindingKey *E) {
|
2010-04-01 08:15:55 +08:00
|
|
|
for ( ; I != E; ++I)
|
|
|
|
VisitBindingKey(*I);
|
2010-03-11 00:32:56 +08:00
|
|
|
}
|
2010-02-03 06:38:47 +08:00
|
|
|
|
2011-01-15 04:34:15 +08:00
|
|
|
void removeDeadBindingsWorker::VisitBinding(SVal V) {
|
2010-03-11 00:32:56 +08:00
|
|
|
// Is it a LazyCompoundVal? All referenced regions are live as well.
|
|
|
|
if (const nonloc::LazyCompoundVal *LCS =
|
|
|
|
dyn_cast<nonloc::LazyCompoundVal>(&V)) {
|
2009-09-29 14:35:00 +08:00
|
|
|
|
2010-03-11 00:32:56 +08:00
|
|
|
const MemRegion *LazyR = LCS->getRegion();
|
|
|
|
RegionBindings B = RegionStoreManager::GetRegionBindings(LCS->getStore());
|
|
|
|
for (RegionBindings::iterator RI = B.begin(), RE = B.end(); RI != RE; ++RI){
|
2010-07-07 07:53:29 +08:00
|
|
|
const SubRegion *baseR = dyn_cast<SubRegion>(RI.getKey().getRegion());
|
|
|
|
if (baseR && baseR->isSubRegionOf(LazyR))
|
2010-03-11 00:32:56 +08:00
|
|
|
VisitBinding(RI.getData());
|
2009-11-26 10:35:42 +08:00
|
|
|
}
|
2010-03-11 00:32:56 +08:00
|
|
|
return;
|
|
|
|
}
|
2009-09-29 14:35:00 +08:00
|
|
|
|
2010-03-11 00:32:56 +08:00
|
|
|
// If V is a region, then add it to the worklist.
|
|
|
|
if (const MemRegion *R = V.getAsRegion())
|
|
|
|
AddToWorkList(R);
|
2009-09-09 23:08:12 +08:00
|
|
|
|
2011-12-07 07:12:27 +08:00
|
|
|
// Update the set of live symbols.
|
2011-12-07 07:12:33 +08:00
|
|
|
for (SymExpr::symbol_iterator SI = V.symbol_begin(), SE = V.symbol_end();
|
|
|
|
SI!=SE; ++SI)
|
2010-03-11 00:32:56 +08:00
|
|
|
SymReaper.markLive(*SI);
|
|
|
|
}
|
2010-03-10 15:20:03 +08:00
|
|
|
|
2011-01-15 04:34:15 +08:00
|
|
|
void removeDeadBindingsWorker::VisitBindingKey(BindingKey K) {
|
2010-04-01 08:15:55 +08:00
|
|
|
const MemRegion *R = K.getRegion();
|
|
|
|
|
2010-03-11 00:32:56 +08:00
|
|
|
// Mark this region "live" by adding it to the worklist. This will cause
|
|
|
|
// use to visit all regions in the cluster (if we haven't visited them
|
|
|
|
// already).
|
2010-04-01 08:15:55 +08:00
|
|
|
if (AddToWorkList(R)) {
|
|
|
|
// Mark the symbol for any live SymbolicRegion as "live". This means we
|
|
|
|
// should continue to track that symbol.
|
|
|
|
if (const SymbolicRegion *SymR = dyn_cast<SymbolicRegion>(R))
|
|
|
|
SymReaper.markLive(SymR->getSymbol());
|
|
|
|
|
|
|
|
// For BlockDataRegions, enqueue the VarRegions for variables marked
|
|
|
|
// with __block (passed-by-reference).
|
|
|
|
// via BlockDeclRefExprs.
|
|
|
|
if (const BlockDataRegion *BD = dyn_cast<BlockDataRegion>(R)) {
|
|
|
|
for (BlockDataRegion::referenced_vars_iterator
|
|
|
|
RI = BD->referenced_vars_begin(), RE = BD->referenced_vars_end();
|
|
|
|
RI != RE; ++RI) {
|
|
|
|
if ((*RI)->getDecl()->getAttr<BlocksAttr>())
|
|
|
|
AddToWorkList(*RI);
|
|
|
|
}
|
2010-03-11 00:32:56 +08:00
|
|
|
|
2010-04-01 08:15:55 +08:00
|
|
|
// No possible data bindings on a BlockDataRegion.
|
|
|
|
return;
|
2009-09-29 14:35:00 +08:00
|
|
|
}
|
|
|
|
}
|
2010-03-10 15:20:03 +08:00
|
|
|
|
2010-04-01 08:15:55 +08:00
|
|
|
// Visit the data binding for K.
|
2010-11-24 08:54:37 +08:00
|
|
|
if (const SVal *V = RM.lookup(B, K))
|
2010-03-11 00:32:56 +08:00
|
|
|
VisitBinding(*V);
|
|
|
|
}
|
|
|
|
|
2011-01-15 04:34:15 +08:00
|
|
|
bool removeDeadBindingsWorker::UpdatePostponed() {
|
2009-10-29 13:14:17 +08:00
|
|
|
// See if any postponed SymbolicRegions are actually live now, after
|
|
|
|
// having done a scan.
|
2010-03-11 00:32:56 +08:00
|
|
|
bool changed = false;
|
|
|
|
|
2011-07-23 18:55:15 +08:00
|
|
|
for (SmallVectorImpl<const SymbolicRegion*>::iterator
|
2010-03-11 00:32:56 +08:00
|
|
|
I = Postponed.begin(), E = Postponed.end() ; I != E ; ++I) {
|
|
|
|
if (const SymbolicRegion *SR = cast_or_null<SymbolicRegion>(*I)) {
|
2009-10-29 13:14:17 +08:00
|
|
|
if (SymReaper.isLive(SR->getSymbol())) {
|
2010-03-11 00:32:56 +08:00
|
|
|
changed |= AddToWorkList(SR);
|
|
|
|
*I = NULL;
|
2009-10-29 13:14:17 +08:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2010-03-10 15:20:03 +08:00
|
|
|
|
2010-03-11 00:32:56 +08:00
|
|
|
return changed;
|
|
|
|
}
|
|
|
|
|
2011-02-19 09:59:33 +08:00
|
|
|
StoreRef RegionStoreManager::removeDeadBindings(Store store,
|
|
|
|
const StackFrameContext *LCtx,
|
2011-08-06 08:29:57 +08:00
|
|
|
SymbolReaper& SymReaper) {
|
2010-08-15 20:45:09 +08:00
|
|
|
RegionBindings B = GetRegionBindings(store);
|
2011-01-15 04:34:15 +08:00
|
|
|
removeDeadBindingsWorker W(*this, StateMgr, B, SymReaper, LCtx);
|
2010-03-11 00:32:56 +08:00
|
|
|
W.GenerateClusters();
|
|
|
|
|
|
|
|
// Enqueue the region roots onto the worklist.
|
2011-08-06 08:29:57 +08:00
|
|
|
for (SymbolReaper::region_iterator I = SymReaper.region_begin(),
|
|
|
|
E = SymReaper.region_end(); I != E; ++I) {
|
2010-03-11 00:32:56 +08:00
|
|
|
W.AddToWorkList(*I);
|
2011-08-06 08:29:57 +08:00
|
|
|
}
|
2010-03-11 00:32:56 +08:00
|
|
|
|
|
|
|
do W.RunWorkList(); while (W.UpdatePostponed());
|
2010-03-10 15:20:03 +08:00
|
|
|
|
2009-06-17 06:36:44 +08:00
|
|
|
// We have now scanned the store, marking reachable regions and symbols
|
|
|
|
// as live. We now remove all the regions that are dead from the store
|
2009-09-09 23:08:12 +08:00
|
|
|
// as well as update DSymbols with the set symbols that are now dead.
|
2009-08-06 12:50:20 +08:00
|
|
|
for (RegionBindings::iterator I = B.begin(), E = B.end(); I != E; ++I) {
|
2010-03-11 00:32:56 +08:00
|
|
|
const BindingKey &K = I.getKey();
|
|
|
|
|
2010-03-11 00:38:41 +08:00
|
|
|
// If the cluster has been visited, we know the region has been marked.
|
2010-03-11 00:32:56 +08:00
|
|
|
if (W.isVisited(K.getRegion()))
|
2009-06-17 06:36:44 +08:00
|
|
|
continue;
|
2009-09-09 23:08:12 +08:00
|
|
|
|
2010-03-11 00:32:56 +08:00
|
|
|
// Remove the dead entry.
|
2010-11-24 08:54:37 +08:00
|
|
|
B = removeBinding(B, K);
|
2009-09-09 23:08:12 +08:00
|
|
|
|
2010-03-11 00:32:56 +08:00
|
|
|
// Mark all non-live symbols that this binding references as dead.
|
|
|
|
if (const SymbolicRegion* SymR = dyn_cast<SymbolicRegion>(K.getRegion()))
|
2009-06-17 06:36:44 +08:00
|
|
|
SymReaper.maybeDead(SymR->getSymbol());
|
2009-09-09 23:08:12 +08:00
|
|
|
|
2010-02-03 11:06:46 +08:00
|
|
|
SVal X = I.getData();
|
2011-12-07 07:12:33 +08:00
|
|
|
SymExpr::symbol_iterator SI = X.symbol_begin(), SE = X.symbol_end();
|
2009-08-02 13:00:15 +08:00
|
|
|
for (; SI != SE; ++SI)
|
|
|
|
SymReaper.maybeDead(*SI);
|
|
|
|
}
|
2010-08-15 20:45:09 +08:00
|
|
|
|
2011-02-19 09:59:33 +08:00
|
|
|
return StoreRef(B.getRootWithoutRetain(), *this);
|
2009-06-17 06:36:44 +08:00
|
|
|
}
|
|
|
|
|
2010-03-11 00:32:56 +08:00
|
|
|
|
2012-01-27 05:29:00 +08:00
|
|
|
StoreRef RegionStoreManager::enterStackFrame(ProgramStateRef state,
|
2012-01-13 03:25:46 +08:00
|
|
|
const LocationContext *callerCtx,
|
|
|
|
const StackFrameContext *calleeCtx)
|
|
|
|
{
|
|
|
|
FunctionDecl const *FD = cast<FunctionDecl>(calleeCtx->getDecl());
|
2011-01-15 04:29:43 +08:00
|
|
|
FunctionDecl::param_const_iterator PI = FD->param_begin(),
|
|
|
|
PE = FD->param_end();
|
2011-02-19 09:59:33 +08:00
|
|
|
StoreRef store = StoreRef(state->getStore(), *this);
|
2009-10-13 10:24:55 +08:00
|
|
|
|
2012-01-13 03:25:46 +08:00
|
|
|
if (CallExpr const *CE = dyn_cast<CallExpr>(calleeCtx->getCallSite())) {
|
2010-03-16 21:14:16 +08:00
|
|
|
CallExpr::const_arg_iterator AI = CE->arg_begin(), AE = CE->arg_end();
|
2009-10-13 10:24:55 +08:00
|
|
|
|
2011-01-15 04:29:43 +08:00
|
|
|
// Copy the arg expression value to the arg variables. We check that
|
|
|
|
// PI != PE because the actual number of arguments may be different than
|
|
|
|
// the function declaration.
|
|
|
|
for (; AI != AE && PI != PE; ++AI, ++PI) {
|
2012-01-13 03:25:46 +08:00
|
|
|
SVal ArgVal = state->getSVal(*AI, callerCtx);
|
2011-02-19 09:59:33 +08:00
|
|
|
store = Bind(store.getStore(),
|
2012-01-13 03:25:46 +08:00
|
|
|
svalBuilder.makeLoc(MRMgr.getVarRegion(*PI, calleeCtx)),
|
|
|
|
ArgVal);
|
2010-03-16 21:14:16 +08:00
|
|
|
}
|
2010-07-02 04:16:50 +08:00
|
|
|
} else if (const CXXConstructExpr *CE =
|
2012-01-13 03:25:46 +08:00
|
|
|
dyn_cast<CXXConstructExpr>(calleeCtx->getCallSite())) {
|
2010-07-02 04:16:50 +08:00
|
|
|
CXXConstructExpr::const_arg_iterator AI = CE->arg_begin(),
|
2010-03-16 21:14:16 +08:00
|
|
|
AE = CE->arg_end();
|
|
|
|
|
|
|
|
// Copy the arg expression value to the arg variables.
|
|
|
|
for (; AI != AE; ++AI, ++PI) {
|
2012-01-13 03:25:46 +08:00
|
|
|
SVal ArgVal = state->getSVal(*AI, callerCtx);
|
2011-02-19 09:59:33 +08:00
|
|
|
store = Bind(store.getStore(),
|
2012-01-13 03:25:46 +08:00
|
|
|
svalBuilder.makeLoc(MRMgr.getVarRegion(*PI, calleeCtx)),
|
|
|
|
ArgVal);
|
2010-03-16 21:14:16 +08:00
|
|
|
}
|
|
|
|
} else
|
2012-01-13 03:25:46 +08:00
|
|
|
assert(isa<CXXDestructorDecl>(calleeCtx->getDecl()));
|
2009-10-13 10:24:55 +08:00
|
|
|
|
2010-08-04 04:44:35 +08:00
|
|
|
return store;
|
2009-10-13 10:24:55 +08:00
|
|
|
}
|
|
|
|
|
2009-06-17 06:36:44 +08:00
|
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
// Utility methods.
|
|
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
|
2011-08-13 07:37:29 +08:00
|
|
|
void RegionStoreManager::print(Store store, raw_ostream &OS,
|
2009-06-17 06:36:44 +08:00
|
|
|
const char* nl, const char *sep) {
|
2009-08-06 12:50:20 +08:00
|
|
|
RegionBindings B = GetRegionBindings(store);
|
2009-10-20 09:20:57 +08:00
|
|
|
OS << "Store (direct and default bindings):" << nl;
|
2009-09-09 23:08:12 +08:00
|
|
|
|
2009-08-06 12:50:20 +08:00
|
|
|
for (RegionBindings::iterator I = B.begin(), E = B.end(); I != E; ++I)
|
2009-09-09 23:08:12 +08:00
|
|
|
OS << ' ' << I.getKey() << " : " << I.getData() << nl;
|
2009-06-17 06:36:44 +08:00
|
|
|
}
|