Author: Denys Petrov Date: 2021-10-25T15:14:10+03:00 New Revision: 3b1165ba3d15de83699be3ff4be3b6adf4d6e977
URL: https://github.com/llvm/llvm-project/commit/3b1165ba3d15de83699be3ff4be3b6adf4d6e977 DIFF: https://github.com/llvm/llvm-project/commit/3b1165ba3d15de83699be3ff4be3b6adf4d6e977.diff LOG: [analyzer] Retrieve incomplete array extent from its redeclaration. Summary: Fix a case when the extent can not be retrieved correctly from incomplete array declaration. Use redeclaration to get the array extent. Differential Revision: https://reviews.llvm.org/D111542 Added: Modified: clang/lib/StaticAnalyzer/Core/RegionStore.cpp clang/test/Analysis/initialization.c Removed: ################################################################################ diff --git a/clang/lib/StaticAnalyzer/Core/RegionStore.cpp b/clang/lib/StaticAnalyzer/Core/RegionStore.cpp index e0e6bca1e7cc..5565e9cfd08c 100644 --- a/clang/lib/StaticAnalyzer/Core/RegionStore.cpp +++ b/clang/lib/StaticAnalyzer/Core/RegionStore.cpp @@ -1641,8 +1641,18 @@ Optional<SVal> RegionStoreManager::getConstantValFromConstArrayInitializer( (!B.isMainAnalysis() || !VD->hasGlobalStorage())) return None; - // Array's declaration should have an initializer. - const Expr *Init = VD->getAnyInitializer(); + // 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: `getAnyInitializer` has an out-parameter, which returns a new `VD` + // from which an initializer is obtained. We replace current `VD` with the new + // `VD`. If the return value of the function is null than `VD` won't be + // replaced. + const Expr *Init = VD->getAnyInitializer(VD); + // NOTE: If `Init` is non-null, then a new `VD` is non-null for sure. So check + // `Init` for null only and don't worry about the replaced `VD`. if (!Init) return None; diff --git a/clang/test/Analysis/initialization.c b/clang/test/Analysis/initialization.c index 7981465394ea..9015113f8640 100644 --- a/clang/test/Analysis/initialization.c +++ b/clang/test/Analysis/initialization.c @@ -103,3 +103,42 @@ void glob_arr_index4() { // FIXME: Should warn {{FALSE}}, since the array has a static storage. clang_analyzer_eval(glob_arr_no_init[2]); // expected-warning{{UNKNOWN}} } + +const int glob_arr3[]; // IncompleteArrayType +const int glob_arr3[4] = {1, 2, 3}; // ConstantArrayType +void glob_arr_index5() { + 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_index6() { + 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}} +} _______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits