[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
This commit is contained in:
Denys Petrov 2021-10-20 15:28:34 +03:00
parent 44e803ef6d
commit 3b1165ba3d
2 changed files with 51 additions and 2 deletions

View File

@ -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;

View File

@ -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}}
}