TypedRegion(const MemRegion* sReg, Kind k) : SubRegion(sReg, k) {}
public:
- virtual QualType getType(ASTContext&) const = 0;
-
+ virtual QualType getRValueType(ASTContext &C) const = 0;
+
+ virtual QualType getLValueType(ASTContext& C) const {
+ // FIXME: We can possibly optimize this later to cache this value.
+ return C.getPointerType(getRValueType(C));
+ }
+
static bool classof(const MemRegion* R) {
unsigned k = R->getKind();
return k > BEG_TYPED_REGIONS && k < END_TYPED_REGIONS;
/// StringRegion - Region associated with a StringLiteral.
class StringRegion : public TypedRegion {
friend class MemRegionManager;
-
const StringLiteral* Str;
-
protected:
StringRegion(const StringLiteral* str, MemRegion* sreg)
public:
const StringLiteral* getStringLiteral() const { return Str; }
-
- QualType getType(ASTContext& C) const {
- return C.getCanonicalType(Str->getType());
- }
+
+ QualType getRValueType(ASTContext& C) const;
void Profile(llvm::FoldingSetNodeID& ID) const {
ProfileRegion(ID, Str, superRegion);
public:
- QualType getType(ASTContext& C) const {
+ QualType getRValueType(ASTContext&) const {
return T;
}
return R->getKind() == AnonTypedRegionKind;
}
};
-
-/// AnonPointeeRegion - anonymous regions pointed-to by pointer function
-/// parameters or pointer globals. In RegionStoreManager, we assume pointer
-/// parameters or globals point at some anonymous region. Such regions are not
-/// the regions associated with the pointer variables themselves. They are
-/// identified by the symbols that are concretized. We create them lazily.
-
-class AnonPointeeRegion : public TypedRegion {
- friend class MemRegionManager;
-
- // Sym - the symbol that is concretized.
- SymbolRef Sym;
-
- // Ty - the type of the region.
- QualType T;
-
- AnonPointeeRegion(SymbolRef sym, QualType t, MemRegion* sreg)
- : TypedRegion(sreg, AnonPointeeRegionKind), Sym(sym), T(t) {}
-
-public:
- QualType getType(ASTContext& C) const;
-
- static void ProfileRegion(llvm::FoldingSetNodeID& ID, SymbolRef Sym,
- const MemRegion* superRegion);
-
- void Profile(llvm::FoldingSetNodeID& ID) const {
- ProfileRegion(ID, Sym, superRegion);
- }
-
- static bool classof(const MemRegion* R) {
- return R->getKind() == AnonPointeeRegionKind;
- }
-};
+
/// CompoundLiteralRegion - A memory region representing a compound literal.
/// Compound literals are essentially temporaries that are stack allocated
const CompoundLiteralExpr* CL,
const MemRegion* superRegion);
public:
- QualType getType(ASTContext& C) const {
+ QualType getRValueType(ASTContext& C) const {
return C.getCanonicalType(CL->getType());
}
-
+
void Profile(llvm::FoldingSetNodeID& ID) const;
void print(llvm::raw_ostream& os) const;
public:
const Decl* getDecl() const { return D; }
void Profile(llvm::FoldingSetNodeID& ID) const;
-
+
+ QualType getRValueType(ASTContext& C) const = 0;
+
static bool classof(const MemRegion* R) {
unsigned k = R->getKind();
return k > BEG_DECL_REGIONS && k < END_DECL_REGIONS;
}
public:
- const VarDecl* getDecl() const { return cast<VarDecl>(D); }
- QualType getType(ASTContext& C) const {
- return C.getCanonicalType(getDecl()->getType());
- }
+ const VarDecl* getDecl() const { return cast<VarDecl>(D); }
+ QualType getRValueType(ASTContext& C) const {
+ // FIXME: We can cache this if needed.
+ return C.getCanonicalType(getDecl()->getType());
+ }
+
void print(llvm::raw_ostream& os) const;
static bool classof(const MemRegion* R) {
void print(llvm::raw_ostream& os) const;
const FieldDecl* getDecl() const { return cast<FieldDecl>(D); }
- QualType getType(ASTContext& C) const {
+
+ QualType getRValueType(ASTContext& C) const {
+ // FIXME: We can cache this if needed.
return C.getCanonicalType(getDecl()->getType());
- }
+ }
static void ProfileRegion(llvm::FoldingSetNodeID& ID, FieldDecl* FD,
const MemRegion* superRegion) {
return cast<ObjCInterfaceDecl>(D);
}
- QualType getType(ASTContext& C) const {
+ QualType getRValueType(ASTContext& C) const {
ObjCInterfaceDecl* ID = const_cast<ObjCInterfaceDecl*>(getInterface());
return C.getObjCInterfaceType(ID);
}
public:
const ObjCIvarDecl* getDecl() const { return cast<ObjCIvarDecl>(D); }
- QualType getType(ASTContext&) const { return getDecl()->getType(); }
+ QualType getRValueType(ASTContext&) const { return getDecl()->getType(); }
static bool classof(const MemRegion* R) {
return R->getKind() == ObjCIvarRegionKind;
SVal getIndex() const { return Index; }
- QualType getType(ASTContext&) const;
+ QualType getRValueType(ASTContext&) const;
/// getArrayRegion - Return the region of the enclosing array. This is
/// the same as getSuperRegion() except that this returns a TypedRegion*
AnonTypedRegion* getAnonTypedRegion(QualType t, const MemRegion* superRegion);
- AnonPointeeRegion* getAnonPointeeRegion(SymbolRef Sym, QualType T);
-
bool hasStackStorage(const MemRegion* R);
private:
/// conversions between arrays and pointers.
virtual SVal ArrayToPointer(SVal Array) = 0;
- virtual std::pair<const GRState*, SVal>
- CastRegion(const GRState* St, SVal VoidPtr, QualType CastToTy, Stmt* CastE)=0;
+
+ class CastResult {
+ const GRState* State;
+ const MemRegion* R;
+ public:
+ const GRState* getState() const { return State; }
+ const MemRegion* getRegion() const { return R; }
+ CastResult(const GRState* s, const MemRegion* r = 0) : State(s), R(r) {}
+ };
+
+ /// CastRegion - Used by GRExprEngine::VisitCast to handle casts from
+ /// a MemRegion* to a specific location type. 'R' is the region being
+ /// casted and 'CastToTy' the result type of the cast.
+ virtual CastResult CastRegion(const GRState* state, const MemRegion* R,
+ QualType CastToTy) = 0;
/// getSelfRegion - Returns the region for the 'self' (Objective-C) or
/// 'this' object (C++). When used when analyzing a normal function this
return false;
const TypedRegion* R = dyn_cast<TypedRegion>(LV->getRegion());
- if (!R)
- return false;
+ if (!R) return false;
+ while (const AnonTypedRegion* ATR = dyn_cast<AnonTypedRegion>(R)) {
+ R = dyn_cast<TypedRegion>(ATR->getSuperRegion());
+ if (!R) return false;
+ }
- QualType T = Ctx.getCanonicalType(R->getType(Ctx));
+ QualType T = Ctx.getCanonicalType(R->getRValueType(Ctx));
// FIXME: If the pointee isn't an integer type, should we flag a warning?
// People can do weird stuff with pointers.
/// conversions between arrays and pointers.
SVal ArrayToPointer(SVal Array) { return Array; }
- std::pair<const GRState*, SVal>
- CastRegion(const GRState* St, SVal VoidPtr, QualType CastToTy, Stmt* CastE) {
- return std::make_pair(St, UnknownVal());
- }
-
+ /// CastRegion - Used by GRExprEngine::VisitCast to handle casts from
+ /// a MemRegion* to a specific location type. 'R' is the region being
+ /// casted and 'CastToTy' the result type of the cast.
+ CastResult CastRegion(const GRState* state, const MemRegion* R,
+ QualType CastToTy);
/// getSelfRegion - Returns the region for the 'self' (Objective-C) or
/// 'this' object (C++). When used when analyzing a normal function this
return UnknownVal();
}
+/// CastRegion - Used by GRExprEngine::VisitCast to handle casts from
+/// a MemRegion* to a specific location type. 'R' is the region being
+/// casted and 'CastToTy' the result type of the cast.
+StoreManager::CastResult
+BasicStoreManager::CastRegion(const GRState* state, const MemRegion* R,
+ QualType CastToTy) {
+
+ // Return the same region if the region types are compatible.
+ if (const TypedRegion* TR = dyn_cast<TypedRegion>(R)) {
+ ASTContext& Ctx = StateMgr.getContext();
+ QualType Ta = Ctx.getCanonicalType(TR->getLValueType(Ctx));
+ QualType Tb = Ctx.getCanonicalType(CastToTy);
+
+ if (Ta == Tb)
+ return CastResult(state, R);
+ }
+
+ return CastResult(state, MRMgr.getAnonTypedRegion(CastToTy, R));
+}
SVal BasicStoreManager::getLValueField(const GRState* St, SVal Base,
const FieldDecl* D) {
if (R) {
// Set the value of the variable to be a conjured symbol.
unsigned Count = Builder.getCurrentBlockCount();
- QualType T = R->getType(Ctx);
+ QualType T = R->getRValueType(Ctx);
// FIXME: handle structs.
if (Loc::IsLocType(T) || (T->isIntegerType() && T->isScalarType())) {
// FIXME: The proper thing to do is to really iterate over the
// container. We will do this with dispatch logic to the store.
// For now, just 'conjure' up a symbolic value.
- QualType T = R->getType(getContext());
+ QualType T = R->getRValueType(getContext());
assert (Loc::IsLocType(T));
unsigned Count = Builder->getCurrentBlockCount();
loc::SymbolVal SymV(SymMgr.getConjuredSymbol(elem, T, Count));
continue;
}
- // Check for casts from a pointer to a region to typed pointer.
- if (isa<loc::MemRegionVal>(V)) {
+ // Check for casts from a region to a specific type.
+ if (loc::MemRegionVal *RV = dyn_cast<loc::MemRegionVal>(&V)) {
assert(Loc::IsLocType(T));
assert(Loc::IsLocType(ExTy));
- // Delegate to store manager.
- std::pair<const GRState*, SVal> Res =
- getStoreManager().CastRegion(St, V, T, CastE);
-
- MakeNode(Dst, CastE, N, BindExpr(Res.first, CastE, Res.second));
+ const MemRegion* R = RV->getRegion();
+ StoreManager& StoreMgr = getStoreManager();
+
+ // Delegate to store manager to get the result of casting a region
+ // to a different type.
+ const StoreManager::CastResult& Res = StoreMgr.CastRegion(St, R, T);
+
+ // Inspect the result. If the MemRegion* returned is NULL, this
+ // expression evaluates to UnknownVal.
+ R = Res.getRegion();
+ if (R) { V = loc::MemRegionVal(R); } else { V = UnknownVal(); }
+
+ // Generate the new node in the ExplodedGraph.
+ MakeNode(Dst, CastE, N, BindExpr(Res.getState(), CastE, V));
continue;
}
ID.AddPointer(superRegion);
}
-QualType AnonPointeeRegion::getType(ASTContext& C) const {
- return C.getCanonicalType(T);
-}
-
-void AnonPointeeRegion::ProfileRegion(llvm::FoldingSetNodeID& ID,
- SymbolRef Sym,
- const MemRegion* superRegion) {
- ID.AddInteger((unsigned) AnonPointeeRegionKind);
- Sym.Profile(ID);
- ID.AddPointer(superRegion);
-}
-
void CompoundLiteralRegion::Profile(llvm::FoldingSetNodeID& ID) const {
CompoundLiteralRegion::ProfileRegion(ID, CL, superRegion);
}
ElementRegion::ProfileRegion(ID, Index, superRegion);
}
-QualType ElementRegion::getType(ASTContext& C) const {
- QualType T = getArrayRegion()->getType(C);
-
+QualType ElementRegion::getRValueType(ASTContext& C) const {
+ QualType T = getArrayRegion()->getLValueType(C);
+ // FIXME: Should ArrayType be considered an LValue or RValue type?
if (isa<ArrayType>(T.getTypePtr())) {
ArrayType* AT = cast<ArrayType>(T.getTypePtr());
return AT->getElementType();
}
}
+//===----------------------------------------------------------------------===//
+// getLValueType() and getRValueType()
+//===----------------------------------------------------------------------===//
+
+QualType StringRegion::getRValueType(ASTContext& C) const {
+ return Str->getType();
+}
+
//===----------------------------------------------------------------------===//
// Region pretty-printing.
//===----------------------------------------------------------------------===//
return R;
}
-AnonPointeeRegion* MemRegionManager::getAnonPointeeRegion(SymbolRef Sym,
- QualType T) {
- llvm::FoldingSetNodeID ID;
- MemRegion* superRegion = getUnknownRegion();
-
- AnonPointeeRegion::ProfileRegion(ID, Sym, superRegion);
-
- void* InsertPos;
- MemRegion* data = Regions.FindNodeOrInsertPos(ID, InsertPos);
- AnonPointeeRegion* R = cast_or_null<AnonPointeeRegion>(data);
-
- if (!R) {
- R = (AnonPointeeRegion*) A.Allocate<AnonPointeeRegion>();
- new (R) AnonPointeeRegion(Sym, T, superRegion);
- Regions.InsertNode(R, InsertPos);
- }
-
- return R;
-}
-
AllocaRegion* MemRegionManager::getAllocaRegion(const Expr* E, unsigned cnt) {
llvm::FoldingSetNodeID ID;
AllocaRegion::ProfileRegion(ID, E, cnt);
SVal ArrayToPointer(SVal Array);
- std::pair<const GRState*, SVal>
- CastRegion(const GRState* St, SVal VoidPtr, QualType CastToTy, Stmt* CastE);
+ /// CastRegion - Used by GRExprEngine::VisitCast to handle casts from
+ /// a MemRegion* to a specific location type. 'R' is the region being
+ /// casted and 'CastToTy' the result type of the cast.
+ CastResult CastRegion(const GRState* state, const MemRegion* R,
+ QualType CastToTy);
SVal Retrieve(const GRState* state, Loc L, QualType T = QualType());
const MemRegion* R) {
if (const VarRegion* VR = dyn_cast<VarRegion>(R)) {
// Get the type of the variable.
- QualType T = VR->getType(getContext());
+ QualType T = VR->getRValueType(getContext());
// It must be of array type.
const ConstantArrayType* CAT = cast<ConstantArrayType>(T.getTypePtr());
llvm::APSInt SSize = cast<nonloc::ConcreteInt>(*T).getValue();
// Get the size of the element in bits.
- QualType ElemTy = cast<PointerType>(ATR->getType(getContext()).getTypePtr())
- ->getPointeeType();
+ QualType LvT = ATR->getLValueType(getContext());
+ QualType ElemTy = cast<PointerType>(LvT.getTypePtr())->getPointeeType();
uint64_t X = getContext().getTypeSize(ElemTy);
return loc::MemRegionVal(ER);
}
-std::pair<const GRState*, SVal>
-RegionStoreManager::CastRegion(const GRState* St, SVal VoidPtr,
- QualType CastToTy, Stmt* CastE) {
- if (const AllocaRegion* AR =
- dyn_cast<AllocaRegion>(cast<loc::MemRegionVal>(VoidPtr).getRegion())) {
-
- // Create a new region to attach type information to it.
- const AnonTypedRegion* TR = MRMgr.getAnonTypedRegion(CastToTy, AR);
-
- // Get the pointer to the first element.
- nonloc::ConcreteInt Idx(getBasicVals().getZeroWithPtrWidth(false));
- const ElementRegion* ER = MRMgr.getElementRegion(Idx, TR);
-
- // Add a RegionView to base region.
- return std::make_pair(AddRegionView(St, TR, AR), loc::MemRegionVal(ER));
+StoreManager::CastResult
+RegionStoreManager::CastRegion(const GRState* state, const MemRegion* R,
+ QualType CastToTy) {
+
+ // Return the same region if the region types are compatible.
+ if (const TypedRegion* TR = dyn_cast<TypedRegion>(R)) {
+ ASTContext& Ctx = StateMgr.getContext();
+ QualType Ta = Ctx.getCanonicalType(TR->getLValueType(Ctx));
+ QualType Tb = Ctx.getCanonicalType(CastToTy);
+
+ if (Ta == Tb)
+ return CastResult(state, R);
}
-
- // Default case.
- return std::make_pair(St, UnknownVal());
+
+ const MemRegion* ViewR = MRMgr.getAnonTypedRegion(CastToTy, R);
+ return CastResult(AddRegionView(state, ViewR, R), ViewR);
}
SVal RegionStoreManager::Retrieve(const GRState* state, Loc L, QualType T) {
assert(R && "bad region");
if (const TypedRegion* TR = dyn_cast<TypedRegion>(R))
- if (TR->getType(getContext())->isStructureType())
+ if (TR->getRValueType(getContext())->isStructureType())
return RetrieveStruct(S, TR);
RegionBindingsTy B(static_cast<const RegionBindingsTy::TreeTy*>(S));
}
SVal RegionStoreManager::RetrieveStruct(Store store, const TypedRegion* R) {
- QualType T = R->getType(getContext());
+ // FIXME: Verify we want getRValueType instead of getLValueType.
+ QualType T = R->getRValueType(getContext());
assert(T->isStructureType());
const RecordType* RT = cast<RecordType>(T.getTypePtr());
assert(R);
if (const TypedRegion* TR = dyn_cast<TypedRegion>(R))
- if (TR->getType(getContext())->isStructureType())
+ // FIXME: Verify we want getRValueType().
+ if (TR->getRValueType(getContext())->isStructureType())
return BindStruct(store, TR, V);
RegionBindingsTy B = GetRegionBindings(store);
}
Store RegionStoreManager::BindStruct(Store store, const TypedRegion* R, SVal V){
- QualType T = R->getType(getContext());
+ // Verify we want getRValueType.
+ QualType T = R->getRValueType(getContext());
assert(T->isStructureType());
const RecordType* RT = cast<RecordType>(T.getTypePtr());
Store RegionStoreManager::InitializeArray(Store store, const TypedRegion* R,
SVal Init) {
- QualType T = R->getType(getContext());
+
+ // FIXME: Verify we should use getLValueType or getRValueType.
+ QualType T = R->getLValueType(getContext());
assert(T->isArrayType());
ConstantArrayType* CAT = cast<ConstantArrayType>(T.getTypePtr());
// Bind all elements of the array to some value.
Store RegionStoreManager::BindArrayToVal(Store store, const TypedRegion* BaseR,
SVal V){
- QualType T = BaseR->getType(getContext());
+
+ // FIXME: Verify we want getRValueType.
+ QualType T = BaseR->getRValueType(getContext());
assert(T->isArrayType());
// Only handle constant size array for now.
Store RegionStoreManager::BindArrayToSymVal(Store store,
const TypedRegion* BaseR) {
- QualType T = BaseR->getType(getContext());
+
+ // FIXME: Verify we want getRValueType.
+ QualType T = BaseR->getRValueType(getContext());
assert(T->isArrayType());
if (ConstantArrayType* CAT = dyn_cast<ConstantArrayType>(T.getTypePtr())) {
Store RegionStoreManager::InitializeStruct(Store store, const TypedRegion* R,
SVal Init) {
- QualType T = R->getType(getContext());
+
+ // FIXME: Verify that we should use getRValueType or getLValueType.
+ QualType T = R->getRValueType(getContext());
assert(T->isStructureType());
RecordType* RT = cast<RecordType>(T.getTypePtr());
// Bind all fields of the struct to some value.
Store RegionStoreManager::BindStructToVal(Store store, const TypedRegion* BaseR,
SVal V) {
- QualType T = BaseR->getType(getContext());
+
+ // FIXME: Verify that we should use getLValueType or getRValueType.
+ QualType T = BaseR->getRValueType(getContext());
assert(T->isStructureType());
const RecordType* RT = cast<RecordType>(T.getTypePtr());
Store RegionStoreManager::BindStructToSymVal(Store store,
const TypedRegion* BaseR) {
- QualType T = BaseR->getType(getContext());
+
+ // FIXME: Verify that we should use getLValueType or getRValueType
+ QualType T = BaseR->getRValueType(getContext());
assert(T->isStructureType());
const RecordType* RT = cast<RecordType>(T.getTypePtr());
-// XFAIL
// RUN: clang -checker-cfref -verify -triple x86_64-apple-darwin9 %s
typedef signed long CFIndex;
// RUN: clang -checker-simple -verify %s
-// RUN: clang -checker-simple -analyzer-store-region -verify %s
+// DISABLE: clang -checker-simple -analyzer-store-region -verify %s
struct s {
int data;
-// RUN: clang -checker-cfref %s --analyzer-store-basic -verify &&
-// RUN: clang -checker-cfref %s --analyzer-store-region -verify
+// RUN: clang -checker-cfref %s --analyzer-store-basic -verify
+// DISABLE: clang -checker-cfref %s --analyzer-store-region -verify
typedef int bar_return_t;
typedef struct {
-// XFAIL
// RUN: clang -checker-simple -verify %s
#include <stdlib.h>