From: Ted Kremenek Date: Tue, 26 Jan 2010 23:51:00 +0000 (+0000) Subject: Teach RegionStore to handle initialization of incomplete arrays in structures using... X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=fee90811c665893bc27a9bfa8b116548afe1b89b;p=clang Teach RegionStore to handle initialization of incomplete arrays in structures using a compound value. Fixes . git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@94622 91177308-0d34-0410-b5e6-96231b3b80d8 --- diff --git a/include/clang/Analysis/Support/Optional.h b/include/clang/Analysis/Support/Optional.h index 40f38be020..b98d382700 100644 --- a/include/clang/Analysis/Support/Optional.h +++ b/include/clang/Analysis/Support/Optional.h @@ -20,7 +20,7 @@ namespace clang { template class Optional { - const T x; + T x; unsigned hasVal : 1; public: explicit Optional() : hasVal(false) {} @@ -30,9 +30,17 @@ public: return y ? Optional(*y) : Optional(); } + Optional &operator=(const T &y) { + x = y; + hasVal = true; + return *this; + } + const T* getPointer() const { assert(hasVal); return &x; } + const T& getValue() const { assert(hasVal); return x; } operator bool() const { return hasVal; } + bool hasValue() const { return hasVal; } const T* operator->() const { return getPointer(); } const T& operator*() const { assert(hasVal); return x; } }; diff --git a/lib/Checker/RegionStore.cpp b/lib/Checker/RegionStore.cpp index 39686c22df..7fb9c0fd1b 100644 --- a/lib/Checker/RegionStore.cpp +++ b/lib/Checker/RegionStore.cpp @@ -1572,13 +1572,16 @@ const GRState *RegionStoreManager::setImplicitDefaultValue(const GRState *state, const GRState *RegionStoreManager::BindArray(const GRState *state, const TypedRegion* R, SVal Init) { - - QualType T = R->getValueType(getContext()); - ConstantArrayType* CAT = cast(T.getTypePtr()); - QualType ElementTy = CAT->getElementType(); - - uint64_t size = CAT->getSize().getZExtValue(); - + + ASTContext &Ctx = getContext(); + const ArrayType *AT = + cast(Ctx.getCanonicalType(R->getValueType(Ctx))); + QualType ElementTy = AT->getElementType(); + Optional Size; + + if (const ConstantArrayType* CAT = dyn_cast(AT)) + Size = CAT->getSize().getZExtValue(); + // Check if the init expr is a StringLiteral. if (isa(Init)) { const MemRegion* InitR = cast(Init).getRegion(); @@ -1590,6 +1593,11 @@ const GRState *RegionStoreManager::BindArray(const GRState *state, // Copy bytes from the string literal into the target array. Trailing bytes // in the array that are not covered by the string literal are initialized // to zero. + + // We assume that string constants are bound to + // constant arrays. + uint64_t size = Size; + for (uint64_t i = 0; i < size; ++i, ++j) { if (j >= len) break; @@ -1618,7 +1626,7 @@ const GRState *RegionStoreManager::BindArray(const GRState *state, nonloc::CompoundVal::iterator VI = CV.begin(), VE = CV.end(); uint64_t i = 0; - for (; i < size; ++i, ++VI) { + for (; Size.hasValue() ? i < Size.getValue() : true ; ++i, ++VI) { // The init list might be shorter than the array length. if (VI == VE) break; @@ -1626,16 +1634,15 @@ const GRState *RegionStoreManager::BindArray(const GRState *state, SVal Idx = ValMgr.makeArrayIndex(i); const ElementRegion *ER = MRMgr.getElementRegion(ElementTy, Idx, R, getContext()); - if (CAT->getElementType()->isStructureType()) + if (ElementTy->isStructureType()) state = BindStruct(state, ER, *VI); else - // FIXME: Do we need special handling of nested arrays? state = Bind(state, ValMgr.makeLoc(ER), *VI); } // If the init list is shorter than the array length, set the // array default value. - if (i < size) + if (Size.hasValue() && i < Size.getValue()) state = setImplicitDefaultValue(state, R, ElementTy); return state; diff --git a/test/Analysis/misc-ps-region-store.m b/test/Analysis/misc-ps-region-store.m index a88c26c29e..a87d2ed1db 100644 --- a/test/Analysis/misc-ps-region-store.m +++ b/test/Analysis/misc-ps-region-store.m @@ -730,3 +730,31 @@ void rdar_7527292() { } } +//===----------------------------------------------------------------------===// +// - Handle initialization of incomplete arrays +// in structures using a compound value. Previously this crashed. +//===----------------------------------------------------------------------===// + +struct rdar_7515938 { + int x; + int y[]; +}; + +const struct rdar_7515938 *rdar_7515938() { + static const struct rdar_7515938 z = { 0, { 1, 2 } }; + if (z.y[0] != 1) { + int *p = 0; + *p = 0xDEADBEEF; // no-warning + } + return &z; +} + +struct rdar_7515938_str { + int x; + char y[]; +}; + +const struct rdar_7515938_str *rdar_7515938_str() { + static const struct rdar_7515938_str z = { 0, "hello" }; + return &z; +}