Search code examples
c++static-analysisclang-static-analyzerclang-tidy

Getting clang-tidy to spot a statically deducible logic error


I don't know if what I'd like is possible, but I figure give it an ask anyway.

I have some Boost library code where I'd like to hint to clang-tidy to issue a warning where through static analysis, a clear instance of undefined behaviour could occur due to bad logic. https://akrzemi1.wordpress.com/2016/12/12/concealing-bugs/ suggests that __builtin_unreachable() might get clang-tidy to trip like this, but I have failed to make it happen (though it trips the UB sanitiser very nicely):

#include <optional>

int main()
{
  std::optional<int> f;
  // Spot the UB before it happens and flag it
  if(!f)
  {
    __builtin_unreachable();
  }
  // Here is the UB
  return *f;
}

In the code above, a static analyser can clearly tell that __builtin_unreachable() must be called. I want clang-tidy to report this, yet clang-tidy-5.0 -checks=* -header-filter=.* temp.cpp -- -std=c++17 reports nothing.

Note I don't need to use __builtin_unreachable(), it's just what Andrzej's C++ Blog suggested. Any technique for getting the clang static analyser, or the MSVC static analyser, or ideally clang-tidy, to deduce when UB must obviously occur through static deduction and flag it at compile time is what I am looking for.

What I am not looking for is a construct which always trips a warning during static analysis irrespective of use case. I only want the static analysis warning to appear when through static analysis alone, it is obvious at compile time that UB could be invoked given some statically deducible logic error.

My thanks in advance!


Solution

  • So, yeah, it turns out that this cannot be done in clang-tidy at least, and probably most other static analysers.

    The gory details of why not can be found at https://lists.llvm.org/pipermail/cfe-dev/2017-June/054120.html, but in essence:

    1. The halting problem i.e. no idea if and how loops are executed.
    2. clang-tidy and other analysers are built to avoid seeing dead code as much as possible. This exactly is opposite to what is needed for the kind of check above.