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(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(Init)) + return B; + } + } - const ArrayType *AT =cast(Ctx.getCanonicalType(R->getValueType())); + const ArrayType *AT = + cast(Ctx.getCanonicalType(R->getValueType())); QualType ElementTy = AT->getElementType(); Optional Size; 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/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}} +}