summaryrefslogtreecommitdiffstats
path: root/clang/test/Analysis/fields.c
diff options
context:
space:
mode:
authorJordan Rose <jordan_rose@apple.com>2013-03-01 23:03:17 +0000
committerJordan Rose <jordan_rose@apple.com>2013-03-01 23:03:17 +0000
commite185d73101dc6b1637ee103133cd6b07057661da (patch)
tree9c2aa045bb93b3fc0d1edfdee00494d53e2bba6f /clang/test/Analysis/fields.c
parentd49963609d58ceaf85de6ad90170a359258a3a2c (diff)
downloadbcm5719-llvm-e185d73101dc6b1637ee103133cd6b07057661da.tar.gz
bcm5719-llvm-e185d73101dc6b1637ee103133cd6b07057661da.zip
[analyzer] Special-case bitfields when finding sub-region bindings.
Previously we were assuming that we'd never ask for the sub-region bindings of a bitfield, since a bitfield cannot have subregions. However, unification of code paths has made that assumption invalid. While we could take advantage of this by just checking for the single possible binding, it's probably better to do the right thing, so that if/when we someday support unions we'll do the right thing there, too. This fixes a handful of false positives in analyzing LLVM. <rdar://problem/13325522> llvm-svn: 176388
Diffstat (limited to 'clang/test/Analysis/fields.c')
-rw-r--r--clang/test/Analysis/fields.c87
1 files changed, 87 insertions, 0 deletions
diff --git a/clang/test/Analysis/fields.c b/clang/test/Analysis/fields.c
index 12e8bbf3671..863a21aaf61 100644
--- a/clang/test/Analysis/fields.c
+++ b/clang/test/Analysis/fields.c
@@ -29,6 +29,10 @@ void test() {
(void)(p = getit()).x;
}
+#define true ((bool)1)
+#define false ((bool)0)
+typedef _Bool bool;
+
void testLazyCompoundVal() {
Point p = {42, 0};
@@ -36,3 +40,86 @@ void testLazyCompoundVal() {
clang_analyzer_eval((q = p).x == 42); // expected-warning{{TRUE}}
clang_analyzer_eval(q.x == 42); // expected-warning{{TRUE}}
}
+
+
+struct Bits {
+ unsigned a : 1;
+ unsigned b : 2;
+ unsigned c : 1;
+
+ bool x;
+
+ struct InnerBits {
+ bool y;
+
+ unsigned d : 16;
+ unsigned e : 6;
+ unsigned f : 2;
+ } inner;
+};
+
+void testBitfields() {
+ struct Bits bits;
+
+ if (foo() && bits.b) // expected-warning {{garbage}}
+ return;
+ if (foo() && bits.inner.e) // expected-warning {{garbage}}
+ return;
+
+ bits.c = 1;
+ clang_analyzer_eval(bits.c == 1); // expected-warning {{TRUE}}
+
+ if (foo() && bits.b) // expected-warning {{garbage}}
+ return;
+ if (foo() && bits.x) // expected-warning {{garbage}}
+ return;
+
+ bits.x = true;
+ clang_analyzer_eval(bits.x == true); // expected-warning{{TRUE}}
+ bits.b = 2;
+ clang_analyzer_eval(bits.x == true); // expected-warning{{TRUE}}
+ if (foo() && bits.c) // no-warning
+ return;
+
+ bits.inner.e = 50;
+ if (foo() && bits.inner.e) // no-warning
+ return;
+ if (foo() && bits.inner.y) // expected-warning {{garbage}}
+ return;
+ if (foo() && bits.inner.f) // expected-warning {{garbage}}
+ return;
+
+ extern struct InnerBits getInner();
+ bits.inner = getInner();
+
+ if (foo() && bits.inner.e) // no-warning
+ return;
+ if (foo() && bits.inner.y) // no-warning
+ return;
+ if (foo() && bits.inner.f) // no-warning
+ return;
+
+ bits.inner.f = 1;
+
+ if (foo() && bits.inner.e) // no-warning
+ return;
+ if (foo() && bits.inner.y) // no-warning
+ return;
+ if (foo() && bits.inner.f) // no-warning
+ return;
+
+ if (foo() && bits.a) // expected-warning {{garbage}}
+ return;
+}
+
+
+//-----------------------------------------------------------------------------
+// Incorrect behavior
+//-----------------------------------------------------------------------------
+
+void testTruncation() {
+ struct Bits bits;
+ bits.c = 0x11; // expected-warning{{implicit truncation}}
+ // FIXME: We don't model truncation of bitfields.
+ clang_analyzer_eval(bits.c == 1); // expected-warning {{FALSE}}
+}
OpenPOWER on IntegriCloud