llvm / llvm-project

The LLVM Project is a collection of modular and reusable compiler and toolchain technologies.
http://llvm.org
Other
27.85k stars 11.47k forks source link

clang-tidy diagnoses "dereference of undefined pointer value" (`clang-analyzer-core.NullDereference`) from an integer multiplication #99764

Open bernardosulzbach opened 1 month ago

bernardosulzbach commented 1 month ago

Output

/home/bernardo/code/clang-tidy-bug-reports/NullDereference/NullDereference.cpp:8:82: warning: Dereference of undefined pointer value [clang-analyzer-core.NullDereference]
    8 |         auto const at = [&](int const row) { std::cout << static_cast<float>(2 * featheringIndex + row) << '\n'; };
      |                                                                                  ^
/home/bernardo/code/clang-tidy-bug-reports/NullDereference/NullDereference.cpp:9:9: note: Calling 'operator()'
    9 |         at(0);
      |         ^~~~~
/home/bernardo/code/clang-tidy-bug-reports/NullDereference/NullDereference.cpp:8:82: note: Dereference of undefined pointer value
    8 |         auto const at = [&](int const row) { std::cout << static_cast<float>(2 * featheringIndex + row) << '\n'; };
      |                                                                                  ^~~~~~~~~~~~~~~

Maybe it needs std::views::enumerate to reproduce?

Version

g++ (SUSE Linux) 13.3.0 clang-tidy version 18.1.8

Inputs

I tried to minify the real source code, but you can probably minify it further and still reproduce.

C++

#include <array>
#include <iostream>
#include <ranges>

int main() {
    std::array<float, 4> constexpr FeatheringLevels = {0.5f, 1.0f, 2.0f};
    for (auto const [featheringIndex, featheringLevel] : std::views::enumerate(FeatheringLevels)) {
        auto const at = [&](int const row) { std::cout << static_cast<float>(2 * featheringIndex + row) << '\n'; };
        at(0);
    }
}

CMake

cmake_minimum_required(VERSION 3.24.0 FATAL_ERROR)

set(CMAKE_COLOR_DIAGNOSTICS ON)

include(CheckCXXCompilerFlag)

project(NullDereference)
set(VERSION_MAJOR 0)
set(VERSION_MINOR 1)

set(CMAKE_CXX_STANDARD 23)
set(CXX_STANDARD_REQUIRED ON)
set(CMAKE_CXX_EXTENSIONS OFF)
set(CMAKE_EXPORT_COMPILE_COMMANDS 1)

# Keep the exclusions sorted
set(CLANG_TIDY_CHECKS_LIST
    boost-*
    bugprone-*
    -bugprone-easily-swappable-parameters
    -bugprone-exception-escape
    -bugprone-unchecked-optional-access
    clang-analyzer-*
    concurrency-*
    cppcoreguidelines-*
    -cppcoreguidelines-avoid-magic-numbers
    -cppcoreguidelines-init-variables
    -cppcoreguidelines-pro-bounds-constant-array-index
    -cppcoreguidelines-pro-type-reinterpret-cast
    -cppcoreguidelines-pro-type-union-access
    misc-*
    -misc-no-recursion
    modernize-*
    -modernize-use-nullptr
    -modernize-use-std-numbers
    -modernize-use-trailing-return-type
    performance-*
    -performance-no-int-to-ptr
    portability-*
    readability-*
    -readability-function-cognitive-complexity
    -readability-identifier-length
    -readability-magic-numbers
    -readability-uppercase-literal-suffix)
list(JOIN CLANG_TIDY_CHECKS_LIST "," CLANG_TIDY_CHECKS_STRING)
set(CMAKE_CXX_CLANG_TIDY clang-tidy "-checks=${CLANG_TIDY_CHECKS_STRING}")

add_executable(NullDereference NullDereference.cpp)
llvmbot commented 1 month ago

@llvm/issue-subscribers-clang-static-analyzer

Author: Bernardo Sulzbach (bernardosulzbach)

# Output ``` /home/bernardo/code/clang-tidy-bug-reports/NullDereference/NullDereference.cpp:8:82: warning: Dereference of undefined pointer value [clang-analyzer-core.NullDereference] 8 | auto const at = [&](int const row) { std::cout << static_cast<float>(2 * featheringIndex + row) << '\n'; }; | ^ /home/bernardo/code/clang-tidy-bug-reports/NullDereference/NullDereference.cpp:9:9: note: Calling 'operator()' 9 | at(0); | ^~~~~ /home/bernardo/code/clang-tidy-bug-reports/NullDereference/NullDereference.cpp:8:82: note: Dereference of undefined pointer value 8 | auto const at = [&](int const row) { std::cout << static_cast<float>(2 * featheringIndex + row) << '\n'; }; | ^~~~~~~~~~~~~~~ ``` Maybe it needs `std::views::enumerate` to reproduce? # Version g++ (SUSE Linux) 13.3.0 clang-tidy version 18.1.8 # Inputs I tried to minify the real source code, but you can probably minify it further and still reproduce. ## C++ ```cpp #include <array> #include <iostream> #include <ranges> int main() { std::array<float, 4> constexpr FeatheringLevels = {0.5f, 1.0f, 2.0f}; for (auto const [featheringIndex, featheringLevel] : std::views::enumerate(FeatheringLevels)) { auto const at = [&](int const row) { std::cout << static_cast<float>(2 * featheringIndex + row) << '\n'; }; at(0); } } ``` ## CMake ```cmake cmake_minimum_required(VERSION 3.24.0 FATAL_ERROR) set(CMAKE_COLOR_DIAGNOSTICS ON) include(CheckCXXCompilerFlag) project(NullDereference) set(VERSION_MAJOR 0) set(VERSION_MINOR 1) set(CMAKE_CXX_STANDARD 23) set(CXX_STANDARD_REQUIRED ON) set(CMAKE_CXX_EXTENSIONS OFF) set(CMAKE_EXPORT_COMPILE_COMMANDS 1) # Keep the exclusions sorted set(CLANG_TIDY_CHECKS_LIST boost-* bugprone-* -bugprone-easily-swappable-parameters -bugprone-exception-escape -bugprone-unchecked-optional-access clang-analyzer-* concurrency-* cppcoreguidelines-* -cppcoreguidelines-avoid-magic-numbers -cppcoreguidelines-init-variables -cppcoreguidelines-pro-bounds-constant-array-index -cppcoreguidelines-pro-type-reinterpret-cast -cppcoreguidelines-pro-type-union-access misc-* -misc-no-recursion modernize-* -modernize-use-nullptr -modernize-use-std-numbers -modernize-use-trailing-return-type performance-* -performance-no-int-to-ptr portability-* readability-* -readability-function-cognitive-complexity -readability-identifier-length -readability-magic-numbers -readability-uppercase-literal-suffix) list(JOIN CLANG_TIDY_CHECKS_LIST "," CLANG_TIDY_CHECKS_STRING) set(CMAKE_CXX_CLANG_TIDY clang-tidy "-checks=${CLANG_TIDY_CHECKS_STRING}") add_executable(NullDereference NullDereference.cpp) ```
chrchr-github commented 1 month ago

Without std::views:

#include <array>

int main() {
    std::array<std::pair<int, int>, 4> a = {};
    for (auto [x, y] : a) {
        auto f = [&]() { return 2 * x ; };
        f();
    }
}

https://godbolt.org/z/T7WdznxdM

chrchr-github commented 1 month ago

This is clean though:

int main() {
    struct { int i, j; } a[1] = {};
    for (auto [x, y] : a) {
        auto f = [&]() { return 2 * x ; };
        f();
    }
}

So the warning seems to be related to std::pair.

steakhal commented 1 month ago

Its probably caused by the structured binding. I know there are a few tickets already for that.

chrchr-github commented 1 month ago

https://github.com/llvm/llvm-project/issues/91835 looks similar.