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"
|
2012-08-14 06:11:42 +08:00
|
|
|
#include "clang/AST/CXXInheritance.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-07-27 05:39:41 +08:00
|
|
|
#include "clang/StaticAnalyzer/Core/PathSensitive/CallEvent.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:
|
2012-08-10 06:55:37 +08:00
|
|
|
enum Kind { Default = 0x0, Direct = 0x1 };
|
2009-10-11 16:08:02 +08:00
|
|
|
private:
|
2012-08-10 06:55:37 +08:00
|
|
|
enum { Symbolic = 0x2 };
|
2012-08-09 02:23:27 +08:00
|
|
|
|
2012-08-10 06:55:37 +08:00
|
|
|
llvm::PointerIntPair<const MemRegion *, 2> P;
|
|
|
|
uint64_t Data;
|
2010-03-10 15:20:03 +08:00
|
|
|
|
2012-08-10 06:55:37 +08:00
|
|
|
explicit BindingKey(const MemRegion *r, const MemRegion *Base, Kind k)
|
|
|
|
: P(r, k | Symbolic), Data(reinterpret_cast<uintptr_t>(Base)) {
|
|
|
|
assert(r && Base && "Must have known regions.");
|
|
|
|
assert(getConcreteOffsetRegion() == Base && "Failed to store base region");
|
|
|
|
}
|
2010-02-03 11:06:46 +08:00
|
|
|
explicit BindingKey(const MemRegion *r, uint64_t offset, Kind k)
|
2012-08-10 06:55:37 +08:00
|
|
|
: P(r, k), Data(offset) {
|
|
|
|
assert(r && "Must have known regions.");
|
|
|
|
assert(getOffset() == offset && "Failed to store offset");
|
2012-08-10 18:06:13 +08:00
|
|
|
assert((r == r->getBaseRegion() || isa<ObjCIvarRegion>(r)) && "Not a base");
|
2012-08-10 06:55:37 +08:00
|
|
|
}
|
2009-10-11 16:08:02 +08:00
|
|
|
public:
|
2010-03-10 15:20:03 +08:00
|
|
|
|
2012-08-10 06:55:37 +08:00
|
|
|
bool isDirect() const { return P.getInt() & Direct; }
|
|
|
|
bool hasSymbolicOffset() const { return P.getInt() & Symbolic; }
|
2010-03-10 15:20:03 +08:00
|
|
|
|
2010-02-03 11:06:46 +08:00
|
|
|
const MemRegion *getRegion() const { return P.getPointer(); }
|
2012-08-09 02:23:27 +08:00
|
|
|
uint64_t getOffset() const {
|
|
|
|
assert(!hasSymbolicOffset());
|
2012-08-10 06:55:37 +08:00
|
|
|
return Data;
|
2012-08-09 02:23:27 +08:00
|
|
|
}
|
|
|
|
|
2012-08-10 06:55:37 +08:00
|
|
|
const MemRegion *getConcreteOffsetRegion() const {
|
|
|
|
assert(hasSymbolicOffset());
|
|
|
|
return reinterpret_cast<const MemRegion *>(static_cast<uintptr_t>(Data));
|
|
|
|
}
|
2010-03-10 15:20:03 +08:00
|
|
|
|
2012-08-10 06:55:51 +08:00
|
|
|
const MemRegion *getBaseRegion() const {
|
|
|
|
if (hasSymbolicOffset())
|
|
|
|
return getConcreteOffsetRegion()->getBaseRegion();
|
|
|
|
return getRegion()->getBaseRegion();
|
|
|
|
}
|
|
|
|
|
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());
|
2012-08-10 06:55:37 +08:00
|
|
|
ID.AddInteger(Data);
|
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;
|
2012-08-10 06:55:37 +08:00
|
|
|
return Data < X.Data;
|
2010-02-03 11:06:46 +08:00
|
|
|
}
|
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() &&
|
2012-08-10 06:55:37 +08:00
|
|
|
Data == X.Data;
|
2010-01-11 08:07:44 +08:00
|
|
|
}
|
2010-08-16 09:15:17 +08:00
|
|
|
|
2012-08-10 06:55:51 +08:00
|
|
|
LLVM_ATTRIBUTE_USED void dump() const;
|
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) {
|
2012-05-09 05:49:54 +08:00
|
|
|
const RegionOffset &RO = R->getAsOffset();
|
2012-08-10 06:55:37 +08:00
|
|
|
if (RO.hasSymbolicOffset())
|
|
|
|
return BindingKey(R, RO.getRegion(), k);
|
2012-08-09 02:23:27 +08:00
|
|
|
|
2012-08-10 06:55:37 +08:00
|
|
|
return BindingKey(RO.getRegion(), RO.getOffset(), k);
|
2010-08-21 20:24:38 +08:00
|
|
|
}
|
|
|
|
|
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) {
|
2012-08-09 02:23:27 +08:00
|
|
|
os << '(' << K.getRegion();
|
|
|
|
if (!K.hasSymbolicOffset())
|
|
|
|
os << ',' << K.getOffset();
|
|
|
|
os << ',' << (K.isDirect() ? "direct" : "default")
|
2010-02-03 11:06:46 +08:00
|
|
|
<< ')';
|
2010-01-11 08:07:44 +08:00
|
|
|
return os;
|
|
|
|
}
|
|
|
|
} // end llvm namespace
|
|
|
|
|
2012-08-10 06:55:51 +08:00
|
|
|
void BindingKey::dump() const {
|
|
|
|
llvm::errs() << *this;
|
|
|
|
}
|
|
|
|
|
2010-01-11 08:07:44 +08:00
|
|
|
//===----------------------------------------------------------------------===//
|
2008-11-24 17:44:56 +08:00
|
|
|
// Actual Store type.
|
2010-01-11 08:07:44 +08:00
|
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
|
2012-08-10 06:55:51 +08:00
|
|
|
typedef llvm::ImmutableMap<BindingKey, SVal> ClusterBindings;
|
|
|
|
typedef llvm::ImmutableMap<const MemRegion *, ClusterBindings> 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 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;
|
2012-08-10 06:55:51 +08:00
|
|
|
ClusterBindings::Factory CBFactory;
|
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)
|
2012-08-10 06:55:51 +08:00
|
|
|
: StoreManager(mgr), Features(f),
|
|
|
|
RBFactory(mgr.getAllocator()), CBFactory(mgr.getAllocator()) {}
|
2008-10-08 10:50:44 +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-07-03 03:27:35 +08:00
|
|
|
const CallEvent *Call,
|
2011-08-28 06:51:26 +08:00
|
|
|
InvalidatedRegions *Invalidated);
|
2009-09-09 23:08:12 +08:00
|
|
|
|
2012-08-09 02:23:27 +08:00
|
|
|
bool scanReachableSymbols(Store S, const MemRegion *R,
|
|
|
|
ScanReachableSymbols &Callbacks);
|
|
|
|
|
2010-02-03 11:06:46 +08:00
|
|
|
public: // Made public for helper classes.
|
2010-03-10 15:20:03 +08:00
|
|
|
|
2012-08-09 02:23:27 +08:00
|
|
|
RegionBindings removeSubRegionBindings(RegionBindings B, const SubRegion *R);
|
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
|
|
|
|
2012-08-10 06:55:51 +08:00
|
|
|
RegionBindings removeCluster(RegionBindings B, const MemRegion *R);
|
|
|
|
|
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
|
|
|
}
|
|
|
|
|
2012-08-22 14:00:12 +08:00
|
|
|
/// \brief Create a new store that binds a value to a compound literal.
|
|
|
|
///
|
|
|
|
/// \param ST The original store whose bindings are the basis for the new
|
|
|
|
/// store.
|
|
|
|
///
|
|
|
|
/// \param CL The compound literal to bind (the binding key).
|
|
|
|
///
|
|
|
|
/// \param LC The LocationContext for the binding.
|
|
|
|
///
|
|
|
|
/// \param V The value to bind to the compound literal.
|
|
|
|
StoreRef bindCompoundLiteral(Store ST,
|
|
|
|
const CompoundLiteralExpr *CL,
|
2011-02-19 09:59:33 +08:00
|
|
|
const LocationContext *LC, SVal V);
|
2009-09-09 23:08:12 +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
|
|
|
|
2012-05-11 06:02:39 +08:00
|
|
|
/// BindVector - Bind a compound value to a vector.
|
|
|
|
StoreRef BindVector(Store store, const TypedValueRegion* R, SVal V);
|
|
|
|
|
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
|
|
|
|
2012-08-10 06:55:54 +08:00
|
|
|
/// Clears out all bindings in the given region and assigns a new value
|
|
|
|
/// as a Default binding.
|
|
|
|
StoreRef BindAggregate(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,
|
2012-05-11 06:02:39 +08:00
|
|
|
const MemRegion *originalRegion,
|
|
|
|
bool includeSuffix = false);
|
2009-09-09 23:08:12 +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);
|
2012-06-02 04:04:04 +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);
|
2012-08-10 06:55:51 +08:00
|
|
|
for (RegionBindings::iterator I = B.begin(), E = B.end(); I != E; ++I) {
|
|
|
|
const ClusterBindings &Cluster = I.getData();
|
|
|
|
for (ClusterBindings::iterator CI = Cluster.begin(), CE = Cluster.end();
|
|
|
|
CI != CE; ++CI) {
|
|
|
|
const BindingKey &K = CI.getKey();
|
|
|
|
if (!K.isDirect())
|
|
|
|
continue;
|
|
|
|
if (const SubRegion *R = dyn_cast<SubRegion>(K.getRegion())) {
|
|
|
|
// FIXME: Possibly incorporate the offset?
|
|
|
|
if (!f.HandleBinding(*this, store, R, CI.getData()))
|
|
|
|
return;
|
|
|
|
}
|
2010-06-17 08:24:42 +08:00
|
|
|
}
|
|
|
|
}
|
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
|
|
|
|
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:
|
2012-08-10 06:55:51 +08:00
|
|
|
typedef llvm::DenseMap<const MemRegion *, const ClusterBindings *> ClusterMap;
|
|
|
|
typedef SmallVector<const MemRegion *, 10> WorkList;
|
|
|
|
|
|
|
|
llvm::SmallPtrSet<const ClusterBindings *, 16> Visited;
|
|
|
|
|
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
|
|
|
|
2012-08-10 06:55:51 +08:00
|
|
|
const ClusterBindings *getCluster(const MemRegion *R) {
|
|
|
|
return B.lookup(R);
|
|
|
|
}
|
|
|
|
|
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; }
|
|
|
|
|
|
|
|
bool isVisited(const MemRegion *R) {
|
2012-08-10 06:55:51 +08:00
|
|
|
return Visited.count(getCluster(R));
|
2010-03-11 00:32:56 +08:00
|
|
|
}
|
2010-03-10 15:19:59 +08:00
|
|
|
|
2010-10-26 08:06:15 +08:00
|
|
|
void GenerateClusters() {
|
2012-08-10 06:55:51 +08:00
|
|
|
// Scan the entire set of bindings and record the region clusters.
|
2010-03-11 00:32:56 +08:00
|
|
|
for (RegionBindings::iterator RI = B.begin(), RE = B.end(); RI != RE; ++RI){
|
2012-08-10 06:55:51 +08:00
|
|
|
const MemRegion *Base = RI.getKey();
|
|
|
|
|
|
|
|
const ClusterBindings &Cluster = RI.getData();
|
|
|
|
assert(!Cluster.isEmpty() && "Empty clusters should be removed");
|
|
|
|
static_cast<DERIVED*>(this)->VisitAddedToCluster(Base, Cluster);
|
|
|
|
|
|
|
|
if (includeGlobals)
|
|
|
|
if (isa<NonStaticGlobalSpaceRegion>(Base->getMemorySpace()))
|
|
|
|
AddToWorkList(Base, &Cluster);
|
2010-03-11 00:32:56 +08:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2012-08-10 06:55:51 +08:00
|
|
|
bool AddToWorkList(const MemRegion *R, const ClusterBindings *C) {
|
2012-08-22 08:02:08 +08:00
|
|
|
if (C && !Visited.insert(C))
|
|
|
|
return false;
|
2012-08-10 06:55:51 +08:00
|
|
|
WL.push_back(R);
|
2010-03-11 00:32:56 +08:00
|
|
|
return true;
|
2010-03-10 15:19:59 +08:00
|
|
|
}
|
|
|
|
|
2010-03-11 00:32:56 +08:00
|
|
|
bool AddToWorkList(const MemRegion *R) {
|
|
|
|
const MemRegion *baseR = R->getBaseRegion();
|
|
|
|
return AddToWorkList(baseR, getCluster(baseR));
|
|
|
|
}
|
|
|
|
|
|
|
|
void RunWorkList() {
|
|
|
|
while (!WL.empty()) {
|
2012-08-10 06:55:51 +08:00
|
|
|
const MemRegion *baseR = WL.pop_back_val();
|
2010-03-11 00:32:56 +08:00
|
|
|
|
2012-08-10 06:55:51 +08:00
|
|
|
// First visit the cluster.
|
|
|
|
if (const ClusterBindings *Cluster = getCluster(baseR))
|
|
|
|
static_cast<DERIVED*>(this)->VisitCluster(baseR, *Cluster);
|
2010-03-11 00:32:56 +08:00
|
|
|
|
2012-08-10 06:55:51 +08:00
|
|
|
// Next, visit the base region.
|
2010-04-01 08:15:55 +08:00
|
|
|
static_cast<DERIVED*>(this)->VisitBaseRegion(baseR);
|
2010-03-10 15:19:59 +08:00
|
|
|
}
|
|
|
|
}
|
2010-03-11 00:32:56 +08:00
|
|
|
|
|
|
|
public:
|
2012-08-10 06:55:51 +08:00
|
|
|
void VisitAddedToCluster(const MemRegion *baseR, const ClusterBindings &C) {}
|
|
|
|
void VisitCluster(const MemRegion *baseR, const ClusterBindings &C) {}
|
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.
|
|
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
|
2012-08-09 02:23:27 +08:00
|
|
|
bool RegionStoreManager::scanReachableSymbols(Store S, const MemRegion *R,
|
|
|
|
ScanReachableSymbols &Callbacks) {
|
2012-08-10 06:55:51 +08:00
|
|
|
assert(R == R->getBaseRegion() && "Should only be called for base regions");
|
2012-08-09 02:23:27 +08:00
|
|
|
RegionBindings B = GetRegionBindings(S);
|
2012-08-10 06:55:51 +08:00
|
|
|
const ClusterBindings *Cluster = B.lookup(R);
|
|
|
|
|
|
|
|
if (!Cluster)
|
|
|
|
return true;
|
|
|
|
|
|
|
|
for (ClusterBindings::iterator RI = Cluster->begin(), RE = Cluster->end();
|
|
|
|
RI != RE; ++RI) {
|
|
|
|
if (!Callbacks.scan(RI.getData()))
|
|
|
|
return false;
|
2012-08-09 02:23:27 +08:00
|
|
|
}
|
2010-03-10 15:19:59 +08:00
|
|
|
|
2012-08-09 02:23:27 +08:00
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
|
|
|
RegionBindings RegionStoreManager::removeSubRegionBindings(RegionBindings B,
|
|
|
|
const SubRegion *R) {
|
|
|
|
BindingKey SRKey = BindingKey::Make(R, BindingKey::Default);
|
2012-08-10 06:55:51 +08:00
|
|
|
const MemRegion *ClusterHead = SRKey.getBaseRegion();
|
|
|
|
if (R == ClusterHead) {
|
|
|
|
// We can remove an entire cluster's bindings all in one go.
|
|
|
|
return RBFactory.remove(B, R);
|
|
|
|
}
|
|
|
|
|
2012-08-09 02:23:27 +08:00
|
|
|
if (SRKey.hasSymbolicOffset()) {
|
|
|
|
const SubRegion *Base = cast<SubRegion>(SRKey.getConcreteOffsetRegion());
|
|
|
|
B = removeSubRegionBindings(B, Base);
|
|
|
|
return addBinding(B, Base, BindingKey::Default, UnknownVal());
|
|
|
|
}
|
|
|
|
|
2012-08-10 06:55:51 +08:00
|
|
|
// This assumes the region being invalidated is char-aligned. This isn't
|
|
|
|
// true for bitfields, but since bitfields have no subregions they shouldn't
|
|
|
|
// be using this function anyway.
|
2012-08-09 02:23:27 +08:00
|
|
|
uint64_t Length = UINT64_MAX;
|
|
|
|
|
|
|
|
SVal Extent = R->getExtent(svalBuilder);
|
|
|
|
if (nonloc::ConcreteInt *ExtentCI = dyn_cast<nonloc::ConcreteInt>(&Extent)) {
|
|
|
|
const llvm::APSInt &ExtentInt = ExtentCI->getValue();
|
|
|
|
assert(ExtentInt.isNonNegative() || ExtentInt.isUnsigned());
|
|
|
|
// Extents are in bytes but region offsets are in bits. Be careful!
|
|
|
|
Length = ExtentInt.getLimitedValue() * Ctx.getCharWidth();
|
|
|
|
}
|
|
|
|
|
2012-08-10 06:55:51 +08:00
|
|
|
const ClusterBindings *Cluster = B.lookup(ClusterHead);
|
|
|
|
if (!Cluster)
|
|
|
|
return B;
|
|
|
|
|
|
|
|
ClusterBindings Result = *Cluster;
|
|
|
|
|
2012-08-09 02:23:27 +08:00
|
|
|
// It is safe to iterate over the bindings as they are being changed
|
|
|
|
// because they are in an ImmutableMap.
|
2012-08-10 06:55:51 +08:00
|
|
|
for (ClusterBindings::iterator I = Cluster->begin(), E = Cluster->end();
|
|
|
|
I != E; ++I) {
|
|
|
|
BindingKey NextKey = I.getKey();
|
2012-08-09 02:23:27 +08:00
|
|
|
if (NextKey.getRegion() == SRKey.getRegion()) {
|
|
|
|
if (NextKey.getOffset() > SRKey.getOffset() &&
|
2012-08-10 06:55:51 +08:00
|
|
|
NextKey.getOffset() - SRKey.getOffset() < Length) {
|
|
|
|
// Case 1: The next binding is inside the region we're invalidating.
|
|
|
|
// Remove it.
|
|
|
|
Result = CBFactory.remove(Result, NextKey);
|
|
|
|
} else if (NextKey.getOffset() == SRKey.getOffset()) {
|
|
|
|
// Case 2: The next binding is at the same offset as the region we're
|
|
|
|
// invalidating. In this case, we need to leave default bindings alone,
|
|
|
|
// since they may be providing a default value for a regions beyond what
|
|
|
|
// we're invalidating.
|
|
|
|
// FIXME: This is probably incorrect; consider invalidating an outer
|
|
|
|
// struct whose first field is bound to a LazyCompoundVal.
|
2012-08-09 02:23:27 +08:00
|
|
|
if (NextKey.isDirect())
|
2012-08-10 06:55:51 +08:00
|
|
|
Result = CBFactory.remove(Result, NextKey);
|
|
|
|
}
|
2012-08-09 02:23:27 +08:00
|
|
|
} else if (NextKey.hasSymbolicOffset()) {
|
|
|
|
const MemRegion *Base = NextKey.getConcreteOffsetRegion();
|
2012-08-10 06:55:51 +08:00
|
|
|
if (R->isSubRegionOf(Base)) {
|
|
|
|
// Case 3: The next key is symbolic and we just changed something within
|
|
|
|
// its concrete region. We don't know if the binding is still valid, so
|
|
|
|
// we'll be conservative and remove it.
|
|
|
|
if (NextKey.isDirect())
|
|
|
|
Result = CBFactory.remove(Result, NextKey);
|
|
|
|
} else if (const SubRegion *BaseSR = dyn_cast<SubRegion>(Base)) {
|
|
|
|
// Case 4: The next key is symbolic, but we changed a known
|
|
|
|
// super-region. In this case the binding is certainly no longer valid.
|
|
|
|
if (R == Base || BaseSR->isSubRegionOf(R))
|
|
|
|
Result = CBFactory.remove(Result, NextKey);
|
|
|
|
}
|
2012-08-09 02:23:27 +08:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2012-08-10 06:55:51 +08:00
|
|
|
if (Result.isEmpty())
|
|
|
|
return RBFactory.remove(B, ClusterHead);
|
|
|
|
return RBFactory.add(B, ClusterHead, Result);
|
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
|
|
|
|
2012-08-10 06:55:51 +08:00
|
|
|
void VisitCluster(const MemRegion *baseR, const ClusterBindings &C);
|
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());
|
|
|
|
|
2012-08-10 06:55:51 +08:00
|
|
|
// FIXME: This should not have to walk all bindings in the old store.
|
2010-02-13 09:52:33 +08:00
|
|
|
for (RegionBindings::iterator RI = B.begin(), RE = B.end(); RI != RE; ++RI){
|
2012-08-10 06:55:51 +08:00
|
|
|
const ClusterBindings &Cluster = RI.getData();
|
|
|
|
for (ClusterBindings::iterator CI = Cluster.begin(), CE = Cluster.end();
|
|
|
|
CI != CE; ++CI) {
|
|
|
|
BindingKey K = CI.getKey();
|
|
|
|
if (const SubRegion *BaseR = dyn_cast<SubRegion>(K.getRegion())) {
|
|
|
|
if (BaseR == LazyR)
|
|
|
|
VisitBinding(CI.getData());
|
|
|
|
else if (K.hasSymbolicOffset() && BaseR->isSubRegionOf(LazyR))
|
|
|
|
VisitBinding(CI.getData());
|
|
|
|
}
|
|
|
|
}
|
2010-02-13 09:52:33 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2012-08-10 06:55:51 +08:00
|
|
|
void invalidateRegionsWorker::VisitCluster(const MemRegion *BaseR,
|
|
|
|
const ClusterBindings &C) {
|
|
|
|
for (ClusterBindings::iterator I = C.begin(), E = C.end(); I != E; ++I)
|
|
|
|
VisitBinding(I.getData());
|
2010-03-10 15:19:59 +08:00
|
|
|
|
2012-08-10 06:55:51 +08:00
|
|
|
B = RM.removeCluster(B, BaseR);
|
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();
|
2012-05-05 05:48:42 +08:00
|
|
|
if (VD->getAttr<BlocksAttr>() || !VD->hasLocalStorage()) {
|
2010-03-11 00:32:56 +08:00
|
|
|
AddToWorkList(VR);
|
2012-05-05 05:48:42 +08:00
|
|
|
}
|
|
|
|
else if (Loc::isLocType(VR->getValueType())) {
|
|
|
|
// Map the current bindings to a Store to retrieve the value
|
|
|
|
// of the binding. If that binding itself is a region, we should
|
|
|
|
// invalidate that region. This is because a block may capture
|
|
|
|
// a pointer value, but the thing pointed by that pointer may
|
|
|
|
// get invalidated.
|
|
|
|
Store store = B.getRootWithoutRetain();
|
|
|
|
SVal V = RM.getBinding(store, loc::MemRegionVal(VR));
|
|
|
|
if (const Loc *L = dyn_cast<Loc>(&V)) {
|
|
|
|
if (const MemRegion *LR = L->getAsRegion())
|
|
|
|
AddToWorkList(LR);
|
|
|
|
}
|
|
|
|
}
|
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-08-22 14:26:06 +08:00
|
|
|
svalBuilder.conjureSymbolVal(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.
|
2012-08-22 14:26:06 +08:00
|
|
|
DefinedOrUnknownSVal V = svalBuilder.conjureSymbolVal(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-08-22 14:26:06 +08:00
|
|
|
svalBuilder.conjureSymbolVal(baseR, Ex, LCtx,
|
2012-02-18 07:13:45 +08:00
|
|
|
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-08-22 14:26:06 +08:00
|
|
|
DefinedOrUnknownSVal V = svalBuilder.conjureSymbolVal(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);
|
2012-08-22 14:26:06 +08:00
|
|
|
SVal V = svalBuilder.conjureSymbolVal(/* SymbolTag = */ (void*) GS, Ex, LCtx,
|
|
|
|
/* type does not matter */ Ctx.IntTy,
|
|
|
|
Count);
|
2012-01-05 07:54:01 +08:00
|
|
|
|
|
|
|
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-07-03 03:27:35 +08:00
|
|
|
const CallEvent *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
|
|
|
|
2012-06-12 08:20:22 +08:00
|
|
|
// Strip off typedefs from the ArrayRegion's ValueType.
|
|
|
|
QualType T = ArrayR->getValueType().getDesugaredType(Ctx);
|
|
|
|
const ArrayType *AT = cast<ArrayType>(T);
|
|
|
|
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
|
|
|
}
|
|
|
|
|
2012-07-18 13:57:33 +08:00
|
|
|
// This mirrors Type::getCXXRecordDeclForPointerType(), but there doesn't
|
|
|
|
// appear to be another need for this in the rest of the codebase.
|
|
|
|
static const CXXRecordDecl *GetCXXRecordDeclForReferenceType(QualType Ty) {
|
|
|
|
if (const ReferenceType *RT = Ty->getAs<ReferenceType>())
|
|
|
|
if (const RecordType *RCT = RT->getPointeeType()->getAs<RecordType>())
|
|
|
|
return dyn_cast<CXXRecordDecl>(RCT->getDecl());
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2010-12-22 16:12:57 +08:00
|
|
|
SVal RegionStoreManager::evalDerivedToBase(SVal derived, QualType baseType) {
|
|
|
|
const CXXRecordDecl *baseDecl;
|
2012-07-18 13:57:33 +08:00
|
|
|
|
2010-12-22 16:12:57 +08:00
|
|
|
if (baseType->isPointerType())
|
|
|
|
baseDecl = baseType->getCXXRecordDeclForPointerType();
|
2012-07-18 13:57:33 +08:00
|
|
|
else if (baseType->isReferenceType())
|
|
|
|
baseDecl = GetCXXRecordDeclForReferenceType(baseType);
|
2010-12-22 16:12:57 +08:00
|
|
|
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();
|
2012-08-14 06:11:34 +08:00
|
|
|
const MemRegion *BaseRegion = baseRegVal->stripCasts(/*StripBases=*/false);
|
2012-04-11 04:59:00 +08:00
|
|
|
|
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);
|
|
|
|
|
2012-08-14 06:11:34 +08:00
|
|
|
if (!derivedType->isVoidType()) {
|
|
|
|
// Static upcasts are marked as DerivedToBase casts by Sema, so this will
|
|
|
|
// only happen when multiple or virtual inheritance is involved.
|
2012-08-14 06:11:42 +08:00
|
|
|
CXXBasePaths Paths(/*FindAmbiguities=*/false, /*RecordPaths=*/true,
|
|
|
|
/*DetectVirtual=*/false);
|
|
|
|
if (SRDecl->isDerivedFrom(DerivedDecl, Paths)) {
|
|
|
|
SVal Result = loc::MemRegionVal(TSR);
|
|
|
|
const CXXBasePath &Path = *Paths.begin();
|
|
|
|
for (CXXBasePath::const_iterator I = Path.begin(), E = Path.end();
|
|
|
|
I != E; ++I) {
|
|
|
|
Result = evalDerivedToBase(Result, I->Base->getType());
|
|
|
|
}
|
|
|
|
return Result;
|
2012-08-14 06:11:34 +08:00
|
|
|
}
|
2012-04-11 04:59:00 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
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
|
|
|
|
2012-06-16 09:28:00 +08:00
|
|
|
if (RTy->isArrayType()) {
|
|
|
|
if (RTy->isConstantArrayType())
|
|
|
|
return getBindingForArray(store, R);
|
|
|
|
else
|
|
|
|
return UnknownVal();
|
|
|
|
}
|
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,
|
2012-05-11 06:02:39 +08:00
|
|
|
const MemRegion *originalRegion,
|
|
|
|
bool includeSuffix) {
|
2011-04-03 12:09:15 +08:00
|
|
|
|
|
|
|
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
|
|
|
|
2012-05-11 06:02:39 +08:00
|
|
|
if (X.second) {
|
|
|
|
if (includeSuffix)
|
|
|
|
return std::make_pair(X.first,
|
|
|
|
MRMgr.getFieldRegionWithSuper(FR, X.second));
|
|
|
|
return X;
|
|
|
|
}
|
|
|
|
|
2009-08-06 09:20:57 +08:00
|
|
|
}
|
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
|
|
|
|
2012-05-11 06:02:39 +08:00
|
|
|
if (X.second) {
|
|
|
|
if (includeSuffix)
|
|
|
|
return std::make_pair(X.first,
|
|
|
|
MRMgr.getCXXBaseObjectRegionWithSuper(baseReg,
|
|
|
|
X.second));
|
|
|
|
return X;
|
|
|
|
}
|
2011-01-13 20:30:12 +08:00
|
|
|
}
|
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,
|
2012-05-09 07:40:38 +08:00
|
|
|
const ElementRegion* R) {
|
|
|
|
// We do not currently model bindings of the CompoundLiteralregion.
|
2012-05-10 01:23:15 +08:00
|
|
|
if (isa<CompoundLiteralRegion>(R->getBaseRegion()))
|
|
|
|
return UnknownVal();
|
2012-05-09 07:40:38 +08:00
|
|
|
|
2009-06-25 13:29:39 +08:00
|
|
|
// 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;
|
2012-05-11 06:49:10 +08:00
|
|
|
llvm::tie(lazyBindingStore, lazyBindingRegion) = GetLazyBinding(B, R, R,
|
|
|
|
true);
|
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-07-07 05:59:56 +08:00
|
|
|
static bool mayHaveLazyBinding(QualType Ty) {
|
|
|
|
return Ty->isArrayType() || Ty->isStructureOrClassType();
|
|
|
|
}
|
|
|
|
|
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-07-07 05:59:56 +08:00
|
|
|
const RecordDecl *RD = R->getValueType()->castAs<RecordType>()->getDecl();
|
|
|
|
if (RD->field_empty())
|
|
|
|
return UnknownVal();
|
|
|
|
|
|
|
|
// If we already have a lazy binding, don't create a new one,
|
|
|
|
// unless the first field might have a lazy binding of its own.
|
|
|
|
// (Right now we can't tell the difference.)
|
|
|
|
QualType FirstFieldType = RD->field_begin()->getType();
|
|
|
|
if (!mayHaveLazyBinding(FirstFieldType)) {
|
|
|
|
RegionBindings B = GetRegionBindings(store);
|
|
|
|
BindingKey K = BindingKey::Make(R, BindingKey::Default);
|
|
|
|
if (const nonloc::LazyCompoundVal *V =
|
|
|
|
dyn_cast_or_null<nonloc::LazyCompoundVal>(lookup(B, K))) {
|
|
|
|
return *V;
|
|
|
|
}
|
2012-05-09 05:49:51 +08:00
|
|
|
}
|
|
|
|
|
2011-03-09 07:18:00 +08:00
|
|
|
return svalBuilder.makeLazyCompoundVal(StoreRef(store, *this), R);
|
2008-10-31 15:16:08 +08:00
|
|
|
}
|
|
|
|
|
2012-05-09 05:49:51 +08:00
|
|
|
SVal RegionStoreManager::getBindingForArray(Store store,
|
2011-08-13 04:02:48 +08:00
|
|
|
const TypedValueRegion * R) {
|
2012-07-07 05:59:56 +08:00
|
|
|
const ConstantArrayType *Ty = Ctx.getAsConstantArrayType(R->getValueType());
|
|
|
|
assert(Ty && "Only constant array types can have compound bindings.");
|
2012-05-09 05:49:51 +08:00
|
|
|
|
2012-07-07 05:59:56 +08:00
|
|
|
// If we already have a lazy binding, don't create a new one,
|
|
|
|
// unless the first element might have a lazy binding of its own.
|
|
|
|
// (Right now we can't tell the difference.)
|
|
|
|
if (!mayHaveLazyBinding(Ty->getElementType())) {
|
|
|
|
RegionBindings B = GetRegionBindings(store);
|
|
|
|
BindingKey K = BindingKey::Make(R, BindingKey::Default);
|
|
|
|
if (const nonloc::LazyCompoundVal *V =
|
|
|
|
dyn_cast_or_null<nonloc::LazyCompoundVal>(lookup(B, K))) {
|
|
|
|
return *V;
|
|
|
|
}
|
2012-05-09 05:49:51 +08:00
|
|
|
}
|
|
|
|
|
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();
|
2012-08-10 06:55:51 +08:00
|
|
|
|
|
|
|
// Quick path: if the base is the head of a cluster, the region is live.
|
|
|
|
if (B.lookup(region))
|
|
|
|
return true;
|
|
|
|
|
|
|
|
// Slow path: if the region is the VALUE of any binding, it is live.
|
|
|
|
for (RegionBindings::iterator RI = B.begin(), RE = B.end(); RI != RE; ++RI) {
|
|
|
|
const ClusterBindings &Cluster = RI.getData();
|
|
|
|
for (ClusterBindings::iterator CI = Cluster.begin(), CE = Cluster.end();
|
|
|
|
CI != CE; ++CI) {
|
|
|
|
const SVal &D = CI.getData();
|
|
|
|
if (const MemRegion *R = D.getAsRegion())
|
|
|
|
if (R->getBaseRegion() == region)
|
|
|
|
return true;
|
|
|
|
}
|
2011-07-29 07:07:46 +08:00
|
|
|
}
|
2012-08-10 06:55:51 +08:00
|
|
|
|
2011-07-29 07:07:46 +08:00
|
|
|
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.
|
2012-05-11 06:02:39 +08:00
|
|
|
if (const TypedValueRegion* TR = dyn_cast<TypedValueRegion>(R)) {
|
|
|
|
QualType Ty = TR->getValueType();
|
2012-08-22 14:00:18 +08:00
|
|
|
if (Ty->isArrayType())
|
|
|
|
return BindArray(store, TR, V);
|
2012-05-11 06:02:39 +08:00
|
|
|
if (Ty->isStructureOrClassType())
|
2010-02-05 13:06:13 +08:00
|
|
|
return BindStruct(store, TR, V);
|
2012-05-11 06:02:39 +08:00
|
|
|
if (Ty->isVectorType())
|
|
|
|
return BindVector(store, TR, V);
|
|
|
|
}
|
2009-09-09 23:08:12 +08:00
|
|
|
|
2012-08-09 02:23:27 +08:00
|
|
|
if (const SymbolicRegion *SR = dyn_cast<SymbolicRegion>(R)) {
|
2009-09-24 12:11:44 +08:00
|
|
|
// 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
|
|
|
|
2012-08-09 02:23:27 +08:00
|
|
|
// Clear out bindings that may overlap with this binding.
|
|
|
|
|
2009-08-01 14:17:29 +08:00
|
|
|
// Perform the binding.
|
2010-02-05 13:06:13 +08:00
|
|
|
RegionBindings B = GetRegionBindings(store);
|
2012-08-09 02:23:27 +08:00
|
|
|
B = removeSubRegionBindings(B, cast<SubRegion>(R));
|
|
|
|
BindingKey Key = BindingKey::Make(R, BindingKey::Direct);
|
|
|
|
return StoreRef(addBinding(B, Key, V).getRootWithoutRetain(), *this);
|
2008-12-16 10:36:30 +08:00
|
|
|
}
|
|
|
|
|
2008-12-20 14:32:12 +08:00
|
|
|
// FIXME: this method should be merged into Bind().
|
2012-08-22 14:00:12 +08:00
|
|
|
StoreRef RegionStoreManager::bindCompoundLiteral(Store ST,
|
2011-02-19 09:59:33 +08:00
|
|
|
const CompoundLiteralExpr *CL,
|
|
|
|
const LocationContext *LC,
|
|
|
|
SVal V) {
|
2012-08-22 14:00:12 +08:00
|
|
|
return Bind(ST, loc::MemRegionVal(MRMgr.getCompoundLiteralRegion(CL, LC)), 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));
|
2012-08-10 06:55:54 +08:00
|
|
|
return BindAggregate(store, R, LCV);
|
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.
|
2012-08-10 06:55:54 +08:00
|
|
|
if (isa<nonloc::LazyCompoundVal>(Init))
|
|
|
|
return BindAggregate(store, R, Init);
|
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
|
|
|
}
|
|
|
|
|
2012-05-11 06:02:39 +08:00
|
|
|
StoreRef RegionStoreManager::BindVector(Store store, const TypedValueRegion* R,
|
|
|
|
SVal V) {
|
|
|
|
QualType T = R->getValueType();
|
|
|
|
assert(T->isVectorType());
|
|
|
|
const VectorType *VT = T->getAs<VectorType>(); // Use getAs for typedefs.
|
|
|
|
|
2012-08-10 06:55:54 +08:00
|
|
|
// Handle lazy compound values and symbolic values.
|
|
|
|
if (isa<nonloc::LazyCompoundVal>(V) || isa<nonloc::SymbolVal>(V))
|
|
|
|
return BindAggregate(store, R, V);
|
2012-05-11 06:02:39 +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.
|
2012-08-10 06:55:54 +08:00
|
|
|
if (!isa<nonloc::CompoundVal>(V)) {
|
|
|
|
return BindAggregate(store, R, UnknownVal());
|
2012-05-11 06:02:39 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
QualType ElemType = VT->getElementType();
|
|
|
|
nonloc::CompoundVal& CV = cast<nonloc::CompoundVal>(V);
|
|
|
|
nonloc::CompoundVal::iterator VI = CV.begin(), VE = CV.end();
|
|
|
|
unsigned index = 0, numElements = VT->getNumElements();
|
|
|
|
StoreRef newStore(store, *this);
|
|
|
|
|
|
|
|
for ( ; index != numElements ; ++index) {
|
|
|
|
if (VI == VE)
|
|
|
|
break;
|
|
|
|
|
|
|
|
NonLoc Idx = svalBuilder.makeArrayIndex(index);
|
|
|
|
const ElementRegion *ER = MRMgr.getElementRegion(ElemType, Idx, R, Ctx);
|
|
|
|
|
|
|
|
if (ElemType->isArrayType())
|
|
|
|
newStore = BindArray(newStore.getStore(), ER, *VI);
|
|
|
|
else if (ElemType->isStructureOrClassType())
|
|
|
|
newStore = BindStruct(newStore.getStore(), ER, *VI);
|
|
|
|
else
|
|
|
|
newStore = Bind(newStore.getStore(), svalBuilder.makeLoc(ER), *VI);
|
|
|
|
}
|
|
|
|
return newStore;
|
|
|
|
}
|
|
|
|
|
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
|
|
|
|
2012-08-10 06:55:54 +08:00
|
|
|
// Handle lazy compound values and symbolic values.
|
|
|
|
if (isa<nonloc::LazyCompoundVal>(V) || isa<nonloc::SymbolVal>(V))
|
|
|
|
return BindAggregate(store, R, V);
|
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.
|
2012-08-10 06:55:54 +08:00
|
|
|
if (V.isUnknown() || !isa<nonloc::CompoundVal>(V))
|
|
|
|
return BindAggregate(store, R, UnknownVal());
|
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();
|
2012-06-07 04:45:41 +08:00
|
|
|
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
|
|
|
}
|
|
|
|
|
2012-08-10 06:55:54 +08:00
|
|
|
StoreRef RegionStoreManager::BindAggregate(Store store, const TypedRegion *R,
|
|
|
|
SVal Val) {
|
2012-08-09 02:23:27 +08:00
|
|
|
// Remove the old bindings, using 'R' as the root of all regions
|
2012-08-10 06:55:54 +08:00
|
|
|
// we will invalidate. Then add the new binding.
|
2009-10-11 16:08:02 +08:00
|
|
|
RegionBindings B = GetRegionBindings(store);
|
2009-01-13 09:49:57 +08:00
|
|
|
|
2012-08-09 02:23:27 +08:00
|
|
|
B = removeSubRegionBindings(B, R);
|
2012-08-10 06:55:54 +08:00
|
|
|
B = addBinding(B, R, BindingKey::Default, Val);
|
2009-09-09 23:08:12 +08:00
|
|
|
|
2012-08-10 06:55:54 +08:00
|
|
|
return StoreRef(B.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) {
|
2012-08-10 06:55:51 +08:00
|
|
|
const MemRegion *Base = K.getBaseRegion();
|
|
|
|
|
|
|
|
const ClusterBindings *ExistingCluster = B.lookup(Base);
|
|
|
|
ClusterBindings Cluster = (ExistingCluster ? *ExistingCluster
|
|
|
|
: CBFactory.getEmptyMap());
|
|
|
|
|
|
|
|
ClusterBindings NewCluster = CBFactory.add(Cluster, K, V);
|
|
|
|
return RBFactory.add(B, Base, NewCluster);
|
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) {
|
2012-08-10 06:55:51 +08:00
|
|
|
const ClusterBindings *Cluster = B.lookup(K.getBaseRegion());
|
|
|
|
if (!Cluster)
|
|
|
|
return 0;
|
|
|
|
|
|
|
|
return Cluster->lookup(K);
|
2010-01-11 08:07:44 +08:00
|
|
|
}
|
|
|
|
|
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) {
|
2012-08-10 06:55:51 +08:00
|
|
|
const MemRegion *Base = K.getBaseRegion();
|
|
|
|
const ClusterBindings *Cluster = B.lookup(Base);
|
|
|
|
if (!Cluster)
|
2010-08-16 09:15:17 +08:00
|
|
|
return B;
|
2012-08-10 06:55:51 +08:00
|
|
|
|
|
|
|
ClusterBindings NewCluster = CBFactory.remove(*Cluster, K);
|
|
|
|
if (NewCluster.isEmpty())
|
|
|
|
return RBFactory.remove(B, Base);
|
|
|
|
return RBFactory.add(B, Base, NewCluster);
|
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
|
|
|
}
|
|
|
|
|
2012-08-10 06:55:51 +08:00
|
|
|
RegionBindings RegionStoreManager::removeCluster(RegionBindings B,
|
|
|
|
const MemRegion *Base) {
|
|
|
|
return RBFactory.remove(B, Base);
|
|
|
|
}
|
|
|
|
|
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.
|
2012-08-10 06:55:51 +08:00
|
|
|
void VisitAddedToCluster(const MemRegion *baseR, const ClusterBindings &C);
|
|
|
|
void VisitCluster(const MemRegion *baseR, const ClusterBindings &C);
|
2010-03-11 00:32:56 +08:00
|
|
|
|
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,
|
2012-08-10 06:55:51 +08:00
|
|
|
const ClusterBindings &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))
|
2012-08-10 06:55:51 +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()))
|
2012-08-10 06:55:51 +08:00
|
|
|
AddToWorkList(SR, &C);
|
2010-03-11 00:32:56 +08:00
|
|
|
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)) {
|
2012-08-10 06:55:51 +08:00
|
|
|
AddToWorkList(baseR, &C);
|
2010-07-02 04:16:50 +08:00
|
|
|
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))
|
2012-08-10 06:55:51 +08:00
|
|
|
AddToWorkList(TR, &C);
|
2010-03-17 11:35:08 +08:00
|
|
|
}
|
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,
|
2012-08-10 06:55:51 +08:00
|
|
|
const ClusterBindings &C) {
|
|
|
|
for (ClusterBindings::iterator I = C.begin(), E = C.end(); I != E; ++I) {
|
|
|
|
VisitBindingKey(I.getKey());
|
|
|
|
VisitBinding(I.getData());
|
|
|
|
}
|
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 =
|
2012-08-10 06:55:51 +08:00
|
|
|
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());
|
2012-08-10 06:55:51 +08:00
|
|
|
|
|
|
|
// FIXME: This should not have to walk all bindings in the old store.
|
2010-03-11 00:32:56 +08:00
|
|
|
for (RegionBindings::iterator RI = B.begin(), RE = B.end(); RI != RE; ++RI){
|
2012-08-10 06:55:51 +08:00
|
|
|
const ClusterBindings &Cluster = RI.getData();
|
|
|
|
for (ClusterBindings::iterator CI = Cluster.begin(), CE = Cluster.end();
|
|
|
|
CI != CE; ++CI) {
|
|
|
|
BindingKey K = CI.getKey();
|
|
|
|
if (const SubRegion *BaseR = dyn_cast<SubRegion>(K.getRegion())) {
|
|
|
|
if (BaseR == LazyR)
|
|
|
|
VisitBinding(CI.getData());
|
|
|
|
else if (K.hasSymbolicOffset() && BaseR->isSubRegionOf(LazyR))
|
|
|
|
VisitBinding(CI.getData());
|
|
|
|
}
|
|
|
|
}
|
2009-11-26 10:35:42 +08:00
|
|
|
}
|
2012-08-10 06:55:51 +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.
|
2012-06-02 04:04:04 +08:00
|
|
|
if (const MemRegion *R = V.getAsRegion()) {
|
2010-03-11 00:32:56 +08:00
|
|
|
AddToWorkList(R);
|
2012-06-02 04:04:04 +08:00
|
|
|
|
|
|
|
// All regions captured by a block are also live.
|
|
|
|
if (const BlockDataRegion *BR = dyn_cast<BlockDataRegion>(R)) {
|
|
|
|
BlockDataRegion::referenced_vars_iterator I = BR->referenced_vars_begin(),
|
|
|
|
E = BR->referenced_vars_end();
|
|
|
|
for ( ; I != E; ++I)
|
|
|
|
AddToWorkList(I.getCapturedRegion());
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
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());
|
2009-09-29 14:35:00 +08:00
|
|
|
}
|
2010-03-11 00:32:56 +08:00
|
|
|
}
|
|
|
|
|
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) {
|
2012-08-10 06:55:51 +08:00
|
|
|
const MemRegion *Base = I.getKey();
|
2010-03-11 00:32:56 +08:00
|
|
|
|
2010-03-11 00:38:41 +08:00
|
|
|
// If the cluster has been visited, we know the region has been marked.
|
2012-08-10 06:55:51 +08:00
|
|
|
if (W.isVisited(Base))
|
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.
|
2012-08-10 06:55:51 +08:00
|
|
|
B = removeCluster(B, Base);
|
2009-09-09 23:08:12 +08:00
|
|
|
|
2012-08-10 06:55:51 +08:00
|
|
|
if (const SymbolicRegion *SymR = dyn_cast<SymbolicRegion>(Base))
|
2009-06-17 06:36:44 +08:00
|
|
|
SymReaper.maybeDead(SymR->getSymbol());
|
2009-09-09 23:08:12 +08:00
|
|
|
|
2012-08-10 06:55:51 +08:00
|
|
|
// Mark all non-live symbols that this binding references as dead.
|
|
|
|
const ClusterBindings &Cluster = I.getData();
|
|
|
|
for (ClusterBindings::iterator CI = Cluster.begin(), CE = Cluster.end();
|
|
|
|
CI != CE; ++CI) {
|
|
|
|
SVal X = CI.getData();
|
|
|
|
SymExpr::symbol_iterator SI = X.symbol_begin(), SE = X.symbol_end();
|
|
|
|
for (; SI != SE; ++SI)
|
|
|
|
SymReaper.maybeDead(*SI);
|
|
|
|
}
|
2009-08-02 13:00:15 +08:00
|
|
|
}
|
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
|
|
|
}
|
|
|
|
|
|
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
// 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);
|
2012-05-09 05:49:47 +08:00
|
|
|
OS << "Store (direct and default bindings), "
|
|
|
|
<< (void*) B.getRootWithoutRetain()
|
|
|
|
<< " :" << nl;
|
2009-09-09 23:08:12 +08:00
|
|
|
|
2012-08-10 06:55:51 +08:00
|
|
|
for (RegionBindings::iterator I = B.begin(), E = B.end(); I != E; ++I) {
|
|
|
|
const ClusterBindings &Cluster = I.getData();
|
|
|
|
for (ClusterBindings::iterator CI = Cluster.begin(), CE = Cluster.end();
|
|
|
|
CI != CE; ++CI) {
|
|
|
|
OS << ' ' << CI.getKey() << " : " << CI.getData() << nl;
|
|
|
|
}
|
|
|
|
OS << nl;
|
|
|
|
}
|
2009-06-17 06:36:44 +08:00
|
|
|
}
|