]> granicus.if.org Git - clang/commitdiff
[analyzer] pr28449: Fix support for various array initializers.
authorArtem Dergachev <artem.dergachev@gmail.com>
Fri, 13 Oct 2017 20:54:56 +0000 (20:54 +0000)
committerArtem Dergachev <artem.dergachev@gmail.com>
Fri, 13 Oct 2017 20:54:56 +0000 (20:54 +0000)
In some cases the analyzer didn't expect an array-type variable to be
initialized with anything other than a string literal. The patch essentially
removes the assertion, and ensures relatively sane behavior.

There is a bigger problem with these initializers. Currently our memory model
(RegionStore) is being ordered to initialize the array with a region that
is assumed to be storing the initializer rvalue, and it guesses to copy
the contents of that region to the array variable. However, it would make
more sense for RegionStore to receive the correct initializer in the first
place. This problem isn't addressed with this patch.

rdar://problem/27248428
Differential Revision: https://reviews.llvm.org/D23963

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

lib/StaticAnalyzer/Core/RegionStore.cpp
test/Analysis/compound-literals.c [new file with mode: 0644]
test/Analysis/objc-encode.m [new file with mode: 0644]

index fae7634405f9b4074fea74c0b8b98e4456d440a1..693a617fb6775605899820fffa44909e0ef24307 100644 (file)
@@ -2088,15 +2088,12 @@ RegionStoreManager::bindArray(RegionBindingsConstRef B,
   if (const ConstantArrayType* CAT = dyn_cast<ConstantArrayType>(AT))
     Size = CAT->getSize().getZExtValue();
 
-  // Check if the init expr is a string literal.
+  // Check if the init expr is a literal. If so, bind the rvalue instead.
+  // FIXME: It's not responsibility of the Store to transform this lvalue
+  // to rvalue. ExprEngine or maybe even CFG should do this before binding.
   if (Optional<loc::MemRegionVal> MRV = Init.getAs<loc::MemRegionVal>()) {
-    const StringRegion *S = cast<StringRegion>(MRV->getRegion());
-
-    // Treat the string as a lazy compound value.
-    StoreRef store(B.asStore(), *this);
-    nonloc::LazyCompoundVal LCV = svalBuilder.makeLazyCompoundVal(store, S)
-        .castAs<nonloc::LazyCompoundVal>();
-    return bindAggregate(B, R, LCV);
+    SVal V = getBinding(B.asStore(), *MRV, R->getValueType());
+    return bindAggregate(B, R, V);
   }
 
   // Handle lazy compound values.
diff --git a/test/Analysis/compound-literals.c b/test/Analysis/compound-literals.c
new file mode 100644 (file)
index 0000000..a2556d2
--- /dev/null
@@ -0,0 +1,9 @@
+// RUN: %clang_cc1 -triple=i386-apple-darwin10 -analyze -analyzer-checker=debug.ExprInspection -verify %s
+void clang_analyzer_eval(int);
+
+// pr28449: Used to crash.
+void foo(void) {
+  static const unsigned short array[] = (const unsigned short[]){0x0F00};
+  // FIXME: Should be true.
+  clang_analyzer_eval(array[0] == 0x0F00); // expected-warning{{UNKNOWN}}
+}
diff --git a/test/Analysis/objc-encode.m b/test/Analysis/objc-encode.m
new file mode 100644 (file)
index 0000000..b2379e9
--- /dev/null
@@ -0,0 +1,9 @@
+// RUN: %clang_cc1 -analyze -analyzer-checker=debug.ExprInspection -verify %s
+// expected-no-diagnostics
+
+void clang_analyzer_eval(int);
+
+// rdar://problem/34831581: Used to crash.
+void foo(void) {
+  char buf1[] = @encode(int **);
+}