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(), "");
+}