ASDenysPetrov updated this revision to Diff 366081.
ASDenysPetrov added a comment.

Rebased.


CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D107073/new/

https://reviews.llvm.org/D107073

Files:
  clang/lib/StaticAnalyzer/Core/RegionStore.cpp
  clang/test/Analysis/initialization.c
  clang/test/Analysis/initialization.cpp

Index: clang/test/Analysis/initialization.cpp
===================================================================
--- clang/test/Analysis/initialization.cpp
+++ clang/test/Analysis/initialization.cpp
@@ -167,7 +167,7 @@
   clang_analyzer_eval(glob_arr3[3][1] == 0); // expected-warning{{TRUE}}
 }
 
-void negative_index1() {
+void glob_arr_negative_index1() {
   int x = 2, y = -2;
   clang_analyzer_eval(glob_arr3[x][y] == 3); // expected-warning{{TRUE}}
   x = 4;
@@ -175,12 +175,12 @@
   clang_analyzer_eval(glob_arr3[x][y] == 7); // expected-warning{{TRUE}}
 }
 
-void out_of_bound_index1() {
+void glob_arr_out_of_bound_index1() {
   int x = -3, y = 2;
   int res = glob_arr3[x][y]; // expected-warning{{garbage or undefined}}
 }
 
-void out_of_bound_index2() {
+void glob_arr_out_of_bound_index2() {
   int x = 3, y = 2;
   int res = glob_arr3[x][y]; // expected-warning{{garbage or undefined}}
 }
@@ -197,12 +197,101 @@
   clang_analyzer_eval(glob_arr4[7] == 0); // expected-warning{{TRUE}}
 }
 
-void out_of_bound_index3() {
+void glob_arr_out_of_bound_index3() {
   int x = -42;
   int res = glob_arr4[x]; // expected-warning{{garbage or undefined}}
 }
 
-void out_of_bound_index4() {
+void glob_arr_out_of_bound_index4() {
   int x = 42;
   int res = glob_arr4[x]; // expected-warning{{garbage or undefined}}
 }
+
+void local_arr_index1() {
+  const int local_arr[2][2][3] = {{{1, 2}}, {{7}}};
+  clang_analyzer_eval(local_arr[0][0][0] == 1); // expected-warning{{TRUE}}
+  clang_analyzer_eval(local_arr[0][0][1] == 2); // expected-warning{{TRUE}}
+  clang_analyzer_eval(local_arr[0][0][2] == 0); // expected-warning{{TRUE}}
+  clang_analyzer_eval(local_arr[0][1][0] == 0); // expected-warning{{TRUE}}
+  clang_analyzer_eval(local_arr[0][1][1] == 0); // expected-warning{{TRUE}}
+  clang_analyzer_eval(local_arr[0][1][2] == 0); // expected-warning{{TRUE}}
+  clang_analyzer_eval(local_arr[1][0][0] == 7); // expected-warning{{TRUE}}
+  clang_analyzer_eval(local_arr[1][0][1] == 0); // expected-warning{{TRUE}}
+  clang_analyzer_eval(local_arr[1][0][2] == 0); // expected-warning{{TRUE}}
+  clang_analyzer_eval(local_arr[1][1][0] == 0); // expected-warning{{TRUE}}
+  clang_analyzer_eval(local_arr[1][1][1] == 0); // expected-warning{{TRUE}}
+  clang_analyzer_eval(local_arr[1][1][2] == 0); // expected-warning{{TRUE}}
+}
+
+void local_arr_index2() {
+  int const local_arr[2][2][3] = {{{1, 2}, {}}, {{7, 8}, {10, 11, 12}}};
+  clang_analyzer_eval(local_arr[0][0][0] == 1);  // expected-warning{{TRUE}}
+  clang_analyzer_eval(local_arr[0][0][1] == 2);  // expected-warning{{TRUE}}
+  clang_analyzer_eval(local_arr[0][0][2] == 0);  // expected-warning{{TRUE}}
+  clang_analyzer_eval(local_arr[0][1][0] == 0);  // expected-warning{{TRUE}}
+  clang_analyzer_eval(local_arr[0][1][1] == 0);  // expected-warning{{TRUE}}
+  clang_analyzer_eval(local_arr[0][1][2] == 0);  // expected-warning{{TRUE}}
+  clang_analyzer_eval(local_arr[1][0][0] == 7);  // expected-warning{{TRUE}}
+  clang_analyzer_eval(local_arr[1][0][1] == 8);  // expected-warning{{TRUE}}
+  clang_analyzer_eval(local_arr[1][0][2] == 0);  // expected-warning{{TRUE}}
+  clang_analyzer_eval(local_arr[1][1][0] == 10); // expected-warning{{TRUE}}
+  clang_analyzer_eval(local_arr[1][1][1] == 11); // expected-warning{{TRUE}}
+  clang_analyzer_eval(local_arr[1][1][2] == 12); // expected-warning{{TRUE}}
+}
+
+void local_arr_index3() {
+  const int local_arr[4][2] = {{}, {3}, {}, {7}};
+  clang_analyzer_eval(local_arr[0][0] == 0); // expected-warning{{TRUE}}
+  clang_analyzer_eval(local_arr[0][1] == 0); // expected-warning{{TRUE}}
+  clang_analyzer_eval(local_arr[1][0] == 3); // expected-warning{{TRUE}}
+  clang_analyzer_eval(local_arr[1][1] == 0); // expected-warning{{TRUE}}
+  clang_analyzer_eval(local_arr[2][0] == 0); // expected-warning{{TRUE}}
+  clang_analyzer_eval(local_arr[2][1] == 0); // expected-warning{{TRUE}}
+  clang_analyzer_eval(local_arr[3][0] == 7); // expected-warning{{TRUE}}
+  clang_analyzer_eval(local_arr[3][1] == 0); // expected-warning{{TRUE}}
+}
+
+void local_arr_negative_index1() {
+  const int local_arr[4][2] = {{}, {3}, {}, {7}};
+  int x = 2, y = -2;
+  clang_analyzer_eval(local_arr[x][y] == 3); // expected-warning{{TRUE}}
+  x = 4;
+  y = -2;
+  clang_analyzer_eval(local_arr[x][y] == 7); // expected-warning{{TRUE}}
+}
+
+void local_arr_out_of_bound_index1() {
+  const int local_arr[4][2] = {{}, {3}, {}, {7}};
+  int x = -3, y = 2;
+  int res = local_arr[x][y]; // expected-warning{{garbage or undefined}}
+}
+
+void local_arr_out_of_bound_index2() {
+  const int local_arr[4][2] = {{}, {3}, {}, {7}};
+  int x = 3, y = 2;
+  int res = local_arr[x][y]; // expected-warning{{garbage or undefined}}
+}
+
+void local_arr_index4() {
+  const int local_arr[8] = {1, 2, 3, 4};
+  clang_analyzer_eval(local_arr[0] == 1); // expected-warning{{TRUE}}
+  clang_analyzer_eval(local_arr[1] == 2); // expected-warning{{TRUE}}
+  clang_analyzer_eval(local_arr[2] == 3); // expected-warning{{TRUE}}
+  clang_analyzer_eval(local_arr[3] == 4); // expected-warning{{TRUE}}
+  clang_analyzer_eval(local_arr[4] == 0); // expected-warning{{TRUE}}
+  clang_analyzer_eval(local_arr[5] == 0); // expected-warning{{TRUE}}
+  clang_analyzer_eval(local_arr[6] == 0); // expected-warning{{TRUE}}
+  clang_analyzer_eval(local_arr[7] == 0); // expected-warning{{TRUE}}
+}
+
+void local_arr_out_of_bound_index3() {
+  const int local_arr[8] = {1, 2, 3, 4};
+  int x = -42;
+  int res = local_arr[x]; // expected-warning{{garbage or undefined}}
+}
+
+void local_arr_out_of_bound_index4() {
+  const int local_arr[8] = {1, 2, 3, 4};
+  int x = 42;
+  int res = local_arr[x]; // expected-warning{{garbage or undefined}}
+}
Index: clang/test/Analysis/initialization.c
===================================================================
--- clang/test/Analysis/initialization.c
+++ clang/test/Analysis/initialization.c
@@ -57,3 +57,27 @@
   int x = 3, y = 2;
   int res = glob_arr1[x][y]; // expected-warning{{garbage or undefined}}
 }
+
+void local_arr_index1() {
+  const int local_arr[8] = {[2] = 3, [0] = 1, [1] = 2, [3] = 4};
+  clang_analyzer_eval(local_arr[0] == 1); // expected-warning{{TRUE}}
+  clang_analyzer_eval(local_arr[1] == 2); // expected-warning{{TRUE}}
+  clang_analyzer_eval(local_arr[2] == 3); // expected-warning{{TRUE}}
+  clang_analyzer_eval(local_arr[3] == 4); // expected-warning{{TRUE}}
+  clang_analyzer_eval(local_arr[4] == 0); // expected-warning{{TRUE}}
+  clang_analyzer_eval(local_arr[5] == 0); // expected-warning{{TRUE}}
+  clang_analyzer_eval(local_arr[6] == 0); // expected-warning{{TRUE}}
+  clang_analyzer_eval(local_arr[7] == 0); // expected-warning{{TRUE}}
+}
+
+void local_arr_out_of_bound_index1() {
+  const int local_arr[8] = {[2] = 3, [0] = 1, [1] = 2, [3] = 4};
+  int x = -42;
+  int res = local_arr[x]; // expected-warning{{garbage or undefined}}
+}
+
+void local_arr_out_of_bound_index2() {
+  const int local_arr[8] = {[2] = 3, [0] = 1, [1] = 2, [3] = 4};
+  int x = 42;
+  int res = local_arr[x]; // expected-warning{{garbage or undefined}}
+}
Index: clang/lib/StaticAnalyzer/Core/RegionStore.cpp
===================================================================
--- clang/lib/StaticAnalyzer/Core/RegionStore.cpp
+++ clang/lib/StaticAnalyzer/Core/RegionStore.cpp
@@ -2234,12 +2234,29 @@
   return B.addBinding(R, BindingKey::Default, V);
 }
 
-RegionBindingsRef
-RegionStoreManager::bindArray(RegionBindingsConstRef B,
-                              const TypedValueRegion* R,
-                              SVal Init) {
+RegionBindingsRef RegionStoreManager::bindArray(RegionBindingsConstRef B,
+                                                const TypedValueRegion *R,
+                                                SVal Init) {
+  // Ignore binding `InitListExpr` to arrays of const type,
+  // since we can directly retrieve values from initializer using
+  // `getConstantValFromConstArrayInitializer`.For example:
+  //   const int arr[42] = { 1, 2, 3 };
+  // The init values of this array will never change, so we don't have to
+  // store them additionally in the RegionStore.
+  if (const auto *VR = dyn_cast<VarRegion>(R)) {
+    const VarDecl *VD = VR->getDecl();
+    // Ignore only arrays which values can't change.
+    if (VD->getType().isConstQualified()) {
+      const Expr *Init = VD->getAnyInitializer();
+      // FIXME: Ignore `StringLiteral` and `CompoundLiteralExpr` as well when
+      // `getConstantValFromConstArrayInitializer` supports them.
+      if (isa_and_nonnull<InitListExpr>(Init))
+        return B;
+    }
+  }
 
-  const ArrayType *AT =cast<ArrayType>(Ctx.getCanonicalType(R->getValueType()));
+  const ArrayType *AT =
+      cast<ArrayType>(Ctx.getCanonicalType(R->getValueType()));
   QualType ElementTy = AT->getElementType();
   Optional<uint64_t> Size;
 
_______________________________________________
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
  • [PATCH] D107073: [analyzer] D... Denys Petrov via Phabricator via cfe-commits

Reply via email to