Как clang-tidy определяет, есть ли разыменование нулевого указателя?
Я получаю предупреждение от clang-tidy, которое жалуется на цикл на основе диапазона для
vector
шаблон, который является пользовательской реализацией вектора. Для кода:
non_std::vector<int> v;
for (const int& e : v) {
}
clang-tidy жалуется на разыменование нулевого указателя:
Разыменование нулевого указателя (загружается из переменной '__begin3') [clang-analyzer- core.NullDereference]
По логике, разыменования нулевого указателя нет. Согласно ссылке https://en.cppreference.com/w/cpp/language/range-for цикла range-base эквивалентно (предположим, C++17):
{
auto && __range = range_expression ;
auto __begin = begin_expr ;
auto __end = end_expr ;
for ( ; __begin != __end; ++__begin) {
range_declaration = *__begin;
loop_statement
}
}
Я переписал код, используя этот эквивалентный код, и у меня такая же проблема. Ниже приведен результат работы clang-tidy:
note: Assuming '__begin' is not equal to '__end' for (; __begin != __end; ++__begin) { ^ note: Loop condition is true. Entering loop body for (; __begin != __end; ++__begin) { ^ note: Null pointer value stored to '__begin' for (; __begin != __end; ++__begin) { ^ note: Assuming '__begin' is not equal to '__end' for (; __begin != __end; ++__begin) { ^ note: Loop condition is true. Entering loop body for (; __begin != __end; ++__begin) { ^ note: Dereference of null pointer (loaded from variable '__begin') const int& e = *__begin; ^
Вот код, который я считаю эквивалентным:
non_std::vector<int> v;
{
auto && __range = v;
auto __begin = __range.begin();
auto __end = __range.end();
for ( ; __begin != __end; ++__begin) {
const int &e = *__begin;
}
}
Clang делает неверное предположение: "Значение нулевого указателя сохранено в '__begin'" для кода внутри тела цикла. Тот же код для
std::vector
не вызывает это предупреждение.
Как clang-tidy определяет, есть ли разыменование нулевого указателя или нет? Как он обрабатывает циклы на основе диапазона для пользовательских контейнеров? Могу ли я что-нибудь сделать с настраиваемым вектором, чтобы предотвратить эту проблему?
Вот ссылка, которая описывает нечто подобное: Я предполагаю, что clang-tidy имеет ярлык для
std::vector
предполагая правильную реализацию, и не так терпимо для других реализаций.
PS.
int
Тип элемента используется здесь только для простоты. Реализация пользовательского вектора - это широко используемая проприетарная библиотека.