r190530 - [analyzer] Handle zeroing constructors for fields of structs with empty bases.

Jordan Rose jordan_rose at apple.com
Wed Sep 11 09:46:51 PDT 2013


Author: jrose
Date: Wed Sep 11 11:46:50 2013
New Revision: 190530

URL: http://llvm.org/viewvc/llvm-project?rev=190530&view=rev
Log:
[analyzer] Handle zeroing constructors for fields of structs with empty bases.

RegionStore tries to protect against accidentally initializing the same
region twice, but it doesn't take subregions into account very well. If
the outer region being initialized is a struct with an empty base class,
the offset of the first field in the struct will be 0. When we initialize
the base class, we may invalidate the contents of the struct by providing
a default value of Unknown (or some new symbol). We then go to initialize
the member with a zeroing constructor, only to find that the region at
that offset in the struct already has a value. The best we can do here is
to invalidate that value and continue; neither the old default value nor
the new 0 is correct for the entire struct after the member constructor call.

The correct solution for this is to track region extents in the store.

<rdar://problem/14914316>

Modified:
    cfe/trunk/lib/StaticAnalyzer/Core/RegionStore.cpp
    cfe/trunk/test/Analysis/ctor.mm

Modified: cfe/trunk/lib/StaticAnalyzer/Core/RegionStore.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/StaticAnalyzer/Core/RegionStore.cpp?rev=190530&r1=190529&r2=190530&view=diff
==============================================================================
--- cfe/trunk/lib/StaticAnalyzer/Core/RegionStore.cpp (original)
+++ cfe/trunk/lib/StaticAnalyzer/Core/RegionStore.cpp Wed Sep 11 11:46:50 2013
@@ -422,11 +422,20 @@ public: // Part of public interface to c
   // BindDefault is only used to initialize a region with a default value.
   StoreRef BindDefault(Store store, const MemRegion *R, SVal V) {
     RegionBindingsRef B = getRegionBindings(store);
-    assert(!B.lookup(R, BindingKey::Default));
     assert(!B.lookup(R, BindingKey::Direct));
-    return StoreRef(B.addBinding(R, BindingKey::Default, V)
-                     .asImmutableMap()
-                     .getRootWithoutRetain(), *this);
+
+    BindingKey Key = BindingKey::Make(R, BindingKey::Default);
+    if (B.lookup(Key)) {
+      const SubRegion *SR = cast<SubRegion>(R);
+      assert(SR->getAsOffset().getOffset() ==
+             SR->getSuperRegion()->getAsOffset().getOffset() &&
+             "A default value must come from a super-region");
+      B = removeSubRegionBindings(B, SR);
+    } else {
+      B = B.addBinding(Key, V);
+    }
+
+    return StoreRef(B.asImmutableMap().getRootWithoutRetain(), *this);
   }
 
   /// Attempt to extract the fields of \p LCV and bind them to the struct region

Modified: cfe/trunk/test/Analysis/ctor.mm
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/Analysis/ctor.mm?rev=190530&r1=190529&r2=190530&view=diff
==============================================================================
--- cfe/trunk/test/Analysis/ctor.mm (original)
+++ cfe/trunk/test/Analysis/ctor.mm Wed Sep 11 11:46:50 2013
@@ -626,6 +626,30 @@ namespace ZeroInitialization {
       // initialized twice.
     }
   };
+
+  class Empty {
+  public:
+    Empty();
+  };
+
+  class PairContainer : public Empty {
+    raw_pair p;
+  public:
+    PairContainer() : Empty(), p() {
+      // This previously caused a crash because the empty base class looked
+      // like an initialization of 'p'.
+    }
+    PairContainer(int) : Empty(), p() {
+      // Test inlining something else here.
+    }
+  };
+
+  class PairContainerContainer {
+    int padding;
+    PairContainer pc;
+  public:
+    PairContainerContainer() : pc(1) {}
+  };
 }
 
 namespace InitializerList {





More information about the cfe-commits mailing list