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

Rebased on top of D106681 <https://reviews.llvm.org/D106681>.


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

https://reviews.llvm.org/D111542

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


Index: clang/test/Analysis/initialization.c
===================================================================
--- clang/test/Analysis/initialization.c
+++ clang/test/Analysis/initialization.c
@@ -97,3 +97,42 @@
   // FIXME: Should warn {{garbage or undefined}}.
   int res = glob_arr2[x][y]; // no-warning
 }
+
+const int glob_arr3[];              // IncompleteArrayType
+const int glob_arr3[4] = {1, 2, 3}; // ConstantArrayType
+void glob_arr_index4() {
+  clang_analyzer_eval(glob_arr3[0] == 1); // expected-warning{{TRUE}}
+  clang_analyzer_eval(glob_arr3[1] == 2); // expected-warning{{TRUE}}
+  clang_analyzer_eval(glob_arr3[2] == 3); // expected-warning{{TRUE}}
+  clang_analyzer_eval(glob_arr3[3] == 0); // expected-warning{{TRUE}}
+}
+
+void glob_invalid_index5() {
+  int x = 42;
+  int res = glob_arr3[x]; // expected-warning{{garbage or undefined}}
+}
+
+void glob_invalid_index6() {
+  int x = -42;
+  int res = glob_arr3[x]; // expected-warning{{garbage or undefined}}
+}
+
+const int glob_arr4[];              // IncompleteArrayType
+const int glob_arr4[4] = {1, 2, 3}; // ConstantArrayType
+const int glob_arr4[];              // ConstantArrayType (according to AST)
+void glob_arr_index5() {
+  clang_analyzer_eval(glob_arr4[0] == 1); // expected-warning{{TRUE}}
+  clang_analyzer_eval(glob_arr4[1] == 2); // expected-warning{{TRUE}}
+  clang_analyzer_eval(glob_arr4[2] == 3); // expected-warning{{TRUE}}
+  clang_analyzer_eval(glob_arr4[3] == 0); // expected-warning{{TRUE}}
+}
+
+void glob_invalid_index7() {
+  int x = 42;
+  int res = glob_arr4[x]; // expected-warning{{garbage or undefined}}
+}
+
+void glob_invalid_index8() {
+  int x = -42;
+  int res = glob_arr4[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
@@ -1640,7 +1640,21 @@
       (!B.isMainAnalysis() || !VD->hasGlobalStorage()))
     return None;
 
-  // Array's declaration should have ConstantArrayType type.
+  // Array's declaration should have `ConstantArrayType` type, because only 
this
+  // type contains an array extent. It may happen that array type can be of
+  // `IncompleteArrayType` type. To get the declaration of `ConstantArrayType`
+  // type, we should find the declaration in the redeclarations chain that has
+  // the initialization expression.
+  // NOTE: `VD` is always non-null if `Init` is non-null, so we can check for
+  // null only one of them.
+  const Expr *Init = VD->getAnyInitializer(VD);
+
+  // Array's declaration should have an initializer.
+  if (!Init)
+    return None;
+
+  // Array's declaration should have ConstantArrayType type, because only this
+  // type contains an array extent.
   const ConstantArrayType *CAT = Ctx.getAsConstantArrayType(VD->getType());
   if (!CAT)
     return None;
@@ -1683,11 +1697,6 @@
     return UndefinedVal();
   // From here `Offset` is in the bounds.
 
-  // Array's declaration should have an initializer.
-  const Expr *Init = VD->getAnyInitializer();
-  if (!Init)
-    return None;
-
   // Handle InitListExpr.
   if (const auto *ILE = dyn_cast<InitListExpr>(Init))
     return getSValFromInitListExpr(ILE, Offset, R->getElementType());


Index: clang/test/Analysis/initialization.c
===================================================================
--- clang/test/Analysis/initialization.c
+++ clang/test/Analysis/initialization.c
@@ -97,3 +97,42 @@
   // FIXME: Should warn {{garbage or undefined}}.
   int res = glob_arr2[x][y]; // no-warning
 }
+
+const int glob_arr3[];              // IncompleteArrayType
+const int glob_arr3[4] = {1, 2, 3}; // ConstantArrayType
+void glob_arr_index4() {
+  clang_analyzer_eval(glob_arr3[0] == 1); // expected-warning{{TRUE}}
+  clang_analyzer_eval(glob_arr3[1] == 2); // expected-warning{{TRUE}}
+  clang_analyzer_eval(glob_arr3[2] == 3); // expected-warning{{TRUE}}
+  clang_analyzer_eval(glob_arr3[3] == 0); // expected-warning{{TRUE}}
+}
+
+void glob_invalid_index5() {
+  int x = 42;
+  int res = glob_arr3[x]; // expected-warning{{garbage or undefined}}
+}
+
+void glob_invalid_index6() {
+  int x = -42;
+  int res = glob_arr3[x]; // expected-warning{{garbage or undefined}}
+}
+
+const int glob_arr4[];              // IncompleteArrayType
+const int glob_arr4[4] = {1, 2, 3}; // ConstantArrayType
+const int glob_arr4[];              // ConstantArrayType (according to AST)
+void glob_arr_index5() {
+  clang_analyzer_eval(glob_arr4[0] == 1); // expected-warning{{TRUE}}
+  clang_analyzer_eval(glob_arr4[1] == 2); // expected-warning{{TRUE}}
+  clang_analyzer_eval(glob_arr4[2] == 3); // expected-warning{{TRUE}}
+  clang_analyzer_eval(glob_arr4[3] == 0); // expected-warning{{TRUE}}
+}
+
+void glob_invalid_index7() {
+  int x = 42;
+  int res = glob_arr4[x]; // expected-warning{{garbage or undefined}}
+}
+
+void glob_invalid_index8() {
+  int x = -42;
+  int res = glob_arr4[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
@@ -1640,7 +1640,21 @@
       (!B.isMainAnalysis() || !VD->hasGlobalStorage()))
     return None;
 
-  // Array's declaration should have ConstantArrayType type.
+  // Array's declaration should have `ConstantArrayType` type, because only this
+  // type contains an array extent. It may happen that array type can be of
+  // `IncompleteArrayType` type. To get the declaration of `ConstantArrayType`
+  // type, we should find the declaration in the redeclarations chain that has
+  // the initialization expression.
+  // NOTE: `VD` is always non-null if `Init` is non-null, so we can check for
+  // null only one of them.
+  const Expr *Init = VD->getAnyInitializer(VD);
+
+  // Array's declaration should have an initializer.
+  if (!Init)
+    return None;
+
+  // Array's declaration should have ConstantArrayType type, because only this
+  // type contains an array extent.
   const ConstantArrayType *CAT = Ctx.getAsConstantArrayType(VD->getType());
   if (!CAT)
     return None;
@@ -1683,11 +1697,6 @@
     return UndefinedVal();
   // From here `Offset` is in the bounds.
 
-  // Array's declaration should have an initializer.
-  const Expr *Init = VD->getAnyInitializer();
-  if (!Init)
-    return None;
-
   // Handle InitListExpr.
   if (const auto *ILE = dyn_cast<InitListExpr>(Init))
     return getSValFromInitListExpr(ILE, Offset, R->getElementType());
_______________________________________________
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits

Reply via email to