diff --git a/clang/lib/AST/ExprConstant.cpp b/clang/lib/AST/ExprConstant.cpp --- a/clang/lib/AST/ExprConstant.cpp +++ b/clang/lib/AST/ExprConstant.cpp @@ -9798,7 +9798,14 @@ ThisOverrideRAII ThisOverride(*Info.CurrentCall, &This, isa(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 --- 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 @@ // 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 +}