clang-analyzer-core.DivideZero only gives a warning once in one function declaration?

I used llvm 12.0.1, when I use clang-tidy to check the following code

// $Id: A5-6-1.cpp 305629 2018-01-29 13:29:25Z piotr.serwa $
#include <cstdint>
#include <stdexcept>

double Fn()
{
  std::int32_t a = 10, b = 5, c = 0;
  std::int32_t y = a / (a - 2 * b);
  std::int32_t z = a / c;
}

I can only get the following warnings, but the last expr z = a / c does not trigger a warning.

/Users/banma-2596/source_code/clang_llvm-12.0.1/llvm-12.0.1-x86-64-linux-build/bin/../../../test/A5_6_1-2.cpp:8:22: warning: Division by zero [clang-analyzer-core.DivideZero]
  std::int32_t y = a / (a - 2 * b);
                     ^
/Users/banma-2596/source_code/clang_llvm-12.0.1/llvm-12.0.1-x86-64-linux-build/bin/../../../test/A5_6_1-2.cpp:8:22: note: Division by zero
/Users/banma-2596/source_code/clang_llvm-12.0.1/llvm-12.0.1-x86-64-linux-build/bin/../../../test/A5_6_1-2.cpp:10:1: warning: non-void function does not return a value [clang-diagnostic-return-type]
}

but if i comment the line std::int32_t y = a / (a - 2 * b); I will get a warning triggered by the last sentence

/Users/banma-2596/source_code/clang_llvm-12.0.1/llvm-12.0.1-x86-64-linux-build/bin/../../../test/A5_6_1-2.cpp:9:22: warning: Division by zero [clang-analyzer-core.DivideZero]
  std::int32_t z = a / c;
                     ^
/Users/banma-2596/source_code/clang_llvm-12.0.1/llvm-12.0.1-x86-64-linux-build/bin/../../../test/A5_6_1-2.cpp:7:31: note: 'c' initialized to 0
  std::int32_t a = 10, b = 5, c = 0;
                              ^
/Users/banma-2596/source_code/clang_llvm-12.0.1/llvm-12.0.1-x86-64-linux-build/bin/../../../test/A5_6_1-2.cpp:9:22: note: Division by zero
  std::int32_t z = a / c;

I don’t understand why and what happens, when I debug in the code I found that, in CoreEngine.cpp:147

dispatchWorkItem(Node, Node->getLocation(), WU);

dispatchWorkItem will process the basic block B1 which contains the all the decls and exprs in function Fn(),but not all the statements in B1 will be processed.

What happened???

I guess, in one function declaration, the clang-analyzer-core.DivideZero only gives a warning once

The static analyzer doesn’t report a division by zero on line std::int32_t z = a / c; because there’s no division by zero on that line. The line is actually not executed at all, because the program always crashes on the previous line due to the previous division by zero, which we do warn you about.

So, everything works correctly, there’s no limitation. If you have these divisions on, say, different branches of an if-statement (and the static analyzer can’t prove that only one of the branches is taken), you’ll have two warnings in the same function.

Well, technically the program isn’t guaranteed to crash during division by zero; instead, undefined behavior is invoked, which may or may not resolve to a crash, depending on optimizer shenanigans. But exploring consequences of undefined behavior is still an equally meaningless process, as literally nothing useful can be said about the program’s behavior under such circumstances.

1 Like

Thank you very much for your explanation. With your hints, I deep into the source code, debug, and find that when static analyzer gives such a warning, the Engine.enqueue will not enqueue the next stmtIdx any more, and indeed, statements later will not be processed.

Thank you very much, @NoQ