Can clang warn about undefined behavior at compile time?

#include <iostream>

int main()
{
    int n = -1000;
    for (int i(0); i != n; ++i)
    {
    }
}

      

The following error is encountered in gcc at compile time:

main.cpp:6:5: warning: iteration 2147483647u invokes undefined behavior [-Waggressive-loop-optimizations]

     for (int i(0); i != n; ++i)

      

Clang -fsanitize=undefined

is a runtime engine. What is the compile time equivalent of clang?

+3


source to share


2 answers


Undefined behavior is often described as such in the standard because it is difficult for the compiler to test it in all situations.



You just ran into one case that is handled by GCC, not Clang. If you look, you can find cases that are handled by one compiler but not another. This is because they are not the same compiler and have different analyzes they perform.

+6


source


Clang can't catch it, at least not as part of the compilation (I haven't tested the clang static analyzer, and if it can't, please report a bug).

GCC decided it was okay to issue warnings from the middle of the optimizer:

$ g++ -Waggressive-loop-optimizations a.cc
$ g++ -Waggressive-loop-optimizations a.cc -O2
a.cc: In function โ€˜int main()โ€™:
a.cc:6:5: warning: iteration 2147483647u invokes undefined behavior [-Waggressive-loop-optimizations]
     for (int i(0); i != n; ++i)
     ^
a.cc:6:5: note: containing loop

      



It's actually really difficult and potentially difficult. The clang devs think that changing which warnings you emit based on the optimization level is bad behavior, we don't think users will miss warnings when building on -O0 or find new errors a few days later when building a build. Second, the way the optimizer is designed is such that it stores one view of the program at any given time and converts it from saying one thing to another, without keeping a history of what it did in comparison to the source code. This article is an LLVM blog articletalks about the problem. Clang warnings are built on top of the classic ASTs, which have a complete view of the source code, including templates and macro histories, so we can always point to the correct code and filter properties such as "was it a template argument".

It is possible to add this to clang, I have not figured out an efficient way to do it after 30 seconds of thinking about it. The problem is that we are willing to spend much more time proving what is in the optimizer than we are, as part of the warning generation. We don't want to pay twice for compilation time. A static analyzer, on the other hand, does not have this limitation and will happily do very expensive work to find your errors.

Finally, as you phrased your question, it sounds like you think clang either does or does not capture all undefined behavior at compile time. We do catch as much as possible and provide dynamic checkers for as much rest as possible, but neither gcc nor clang promise to catch all undefined behavior either at compile time or at runtime. There are too many and there is no list of what it is all about (some operations are clearly UB in the standard, some are UB simply because the standard cannot define what the behavior is!).

+4


source







All Articles