diff options
-rw-r--r-- | include/clang/Analysis/PathSensitive/MemRegion.h | 14 | ||||
-rw-r--r-- | lib/Analysis/BasicStore.cpp | 23 | ||||
-rw-r--r-- | lib/Analysis/GRExprEngine.cpp | 12 | ||||
-rw-r--r-- | lib/Analysis/MemRegion.cpp | 8 | ||||
-rw-r--r-- | lib/Analysis/RegionStore.cpp | 16 | ||||
-rw-r--r-- | test/Analysis/rdar-6442306-1.m | 31 |
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); + } +} |