diff --git a/clang/include/clang/StaticAnalyzer/Core/PathSensitive/ProgramState.h b/clang/include/clang/StaticAnalyzer/Core/PathSensitive/ProgramState.h index 42ef1db45591..ed1ab8c4cb45 100644 --- a/clang/include/clang/StaticAnalyzer/Core/PathSensitive/ProgramState.h +++ b/clang/include/clang/StaticAnalyzer/Core/PathSensitive/ProgramState.h @@ -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. diff --git a/clang/include/clang/StaticAnalyzer/Core/PathSensitive/Store.h b/clang/include/clang/StaticAnalyzer/Core/PathSensitive/Store.h index 230ce1ea5cf1..5b167084e253 100644 --- a/clang/include/clang/StaticAnalyzer/Core/PathSensitive/Store.h +++ b/clang/include/clang/StaticAnalyzer/Core/PathSensitive/Store.h @@ -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. diff --git a/clang/lib/StaticAnalyzer/Core/RegionStore.cpp b/clang/lib/StaticAnalyzer/Core/RegionStore.cpp index 729fc009fe80..00a6f7119042 100644 --- a/clang/lib/StaticAnalyzer/Core/RegionStore.cpp +++ b/clang/lib/StaticAnalyzer/Core/RegionStore.cpp @@ -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()) return UnknownVal(); const MemRegion* R = Array.castAs().getRegion(); - const TypedValueRegion* ArrayR = dyn_cast(R); - - if (!ArrayR) - return UnknownVal(); - - // Strip off typedefs from the ArrayRegion's ValueType. - QualType T = ArrayR->getValueType().getDesugaredType(Ctx); - const ArrayType *AT = dyn_cast(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)); } //===----------------------------------------------------------------------===// diff --git a/clang/lib/StaticAnalyzer/Core/SValBuilder.cpp b/clang/lib/StaticAnalyzer/Core/SValBuilder.cpp index 9d77a3ef58fb..ecfceaa0f3cf 100644 --- a/clang/lib/StaticAnalyzer/Core/SValBuilder.cpp +++ b/clang/lib/StaticAnalyzer/Core/SValBuilder.cpp @@ -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(originalTy.getCanonicalType())) { // We will always decay to a pointer. - val = StateMgr.ArrayToPointer(val.castAs()); + QualType elemTy = arrayT->getElementType(); + val = StateMgr.ArrayToPointer(val.castAs(), elemTy); // Are we casting from an array to a pointer? If so just pass on // the decayed value. diff --git a/clang/test/Analysis/reference.cpp b/clang/test/Analysis/reference.cpp index 1dabe7bc1a3d..bd5eaaa30909 100644 --- a/clang/test/Analysis/reference.cpp +++ b/clang/test/Analysis/reference.cpp @@ -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() {