diff --git a/gcc/cp/class.cc b/gcc/cp/class.cc index d37e9d4d576..68b62086340 100644 --- a/gcc/cp/class.cc +++ b/gcc/cp/class.cc @@ -6476,7 +6476,15 @@ end_of_class (tree t, eoc_mode mode) size of the type (usually 1) for computing nvsize. */ size = TYPE_SIZE_UNIT (TREE_TYPE (field)); - offset = size_binop (PLUS_EXPR, byte_position (field), size); + if (DECL_BIT_FIELD_TYPE (field)) + { + offset = size_binop (PLUS_EXPR, bit_position (field), + DECL_SIZE (field)); + offset = size_binop (CEIL_DIV_EXPR, offset, bitsize_unit_node); + offset = fold_convert (sizetype, offset); + } + else + offset = size_binop (PLUS_EXPR, byte_position (field), size); if (tree_int_cst_lt (result, offset)) result = offset; } diff --git a/gcc/testsuite/g++.dg/abi/no_unique_address7.C b/gcc/testsuite/g++.dg/abi/no_unique_address7.C new file mode 100644 index 00000000000..82fcedf070e --- /dev/null +++ b/gcc/testsuite/g++.dg/abi/no_unique_address7.C @@ -0,0 +1,33 @@ +// PR c++/109039 +// { dg-do run { target c++11 } } + +struct X { + signed short x0 : 7; + signed short x1 : 8; + X () : x0 (1), x1 (2) {} + int get () { return x0 + x1; } +}; + +struct S { + [[no_unique_address]] X x; + signed char c; + S () : c (0) {} +}; + +S s; + +int +main () +{ + if (s.x.x0 != 1 || s.x.x1 != 2 || s.c != 0) + __builtin_abort (); + s.x.x0 = -1; + s.x.x1 = -1; + if (s.x.x0 != -1 || s.x.x1 != -1 || s.c != 0) + __builtin_abort (); + s.c = -1; + s.x.x0 = 0; + s.x.x1 = 0; + if (s.x.x0 != 0 || s.x.x1 != 0 || s.c != -1) + __builtin_abort (); +}