]> granicus.if.org Git - clang/commitdiff
Augment RegionStore::BindStruct() to bind symbolicated struct values. This fixes...
authorTed Kremenek <kremenek@apple.com>
Thu, 29 Jul 2010 00:28:47 +0000 (00:28 +0000)
committerTed Kremenek <kremenek@apple.com>
Thu, 29 Jul 2010 00:28:47 +0000 (00:28 +0000)
git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@109710 91177308-0d34-0410-b5e6-96231b3b80d8

lib/Checker/RegionStore.cpp
test/Analysis/misc-ps-region-store.m
test/Analysis/uninit-vals-ps-region.m

index 74a7fee048890151374d0b56a10dcdbb088820d6..7d708f887727af873135b18b63adf21914b3ca58 100644 (file)
@@ -289,7 +289,7 @@ public: // Part of public interface to class.
   Store BindArray(Store store, const TypedRegion* R, SVal V);
 
   /// KillStruct - Set the entire struct to unknown.
-  Store KillStruct(Store store, const TypedRegion* R);
+  Store KillStruct(Store store, const TypedRegion* R, SVal DefaultVal);
 
   Store Remove(Store store, Loc LV);
 
@@ -1560,10 +1560,11 @@ Store RegionStoreManager::BindStruct(Store store, const TypedRegion* R,
   if (const nonloc::LazyCompoundVal *LCV=dyn_cast<nonloc::LazyCompoundVal>(&V))
     return CopyLazyBindings(*LCV, store, R);
 
-  // We may get non-CompoundVal accidentally due to imprecise cast logic.
-  // Ignore them and kill the field values.
+  // We may get non-CompoundVal accidentally due to imprecise cast logic or
+  // that we are binding symbolic struct value. Kill the field values, and if
+  // the value is symbolic go and bind it as a "default" binding.
   if (V.isUnknown() || !isa<nonloc::CompoundVal>(V))
-    return KillStruct(store, R);
+    return KillStruct(store, R, isa<nonloc::SymbolVal>(V) ? V : UnknownVal());
 
   nonloc::CompoundVal& CV = cast<nonloc::CompoundVal>(V);
   nonloc::CompoundVal::iterator VI = CV.begin(), VE = CV.end();
@@ -1596,14 +1597,15 @@ Store RegionStoreManager::BindStruct(Store store, const TypedRegion* R,
   return store;
 }
 
-Store RegionStoreManager::KillStruct(Store store, const TypedRegion* R) {
+Store RegionStoreManager::KillStruct(Store store, const TypedRegion* R,
+                                     SVal DefaultVal) {
   RegionBindings B = GetRegionBindings(store);
   llvm::OwningPtr<RegionStoreSubRegionMap>
     SubRegions(getRegionStoreSubRegionMap(store));
   RemoveSubRegionBindings(B, R, *SubRegions);
 
   // Set the default value of the struct region to "unknown".
-  return Add(B, R, BindingKey::Default, UnknownVal()).getRoot();
+  return Add(B, R, BindingKey::Default, DefaultVal).getRoot();
 }
 
 Store RegionStoreManager::CopyLazyBindings(nonloc::LazyCompoundVal V,
index 6b4f658a3f8564c6800824c7dcfb746eb7d2bf6c..e8b9533de5ef60d9a469903bda0cc0c0913658b3 100644 (file)
@@ -1041,3 +1041,19 @@ void pr_7450() {
   pr_7450_aux(p + 8);
 }
 
+// <rdar://problem/8243408> - Symbolicate struct values returned by value.
+struct s_rdar_8243408 { int x; };
+extern struct s_rdar_8243408 rdar_8243408_aux(void);
+void rdar_8243408(void) {
+  struct s_rdar_8243408 a = { 1 }, *b = 0;
+  while (a.x && !b)
+    a = rdar_8243408_aux();
+
+  // Previously there was a false error here with 'b' being null.
+  (void) (a.x && b->x); // no-warning
+
+  // Introduce a null deref to ensure we are checking this path.
+  int *p = 0;
+  *p = 0xDEADBEEF; // expected-warning{{Dereference of null pointer}}
+}
+
index 69c1ecd1e3a65953950e0af910d8f73c64349570..ae8f1322f4f5cdb1e5a59f69c9c2edb3f9e0d55b 100644 (file)
@@ -42,7 +42,7 @@ void test_uninit_pos_3() {
 void test_uninit_neg() {
   struct TestUninit v1 = { 0, 0 };
   struct TestUninit v2 = test_uninit_aux();
-  test_unit_aux2(v2.x + v1.y); // no-warning
+  test_unit_aux2(v2.x + v1.y); // expected-warning{{The right operand to '+' is always 0}}
 }
 
 extern void test_uninit_struct_arg_aux(struct TestUninit arg);