]> granicus.if.org Git - clang/commitdiff
[analyzer] Do not believe lazy binding when symbolic region types do not match
authorAnna Zaks <ganna@apple.com>
Tue, 19 Mar 2013 22:38:09 +0000 (22:38 +0000)
committerAnna Zaks <ganna@apple.com>
Tue, 19 Mar 2013 22:38:09 +0000 (22:38 +0000)
This fixes a crash when analyzing LLVM that was exposed by r177220 (modeling of
trivial copy/move assignment operators).

When we look up a lazy binding for “Builder”, we see the direct binding of Loc at offset 0.
Previously, we believed the binding, which led to a crash. Now, we do not believe it as
the types do not match.

git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@177453 91177308-0d34-0410-b5e6-96231b3b80d8

lib/StaticAnalyzer/Core/RegionStore.cpp
test/Analysis/region-store.cpp [new file with mode: 0644]
test/Analysis/uninit-vals.m

index 82db23dd6b8e0a1e96c415180feccf0136f1900a..731c3ed8ccb607283f9b216ef60545efe44ca917 100644 (file)
@@ -1265,6 +1265,17 @@ SVal RegionStoreManager::getBinding(RegionBindingsConstRef B, Loc L, QualType T)
   return svalBuilder.getRegionValueSymbolVal(R);
 }
 
+static QualType getUnderlyingType(const SubRegion *R) {
+  QualType RegionTy;
+  if (const TypedValueRegion *TVR = dyn_cast<TypedValueRegion>(R))
+    RegionTy = TVR->getValueType();
+
+  if (const SymbolicRegion *SR = dyn_cast<SymbolicRegion>(R))
+    RegionTy = SR->getSymbol()->getType();
+
+  return RegionTy;
+}
+
 /// Checks to see if store \p B has a lazy binding for region \p R.
 ///
 /// If \p AllowSubregionBindings is \c false, a lazy binding will be rejected
@@ -1283,11 +1294,11 @@ getExistingLazyBinding(SValBuilder &SVB, RegionBindingsConstRef B,
   if (!LCV)
     return None;
 
-  // If the LCV is for a subregion, the types won't match, and we shouldn't
-  // reuse the binding. Unfortuately we can only check this if the destination
-  // region is a TypedValueRegion.
-  if (const TypedValueRegion *TVR = dyn_cast<TypedValueRegion>(R)) {
-    QualType RegionTy = TVR->getValueType();
+  // If the LCV is for a subregion, the types might not match, and we shouldn't
+  // reuse the binding.
+  QualType RegionTy = getUnderlyingType(R);
+  if (!RegionTy.isNull() &&
+      !RegionTy->isVoidPointerType()) {
     QualType SourceRegionTy = LCV->getRegion()->getValueType();
     if (!SVB.getContext().hasSameUnqualifiedType(RegionTy, SourceRegionTy))
       return None;
diff --git a/test/Analysis/region-store.cpp b/test/Analysis/region-store.cpp
new file mode 100644 (file)
index 0000000..5ea5c3f
--- /dev/null
@@ -0,0 +1,28 @@
+// RUN: %clang_cc1 -analyze -analyzer-checker=core,unix -verify %s
+// expected-no-diagnostics
+
+class Loc {
+  int x;
+};
+class P1 {
+public:
+  Loc l;
+  void setLoc(Loc L) {
+    l = L;
+  }
+  
+};
+class P2 {
+public:
+  int m;
+  int accessBase() {
+    return m;
+  }
+};
+class Derived: public P1, public P2 {
+};
+int radar13445834(Derived *Builder, Loc l) {
+  Builder->setLoc(l);
+  return Builder->accessBase();
+  
+}
\ No newline at end of file
index 6813b8ebf8d5670ce4e0b8c191ad05c9bb496a5b..9f611ade69b3df400fba31c54c150a61d5b8f791 100644 (file)
@@ -80,12 +80,8 @@ void PR14765_incorrectBehavior(Circle *testObj) {
 
   testObj->origin = makePoint(0.0, 0.0);
 
-  // FIXME: Assigning to 'testObj->origin' kills the default binding for the
-  // whole region, meaning that we've forgotten that testObj->size should also
-  // default to 0. Tracked by <rdar://problem/12701038>.
-  // This should be TRUE.
-  clang_analyzer_eval(testObj->size == oldSize); // expected-warning{{UNKNOWN}}
-
+  clang_analyzer_eval(testObj->size == oldSize); // expected-warning{{TRUE}}
+  
   free(testObj);
 }