[clang] 01b9e61 - [Clang][Codegen] Truncate initializers of union bitfield members

Tomas Matheson via cfe-commits cfe-commits at lists.llvm.org
Thu Jan 28 01:25:55 PST 2021


Author: Tomas Matheson
Date: 2021-01-28T09:19:19Z
New Revision: 01b9e613c28b833327ab4de93d0638a5c8d3514f

URL: https://github.com/llvm/llvm-project/commit/01b9e613c28b833327ab4de93d0638a5c8d3514f
DIFF: https://github.com/llvm/llvm-project/commit/01b9e613c28b833327ab4de93d0638a5c8d3514f.diff

LOG: [Clang][Codegen] Truncate initializers of union bitfield members

If an initial value is given for a bitfield that does not fit in the
bitfield, the value should be truncated. Constant folding for
expressions did not account for this truncation in the case of union
member functions, despite a warning being emitted. In some contexts,
evaluation of expressions was not enabled unless C++11, ROPI or RWPI
was enabled.

Differential Revision: https://reviews.llvm.org/D93101

Added: 
    

Modified: 
    clang/lib/AST/ExprConstant.cpp
    clang/test/CodeGenCXX/bitfield-layout.cpp

Removed: 
    


################################################################################
diff  --git a/clang/lib/AST/ExprConstant.cpp b/clang/lib/AST/ExprConstant.cpp
index c1973720e49a..0f0c33b0ac85 100644
--- a/clang/lib/AST/ExprConstant.cpp
+++ b/clang/lib/AST/ExprConstant.cpp
@@ -9798,7 +9798,14 @@ bool RecordExprEvaluator::VisitInitListExpr(const InitListExpr *E) {
     ThisOverrideRAII ThisOverride(*Info.CurrentCall, &This,
                                   isa<CXXDefaultInitExpr>(InitExpr));
 
-    return EvaluateInPlace(Result.getUnionValue(), Info, Subobject, InitExpr);
+    if (EvaluateInPlace(Result.getUnionValue(), Info, Subobject, InitExpr)) {
+      if (Field->isBitField())
+        return truncateBitfieldValue(Info, InitExpr, Result.getUnionValue(),
+                                     Field);
+      return true;
+    }
+
+    return false;
   }
 
   if (!Result.hasValue())

diff  --git a/clang/test/CodeGenCXX/bitfield-layout.cpp b/clang/test/CodeGenCXX/bitfield-layout.cpp
index 49b196253f3c..79dbf9c691c4 100644
--- a/clang/test/CodeGenCXX/bitfield-layout.cpp
+++ b/clang/test/CodeGenCXX/bitfield-layout.cpp
@@ -2,6 +2,7 @@
 // RUN: %clang_cc1 %s -triple=i386-apple-darwin10 -emit-llvm -o - -O3 | FileCheck %s
 // RUN: %clang_cc1 %s -triple=aarch64_be-none-eabi -emit-llvm -o - -O3 | FileCheck %s
 // RUN: %clang_cc1 %s -triple=thumbv7_be-none-eabi -emit-llvm -o - -O3 | FileCheck %s
+// RUN: %clang_cc1 %s -triple=x86_64-unknown-unknown -emit-llvm -o - -O3 -std=c++11 | FileCheck -check-prefix=CHECK -check-prefix=CHECK-LP64 %s
 
 // CHECK-LP64: %union.Test1 = type { i32, [4 x i8] }
 union Test1 {
@@ -84,3 +85,68 @@ int test_init() {
   // CHECK: ret i32 0
   return 0;
 }
+
+extern "C" {
+int test_trunc_int() {
+  union {
+    int i : 4; // truncated to 0b1111 == -1
+  } const U = {15};  // 0b00001111
+  return U.i;
+}
+// CHECK: define dso_local i32 @test_trunc_int()
+// CHECK: ret i32 -1
+
+int test_trunc_three_bits() {
+  union {
+    int i : 3; // truncated to 0b111 == -1
+  } const U = {15};  // 0b00001111
+  return U.i;
+}
+// CHECK: define dso_local i32 @test_trunc_three_bits()
+// CHECK: ret i32 -1
+
+int test_trunc_1() {
+  union {
+    int i : 1; // truncated to 0b1 == -1
+  } const U = {15};  // 0b00001111
+  return U.i;
+}
+// CHECK: define dso_local i32 @test_trunc_1()
+// CHECK: ret i32 -1
+
+int test_trunc_zero() {
+  union {
+    int i : 4; // truncated to 0b0000 == 0
+  } const U = {80};  // 0b01010000
+  return U.i;
+}
+// CHECK: define dso_local i32 @test_trunc_zero()
+// CHECK: ret i32 0
+
+int test_constexpr() {
+  union {
+    int i : 3;           // truncated to 0b111 == -1
+  } const U = {1 + 2 + 4 + 8}; // 0b00001111
+  return U.i;
+}
+// CHECK: define dso_local i32 @test_constexpr()
+// CHECK: ret i32 -1
+
+int test_notrunc() {
+  union {
+    int i : 12;          // not truncated
+  } const U = {1 + 2 + 4 + 8}; // 0b00001111
+  return U.i;
+}
+// CHECK: define dso_local i32 @test_notrunc()
+// CHECK: ret i32 15
+
+long long test_trunc_long_long() {
+  union {
+    long long i : 14; // truncated to 0b00111101001101 ==
+  } const U = {0b0100111101001101};
+  return U.i;
+}
+// CHECK: define dso_local i64 @test_trunc_long_long()
+// CHECK: ret i64 3917
+}


        


More information about the cfe-commits mailing list