2008-10-08 10:50:44 +08:00
|
|
|
//== RegionStore.cpp - Field-sensitive store model --------------*- C++ -*--==//
|
|
|
|
//
|
|
|
|
// The LLVM Compiler Infrastructure
|
|
|
|
//
|
|
|
|
// This file is distributed under the University of Illinois Open Source
|
|
|
|
// License. See LICENSE.TXT for details.
|
|
|
|
//
|
|
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
//
|
|
|
|
// This file defines a basic region store model. In this model, we do have field
|
|
|
|
// sensitivity. But we assume nothing about the heap shape. So recursive data
|
|
|
|
// structures are largely ignored. Basically we do 1-limiting analysis.
|
|
|
|
// Parameter pointers are assumed with no aliasing. Pointee objects of
|
|
|
|
// parameters are created lazily.
|
|
|
|
//
|
|
|
|
//===----------------------------------------------------------------------===//
|
2010-01-25 12:41:41 +08:00
|
|
|
#include "clang/Checker/PathSensitive/MemRegion.h"
|
|
|
|
#include "clang/Analysis/AnalysisContext.h"
|
|
|
|
#include "clang/Checker/PathSensitive/GRState.h"
|
|
|
|
#include "clang/Checker/PathSensitive/GRStateTrait.h"
|
2008-10-08 10:50:44 +08:00
|
|
|
#include "clang/Analysis/Analyses/LiveVariables.h"
|
2009-08-07 05:43:54 +08:00
|
|
|
#include "clang/Analysis/Support/Optional.h"
|
2009-05-06 19:51:48 +08:00
|
|
|
#include "clang/Basic/TargetInfo.h"
|
2010-01-18 16:54:31 +08:00
|
|
|
#include "clang/AST/CharUnits.h"
|
2008-10-08 10:50:44 +08:00
|
|
|
|
|
|
|
#include "llvm/ADT/ImmutableMap.h"
|
2008-11-16 12:07:26 +08:00
|
|
|
#include "llvm/ADT/ImmutableList.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;
|
|
|
|
|
2009-08-06 09:20:57 +08:00
|
|
|
#define USE_EXPLICIT_COMPOUND 0
|
2009-07-22 12:35:42 +08:00
|
|
|
|
2010-01-11 08:07:44 +08:00
|
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
// Representation of value bindings.
|
|
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
|
2009-10-11 16:08:02 +08:00
|
|
|
namespace {
|
|
|
|
class BindingVal {
|
|
|
|
public:
|
|
|
|
enum BindingKind { Direct, Default };
|
|
|
|
private:
|
|
|
|
SVal Value;
|
|
|
|
BindingKind Kind;
|
|
|
|
|
|
|
|
public:
|
|
|
|
BindingVal(SVal V, BindingKind K) : Value(V), Kind(K) {}
|
|
|
|
|
|
|
|
bool isDefault() const { return Kind == Default; }
|
|
|
|
|
|
|
|
const SVal *getValue() const { return &Value; }
|
|
|
|
|
|
|
|
const SVal *getDirectValue() const { return isDefault() ? 0 : &Value; }
|
|
|
|
|
|
|
|
const SVal *getDefaultValue() const { return isDefault() ? &Value : 0; }
|
|
|
|
|
|
|
|
void Profile(llvm::FoldingSetNodeID& ID) const {
|
|
|
|
Value.Profile(ID);
|
|
|
|
ID.AddInteger(Kind);
|
|
|
|
}
|
|
|
|
|
|
|
|
inline bool operator==(const BindingVal& R) const {
|
|
|
|
return Value == R.Value && Kind == R.Kind;
|
|
|
|
}
|
|
|
|
|
|
|
|
inline bool operator!=(const BindingVal& R) const {
|
|
|
|
return !(*this == R);
|
|
|
|
}
|
|
|
|
};
|
|
|
|
}
|
|
|
|
|
|
|
|
namespace llvm {
|
|
|
|
static inline
|
|
|
|
llvm::raw_ostream& operator<<(llvm::raw_ostream& os, BindingVal V) {
|
|
|
|
if (V.isDefault())
|
|
|
|
os << "(default) ";
|
|
|
|
else
|
|
|
|
os << "(direct) ";
|
|
|
|
os << *V.getValue();
|
|
|
|
return os;
|
|
|
|
}
|
|
|
|
} // end llvm namespace
|
|
|
|
|
2010-01-11 08:07:44 +08:00
|
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
// Representation of binding keys.
|
|
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
|
|
|
|
namespace {
|
|
|
|
class BindingKey : public std::pair<const MemRegion*, uint64_t> {
|
|
|
|
public:
|
2010-01-11 10:33:26 +08:00
|
|
|
explicit BindingKey(const MemRegion *r, uint64_t offset)
|
|
|
|
: std::pair<const MemRegion*,uint64_t>(r, offset) { assert(r); }
|
2010-01-11 08:07:44 +08:00
|
|
|
|
|
|
|
const MemRegion *getRegion() const { return first; }
|
|
|
|
uint64_t getOffset() const { return second; }
|
|
|
|
|
|
|
|
void Profile(llvm::FoldingSetNodeID& ID) const {
|
|
|
|
ID.AddPointer(getRegion());
|
|
|
|
ID.AddInteger(getOffset());
|
|
|
|
}
|
2010-01-11 10:33:26 +08:00
|
|
|
|
|
|
|
static BindingKey Make(const MemRegion *R);
|
2010-01-11 08:07:44 +08:00
|
|
|
};
|
|
|
|
} // end anonymous namespace
|
|
|
|
|
|
|
|
namespace llvm {
|
|
|
|
static inline
|
|
|
|
llvm::raw_ostream& operator<<(llvm::raw_ostream& os, BindingKey K) {
|
|
|
|
os << '(' << K.getRegion() << ',' << K.getOffset() << ')';
|
|
|
|
return os;
|
|
|
|
}
|
|
|
|
} // end llvm namespace
|
|
|
|
|
|
|
|
//===----------------------------------------------------------------------===//
|
2008-11-24 17:44:56 +08:00
|
|
|
// Actual Store type.
|
2010-01-11 08:07:44 +08:00
|
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
|
|
|
|
typedef llvm::ImmutableMap<BindingKey, BindingVal> RegionBindings;
|
2008-11-24 17:44:56 +08:00
|
|
|
|
2009-06-17 06:36:44 +08:00
|
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
// Fine-grained control of RegionStoreManager.
|
|
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
|
|
|
|
namespace {
|
2009-11-28 14:07:30 +08:00
|
|
|
struct minimal_features_tag {};
|
|
|
|
struct maximal_features_tag {};
|
2009-09-09 23:08:12 +08:00
|
|
|
|
2009-11-28 14:07:30 +08:00
|
|
|
class RegionStoreFeatures {
|
2009-06-17 06:36:44 +08:00
|
|
|
bool SupportsFields;
|
|
|
|
bool SupportsRemaining;
|
2009-09-09 23:08:12 +08:00
|
|
|
|
2009-06-17 06:36:44 +08:00
|
|
|
public:
|
|
|
|
RegionStoreFeatures(minimal_features_tag) :
|
|
|
|
SupportsFields(false), SupportsRemaining(false) {}
|
2009-09-09 23:08:12 +08:00
|
|
|
|
2009-06-17 06:36:44 +08:00
|
|
|
RegionStoreFeatures(maximal_features_tag) :
|
|
|
|
SupportsFields(true), SupportsRemaining(false) {}
|
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; }
|
|
|
|
bool supportsRemaining() const { return SupportsRemaining; }
|
|
|
|
};
|
|
|
|
}
|
|
|
|
|
2008-12-24 09:05:03 +08:00
|
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
// Region "Extents"
|
|
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
//
|
|
|
|
// MemRegions represent chunks of memory with a size (their "extent"). This
|
|
|
|
// GDM entry tracks the extents for regions. Extents are in bytes.
|
2009-01-08 06:18:50 +08:00
|
|
|
//
|
2009-11-28 14:07:30 +08:00
|
|
|
namespace { class RegionExtents {}; }
|
2008-12-24 09:05:03 +08:00
|
|
|
static int RegionExtentsIndex = 0;
|
2008-11-24 17:44:56 +08:00
|
|
|
namespace clang {
|
2008-12-24 09:05:03 +08:00
|
|
|
template<> struct GRStateTrait<RegionExtents>
|
|
|
|
: public GRStatePartialTrait<llvm::ImmutableMap<const MemRegion*, SVal> > {
|
|
|
|
static void* GDMIndex() { return &RegionExtentsIndex; }
|
|
|
|
};
|
2008-11-24 17:44:56 +08:00
|
|
|
}
|
|
|
|
|
2009-08-01 14:17:29 +08:00
|
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
// Utility functions.
|
|
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
|
|
|
|
static bool IsAnyPointerOrIntptr(QualType ty, ASTContext &Ctx) {
|
|
|
|
if (ty->isAnyPointerType())
|
|
|
|
return true;
|
2009-09-09 23:08:12 +08:00
|
|
|
|
2009-08-01 14:17:29 +08:00
|
|
|
return ty->isIntegerType() && ty->isScalarType() &&
|
|
|
|
Ctx.getTypeSize(ty) == Ctx.getTypeSize(Ctx.VoidPtrTy);
|
|
|
|
}
|
|
|
|
|
2008-12-24 09:05:03 +08:00
|
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
// Main RegionStore logic.
|
|
|
|
//===----------------------------------------------------------------------===//
|
2008-12-04 10:08:27 +08:00
|
|
|
|
2008-10-08 10:50:44 +08:00
|
|
|
namespace {
|
2009-09-09 23:08:12 +08:00
|
|
|
|
2009-11-28 14:07:30 +08:00
|
|
|
class RegionStoreSubRegionMap : public SubRegionMap {
|
2010-02-03 06:38:47 +08:00
|
|
|
public:
|
|
|
|
typedef llvm::ImmutableSet<const MemRegion*> Set;
|
|
|
|
typedef llvm::DenseMap<const MemRegion*, Set> Map;
|
|
|
|
private:
|
|
|
|
Set::Factory F;
|
2009-03-03 09:35:36 +08:00
|
|
|
Map M;
|
|
|
|
public:
|
2009-08-06 03:09:24 +08:00
|
|
|
bool add(const MemRegion* Parent, const MemRegion* SubRegion) {
|
2009-03-03 09:35:36 +08:00
|
|
|
Map::iterator I = M.find(Parent);
|
2009-08-06 03:09:24 +08:00
|
|
|
|
|
|
|
if (I == M.end()) {
|
2009-08-05 13:31:02 +08:00
|
|
|
M.insert(std::make_pair(Parent, F.Add(F.GetEmptySet(), SubRegion)));
|
2009-08-06 03:09:24 +08:00
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
|
|
|
I->second = F.Add(I->second, SubRegion);
|
|
|
|
return false;
|
2009-03-03 09:35:36 +08:00
|
|
|
}
|
2009-09-09 23:08:12 +08:00
|
|
|
|
2009-08-06 09:20:57 +08:00
|
|
|
void process(llvm::SmallVectorImpl<const SubRegion*> &WL, const SubRegion *R);
|
2009-09-09 23:08:12 +08:00
|
|
|
|
2009-03-03 09:35:36 +08:00
|
|
|
~RegionStoreSubRegionMap() {}
|
2010-02-03 06:38:47 +08:00
|
|
|
|
|
|
|
const Set *getSubRegions(const MemRegion *Parent) const {
|
|
|
|
Map::const_iterator I = M.find(Parent);
|
|
|
|
return I == M.end() ? NULL : &I->second;
|
|
|
|
}
|
2009-09-09 23:08:12 +08:00
|
|
|
|
2009-03-03 10:51:43 +08:00
|
|
|
bool iterSubRegions(const MemRegion* Parent, Visitor& V) const {
|
2009-11-10 09:17:45 +08:00
|
|
|
Map::const_iterator I = M.find(Parent);
|
2009-03-03 09:35:36 +08:00
|
|
|
|
|
|
|
if (I == M.end())
|
2009-03-03 10:51:43 +08:00
|
|
|
return true;
|
2009-09-09 23:08:12 +08:00
|
|
|
|
2010-02-03 06:38:47 +08:00
|
|
|
Set S = I->second;
|
|
|
|
for (Set::iterator SI=S.begin(),SE=S.end(); SI != SE; ++SI) {
|
2009-03-03 09:35:36 +08:00
|
|
|
if (!V.Visit(Parent, *SI))
|
2009-03-03 10:51:43 +08:00
|
|
|
return false;
|
2009-03-03 09:35:36 +08:00
|
|
|
}
|
2009-09-09 23:08:12 +08:00
|
|
|
|
2009-03-03 10:51:43 +08:00
|
|
|
return true;
|
2009-03-03 09:35:36 +08:00
|
|
|
}
|
2009-09-09 23:08:12 +08:00
|
|
|
};
|
2009-03-03 09:35:36 +08:00
|
|
|
|
2009-11-28 14:07:30 +08:00
|
|
|
class RegionStoreManager : public StoreManager {
|
2009-06-17 06:36:44 +08:00
|
|
|
const RegionStoreFeatures Features;
|
2009-08-06 12:50:20 +08:00
|
|
|
RegionBindings::Factory RBFactory;
|
2009-09-29 14:35:00 +08:00
|
|
|
|
|
|
|
typedef llvm::DenseMap<const GRState *, RegionStoreSubRegionMap*> SMCache;
|
|
|
|
SMCache SC;
|
|
|
|
|
2008-10-08 10:50:44 +08:00
|
|
|
public:
|
2009-09-09 23:08:12 +08:00
|
|
|
RegionStoreManager(GRStateManager& mgr, const RegionStoreFeatures &f)
|
2009-07-30 05:43:22 +08:00
|
|
|
: StoreManager(mgr),
|
2009-06-17 06:36:44 +08:00
|
|
|
Features(f),
|
2010-02-03 06:38:47 +08:00
|
|
|
RBFactory(mgr.getAllocator(), 3) {}
|
2008-10-08 10:50:44 +08:00
|
|
|
|
2009-09-29 14:35:00 +08:00
|
|
|
virtual ~RegionStoreManager() {
|
|
|
|
for (SMCache::iterator I = SC.begin(), E = SC.end(); I != E; ++I)
|
|
|
|
delete (*I).second;
|
|
|
|
}
|
2008-10-08 10:50:44 +08:00
|
|
|
|
2009-08-01 14:17:29 +08:00
|
|
|
SubRegionMap *getSubRegionMap(const GRState *state);
|
2009-09-09 23:08:12 +08:00
|
|
|
|
2009-10-11 16:08:02 +08:00
|
|
|
RegionStoreSubRegionMap *getRegionStoreSubRegionMap(Store store);
|
2009-09-09 23:08:12 +08:00
|
|
|
|
2009-10-11 16:08:02 +08:00
|
|
|
Optional<SVal> getBinding(RegionBindings B, const MemRegion *R);
|
|
|
|
Optional<SVal> getDirectBinding(RegionBindings B, const MemRegion *R);
|
2009-08-07 05:43:54 +08:00
|
|
|
/// getDefaultBinding - Returns an SVal* representing an optional default
|
|
|
|
/// binding associated with a region and its subregions.
|
2009-10-11 16:08:02 +08:00
|
|
|
Optional<SVal> getDefaultBinding(RegionBindings B, const MemRegion *R);
|
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
|
|
|
|
/// the value is not specified.
|
|
|
|
const GRState *setImplicitDefaultValue(const GRState *state,
|
|
|
|
const MemRegion *R,
|
|
|
|
QualType T);
|
2009-09-09 23:08:12 +08:00
|
|
|
|
2008-12-24 15:46:32 +08:00
|
|
|
/// getLValueString - Returns an SVal representing the lvalue of a
|
|
|
|
/// StringLiteral. Within RegionStore a StringLiteral has an
|
|
|
|
/// associated StringRegion, and the lvalue of a StringLiteral is
|
|
|
|
/// the lvalue of that region.
|
2009-10-14 11:33:08 +08:00
|
|
|
SVal getLValueString(const StringLiteral* S);
|
2008-10-25 22:18:57 +08:00
|
|
|
|
2008-12-24 15:46:32 +08:00
|
|
|
/// getLValueCompoundLiteral - Returns an SVal representing the
|
|
|
|
/// lvalue of a compound literal. Within RegionStore a compound
|
|
|
|
/// literal has an associated region, and the lvalue of the
|
|
|
|
/// compound literal is the lvalue of that region.
|
2009-10-14 11:33:08 +08:00
|
|
|
SVal getLValueCompoundLiteral(const CompoundLiteralExpr*);
|
2008-11-07 18:38:33 +08:00
|
|
|
|
2008-12-24 15:46:32 +08:00
|
|
|
/// getLValueVar - Returns an SVal that represents the lvalue of a
|
|
|
|
/// variable. Within RegionStore a variable has an associated
|
|
|
|
/// VarRegion, and the lvalue of the variable is the lvalue of that region.
|
2009-10-14 11:33:08 +08:00
|
|
|
SVal getLValueVar(const VarDecl *VD, const LocationContext *LC);
|
2009-09-09 23:08:12 +08:00
|
|
|
|
2009-10-14 11:33:08 +08:00
|
|
|
SVal getLValueIvar(const ObjCIvarDecl* D, SVal Base);
|
2008-10-22 21:44:38 +08:00
|
|
|
|
2009-10-14 11:33:08 +08:00
|
|
|
SVal getLValueField(const FieldDecl* D, SVal Base);
|
2009-09-09 23:08:12 +08:00
|
|
|
|
2009-10-14 11:33:08 +08:00
|
|
|
SVal getLValueFieldOrIvar(const Decl* D, SVal Base);
|
2008-10-22 21:44:38 +08:00
|
|
|
|
2009-10-14 11:33:08 +08:00
|
|
|
SVal getLValueElement(QualType elementType, SVal Offset, SVal Base);
|
2008-10-24 09:09:32 +08:00
|
|
|
|
2008-11-22 21:21:46 +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
|
|
|
|
/// the array). This is called by GRExprEngine when evaluating
|
|
|
|
/// 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
|
|
|
|
2009-06-25 07:06:47 +08:00
|
|
|
SVal EvalBinOp(const GRState *state, BinaryOperator::Opcode Op,Loc L,
|
2009-06-26 08:41:43 +08:00
|
|
|
NonLoc R, QualType resultTy);
|
2008-10-24 09:38:55 +08:00
|
|
|
|
2009-09-09 23:08:12 +08:00
|
|
|
Store getInitialStore(const LocationContext *InitLoc) {
|
2009-08-22 07:25:54 +08:00
|
|
|
return RBFactory.GetEmptyMap().getRoot();
|
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.
|
|
|
|
//===-------------------------------------------------------------------===//
|
2008-12-20 14:32:12 +08:00
|
|
|
|
2009-07-30 02:16:25 +08:00
|
|
|
const GRState *InvalidateRegion(const GRState *state, const MemRegion *R,
|
2009-10-16 08:30:49 +08:00
|
|
|
const Expr *E, unsigned Count,
|
2009-12-03 11:27:11 +08:00
|
|
|
InvalidatedSymbols *IS) {
|
|
|
|
return RegionStoreManager::InvalidateRegions(state, &R, &R+1, E, Count, IS);
|
|
|
|
}
|
|
|
|
|
|
|
|
const GRState *InvalidateRegions(const GRState *state,
|
|
|
|
const MemRegion * const *Begin,
|
|
|
|
const MemRegion * const *End,
|
|
|
|
const Expr *E, unsigned Count,
|
|
|
|
InvalidatedSymbols *IS);
|
2009-09-09 23:08:12 +08:00
|
|
|
|
2009-08-01 14:17:29 +08:00
|
|
|
private:
|
2009-10-11 16:08:02 +08:00
|
|
|
void RemoveSubRegionBindings(RegionBindings &B, const MemRegion *R,
|
2009-08-06 09:20:57 +08:00
|
|
|
RegionStoreSubRegionMap &M);
|
2009-09-09 23:08:12 +08:00
|
|
|
|
2010-01-11 08:07:44 +08:00
|
|
|
RegionBindings Add(RegionBindings B, BindingKey K, BindingVal V);
|
|
|
|
RegionBindings Add(RegionBindings B, const MemRegion *R, BindingVal V);
|
|
|
|
|
|
|
|
const BindingVal *Lookup(RegionBindings B, BindingKey K);
|
|
|
|
const BindingVal *Lookup(RegionBindings B, const MemRegion *R);
|
|
|
|
|
|
|
|
RegionBindings Remove(RegionBindings B, BindingKey K);
|
|
|
|
RegionBindings Remove(RegionBindings B, const MemRegion *R);
|
|
|
|
Store Remove(Store store, BindingKey K);
|
|
|
|
|
2009-09-09 23:08:12 +08:00
|
|
|
public:
|
2009-06-18 06:02:04 +08:00
|
|
|
const GRState *Bind(const GRState *state, Loc LV, SVal V);
|
2008-10-21 13:29:26 +08:00
|
|
|
|
2009-06-18 06:02:04 +08:00
|
|
|
const GRState *BindCompoundLiteral(const GRState *state,
|
2009-12-08 06:05:27 +08:00
|
|
|
const CompoundLiteralExpr* CL,
|
|
|
|
const LocationContext *LC,
|
|
|
|
SVal V);
|
2009-09-09 23:08:12 +08:00
|
|
|
|
2009-11-04 08:09:15 +08:00
|
|
|
const GRState *BindDecl(const GRState *ST, const VarRegion *VR,
|
|
|
|
SVal InitVal);
|
2008-11-24 17:44:56 +08:00
|
|
|
|
2009-11-04 08:09:15 +08:00
|
|
|
const GRState *BindDeclWithNoInit(const GRState *state,
|
|
|
|
const VarRegion *) {
|
2009-06-18 06:02:04 +08:00
|
|
|
return state;
|
2008-10-08 10:50:44 +08:00
|
|
|
}
|
2008-10-24 09:38:55 +08:00
|
|
|
|
2009-06-18 06:02:04 +08:00
|
|
|
/// BindStruct - Bind a compound value to a structure.
|
|
|
|
const GRState *BindStruct(const GRState *, const TypedRegion* R, SVal V);
|
2009-09-09 23:08:12 +08:00
|
|
|
|
2009-06-18 06:02:04 +08:00
|
|
|
const GRState *BindArray(const GRState *state, const TypedRegion* R, SVal V);
|
2009-09-09 23:08:12 +08:00
|
|
|
|
|
|
|
/// KillStruct - Set the entire struct to unknown.
|
2009-10-11 16:08:02 +08:00
|
|
|
Store KillStruct(Store store, const TypedRegion* R);
|
2008-10-24 09:38:55 +08:00
|
|
|
|
2009-06-18 06:02:04 +08:00
|
|
|
Store Remove(Store store, Loc LV);
|
2010-01-11 08:07:44 +08:00
|
|
|
|
2009-06-18 06:02:04 +08:00
|
|
|
|
|
|
|
//===------------------------------------------------------------------===//
|
|
|
|
// Loading values from regions.
|
|
|
|
//===------------------------------------------------------------------===//
|
2009-09-09 23:08:12 +08:00
|
|
|
|
2009-06-18 06:02:04 +08:00
|
|
|
/// The high level logic for this method is this:
|
|
|
|
/// Retrieve (L)
|
|
|
|
/// if L has binding
|
|
|
|
/// return L's binding
|
|
|
|
/// else if L is in killset
|
|
|
|
/// return unknown
|
|
|
|
/// else
|
|
|
|
/// if L is on stack or heap
|
|
|
|
/// return undefined
|
|
|
|
/// else
|
|
|
|
/// return symbolic
|
2009-07-22 05:03:30 +08:00
|
|
|
SValuator::CastResult Retrieve(const GRState *state, Loc L,
|
|
|
|
QualType T = QualType());
|
2009-06-25 12:50:44 +08:00
|
|
|
|
2009-07-15 14:09:28 +08:00
|
|
|
SVal RetrieveElement(const GRState *state, const ElementRegion *R);
|
2009-06-25 13:29:39 +08:00
|
|
|
|
2009-07-15 14:09:28 +08:00
|
|
|
SVal RetrieveField(const GRState *state, const FieldRegion *R);
|
2009-09-09 23:08:12 +08:00
|
|
|
|
2009-07-15 14:09:28 +08:00
|
|
|
SVal RetrieveObjCIvar(const GRState *state, const ObjCIvarRegion *R);
|
2009-09-09 23:08:12 +08:00
|
|
|
|
2009-07-21 08:12:07 +08:00
|
|
|
SVal RetrieveVar(const GRState *state, const VarRegion *R);
|
2009-09-09 23:08:12 +08:00
|
|
|
|
2009-07-21 06:58:02 +08:00
|
|
|
SVal RetrieveLazySymbol(const GRState *state, const TypedRegion *R);
|
2009-09-09 23:08:12 +08:00
|
|
|
|
2009-08-07 06:33:36 +08:00
|
|
|
SVal RetrieveFieldOrElementCommon(const GRState *state, const TypedRegion *R,
|
|
|
|
QualType Ty, const MemRegion *superR);
|
2009-09-09 23:08:12 +08:00
|
|
|
|
2008-12-04 09:12:41 +08:00
|
|
|
/// Retrieve the values in a struct and return a CompoundVal, used when doing
|
2009-09-09 23:08:12 +08:00
|
|
|
/// struct copy:
|
|
|
|
/// struct s x, y;
|
2008-12-04 09:12:41 +08:00
|
|
|
/// x = y;
|
|
|
|
/// y's value is retrieved by this method.
|
2009-06-18 06:02:04 +08:00
|
|
|
SVal RetrieveStruct(const GRState *St, const TypedRegion* R);
|
2009-09-09 23:08:12 +08:00
|
|
|
|
2009-06-18 06:02:04 +08:00
|
|
|
SVal RetrieveArray(const GRState *St, const TypedRegion* R);
|
2009-09-09 23:08:12 +08:00
|
|
|
|
2009-12-21 14:52:24 +08:00
|
|
|
/// Get the state and region whose binding this region R corresponds to.
|
2009-08-06 09:20:57 +08:00
|
|
|
std::pair<const GRState*, const MemRegion*>
|
2009-08-06 12:50:20 +08:00
|
|
|
GetLazyBinding(RegionBindings B, const MemRegion *R);
|
2009-09-09 23:08:12 +08:00
|
|
|
|
2009-08-06 09:20:57 +08:00
|
|
|
const GRState* CopyLazyBindings(nonloc::LazyCompoundVal V,
|
|
|
|
const GRState *state,
|
|
|
|
const TypedRegion *R);
|
2008-12-04 09:12:41 +08:00
|
|
|
|
2009-09-24 12:11:44 +08:00
|
|
|
const ElementRegion *GetElementZeroRegion(const SymbolicRegion *SR,
|
|
|
|
QualType T);
|
|
|
|
|
2009-06-18 06:02:04 +08:00
|
|
|
//===------------------------------------------------------------------===//
|
|
|
|
// State pruning.
|
|
|
|
//===------------------------------------------------------------------===//
|
2009-09-09 23:08:12 +08:00
|
|
|
|
2009-06-18 06:02:04 +08:00
|
|
|
/// RemoveDeadBindings - Scans the RegionStore of 'state' for dead values.
|
|
|
|
/// It returns a new Store with these values removed.
|
2009-08-02 12:45:08 +08:00
|
|
|
void RemoveDeadBindings(GRState &state, Stmt* Loc, SymbolReaper& SymReaper,
|
2009-06-18 06:02:04 +08:00
|
|
|
llvm::SmallVectorImpl<const MemRegion*>& RegionRoots);
|
2009-05-03 08:27:40 +08:00
|
|
|
|
2009-10-13 10:24:55 +08:00
|
|
|
const GRState *EnterStackFrame(const GRState *state,
|
|
|
|
const StackFrameContext *frame);
|
|
|
|
|
2009-06-18 06:02:04 +08:00
|
|
|
//===------------------------------------------------------------------===//
|
|
|
|
// Region "extents".
|
|
|
|
//===------------------------------------------------------------------===//
|
2009-09-09 23:08:12 +08:00
|
|
|
|
2010-01-18 16:54:31 +08:00
|
|
|
const GRState *setExtent(const GRState *state,const MemRegion* R,SVal Extent);
|
2009-11-12 10:48:32 +08:00
|
|
|
DefinedOrUnknownSVal getSizeInElements(const GRState *state,
|
2010-01-18 16:54:31 +08:00
|
|
|
const MemRegion* R, QualType EleTy);
|
2008-11-23 12:30:35 +08:00
|
|
|
|
2009-06-18 06:02:04 +08:00
|
|
|
//===------------------------------------------------------------------===//
|
2008-10-31 15:16:08 +08:00
|
|
|
// Utility methods.
|
2009-06-18 06:02:04 +08:00
|
|
|
//===------------------------------------------------------------------===//
|
2009-09-09 23:08:12 +08:00
|
|
|
|
2009-08-06 12:50:20 +08:00
|
|
|
static inline RegionBindings GetRegionBindings(Store store) {
|
2009-10-11 16:08:02 +08:00
|
|
|
return RegionBindings(static_cast<const RegionBindings::TreeTy*>(store));
|
2009-06-18 06:02:04 +08:00
|
|
|
}
|
|
|
|
|
2009-06-25 07:06:47 +08:00
|
|
|
void print(Store store, llvm::raw_ostream& Out, const char* nl,
|
|
|
|
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) {
|
|
|
|
// FIXME: Implement.
|
|
|
|
}
|
2008-11-16 12:07:26 +08:00
|
|
|
|
2009-06-18 06:02:04 +08:00
|
|
|
// FIXME: Remove.
|
|
|
|
BasicValueFactory& getBasicVals() {
|
|
|
|
return StateMgr.getBasicVals();
|
|
|
|
}
|
2009-09-09 23:08:12 +08:00
|
|
|
|
2009-06-18 06:02:04 +08:00
|
|
|
// FIXME: Remove.
|
|
|
|
ASTContext& getContext() { return StateMgr.getContext(); }
|
2008-10-08 10:50:44 +08:00
|
|
|
};
|
|
|
|
|
|
|
|
} // end anonymous namespace
|
|
|
|
|
2009-06-17 06:36:44 +08:00
|
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
// RegionStore creation.
|
|
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
|
|
|
|
StoreManager *clang::CreateRegionStoreManager(GRStateManager& StMgr) {
|
|
|
|
RegionStoreFeatures F = maximal_features_tag();
|
|
|
|
return new RegionStoreManager(StMgr, F);
|
|
|
|
}
|
|
|
|
|
|
|
|
StoreManager *clang::CreateFieldsOnlyRegionStoreManager(GRStateManager &StMgr) {
|
|
|
|
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
|
|
|
void
|
|
|
|
RegionStoreSubRegionMap::process(llvm::SmallVectorImpl<const SubRegion*> &WL,
|
2009-09-09 23:08:12 +08:00
|
|
|
const SubRegion *R) {
|
2009-08-06 09:20:57 +08:00
|
|
|
const MemRegion *superR = R->getSuperRegion();
|
|
|
|
if (add(superR, R))
|
|
|
|
if (const SubRegion *sr = dyn_cast<SubRegion>(superR))
|
2009-09-09 23:08:12 +08:00
|
|
|
WL.push_back(sr);
|
2009-08-06 09:20:57 +08:00
|
|
|
}
|
|
|
|
|
2009-08-01 14:17:29 +08:00
|
|
|
RegionStoreSubRegionMap*
|
2009-10-11 16:08:02 +08:00
|
|
|
RegionStoreManager::getRegionStoreSubRegionMap(Store store) {
|
|
|
|
RegionBindings B = GetRegionBindings(store);
|
2009-03-03 09:35:36 +08:00
|
|
|
RegionStoreSubRegionMap *M = new RegionStoreSubRegionMap();
|
2009-09-09 23:08:12 +08:00
|
|
|
|
2009-08-01 14:17:29 +08:00
|
|
|
llvm::SmallVector<const SubRegion*, 10> WL;
|
|
|
|
|
2009-08-06 12:50:20 +08:00
|
|
|
for (RegionBindings::iterator I=B.begin(), E=B.end(); I!=E; ++I)
|
2010-01-11 08:07:44 +08:00
|
|
|
if (const SubRegion *R = dyn_cast<SubRegion>(I.getKey().getRegion()))
|
2009-08-06 09:20:57 +08:00
|
|
|
M->process(WL, R);
|
2009-09-09 23:08:12 +08:00
|
|
|
|
|
|
|
// We also need to record in the subregion map "intermediate" regions that
|
2009-08-01 14:17:29 +08:00
|
|
|
// don't have direct bindings but are super regions of those that do.
|
|
|
|
while (!WL.empty()) {
|
|
|
|
const SubRegion *R = WL.back();
|
|
|
|
WL.pop_back();
|
2009-08-06 09:20:57 +08:00
|
|
|
M->process(WL, R);
|
2009-08-01 14:17:29 +08:00
|
|
|
}
|
|
|
|
|
2009-03-04 03:02:42 +08:00
|
|
|
return M;
|
2009-03-03 09:35:36 +08:00
|
|
|
}
|
2008-12-24 15:46:32 +08:00
|
|
|
|
2009-08-01 14:17:29 +08:00
|
|
|
SubRegionMap *RegionStoreManager::getSubRegionMap(const GRState *state) {
|
2009-10-11 16:08:02 +08:00
|
|
|
return getRegionStoreSubRegionMap(state->getStore());
|
2009-08-01 14:17:29 +08:00
|
|
|
}
|
|
|
|
|
2009-07-30 02:16:25 +08:00
|
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
// Binding invalidation.
|
|
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
|
2010-02-03 06:38:47 +08:00
|
|
|
|
2009-10-11 16:08:02 +08:00
|
|
|
void RegionStoreManager::RemoveSubRegionBindings(RegionBindings &B,
|
|
|
|
const MemRegion *R,
|
|
|
|
RegionStoreSubRegionMap &M) {
|
2010-02-03 06:38:47 +08:00
|
|
|
|
|
|
|
if (const RegionStoreSubRegionMap::Set *S = M.getSubRegions(R))
|
|
|
|
for (RegionStoreSubRegionMap::Set::iterator I = S->begin(), E = S->end();
|
|
|
|
I != E; ++I)
|
|
|
|
RemoveSubRegionBindings(B, *I, M);
|
2010-01-11 08:07:44 +08:00
|
|
|
|
|
|
|
B = Remove(B, R);
|
2009-08-01 14:17:29 +08:00
|
|
|
}
|
|
|
|
|
2009-12-03 11:27:11 +08:00
|
|
|
const GRState *RegionStoreManager::InvalidateRegions(const GRState *state,
|
|
|
|
const MemRegion * const *I,
|
|
|
|
const MemRegion * const *E,
|
|
|
|
const Expr *Ex,
|
|
|
|
unsigned Count,
|
|
|
|
InvalidatedSymbols *IS) {
|
2009-07-30 02:16:25 +08:00
|
|
|
ASTContext& Ctx = StateMgr.getContext();
|
2009-09-09 23:08:12 +08:00
|
|
|
|
2009-09-28 04:45:21 +08:00
|
|
|
// Get the mapping of regions -> subregions.
|
|
|
|
llvm::OwningPtr<RegionStoreSubRegionMap>
|
2009-10-11 16:08:02 +08:00
|
|
|
SubRegions(getRegionStoreSubRegionMap(state->getStore()));
|
2009-09-28 04:45:21 +08:00
|
|
|
|
|
|
|
RegionBindings B = GetRegionBindings(state->getStore());
|
2009-10-11 16:08:02 +08:00
|
|
|
|
2009-09-28 04:45:21 +08:00
|
|
|
llvm::DenseMap<const MemRegion *, unsigned> Visited;
|
|
|
|
llvm::SmallVector<const MemRegion *, 10> WorkList;
|
2009-12-03 11:27:11 +08:00
|
|
|
|
|
|
|
for ( ; I != E; ++I) {
|
|
|
|
// Strip away casts.
|
|
|
|
WorkList.push_back((*I)->StripCasts());
|
|
|
|
}
|
2009-09-28 04:45:21 +08:00
|
|
|
|
|
|
|
while (!WorkList.empty()) {
|
2009-12-03 11:27:11 +08:00
|
|
|
const MemRegion *R = WorkList.back();
|
2009-09-28 04:45:21 +08:00
|
|
|
WorkList.pop_back();
|
|
|
|
|
|
|
|
// Have we visited this region before?
|
|
|
|
unsigned &visited = Visited[R];
|
|
|
|
if (visited)
|
|
|
|
continue;
|
|
|
|
visited = 1;
|
|
|
|
|
|
|
|
// Add subregions to work list.
|
2010-02-03 06:38:47 +08:00
|
|
|
if (const RegionStoreSubRegionMap::Set *S = SubRegions->getSubRegions(R))
|
|
|
|
for (RegionStoreSubRegionMap::Set::iterator I = S->begin(), E = S->end();
|
|
|
|
I != E; ++I)
|
|
|
|
WorkList.push_back(*I);
|
2009-10-11 16:08:02 +08:00
|
|
|
|
|
|
|
// Get the old binding. Is it a region? If so, add it to the worklist.
|
|
|
|
if (Optional<SVal> V = getDirectBinding(B, R)) {
|
|
|
|
if (const MemRegion *RV = V->getAsRegion())
|
|
|
|
WorkList.push_back(RV);
|
2009-10-16 08:30:49 +08:00
|
|
|
|
|
|
|
// A symbol? Mark it touched by the invalidation.
|
|
|
|
if (IS) {
|
|
|
|
if (SymbolRef Sym = V->getAsSymbol())
|
|
|
|
IS->insert(Sym);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// Symbolic region? Mark that symbol touched by the invalidation.
|
|
|
|
if (IS) {
|
|
|
|
if (const SymbolicRegion *SR = dyn_cast<SymbolicRegion>(R))
|
|
|
|
IS->insert(SR->getSymbol());
|
2009-10-11 16:08:02 +08:00
|
|
|
}
|
2009-12-03 16:25:47 +08:00
|
|
|
|
|
|
|
// BlockDataRegion? If so, invalidate captured variables that are passed
|
|
|
|
// by reference.
|
|
|
|
if (const BlockDataRegion *BR = dyn_cast<BlockDataRegion>(R)) {
|
|
|
|
for (BlockDataRegion::referenced_vars_iterator
|
|
|
|
I = BR->referenced_vars_begin(), E = BR->referenced_vars_end() ;
|
|
|
|
I != E; ++I) {
|
|
|
|
const VarRegion *VR = *I;
|
|
|
|
if (VR->getDecl()->getAttr<BlocksAttr>())
|
|
|
|
WorkList.push_back(VR);
|
|
|
|
}
|
|
|
|
continue;
|
|
|
|
}
|
2009-10-11 16:08:02 +08:00
|
|
|
|
2009-10-16 08:30:49 +08:00
|
|
|
// Handle the region itself.
|
2009-12-17 07:53:37 +08:00
|
|
|
if (isa<AllocaRegion>(R) || isa<SymbolicRegion>(R)) {
|
2009-10-11 16:08:02 +08:00
|
|
|
// Invalidate the region by setting its default value to
|
|
|
|
// conjured symbol. The type of the symbol is irrelavant.
|
2009-09-28 04:45:21 +08:00
|
|
|
DefinedOrUnknownSVal V = ValMgr.getConjuredSymbolVal(R, Ex, Ctx.IntTy,
|
2010-01-11 08:07:44 +08:00
|
|
|
Count);
|
|
|
|
B = Add(B, R, BindingVal(V, BindingVal::Default));
|
2009-09-28 04:45:21 +08:00
|
|
|
continue;
|
|
|
|
}
|
2009-08-01 14:17:29 +08:00
|
|
|
|
2009-09-28 04:45:21 +08:00
|
|
|
if (!R->isBoundable())
|
|
|
|
continue;
|
|
|
|
|
|
|
|
const TypedRegion *TR = cast<TypedRegion>(R);
|
|
|
|
QualType T = TR->getValueType(Ctx);
|
|
|
|
|
|
|
|
if (const RecordType *RT = T->getAsStructureType()) {
|
|
|
|
const RecordDecl *RD = RT->getDecl()->getDefinition(Ctx);
|
|
|
|
|
2009-10-11 16:08:02 +08:00
|
|
|
// No record definition. There is nothing we can do.
|
2009-09-28 04:45:21 +08:00
|
|
|
if (!RD)
|
|
|
|
continue;
|
|
|
|
|
2009-10-11 16:08:02 +08:00
|
|
|
// Invalidate the region by setting its default value to
|
|
|
|
// conjured symbol. The type of the symbol is irrelavant.
|
2009-09-28 04:45:21 +08:00
|
|
|
DefinedOrUnknownSVal V = ValMgr.getConjuredSymbolVal(R, Ex, Ctx.IntTy,
|
|
|
|
Count);
|
2010-01-11 08:07:44 +08:00
|
|
|
B = Add(B, R, BindingVal(V, BindingVal::Default));
|
2009-09-28 04:45:21 +08:00
|
|
|
continue;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (const ArrayType *AT = Ctx.getAsArrayType(T)) {
|
|
|
|
// Set the default value of the array to conjured symbol.
|
|
|
|
DefinedOrUnknownSVal V =
|
|
|
|
ValMgr.getConjuredSymbolVal(R, Ex, AT->getElementType(), Count);
|
2010-01-11 08:07:44 +08:00
|
|
|
B = Add(B, R, BindingVal(V, BindingVal::Default));
|
2009-09-28 04:45:21 +08:00
|
|
|
continue;
|
|
|
|
}
|
2009-09-29 11:34:03 +08:00
|
|
|
|
|
|
|
if ((isa<FieldRegion>(R)||isa<ElementRegion>(R)||isa<ObjCIvarRegion>(R))
|
|
|
|
&& Visited[cast<SubRegion>(R)->getSuperRegion()]) {
|
2009-10-11 16:08:02 +08:00
|
|
|
// For fields and elements whose super region has also been invalidated,
|
|
|
|
// only remove the old binding. The super region will get set with a
|
|
|
|
// default value from which we can lazily derive a new symbolic value.
|
2010-01-11 08:07:44 +08:00
|
|
|
B = Remove(B, R);
|
2009-09-29 11:34:03 +08:00
|
|
|
continue;
|
|
|
|
}
|
2009-09-28 04:45:21 +08:00
|
|
|
|
2009-09-29 11:12:50 +08:00
|
|
|
// Invalidate the binding.
|
2009-09-28 04:45:21 +08:00
|
|
|
DefinedOrUnknownSVal V = ValMgr.getConjuredSymbolVal(R, Ex, T, Count);
|
|
|
|
assert(SymbolManager::canSymbolicate(T) || V.isUnknown());
|
2010-01-11 08:07:44 +08:00
|
|
|
B = Add(B, R, BindingVal(V, BindingVal::Direct));
|
2009-07-30 02:16:25 +08:00
|
|
|
}
|
2009-09-09 23:08:12 +08:00
|
|
|
|
2009-09-28 04:45:21 +08:00
|
|
|
// Create a new state with the updated bindings.
|
2009-10-11 16:08:02 +08:00
|
|
|
return state->makeWithStore(B.getRoot());
|
2009-07-30 02:16:25 +08:00
|
|
|
}
|
|
|
|
|
2009-06-17 06:36:44 +08:00
|
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
// getLValueXXX methods.
|
|
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
|
2008-12-24 15:46:32 +08:00
|
|
|
/// getLValueString - Returns an SVal representing the lvalue of a
|
|
|
|
/// StringLiteral. Within RegionStore a StringLiteral has an
|
|
|
|
/// associated StringRegion, and the lvalue of a StringLiteral is the
|
|
|
|
/// lvalue of that region.
|
2009-10-14 11:33:08 +08:00
|
|
|
SVal RegionStoreManager::getLValueString(const StringLiteral* S) {
|
2008-10-25 22:18:57 +08:00
|
|
|
return loc::MemRegionVal(MRMgr.getStringRegion(S));
|
|
|
|
}
|
|
|
|
|
2008-12-24 15:46:32 +08:00
|
|
|
/// getLValueVar - Returns an SVal that represents the lvalue of a
|
|
|
|
/// variable. Within RegionStore a variable has an associated
|
|
|
|
/// VarRegion, and the lvalue of the variable is the lvalue of that region.
|
2009-10-14 11:33:08 +08:00
|
|
|
SVal RegionStoreManager::getLValueVar(const VarDecl *VD,
|
2009-08-22 06:28:32 +08:00
|
|
|
const LocationContext *LC) {
|
|
|
|
return loc::MemRegionVal(MRMgr.getVarRegion(VD, LC));
|
2008-10-22 21:44:38 +08:00
|
|
|
}
|
2008-11-07 18:38:33 +08:00
|
|
|
|
2009-10-14 11:33:08 +08:00
|
|
|
SVal RegionStoreManager::getLValueIvar(const ObjCIvarDecl* D, SVal Base) {
|
|
|
|
return getLValueFieldOrIvar(D, Base);
|
2008-10-22 21:44:38 +08:00
|
|
|
}
|
|
|
|
|
2009-10-14 11:33:08 +08:00
|
|
|
SVal RegionStoreManager::getLValueField(const FieldDecl* D, SVal Base) {
|
|
|
|
return getLValueFieldOrIvar(D, Base);
|
2009-03-05 12:50:08 +08:00
|
|
|
}
|
|
|
|
|
2009-10-14 11:33:08 +08:00
|
|
|
SVal RegionStoreManager::getLValueFieldOrIvar(const Decl* D, SVal Base) {
|
2008-10-22 21:44:38 +08:00
|
|
|
if (Base.isUnknownOrUndef())
|
|
|
|
return Base;
|
|
|
|
|
|
|
|
Loc BaseL = cast<Loc>(Base);
|
|
|
|
const MemRegion* BaseR = 0;
|
|
|
|
|
|
|
|
switch (BaseL.getSubKind()) {
|
|
|
|
case loc::MemRegionKind:
|
|
|
|
BaseR = cast<loc::MemRegionVal>(BaseL).getRegion();
|
|
|
|
break;
|
|
|
|
|
|
|
|
case loc::GotoLabelKind:
|
|
|
|
// These are anormal cases. Flag an undefined value.
|
|
|
|
return UndefinedVal();
|
|
|
|
|
|
|
|
case loc::ConcreteIntKind:
|
|
|
|
// While these seem funny, this can happen through casts.
|
|
|
|
// FIXME: What we should return is the field offset. For example,
|
|
|
|
// add the field offset to the integer value. That way funny things
|
|
|
|
// like this work properly: &(((struct foo *) 0xa)->f)
|
|
|
|
return Base;
|
|
|
|
|
|
|
|
default:
|
2008-11-07 16:57:30 +08:00
|
|
|
assert(0 && "Unhandled Base.");
|
2008-10-22 21:44:38 +08:00
|
|
|
return Base;
|
|
|
|
}
|
2009-09-09 23:08:12 +08:00
|
|
|
|
2009-03-05 12:50:08 +08:00
|
|
|
// NOTE: We must have this check first because ObjCIvarDecl is a subclass
|
|
|
|
// of FieldDecl.
|
|
|
|
if (const ObjCIvarDecl *ID = dyn_cast<ObjCIvarDecl>(D))
|
|
|
|
return loc::MemRegionVal(MRMgr.getObjCIvarRegion(ID, BaseR));
|
2008-10-22 21:44:38 +08:00
|
|
|
|
2009-03-05 12:50:08 +08:00
|
|
|
return loc::MemRegionVal(MRMgr.getFieldRegion(cast<FieldDecl>(D), BaseR));
|
2008-10-22 21:44:38 +08:00
|
|
|
}
|
|
|
|
|
2009-10-14 11:33:08 +08:00
|
|
|
SVal RegionStoreManager::getLValueElement(QualType elementType, SVal Offset,
|
|
|
|
SVal Base) {
|
2008-10-24 09:09:32 +08:00
|
|
|
|
2009-03-10 06:44:49 +08:00
|
|
|
// If the base is an unknown or undefined value, just return it back.
|
|
|
|
// FIXME: For absolute pointer addresses, we just return that value back as
|
|
|
|
// well, although in reality we should return the offset added to that
|
|
|
|
// value.
|
|
|
|
if (Base.isUnknownOrUndef() || isa<loc::ConcreteInt>(Base))
|
2008-10-27 20:23:17 +08:00
|
|
|
return Base;
|
|
|
|
|
2009-01-23 04:27:48 +08:00
|
|
|
// Only handle integer offsets... for now.
|
|
|
|
if (!isa<nonloc::ConcreteInt>(Offset))
|
2008-11-13 17:48:44 +08:00
|
|
|
return UnknownVal();
|
2008-10-24 09:09:32 +08:00
|
|
|
|
2009-05-09 21:20:07 +08:00
|
|
|
const MemRegion* BaseRegion = cast<loc::MemRegionVal>(Base).getRegion();
|
2008-10-24 09:09:32 +08:00
|
|
|
|
2009-01-23 04:27:48 +08:00
|
|
|
// Pointer of any type can be cast and used as array base.
|
|
|
|
const ElementRegion *ElemR = dyn_cast<ElementRegion>(BaseRegion);
|
2009-09-09 23:08:12 +08:00
|
|
|
|
2009-07-16 09:33:37 +08:00
|
|
|
// Convert the offset to the appropriate size and signedness.
|
|
|
|
Offset = ValMgr.convertToArrayIndex(Offset);
|
2009-09-09 23:08:12 +08:00
|
|
|
|
2009-01-23 04:27:48 +08:00
|
|
|
if (!ElemR) {
|
|
|
|
//
|
|
|
|
// If the base region is not an ElementRegion, create one.
|
|
|
|
// This can happen in the following example:
|
|
|
|
//
|
|
|
|
// char *p = __builtin_alloc(10);
|
|
|
|
// p[1] = 8;
|
|
|
|
//
|
2009-05-09 21:20:07 +08:00
|
|
|
// Observe that 'p' binds to an AllocaRegion.
|
2009-01-23 04:27:48 +08:00
|
|
|
//
|
2009-05-04 14:18:28 +08:00
|
|
|
return loc::MemRegionVal(MRMgr.getElementRegion(elementType, Offset,
|
2009-06-16 17:55:50 +08:00
|
|
|
BaseRegion, getContext()));
|
2009-01-23 04:27:48 +08:00
|
|
|
}
|
2009-09-09 23:08:12 +08:00
|
|
|
|
2009-01-23 04:27:48 +08:00
|
|
|
SVal BaseIdx = ElemR->getIndex();
|
2009-09-09 23:08:12 +08:00
|
|
|
|
2009-01-23 04:27:48 +08:00
|
|
|
if (!isa<nonloc::ConcreteInt>(BaseIdx))
|
|
|
|
return UnknownVal();
|
2009-09-09 23:08:12 +08:00
|
|
|
|
2009-01-23 04:27:48 +08:00
|
|
|
const llvm::APSInt& BaseIdxI = cast<nonloc::ConcreteInt>(BaseIdx).getValue();
|
|
|
|
const llvm::APSInt& OffI = cast<nonloc::ConcreteInt>(Offset).getValue();
|
|
|
|
assert(BaseIdxI.isSigned());
|
2009-09-09 23:08:12 +08:00
|
|
|
|
2009-07-16 09:33:37 +08:00
|
|
|
// Compute the new index.
|
|
|
|
SVal NewIdx = nonloc::ConcreteInt(getBasicVals().getValue(BaseIdxI + OffI));
|
2009-09-09 23:08:12 +08:00
|
|
|
|
2009-07-16 09:33:37 +08:00
|
|
|
// Construct the new ElementRegion.
|
|
|
|
const MemRegion *ArrayR = ElemR->getSuperRegion();
|
2009-06-16 17:55:50 +08:00
|
|
|
return loc::MemRegionVal(MRMgr.getElementRegion(elementType, NewIdx, ArrayR,
|
2009-09-09 23:08:12 +08:00
|
|
|
getContext()));
|
2008-10-24 09:09:32 +08:00
|
|
|
}
|
|
|
|
|
2009-06-17 06:36:44 +08:00
|
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
// Extents for regions.
|
|
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
|
2009-11-12 10:48:32 +08:00
|
|
|
DefinedOrUnknownSVal RegionStoreManager::getSizeInElements(const GRState *state,
|
2010-01-18 16:54:31 +08:00
|
|
|
const MemRegion *R,
|
|
|
|
QualType EleTy) {
|
2009-09-09 23:08:12 +08:00
|
|
|
|
2009-07-11 06:30:06 +08:00
|
|
|
switch (R->getKind()) {
|
2010-01-05 10:18:06 +08:00
|
|
|
case MemRegion::CXXThisRegionKind:
|
|
|
|
assert(0 && "Cannot get size of 'this' region");
|
2009-12-08 06:05:27 +08:00
|
|
|
case MemRegion::GenericMemSpaceRegionKind:
|
|
|
|
case MemRegion::StackLocalsSpaceRegionKind:
|
|
|
|
case MemRegion::StackArgumentsSpaceRegionKind:
|
|
|
|
case MemRegion::HeapSpaceRegionKind:
|
|
|
|
case MemRegion::GlobalsSpaceRegionKind:
|
2009-12-11 14:43:27 +08:00
|
|
|
case MemRegion::UnknownSpaceRegionKind:
|
2009-07-11 06:30:06 +08:00
|
|
|
assert(0 && "Cannot index into a MemSpace");
|
2009-09-09 23:08:12 +08:00
|
|
|
return UnknownVal();
|
|
|
|
|
2009-11-25 09:32:22 +08:00
|
|
|
case MemRegion::FunctionTextRegionKind:
|
|
|
|
case MemRegion::BlockTextRegionKind:
|
2009-11-26 07:53:07 +08:00
|
|
|
case MemRegion::BlockDataRegionKind:
|
2009-07-11 06:30:06 +08:00
|
|
|
// Technically this can happen if people do funny things with casts.
|
|
|
|
return UnknownVal();
|
2008-11-22 21:21:46 +08:00
|
|
|
|
2009-07-11 06:30:06 +08:00
|
|
|
// Not yet handled.
|
|
|
|
case MemRegion::AllocaRegionKind:
|
|
|
|
case MemRegion::CompoundLiteralRegionKind:
|
|
|
|
case MemRegion::ElementRegionKind:
|
|
|
|
case MemRegion::FieldRegionKind:
|
|
|
|
case MemRegion::ObjCIvarRegionKind:
|
2009-12-16 19:27:52 +08:00
|
|
|
case MemRegion::CXXObjectRegionKind:
|
2009-01-30 08:08:43 +08:00
|
|
|
return UnknownVal();
|
2009-09-09 23:08:12 +08:00
|
|
|
|
2010-01-18 16:54:31 +08:00
|
|
|
case MemRegion::SymbolicRegionKind: {
|
|
|
|
const SVal *Size = state->get<RegionExtents>(R);
|
|
|
|
if (!Size)
|
|
|
|
return UnknownVal();
|
|
|
|
const nonloc::ConcreteInt *CI = dyn_cast<nonloc::ConcreteInt>(Size);
|
|
|
|
if (!CI)
|
|
|
|
return UnknownVal();
|
|
|
|
|
|
|
|
CharUnits RegionSize =
|
|
|
|
CharUnits::fromQuantity(CI->getValue().getSExtValue());
|
|
|
|
CharUnits EleSize = getContext().getTypeSizeInChars(EleTy);
|
|
|
|
assert(RegionSize % EleSize == 0);
|
|
|
|
|
|
|
|
return ValMgr.makeIntVal(RegionSize / EleSize, false);
|
|
|
|
}
|
|
|
|
|
2009-07-11 06:30:06 +08:00
|
|
|
case MemRegion::StringRegionKind: {
|
|
|
|
const StringLiteral* Str = cast<StringRegion>(R)->getStringLiteral();
|
2009-09-09 23:08:12 +08:00
|
|
|
// We intentionally made the size value signed because it participates in
|
2009-07-11 06:30:06 +08:00
|
|
|
// operations with signed indices.
|
|
|
|
return ValMgr.makeIntVal(Str->getByteLength()+1, false);
|
2009-01-30 08:08:43 +08:00
|
|
|
}
|
2009-09-09 23:08:12 +08:00
|
|
|
|
2009-07-11 06:30:06 +08:00
|
|
|
case MemRegion::VarRegionKind: {
|
|
|
|
const VarRegion* VR = cast<VarRegion>(R);
|
|
|
|
// Get the type of the variable.
|
|
|
|
QualType T = VR->getDesugaredValueType(getContext());
|
2009-09-09 23:08:12 +08:00
|
|
|
|
2009-07-11 06:30:06 +08:00
|
|
|
// FIXME: Handle variable-length arrays.
|
|
|
|
if (isa<VariableArrayType>(T))
|
|
|
|
return UnknownVal();
|
2009-09-09 23:08:12 +08:00
|
|
|
|
2009-07-11 06:30:06 +08:00
|
|
|
if (const ConstantArrayType* CAT = dyn_cast<ConstantArrayType>(T)) {
|
|
|
|
// return the size as signed integer.
|
|
|
|
return ValMgr.makeIntVal(CAT->getSize(), false);
|
|
|
|
}
|
2009-08-02 13:15:23 +08:00
|
|
|
|
2009-07-11 06:30:06 +08:00
|
|
|
// Clients can use ordinary variables as if they were arrays. These
|
|
|
|
// essentially are arrays of size 1.
|
|
|
|
return ValMgr.makeIntVal(1, false);
|
2009-05-06 19:51:48 +08:00
|
|
|
}
|
2009-05-06 16:08:27 +08:00
|
|
|
}
|
2009-09-09 23:08:12 +08:00
|
|
|
|
2009-07-11 06:30:06 +08:00
|
|
|
assert(0 && "Unreachable");
|
2009-01-07 03:12:06 +08:00
|
|
|
return UnknownVal();
|
2008-11-22 21:21:46 +08:00
|
|
|
}
|
|
|
|
|
2009-06-18 06:02:04 +08:00
|
|
|
const GRState *RegionStoreManager::setExtent(const GRState *state,
|
|
|
|
const MemRegion *region,
|
|
|
|
SVal extent) {
|
|
|
|
return state->set<RegionExtents>(region, extent);
|
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
|
|
|
|
/// the array). This is called by GRExprEngine when evaluating casts
|
|
|
|
/// from arrays to pointers.
|
2009-03-30 13:55:46 +08:00
|
|
|
SVal RegionStoreManager::ArrayToPointer(Loc Array) {
|
2008-12-14 03:24:37 +08:00
|
|
|
if (!isa<loc::MemRegionVal>(Array))
|
|
|
|
return UnknownVal();
|
2009-09-09 23:08:12 +08:00
|
|
|
|
2008-12-14 03:24:37 +08:00
|
|
|
const MemRegion* R = cast<loc::MemRegionVal>(&Array)->getRegion();
|
|
|
|
const TypedRegion* ArrayR = dyn_cast<TypedRegion>(R);
|
2009-09-09 23:08:12 +08:00
|
|
|
|
2009-01-13 09:03:27 +08:00
|
|
|
if (!ArrayR)
|
2008-12-14 03:24:37 +08:00
|
|
|
return UnknownVal();
|
2009-09-09 23:08:12 +08:00
|
|
|
|
2009-05-09 11:57:34 +08:00
|
|
|
// Strip off typedefs from the ArrayRegion's ValueType.
|
2009-09-30 07:03:30 +08:00
|
|
|
QualType T = ArrayR->getValueType(getContext()).getDesugaredType();
|
2009-05-04 14:18:28 +08:00
|
|
|
ArrayType *AT = cast<ArrayType>(T);
|
|
|
|
T = AT->getElementType();
|
2009-09-09 23:08:12 +08:00
|
|
|
|
2009-07-16 08:00:11 +08:00
|
|
|
SVal ZeroIdx = ValMgr.makeZeroArrayIndex();
|
2009-12-04 08:26:31 +08:00
|
|
|
return loc::MemRegionVal(MRMgr.getElementRegion(T, ZeroIdx, ArrayR,
|
|
|
|
getContext()));
|
2008-10-24 09:09:32 +08:00
|
|
|
}
|
|
|
|
|
2009-06-17 06:36:44 +08:00
|
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
// Pointer arithmetic.
|
|
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
|
2009-09-09 23:08:12 +08:00
|
|
|
SVal RegionStoreManager::EvalBinOp(const GRState *state,
|
2009-06-26 08:41:43 +08:00
|
|
|
BinaryOperator::Opcode Op, Loc L, NonLoc R,
|
|
|
|
QualType resultTy) {
|
2009-05-09 23:18:12 +08:00
|
|
|
// Assume the base location is MemRegionVal.
|
2009-03-03 10:51:43 +08:00
|
|
|
if (!isa<loc::MemRegionVal>(L))
|
2009-03-02 15:52:23 +08:00
|
|
|
return UnknownVal();
|
|
|
|
|
2009-04-03 15:33:13 +08:00
|
|
|
const MemRegion* MR = cast<loc::MemRegionVal>(L).getRegion();
|
2009-05-09 23:18:12 +08:00
|
|
|
const ElementRegion *ER = 0;
|
2009-05-20 17:00:16 +08:00
|
|
|
|
2009-07-11 08:58:27 +08:00
|
|
|
switch (MR->getKind()) {
|
|
|
|
case MemRegion::SymbolicRegionKind: {
|
|
|
|
const SymbolicRegion *SR = cast<SymbolicRegion>(MR);
|
2009-08-02 13:15:23 +08:00
|
|
|
SymbolRef Sym = SR->getSymbol();
|
2009-08-26 06:55:09 +08:00
|
|
|
QualType T = Sym->getType(getContext());
|
|
|
|
QualType EleTy;
|
2009-09-09 23:08:12 +08:00
|
|
|
|
2009-08-26 06:55:09 +08:00
|
|
|
if (const PointerType *PT = T->getAs<PointerType>())
|
|
|
|
EleTy = PT->getPointeeType();
|
|
|
|
else
|
2009-09-22 07:43:11 +08:00
|
|
|
EleTy = T->getAs<ObjCObjectPointerType>()->getPointeeType();
|
2009-09-09 23:08:12 +08:00
|
|
|
|
2009-07-11 08:58:27 +08:00
|
|
|
SVal ZeroIdx = ValMgr.makeZeroArrayIndex();
|
|
|
|
ER = MRMgr.getElementRegion(EleTy, ZeroIdx, SR, getContext());
|
2009-09-09 23:08:12 +08:00
|
|
|
break;
|
2009-06-19 12:51:14 +08:00
|
|
|
}
|
2009-07-11 08:58:27 +08:00
|
|
|
case MemRegion::AllocaRegionKind: {
|
|
|
|
const AllocaRegion *AR = cast<AllocaRegion>(MR);
|
2009-08-02 13:15:23 +08:00
|
|
|
QualType T = getContext().CharTy; // Create an ElementRegion of bytes.
|
2009-07-30 05:53:49 +08:00
|
|
|
QualType EleTy = T->getAs<PointerType>()->getPointeeType();
|
2009-07-11 08:58:27 +08:00
|
|
|
SVal ZeroIdx = ValMgr.makeZeroArrayIndex();
|
|
|
|
ER = MRMgr.getElementRegion(EleTy, ZeroIdx, AR, getContext());
|
2009-09-09 23:08:12 +08:00
|
|
|
break;
|
2009-07-11 08:58:27 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
case MemRegion::ElementRegionKind: {
|
|
|
|
ER = cast<ElementRegion>(MR);
|
|
|
|
break;
|
|
|
|
}
|
2009-09-09 23:08:12 +08:00
|
|
|
|
2009-07-11 08:58:27 +08:00
|
|
|
// Not yet handled.
|
|
|
|
case MemRegion::VarRegionKind:
|
2009-10-06 09:39:48 +08:00
|
|
|
case MemRegion::StringRegionKind: {
|
|
|
|
|
|
|
|
}
|
|
|
|
// Fall-through.
|
2009-07-11 08:58:27 +08:00
|
|
|
case MemRegion::CompoundLiteralRegionKind:
|
|
|
|
case MemRegion::FieldRegionKind:
|
|
|
|
case MemRegion::ObjCIvarRegionKind:
|
2009-12-16 19:27:52 +08:00
|
|
|
case MemRegion::CXXObjectRegionKind:
|
2009-07-11 08:58:27 +08:00
|
|
|
return UnknownVal();
|
2009-09-09 23:08:12 +08:00
|
|
|
|
2009-11-25 09:32:22 +08:00
|
|
|
case MemRegion::FunctionTextRegionKind:
|
|
|
|
case MemRegion::BlockTextRegionKind:
|
2009-11-26 07:53:07 +08:00
|
|
|
case MemRegion::BlockDataRegionKind:
|
2009-07-11 08:58:27 +08:00
|
|
|
// Technically this can happen if people do funny things with casts.
|
|
|
|
return UnknownVal();
|
2009-09-09 23:08:12 +08:00
|
|
|
|
2010-01-05 10:18:06 +08:00
|
|
|
case MemRegion::CXXThisRegionKind:
|
|
|
|
assert(0 &&
|
|
|
|
"Cannot perform pointer arithmetic on implicit argument 'this'");
|
2009-12-08 06:05:27 +08:00
|
|
|
case MemRegion::GenericMemSpaceRegionKind:
|
|
|
|
case MemRegion::StackLocalsSpaceRegionKind:
|
|
|
|
case MemRegion::StackArgumentsSpaceRegionKind:
|
|
|
|
case MemRegion::HeapSpaceRegionKind:
|
|
|
|
case MemRegion::GlobalsSpaceRegionKind:
|
2009-12-11 14:43:27 +08:00
|
|
|
case MemRegion::UnknownSpaceRegionKind:
|
2009-07-11 08:58:27 +08:00
|
|
|
assert(0 && "Cannot perform pointer arithmetic on a MemSpace");
|
|
|
|
return UnknownVal();
|
2009-06-21 21:24:24 +08:00
|
|
|
}
|
2009-03-02 15:52:23 +08:00
|
|
|
|
|
|
|
SVal Idx = ER->getIndex();
|
|
|
|
nonloc::ConcreteInt* Base = dyn_cast<nonloc::ConcreteInt>(&Idx);
|
|
|
|
|
2009-10-06 09:39:48 +08:00
|
|
|
// For now, only support:
|
|
|
|
// (a) concrete integer indices that can easily be resolved
|
|
|
|
// (b) 0 + symbolic index
|
|
|
|
if (Base) {
|
|
|
|
if (nonloc::ConcreteInt *Offset = dyn_cast<nonloc::ConcreteInt>(&R)) {
|
|
|
|
// FIXME: Should use SValuator here.
|
|
|
|
SVal NewIdx =
|
|
|
|
Base->evalBinOp(ValMgr, Op,
|
2009-07-16 09:33:37 +08:00
|
|
|
cast<nonloc::ConcreteInt>(ValMgr.convertToArrayIndex(*Offset)));
|
2009-10-06 09:39:48 +08:00
|
|
|
const MemRegion* NewER =
|
|
|
|
MRMgr.getElementRegion(ER->getElementType(), NewIdx,
|
|
|
|
ER->getSuperRegion(), getContext());
|
|
|
|
return ValMgr.makeLoc(NewER);
|
|
|
|
}
|
|
|
|
if (0 == Base->getValue()) {
|
|
|
|
const MemRegion* NewER =
|
|
|
|
MRMgr.getElementRegion(ER->getElementType(), R,
|
|
|
|
ER->getSuperRegion(), getContext());
|
|
|
|
return ValMgr.makeLoc(NewER);
|
|
|
|
}
|
2009-03-03 10:51:43 +08:00
|
|
|
}
|
2009-09-09 23:08:12 +08:00
|
|
|
|
2009-03-03 10:51:43 +08:00
|
|
|
return UnknownVal();
|
2009-03-02 15:52:23 +08:00
|
|
|
}
|
|
|
|
|
2009-06-17 06:36:44 +08:00
|
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
// Loading values from regions.
|
|
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
|
2009-10-11 16:08:02 +08:00
|
|
|
Optional<SVal> RegionStoreManager::getDirectBinding(RegionBindings B,
|
|
|
|
const MemRegion *R) {
|
2010-01-11 08:07:44 +08:00
|
|
|
if (const BindingVal *BV = Lookup(B, R))
|
2009-10-11 16:08:02 +08:00
|
|
|
return Optional<SVal>::create(BV->getDirectValue());
|
|
|
|
|
|
|
|
return Optional<SVal>();
|
|
|
|
}
|
|
|
|
|
|
|
|
Optional<SVal> RegionStoreManager::getDefaultBinding(RegionBindings B,
|
2009-08-07 05:43:54 +08:00
|
|
|
const MemRegion *R) {
|
2009-09-09 23:08:12 +08:00
|
|
|
|
2009-08-07 05:43:54 +08:00
|
|
|
if (R->isBoundable())
|
|
|
|
if (const TypedRegion *TR = dyn_cast<TypedRegion>(R))
|
|
|
|
if (TR->getValueType(getContext())->isUnionType())
|
|
|
|
return UnknownVal();
|
|
|
|
|
2010-01-11 08:07:44 +08:00
|
|
|
if (const BindingVal *V = Lookup(B, R))
|
2009-10-11 16:08:02 +08:00
|
|
|
return Optional<SVal>::create(V->getDefaultValue());
|
|
|
|
|
|
|
|
return Optional<SVal>();
|
|
|
|
}
|
|
|
|
|
|
|
|
Optional<SVal> RegionStoreManager::getBinding(RegionBindings B,
|
|
|
|
const MemRegion *R) {
|
2010-01-11 08:07:44 +08:00
|
|
|
if (const BindingVal *BV = Lookup(B, R))
|
2009-10-11 16:08:02 +08:00
|
|
|
return Optional<SVal>::create(BV->getValue());
|
|
|
|
|
|
|
|
return Optional<SVal>();
|
2009-08-07 05:43:54 +08:00
|
|
|
}
|
|
|
|
|
2009-07-15 10:31:43 +08:00
|
|
|
static bool IsReinterpreted(QualType RTy, QualType UsedTy, ASTContext &Ctx) {
|
|
|
|
RTy = Ctx.getCanonicalType(RTy);
|
|
|
|
UsedTy = Ctx.getCanonicalType(UsedTy);
|
2009-09-09 23:08:12 +08:00
|
|
|
|
2009-07-15 10:31:43 +08:00
|
|
|
if (RTy == UsedTy)
|
|
|
|
return false;
|
2009-09-09 23:08:12 +08:00
|
|
|
|
|
|
|
|
2009-07-21 06:58:02 +08:00
|
|
|
// Recursively check the types. We basically want to see if a pointer value
|
2009-09-09 23:08:12 +08:00
|
|
|
// is ever reinterpreted as a non-pointer, e.g. void** and intptr_t*
|
2009-07-21 06:58:02 +08:00
|
|
|
// represents a reinterpretation.
|
|
|
|
if (Loc::IsLocType(RTy) && Loc::IsLocType(UsedTy)) {
|
2009-09-09 23:08:12 +08:00
|
|
|
const PointerType *PRTy = RTy->getAs<PointerType>();
|
2009-07-30 05:53:49 +08:00
|
|
|
const PointerType *PUsedTy = UsedTy->getAs<PointerType>();
|
2009-07-21 06:58:02 +08:00
|
|
|
|
|
|
|
return PUsedTy && PRTy &&
|
|
|
|
IsReinterpreted(PRTy->getPointeeType(),
|
2009-09-09 23:08:12 +08:00
|
|
|
PUsedTy->getPointeeType(), Ctx);
|
2009-07-21 06:58:02 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
return true;
|
2009-07-15 10:31:43 +08:00
|
|
|
}
|
|
|
|
|
2009-09-24 12:11:44 +08:00
|
|
|
const ElementRegion *
|
|
|
|
RegionStoreManager::GetElementZeroRegion(const SymbolicRegion *SR, QualType T) {
|
|
|
|
ASTContext &Ctx = getContext();
|
|
|
|
SVal idx = ValMgr.makeZeroArrayIndex();
|
|
|
|
assert(!T.isNull());
|
|
|
|
return MRMgr.getElementRegion(T, idx, SR, Ctx);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
2009-07-22 05:03:30 +08:00
|
|
|
SValuator::CastResult
|
|
|
|
RegionStoreManager::Retrieve(const GRState *state, Loc L, QualType T) {
|
2009-06-18 06:02:04 +08:00
|
|
|
|
2008-10-21 13:29:26 +08:00
|
|
|
assert(!isa<UnknownVal>(L) && "location unknown");
|
|
|
|
assert(!isa<UndefinedVal>(L) && "location undefined");
|
2009-12-16 07:23:27 +08:00
|
|
|
|
2008-12-24 15:46:32 +08:00
|
|
|
// FIXME: Is this even possible? Shouldn't this be treated as a null
|
|
|
|
// dereference at a higher level?
|
2008-12-20 14:32:12 +08:00
|
|
|
if (isa<loc::ConcreteInt>(L))
|
2009-07-22 05:03:30 +08:00
|
|
|
return SValuator::CastResult(state, UndefinedVal());
|
2009-12-16 07:23:27 +08:00
|
|
|
|
2009-06-18 06:02:04 +08:00
|
|
|
const MemRegion *MR = cast<loc::MemRegionVal>(L).getRegion();
|
2009-04-03 15:33:13 +08:00
|
|
|
|
2009-05-20 17:18:48 +08:00
|
|
|
// FIXME: return symbolic value for these cases.
|
2009-04-03 15:33:13 +08:00
|
|
|
// Example:
|
|
|
|
// void f(int* p) { int x = *p; }
|
2009-05-20 17:18:48 +08:00
|
|
|
// char* p = alloca();
|
|
|
|
// read(p);
|
|
|
|
// c = *p;
|
2009-07-15 04:48:22 +08:00
|
|
|
if (isa<AllocaRegion>(MR))
|
2009-07-22 05:03:30 +08:00
|
|
|
return SValuator::CastResult(state, UnknownVal());
|
2009-09-09 23:08:12 +08:00
|
|
|
|
2009-09-24 12:11:44 +08:00
|
|
|
if (const SymbolicRegion *SR = dyn_cast<SymbolicRegion>(MR))
|
|
|
|
MR = GetElementZeroRegion(SR, T);
|
2009-09-09 23:08:12 +08:00
|
|
|
|
2009-08-04 05:41:46 +08:00
|
|
|
if (isa<CodeTextRegion>(MR))
|
|
|
|
return SValuator::CastResult(state, UnknownVal());
|
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.
|
2009-06-18 06:02:04 +08:00
|
|
|
const TypedRegion *R = cast<TypedRegion>(MR);
|
2009-07-15 10:31:43 +08:00
|
|
|
QualType RTy = R->getValueType(getContext());
|
2008-10-21 13:29:26 +08:00
|
|
|
|
2008-12-24 15:46:32 +08:00
|
|
|
// FIXME: We should eventually handle funny addressing. e.g.:
|
|
|
|
//
|
|
|
|
// int x = ...;
|
|
|
|
// int *p = &x;
|
|
|
|
// char *q = (char*) p;
|
|
|
|
// char c = *q; // returns the first byte of 'x'.
|
|
|
|
//
|
|
|
|
// Such funny addressing will occur due to layering of regions.
|
|
|
|
|
2009-08-01 14:17:29 +08:00
|
|
|
#if 0
|
2009-07-15 10:31:43 +08:00
|
|
|
ASTContext &Ctx = getContext();
|
|
|
|
if (!T.isNull() && IsReinterpreted(RTy, T, Ctx)) {
|
2009-07-16 09:33:37 +08:00
|
|
|
SVal ZeroIdx = ValMgr.makeZeroArrayIndex();
|
|
|
|
R = MRMgr.getElementRegion(T, ZeroIdx, R, Ctx);
|
2009-07-15 10:31:43 +08:00
|
|
|
RTy = T;
|
2009-07-15 12:23:32 +08:00
|
|
|
assert(Ctx.getCanonicalType(RTy) ==
|
|
|
|
Ctx.getCanonicalType(R->getValueType(Ctx)));
|
2009-09-09 23:08:12 +08:00
|
|
|
}
|
2009-08-01 14:17:29 +08:00
|
|
|
#endif
|
2009-05-03 08:27:40 +08:00
|
|
|
|
2009-03-09 17:15:51 +08:00
|
|
|
if (RTy->isStructureType())
|
2009-07-22 05:03:30 +08:00
|
|
|
return SValuator::CastResult(state, RetrieveStruct(state, R));
|
2009-09-09 23:08:12 +08:00
|
|
|
|
2009-08-07 05:43:54 +08:00
|
|
|
// FIXME: Handle unions.
|
|
|
|
if (RTy->isUnionType())
|
|
|
|
return SValuator::CastResult(state, UnknownVal());
|
2009-05-03 08:27:40 +08:00
|
|
|
|
|
|
|
if (RTy->isArrayType())
|
2009-07-22 05:03:30 +08:00
|
|
|
return SValuator::CastResult(state, RetrieveArray(state, R));
|
2009-05-03 08:27:40 +08:00
|
|
|
|
2009-03-09 17:15:51 +08:00
|
|
|
// FIXME: handle Vector types.
|
|
|
|
if (RTy->isVectorType())
|
2009-07-22 05:03:30 +08:00
|
|
|
return SValuator::CastResult(state, UnknownVal());
|
2009-06-28 22:16:39 +08:00
|
|
|
|
|
|
|
if (const FieldRegion* FR = dyn_cast<FieldRegion>(R))
|
2009-11-16 12:49:44 +08:00
|
|
|
return SValuator::CastResult(state,
|
2010-01-11 10:33:26 +08:00
|
|
|
CastRetrievedVal(RetrieveField(state, FR), FR,
|
|
|
|
T, false));
|
|
|
|
|
|
|
|
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.
|
2009-11-16 12:49:44 +08:00
|
|
|
return SValuator::CastResult(state,
|
2010-01-11 10:33:26 +08:00
|
|
|
CastRetrievedVal(RetrieveElement(state, ER),
|
|
|
|
ER, T, false));
|
|
|
|
}
|
|
|
|
|
|
|
|
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).
|
2009-11-16 12:49:44 +08:00
|
|
|
return SValuator::CastResult(state,
|
2010-01-11 10:33:26 +08:00
|
|
|
CastRetrievedVal(RetrieveObjCIvar(state, IVR),
|
|
|
|
IVR, T, false));
|
|
|
|
}
|
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
|
|
|
|
// storing them or reinterpret them lazily (as we do here).
|
2009-11-16 12:49:44 +08:00
|
|
|
return SValuator::CastResult(state,
|
2010-01-11 10:33:26 +08:00
|
|
|
CastRetrievedVal(RetrieveVar(state, VR), VR, T,
|
|
|
|
false));
|
|
|
|
}
|
2009-07-21 06:58:02 +08:00
|
|
|
|
2009-08-06 12:50:20 +08:00
|
|
|
RegionBindings B = GetRegionBindings(state->getStore());
|
2010-01-11 08:07:44 +08:00
|
|
|
const BindingVal *V = Lookup(B, R);
|
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)
|
2009-10-11 16:08:02 +08:00
|
|
|
if (SVal const *SV = V->getValue())
|
|
|
|
return SValuator::CastResult(state, *SV);
|
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.
|
2009-07-22 05:03:30 +08:00
|
|
|
return SValuator::CastResult(state, UndefinedVal());
|
2008-12-24 15:46:32 +08:00
|
|
|
}
|
|
|
|
|
2009-07-03 06:16:42 +08:00
|
|
|
// All other values are symbolic.
|
2009-12-16 07:23:27 +08:00
|
|
|
return SValuator::CastResult(state, ValMgr.getRegionValueSymbolVal(R, RTy));
|
2008-10-21 13:29:26 +08:00
|
|
|
}
|
2009-09-09 23:08:12 +08:00
|
|
|
|
2009-08-06 09:20:57 +08:00
|
|
|
std::pair<const GRState*, const MemRegion*>
|
2009-08-06 12:50:20 +08:00
|
|
|
RegionStoreManager::GetLazyBinding(RegionBindings B, const MemRegion *R) {
|
2009-10-11 16:08:02 +08:00
|
|
|
if (Optional<SVal> OV = getDirectBinding(B, R))
|
|
|
|
if (const nonloc::LazyCompoundVal *V =
|
|
|
|
dyn_cast<nonloc::LazyCompoundVal>(OV.getPointer()))
|
|
|
|
return std::make_pair(V->getState(), V->getRegion());
|
2009-09-09 23:08:12 +08:00
|
|
|
|
2009-08-06 09:20:57 +08:00
|
|
|
if (const ElementRegion *ER = dyn_cast<ElementRegion>(R)) {
|
|
|
|
const std::pair<const GRState *, const MemRegion *> &X =
|
|
|
|
GetLazyBinding(B, ER->getSuperRegion());
|
2009-09-09 23:08:12 +08:00
|
|
|
|
2009-08-06 09:20:57 +08:00
|
|
|
if (X.first)
|
|
|
|
return std::make_pair(X.first,
|
|
|
|
MRMgr.getElementRegionWithSuper(ER, X.second));
|
2009-09-09 23:08:12 +08:00
|
|
|
}
|
2009-08-06 09:20:57 +08:00
|
|
|
else if (const FieldRegion *FR = dyn_cast<FieldRegion>(R)) {
|
|
|
|
const std::pair<const GRState *, const MemRegion *> &X =
|
|
|
|
GetLazyBinding(B, FR->getSuperRegion());
|
2009-09-09 23:08:12 +08:00
|
|
|
|
2009-08-06 09:20:57 +08:00
|
|
|
if (X.first)
|
|
|
|
return std::make_pair(X.first,
|
|
|
|
MRMgr.getFieldRegionWithSuper(FR, X.second));
|
|
|
|
}
|
2009-08-01 14:17:29 +08:00
|
|
|
|
2009-08-06 09:20:57 +08:00
|
|
|
return std::make_pair((const GRState*) 0, (const MemRegion *) 0);
|
|
|
|
}
|
2008-10-21 13:29:26 +08:00
|
|
|
|
2009-06-25 13:29:39 +08:00
|
|
|
SVal RegionStoreManager::RetrieveElement(const GRState* state,
|
|
|
|
const ElementRegion* R) {
|
|
|
|
// Check if the region has a binding.
|
2009-08-06 12:50:20 +08:00
|
|
|
RegionBindings B = GetRegionBindings(state->getStore());
|
2010-01-11 10:33:26 +08:00
|
|
|
if (Optional<SVal> V = getDirectBinding(B, R))
|
2009-06-25 13:29:39 +08:00
|
|
|
return *V;
|
|
|
|
|
2009-07-02 07:19:52 +08:00
|
|
|
const MemRegion* superR = R->getSuperRegion();
|
|
|
|
|
2009-06-25 13:29:39 +08:00
|
|
|
// Check if the region is an element region of a string literal.
|
2009-07-02 07:19:52 +08:00
|
|
|
if (const StringRegion *StrR=dyn_cast<StringRegion>(superR)) {
|
2009-09-30 00:36:48 +08:00
|
|
|
// FIXME: Handle loads from strings where the literal is treated as
|
|
|
|
// an integer, e.g., *((unsigned int*)"hello")
|
|
|
|
ASTContext &Ctx = getContext();
|
2009-11-10 06:08:55 +08:00
|
|
|
QualType T = Ctx.getAsArrayType(StrR->getValueType(Ctx))->getElementType();
|
2009-09-30 00:36:48 +08:00
|
|
|
if (T != Ctx.getCanonicalType(R->getElementType()))
|
|
|
|
return UnknownVal();
|
|
|
|
|
2009-06-25 13:29:39 +08:00
|
|
|
const StringLiteral *Str = StrR->getStringLiteral();
|
|
|
|
SVal Idx = R->getIndex();
|
|
|
|
if (nonloc::ConcreteInt *CI = dyn_cast<nonloc::ConcreteInt>(&Idx)) {
|
|
|
|
int64_t i = CI->getValue().getSExtValue();
|
2009-09-09 23:08:12 +08:00
|
|
|
int64_t byteLength = Str->getByteLength();
|
2009-09-06 01:59:01 +08:00
|
|
|
if (i > byteLength) {
|
|
|
|
// Buffer overflow checking in GRExprEngine should handle this case,
|
|
|
|
// but we shouldn't rely on it to not overflow here if that checking
|
|
|
|
// is disabled.
|
|
|
|
return UnknownVal();
|
2009-09-09 23:08:12 +08:00
|
|
|
}
|
2009-09-06 01:59:01 +08:00
|
|
|
char c = (i == byteLength) ? '\0' : Str->getStrData()[i];
|
2009-09-30 00:36:48 +08:00
|
|
|
return ValMgr.makeIntVal(c, T);
|
2009-06-25 13:29:39 +08:00
|
|
|
}
|
|
|
|
}
|
2009-09-09 23:08:12 +08:00
|
|
|
|
2009-08-07 06:33:36 +08:00
|
|
|
// Check if the immediate super region has a direct binding.
|
2009-10-11 16:08:02 +08:00
|
|
|
if (Optional<SVal> V = getDirectBinding(B, superR)) {
|
2009-07-15 10:31:43 +08:00
|
|
|
if (SymbolRef parentSym = V->getAsSymbol())
|
|
|
|
return ValMgr.getDerivedRegionValueSymbolVal(parentSym, R);
|
2009-07-22 12:35:42 +08:00
|
|
|
|
|
|
|
if (V->isUnknownOrUndef())
|
|
|
|
return *V;
|
2009-08-07 06:33:36 +08:00
|
|
|
|
|
|
|
// Handle LazyCompoundVals for the immediate super region. Other cases
|
|
|
|
// are handled in 'RetrieveFieldOrElementCommon'.
|
2009-09-09 23:08:12 +08:00
|
|
|
if (const nonloc::LazyCompoundVal *LCV =
|
2009-08-07 06:33:36 +08:00
|
|
|
dyn_cast<nonloc::LazyCompoundVal>(V)) {
|
2009-09-09 23:08:12 +08:00
|
|
|
|
2009-08-07 06:33:36 +08:00
|
|
|
R = MRMgr.getElementRegionWithSuper(R, LCV->getRegion());
|
|
|
|
return RetrieveElement(LCV->getState(), R);
|
|
|
|
}
|
2009-09-09 23:08:12 +08:00
|
|
|
|
2009-07-15 10:31:43 +08:00
|
|
|
// Other cases: give up.
|
2009-07-03 14:11:41 +08:00
|
|
|
return UnknownVal();
|
2009-06-30 20:32:59 +08:00
|
|
|
}
|
2010-01-11 10:33:26 +08:00
|
|
|
|
2009-08-07 06:33:36 +08:00
|
|
|
return RetrieveFieldOrElementCommon(state, R, R->getElementType(), superR);
|
2009-06-25 13:29:39 +08:00
|
|
|
}
|
|
|
|
|
2009-09-09 23:08:12 +08:00
|
|
|
SVal RegionStoreManager::RetrieveField(const GRState* state,
|
2009-06-25 12:50:44 +08:00
|
|
|
const FieldRegion* R) {
|
|
|
|
|
|
|
|
// Check if the region has a binding.
|
2009-08-06 12:50:20 +08:00
|
|
|
RegionBindings B = GetRegionBindings(state->getStore());
|
2009-10-11 16:08:02 +08:00
|
|
|
if (Optional<SVal> V = getDirectBinding(B, R))
|
2009-06-25 12:50:44 +08:00
|
|
|
return *V;
|
|
|
|
|
2009-08-07 06:33:36 +08:00
|
|
|
QualType Ty = R->getValueType(getContext());
|
|
|
|
return RetrieveFieldOrElementCommon(state, R, Ty, R->getSuperRegion());
|
|
|
|
}
|
2009-09-09 23:08:12 +08:00
|
|
|
|
2009-08-07 06:33:36 +08:00
|
|
|
SVal RegionStoreManager::RetrieveFieldOrElementCommon(const GRState *state,
|
|
|
|
const TypedRegion *R,
|
|
|
|
QualType Ty,
|
|
|
|
const MemRegion *superR) {
|
|
|
|
|
2009-09-09 23:08:12 +08:00
|
|
|
// At this point we have already checked in either RetrieveElement or
|
2009-08-07 06:33:36 +08:00
|
|
|
// RetrieveField if 'R' has a direct binding.
|
2009-09-09 23:08:12 +08:00
|
|
|
|
2009-08-07 06:33:36 +08:00
|
|
|
RegionBindings B = GetRegionBindings(state->getStore());
|
2009-09-09 23:08:12 +08:00
|
|
|
|
2009-08-01 14:17:29 +08:00
|
|
|
while (superR) {
|
2009-10-11 16:08:02 +08:00
|
|
|
if (const Optional<SVal> &D = getDefaultBinding(B, superR)) {
|
2009-08-01 14:17:29 +08:00
|
|
|
if (SymbolRef parentSym = D->getAsSymbol())
|
|
|
|
return ValMgr.getDerivedRegionValueSymbolVal(parentSym, R);
|
2009-09-09 23:08:12 +08:00
|
|
|
|
2009-08-01 14:17:29 +08:00
|
|
|
if (D->isZeroConstant())
|
|
|
|
return ValMgr.makeZeroVal(Ty);
|
2009-09-09 23:08:12 +08:00
|
|
|
|
2009-08-01 14:17:29 +08:00
|
|
|
if (D->isUnknown())
|
|
|
|
return *D;
|
2009-09-09 23:08:12 +08:00
|
|
|
|
2009-08-01 14:17:29 +08:00
|
|
|
assert(0 && "Unknown default value");
|
|
|
|
}
|
2009-09-09 23:08:12 +08:00
|
|
|
|
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.
|
|
|
|
if (isa<FieldRegion>(superR) || isa<ElementRegion>(superR)) {
|
|
|
|
superR = cast<SubRegion>(superR)->getSuperRegion();
|
|
|
|
continue;
|
|
|
|
}
|
2009-09-09 23:08:12 +08:00
|
|
|
|
2009-08-01 14:17:29 +08:00
|
|
|
break;
|
2009-08-06 09:20:57 +08:00
|
|
|
}
|
2009-09-09 23:08:12 +08:00
|
|
|
|
2009-08-06 09:20:57 +08:00
|
|
|
// Lazy binding?
|
|
|
|
const GRState *lazyBindingState = NULL;
|
2009-08-07 06:33:36 +08:00
|
|
|
const MemRegion *lazyBindingRegion = NULL;
|
|
|
|
llvm::tie(lazyBindingState, lazyBindingRegion) = GetLazyBinding(B, R);
|
2009-09-09 23:08:12 +08:00
|
|
|
|
2009-08-06 09:20:57 +08:00
|
|
|
if (lazyBindingState) {
|
2009-08-07 06:33:36 +08:00
|
|
|
assert(lazyBindingRegion && "Lazy-binding region not set");
|
2009-09-09 23:08:12 +08:00
|
|
|
|
2009-08-07 06:33:36 +08:00
|
|
|
if (isa<ElementRegion>(R))
|
|
|
|
return RetrieveElement(lazyBindingState,
|
|
|
|
cast<ElementRegion>(lazyBindingRegion));
|
2009-09-09 23:08:12 +08:00
|
|
|
|
2009-08-06 09:20:57 +08:00
|
|
|
return RetrieveField(lazyBindingState,
|
2009-08-07 06:33:36 +08:00
|
|
|
cast<FieldRegion>(lazyBindingRegion));
|
2009-09-09 23:08:12 +08:00
|
|
|
}
|
|
|
|
|
2010-01-05 10:18:06 +08:00
|
|
|
if (R->hasStackNonParametersStorage()) {
|
2009-08-07 06:33:36 +08:00
|
|
|
if (isa<ElementRegion>(R)) {
|
|
|
|
// Currently we don't reason specially about Clang-style vectors. Check
|
|
|
|
// if superR is a vector and if so return Unknown.
|
|
|
|
if (const TypedRegion *typedSuperR = dyn_cast<TypedRegion>(superR)) {
|
|
|
|
if (typedSuperR->getValueType(getContext())->isVectorType())
|
|
|
|
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
|
|
|
|
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.
|
2009-12-16 07:23:27 +08:00
|
|
|
return ValMgr.getRegionValueSymbolVal(R, Ty);
|
2009-06-25 12:50:44 +08:00
|
|
|
}
|
2009-09-09 23:08:12 +08:00
|
|
|
|
|
|
|
SVal RegionStoreManager::RetrieveObjCIvar(const GRState* state,
|
2009-07-15 14:09:28 +08:00
|
|
|
const ObjCIvarRegion* R) {
|
|
|
|
|
|
|
|
// Check if the region has a binding.
|
2009-08-06 12:50:20 +08:00
|
|
|
RegionBindings B = GetRegionBindings(state->getStore());
|
2009-07-15 14:09:28 +08:00
|
|
|
|
2009-10-11 16:08:02 +08:00
|
|
|
if (Optional<SVal> V = getDirectBinding(B, R))
|
2009-07-15 14:09:28 +08:00
|
|
|
return *V;
|
2009-09-09 23:08:12 +08:00
|
|
|
|
2009-07-15 14:09:28 +08:00
|
|
|
const MemRegion *superR = R->getSuperRegion();
|
|
|
|
|
2009-10-20 09:20:57 +08:00
|
|
|
// Check if the super region has a default binding.
|
|
|
|
if (Optional<SVal> V = getDefaultBinding(B, superR)) {
|
2009-07-15 14:09:28 +08:00
|
|
|
if (SymbolRef parentSym = V->getAsSymbol())
|
|
|
|
return ValMgr.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
|
|
|
|
2009-07-21 06:58:02 +08:00
|
|
|
return RetrieveLazySymbol(state, R);
|
|
|
|
}
|
|
|
|
|
2009-07-21 08:12:07 +08:00
|
|
|
SVal RegionStoreManager::RetrieveVar(const GRState *state,
|
|
|
|
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.
|
2009-08-06 12:50:20 +08:00
|
|
|
RegionBindings B = GetRegionBindings(state->getStore());
|
2009-09-09 23:08:12 +08:00
|
|
|
|
2009-10-11 16:08:02 +08:00
|
|
|
if (Optional<SVal> V = getDirectBinding(B, R))
|
2009-07-21 08:12:07 +08:00
|
|
|
return *V;
|
2009-09-09 23:08:12 +08:00
|
|
|
|
2009-07-21 08:12:07 +08:00
|
|
|
// Lazily derive a value for the VarRegion.
|
|
|
|
const VarDecl *VD = R->getDecl();
|
2009-09-09 23:08:12 +08:00
|
|
|
|
2009-12-11 14:43:27 +08:00
|
|
|
if (R->hasGlobalsOrParametersStorage() ||
|
|
|
|
isa<UnknownSpaceRegion>(R->getMemorySpace()))
|
2009-12-16 07:23:27 +08:00
|
|
|
return ValMgr.getRegionValueSymbolVal(R, VD->getType());
|
2009-09-09 23:08:12 +08:00
|
|
|
|
2009-07-21 08:12:07 +08:00
|
|
|
return UndefinedVal();
|
|
|
|
}
|
|
|
|
|
2009-09-09 23:08:12 +08:00
|
|
|
SVal RegionStoreManager::RetrieveLazySymbol(const GRState *state,
|
2009-07-21 06:58:02 +08:00
|
|
|
const TypedRegion *R) {
|
2009-09-09 23:08:12 +08:00
|
|
|
|
2009-07-21 06:58:02 +08:00
|
|
|
QualType valTy = R->getValueType(getContext());
|
2009-07-22 12:35:42 +08:00
|
|
|
|
2009-07-15 14:09:28 +08:00
|
|
|
// All other values are symbolic.
|
2009-12-16 07:23:27 +08:00
|
|
|
return ValMgr.getRegionValueSymbolVal(R, valTy);
|
2009-07-15 14:09:28 +08:00
|
|
|
}
|
|
|
|
|
2009-09-09 23:08:12 +08:00
|
|
|
SVal RegionStoreManager::RetrieveStruct(const GRState *state,
|
|
|
|
const TypedRegion* R) {
|
2009-05-09 11:57:34 +08:00
|
|
|
QualType T = R->getValueType(getContext());
|
2008-10-31 15:16:08 +08:00
|
|
|
assert(T->isStructureType());
|
|
|
|
|
2009-06-11 15:27:30 +08:00
|
|
|
const RecordType* RT = T->getAsStructureType();
|
2008-10-31 15:16:08 +08:00
|
|
|
RecordDecl* RD = RT->getDecl();
|
|
|
|
assert(RD->isDefinition());
|
2009-08-06 20:56:50 +08:00
|
|
|
(void)RD;
|
2009-08-06 09:20:57 +08:00
|
|
|
#if USE_EXPLICIT_COMPOUND
|
2008-10-31 15:16:08 +08:00
|
|
|
llvm::ImmutableList<SVal> StructVal = getBasicVals().getEmptySValList();
|
|
|
|
|
2009-06-18 06:02:04 +08:00
|
|
|
// FIXME: We shouldn't use a std::vector. If RecordDecl doesn't have a
|
|
|
|
// reverse iterator, we should implement one.
|
2009-06-30 10:36:12 +08:00
|
|
|
std::vector<FieldDecl *> Fields(RD->field_begin(), RD->field_end());
|
2008-12-12 00:49:14 +08:00
|
|
|
|
2008-12-12 04:41:00 +08:00
|
|
|
for (std::vector<FieldDecl *>::reverse_iterator Field = Fields.rbegin(),
|
|
|
|
FieldEnd = Fields.rend();
|
|
|
|
Field != FieldEnd; ++Field) {
|
|
|
|
FieldRegion* FR = MRMgr.getFieldRegion(*Field, R);
|
2009-05-03 08:27:40 +08:00
|
|
|
QualType FTy = (*Field)->getType();
|
2009-07-22 05:03:30 +08:00
|
|
|
SVal FieldValue = Retrieve(state, loc::MemRegionVal(FR), FTy).getSVal();
|
2008-10-31 15:16:08 +08:00
|
|
|
StructVal = getBasicVals().consVals(FieldValue, StructVal);
|
|
|
|
}
|
|
|
|
|
2009-06-23 17:02:15 +08:00
|
|
|
return ValMgr.makeCompoundVal(T, StructVal);
|
2009-08-06 09:20:57 +08:00
|
|
|
#else
|
|
|
|
return ValMgr.makeLazyCompoundVal(state, R);
|
|
|
|
#endif
|
2008-10-31 15:16:08 +08:00
|
|
|
}
|
|
|
|
|
2009-06-18 06:02:04 +08:00
|
|
|
SVal RegionStoreManager::RetrieveArray(const GRState *state,
|
|
|
|
const TypedRegion * R) {
|
2009-08-06 09:20:57 +08:00
|
|
|
#if USE_EXPLICIT_COMPOUND
|
2009-05-09 11:57:34 +08:00
|
|
|
QualType T = R->getValueType(getContext());
|
2009-05-03 08:27:40 +08:00
|
|
|
ConstantArrayType* CAT = cast<ConstantArrayType>(T.getTypePtr());
|
|
|
|
|
|
|
|
llvm::ImmutableList<SVal> ArrayVal = getBasicVals().getEmptySValList();
|
2009-07-16 09:33:37 +08:00
|
|
|
uint64_t size = CAT->getSize().getZExtValue();
|
|
|
|
for (uint64_t i = 0; i < size; ++i) {
|
|
|
|
SVal Idx = ValMgr.makeArrayIndex(i);
|
2009-06-16 17:55:50 +08:00
|
|
|
ElementRegion* ER = MRMgr.getElementRegion(CAT->getElementType(), Idx, R,
|
2009-09-09 23:08:12 +08:00
|
|
|
getContext());
|
2009-05-04 14:18:28 +08:00
|
|
|
QualType ETy = ER->getElementType();
|
2009-07-22 05:03:30 +08:00
|
|
|
SVal ElementVal = Retrieve(state, loc::MemRegionVal(ER), ETy).getSVal();
|
2009-05-03 08:27:40 +08:00
|
|
|
ArrayVal = getBasicVals().consVals(ElementVal, ArrayVal);
|
|
|
|
}
|
|
|
|
|
2009-06-23 17:02:15 +08:00
|
|
|
return ValMgr.makeCompoundVal(T, ArrayVal);
|
2009-08-06 09:20:57 +08:00
|
|
|
#else
|
|
|
|
assert(isa<ConstantArrayType>(R->getValueType(getContext())));
|
|
|
|
return ValMgr.makeLazyCompoundVal(state, R);
|
|
|
|
#endif
|
2009-05-03 08:27:40 +08:00
|
|
|
}
|
|
|
|
|
2009-06-17 06:36:44 +08:00
|
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
// Binding values to regions.
|
|
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
|
|
|
|
Store RegionStoreManager::Remove(Store store, Loc L) {
|
|
|
|
if (isa<loc::MemRegionVal>(L))
|
2010-01-11 10:33:26 +08:00
|
|
|
if (const MemRegion* R = cast<loc::MemRegionVal>(L).getRegion())
|
|
|
|
return Remove(store, BindingKey::Make(R));
|
2009-09-09 23:08:12 +08:00
|
|
|
|
2009-06-17 06:36:44 +08:00
|
|
|
return store;
|
|
|
|
}
|
|
|
|
|
2009-06-18 06:02:04 +08:00
|
|
|
const GRState *RegionStoreManager::Bind(const GRState *state, Loc L, SVal V) {
|
2009-06-28 18:16:11 +08:00
|
|
|
if (isa<loc::ConcreteInt>(L))
|
|
|
|
return state;
|
|
|
|
|
2008-12-20 14:32:12 +08:00
|
|
|
// If we get here, the location should be a region.
|
2009-08-01 14:17:29 +08:00
|
|
|
const MemRegion *R = cast<loc::MemRegionVal>(L).getRegion();
|
2009-09-09 23:08:12 +08:00
|
|
|
|
2008-12-20 14:32:12 +08:00
|
|
|
// Check if the region is a struct region.
|
2008-10-31 16:10:01 +08:00
|
|
|
if (const TypedRegion* TR = dyn_cast<TypedRegion>(R))
|
2009-05-09 11:57:34 +08:00
|
|
|
if (TR->getValueType(getContext())->isStructureType())
|
2009-06-18 06:02:04 +08:00
|
|
|
return BindStruct(state, TR, V);
|
2009-09-09 23:08:12 +08:00
|
|
|
|
2009-08-01 14:17:29 +08:00
|
|
|
// Special case: the current region represents a cast and it and the super
|
|
|
|
// region both have pointer types or intptr_t types. If so, perform the
|
|
|
|
// bind to the super region.
|
|
|
|
// This is needed to support OSAtomicCompareAndSwap and friends or other
|
2009-09-09 23:08:12 +08:00
|
|
|
// loads that treat integers as pointers and vis versa.
|
2009-08-01 14:17:29 +08:00
|
|
|
if (const ElementRegion *ER = dyn_cast<ElementRegion>(R)) {
|
|
|
|
if (ER->getIndex().isZeroConstant()) {
|
|
|
|
if (const TypedRegion *superR =
|
|
|
|
dyn_cast<TypedRegion>(ER->getSuperRegion())) {
|
|
|
|
ASTContext &Ctx = getContext();
|
|
|
|
QualType superTy = superR->getValueType(Ctx);
|
|
|
|
QualType erTy = ER->getValueType(Ctx);
|
2009-09-09 23:08:12 +08:00
|
|
|
|
|
|
|
if (IsAnyPointerOrIntptr(superTy, Ctx) &&
|
2009-08-01 14:17:29 +08:00
|
|
|
IsAnyPointerOrIntptr(erTy, Ctx)) {
|
2009-09-09 23:08:12 +08:00
|
|
|
SValuator::CastResult cr =
|
|
|
|
ValMgr.getSValuator().EvalCast(V, state, superTy, erTy);
|
2009-08-01 14:17:29 +08:00
|
|
|
return Bind(cr.getState(), loc::MemRegionVal(superR), cr.getSVal());
|
|
|
|
}
|
2009-09-22 06:58:52 +08:00
|
|
|
// For now, just invalidate the fields of the struct/union/class.
|
|
|
|
// FIXME: Precisely handle the fields of the record.
|
|
|
|
if (superTy->isRecordType())
|
2009-10-16 08:30:49 +08:00
|
|
|
return InvalidateRegion(state, superR, NULL, 0, NULL);
|
2009-08-01 14:17:29 +08:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2009-09-24 12:11:44 +08:00
|
|
|
else if (const SymbolicRegion *SR = dyn_cast<SymbolicRegion>(R)) {
|
|
|
|
// Binding directly to a symbolic region should be treated as binding
|
|
|
|
// to element 0.
|
|
|
|
QualType T = SR->getSymbol()->getType(getContext());
|
Add (initial?) static analyzer support for handling C++ references.
This change was a lot bigger than I originally anticipated; among
other things it requires us storing more information in the CFG to
record what block-level expressions need to be evaluated as lvalues.
The big change is that CFGBlocks no longer contain Stmt*'s by
CFGElements. Currently CFGElements just wrap Stmt*, but they also
store a bit indicating whether the block-level expression should be
evalauted as an lvalue. DeclStmts involving the initialization of a
reference require us treating the initialization expression as an
lvalue, even though that information isn't recorded in the AST.
Conceptually this change isn't that complicated, but it required
bubbling up the data through the CFGBuilder, to GRCoreEngine, and
eventually to GRExprEngine.
The addition of CFGElement is also useful for when we want to handle
more control-flow constructs or other data we want to keep in the CFG
that isn't represented well with just a block of statements.
In GRExprEngine, this patch introduces logic for evaluating the
lvalues of references, which currently retrieves the internal "pointer
value" that the reference represents. EvalLoad does a two stage load
to catch null dereferences involving an invalid reference (although
this could possibly be caught earlier during the initialization of a
reference).
Symbols are currently symbolicated using the reference type, instead
of a pointer type, and special handling is required creating
ElementRegions that layer on SymbolicRegions (see the changes to
RegionStoreManager).
Along the way, the DeadStoresChecker also silences warnings involving
dead stores to references. This was the original change I introduced
(which I wrote test cases for) that I realized caused GRExprEngine to
crash.
llvm-svn: 91501
2009-12-16 11:18:58 +08:00
|
|
|
|
|
|
|
// FIXME: Is this the right way to handle symbols that are references?
|
|
|
|
if (const PointerType *PT = T->getAs<PointerType>())
|
|
|
|
T = PT->getPointeeType();
|
|
|
|
else
|
|
|
|
T = T->getAs<ReferenceType>()->getPointeeType();
|
|
|
|
|
2009-09-24 12:11:44 +08:00
|
|
|
R = GetElementZeroRegion(SR, T);
|
|
|
|
}
|
2009-09-09 23:08:12 +08:00
|
|
|
|
2009-08-01 14:17:29 +08:00
|
|
|
// Perform the binding.
|
2009-08-06 12:50:20 +08:00
|
|
|
RegionBindings B = GetRegionBindings(state->getStore());
|
2010-01-11 08:07:44 +08:00
|
|
|
return state->makeWithStore(Add(B, R,
|
|
|
|
BindingVal(V, BindingVal::Direct)).getRoot());
|
2008-12-16 10:36:30 +08:00
|
|
|
}
|
|
|
|
|
2009-08-22 06:28:32 +08:00
|
|
|
const GRState *RegionStoreManager::BindDecl(const GRState *ST,
|
2009-11-04 08:09:15 +08:00
|
|
|
const VarRegion *VR,
|
2009-08-22 06:28:32 +08:00
|
|
|
SVal InitVal) {
|
2008-10-21 13:29:26 +08:00
|
|
|
|
2009-11-04 08:09:15 +08:00
|
|
|
QualType T = VR->getDecl()->getType();
|
2008-10-21 13:29:26 +08:00
|
|
|
|
2009-01-21 14:57:53 +08:00
|
|
|
if (T->isArrayType())
|
2009-08-22 06:28:32 +08:00
|
|
|
return BindArray(ST, VR, InitVal);
|
2009-01-21 14:57:53 +08:00
|
|
|
if (T->isStructureType())
|
2009-08-22 06:28:32 +08:00
|
|
|
return BindStruct(ST, VR, InitVal);
|
2008-10-31 18:24:47 +08:00
|
|
|
|
2009-08-22 06:28:32 +08:00
|
|
|
return Bind(ST, ValMgr.makeLoc(VR), InitVal);
|
2008-10-21 13:29:26 +08:00
|
|
|
}
|
|
|
|
|
2008-12-20 14:32:12 +08:00
|
|
|
// FIXME: this method should be merged into Bind().
|
2009-06-18 06:02:04 +08:00
|
|
|
const GRState *
|
|
|
|
RegionStoreManager::BindCompoundLiteral(const GRState *state,
|
2009-12-08 06:05:27 +08:00
|
|
|
const CompoundLiteralExpr *CL,
|
|
|
|
const LocationContext *LC,
|
2009-06-18 06:02:04 +08:00
|
|
|
SVal V) {
|
2009-12-08 06:05:27 +08:00
|
|
|
return Bind(state, loc::MemRegionVal(MRMgr.getCompoundLiteralRegion(CL, LC)),
|
|
|
|
V);
|
2008-11-07 18:38:33 +08:00
|
|
|
}
|
|
|
|
|
2009-11-20 04:20:24 +08:00
|
|
|
const GRState *RegionStoreManager::setImplicitDefaultValue(const GRState *state,
|
|
|
|
const MemRegion *R,
|
|
|
|
QualType T) {
|
|
|
|
Store store = state->getStore();
|
|
|
|
RegionBindings B = GetRegionBindings(store);
|
|
|
|
SVal V;
|
|
|
|
|
|
|
|
if (Loc::IsLocType(T))
|
|
|
|
V = ValMgr.makeNull();
|
|
|
|
else if (T->isIntegerType())
|
|
|
|
V = ValMgr.makeZeroVal(T);
|
|
|
|
else if (T->isStructureType() || T->isArrayType()) {
|
|
|
|
// Set the default value to a zero constant when it is a structure
|
|
|
|
// or array. The type doesn't really matter.
|
|
|
|
V = ValMgr.makeZeroVal(ValMgr.getContext().IntTy);
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
return state;
|
|
|
|
}
|
2010-01-11 08:07:44 +08:00
|
|
|
|
|
|
|
return state->makeWithStore(Add(B, R,
|
|
|
|
BindingVal(V, BindingVal::Default)).getRoot());
|
2009-11-20 04:20:24 +08:00
|
|
|
}
|
|
|
|
|
2009-06-18 06:02:04 +08:00
|
|
|
const GRState *RegionStoreManager::BindArray(const GRState *state,
|
2009-07-16 09:33:37 +08:00
|
|
|
const TypedRegion* R,
|
2009-06-18 06:02:04 +08:00
|
|
|
SVal Init) {
|
2010-01-27 07:51:00 +08:00
|
|
|
|
|
|
|
ASTContext &Ctx = getContext();
|
|
|
|
const ArrayType *AT =
|
|
|
|
cast<ArrayType>(Ctx.getCanonicalType(R->getValueType(Ctx)));
|
|
|
|
QualType ElementTy = AT->getElementType();
|
|
|
|
Optional<uint64_t> Size;
|
|
|
|
|
|
|
|
if (const ConstantArrayType* CAT = dyn_cast<ConstantArrayType>(AT))
|
|
|
|
Size = CAT->getSize().getZExtValue();
|
|
|
|
|
2008-11-30 13:49:49 +08:00
|
|
|
// Check if the init expr is a StringLiteral.
|
|
|
|
if (isa<loc::MemRegionVal>(Init)) {
|
|
|
|
const MemRegion* InitR = cast<loc::MemRegionVal>(Init).getRegion();
|
|
|
|
const StringLiteral* S = cast<StringRegion>(InitR)->getStringLiteral();
|
|
|
|
const char* str = S->getStrData();
|
|
|
|
unsigned len = S->getByteLength();
|
|
|
|
unsigned j = 0;
|
|
|
|
|
2008-12-20 14:32:12 +08:00
|
|
|
// Copy bytes from the string literal into the target array. Trailing bytes
|
|
|
|
// in the array that are not covered by the string literal are initialized
|
|
|
|
// to zero.
|
2010-01-27 07:51:00 +08:00
|
|
|
|
|
|
|
// We assume that string constants are bound to
|
|
|
|
// constant arrays.
|
2010-01-28 00:31:37 +08:00
|
|
|
uint64_t size = Size.getValue();
|
2010-01-27 07:51:00 +08:00
|
|
|
|
2009-07-16 09:33:37 +08:00
|
|
|
for (uint64_t i = 0; i < size; ++i, ++j) {
|
2008-12-20 14:32:12 +08:00
|
|
|
if (j >= len)
|
|
|
|
break;
|
|
|
|
|
2009-07-16 09:33:37 +08:00
|
|
|
SVal Idx = ValMgr.makeArrayIndex(i);
|
2009-12-04 08:26:31 +08:00
|
|
|
const ElementRegion* ER = MRMgr.getElementRegion(ElementTy, Idx, R,
|
|
|
|
getContext());
|
2008-11-30 13:49:49 +08:00
|
|
|
|
2009-06-23 17:02:15 +08:00
|
|
|
SVal V = ValMgr.makeIntVal(str[j], sizeof(char)*8, true);
|
2009-06-18 06:02:04 +08:00
|
|
|
state = Bind(state, loc::MemRegionVal(ER), V);
|
2008-11-30 13:49:49 +08:00
|
|
|
}
|
|
|
|
|
2009-06-18 06:02:04 +08:00
|
|
|
return state;
|
2008-11-30 13:49:49 +08:00
|
|
|
}
|
2008-10-31 18:24:47 +08:00
|
|
|
|
2009-08-06 09:20:57 +08:00
|
|
|
// Handle lazy compound values.
|
|
|
|
if (nonloc::LazyCompoundVal *LCV = dyn_cast<nonloc::LazyCompoundVal>(&Init))
|
|
|
|
return CopyLazyBindings(*LCV, state, R);
|
2009-09-09 23:08:12 +08:00
|
|
|
|
|
|
|
// Remaining case: explicit compound values.
|
2009-11-20 04:20:24 +08:00
|
|
|
|
|
|
|
if (Init.isUnknown())
|
|
|
|
return setImplicitDefaultValue(state, R, ElementTy);
|
|
|
|
|
2008-10-31 18:24:47 +08:00
|
|
|
nonloc::CompoundVal& CV = cast<nonloc::CompoundVal>(Init);
|
|
|
|
nonloc::CompoundVal::iterator VI = CV.begin(), VE = CV.end();
|
2009-07-16 09:33:37 +08:00
|
|
|
uint64_t i = 0;
|
2009-09-09 23:08:12 +08:00
|
|
|
|
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
|
|
|
|
2009-07-16 09:33:37 +08:00
|
|
|
SVal Idx = ValMgr.makeArrayIndex(i);
|
2009-12-04 08:26:31 +08:00
|
|
|
const ElementRegion *ER = MRMgr.getElementRegion(ElementTy, Idx, R, getContext());
|
2008-11-19 19:06:24 +08:00
|
|
|
|
2010-01-27 07:51:00 +08:00
|
|
|
if (ElementTy->isStructureType())
|
2009-06-18 06:02:04 +08:00
|
|
|
state = BindStruct(state, ER, *VI);
|
2008-12-20 14:32:12 +08:00
|
|
|
else
|
2009-06-23 17:02:15 +08:00
|
|
|
state = Bind(state, ValMgr.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())
|
2009-11-20 04:20:24 +08:00
|
|
|
state = setImplicitDefaultValue(state, R, ElementTy);
|
2009-06-23 13:23:38 +08:00
|
|
|
|
2009-06-18 06:02:04 +08:00
|
|
|
return state;
|
2008-11-19 19:06:24 +08:00
|
|
|
}
|
|
|
|
|
2009-06-18 06:02:04 +08:00
|
|
|
const GRState *
|
|
|
|
RegionStoreManager::BindStruct(const GRState *state, const TypedRegion* R,
|
|
|
|
SVal V) {
|
2009-09-09 23:08:12 +08:00
|
|
|
|
2009-06-18 06:02:04 +08:00
|
|
|
if (!Features.supportsFields())
|
|
|
|
return state;
|
2009-09-09 23:08:12 +08:00
|
|
|
|
2009-05-09 11:57:34 +08:00
|
|
|
QualType T = R->getValueType(getContext());
|
2008-10-31 18:53:01 +08:00
|
|
|
assert(T->isStructureType());
|
|
|
|
|
2009-07-30 05:53:49 +08:00
|
|
|
const RecordType* RT = T->getAs<RecordType>();
|
2008-10-31 18:53:01 +08:00
|
|
|
RecordDecl* RD = RT->getDecl();
|
2009-03-11 17:07:35 +08:00
|
|
|
|
|
|
|
if (!RD->isDefinition())
|
2009-06-18 06:02:04 +08:00
|
|
|
return state;
|
2008-10-31 18:53:01 +08:00
|
|
|
|
2009-08-06 09:20:57 +08:00
|
|
|
// Handle lazy compound values.
|
2009-10-11 16:08:02 +08:00
|
|
|
if (const nonloc::LazyCompoundVal *LCV=dyn_cast<nonloc::LazyCompoundVal>(&V))
|
2009-08-06 09:20:57 +08:00
|
|
|
return CopyLazyBindings(*LCV, state, R);
|
2009-09-09 23:08:12 +08:00
|
|
|
|
2009-06-18 06:02:04 +08:00
|
|
|
// We may get non-CompoundVal accidentally due to imprecise cast logic.
|
|
|
|
// Ignore them and kill the field values.
|
|
|
|
if (V.isUnknown() || !isa<nonloc::CompoundVal>(V))
|
2009-10-11 16:08:02 +08:00
|
|
|
return state->makeWithStore(KillStruct(state->getStore(), R));
|
2009-06-11 17:11:27 +08:00
|
|
|
|
2008-12-20 14:32:12 +08:00
|
|
|
nonloc::CompoundVal& CV = cast<nonloc::CompoundVal>(V);
|
2008-10-31 18:53:01 +08:00
|
|
|
nonloc::CompoundVal::iterator VI = CV.begin(), VE = CV.end();
|
2009-06-23 13:43:16 +08:00
|
|
|
|
|
|
|
RecordDecl::field_iterator FI, FE;
|
|
|
|
|
2009-06-30 10:36:12 +08:00
|
|
|
for (FI = RD->field_begin(), FE = RD->field_end(); FI != FE; ++FI, ++VI) {
|
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
|
|
|
|
2008-12-20 14:32:12 +08:00
|
|
|
QualType FTy = (*FI)->getType();
|
2009-09-23 05:19:14 +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())
|
2009-06-18 06:02:04 +08:00
|
|
|
state = BindArray(state, FR, *VI);
|
2008-12-20 14:32:12 +08:00
|
|
|
else if (FTy->isStructureType())
|
2009-06-18 06:02:04 +08:00
|
|
|
state = BindStruct(state, FR, *VI);
|
2009-09-23 05:19:14 +08:00
|
|
|
else
|
|
|
|
state = Bind(state, ValMgr.makeLoc(FR), *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) {
|
|
|
|
Store store = state->getStore();
|
|
|
|
RegionBindings B = GetRegionBindings(store);
|
2010-01-11 08:07:44 +08:00
|
|
|
B = Add(B, R, BindingVal(ValMgr.makeIntVal(0, false), BindingVal::Default));
|
2009-10-11 16:08:02 +08:00
|
|
|
state = state->makeWithStore(B.getRoot());
|
|
|
|
}
|
2009-06-23 13:43:16 +08:00
|
|
|
|
2009-06-18 06:02:04 +08:00
|
|
|
return state;
|
2008-11-19 19:06:24 +08:00
|
|
|
}
|
|
|
|
|
2009-10-11 16:08:02 +08:00
|
|
|
Store RegionStoreManager::KillStruct(Store store, const TypedRegion* R) {
|
|
|
|
RegionBindings B = GetRegionBindings(store);
|
|
|
|
llvm::OwningPtr<RegionStoreSubRegionMap>
|
|
|
|
SubRegions(getRegionStoreSubRegionMap(store));
|
|
|
|
RemoveSubRegionBindings(B, R, *SubRegions);
|
2009-01-13 09:49:57 +08:00
|
|
|
|
2009-06-25 13:52:16 +08:00
|
|
|
// Set the default value of the struct region to "unknown".
|
2010-01-11 08:07:44 +08:00
|
|
|
B = Add(B, R, BindingVal(UnknownVal(), BindingVal::Default));
|
2009-01-13 09:49:57 +08:00
|
|
|
|
2009-10-11 16:08:02 +08:00
|
|
|
return B.getRoot();
|
2009-01-13 09:49:57 +08:00
|
|
|
}
|
|
|
|
|
2009-08-06 09:20:57 +08:00
|
|
|
const GRState*
|
|
|
|
RegionStoreManager::CopyLazyBindings(nonloc::LazyCompoundVal V,
|
|
|
|
const GRState *state,
|
|
|
|
const TypedRegion *R) {
|
|
|
|
|
|
|
|
// Nuke the old bindings stemming from R.
|
2009-08-06 12:50:20 +08:00
|
|
|
RegionBindings B = GetRegionBindings(state->getStore());
|
2009-06-17 06:36:44 +08:00
|
|
|
|
2009-09-09 23:08:12 +08:00
|
|
|
llvm::OwningPtr<RegionStoreSubRegionMap>
|
2009-10-11 16:08:02 +08:00
|
|
|
SubRegions(getRegionStoreSubRegionMap(state->getStore()));
|
2009-08-06 09:20:57 +08:00
|
|
|
|
2009-09-09 23:08:12 +08:00
|
|
|
// B and DVM are updated after the call to RemoveSubRegionBindings.
|
2009-10-11 16:08:02 +08:00
|
|
|
RemoveSubRegionBindings(B, R, *SubRegions.get());
|
2009-09-09 23:08:12 +08:00
|
|
|
|
2009-08-06 09:20:57 +08:00
|
|
|
// Now copy the bindings. This amounts to just binding 'V' to 'R'. This
|
|
|
|
// results in a zero-copy algorithm.
|
2010-01-11 08:07:44 +08:00
|
|
|
return state->makeWithStore(Add(B, R,
|
|
|
|
BindingVal(V, BindingVal::Direct)).getRoot());
|
|
|
|
}
|
|
|
|
|
|
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
// "Raw" retrievals and bindings.
|
|
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
|
2010-01-11 10:33:26 +08:00
|
|
|
BindingKey BindingKey::Make(const MemRegion *R) {
|
|
|
|
if (const ElementRegion *ER = dyn_cast<ElementRegion>(R)) {
|
|
|
|
const RegionRawOffset &O = ER->getAsRawOffset();
|
|
|
|
|
|
|
|
if (O.getRegion())
|
|
|
|
return BindingKey(O.getRegion(), O.getByteOffset());
|
|
|
|
|
|
|
|
// FIXME: There are some ElementRegions for which we cannot compute
|
|
|
|
// raw offsets yet, including regions with symbolic offsets.
|
|
|
|
}
|
|
|
|
|
|
|
|
return BindingKey(R, 0);
|
|
|
|
}
|
|
|
|
|
2010-01-11 08:07:44 +08:00
|
|
|
RegionBindings RegionStoreManager::Add(RegionBindings B, BindingKey K,
|
|
|
|
BindingVal V) {
|
|
|
|
return RBFactory.Add(B, K, V);
|
|
|
|
}
|
|
|
|
|
|
|
|
RegionBindings RegionStoreManager::Add(RegionBindings B, const MemRegion *R,
|
|
|
|
BindingVal V) {
|
2010-01-11 10:33:26 +08:00
|
|
|
return Add(B, BindingKey::Make(R), V);
|
2010-01-11 08:07:44 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
const BindingVal *RegionStoreManager::Lookup(RegionBindings B, BindingKey K) {
|
|
|
|
return B.lookup(K);
|
|
|
|
}
|
|
|
|
|
|
|
|
const BindingVal *RegionStoreManager::Lookup(RegionBindings B,
|
|
|
|
const MemRegion *R) {
|
2010-01-11 10:33:26 +08:00
|
|
|
return Lookup(B, BindingKey::Make(R));
|
2010-01-11 08:07:44 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
RegionBindings RegionStoreManager::Remove(RegionBindings B, BindingKey K) {
|
|
|
|
return RBFactory.Remove(B, K);
|
|
|
|
}
|
|
|
|
|
|
|
|
RegionBindings RegionStoreManager::Remove(RegionBindings B, const MemRegion *R){
|
2010-01-11 10:33:26 +08:00
|
|
|
return Remove(B, BindingKey::Make(R));
|
2010-01-11 08:07:44 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
Store RegionStoreManager::Remove(Store store, BindingKey K) {
|
|
|
|
RegionBindings B = GetRegionBindings(store);
|
|
|
|
return Remove(B, K).getRoot();
|
2009-08-06 09:20:57 +08:00
|
|
|
}
|
2009-09-09 23:08:12 +08:00
|
|
|
|
2009-06-17 06:36:44 +08:00
|
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
// State pruning.
|
|
|
|
//===----------------------------------------------------------------------===//
|
2009-09-29 14:35:00 +08:00
|
|
|
|
2009-09-09 23:08:12 +08:00
|
|
|
void RegionStoreManager::RemoveDeadBindings(GRState &state, Stmt* Loc,
|
2009-08-02 12:45:08 +08:00
|
|
|
SymbolReaper& SymReaper,
|
2009-06-17 06:36:44 +08:00
|
|
|
llvm::SmallVectorImpl<const MemRegion*>& RegionRoots)
|
2009-09-09 23:08:12 +08:00
|
|
|
{
|
2009-10-18 01:45:11 +08:00
|
|
|
typedef std::pair<const GRState*, const MemRegion *> RBDNode;
|
|
|
|
|
2009-08-02 12:45:08 +08:00
|
|
|
Store store = state.getStore();
|
2009-08-06 12:50:20 +08:00
|
|
|
RegionBindings B = GetRegionBindings(store);
|
2009-09-09 23:08:12 +08:00
|
|
|
|
2009-06-17 06:36:44 +08:00
|
|
|
// The backmap from regions to subregions.
|
2009-08-01 14:17:29 +08:00
|
|
|
llvm::OwningPtr<RegionStoreSubRegionMap>
|
2009-10-11 16:08:02 +08:00
|
|
|
SubRegions(getRegionStoreSubRegionMap(store));
|
2009-09-29 14:35:00 +08:00
|
|
|
|
2009-11-26 10:35:42 +08:00
|
|
|
// Do a pass over the regions in the store. For VarRegions we check if
|
|
|
|
// the variable is still live and if so add it to the list of live roots.
|
|
|
|
// For other regions we populate our region backmap.
|
2009-06-17 06:36:44 +08:00
|
|
|
llvm::SmallVector<const MemRegion*, 10> IntermediateRoots;
|
2009-09-29 14:35:00 +08:00
|
|
|
|
2009-08-01 14:17:29 +08:00
|
|
|
// Scan the direct bindings for "intermediate" roots.
|
2009-08-06 12:50:20 +08:00
|
|
|
for (RegionBindings::iterator I = B.begin(), E = B.end(); I != E; ++I) {
|
2010-01-11 08:07:44 +08:00
|
|
|
const MemRegion *R = I.getKey().getRegion();
|
2009-08-01 14:17:29 +08:00
|
|
|
IntermediateRoots.push_back(R);
|
2009-06-17 06:36:44 +08:00
|
|
|
}
|
2009-09-29 14:35:00 +08:00
|
|
|
|
2009-08-01 14:17:29 +08:00
|
|
|
// Process the "intermediate" roots to find if they are referenced by
|
2009-09-09 23:08:12 +08:00
|
|
|
// real roots.
|
2009-10-17 16:39:24 +08:00
|
|
|
llvm::SmallVector<RBDNode, 10> WorkList;
|
2009-10-29 13:14:17 +08:00
|
|
|
llvm::SmallVector<RBDNode, 10> Postponed;
|
|
|
|
|
2009-10-18 12:15:47 +08:00
|
|
|
llvm::DenseSet<const MemRegion*> IntermediateVisited;
|
2009-09-29 14:35:00 +08:00
|
|
|
|
2009-06-17 06:36:44 +08:00
|
|
|
while (!IntermediateRoots.empty()) {
|
|
|
|
const MemRegion* R = IntermediateRoots.back();
|
|
|
|
IntermediateRoots.pop_back();
|
2009-09-29 14:35:00 +08:00
|
|
|
|
2009-10-17 16:39:24 +08:00
|
|
|
if (IntermediateVisited.count(R))
|
2009-09-29 14:35:00 +08:00
|
|
|
continue;
|
2009-10-17 16:39:24 +08:00
|
|
|
IntermediateVisited.insert(R);
|
2009-09-29 14:35:00 +08:00
|
|
|
|
2009-06-17 06:36:44 +08:00
|
|
|
if (const VarRegion* VR = dyn_cast<VarRegion>(R)) {
|
2009-12-05 04:32:20 +08:00
|
|
|
if (SymReaper.isLive(Loc, VR))
|
2009-10-17 16:39:24 +08:00
|
|
|
WorkList.push_back(std::make_pair(&state, VR));
|
2009-08-01 14:17:29 +08:00
|
|
|
continue;
|
|
|
|
}
|
2009-09-29 14:35:00 +08:00
|
|
|
|
2009-08-01 14:17:29 +08:00
|
|
|
if (const SymbolicRegion* SR = dyn_cast<SymbolicRegion>(R)) {
|
2009-10-29 13:14:17 +08:00
|
|
|
llvm::SmallVectorImpl<RBDNode> &Q =
|
|
|
|
SymReaper.isLive(SR->getSymbol()) ? WorkList : Postponed;
|
|
|
|
|
|
|
|
Q.push_back(std::make_pair(&state, SR));
|
|
|
|
|
2009-08-01 14:17:29 +08:00
|
|
|
continue;
|
2009-06-17 06:36:44 +08:00
|
|
|
}
|
2009-09-29 14:35:00 +08:00
|
|
|
|
|
|
|
// Add the super region for R to the worklist if it is a subregion.
|
2009-08-01 14:17:29 +08:00
|
|
|
if (const SubRegion* superR =
|
2009-09-29 14:35:00 +08:00
|
|
|
dyn_cast<SubRegion>(cast<SubRegion>(R)->getSuperRegion()))
|
2009-08-01 14:17:29 +08:00
|
|
|
IntermediateRoots.push_back(superR);
|
2009-06-17 06:36:44 +08:00
|
|
|
}
|
2009-09-09 23:08:12 +08:00
|
|
|
|
2009-09-29 14:35:00 +08:00
|
|
|
// Enqueue the RegionRoots onto WorkList.
|
|
|
|
for (llvm::SmallVectorImpl<const MemRegion*>::iterator I=RegionRoots.begin(),
|
|
|
|
E=RegionRoots.end(); I!=E; ++I) {
|
2009-10-17 16:39:24 +08:00
|
|
|
WorkList.push_back(std::make_pair(&state, *I));
|
2009-09-09 23:08:12 +08:00
|
|
|
}
|
2009-09-29 14:35:00 +08:00
|
|
|
RegionRoots.clear();
|
|
|
|
|
2009-10-18 12:15:47 +08:00
|
|
|
llvm::DenseSet<RBDNode> Visited;
|
2009-09-29 14:35:00 +08:00
|
|
|
|
2009-10-29 13:14:17 +08:00
|
|
|
tryAgain:
|
2009-09-29 14:35:00 +08:00
|
|
|
while (!WorkList.empty()) {
|
2009-10-17 16:39:24 +08:00
|
|
|
RBDNode N = WorkList.back();
|
2009-09-29 14:35:00 +08:00
|
|
|
WorkList.pop_back();
|
|
|
|
|
|
|
|
// Have we visited this node before?
|
2009-10-17 16:39:24 +08:00
|
|
|
if (Visited.count(N))
|
2009-09-29 14:35:00 +08:00
|
|
|
continue;
|
2009-10-17 16:39:24 +08:00
|
|
|
Visited.insert(N);
|
|
|
|
|
|
|
|
const MemRegion *R = N.second;
|
|
|
|
const GRState *state_N = N.first;
|
2009-09-29 14:35:00 +08:00
|
|
|
|
2009-10-17 16:39:24 +08:00
|
|
|
// Enqueue subregions.
|
|
|
|
RegionStoreSubRegionMap *M;
|
2009-09-29 14:35:00 +08:00
|
|
|
|
2009-10-17 16:39:24 +08:00
|
|
|
if (&state == state_N)
|
|
|
|
M = SubRegions.get();
|
|
|
|
else {
|
|
|
|
RegionStoreSubRegionMap *& SM = SC[state_N];
|
|
|
|
if (!SM)
|
|
|
|
SM = getRegionStoreSubRegionMap(state_N->getStore());
|
|
|
|
M = SM;
|
2009-09-29 14:35:00 +08:00
|
|
|
}
|
2010-02-03 06:38:47 +08:00
|
|
|
|
|
|
|
if (const RegionStoreSubRegionMap::Set *S = M->getSubRegions(R))
|
|
|
|
for (RegionStoreSubRegionMap::Set::iterator I = S->begin(), E = S->end();
|
|
|
|
I != E; ++I)
|
|
|
|
WorkList.push_back(std::make_pair(state_N, *I));
|
2009-10-17 16:39:24 +08:00
|
|
|
|
2009-09-29 14:35:00 +08:00
|
|
|
// Enqueue the super region.
|
|
|
|
if (const SubRegion *SR = dyn_cast<SubRegion>(R)) {
|
|
|
|
const MemRegion *superR = SR->getSuperRegion();
|
|
|
|
if (!isa<MemSpaceRegion>(superR)) {
|
|
|
|
// If 'R' is a field or an element, we want to keep the bindings
|
|
|
|
// for the other fields and elements around. The reason is that
|
2009-10-11 16:08:02 +08:00
|
|
|
// pointer arithmetic can get us to the other fields or elements.
|
2009-10-17 15:32:08 +08:00
|
|
|
assert(isa<FieldRegion>(R) || isa<ElementRegion>(R)
|
|
|
|
|| isa<ObjCIvarRegion>(R));
|
2009-10-17 16:39:24 +08:00
|
|
|
WorkList.push_back(std::make_pair(state_N, superR));
|
2009-09-29 14:35:00 +08:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// Mark the symbol for any live SymbolicRegion as "live". This means we
|
|
|
|
// should continue to track that symbol.
|
2009-11-26 10:35:42 +08:00
|
|
|
if (const SymbolicRegion *SymR = dyn_cast<SymbolicRegion>(R))
|
2009-09-29 14:35:00 +08:00
|
|
|
SymReaper.markLive(SymR->getSymbol());
|
2009-11-26 10:35:42 +08:00
|
|
|
|
2009-12-04 01:48:05 +08:00
|
|
|
// For BlockDataRegions, enqueue the VarRegions for variables marked
|
|
|
|
// with __block (passed-by-reference).
|
2009-11-26 10:35:42 +08:00
|
|
|
// via BlockDeclRefExprs.
|
|
|
|
if (const BlockDataRegion *BD = dyn_cast<BlockDataRegion>(R)) {
|
|
|
|
for (BlockDataRegion::referenced_vars_iterator
|
|
|
|
RI = BD->referenced_vars_begin(), RE = BD->referenced_vars_end();
|
2009-12-04 01:48:05 +08:00
|
|
|
RI != RE; ++RI) {
|
|
|
|
if ((*RI)->getDecl()->getAttr<BlocksAttr>())
|
|
|
|
WorkList.push_back(std::make_pair(state_N, *RI));
|
|
|
|
}
|
2009-11-26 10:35:42 +08:00
|
|
|
// No possible data bindings on a BlockDataRegion. Continue to the
|
|
|
|
// next region in the worklist.
|
|
|
|
continue;
|
|
|
|
}
|
2009-09-29 14:35:00 +08:00
|
|
|
|
|
|
|
Store store_N = state_N->getStore();
|
|
|
|
RegionBindings B_N = GetRegionBindings(store_N);
|
|
|
|
|
|
|
|
// Get the data binding for R (if any).
|
2009-10-11 16:08:02 +08:00
|
|
|
Optional<SVal> V = getBinding(B_N, R);
|
2009-09-09 23:08:12 +08:00
|
|
|
|
2009-10-11 16:08:02 +08:00
|
|
|
if (V) {
|
|
|
|
// Check for lazy bindings.
|
|
|
|
if (const nonloc::LazyCompoundVal *LCV =
|
|
|
|
dyn_cast<nonloc::LazyCompoundVal>(V.getPointer())) {
|
2009-09-29 14:35:00 +08:00
|
|
|
|
2009-10-11 16:08:02 +08:00
|
|
|
const LazyCompoundValData *D = LCV->getCVData();
|
2009-10-17 16:39:24 +08:00
|
|
|
WorkList.push_back(std::make_pair(D->getState(), D->getRegion()));
|
2009-10-11 16:08:02 +08:00
|
|
|
}
|
|
|
|
else {
|
2009-09-29 14:35:00 +08:00
|
|
|
// Update the set of live symbols.
|
2009-10-11 16:08:02 +08:00
|
|
|
for (SVal::symbol_iterator SI=V->symbol_begin(), SE=V->symbol_end();
|
2009-09-29 14:35:00 +08:00
|
|
|
SI!=SE;++SI)
|
|
|
|
SymReaper.markLive(*SI);
|
|
|
|
|
2009-10-11 16:08:02 +08:00
|
|
|
// If V is a region, then add it to the worklist.
|
|
|
|
if (const MemRegion *RX = V->getAsRegion())
|
2009-10-17 16:39:24 +08:00
|
|
|
WorkList.push_back(std::make_pair(state_N, RX));
|
2009-09-29 14:35:00 +08:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2009-10-29 13:14:17 +08:00
|
|
|
// See if any postponed SymbolicRegions are actually live now, after
|
|
|
|
// having done a scan.
|
|
|
|
for (llvm::SmallVectorImpl<RBDNode>::iterator I = Postponed.begin(),
|
|
|
|
E = Postponed.end() ; I != E ; ++I) {
|
|
|
|
if (const SymbolicRegion *SR = cast_or_null<SymbolicRegion>(I->second)) {
|
|
|
|
if (SymReaper.isLive(SR->getSymbol())) {
|
|
|
|
WorkList.push_back(*I);
|
|
|
|
I->second = NULL;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if (!WorkList.empty())
|
|
|
|
goto tryAgain;
|
|
|
|
|
2009-06-17 06:36:44 +08:00
|
|
|
// We have now scanned the store, marking reachable regions and symbols
|
|
|
|
// as live. We now remove all the regions that are dead from the store
|
2009-09-09 23:08:12 +08:00
|
|
|
// as well as update DSymbols with the set symbols that are now dead.
|
2009-08-06 12:50:20 +08:00
|
|
|
for (RegionBindings::iterator I = B.begin(), E = B.end(); I != E; ++I) {
|
2010-01-11 08:07:44 +08:00
|
|
|
const MemRegion* R = I.getKey().getRegion();
|
2009-06-17 06:36:44 +08:00
|
|
|
// If this region live? Is so, none of its symbols are dead.
|
2009-10-17 16:39:24 +08:00
|
|
|
if (Visited.count(std::make_pair(&state, R)))
|
2009-06-17 06:36:44 +08:00
|
|
|
continue;
|
2009-09-09 23:08:12 +08:00
|
|
|
|
2009-06-17 06:36:44 +08:00
|
|
|
// Remove this dead region from the store.
|
2010-01-11 08:07:44 +08:00
|
|
|
store = Remove(store, I.getKey());
|
2009-09-09 23:08:12 +08:00
|
|
|
|
2009-06-17 06:36:44 +08:00
|
|
|
// Mark all non-live symbols that this region references as dead.
|
|
|
|
if (const SymbolicRegion* SymR = dyn_cast<SymbolicRegion>(R))
|
|
|
|
SymReaper.maybeDead(SymR->getSymbol());
|
2009-09-09 23:08:12 +08:00
|
|
|
|
2009-10-11 16:08:02 +08:00
|
|
|
SVal X = *I.getData().getValue();
|
2009-08-02 13:00:15 +08:00
|
|
|
SVal::symbol_iterator SI = X.symbol_begin(), SE = X.symbol_end();
|
|
|
|
for (; SI != SE; ++SI)
|
|
|
|
SymReaper.maybeDead(*SI);
|
|
|
|
}
|
2009-09-09 23:08:12 +08:00
|
|
|
|
2009-08-02 12:45:08 +08:00
|
|
|
// Write the store back.
|
|
|
|
state.setStore(store);
|
2009-06-17 06:36:44 +08:00
|
|
|
}
|
|
|
|
|
2009-10-13 10:24:55 +08:00
|
|
|
GRState const *RegionStoreManager::EnterStackFrame(GRState const *state,
|
|
|
|
StackFrameContext const *frame) {
|
|
|
|
FunctionDecl const *FD = cast<FunctionDecl>(frame->getDecl());
|
|
|
|
CallExpr const *CE = cast<CallExpr>(frame->getCallSite());
|
|
|
|
|
|
|
|
FunctionDecl::param_const_iterator PI = FD->param_begin();
|
|
|
|
|
|
|
|
CallExpr::const_arg_iterator AI = CE->arg_begin(), AE = CE->arg_end();
|
|
|
|
|
|
|
|
// Copy the arg expression value to the arg variables.
|
|
|
|
for (; AI != AE; ++AI, ++PI) {
|
|
|
|
SVal ArgVal = state->getSVal(*AI);
|
2009-12-04 08:26:31 +08:00
|
|
|
state = Bind(state, ValMgr.makeLoc(MRMgr.getVarRegion(*PI, frame)), ArgVal);
|
2009-10-13 10:24:55 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
return state;
|
|
|
|
}
|
|
|
|
|
2009-06-17 06:36:44 +08:00
|
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
// Utility methods.
|
|
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
|
2009-06-25 07:06:47 +08:00
|
|
|
void RegionStoreManager::print(Store store, llvm::raw_ostream& OS,
|
2009-06-17 06:36:44 +08:00
|
|
|
const char* nl, const char *sep) {
|
2009-08-06 12:50:20 +08:00
|
|
|
RegionBindings B = GetRegionBindings(store);
|
2009-10-20 09:20:57 +08:00
|
|
|
OS << "Store (direct and default bindings):" << nl;
|
2009-09-09 23:08:12 +08:00
|
|
|
|
2009-08-06 12:50:20 +08:00
|
|
|
for (RegionBindings::iterator I = B.begin(), E = B.end(); I != E; ++I)
|
2009-09-09 23:08:12 +08:00
|
|
|
OS << ' ' << I.getKey() << " : " << I.getData() << nl;
|
2009-06-17 06:36:44 +08:00
|
|
|
}
|