[cfe-commits] r94622 - in /cfe/trunk: include/clang/Analysis/Support/Optional.h lib/Checker/RegionStore.cpp test/Analysis/misc-ps-region-store.m

Ted Kremenek kremenek at apple.com
Tue Jan 26 15:51:00 PST 2010


Author: kremenek
Date: Tue Jan 26 17:51:00 2010
New Revision: 94622

URL: http://llvm.org/viewvc/llvm-project?rev=94622&view=rev
Log:
Teach RegionStore to handle initialization of incomplete arrays in structures using a compound value.  Fixes <rdar://problem/7515938>.

Modified:
    cfe/trunk/include/clang/Analysis/Support/Optional.h
    cfe/trunk/lib/Checker/RegionStore.cpp
    cfe/trunk/test/Analysis/misc-ps-region-store.m

Modified: cfe/trunk/include/clang/Analysis/Support/Optional.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Analysis/Support/Optional.h?rev=94622&r1=94621&r2=94622&view=diff

==============================================================================
--- cfe/trunk/include/clang/Analysis/Support/Optional.h (original)
+++ cfe/trunk/include/clang/Analysis/Support/Optional.h Tue Jan 26 17:51:00 2010
@@ -20,7 +20,7 @@
 
 template<typename T>
 class Optional {
-  const T x;
+  T x;
   unsigned hasVal : 1;
 public:
   explicit Optional() : hasVal(false) {}
@@ -30,9 +30,17 @@
     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; }
 };

Modified: cfe/trunk/lib/Checker/RegionStore.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Checker/RegionStore.cpp?rev=94622&r1=94621&r2=94622&view=diff

==============================================================================
--- cfe/trunk/lib/Checker/RegionStore.cpp (original)
+++ cfe/trunk/lib/Checker/RegionStore.cpp Tue Jan 26 17:51:00 2010
@@ -1572,13 +1572,16 @@
 const GRState *RegionStoreManager::BindArray(const GRState *state,
                                              const TypedRegion* R,
                                              SVal Init) {
-
-  QualType T = R->getValueType(getContext());
-  ConstantArrayType* CAT = cast<ConstantArrayType>(T.getTypePtr());
-  QualType ElementTy = CAT->getElementType();
-
-  uint64_t size = CAT->getSize().getZExtValue();
-
+  
+  ASTContext &Ctx = getContext();
+  const ArrayType *AT =
+    cast<ArrayType>(Ctx.getCanonicalType(R->getValueType(Ctx)));
+  QualType ElementTy = AT->getElementType();  
+  Optional<uint64_t> Size;
+  
+  if (const ConstantArrayType* CAT = dyn_cast<ConstantArrayType>(AT))
+    Size = CAT->getSize().getZExtValue();
+    
   // Check if the init expr is a StringLiteral.
   if (isa<loc::MemRegionVal>(Init)) {
     const MemRegion* InitR = cast<loc::MemRegionVal>(Init).getRegion();
@@ -1590,6 +1593,11 @@
     // 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 @@
   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 @@
     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;

Modified: cfe/trunk/test/Analysis/misc-ps-region-store.m
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/Analysis/misc-ps-region-store.m?rev=94622&r1=94621&r2=94622&view=diff

==============================================================================
--- cfe/trunk/test/Analysis/misc-ps-region-store.m (original)
+++ cfe/trunk/test/Analysis/misc-ps-region-store.m Tue Jan 26 17:51:00 2010
@@ -730,3 +730,31 @@
   }
 }
 
+//===----------------------------------------------------------------------===//
+// <rdar://problem/7515938> - 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;
+}





More information about the cfe-commits mailing list