aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--include/clang/Analysis/PathSensitive/MemRegion.h14
-rw-r--r--lib/Analysis/BasicStore.cpp23
-rw-r--r--lib/Analysis/GRExprEngine.cpp12
-rw-r--r--lib/Analysis/MemRegion.cpp8
-rw-r--r--lib/Analysis/RegionStore.cpp16
-rw-r--r--test/Analysis/rdar-6442306-1.m31
6 files changed, 79 insertions, 25 deletions
diff --git a/include/clang/Analysis/PathSensitive/MemRegion.h b/include/clang/Analysis/PathSensitive/MemRegion.h
index 5da0ccafc2..b1318f7da8 100644
--- a/include/clang/Analysis/PathSensitive/MemRegion.h
+++ b/include/clang/Analysis/PathSensitive/MemRegion.h
@@ -424,7 +424,7 @@ class ElementRegion : public TypedRegion {
cast<nonloc::ConcreteInt>(&Idx)->getValue().isSigned()) &&
"The index must be signed");
}
-
+
static void ProfileRegion(llvm::FoldingSetNodeID& ID, SVal Idx,
const MemRegion* superRegion);
@@ -434,6 +434,13 @@ public:
QualType getType(ASTContext&) const;
+ /// getArrayRegion - Return the region of the enclosing array. This is
+ /// the same as getSuperRegion() except that this returns a TypedRegion*
+ /// instead of a MemRegion*.
+ const TypedRegion* getArrayRegion() const {
+ return cast<TypedRegion>(getSuperRegion());
+ }
+
void print(llvm::raw_ostream& os) const;
void Profile(llvm::FoldingSetNodeID& ID) const;
@@ -500,13 +507,14 @@ public:
/// a specified VarDecl.
VarRegion* getVarRegion(const VarDecl* vd);
- ElementRegion* getElementRegion(SVal Idx, const MemRegion* superRegion);
+ ElementRegion* getElementRegion(SVal Idx, const TypedRegion* superRegion);
/// getFieldRegion - Retrieve or create the memory region associated with
/// a specified FieldDecl. 'superRegion' corresponds to the containing
/// memory region (which typically represents the memory representing
/// a structure or class).
- FieldRegion* getFieldRegion(const FieldDecl* fd, const MemRegion* superRegion);
+ FieldRegion* getFieldRegion(const FieldDecl* fd,
+ const MemRegion* superRegion);
/// getObjCObjectRegion - Retrieve or create the memory region associated with
/// the instance of a specified Objective-C class.
diff --git a/lib/Analysis/BasicStore.cpp b/lib/Analysis/BasicStore.cpp
index 207f609609..91d85c4c2b 100644
--- a/lib/Analysis/BasicStore.cpp
+++ b/lib/Analysis/BasicStore.cpp
@@ -171,7 +171,7 @@ SVal BasicStoreManager::getLValueElement(const GRState* St, SVal Base,
return Base;
Loc BaseL = cast<Loc>(Base);
- const MemRegion* BaseR = 0;
+ const TypedRegion* BaseR = 0;
switch(BaseL.getSubKind()) {
case loc::SymbolValKind: {
@@ -194,9 +194,19 @@ SVal BasicStoreManager::getLValueElement(const GRState* St, SVal Base,
// Technically we can get here if people do funny things with casts.
return UndefinedVal();
- case loc::MemRegionKind:
- BaseR = cast<loc::MemRegionVal>(BaseL).getRegion();
+ case loc::MemRegionKind: {
+ const MemRegion *R = cast<loc::MemRegionVal>(BaseL).getRegion();
+ if (const TypedRegion *TR = dyn_cast<TypedRegion>(R)) {
+ BaseR = TR;
+ break;
+ }
+
+ // FIXME: Handle SymbolRegions? Shouldn't be possible in
+ // BasicStoreManager.
+ assert(!isa<SymbolicRegion>(R));
+
break;
+ }
case loc::ConcreteIntKind:
// While these seem funny, this can happen through casts.
@@ -210,9 +220,10 @@ SVal BasicStoreManager::getLValueElement(const GRState* St, SVal Base,
return Base;
}
- // We return an "unknown" index because we aren't reasoning about indices
- // at all.
- return loc::MemRegionVal(MRMgr.getElementRegion(UnknownVal(), BaseR));
+ if (BaseR)
+ return loc::MemRegionVal(MRMgr.getElementRegion(UnknownVal(), BaseR));
+ else
+ return UnknownVal();
}
SVal BasicStoreManager::Retrieve(const GRState* state, Loc LV, QualType T) {
diff --git a/lib/Analysis/GRExprEngine.cpp b/lib/Analysis/GRExprEngine.cpp
index 96776b46ff..74e1a07631 100644
--- a/lib/Analysis/GRExprEngine.cpp
+++ b/lib/Analysis/GRExprEngine.cpp
@@ -1731,7 +1731,7 @@ void GRExprEngine::VisitCast(Expr* CastE, Expr* Ex, NodeTy* Pred, NodeSet& Dst){
continue;
}
- // Check for casts from AllocaRegion pointer to typed pointer.
+ // Check for casts from a pointer to a region to typed pointer.
if (isa<loc::MemRegionVal>(V)) {
assert(Loc::IsLocType(T));
assert(Loc::IsLocType(ExTy));
@@ -1740,14 +1740,8 @@ void GRExprEngine::VisitCast(Expr* CastE, Expr* Ex, NodeTy* Pred, NodeSet& Dst){
std::pair<const GRState*, SVal> Res =
getStoreManager().CastRegion(St, V, T, CastE);
- const GRState* NewSt = Res.first;
- SVal NewPtr = Res.second;
-
- // If no new region is created, fall through to the default case.
- if (NewSt != St) {
- MakeNode(Dst, CastE, N, BindExpr(NewSt, CastE, NewPtr));
- continue;
- }
+ MakeNode(Dst, CastE, N, BindExpr(Res.first, CastE, Res.second));
+ continue;
}
// All other cases.
diff --git a/lib/Analysis/MemRegion.cpp b/lib/Analysis/MemRegion.cpp
index 1e580a8cd3..94ffb3f152 100644
--- a/lib/Analysis/MemRegion.cpp
+++ b/lib/Analysis/MemRegion.cpp
@@ -107,14 +107,13 @@ void ElementRegion::Profile(llvm::FoldingSetNodeID& ID) const {
}
QualType ElementRegion::getType(ASTContext& C) const {
- QualType T = cast<TypedRegion>(superRegion)->getType(C);
+ QualType T = getArrayRegion()->getType(C);
if (isa<ArrayType>(T.getTypePtr())) {
ArrayType* AT = cast<ArrayType>(T.getTypePtr());
return AT->getElementType();
}
else {
- assert (isa<AnonTypedRegion>(superRegion));
PointerType* PtrT = cast<PointerType>(T.getTypePtr());
QualType PTy = PtrT->getPointeeType();
return C.getCanonicalType(PTy);
@@ -278,8 +277,9 @@ MemRegionManager::getCompoundLiteralRegion(const CompoundLiteralExpr* CL) {
return R;
}
-ElementRegion* MemRegionManager::getElementRegion(SVal Idx,
- const MemRegion* superRegion){
+ElementRegion*
+MemRegionManager::getElementRegion(SVal Idx, const TypedRegion* superRegion){
+
llvm::FoldingSetNodeID ID;
ElementRegion::ProfileRegion(ID, Idx, superRegion);
diff --git a/lib/Analysis/RegionStore.cpp b/lib/Analysis/RegionStore.cpp
index e065c5c410..defa80f324 100644
--- a/lib/Analysis/RegionStore.cpp
+++ b/lib/Analysis/RegionStore.cpp
@@ -287,7 +287,7 @@ SVal RegionStoreManager::getLValueElement(const GRState* St,
SVal NewIdx = CI1->EvalBinOp(getBasicVals(), BinaryOperator::Add, *CI2);
return loc::MemRegionVal(MRMgr.getElementRegion(NewIdx,
- ElemR->getSuperRegion()));
+ ElemR->getArrayRegion()));
}
return UnknownVal();
@@ -360,8 +360,18 @@ SVal RegionStoreManager::getSizeInElements(const GRState* St,
// Cast 'pointer to array' to 'pointer to the first element of array'.
SVal RegionStoreManager::ArrayToPointer(SVal Array) {
- const MemRegion* ArrayR = cast<loc::MemRegionVal>(&Array)->getRegion();
-
+ if (Array.isUnknownOrUndef())
+ return Array;
+
+ if (!isa<loc::MemRegionVal>(Array))
+ return UnknownVal();
+
+ const MemRegion* R = cast<loc::MemRegionVal>(&Array)->getRegion();
+ const TypedRegion* ArrayR = dyn_cast<TypedRegion>(R);
+
+ if (ArrayR)
+ return UnknownVal();
+
nonloc::ConcreteInt Idx(getBasicVals().getZeroWithPtrWidth(false));
ElementRegion* ER = MRMgr.getElementRegion(Idx, ArrayR);
diff --git a/test/Analysis/rdar-6442306-1.m b/test/Analysis/rdar-6442306-1.m
new file mode 100644
index 0000000000..fa8f0aa168
--- /dev/null
+++ b/test/Analysis/rdar-6442306-1.m
@@ -0,0 +1,31 @@
+// RUN: clang -checker-cfref %s --analyzer-store-basic -verify &&
+// RUN: clang -checker-cfref %s --analyzer-store-region -verify
+
+typedef int bar_return_t;
+typedef struct {
+ unsigned char int_rep;
+} Foo_record_t;
+extern Foo_record_t Foo_record;
+struct QuxSize {};
+typedef struct QuxSize QuxSize;
+typedef struct {
+ Foo_record_t Foo;
+ QuxSize size;
+} __Request__SetPortalSize_t;
+
+static __inline__ bar_return_t
+__Beeble_check__Request__SetPortalSize_t(__attribute__((__unused__)) __Request__SetPortalSize_t *In0P) {
+ if (In0P->Foo.int_rep != Foo_record.int_rep) {
+ do {
+ int __i__, __C__ = (2);
+ for (__i__ = 0;
+ __i__ < __C__;
+ __i__++) do {
+ *(&((double *)(&In0P->size))[__i__]) =
+ __Foo_READSWAP__double(&((double *)(&In0P->size))[__i__]);
+ }
+ while (0);
+ }
+ while (0);
+ }
+}