[analyzer] Use the expression’s type instead of region’s type in ArrayToPointer decay evaluation

This gives slightly better precision, specifically, in cases where a non-typed region represents the array
or when the type is a non-array type, which can happen when an array is a result of a reinterpret_cast.

llvm-svn: 182810
This commit is contained in:
Anna Zaks 2013-05-28 23:24:01 +00:00
parent 93132f504f
commit 5416ab0156
5 changed files with 17 additions and 21 deletions

View File

@ -516,8 +516,8 @@ public:
public:
SVal ArrayToPointer(Loc Array) {
return StoreMgr->ArrayToPointer(Array);
SVal ArrayToPointer(Loc Array, QualType ElementTy) {
return StoreMgr->ArrayToPointer(Array, ElementTy);
}
// Methods that manipulate the GDM.

View File

@ -111,7 +111,7 @@ public:
/// ArrayToPointer - Used by ExprEngine::VistCast to handle implicit
/// conversions between arrays and pointers.
virtual SVal ArrayToPointer(Loc Array) = 0;
virtual SVal ArrayToPointer(Loc Array, QualType ElementTy) = 0;
/// Evaluates a chain of derived-to-base casts through the path specified in
/// \p Cast.

View File

@ -377,7 +377,7 @@ public:
/// version of that lvalue (i.e., a pointer to the first element of
/// the array). This is called by ExprEngine when evaluating
/// casts from arrays to pointers.
SVal ArrayToPointer(Loc Array);
SVal ArrayToPointer(Loc Array, QualType ElementTy);
StoreRef getInitialStore(const LocationContext *InitLoc) {
return StoreRef(RBFactory.getEmptyMap().getRootWithoutRetain(), *this);
@ -1250,26 +1250,13 @@ RegionStoreManager::getSizeInElements(ProgramStateRef state,
/// version of that lvalue (i.e., a pointer to the first element of
/// the array). This is called by ExprEngine when evaluating casts
/// from arrays to pointers.
SVal RegionStoreManager::ArrayToPointer(Loc Array) {
SVal RegionStoreManager::ArrayToPointer(Loc Array, QualType T) {
if (!Array.getAs<loc::MemRegionVal>())
return UnknownVal();
const MemRegion* R = Array.castAs<loc::MemRegionVal>().getRegion();
const TypedValueRegion* ArrayR = dyn_cast<TypedValueRegion>(R);
if (!ArrayR)
return UnknownVal();
// Strip off typedefs from the ArrayRegion's ValueType.
QualType T = ArrayR->getValueType().getDesugaredType(Ctx);
const ArrayType *AT = dyn_cast<ArrayType>(T);
if (!AT)
return UnknownVal();
T = AT->getElementType();
NonLoc ZeroIdx = svalBuilder.makeZeroArrayIndex();
return loc::MemRegionVal(MRMgr.getElementRegion(T, ZeroIdx, ArrayR, Ctx));
return loc::MemRegionVal(MRMgr.getElementRegion(T, ZeroIdx, R, Ctx));
}
//===----------------------------------------------------------------------===//

View File

@ -435,9 +435,11 @@ SVal SValBuilder::evalCast(SVal val, QualType castTy, QualType originalTy) {
}
// Check for casts from array type to another type.
if (originalTy->isArrayType()) {
if (const ArrayType *arrayT =
dyn_cast<ArrayType>(originalTy.getCanonicalType())) {
// We will always decay to a pointer.
val = StateMgr.ArrayToPointer(val.castAs<Loc>());
QualType elemTy = arrayT->getElementType();
val = StateMgr.ArrayToPointer(val.castAs<Loc>(), elemTy);
// Are we casting from an array to a pointer? If so just pass on
// the decayed value.

View File

@ -75,6 +75,13 @@ namespace PR13440 {
int (&x)[1];
int *m() { return x; }
void testArrayToPointerDecayWithNonTypedValueRegion() {
int *p = x;
int *q = x;
clang_analyzer_eval(p[0] == q[0]); // expected-warning{{TRUE}}
}
};
void test() {