Skip to content
Snippets Groups Projects
Commit 7f1fd2f1 authored by Anna Zaks's avatar Anna Zaks
Browse files

[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.

git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@182810 91177308-0d34-0410-b5e6-96231b3b80d8
parent 3056439b
No related branches found
No related tags found
No related merge requests found
......@@ -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() {
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment