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.
|
|
|
|
//
|
|
|
|
//===----------------------------------------------------------------------===//
|
2012-12-01 23:09:41 +08:00
|
|
|
#include "clang/AST/Attr.h"
|
2010-01-18 16:54:31 +08:00
|
|
|
#include "clang/AST/CharUnits.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"
|
2012-12-01 23:09:41 +08:00
|
|
|
#include "clang/StaticAnalyzer/Core/PathSensitive/MemRegion.h"
|
2011-08-16 06:09:50 +08:00
|
|
|
#include "clang/StaticAnalyzer/Core/PathSensitive/ProgramState.h"
|
|
|
|
#include "clang/StaticAnalyzer/Core/PathSensitive/ProgramStateTrait.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;
|
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
|
|
|
|
2013-02-15 08:32:03 +08:00
|
|
|
/// Create a key for a binding to region \p r, which has a symbolic offset
|
|
|
|
/// from region \p Base.
|
|
|
|
explicit BindingKey(const SubRegion *r, const SubRegion *Base, Kind k)
|
2012-08-10 06:55:37 +08:00
|
|
|
: 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");
|
|
|
|
}
|
2013-02-15 08:32:03 +08:00
|
|
|
|
|
|
|
/// Create a key for a binding at \p offset from base region \p r.
|
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
|
|
|
}
|
|
|
|
|
2013-02-15 08:32:03 +08:00
|
|
|
const SubRegion *getConcreteOffsetRegion() const {
|
2012-08-10 06:55:37 +08:00
|
|
|
assert(hasSymbolicOffset());
|
2013-02-15 08:32:03 +08:00
|
|
|
return reinterpret_cast<const SubRegion *>(static_cast<uintptr_t>(Data));
|
2012-08-10 06:55:37 +08:00
|
|
|
}
|
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())
|
2013-02-15 08:32:03 +08:00
|
|
|
return BindingKey(cast<SubRegion>(R), cast<SubRegion>(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-12-07 14:49:27 +08:00
|
|
|
typedef llvm::ImmutableMap<BindingKey, SVal> ClusterBindings;
|
|
|
|
typedef llvm::ImmutableMapRef<BindingKey, SVal> ClusterBindingsRef;
|
2012-12-07 09:55:21 +08:00
|
|
|
|
|
|
|
typedef llvm::ImmutableMap<const MemRegion *, ClusterBindings>
|
|
|
|
RegionBindings;
|
|
|
|
|
|
|
|
namespace {
|
|
|
|
class RegionBindingsRef : public llvm::ImmutableMapRef<const MemRegion *,
|
|
|
|
ClusterBindings> {
|
|
|
|
ClusterBindings::Factory &CBFactory;
|
|
|
|
public:
|
|
|
|
typedef llvm::ImmutableMapRef<const MemRegion *, ClusterBindings>
|
|
|
|
ParentTy;
|
|
|
|
|
|
|
|
RegionBindingsRef(ClusterBindings::Factory &CBFactory,
|
|
|
|
const RegionBindings::TreeTy *T,
|
|
|
|
RegionBindings::TreeTy::Factory *F)
|
2012-12-07 11:28:20 +08:00
|
|
|
: llvm::ImmutableMapRef<const MemRegion *, ClusterBindings>(T, F),
|
|
|
|
CBFactory(CBFactory) {}
|
2012-12-07 09:55:21 +08:00
|
|
|
|
|
|
|
RegionBindingsRef(const ParentTy &P, ClusterBindings::Factory &CBFactory)
|
2012-12-07 11:28:20 +08:00
|
|
|
: llvm::ImmutableMapRef<const MemRegion *, ClusterBindings>(P),
|
|
|
|
CBFactory(CBFactory) {}
|
2012-12-07 09:55:21 +08:00
|
|
|
|
2012-12-08 03:54:25 +08:00
|
|
|
RegionBindingsRef add(key_type_ref K, data_type_ref D) const {
|
|
|
|
return RegionBindingsRef(static_cast<const ParentTy*>(this)->add(K, D),
|
2012-12-07 09:55:21 +08:00
|
|
|
CBFactory);
|
|
|
|
}
|
|
|
|
|
2012-12-08 03:54:25 +08:00
|
|
|
RegionBindingsRef remove(key_type_ref K) const {
|
|
|
|
return RegionBindingsRef(static_cast<const ParentTy*>(this)->remove(K),
|
2012-12-07 09:55:21 +08:00
|
|
|
CBFactory);
|
|
|
|
}
|
|
|
|
|
2012-12-08 03:54:25 +08:00
|
|
|
RegionBindingsRef addBinding(BindingKey K, SVal V) const;
|
2012-12-07 09:55:21 +08:00
|
|
|
|
|
|
|
RegionBindingsRef addBinding(const MemRegion *R,
|
2012-12-08 03:54:25 +08:00
|
|
|
BindingKey::Kind k, SVal V) const;
|
2012-12-07 09:55:21 +08:00
|
|
|
|
|
|
|
RegionBindingsRef &operator=(const RegionBindingsRef &X) {
|
|
|
|
*static_cast<ParentTy*>(this) = X;
|
|
|
|
return *this;
|
|
|
|
}
|
|
|
|
|
2012-12-08 03:54:25 +08:00
|
|
|
const SVal *lookup(BindingKey K) const;
|
|
|
|
const SVal *lookup(const MemRegion *R, BindingKey::Kind k) const;
|
2012-12-07 09:55:21 +08:00
|
|
|
const ClusterBindings *lookup(const MemRegion *R) const {
|
|
|
|
return static_cast<const ParentTy*>(this)->lookup(R);
|
|
|
|
}
|
|
|
|
|
|
|
|
RegionBindingsRef removeBinding(BindingKey K);
|
|
|
|
|
|
|
|
RegionBindingsRef removeBinding(const MemRegion *R,
|
|
|
|
BindingKey::Kind k);
|
|
|
|
|
|
|
|
RegionBindingsRef removeBinding(const MemRegion *R) {
|
|
|
|
return removeBinding(R, BindingKey::Direct).
|
|
|
|
removeBinding(R, BindingKey::Default);
|
|
|
|
}
|
|
|
|
|
2012-12-08 03:54:25 +08:00
|
|
|
Optional<SVal> getDirectBinding(const MemRegion *R) const;
|
2012-12-07 09:55:21 +08:00
|
|
|
|
|
|
|
/// getDefaultBinding - Returns an SVal* representing an optional default
|
|
|
|
/// binding associated with a region and its subregions.
|
2012-12-08 03:54:25 +08:00
|
|
|
Optional<SVal> getDefaultBinding(const MemRegion *R) const;
|
2012-12-08 02:32:08 +08:00
|
|
|
|
|
|
|
/// Return the internal tree as a Store.
|
|
|
|
Store asStore() const {
|
|
|
|
return asImmutableMap().getRootWithoutRetain();
|
|
|
|
}
|
2012-12-14 09:23:13 +08:00
|
|
|
|
2013-01-13 03:30:44 +08:00
|
|
|
void dump(raw_ostream &OS, const char *nl) const {
|
2012-12-14 09:23:13 +08:00
|
|
|
for (iterator I = begin(), E = 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;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
LLVM_ATTRIBUTE_USED void dump() const {
|
|
|
|
dump(llvm::errs(), "\n");
|
|
|
|
}
|
2012-12-07 09:55:21 +08:00
|
|
|
};
|
|
|
|
} // end anonymous namespace
|
|
|
|
|
2012-12-08 03:54:25 +08:00
|
|
|
typedef const RegionBindingsRef& RegionBindingsConstRef;
|
|
|
|
|
|
|
|
Optional<SVal> RegionBindingsRef::getDirectBinding(const MemRegion *R) const {
|
2012-12-07 09:55:21 +08:00
|
|
|
if (const SVal *V = lookup(R, BindingKey::Direct))
|
|
|
|
return *V;
|
|
|
|
return Optional<SVal>();
|
|
|
|
}
|
|
|
|
|
2012-12-08 03:54:25 +08:00
|
|
|
Optional<SVal> RegionBindingsRef::getDefaultBinding(const MemRegion *R) const {
|
2012-12-07 09:55:21 +08:00
|
|
|
if (R->isBoundable())
|
|
|
|
if (const TypedValueRegion *TR = dyn_cast<TypedValueRegion>(R))
|
|
|
|
if (TR->getValueType()->isUnionType())
|
|
|
|
return UnknownVal();
|
|
|
|
if (const SVal *V = lookup(R, BindingKey::Default))
|
|
|
|
return *V;
|
|
|
|
return Optional<SVal>();
|
|
|
|
}
|
|
|
|
|
2012-12-08 03:54:25 +08:00
|
|
|
RegionBindingsRef RegionBindingsRef::addBinding(BindingKey K, SVal V) const {
|
2012-12-07 09:55:21 +08:00
|
|
|
const MemRegion *Base = K.getBaseRegion();
|
|
|
|
|
|
|
|
const ClusterBindings *ExistingCluster = lookup(Base);
|
|
|
|
ClusterBindings Cluster = (ExistingCluster ? *ExistingCluster
|
|
|
|
: CBFactory.getEmptyMap());
|
|
|
|
|
|
|
|
ClusterBindings NewCluster = CBFactory.add(Cluster, K, V);
|
|
|
|
return add(Base, NewCluster);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
RegionBindingsRef RegionBindingsRef::addBinding(const MemRegion *R,
|
|
|
|
BindingKey::Kind k,
|
2012-12-08 03:54:25 +08:00
|
|
|
SVal V) const {
|
2012-12-07 09:55:21 +08:00
|
|
|
return addBinding(BindingKey::Make(R, k), V);
|
|
|
|
}
|
|
|
|
|
2012-12-08 03:54:25 +08:00
|
|
|
const SVal *RegionBindingsRef::lookup(BindingKey K) const {
|
2012-12-07 09:55:21 +08:00
|
|
|
const ClusterBindings *Cluster = lookup(K.getBaseRegion());
|
|
|
|
if (!Cluster)
|
|
|
|
return 0;
|
|
|
|
return Cluster->lookup(K);
|
|
|
|
}
|
|
|
|
|
|
|
|
const SVal *RegionBindingsRef::lookup(const MemRegion *R,
|
2012-12-08 03:54:25 +08:00
|
|
|
BindingKey::Kind k) const {
|
2012-12-07 09:55:21 +08:00
|
|
|
return lookup(BindingKey::Make(R, k));
|
|
|
|
}
|
|
|
|
|
|
|
|
RegionBindingsRef RegionBindingsRef::removeBinding(BindingKey K) {
|
|
|
|
const MemRegion *Base = K.getBaseRegion();
|
|
|
|
const ClusterBindings *Cluster = lookup(Base);
|
|
|
|
if (!Cluster)
|
|
|
|
return *this;
|
|
|
|
|
|
|
|
ClusterBindings NewCluster = CBFactory.remove(*Cluster, K);
|
|
|
|
if (NewCluster.isEmpty())
|
|
|
|
return remove(Base);
|
|
|
|
return add(Base, NewCluster);
|
|
|
|
}
|
|
|
|
|
|
|
|
RegionBindingsRef RegionBindingsRef::removeBinding(const MemRegion *R,
|
|
|
|
BindingKey::Kind k){
|
|
|
|
return removeBinding(BindingKey::Make(R, k));
|
|
|
|
}
|
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 {
|
2012-12-07 09:55:21 +08:00
|
|
|
public:
|
2009-06-17 06:36:44 +08:00
|
|
|
const RegionStoreFeatures Features;
|
2009-08-06 12:50:20 +08:00
|
|
|
RegionBindings::Factory RBFactory;
|
2012-12-07 09:55:21 +08:00
|
|
|
mutable ClusterBindings::Factory CBFactory;
|
2010-03-10 15:20:03 +08:00
|
|
|
|
2013-02-15 08:32:12 +08:00
|
|
|
typedef std::vector<SVal> SValListTy;
|
|
|
|
private:
|
|
|
|
typedef llvm::DenseMap<const LazyCompoundValData *,
|
|
|
|
SValListTy> LazyBindingsMapTy;
|
|
|
|
LazyBindingsMapTy LazyBindingsMap;
|
|
|
|
|
|
|
|
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
|
|
|
|
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.
|
2012-12-08 03:54:25 +08:00
|
|
|
RegionBindingsRef setImplicitDefaultValue(RegionBindingsConstRef B,
|
|
|
|
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
|
|
|
|
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-12-07 09:55:21 +08:00
|
|
|
RegionBindingsRef invalidateGlobalRegion(MemRegion::Kind K,
|
|
|
|
const Expr *Ex,
|
|
|
|
unsigned Count,
|
|
|
|
const LocationContext *LCtx,
|
|
|
|
RegionBindingsRef 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);
|
|
|
|
|
2012-12-08 03:54:25 +08:00
|
|
|
RegionBindingsRef removeSubRegionBindings(RegionBindingsConstRef B,
|
2012-12-07 09:55:21 +08:00
|
|
|
const SubRegion *R);
|
2012-08-10 06:55:51 +08:00
|
|
|
|
2010-02-03 11:06:46 +08:00
|
|
|
public: // Part of public interface to class.
|
|
|
|
|
2012-12-08 03:54:25 +08:00
|
|
|
virtual StoreRef Bind(Store store, Loc LV, SVal V) {
|
|
|
|
return StoreRef(bind(getRegionBindings(store), LV, V).asStore(), *this);
|
|
|
|
}
|
|
|
|
|
|
|
|
RegionBindingsRef bind(RegionBindingsConstRef B, 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) {
|
2012-12-07 09:55:21 +08:00
|
|
|
RegionBindingsRef B = getRegionBindings(store);
|
|
|
|
assert(!B.lookup(R, BindingKey::Default));
|
|
|
|
assert(!B.lookup(R, BindingKey::Direct));
|
|
|
|
return StoreRef(B.addBinding(R, BindingKey::Default, V)
|
|
|
|
.asImmutableMap()
|
|
|
|
.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.
|
2012-12-08 03:54:25 +08:00
|
|
|
RegionBindingsRef bindStruct(RegionBindingsConstRef B,
|
|
|
|
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.
|
2012-12-08 03:54:25 +08:00
|
|
|
RegionBindingsRef bindVector(RegionBindingsConstRef B,
|
|
|
|
const TypedValueRegion* R, SVal V);
|
2012-05-11 06:02:39 +08:00
|
|
|
|
2012-12-08 03:54:25 +08:00
|
|
|
RegionBindingsRef bindArray(RegionBindingsConstRef B,
|
|
|
|
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.
|
2012-12-08 03:54:25 +08:00
|
|
|
RegionBindingsRef bindAggregate(RegionBindingsConstRef B,
|
|
|
|
const TypedRegion *R,
|
|
|
|
SVal DefaultVal);
|
2008-10-24 09:38:55 +08:00
|
|
|
|
2012-08-22 14:37:46 +08:00
|
|
|
/// \brief Create a new store with the specified binding removed.
|
2012-08-23 07:50:41 +08:00
|
|
|
/// \param ST the original store, that is the basis for the new store.
|
|
|
|
/// \param L the location whose binding should be removed.
|
2012-12-08 03:54:25 +08:00
|
|
|
virtual StoreRef killBinding(Store ST, Loc L);
|
2010-03-10 15:20:03 +08:00
|
|
|
|
2011-02-19 09:59:33 +08:00
|
|
|
void incrementReferenceCount(Store store) {
|
2012-12-07 09:55:21 +08:00
|
|
|
getRegionBindings(store).manualRetain();
|
2011-02-19 09:59:33 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
/// 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) {
|
2012-12-07 09:55:21 +08:00
|
|
|
getRegionBindings(store).manualRelease();
|
2011-02-19 09:59:33 +08:00
|
|
|
}
|
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-12-08 03:54:25 +08:00
|
|
|
virtual SVal getBinding(Store S, Loc L, QualType T) {
|
|
|
|
return getBinding(getRegionBindings(S), L, T);
|
|
|
|
}
|
|
|
|
|
|
|
|
SVal getBinding(RegionBindingsConstRef B, Loc L, QualType T = QualType());
|
2009-06-25 12:50:44 +08:00
|
|
|
|
2012-12-08 03:54:25 +08:00
|
|
|
SVal getBindingForElement(RegionBindingsConstRef B, const ElementRegion *R);
|
2009-06-25 13:29:39 +08:00
|
|
|
|
2012-12-08 03:54:25 +08:00
|
|
|
SVal getBindingForField(RegionBindingsConstRef B, const FieldRegion *R);
|
2009-09-09 23:08:12 +08:00
|
|
|
|
2012-12-08 03:54:25 +08:00
|
|
|
SVal getBindingForObjCIvar(RegionBindingsConstRef B, const ObjCIvarRegion *R);
|
2009-09-09 23:08:12 +08:00
|
|
|
|
2012-12-08 03:54:25 +08:00
|
|
|
SVal getBindingForVar(RegionBindingsConstRef B, 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-12-08 03:54:25 +08:00
|
|
|
SVal getBindingForFieldOrElementCommon(RegionBindingsConstRef B,
|
|
|
|
const TypedValueRegion *R,
|
|
|
|
QualType Ty,
|
|
|
|
const MemRegion *superR);
|
2011-03-17 11:51:51 +08:00
|
|
|
|
2013-02-21 09:34:51 +08:00
|
|
|
SVal getLazyBinding(const SubRegion *LazyBindingRegion,
|
2012-12-08 03:54:25 +08:00
|
|
|
RegionBindingsRef LazyBinding);
|
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.
|
2013-02-02 03:49:57 +08:00
|
|
|
SVal getBindingForStruct(RegionBindingsConstRef B, const TypedValueRegion *R);
|
|
|
|
SVal getBindingForArray(RegionBindingsConstRef B, const TypedValueRegion *R);
|
|
|
|
NonLoc createLazyBinding(RegionBindingsConstRef B, 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-12-08 03:54:25 +08:00
|
|
|
Optional<SVal> getBindingForDerivedDefaultValue(RegionBindingsConstRef B,
|
2012-01-12 10:22:40 +08:00
|
|
|
const MemRegion *superR,
|
|
|
|
const TypedValueRegion *R,
|
|
|
|
QualType Ty);
|
2010-07-02 04:16:50 +08:00
|
|
|
|
2013-02-20 04:28:33 +08:00
|
|
|
/// Get the state and region whose binding this region \p R corresponds to.
|
|
|
|
///
|
|
|
|
/// If there is no lazy binding for \p R, the returned value will have a null
|
|
|
|
/// \c second. Note that a null pointer can represents a valid Store.
|
2013-02-21 09:34:51 +08:00
|
|
|
std::pair<Store, const SubRegion *>
|
|
|
|
findLazyBinding(RegionBindingsConstRef B, const SubRegion *R,
|
|
|
|
const SubRegion *originalRegion);
|
2009-09-09 23:08:12 +08:00
|
|
|
|
2013-02-15 08:32:12 +08:00
|
|
|
/// Returns the cached set of interesting SVals contained within a lazy
|
|
|
|
/// binding.
|
|
|
|
///
|
|
|
|
/// The precise value of "interesting" is determined for the purposes of
|
|
|
|
/// RegionStore's internal analysis. It must always contain all regions and
|
|
|
|
/// symbols, but may omit constants and other kinds of SVal.
|
|
|
|
const SValListTy &getInterestingValues(nonloc::LazyCompoundVal LCV);
|
|
|
|
|
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
|
|
|
|
2012-12-07 09:55:21 +08:00
|
|
|
RegionBindingsRef getRegionBindings(Store store) const {
|
|
|
|
return RegionBindingsRef(CBFactory,
|
|
|
|
static_cast<const RegionBindings::TreeTy*>(store),
|
|
|
|
RBFactory.getTreeFactory());
|
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) {
|
2012-12-07 09:55:21 +08:00
|
|
|
RegionBindingsRef B = getRegionBindings(store);
|
|
|
|
for (RegionBindingsRef::iterator I = B.begin(), E = B.end(); I != E; ++I) {
|
2012-08-10 06:55:51 +08:00
|
|
|
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
|
|
|
|
2012-12-07 09:55:21 +08:00
|
|
|
RegionBindingsRef 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,
|
2012-12-07 09:55:21 +08:00
|
|
|
RegionBindingsRef 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
|
|
|
|
2012-12-07 09:55:21 +08:00
|
|
|
RegionBindingsRef getRegionBindings() const { return B; }
|
2010-03-11 00:32:56 +08:00
|
|
|
|
|
|
|
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.
|
2012-12-07 09:55:21 +08:00
|
|
|
for (RegionBindingsRef::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-12-07 09:55:21 +08:00
|
|
|
RegionBindingsRef 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;
|
|
|
|
}
|
|
|
|
|
2012-11-10 09:40:08 +08:00
|
|
|
static inline bool isUnionField(const FieldRegion *FR) {
|
|
|
|
return FR->getDecl()->getParent()->isUnion();
|
|
|
|
}
|
|
|
|
|
|
|
|
typedef SmallVector<const FieldDecl *, 8> FieldVector;
|
|
|
|
|
|
|
|
void getSymbolicOffsetFields(BindingKey K, FieldVector &Fields) {
|
|
|
|
assert(K.hasSymbolicOffset() && "Not implemented for concrete offset keys");
|
|
|
|
|
|
|
|
const MemRegion *Base = K.getConcreteOffsetRegion();
|
|
|
|
const MemRegion *R = K.getRegion();
|
|
|
|
|
|
|
|
while (R != Base) {
|
|
|
|
if (const FieldRegion *FR = dyn_cast<FieldRegion>(R))
|
|
|
|
if (!isUnionField(FR))
|
|
|
|
Fields.push_back(FR->getDecl());
|
|
|
|
|
|
|
|
R = cast<SubRegion>(R)->getSuperRegion();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
static bool isCompatibleWithFields(BindingKey K, const FieldVector &Fields) {
|
|
|
|
assert(K.hasSymbolicOffset() && "Not implemented for concrete offset keys");
|
|
|
|
|
|
|
|
if (Fields.empty())
|
|
|
|
return true;
|
|
|
|
|
|
|
|
FieldVector FieldsInBindingKey;
|
|
|
|
getSymbolicOffsetFields(K, FieldsInBindingKey);
|
|
|
|
|
|
|
|
ptrdiff_t Delta = FieldsInBindingKey.size() - Fields.size();
|
|
|
|
if (Delta >= 0)
|
|
|
|
return std::equal(FieldsInBindingKey.begin() + Delta,
|
|
|
|
FieldsInBindingKey.end(),
|
|
|
|
Fields.begin());
|
|
|
|
else
|
|
|
|
return std::equal(FieldsInBindingKey.begin(), FieldsInBindingKey.end(),
|
|
|
|
Fields.begin() - Delta);
|
|
|
|
}
|
|
|
|
|
2013-02-15 08:32:06 +08:00
|
|
|
/// Collects all keys in \p Cluster that may refer to bindings within \p Top.
|
|
|
|
///
|
|
|
|
/// The \p IncludeAllDefaultBindings parameter specifies whether to include
|
|
|
|
/// default bindings that may extend beyond \p Top itself, e.g. if \p Top is
|
|
|
|
/// an aggregate within a larger aggregate with a default binding.
|
2013-02-15 08:32:03 +08:00
|
|
|
static void collectSubRegionKeys(SmallVectorImpl<BindingKey> &Keys,
|
|
|
|
SValBuilder &SVB,
|
|
|
|
const ClusterBindings &Cluster,
|
2013-02-15 08:32:06 +08:00
|
|
|
const SubRegion *Top, BindingKey TopKey,
|
|
|
|
bool IncludeAllDefaultBindings) {
|
2012-11-10 09:40:08 +08:00
|
|
|
FieldVector FieldsInSymbolicSubregions;
|
2013-02-15 08:32:03 +08:00
|
|
|
if (TopKey.hasSymbolicOffset()) {
|
|
|
|
getSymbolicOffsetFields(TopKey, FieldsInSymbolicSubregions);
|
|
|
|
Top = cast<SubRegion>(TopKey.getConcreteOffsetRegion());
|
|
|
|
TopKey = BindingKey::Make(Top, BindingKey::Default);
|
2012-08-09 02:23:27 +08:00
|
|
|
}
|
|
|
|
|
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;
|
2013-02-15 08:32:03 +08:00
|
|
|
SVal Extent = Top->getExtent(SVB);
|
2013-02-21 06:23:23 +08:00
|
|
|
if (Optional<nonloc::ConcreteInt> ExtentCI =
|
2013-02-20 13:52:05 +08:00
|
|
|
Extent.getAs<nonloc::ConcreteInt>()) {
|
2012-08-09 02:23:27 +08:00
|
|
|
const llvm::APSInt &ExtentInt = ExtentCI->getValue();
|
|
|
|
assert(ExtentInt.isNonNegative() || ExtentInt.isUnsigned());
|
|
|
|
// Extents are in bytes but region offsets are in bits. Be careful!
|
2013-02-15 08:32:03 +08:00
|
|
|
Length = ExtentInt.getLimitedValue() * SVB.getContext().getCharWidth();
|
2012-08-09 02:23:27 +08:00
|
|
|
}
|
|
|
|
|
2013-02-15 08:32:03 +08:00
|
|
|
for (ClusterBindings::iterator I = Cluster.begin(), E = Cluster.end();
|
2012-08-10 06:55:51 +08:00
|
|
|
I != E; ++I) {
|
|
|
|
BindingKey NextKey = I.getKey();
|
2013-02-15 08:32:03 +08:00
|
|
|
if (NextKey.getRegion() == TopKey.getRegion()) {
|
2012-11-10 09:40:08 +08:00
|
|
|
// FIXME: This doesn't catch the case where we're really invalidating a
|
|
|
|
// region with a symbolic offset. Example:
|
|
|
|
// R: points[i].y
|
|
|
|
// Next: points[0].x
|
|
|
|
|
2013-02-15 08:32:03 +08:00
|
|
|
if (NextKey.getOffset() > TopKey.getOffset() &&
|
|
|
|
NextKey.getOffset() - TopKey.getOffset() < Length) {
|
2012-08-10 06:55:51 +08:00
|
|
|
// Case 1: The next binding is inside the region we're invalidating.
|
|
|
|
// Remove it.
|
2013-02-15 08:32:03 +08:00
|
|
|
Keys.push_back(NextKey);
|
2012-11-10 09:40:08 +08:00
|
|
|
|
2013-02-15 08:32:03 +08:00
|
|
|
} else if (NextKey.getOffset() == TopKey.getOffset()) {
|
2012-08-10 06:55:51 +08:00
|
|
|
// 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.
|
2013-02-15 08:32:06 +08:00
|
|
|
if (IncludeAllDefaultBindings || NextKey.isDirect())
|
2013-02-15 08:32:03 +08:00
|
|
|
Keys.push_back(NextKey);
|
2012-08-10 06:55:51 +08:00
|
|
|
}
|
2013-02-15 08:32:03 +08:00
|
|
|
|
2012-08-09 02:23:27 +08:00
|
|
|
} else if (NextKey.hasSymbolicOffset()) {
|
|
|
|
const MemRegion *Base = NextKey.getConcreteOffsetRegion();
|
2013-02-15 08:32:03 +08:00
|
|
|
if (Top->isSubRegionOf(Base)) {
|
2012-08-10 06:55:51 +08:00
|
|
|
// 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.
|
2013-02-15 08:32:06 +08:00
|
|
|
if (IncludeAllDefaultBindings || NextKey.isDirect())
|
2012-11-10 09:40:08 +08:00
|
|
|
if (isCompatibleWithFields(NextKey, FieldsInSymbolicSubregions))
|
2013-02-15 08:32:03 +08:00
|
|
|
Keys.push_back(NextKey);
|
2012-08-10 06:55:51 +08:00
|
|
|
} 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.
|
2013-02-15 08:32:03 +08:00
|
|
|
if (Top == Base || BaseSR->isSubRegionOf(Top))
|
2012-11-10 09:40:08 +08:00
|
|
|
if (isCompatibleWithFields(NextKey, FieldsInSymbolicSubregions))
|
2013-02-15 08:32:03 +08:00
|
|
|
Keys.push_back(NextKey);
|
2012-08-10 06:55:51 +08:00
|
|
|
}
|
2012-08-09 02:23:27 +08:00
|
|
|
}
|
|
|
|
}
|
2013-02-15 08:32:03 +08:00
|
|
|
}
|
|
|
|
|
2013-02-15 08:32:06 +08:00
|
|
|
static void collectSubRegionKeys(SmallVectorImpl<BindingKey> &Keys,
|
|
|
|
SValBuilder &SVB,
|
|
|
|
const ClusterBindings &Cluster,
|
|
|
|
const SubRegion *Top,
|
|
|
|
bool IncludeAllDefaultBindings) {
|
|
|
|
collectSubRegionKeys(Keys, SVB, Cluster, Top,
|
|
|
|
BindingKey::Make(Top, BindingKey::Default),
|
|
|
|
IncludeAllDefaultBindings);
|
|
|
|
}
|
|
|
|
|
2013-02-15 08:32:03 +08:00
|
|
|
RegionBindingsRef
|
|
|
|
RegionStoreManager::removeSubRegionBindings(RegionBindingsConstRef B,
|
|
|
|
const SubRegion *Top) {
|
|
|
|
BindingKey TopKey = BindingKey::Make(Top, BindingKey::Default);
|
|
|
|
const MemRegion *ClusterHead = TopKey.getBaseRegion();
|
|
|
|
if (Top == ClusterHead) {
|
|
|
|
// We can remove an entire cluster's bindings all in one go.
|
|
|
|
return B.remove(Top);
|
|
|
|
}
|
|
|
|
|
|
|
|
const ClusterBindings *Cluster = B.lookup(ClusterHead);
|
|
|
|
if (!Cluster)
|
|
|
|
return B;
|
|
|
|
|
|
|
|
SmallVector<BindingKey, 32> Keys;
|
2013-02-15 08:32:06 +08:00
|
|
|
collectSubRegionKeys(Keys, svalBuilder, *Cluster, Top, TopKey,
|
|
|
|
/*IncludeAllDefaultBindings=*/false);
|
2013-02-15 08:32:03 +08:00
|
|
|
|
|
|
|
ClusterBindingsRef Result(*Cluster, CBFactory);
|
|
|
|
for (SmallVectorImpl<BindingKey>::const_iterator I = Keys.begin(),
|
|
|
|
E = Keys.end();
|
|
|
|
I != E; ++I)
|
|
|
|
Result = Result.remove(*I);
|
2012-08-09 02:23:27 +08:00
|
|
|
|
2012-11-10 09:40:08 +08:00
|
|
|
// If we're invalidating a region with a symbolic offset, we need to make sure
|
|
|
|
// we don't treat the base region as uninitialized anymore.
|
|
|
|
// FIXME: This isn't very precise; see the example in the loop.
|
2013-02-15 08:32:03 +08:00
|
|
|
if (TopKey.hasSymbolicOffset()) {
|
|
|
|
const SubRegion *Concrete = TopKey.getConcreteOffsetRegion();
|
|
|
|
Result = Result.add(BindingKey::Make(Concrete, BindingKey::Default),
|
|
|
|
UnknownVal());
|
|
|
|
}
|
2012-11-10 09:40:08 +08:00
|
|
|
|
2012-12-07 03:40:32 +08:00
|
|
|
if (Result.isEmpty())
|
2012-12-07 09:55:21 +08:00
|
|
|
return B.remove(ClusterHead);
|
2012-12-07 14:49:27 +08:00
|
|
|
return B.add(ClusterHead, Result.asImmutableMap());
|
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;
|
2012-12-20 08:38:25 +08:00
|
|
|
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,
|
2012-12-07 09:55:21 +08:00
|
|
|
RegionBindingsRef b,
|
2010-03-11 00:32:56 +08:00
|
|
|
const Expr *ex, unsigned count,
|
2012-02-18 07:13:45 +08:00
|
|
|
const LocationContext *lctx,
|
2012-12-20 08:38:25 +08:00
|
|
|
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.
|
2013-02-21 06:23:23 +08:00
|
|
|
if (Optional<nonloc::LazyCompoundVal> LCS =
|
2013-02-20 13:52:05 +08:00
|
|
|
V.getAs<nonloc::LazyCompoundVal>()) {
|
2010-02-13 09:52:33 +08:00
|
|
|
|
2013-02-15 08:32:12 +08:00
|
|
|
const RegionStoreManager::SValListTy &Vals = RM.getInterestingValues(*LCS);
|
2010-02-13 09:52:33 +08:00
|
|
|
|
2013-02-15 08:32:12 +08:00
|
|
|
for (RegionStoreManager::SValListTy::const_iterator I = Vals.begin(),
|
|
|
|
E = Vals.end();
|
|
|
|
I != E; ++I)
|
|
|
|
VisitBinding(*I);
|
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-12-07 09:55:21 +08:00
|
|
|
B = B.remove(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) {
|
2012-12-06 15:17:20 +08:00
|
|
|
const VarRegion *VR = BI.getCapturedRegion();
|
2010-03-11 00:32:56 +08:00
|
|
|
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.
|
2012-12-08 03:54:25 +08:00
|
|
|
SVal V = RM.getBinding(B, loc::MemRegionVal(VR));
|
2013-02-21 06:23:23 +08:00
|
|
|
if (Optional<Loc> L = V.getAs<Loc>()) {
|
2012-05-05 05:48:42 +08:00
|
|
|
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);
|
2012-12-07 09:55:21 +08:00
|
|
|
B = B.addBinding(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);
|
2012-12-07 09:55:21 +08:00
|
|
|
B = B.addBinding(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);
|
2012-12-07 09:55:21 +08:00
|
|
|
B = B.addBinding(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.
|
2012-12-07 09:55:21 +08:00
|
|
|
B = B.removeBinding(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());
|
2012-12-07 09:55:21 +08:00
|
|
|
B = B.addBinding(baseR, BindingKey::Direct, V);
|
2009-07-30 02:16:25 +08:00
|
|
|
}
|
|
|
|
|
2012-12-07 09:55:21 +08:00
|
|
|
RegionBindingsRef
|
|
|
|
RegionStoreManager::invalidateGlobalRegion(MemRegion::Kind K,
|
|
|
|
const Expr *Ex,
|
|
|
|
unsigned Count,
|
|
|
|
const LocationContext *LCtx,
|
|
|
|
RegionBindingsRef B,
|
|
|
|
InvalidatedRegions *Invalidated) {
|
2012-01-05 07:54:01 +08:00
|
|
|
// 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-09-06 23:59:27 +08:00
|
|
|
SVal V = svalBuilder.conjureSymbolVal(/* SymbolTag = */ (const void*) GS, Ex, LCtx,
|
2012-08-22 14:26:06 +08:00
|
|
|
/* type does not matter */ Ctx.IntTy,
|
|
|
|
Count);
|
2012-01-05 07:54:01 +08:00
|
|
|
|
2012-12-07 09:55:21 +08:00
|
|
|
B = B.removeBinding(GS)
|
|
|
|
.addBinding(BindingKey::Make(GS, BindingKey::Default), V);
|
2012-01-05 07:54:01 +08:00
|
|
|
|
|
|
|
// 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;
|
|
|
|
}
|
|
|
|
|
2012-12-07 09:55:21 +08:00
|
|
|
StoreRef
|
|
|
|
RegionStoreManager::invalidateRegions(Store store,
|
|
|
|
ArrayRef<const MemRegion *> Regions,
|
|
|
|
const Expr *Ex, unsigned Count,
|
|
|
|
const LocationContext *LCtx,
|
|
|
|
InvalidatedSymbols &IS,
|
|
|
|
const CallEvent *Call,
|
|
|
|
InvalidatedRegions *Invalidated) {
|
2011-02-12 03:48:15 +08:00
|
|
|
invalidateRegionsWorker W(*this, StateMgr,
|
2012-12-07 09:55:21 +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.
|
2012-12-07 09:55:21 +08:00
|
|
|
RegionBindingsRef B = W.getRegionBindings();
|
2010-07-02 04:16:50 +08:00
|
|
|
|
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
|
|
|
}
|
|
|
|
|
2012-12-08 02:32:08 +08:00
|
|
|
return StoreRef(B.asStore(), *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) {
|
2013-02-20 13:52:05 +08:00
|
|
|
if (!Array.getAs<loc::MemRegionVal>())
|
2008-12-14 03:24:37 +08:00
|
|
|
return UnknownVal();
|
2009-09-09 23:08:12 +08:00
|
|
|
|
2013-02-20 13:52:05 +08:00
|
|
|
const MemRegion* R = Array.castAs<loc::MemRegionVal>().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
|
|
|
}
|
|
|
|
|
2009-06-17 06:36:44 +08:00
|
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
// Loading values from regions.
|
|
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
|
2012-12-08 03:54:25 +08:00
|
|
|
SVal RegionStoreManager::getBinding(RegionBindingsConstRef B, Loc L, QualType T) {
|
2013-02-20 13:52:05 +08:00
|
|
|
assert(!L.getAs<UnknownVal>() && "location unknown");
|
|
|
|
assert(!L.getAs<UndefinedVal>() && "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.
|
2013-02-20 13:52:05 +08:00
|
|
|
if (L.getAs<loc::ConcreteInt>()) {
|
2010-11-12 07:10:10 +08:00
|
|
|
return UnknownVal();
|
|
|
|
}
|
2013-02-20 13:52:05 +08:00
|
|
|
if (!L.getAs<loc::MemRegionVal>()) {
|
2011-01-25 08:04:03 +08:00
|
|
|
return UnknownVal();
|
|
|
|
}
|
2010-03-10 15:20:03 +08:00
|
|
|
|
2013-02-20 13:52:05 +08:00
|
|
|
const MemRegion *MR = L.castAs<loc::MemRegionVal>().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);
|
2012-09-26 14:00:14 +08:00
|
|
|
T = SR->getSymbol()->getType();
|
2012-01-13 08:56:48 +08:00
|
|
|
}
|
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
|
|
|
|
2013-01-10 02:46:17 +08:00
|
|
|
// FIXME: we do not yet model the parts of a complex type, so treat the
|
|
|
|
// whole thing as "unknown".
|
|
|
|
if (RTy->isAnyComplexType())
|
|
|
|
return UnknownVal();
|
|
|
|
|
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-12-08 03:54:25 +08:00
|
|
|
return getBindingForStruct(B, 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())
|
2012-12-08 03:54:25 +08:00
|
|
|
return getBindingForArray(B, R);
|
2012-06-16 09:28:00 +08:00
|
|
|
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-12-08 03:54:25 +08:00
|
|
|
return CastRetrievedVal(getBindingForField(B, 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-12-08 03:54:25 +08:00
|
|
|
return CastRetrievedVal(getBindingForElement(B, 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-12-08 03:54:25 +08:00
|
|
|
return CastRetrievedVal(getBindingForObjCIvar(B, 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-12-08 03:54:25 +08:00
|
|
|
return CastRetrievedVal(getBindingForVar(B, VR), VR, T, false);
|
2010-01-11 10:33:26 +08:00
|
|
|
}
|
2009-07-21 06:58:02 +08:00
|
|
|
|
2012-12-07 09:55:21 +08:00
|
|
|
const SVal *V = B.lookup(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
|
|
|
|
2013-02-21 09:34:51 +08:00
|
|
|
/// Checks to see if store \p B has a lazy binding for region \p R.
|
|
|
|
///
|
|
|
|
/// If \p AllowSubregionBindings is \c false, a lazy binding will be rejected
|
|
|
|
/// if there are additional bindings within \p R.
|
|
|
|
///
|
|
|
|
/// Note that unlike RegionStoreManager::findLazyBinding, this will not search
|
|
|
|
/// for lazy bindings for super-regions of \p R.
|
|
|
|
static Optional<nonloc::LazyCompoundVal>
|
|
|
|
getExistingLazyBinding(SValBuilder &SVB, RegionBindingsConstRef B,
|
|
|
|
const SubRegion *R, bool AllowSubregionBindings) {
|
|
|
|
Optional<SVal> V = B.getDefaultBinding(R);
|
|
|
|
if (!V)
|
|
|
|
return Optional<nonloc::LazyCompoundVal>();
|
|
|
|
|
|
|
|
Optional<nonloc::LazyCompoundVal> LCV = V->getAs<nonloc::LazyCompoundVal>();
|
|
|
|
if (!LCV)
|
|
|
|
return Optional<nonloc::LazyCompoundVal>();
|
|
|
|
|
|
|
|
// If the LCV is for a subregion, the types won't match, and we shouldn't
|
|
|
|
// reuse the binding. Unfortuately we can only check this if the destination
|
|
|
|
// region is a TypedValueRegion.
|
|
|
|
if (const TypedValueRegion *TVR = dyn_cast<TypedValueRegion>(R)) {
|
|
|
|
QualType RegionTy = TVR->getValueType();
|
|
|
|
QualType SourceRegionTy = LCV->getRegion()->getValueType();
|
|
|
|
if (!SVB.getContext().hasSameUnqualifiedType(RegionTy, SourceRegionTy))
|
|
|
|
return Optional<nonloc::LazyCompoundVal>();
|
|
|
|
}
|
|
|
|
|
|
|
|
if (!AllowSubregionBindings) {
|
|
|
|
// If there are any other bindings within this region, we shouldn't reuse
|
|
|
|
// the top-level binding.
|
|
|
|
SmallVector<BindingKey, 16> Keys;
|
|
|
|
collectSubRegionKeys(Keys, SVB, *B.lookup(R->getBaseRegion()), R,
|
|
|
|
/*IncludeAllDefaultBindings=*/true);
|
|
|
|
if (Keys.size() > 1)
|
|
|
|
return Optional<nonloc::LazyCompoundVal>();
|
|
|
|
}
|
|
|
|
|
|
|
|
return *LCV;
|
|
|
|
}
|
2013-02-20 04:28:33 +08:00
|
|
|
|
2013-02-21 09:34:51 +08:00
|
|
|
|
|
|
|
std::pair<Store, const SubRegion *>
|
|
|
|
RegionStoreManager::findLazyBinding(RegionBindingsConstRef B,
|
|
|
|
const SubRegion *R,
|
|
|
|
const SubRegion *originalRegion) {
|
2011-04-03 12:09:15 +08:00
|
|
|
if (originalRegion != R) {
|
2013-02-21 09:34:51 +08:00
|
|
|
if (Optional<nonloc::LazyCompoundVal> V =
|
|
|
|
getExistingLazyBinding(svalBuilder, B, R, true))
|
|
|
|
return std::make_pair(V->getStore(), V->getRegion());
|
2011-04-03 12:09:15 +08:00
|
|
|
}
|
2013-02-21 09:34:51 +08:00
|
|
|
|
|
|
|
typedef std::pair<Store, const SubRegion *> StoreRegionPair;
|
|
|
|
StoreRegionPair Result = StoreRegionPair();
|
|
|
|
|
2009-08-06 09:20:57 +08:00
|
|
|
if (const ElementRegion *ER = dyn_cast<ElementRegion>(R)) {
|
2013-02-21 09:34:51 +08:00
|
|
|
Result = findLazyBinding(B, cast<SubRegion>(ER->getSuperRegion()),
|
|
|
|
originalRegion);
|
2009-09-09 23:08:12 +08:00
|
|
|
|
2013-02-21 09:34:51 +08:00
|
|
|
if (Result.second)
|
|
|
|
Result.second = MRMgr.getElementRegionWithSuper(ER, Result.second);
|
|
|
|
|
|
|
|
} else if (const FieldRegion *FR = dyn_cast<FieldRegion>(R)) {
|
|
|
|
Result = findLazyBinding(B, cast<SubRegion>(FR->getSuperRegion()),
|
|
|
|
originalRegion);
|
|
|
|
|
|
|
|
if (Result.second)
|
|
|
|
Result.second = MRMgr.getFieldRegionWithSuper(FR, Result.second);
|
2009-09-09 23:08:12 +08:00
|
|
|
|
2013-02-20 04:28:33 +08:00
|
|
|
} else if (const CXXBaseObjectRegion *BaseReg =
|
|
|
|
dyn_cast<CXXBaseObjectRegion>(R)) {
|
|
|
|
// 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.
|
2013-02-21 09:34:51 +08:00
|
|
|
Result = findLazyBinding(B, cast<SubRegion>(BaseReg->getSuperRegion()),
|
|
|
|
originalRegion);
|
2011-01-13 20:30:12 +08:00
|
|
|
|
2013-02-21 09:34:51 +08:00
|
|
|
if (Result.second)
|
|
|
|
Result.second = MRMgr.getCXXBaseObjectRegionWithSuper(BaseReg,
|
|
|
|
Result.second);
|
2011-01-13 20:30:12 +08:00
|
|
|
}
|
2011-03-17 11:51:51 +08:00
|
|
|
|
2013-02-21 09:34:51 +08:00
|
|
|
return Result;
|
2009-08-06 09:20:57 +08:00
|
|
|
}
|
2008-10-21 13:29:26 +08:00
|
|
|
|
2012-12-08 03:54:25 +08:00
|
|
|
SVal RegionStoreManager::getBindingForElement(RegionBindingsConstRef B,
|
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.
|
2012-12-07 09:55:21 +08:00
|
|
|
if (const Optional<SVal> &V = B.getDirectBinding(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();
|
2013-02-21 06:23:23 +08:00
|
|
|
if (Optional<nonloc::ConcreteInt> CI = Idx.getAs<nonloc::ConcreteInt>()) {
|
2009-06-25 13:29:39 +08:00
|
|
|
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)) {
|
2012-12-07 09:55:21 +08:00
|
|
|
if (const Optional<SVal> &V = B.getDirectBinding(superR)) {
|
2010-05-31 09:22:04 +08:00
|
|
|
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-12-08 03:54:25 +08:00
|
|
|
return getBindingForFieldOrElementCommon(B, R, R->getElementType(),
|
2012-01-12 10:22:40 +08:00
|
|
|
superR);
|
2009-06-25 13:29:39 +08:00
|
|
|
}
|
|
|
|
|
2012-12-08 03:54:25 +08:00
|
|
|
SVal RegionStoreManager::getBindingForField(RegionBindingsConstRef B,
|
|
|
|
const FieldRegion* R) {
|
2009-06-25 12:50:44 +08:00
|
|
|
|
|
|
|
// Check if the region has a binding.
|
2012-12-07 09:55:21 +08:00
|
|
|
if (const Optional<SVal> &V = B.getDirectBinding(R))
|
2009-06-25 12:50:44 +08:00
|
|
|
return *V;
|
|
|
|
|
2010-08-11 14:10:55 +08:00
|
|
|
QualType Ty = R->getValueType();
|
2012-12-08 03:54:25 +08:00
|
|
|
return getBindingForFieldOrElementCommon(B, 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-12-08 03:54:25 +08:00
|
|
|
RegionStoreManager::getBindingForDerivedDefaultValue(RegionBindingsConstRef B,
|
2012-01-12 10:22:40 +08:00
|
|
|
const MemRegion *superR,
|
|
|
|
const TypedValueRegion *R,
|
|
|
|
QualType Ty) {
|
2010-07-02 04:16:50 +08:00
|
|
|
|
2012-12-07 09:55:21 +08:00
|
|
|
if (const Optional<SVal> &D = B.getDefaultBinding(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.
|
2013-02-20 13:52:05 +08:00
|
|
|
if (val.getAs<nonloc::LazyCompoundVal>())
|
2011-03-17 11:51:51 +08:00
|
|
|
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>();
|
|
|
|
}
|
|
|
|
|
2013-02-21 09:34:51 +08:00
|
|
|
SVal RegionStoreManager::getLazyBinding(const SubRegion *LazyBindingRegion,
|
2012-12-08 03:54:25 +08:00
|
|
|
RegionBindingsRef LazyBinding) {
|
2013-01-31 10:57:06 +08:00
|
|
|
SVal Result;
|
2012-12-08 03:54:25 +08:00
|
|
|
if (const ElementRegion *ER = dyn_cast<ElementRegion>(LazyBindingRegion))
|
2013-01-31 10:57:06 +08:00
|
|
|
Result = getBindingForElement(LazyBinding, ER);
|
|
|
|
else
|
|
|
|
Result = getBindingForField(LazyBinding,
|
|
|
|
cast<FieldRegion>(LazyBindingRegion));
|
|
|
|
|
|
|
|
// This is a hack to deal with RegionStore's inability to distinguish a
|
|
|
|
// default value for /part/ of an aggregate from a default value for the
|
|
|
|
// /entire/ aggregate. The most common case of this is when struct Outer
|
|
|
|
// has as its first member a struct Inner, which is copied in from a stack
|
|
|
|
// variable. In this case, even if the Outer's default value is symbolic, 0,
|
|
|
|
// or unknown, it gets overridden by the Inner's default value of undefined.
|
|
|
|
//
|
|
|
|
// This is a general problem -- if the Inner is zero-initialized, the Outer
|
|
|
|
// will now look zero-initialized. The proper way to solve this is with a
|
|
|
|
// new version of RegionStore that tracks the extent of a binding as well
|
|
|
|
// as the offset.
|
|
|
|
//
|
|
|
|
// This hack only takes care of the undefined case because that can very
|
|
|
|
// quickly result in a warning.
|
|
|
|
if (Result.isUndef())
|
|
|
|
Result = UnknownVal();
|
|
|
|
|
|
|
|
return Result;
|
2011-03-17 11:51:51 +08:00
|
|
|
}
|
|
|
|
|
2012-12-08 03:54:25 +08:00
|
|
|
SVal
|
|
|
|
RegionStoreManager::getBindingForFieldOrElementCommon(RegionBindingsConstRef B,
|
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.
|
2012-04-26 13:08:26 +08:00
|
|
|
|
|
|
|
// Lazy binding?
|
|
|
|
Store lazyBindingStore = NULL;
|
2013-02-21 09:34:51 +08:00
|
|
|
const SubRegion *lazyBindingRegion = NULL;
|
|
|
|
llvm::tie(lazyBindingStore, lazyBindingRegion) = findLazyBinding(B, R, R);
|
2012-04-26 13:08:26 +08:00
|
|
|
if (lazyBindingRegion)
|
2012-12-08 03:54:25 +08:00
|
|
|
return getLazyBinding(lazyBindingRegion,
|
|
|
|
getRegionBindings(lazyBindingStore));
|
2012-04-26 13:08:26 +08:00
|
|
|
|
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-12-08 03:54:25 +08:00
|
|
|
SVal RegionStoreManager::getBindingForObjCIvar(RegionBindingsConstRef B,
|
2012-01-12 10:22:40 +08:00
|
|
|
const ObjCIvarRegion* R) {
|
2012-12-08 03:54:25 +08:00
|
|
|
// Check if the region has a binding.
|
2012-12-07 09:55:21 +08:00
|
|
|
if (const Optional<SVal> &V = B.getDirectBinding(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.
|
2012-12-07 09:55:21 +08:00
|
|
|
if (const Optional<SVal> &V = B.getDefaultBinding(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
|
|
|
}
|
|
|
|
|
[analyzer] Try constant-evaluation for all variables, not just globals.
In C++, constants captured by lambdas (and blocks) are not actually stored
in the closure object, since they can be expanded at compile time. In this
case, they will have no binding when we go to look them up. Previously,
RegionStore thought they were uninitialized stack variables; now, it checks
to see if they are a constant we know how to evaluate, using the same logic
as r175026.
This particular code path is only for scalar variables. Constant arrays and
structs are still unfortunately unhandled; we'll need a stronger solution
for those.
This may have a small performance impact, but only for truly-undefined
local variables, captures in a non-inlined block, and non-constant globals.
Even then, in the non-constant case we're only doing a quick type check.
<rdar://problem/13105553>
llvm-svn: 175194
2013-02-15 03:06:11 +08:00
|
|
|
static Optional<SVal> getConstValue(SValBuilder &SVB, const VarDecl *VD) {
|
|
|
|
ASTContext &Ctx = SVB.getContext();
|
|
|
|
if (!VD->getType().isConstQualified())
|
|
|
|
return Optional<SVal>();
|
|
|
|
|
|
|
|
const Expr *Init = VD->getInit();
|
|
|
|
if (!Init)
|
|
|
|
return Optional<SVal>();
|
|
|
|
|
|
|
|
llvm::APSInt Result;
|
|
|
|
if (Init->EvaluateAsInt(Result, Ctx))
|
|
|
|
return SVB.makeIntVal(Result);
|
|
|
|
|
|
|
|
if (Init->isNullPointerConstant(Ctx, Expr::NPC_ValueDependentIsNotNull))
|
|
|
|
return SVB.makeNull();
|
|
|
|
|
|
|
|
// FIXME: Handle other possible constant expressions.
|
|
|
|
return Optional<SVal>();
|
|
|
|
}
|
|
|
|
|
2012-12-08 03:54:25 +08:00
|
|
|
SVal RegionStoreManager::getBindingForVar(RegionBindingsConstRef B,
|
|
|
|
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.
|
2012-12-07 09:55:21 +08:00
|
|
|
if (const Optional<SVal> &V = B.getDirectBinding(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
|
|
|
const MemSpaceRegion *MS = R->getMemorySpace();
|
2010-03-10 15:20:03 +08:00
|
|
|
|
[analyzer] Try constant-evaluation for all variables, not just globals.
In C++, constants captured by lambdas (and blocks) are not actually stored
in the closure object, since they can be expanded at compile time. In this
case, they will have no binding when we go to look them up. Previously,
RegionStore thought they were uninitialized stack variables; now, it checks
to see if they are a constant we know how to evaluate, using the same logic
as r175026.
This particular code path is only for scalar variables. Constant arrays and
structs are still unfortunately unhandled; we'll need a stronger solution
for those.
This may have a small performance impact, but only for truly-undefined
local variables, captures in a non-inlined block, and non-constant globals.
Even then, in the non-constant case we're only doing a quick type check.
<rdar://problem/13105553>
llvm-svn: 175194
2013-02-15 03:06:11 +08:00
|
|
|
// Arguments are always symbolic.
|
|
|
|
if (isa<StackArgumentsSpaceRegion>(MS))
|
|
|
|
return svalBuilder.getRegionValueSymbolVal(R);
|
|
|
|
|
|
|
|
// Is 'VD' declared constant? If so, retrieve the constant value.
|
|
|
|
if (Optional<SVal> V = getConstValue(svalBuilder, VD))
|
|
|
|
return *V;
|
|
|
|
|
|
|
|
// This must come after the check for constants because closure-captured
|
|
|
|
// constant variables may appear in UnknownSpaceRegion.
|
|
|
|
if (isa<UnknownSpaceRegion>(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)) {
|
[analyzer] Try constant-evaluation for all variables, not just globals.
In C++, constants captured by lambdas (and blocks) are not actually stored
in the closure object, since they can be expanded at compile time. In this
case, they will have no binding when we go to look them up. Previously,
RegionStore thought they were uninitialized stack variables; now, it checks
to see if they are a constant we know how to evaluate, using the same logic
as r175026.
This particular code path is only for scalar variables. Constant arrays and
structs are still unfortunately unhandled; we'll need a stronger solution
for those.
This may have a small performance impact, but only for truly-undefined
local variables, captures in a non-inlined block, and non-constant globals.
Even then, in the non-constant case we're only doing a quick type check.
<rdar://problem/13105553>
llvm-svn: 175194
2013-02-15 03:06:11 +08:00
|
|
|
QualType T = VD->getType();
|
|
|
|
|
2013-02-13 11:11:01 +08:00
|
|
|
// Function-scoped static variables are default-initialized to 0; if they
|
|
|
|
// have an initializer, it would have been processed by now.
|
|
|
|
if (isa<StaticGlobalSpaceRegion>(MS))
|
|
|
|
return svalBuilder.makeZeroVal(T);
|
|
|
|
|
[analyzer] Try constant-evaluation for all variables, not just globals.
In C++, constants captured by lambdas (and blocks) are not actually stored
in the closure object, since they can be expanded at compile time. In this
case, they will have no binding when we go to look them up. Previously,
RegionStore thought they were uninitialized stack variables; now, it checks
to see if they are a constant we know how to evaluate, using the same logic
as r175026.
This particular code path is only for scalar variables. Constant arrays and
structs are still unfortunately unhandled; we'll need a stronger solution
for those.
This may have a small performance impact, but only for truly-undefined
local variables, captures in a non-inlined block, and non-constant globals.
Even then, in the non-constant case we're only doing a quick type check.
<rdar://problem/13105553>
llvm-svn: 175194
2013-02-15 03:06:11 +08:00
|
|
|
if (Optional<SVal> V = getBindingForDerivedDefaultValue(B, MS, R, T))
|
2013-02-13 11:11:01 +08:00
|
|
|
return V.getValue();
|
2010-02-06 12:04:46 +08:00
|
|
|
|
2013-02-13 11:11:01 +08:00
|
|
|
return svalBuilder.getRegionValueSymbolVal(R);
|
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
|
|
|
}
|
|
|
|
|
2013-02-15 08:32:12 +08:00
|
|
|
const RegionStoreManager::SValListTy &
|
|
|
|
RegionStoreManager::getInterestingValues(nonloc::LazyCompoundVal LCV) {
|
|
|
|
// First, check the cache.
|
|
|
|
LazyBindingsMapTy::iterator I = LazyBindingsMap.find(LCV.getCVData());
|
|
|
|
if (I != LazyBindingsMap.end())
|
|
|
|
return I->second;
|
|
|
|
|
|
|
|
// If we don't have a list of values cached, start constructing it.
|
2013-02-20 08:27:26 +08:00
|
|
|
SValListTy List;
|
2013-02-15 08:32:12 +08:00
|
|
|
|
|
|
|
const SubRegion *LazyR = LCV.getRegion();
|
|
|
|
RegionBindingsRef B = getRegionBindings(LCV.getStore());
|
|
|
|
|
|
|
|
// If this region had /no/ bindings at the time, there are no interesting
|
|
|
|
// values to return.
|
|
|
|
const ClusterBindings *Cluster = B.lookup(LazyR->getBaseRegion());
|
|
|
|
if (!Cluster)
|
2013-02-20 08:27:26 +08:00
|
|
|
return (LazyBindingsMap[LCV.getCVData()] = llvm_move(List));
|
2013-02-15 08:32:12 +08:00
|
|
|
|
|
|
|
SmallVector<BindingKey, 32> Keys;
|
|
|
|
collectSubRegionKeys(Keys, svalBuilder, *Cluster, LazyR,
|
|
|
|
/*IncludeAllDefaultBindings=*/true);
|
|
|
|
for (SmallVectorImpl<BindingKey>::const_iterator I = Keys.begin(),
|
|
|
|
E = Keys.end();
|
|
|
|
I != E; ++I) {
|
|
|
|
SVal V = *Cluster->lookup(*I);
|
|
|
|
if (V.isUnknownOrUndef() || V.isConstant())
|
|
|
|
continue;
|
|
|
|
|
2013-02-21 06:23:23 +08:00
|
|
|
if (Optional<nonloc::LazyCompoundVal> InnerLCV =
|
2013-02-20 13:52:05 +08:00
|
|
|
V.getAs<nonloc::LazyCompoundVal>()) {
|
2013-02-15 08:32:12 +08:00
|
|
|
const SValListTy &InnerList = getInterestingValues(*InnerLCV);
|
|
|
|
List.insert(List.end(), InnerList.begin(), InnerList.end());
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
|
|
|
|
List.push_back(V);
|
|
|
|
}
|
|
|
|
|
2013-02-20 08:27:26 +08:00
|
|
|
return (LazyBindingsMap[LCV.getCVData()] = llvm_move(List));
|
2013-02-15 08:32:12 +08:00
|
|
|
}
|
|
|
|
|
2013-02-02 03:49:57 +08:00
|
|
|
NonLoc RegionStoreManager::createLazyBinding(RegionBindingsConstRef B,
|
|
|
|
const TypedValueRegion *R) {
|
2013-02-21 09:34:51 +08:00
|
|
|
if (Optional<nonloc::LazyCompoundVal> V =
|
|
|
|
getExistingLazyBinding(svalBuilder, B, R, false))
|
|
|
|
return *V;
|
2013-02-02 03:49:57 +08:00
|
|
|
|
|
|
|
return svalBuilder.makeLazyCompoundVal(StoreRef(B.asStore(), *this), R);
|
2012-07-07 05:59:56 +08:00
|
|
|
}
|
|
|
|
|
2012-12-08 03:54:25 +08:00
|
|
|
SVal RegionStoreManager::getBindingForStruct(RegionBindingsConstRef B,
|
2013-02-02 03:49:57 +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();
|
|
|
|
|
2013-02-02 03:49:57 +08:00
|
|
|
return createLazyBinding(B, R);
|
2008-10-31 15:16:08 +08:00
|
|
|
}
|
|
|
|
|
2012-12-08 03:54:25 +08:00
|
|
|
SVal RegionStoreManager::getBindingForArray(RegionBindingsConstRef B,
|
2013-02-02 03:49:57 +08:00
|
|
|
const TypedValueRegion *R) {
|
|
|
|
assert(Ctx.getAsConstantArrayType(R->getValueType()) &&
|
|
|
|
"Only constant array types can have compound bindings.");
|
2012-05-09 05:49:51 +08:00
|
|
|
|
2013-02-02 03:49:57 +08:00
|
|
|
return createLazyBinding(B, 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 {
|
2012-12-07 09:55:21 +08:00
|
|
|
RegionBindingsRef B = getRegionBindings(store);
|
2011-07-29 07:07:46 +08:00
|
|
|
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.
|
2012-12-07 09:55:21 +08:00
|
|
|
for (RegionBindingsRef::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) {
|
|
|
|
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.
|
|
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
|
2012-08-22 14:37:46 +08:00
|
|
|
StoreRef RegionStoreManager::killBinding(Store ST, Loc L) {
|
2013-02-21 06:23:23 +08:00
|
|
|
if (Optional<loc::MemRegionVal> LV = L.getAs<loc::MemRegionVal>())
|
2013-02-20 13:52:05 +08:00
|
|
|
if (const MemRegion* R = LV->getRegion())
|
2012-12-07 09:55:21 +08:00
|
|
|
return StoreRef(getRegionBindings(ST).removeBinding(R)
|
|
|
|
.asImmutableMap()
|
|
|
|
.getRootWithoutRetain(),
|
2011-02-19 09:59:33 +08:00
|
|
|
*this);
|
2009-09-09 23:08:12 +08:00
|
|
|
|
2012-08-22 14:37:46 +08:00
|
|
|
return StoreRef(ST, *this);
|
2009-06-17 06:36:44 +08:00
|
|
|
}
|
|
|
|
|
2012-12-08 03:54:25 +08:00
|
|
|
RegionBindingsRef
|
|
|
|
RegionStoreManager::bind(RegionBindingsConstRef B, Loc L, SVal V) {
|
2013-02-20 13:52:05 +08:00
|
|
|
if (L.getAs<loc::ConcreteInt>())
|
2012-12-08 03:54:25 +08:00
|
|
|
return B;
|
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.
|
2013-02-20 13:52:05 +08:00
|
|
|
const MemRegion *R = L.castAs<loc::MemRegionVal>().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())
|
2012-12-08 03:54:25 +08:00
|
|
|
return bindArray(B, TR, V);
|
2012-05-11 06:02:39 +08:00
|
|
|
if (Ty->isStructureOrClassType())
|
2012-12-08 03:54:25 +08:00
|
|
|
return bindStruct(B, TR, V);
|
2012-05-11 06:02:39 +08:00
|
|
|
if (Ty->isVectorType())
|
2012-12-08 03:54:25 +08:00
|
|
|
return bindVector(B, TR, V);
|
2012-05-11 06:02:39 +08:00
|
|
|
}
|
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.
|
2012-09-26 14:00:14 +08:00
|
|
|
QualType T = SR->getSymbol()->getType();
|
2012-09-06 01:11:22 +08:00
|
|
|
if (T->isAnyPointerType() || T->isReferenceType())
|
|
|
|
T = T->getPointeeType();
|
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
|
|
|
|
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.
|
2012-12-08 03:54:25 +08:00
|
|
|
RegionBindingsRef NewB = removeSubRegionBindings(B, cast<SubRegion>(R));
|
|
|
|
return NewB.addBinding(BindingKey::Make(R, BindingKey::Direct), V);
|
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
|
|
|
}
|
|
|
|
|
2012-12-08 03:54:25 +08:00
|
|
|
RegionBindingsRef
|
|
|
|
RegionStoreManager::setImplicitDefaultValue(RegionBindingsConstRef B,
|
|
|
|
const MemRegion *R,
|
|
|
|
QualType T) {
|
2009-11-20 04:20:24 +08:00
|
|
|
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
|
|
|
|
2012-12-08 03:54:25 +08:00
|
|
|
return B.addBinding(R, BindingKey::Default, V);
|
2009-11-20 04:20:24 +08:00
|
|
|
}
|
2010-03-10 15:20:03 +08:00
|
|
|
|
2012-12-08 03:54:25 +08:00
|
|
|
RegionBindingsRef
|
|
|
|
RegionStoreManager::bindArray(RegionBindingsConstRef B,
|
|
|
|
const TypedValueRegion* R,
|
|
|
|
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.
|
2013-02-21 06:23:23 +08:00
|
|
|
if (Optional<loc::MemRegionVal> MRV = Init.getAs<loc::MemRegionVal>()) {
|
2012-11-28 13:36:28 +08:00
|
|
|
const StringRegion *S = cast<StringRegion>(MRV->getRegion());
|
|
|
|
|
|
|
|
// Treat the string as a lazy compound value.
|
2012-12-08 03:54:25 +08:00
|
|
|
StoreRef store(B.asStore(), *this);
|
2013-02-20 13:52:05 +08:00
|
|
|
nonloc::LazyCompoundVal LCV = svalBuilder.makeLazyCompoundVal(store, S)
|
|
|
|
.castAs<nonloc::LazyCompoundVal>();
|
2012-12-08 03:54:25 +08:00
|
|
|
return bindAggregate(B, 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.
|
2013-02-20 13:52:05 +08:00
|
|
|
if (Init.getAs<nonloc::LazyCompoundVal>())
|
2012-12-08 03:54:25 +08:00
|
|
|
return bindAggregate(B, 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())
|
2012-12-08 03:54:25 +08:00
|
|
|
return setImplicitDefaultValue(B, R, ElementTy);
|
2010-03-10 15:20:03 +08:00
|
|
|
|
2013-02-20 13:52:05 +08:00
|
|
|
const nonloc::CompoundVal& CV = Init.castAs<nonloc::CompoundVal>();
|
2008-10-31 18:24:47 +08:00
|
|
|
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
|
|
|
|
2012-12-08 03:54:25 +08:00
|
|
|
RegionBindingsRef NewB(B);
|
|
|
|
|
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())
|
2012-12-08 03:54:25 +08:00
|
|
|
NewB = bindStruct(NewB, ER, *VI);
|
2010-08-20 09:05:59 +08:00
|
|
|
else if (ElementTy->isArrayType())
|
2012-12-08 03:54:25 +08:00
|
|
|
NewB = bindArray(NewB, ER, *VI);
|
2008-12-20 14:32:12 +08:00
|
|
|
else
|
2012-12-08 03:54:25 +08:00
|
|
|
NewB = bind(NewB, 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())
|
2012-12-08 03:54:25 +08:00
|
|
|
NewB = setImplicitDefaultValue(NewB, R, ElementTy);
|
2009-06-23 13:23:38 +08:00
|
|
|
|
2012-12-08 03:54:25 +08:00
|
|
|
return NewB;
|
2008-11-19 19:06:24 +08:00
|
|
|
}
|
|
|
|
|
2012-12-08 03:54:25 +08:00
|
|
|
RegionBindingsRef RegionStoreManager::bindVector(RegionBindingsConstRef B,
|
|
|
|
const TypedValueRegion* R,
|
|
|
|
SVal V) {
|
2012-05-11 06:02:39 +08:00
|
|
|
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.
|
2013-02-20 13:52:05 +08:00
|
|
|
if (V.getAs<nonloc::LazyCompoundVal>() || V.getAs<nonloc::SymbolVal>())
|
2012-12-08 03:54:25 +08:00
|
|
|
return bindAggregate(B, 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.
|
2013-02-20 13:52:05 +08:00
|
|
|
if (!V.getAs<nonloc::CompoundVal>()) {
|
2012-12-08 03:54:25 +08:00
|
|
|
return bindAggregate(B, R, UnknownVal());
|
2012-05-11 06:02:39 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
QualType ElemType = VT->getElementType();
|
2013-02-20 13:52:05 +08:00
|
|
|
nonloc::CompoundVal CV = V.castAs<nonloc::CompoundVal>();
|
2012-05-11 06:02:39 +08:00
|
|
|
nonloc::CompoundVal::iterator VI = CV.begin(), VE = CV.end();
|
|
|
|
unsigned index = 0, numElements = VT->getNumElements();
|
2012-12-08 03:54:25 +08:00
|
|
|
RegionBindingsRef NewB(B);
|
|
|
|
|
2012-05-11 06:02:39 +08:00
|
|
|
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())
|
2012-12-08 03:54:25 +08:00
|
|
|
NewB = bindArray(NewB, ER, *VI);
|
2012-05-11 06:02:39 +08:00
|
|
|
else if (ElemType->isStructureOrClassType())
|
2012-12-08 03:54:25 +08:00
|
|
|
NewB = bindStruct(NewB, ER, *VI);
|
2012-05-11 06:02:39 +08:00
|
|
|
else
|
2012-12-08 03:54:25 +08:00
|
|
|
NewB = bind(NewB, svalBuilder.makeLoc(ER), *VI);
|
2012-05-11 06:02:39 +08:00
|
|
|
}
|
2012-12-08 03:54:25 +08:00
|
|
|
return NewB;
|
2012-05-11 06:02:39 +08:00
|
|
|
}
|
|
|
|
|
2012-12-08 03:54:25 +08:00
|
|
|
RegionBindingsRef RegionStoreManager::bindStruct(RegionBindingsConstRef B,
|
|
|
|
const TypedValueRegion* R,
|
|
|
|
SVal V) {
|
2009-06-18 06:02:04 +08:00
|
|
|
if (!Features.supportsFields())
|
2012-12-08 03:54:25 +08:00
|
|
|
return B;
|
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())
|
2012-12-08 03:54:25 +08:00
|
|
|
return B;
|
2008-10-31 18:53:01 +08:00
|
|
|
|
2012-08-10 06:55:54 +08:00
|
|
|
// Handle lazy compound values and symbolic values.
|
2013-02-20 13:52:05 +08:00
|
|
|
if (V.getAs<nonloc::LazyCompoundVal>() || V.getAs<nonloc::SymbolVal>())
|
2012-12-08 03:54:25 +08:00
|
|
|
return bindAggregate(B, 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.
|
2013-02-20 13:52:05 +08:00
|
|
|
if (V.isUnknown() || !V.getAs<nonloc::CompoundVal>())
|
2012-12-08 03:54:25 +08:00
|
|
|
return bindAggregate(B, R, UnknownVal());
|
2009-06-11 17:11:27 +08:00
|
|
|
|
2013-02-20 13:52:05 +08:00
|
|
|
const nonloc::CompoundVal& CV = V.castAs<nonloc::CompoundVal>();
|
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;
|
2012-12-08 03:54:25 +08:00
|
|
|
RegionBindingsRef NewB(B);
|
|
|
|
|
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())
|
2012-12-08 03:54:25 +08:00
|
|
|
NewB = bindArray(NewB, FR, *VI);
|
2010-04-27 05:31:17 +08:00
|
|
|
else if (FTy->isStructureOrClassType())
|
2012-12-08 03:54:25 +08:00
|
|
|
NewB = bindStruct(NewB, FR, *VI);
|
2009-09-23 05:19:14 +08:00
|
|
|
else
|
2012-12-08 03:54:25 +08:00
|
|
|
NewB = bind(NewB, 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) {
|
2012-12-08 03:54:25 +08:00
|
|
|
NewB = NewB.addBinding(R, BindingKey::Default,
|
|
|
|
svalBuilder.makeIntVal(0, false));
|
2009-10-11 16:08:02 +08:00
|
|
|
}
|
2009-06-23 13:43:16 +08:00
|
|
|
|
2012-12-08 03:54:25 +08:00
|
|
|
return NewB;
|
2008-11-19 19:06:24 +08:00
|
|
|
}
|
|
|
|
|
2012-12-08 03:54:25 +08:00
|
|
|
RegionBindingsRef
|
|
|
|
RegionStoreManager::bindAggregate(RegionBindingsConstRef B,
|
|
|
|
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.
|
2012-12-08 03:54:25 +08:00
|
|
|
return removeSubRegionBindings(B, R).addBinding(R, BindingKey::Default, Val);
|
2012-08-10 06:55:51 +08:00
|
|
|
}
|
|
|
|
|
2009-06-17 06:36:44 +08:00
|
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
// State pruning.
|
|
|
|
//===----------------------------------------------------------------------===//
|
2010-03-10 15:20:03 +08:00
|
|
|
|
2010-03-11 00:32:56 +08:00
|
|
|
namespace {
|
2011-01-15 04:34:15 +08:00
|
|
|
class removeDeadBindingsWorker :
|
|
|
|
public ClusterAnalysis<removeDeadBindingsWorker> {
|
2011-07-23 18:55:15 +08:00
|
|
|
SmallVector<const SymbolicRegion*, 12> Postponed;
|
2010-03-11 00:32:56 +08:00
|
|
|
SymbolReaper &SymReaper;
|
2010-03-17 11:35:08 +08:00
|
|
|
const StackFrameContext *CurrentLCtx;
|
2010-07-02 04:16:50 +08:00
|
|
|
|
2010-03-11 00:32:56 +08:00
|
|
|
public:
|
2012-01-12 10:22:40 +08:00
|
|
|
removeDeadBindingsWorker(RegionStoreManager &rm,
|
|
|
|
ProgramStateManager &stateMgr,
|
2012-12-07 09:55:21 +08:00
|
|
|
RegionBindingsRef 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
|
|
|
|
|
|
|
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();
|
2012-11-03 10:54:20 +08:00
|
|
|
if (CurrentLCtx &&
|
|
|
|
(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) {
|
2012-09-08 09:24:49 +08:00
|
|
|
// Mark the symbol for any SymbolicRegion with live bindings as live itself.
|
|
|
|
// This means we should continue to track that symbol.
|
|
|
|
if (const SymbolicRegion *SymR = dyn_cast<SymbolicRegion>(baseR))
|
|
|
|
SymReaper.markLive(SymR->getSymbol());
|
|
|
|
|
|
|
|
for (ClusterBindings::iterator I = C.begin(), E = C.end(); I != E; ++I)
|
2012-08-10 06:55:51 +08:00
|
|
|
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.
|
2013-02-21 06:23:23 +08:00
|
|
|
if (Optional<nonloc::LazyCompoundVal> LCS =
|
2013-02-20 13:52:05 +08:00
|
|
|
V.getAs<nonloc::LazyCompoundVal>()) {
|
2009-09-29 14:35:00 +08:00
|
|
|
|
2013-02-15 08:32:12 +08:00
|
|
|
const RegionStoreManager::SValListTy &Vals = RM.getInterestingValues(*LCS);
|
2013-02-15 08:32:06 +08:00
|
|
|
|
2013-02-15 08:32:12 +08:00
|
|
|
for (RegionStoreManager::SValListTy::const_iterator I = Vals.begin(),
|
|
|
|
E = Vals.end();
|
|
|
|
I != E; ++I)
|
|
|
|
VisitBinding(*I);
|
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();
|
2012-09-08 09:24:49 +08:00
|
|
|
for ( ; I != E; ++I)
|
|
|
|
AddToWorkList(I.getCapturedRegion());
|
2012-06-02 04:04:04 +08:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
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
|
|
|
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) {
|
2012-09-08 09:24:49 +08:00
|
|
|
if (const SymbolicRegion *SR = *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) {
|
2012-12-07 09:55:21 +08:00
|
|
|
RegionBindingsRef 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.
|
2012-12-07 09:55:21 +08:00
|
|
|
for (RegionBindingsRef::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-12-07 09:55:21 +08:00
|
|
|
B = B.remove(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
|
|
|
|
2012-12-08 02:32:08 +08:00
|
|
|
return StoreRef(B.asStore(), *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) {
|
2012-12-07 09:55:21 +08:00
|
|
|
RegionBindingsRef B = getRegionBindings(store);
|
2012-05-09 05:49:47 +08:00
|
|
|
OS << "Store (direct and default bindings), "
|
2012-12-08 02:32:08 +08:00
|
|
|
<< B.asStore()
|
2012-05-09 05:49:47 +08:00
|
|
|
<< " :" << nl;
|
2012-12-14 09:23:13 +08:00
|
|
|
B.dump(OS, nl);
|
2009-06-17 06:36:44 +08:00
|
|
|
}
|