protected:
MemRegion(Kind k) : kind(k) {}
virtual ~MemRegion();
- ASTContext &getContext() const;
public:
+ ASTContext &getContext() const;
+
virtual void Profile(llvm::FoldingSetNodeID& ID) const = 0;
virtual MemRegionManager* getMemRegionManager() const = 0;
// Loading values from regions.
//===----------------------------------------------------------------------===//
+static bool IsReinterpreted(QualType RTy, QualType UsedTy, ASTContext &Ctx) {
+ RTy = Ctx.getCanonicalType(RTy);
+ UsedTy = Ctx.getCanonicalType(UsedTy);
+
+ if (RTy == UsedTy)
+ return false;
+
+ return !(Loc::IsLocType(RTy) && Loc::IsLocType(UsedTy));
+}
+
SVal RegionStoreManager::Retrieve(const GRState *state, Loc L, QualType T) {
assert(!isa<UnknownVal>(L) && "location unknown");
if (isa<SymbolicRegion>(MR)) {
ASTContext &Ctx = getContext();
SVal idx = ValMgr.makeIntVal(0, Ctx.IntTy);
+ assert(!T.isNull());
MR = MRMgr.getElementRegion(T, idx, MR, Ctx);
}
// 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.
const TypedRegion *R = cast<TypedRegion>(MR);
- assert(R && "bad region");
+ QualType RTy = R->getValueType(getContext());
// FIXME: We should eventually handle funny addressing. e.g.:
//
//
// Such funny addressing will occur due to layering of regions.
- QualType RTy = R->getValueType(getContext());
+ ASTContext &Ctx = getContext();
+ if (!T.isNull() && IsReinterpreted(RTy, T, Ctx)) {
+ SVal idx = ValMgr.makeIntVal(0, Ctx.IntTy);
+ R = MRMgr.getElementRegion(T, idx, R, Ctx);
+ RTy = T;
+ assert(RTy == R->getValueType(Ctx));
+ }
if (RTy->isStructureType())
return RetrieveStruct(state, R);
}
// Check if the super region has a binding.
- if (B.lookup(superR)) {
- // We do not extract the bit value from super region for now.
+ if (const SVal *V = B.lookup(superR)) {
+ if (SymbolRef parentSym = V->getAsSymbol())
+ return ValMgr.getDerivedRegionValueSymbolVal(parentSym, R);
+
+ // Other cases: give up.
return UnknownVal();
}
}
const TypedRegion *TR = cast<TypedRegion>(R);
+ QualType T = TR->getValueType(Ctx);
- QualType T;
-
- // If the region is cast to another type, use that type.
+ // If the region is cast to another type, use that type.
if (const QualType *CastTy = getCastType(state, R)) {
assert(!(*CastTy)->isObjCObjectPointerType());
- T = (*CastTy)->getAsPointerType()->getPointeeType();
- } else
- T = TR->getValueType(Ctx);
+ QualType NewT = (*CastTy)->getAsPointerType()->getPointeeType();
+ // The only exception is if the original region had a location type as its
+ // value type we always want to treat the region as binding to a location.
+ // This issue can arise when pointers are casted to integers and back.
+ if (!Loc::IsLocType(T) || Loc::IsLocType(NewT))
+ T = NewT;
+ }
+
if (Loc::IsLocType(T) || (T->isIntegerType() && T->isScalarType())) {
SVal V = ValMgr.getConjuredSymbolVal(E, T, Count);
return Bind(state, ValMgr.makeLoc(TR), V);
// RUN: clang-cc -triple i386-apple-darwin9 -analyze -checker-cfref --analyzer-store=region --verify -fblocks %s
-typedef struct _BStruct { void *grue; } BStruct;
-void testB_aux(void *ptr);
-void testB(BStruct *b) {
- {
- int *__gruep__ = ((int *)&((b)->grue));
- int __gruev__ = *__gruep__;
- int __gruev2__ = *__gruep__;
- if (__gruev__ != __gruev2__) {
- int *p = 0;
- *p = 0xDEADBEEF;
- }
-
- testB_aux(__gruep__);
- }
- {
- int *__gruep__ = ((int *)&((b)->grue));
- int __gruev__ = *__gruep__;
- int __gruev2__ = *__gruep__;
- if (__gruev__ != __gruev2__) {
- int *p = 0;
- *p = 0xDEADBEEF;
- }
-
- if (~0 != __gruev__) {}
- }
+// Here is a case where a pointer is treated as integer, invalidated as an
+// integer, and then used again as a pointer. This test just makes sure
+// we don't crash.
+typedef unsigned uintptr_t;
+void test_pointer_invalidated_as_int_aux(uintptr_t* ptr);
+void test_pointer_invalidated_as_int() {
+ void *x;
+ test_pointer_invalidated_as_int_aux((uintptr_t*) &x);
+ // Here we have a pointer to integer cast.
+ uintptr_t y = (uintptr_t) x;
}
// RUN: clang-cc -triple x86_64-apple-darwin9 -analyze -checker-cfref --analyzer-store=region --verify -fblocks %s
-// This test case appears in misc-ps-region-store-i386.m, but fails under x86_64.
-// The reason is that 'int' is smaller than a pointer on a 64-bit architecture,
-// and we aren't reasoning yet about just the first 32-bits of the pointer.
-typedef struct _BStruct { void *grue; } BStruct;
-void testB_aux(void *ptr);
-void testB(BStruct *b) {
- {
- int *__gruep__ = ((int *)&((b)->grue));
- int __gruev__ = *__gruep__;
- int __gruev2__ = *__gruep__;
- if (__gruev__ != __gruev2__) {
- int *p = 0;
- *p = 0xDEADBEEF; // no-warning
- }
-
- testB_aux(__gruep__);
- }
- {
- int *__gruep__ = ((int *)&((b)->grue));
- int __gruev__ = *__gruep__;
- int __gruev2__ = *__gruep__;
- if (__gruev__ != __gruev2__) {
- int *p = 0;
- *p = 0xDEADBEEF; // expected-warning{{null}}
- }
-
- if (~0 != __gruev__) {}
- }
+// Here is a case where a pointer is treated as integer, invalidated as an
+// integer, and then used again as a pointer. This test just makes sure
+// we don't crash.
+typedef unsigned long uintptr_t;
+void test_pointer_invalidated_as_int_aux(uintptr_t* ptr);
+void test_pointer_invalidated_as_int() {
+ void *x;
+ test_pointer_invalidated_as_int_aux((uintptr_t*) &x);
+ // Here we have a pointer to integer cast.
+ uintptr_t y = (uintptr_t) x;
}
+
void testB_aux(void *ptr);
void testB(BStruct *b) {
- // This case has moved to 'misc-ps-region-store-i386.m' and
- // 'misc-ps-region-store-x86_64.m'. It succeeds under x86_64. When it
- // passes it both, pull it in here.
+ {
+ int *__gruep__ = ((int *)&((b)->grue));
+ int __gruev__ = *__gruep__;
+ int __gruev2__ = *__gruep__;
+ if (__gruev__ != __gruev2__) {
+ int *p = 0;
+ *p = 0xDEADBEEF; // no-warning
+ }
+
+ testB_aux(__gruep__);
+ }
+ {
+ int *__gruep__ = ((int *)&((b)->grue));
+ int __gruev__ = *__gruep__;
+ int __gruev2__ = *__gruep__;
+ if (__gruev__ != __gruev2__) {
+ int *p = 0;
+ *p = 0xDEADBEEF; // no-warning
+ }
+
+ if (~0 != __gruev__) {}
+ }
}
void testB_2(BStruct *b) {