Как 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Тип элемента используется здесь только для простоты. Реализация пользовательского вектора - это широко используемая проприетарная библиотека.

0 ответов

Другие вопросы по тегам