forked from OSchip/llvm-project
[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:
parent
93132f504f
commit
5416ab0156
|
@ -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.
|
||||
|
|
|
@ -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.
|
||||
|
|
|
@ -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));
|
||||
}
|
||||
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
|
|
@ -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.
|
||||
|
|
|
@ -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() {
|
||||
|
|
Loading…
Reference in New Issue