llvm / llvm-project

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

[analyzer] FP due to not handling std::vector iteration and member fns #101635

Open chrchr-github opened 1 month ago

chrchr-github commented 1 month ago
#include <vector>

int f(const std::vector<int>& v) {
    const int* p = nullptr;
    bool b = false;
    std::vector<int> w;
    for (const auto& i : v) {
        if (!b) {
            p = &i;
            b = true;
        }
        else
            w.emplace_back(i);
    }
    int x = 0;
    for (auto j : w) {
        x = std::max(*p, j);
    }
    return x;
}

p is assigned before any element is placed into w. https://godbolt.org/z/WxPv13qz9

llvmbot commented 1 month ago

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

Author: None (chrchr-github)

~~~c++ #include <vector> int f(const std::vector<int>& v) { const int* p = nullptr; bool b = false; std::vector<int> w; for (const auto& i : v) { if (!b) { p = &i; b = true; } else w.emplace_back(i); } int x = 0; for (auto j : w) { x = std::max(*p, j); } return x; } ~~~ `p` is assigned before any element is placed into `w`. https://godbolt.org/z/WxPv13qz9
steakhal commented 1 month ago

It's unfortunate - but true - that we don't make the assumption that a default constructed vector is empty - hence it should not take the second loop; so I think we can reduce this case into https://godbolt.org/z/19s5f6chG :

#include <vector>
int f() {
  const int* p = nullptr;
  std::vector<int> w;
  return w.empty() ? 0 : *p; // FP on the dead ternary branch
}