summaryrefslogtreecommitdiff
path: root/test/Analysis
diff options
context:
space:
mode:
authorGeorge Karpenkov <ekarpenkov@apple.com>2017-11-09 19:06:22 +0000
committerGeorge Karpenkov <ekarpenkov@apple.com>2017-11-09 19:06:22 +0000
commitf7de82cd931d82084cb7e718578b92f94882fb19 (patch)
tree91caf397ac9f7158c8e54567f6bf35f290e94a84 /test/Analysis
parent1e53b12c1879c4e056b8ae443419b45a735bcc2e (diff)
[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 git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@317820 91177308-0d34-0410-b5e6-96231b3b80d8
Diffstat (limited to 'test/Analysis')
-rw-r--r--test/Analysis/constant-folding.c39
1 files changed, 39 insertions, 0 deletions
diff --git a/test/Analysis/constant-folding.c b/test/Analysis/constant-folding.c
index a6d2b74942..8189868be2 100644
--- a/test/Analysis/constant-folding.c
+++ b/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}}
+}