diff options
author | George Karpenkov <ekarpenkov@apple.com> | 2017-11-09 19:06:22 +0000 |
---|---|---|
committer | George Karpenkov <ekarpenkov@apple.com> | 2017-11-09 19:06:22 +0000 |
commit | bbb66ad7b2daba4b6f7ccfb8d15fa656c99ef00b (patch) | |
tree | 2260c5f08a00ea03b45c8a1e9f76db52b549fe8c /clang/test/Analysis/constant-folding.c | |
parent | c019c39f4f75320aefb4142fffc2f3c3cea44e9e (diff) | |
download | bcm5719-llvm-bbb66ad7b2daba4b6f7ccfb8d15fa656c99ef00b.tar.gz bcm5719-llvm-bbb66ad7b2daba4b6f7ccfb8d15fa656c99ef00b.zip |
[analyzer] assume bitwise arithmetic axioms
Patches the solver to assume that bitwise OR of an unsigned value with a
constant always produces a value larger-or-equal than the constant, and
bitwise AND with a constant always produces a value less-or-equal than
the constant.
This patch is especially useful in the context of using bitwise
arithmetic for error code encoding: the analyzer would be able to state
that the error code produced using a bitwise OR is non-zero.
Differential Revision: https://reviews.llvm.org/D39707
llvm-svn: 317820
Diffstat (limited to 'clang/test/Analysis/constant-folding.c')
-rw-r--r-- | clang/test/Analysis/constant-folding.c | 39 |
1 files changed, 39 insertions, 0 deletions
diff --git a/clang/test/Analysis/constant-folding.c b/clang/test/Analysis/constant-folding.c index a6d2b749427..8189868be2e 100644 --- a/clang/test/Analysis/constant-folding.c +++ b/clang/test/Analysis/constant-folding.c @@ -76,3 +76,42 @@ void testMixedTypeComparisons (char a, unsigned long b) { clang_analyzer_eval(b >= a); // expected-warning{{TRUE}} clang_analyzer_eval(a != b); // expected-warning{{TRUE}} } + +void testBitwiseRules(unsigned int a, int b) { + clang_analyzer_eval((a | 1) >= 1); // expected-warning{{TRUE}} + clang_analyzer_eval((a | -1) >= -1); // expected-warning{{TRUE}} + clang_analyzer_eval((a | 2) >= 2); // expected-warning{{TRUE}} + clang_analyzer_eval((a | 5) >= 5); // expected-warning{{TRUE}} + clang_analyzer_eval((a | 10) >= 10); // expected-warning{{TRUE}} + + // Argument order should not influence this + clang_analyzer_eval((1 | a) >= 1); // expected-warning{{TRUE}} + + clang_analyzer_eval((a & 1) <= 1); // expected-warning{{TRUE}} + clang_analyzer_eval((a & 2) <= 2); // expected-warning{{TRUE}} + clang_analyzer_eval((a & 5) <= 5); // expected-warning{{TRUE}} + clang_analyzer_eval((a & 10) <= 10); // expected-warning{{TRUE}} + clang_analyzer_eval((a & -10) <= 10); // expected-warning{{UNKNOWN}} + + // Again, check for different argument order. + clang_analyzer_eval((1 & a) <= 1); // expected-warning{{TRUE}} + + unsigned int c = a; + c |= 1; + clang_analyzer_eval((c | 0) == 0); // expected-warning{{FALSE}} + + // Rules don't apply to signed typed, as the values might be negative. + clang_analyzer_eval((b | 1) > 0); // expected-warning{{UNKNOWN}} + + // Even for signed values, bitwise OR with a non-zero is always non-zero. + clang_analyzer_eval((b | 1) == 0); // expected-warning{{FALSE}} + clang_analyzer_eval((b | -2) == 0); // expected-warning{{FALSE}} + clang_analyzer_eval((b | 10) == 0); // expected-warning{{FALSE}} + clang_analyzer_eval((b | 0) == 0); // expected-warning{{UNKNOWN}} + clang_analyzer_eval((b | -2) >= 0); // expected-warning{{UNKNOWN}} + + // Check that dynamically computed constants also work. + int constant = 1 << 3; + unsigned int d = a | constant; + clang_analyzer_eval(constant > 0); // expected-warning{{TRUE}} +} |