PR16755: When initializing or modifying a bitfield member in a constant
expression, truncate the stored value to the size of the bitfield.
llvm-svn: 187782
diff --git a/clang/test/SemaCXX/constant-expression-cxx11.cpp b/clang/test/SemaCXX/constant-expression-cxx11.cpp
index 8d16962..6824909 100644
--- a/clang/test/SemaCXX/constant-expression-cxx11.cpp
+++ b/clang/test/SemaCXX/constant-expression-cxx11.cpp
@@ -1727,3 +1727,40 @@
constexpr int k1 = S().t; // ok, int is lifetime-extended to end of constructor
constexpr int k2 = S(0).t; // expected-error {{constant expression}} expected-note {{in call}}
}
+
+namespace Bitfields {
+ struct A {
+ bool b : 1;
+ unsigned u : 5;
+ int n : 5;
+ bool b2 : 3;
+ unsigned u2 : 74; // expected-warning {{exceeds the size of its type}}
+ int n2 : 81; // expected-warning {{exceeds the size of its type}}
+ };
+
+ constexpr A a = { false, 33, 31, false, 0xffffffff, 0x7fffffff }; // expected-warning 2{{truncation}}
+ static_assert(a.b == 0 && a.u == 1 && a.n == -1 && a.b2 == 0 &&
+ a.u2 + 1 == 0 && a.n2 == 0x7fffffff,
+ "bad truncation of bitfield values");
+
+ struct B {
+ int n : 3;
+ constexpr B(int k) : n(k) {}
+ };
+ static_assert(B(3).n == 3, "");
+ static_assert(B(4).n == -4, "");
+ static_assert(B(7).n == -1, "");
+ static_assert(B(8).n == 0, "");
+ static_assert(B(-1).n == -1, "");
+ static_assert(B(-8889).n == -1, "");
+
+ namespace PR16755 {
+ struct X {
+ int x : 1;
+ constexpr static int f(int x) {
+ return X{x}.x;
+ }
+ };
+ static_assert(X::f(3) == -1, "3 should truncate to -1");
+ }
+}
diff --git a/clang/test/SemaCXX/constant-expression-cxx1y.cpp b/clang/test/SemaCXX/constant-expression-cxx1y.cpp
index ee88a3b..ebe8e98 100644
--- a/clang/test/SemaCXX/constant-expression-cxx1y.cpp
+++ b/clang/test/SemaCXX/constant-expression-cxx1y.cpp
@@ -870,3 +870,20 @@
}
static_assert((lifetime_versus_loops(), true), "");
}
+
+namespace Bitfields {
+ struct A {
+ bool b : 3;
+ int n : 4;
+ unsigned u : 5;
+ };
+ constexpr bool test() {
+ A a {};
+ a.b += 2;
+ --a.n;
+ --a.u;
+ a.n = -a.n * 3;
+ return a.b == false && a.n == 3 && a.u == 31;
+ }
+ static_assert(test(), "");
+}