The following patch rewrites the bitfield handling of the C++ memory model and enables it unconditionally to fix PR52080. As I suggested earlier at some point this moves computation of what the memory model considers the underlying object we may access to the point where we lay out a structure type. This allows other passes like for example SRA or a new bitfield lowering pass to use a canonical (and correct) addressable object to access bitfields. The underlying object is represented as a FIELD_DECL that would be a suitable replacement for all bitfield FIELD_DECLs if you wrap it inside a BIT_FIELD_REF (see the gimplify.c hunk). But the main purpose (for now) is to make use of it in get_bit_range which no longer needs to walk all fields of a record nor build new trees or use get_inner_reference.
If the C frontend would stop using DECL_INITIAL temporarily for bitfield FIELD_DECLs we could avoid adding a new member to struct tree_field_decl - Joseph, is it possible to avoid using DECL_INITIAL? There are still corner-cases I also pointed out in the existing get_bit_range code, namely if you consider tail-padding re-use with C++ inheritance (I didn't try hard to construct a testcase yet). The C++ memory model folks have not yet expressed their opinion as to how this case is supposed to be handled - a testcase would look like struct Base { int i : 1; }; struct Deriv : Base { char c; }; where Deriv::c would be at byte offset 1 (the current code will allow SImode accesses to Base:i). Note that in the above case tail-padding is _not_ reused (for some reason). Bootstrapped and tested on x86_64-unknown-linux-gnu. Any comments? Thanks, Richard. 2012-02-07 Richard Guenther <rguent...@suse.de> * tree.h (DECL_BIT_FIELD_REPRESENTATIVE): New define. (struct tree_field_decl): New field bit_field_representative. * stor-layout.c (start_bitfield_representative): New function. (finish_bitfield_representative): Likewise. (finish_bitfield_layout): Likewise. (finish_record_layout): Call finish_bitfield_layout. * tree-streamer-in.c (lto_input_ts_field_decl_tree_pointers): Stream DECL_BIT_FIELD_REPRESENTATIVE. * tree-streamer-out.c (write_ts_field_decl_tree_pointers): Likewise. PR middle-end/52080 PR middle-end/52097 PR middle-end/48124 * expr.c (get_bit_range): Unconditionally extract bitrange from DECL_BIT_FIELD_REPRESENTATIVE. (expand_assignment): Adjust call to get_bit_range. * gimplify.c (gimplify_expr): Translate bitfield accesses to BIT_FIELD_REFs of the representative. * tree-sra.c (create_access_replacement): Only rename the replacement if we can rewrite it into SSA form. Properly mark register typed replacements that we cannot rewrite with TREE_ADDRESSABLE. * gcc.dg/torture/pr48124-1.c: New testcase. * gcc.dg/torture/pr48124-2.c: Likewise. * gcc.dg/torture/pr48124-3.c: Likewise. * gcc.dg/torture/pr48124-4.c: Likewise. Index: gcc/stor-layout.c =================================================================== *** gcc/stor-layout.c.orig 2012-02-07 11:04:21.000000000 +0100 --- gcc/stor-layout.c 2012-02-07 11:19:55.000000000 +0100 *************** finalize_type_size (tree type) *** 1722,1727 **** --- 1722,1908 ---- } } + /* Return a new underlying object for a bitfield started with FIELD. */ + + static tree + start_bitfield_representative (tree field) + { + tree repr = make_node (FIELD_DECL); + DECL_FIELD_OFFSET (repr) = DECL_FIELD_OFFSET (field); + /* Force the representative to begin at an BITS_PER_UNIT aligned + boundary - C++ may use tail-padding of a base object to + continue packing bits so the bitfield region does not start + at bit zero (see g++.dg/abi/bitfield5.C for example). + Unallocated bits may happen for other reasons as well, + for example Ada which allows explicit bit-granular structure layout. */ + DECL_FIELD_BIT_OFFSET (repr) + = size_binop (BIT_AND_EXPR, + DECL_FIELD_BIT_OFFSET (field), + bitsize_int (~(BITS_PER_UNIT - 1))); + SET_DECL_OFFSET_ALIGN (repr, DECL_OFFSET_ALIGN (field)); + DECL_SIZE (repr) = DECL_SIZE (field); + DECL_PACKED (repr) = DECL_PACKED (field); + DECL_CONTEXT (repr) = DECL_CONTEXT (field); + return repr; + } + + /* Finish up a bitfield group that was started by creating the underlying + object REPR with the last fied in the bitfield group FIELD. */ + + static void + finish_bitfield_representative (tree repr, tree field) + { + unsigned HOST_WIDE_INT bitsize, maxbitsize, modesize; + enum machine_mode mode; + tree nextf, size; + + size = size_diffop (DECL_FIELD_OFFSET (field), + DECL_FIELD_OFFSET (repr)); + gcc_assert (host_integerp (size, 1)); + bitsize = (tree_low_cst (size, 1) * BITS_PER_UNIT + + tree_low_cst (DECL_FIELD_BIT_OFFSET (field), 1) + - tree_low_cst (DECL_FIELD_BIT_OFFSET (repr), 1) + + tree_low_cst (DECL_SIZE (field), 1)); + + /* Now nothing tells us how to pad out bitsize ... */ + nextf = DECL_CHAIN (field); + while (nextf && TREE_CODE (nextf) != FIELD_DECL) + nextf = DECL_CHAIN (nextf); + if (nextf) + { + tree maxsize; + /* If there was an error, the field may be not layed out + correctly. Don't bother to do anything. */ + if (TREE_TYPE (nextf) == error_mark_node) + return; + maxsize = size_diffop (DECL_FIELD_OFFSET (nextf), + DECL_FIELD_OFFSET (repr)); + gcc_assert (host_integerp (maxsize, 1)); + maxbitsize = (tree_low_cst (maxsize, 1) * BITS_PER_UNIT + + tree_low_cst (DECL_FIELD_BIT_OFFSET (nextf), 1) + - tree_low_cst (DECL_FIELD_BIT_OFFSET (repr), 1)); + } + else + { + /* ??? If you consider that tail-padding of this struct might be + re-used when deriving from it we cannot really do the following + and thus need to set maxsize to bitsize? */ + tree maxsize = size_diffop (TYPE_SIZE_UNIT (DECL_CONTEXT (field)), + DECL_FIELD_OFFSET (repr)); + gcc_assert (host_integerp (maxsize, 1)); + maxbitsize = (tree_low_cst (maxsize, 1) * BITS_PER_UNIT + - tree_low_cst (DECL_FIELD_BIT_OFFSET (repr), 1)); + } + + /* Only if we don't artificially break up the representative in + the middle of a large bitfield with different possibly + overlapping representatives. And all representatives start + at byte offset. */ + gcc_assert (maxbitsize % BITS_PER_UNIT == 0); + + /* Round up bitsize to multiples of BITS_PER_UNIT. */ + bitsize = (bitsize + BITS_PER_UNIT - 1) & ~(BITS_PER_UNIT - 1); + + /* Find the smallest nice mode to use. + ??? Possibly use get_best_mode with appropriate arguments instead + (which would eventually require splitting representatives here). */ + for (modesize = bitsize; modesize <= maxbitsize; modesize += BITS_PER_UNIT) + { + mode = mode_for_size (modesize, MODE_INT, 1); + if (mode != BLKmode) + break; + } + + if (mode == BLKmode) + { + /* We really want a BLKmode representative only as a last resort, + considering the member b in + struct { int a : 7; int b : 17; int c; } __attribute__((packed)); + Otherwise we simply want to split the representative up + allowing for overlaps within the bitfield region as required for + struct { int a : 7; int b : 7; int c : 10; int d; } __attribute__((packed)); + [0, 15] HImode for a and b, [8, 23] HImode for c. */ + DECL_SIZE (repr) = bitsize_int (bitsize); + DECL_SIZE_UNIT (repr) = size_int (bitsize / BITS_PER_UNIT); + DECL_MODE (repr) = BLKmode; + TREE_TYPE (repr) = build_array_type_nelts (unsigned_char_type_node, + bitsize / BITS_PER_UNIT); + } + else + { + DECL_SIZE (repr) = bitsize_int (modesize); + DECL_SIZE_UNIT (repr) = size_int (modesize / BITS_PER_UNIT); + DECL_MODE (repr) = mode; + TREE_TYPE (repr) = lang_hooks.types.type_for_mode (mode, 1); + } + + /* Remember whether the bitfield group is at the end of the + structure or not. */ + DECL_CHAIN (repr) = nextf; + } + + /* Compute and set FIELD_DECLs for the underlying objects we should + use for bitfield access for the structure layed out with RLI. */ + + static void + finish_bitfield_layout (record_layout_info rli) + { + tree field, prev; + tree repr = NULL_TREE; + + /* Unions would be special, for the ease of type-punning optimizations + we could use the underlying type as hint for the representative + if the bitfield would fit and the representative would not exceed + the union in size. */ + if (TREE_CODE (rli->t) != RECORD_TYPE) + return; + + for (prev = NULL_TREE, field = TYPE_FIELDS (rli->t); + field; field = DECL_CHAIN (field)) + { + if (TREE_CODE (field) != FIELD_DECL) + continue; + + /* In the C++ memory model, consecutive bit fields in a structure are + considered one memory location and updating a memory location + may not store into adjacent memory locations. */ + if (!repr + && DECL_BIT_FIELD_TYPE (field)) + { + /* Start new representative. */ + repr = start_bitfield_representative (field); + } + else if (repr + && ! DECL_BIT_FIELD_TYPE (field)) + { + /* Finish off new representative. */ + finish_bitfield_representative (repr, prev); + repr = NULL_TREE; + } + else if (DECL_BIT_FIELD_TYPE (field)) + { + /* Zero-size bitfields finish off a representative and + do not have a representative themselves. This is + required by the C++ memory model. */ + if (integer_zerop (DECL_SIZE (field))) + { + finish_bitfield_representative (repr, prev); + repr = NULL_TREE; + } + } + else + continue; + + if (repr) + DECL_BIT_FIELD_REPRESENTATIVE (field) = repr; + + prev = field; + } + + if (repr) + finish_bitfield_representative (repr, prev); + } + /* Do all of the work required to layout the type indicated by RLI, once the fields have been laid out. This function will call `free' for RLI, unless FREE_P is false. Passing a value other than false *************** finish_record_layout (record_layout_info *** 1742,1747 **** --- 1923,1931 ---- /* Perform any last tweaks to the TYPE_SIZE, etc. */ finalize_type_size (rli->t); + /* Compute bitfield representatives. */ + finish_bitfield_layout (rli); + /* Propagate TYPE_PACKED to variants. With C++ templates, handle_packed_attribute is too early to do this. */ for (variant = TYPE_NEXT_VARIANT (rli->t); variant; Index: gcc/tree.h =================================================================== *** gcc/tree.h.orig 2012-02-07 11:04:21.000000000 +0100 --- gcc/tree.h 2012-02-07 11:05:20.000000000 +0100 *************** struct GTY(()) tree_decl_with_rtl { *** 3021,3026 **** --- 3021,3032 ---- #define DECL_BIT_FIELD_TYPE(NODE) \ (FIELD_DECL_CHECK (NODE)->field_decl.bit_field_type) + /* In a FIELD_DECL, this is a pointer to the storage representative + FIELD_DECL. + ??? Try harder to find a pointer we can re-use. */ + #define DECL_BIT_FIELD_REPRESENTATIVE(NODE) \ + (FIELD_DECL_CHECK (NODE)->field_decl.bit_field_representative) + /* For a FIELD_DECL in a QUAL_UNION_TYPE, records the expression, which if nonzero, indicates that the field occupies the type. */ #define DECL_QUALIFIER(NODE) (FIELD_DECL_CHECK (NODE)->field_decl.qualifier) *************** struct GTY(()) tree_field_decl { *** 3071,3076 **** --- 3077,3083 ---- tree offset; tree bit_field_type; + tree bit_field_representative; tree qualifier; tree bit_offset; tree fcontext; Index: gcc/gimplify.c =================================================================== *** gcc/gimplify.c.orig 2012-02-07 11:04:21.000000000 +0100 --- gcc/gimplify.c 2012-02-07 11:05:20.000000000 +0100 *************** gimplify_expr (tree *expr_p, gimple_seq *** 6887,6897 **** fallback != fb_none); break; case ARRAY_REF: case ARRAY_RANGE_REF: case REALPART_EXPR: case IMAGPART_EXPR: - case COMPONENT_REF: case VIEW_CONVERT_EXPR: ret = gimplify_compound_lval (expr_p, pre_p, post_p, fallback ? fallback : fb_rvalue); --- 6887,6931 ---- fallback != fb_none); break; + case COMPONENT_REF: + #if 0 + if (DECL_BIT_FIELD_TYPE (TREE_OPERAND (*expr_p, 1))) + { + tree field = TREE_OPERAND (*expr_p, 1); + tree repr = DECL_BIT_FIELD_REPRESENTATIVE (field); + gcc_assert (TREE_OPERAND (*expr_p, 2) == NULL_TREE); + if (repr != NULL_TREE) + { + tree offset; + offset = size_diffop (DECL_FIELD_OFFSET (field), + DECL_FIELD_OFFSET (repr)); + offset = size_binop (MULT_EXPR, + offset, ssize_int (BITS_PER_UNIT)); + offset = fold_convert (sbitsizetype, offset); + offset = size_binop (PLUS_EXPR, offset, + size_diffop (DECL_FIELD_BIT_OFFSET (field), + DECL_FIELD_BIT_OFFSET (repr))); + *expr_p = build3_loc (input_location, + BIT_FIELD_REF, + TREE_TYPE (*expr_p), + build3_loc (input_location, + COMPONENT_REF, + TREE_TYPE (repr), + TREE_OPERAND (*expr_p, 0), + repr, + NULL_TREE), + DECL_SIZE (field), offset); + ret = GS_OK; + break; + } + } + #endif + + /* Fall thru. */ case ARRAY_REF: case ARRAY_RANGE_REF: case REALPART_EXPR: case IMAGPART_EXPR: case VIEW_CONVERT_EXPR: ret = gimplify_compound_lval (expr_p, pre_p, post_p, fallback ? fallback : fb_rvalue); Index: gcc/tree-sra.c =================================================================== *** gcc/tree-sra.c.orig 2012-02-07 11:04:21.000000000 +0100 --- gcc/tree-sra.c 2012-02-07 11:05:20.000000000 +0100 *************** create_access_replacement (struct access *** 1922,1934 **** repl = create_tmp_var (access->type, "SR"); add_referenced_var (repl); ! if (rename) mark_sym_for_renaming (repl); ! if (!access->grp_partial_lhs ! && (TREE_CODE (access->type) == COMPLEX_TYPE ! || TREE_CODE (access->type) == VECTOR_TYPE)) ! DECL_GIMPLE_REG_P (repl) = 1; DECL_SOURCE_LOCATION (repl) = DECL_SOURCE_LOCATION (access->base); DECL_ARTIFICIAL (repl) = 1; --- 1922,1940 ---- repl = create_tmp_var (access->type, "SR"); add_referenced_var (repl); ! if (!access->grp_partial_lhs ! && rename) mark_sym_for_renaming (repl); ! if (TREE_CODE (access->type) == COMPLEX_TYPE ! || TREE_CODE (access->type) == VECTOR_TYPE) ! { ! if (!access->grp_partial_lhs) ! DECL_GIMPLE_REG_P (repl) = 1; ! } ! else if (access->grp_partial_lhs ! && is_gimple_reg_type (access->type)) ! TREE_ADDRESSABLE (repl) = 1; DECL_SOURCE_LOCATION (repl) = DECL_SOURCE_LOCATION (access->base); DECL_ARTIFICIAL (repl) = 1; Index: gcc/tree-cfg.c =================================================================== *** gcc/tree-cfg.c.orig 2012-02-07 11:04:21.000000000 +0100 --- gcc/tree-cfg.c 2012-02-07 11:05:20.000000000 +0100 *************** verify_expr (tree *tp, int *walk_subtree *** 2863,2879 **** error ("invalid position or size operand to BIT_FIELD_REF"); return t; } ! else if (INTEGRAL_TYPE_P (TREE_TYPE (t)) ! && (TYPE_PRECISION (TREE_TYPE (t)) ! != TREE_INT_CST_LOW (TREE_OPERAND (t, 1)))) { error ("integral result type precision does not match " "field size of BIT_FIELD_REF"); return t; } ! if (!INTEGRAL_TYPE_P (TREE_TYPE (t)) ! && (GET_MODE_PRECISION (TYPE_MODE (TREE_TYPE (t))) ! != TREE_INT_CST_LOW (TREE_OPERAND (t, 1)))) { error ("mode precision of non-integral result does not " "match field size of BIT_FIELD_REF"); --- 2863,2881 ---- error ("invalid position or size operand to BIT_FIELD_REF"); return t; } ! if (INTEGRAL_TYPE_P (TREE_TYPE (t)) ! && (TYPE_PRECISION (TREE_TYPE (t)) ! != TREE_INT_CST_LOW (TREE_OPERAND (t, 1)))) { error ("integral result type precision does not match " "field size of BIT_FIELD_REF"); return t; } ! else if (!INTEGRAL_TYPE_P (TREE_TYPE (t)) ! && !AGGREGATE_TYPE_P (TREE_TYPE (t)) ! && TYPE_MODE (TREE_TYPE (t)) != BLKmode ! && (GET_MODE_PRECISION (TYPE_MODE (TREE_TYPE (t))) ! != TREE_INT_CST_LOW (TREE_OPERAND (t, 1)))) { error ("mode precision of non-integral result does not " "match field size of BIT_FIELD_REF"); Index: gcc/expr.c =================================================================== *** gcc/expr.c.orig 2012-02-07 11:04:54.000000000 +0100 --- gcc/expr.c 2012-02-07 11:46:53.000000000 +0100 *************** optimize_bitfield_assignment_op (unsigne *** 4439,4551 **** /* In the C++ memory model, consecutive bit fields in a structure are considered one memory location. ! Given a COMPONENT_REF, this function returns the bit range of ! consecutive bits in which this COMPONENT_REF belongs in. The ! values are returned in *BITSTART and *BITEND. If either the C++ ! memory model is not activated, or this memory access is not thread ! visible, 0 is returned in *BITSTART and *BITEND. ! ! EXP is the COMPONENT_REF. ! INNERDECL is the actual object being referenced. ! BITPOS is the position in bits where the bit starts within the structure. ! BITSIZE is size in bits of the field being referenced in EXP. ! ! For example, while storing into FOO.A here... ! ! struct { ! BIT 0: ! unsigned int a : 4; ! unsigned int b : 1; ! BIT 8: ! unsigned char c; ! unsigned int d : 6; ! } foo; ! ! ...we are not allowed to store past <b>, so for the layout above, a ! range of 0..7 (because no one cares if we store into the ! padding). */ static void get_bit_range (unsigned HOST_WIDE_INT *bitstart, unsigned HOST_WIDE_INT *bitend, ! tree exp, tree innerdecl, ! HOST_WIDE_INT bitpos, HOST_WIDE_INT bitsize) { ! tree field, record_type, fld; ! bool found_field = false; ! bool prev_field_is_bitfield; gcc_assert (TREE_CODE (exp) == COMPONENT_REF); ! /* If other threads can't see this value, no need to restrict stores. */ ! if (ALLOW_STORE_DATA_RACES ! || ((TREE_CODE (innerdecl) == MEM_REF ! || TREE_CODE (innerdecl) == TARGET_MEM_REF) ! && !ptr_deref_may_alias_global_p (TREE_OPERAND (innerdecl, 0))) ! || (DECL_P (innerdecl) ! && ((TREE_CODE (innerdecl) == VAR_DECL ! && DECL_THREAD_LOCAL_P (innerdecl)) ! || !TREE_STATIC (innerdecl)))) { *bitstart = *bitend = 0; return; } ! /* Bit field we're storing into. */ ! field = TREE_OPERAND (exp, 1); ! record_type = DECL_FIELD_CONTEXT (field); ! ! /* Count the contiguous bitfields for the memory location that ! contains FIELD. */ ! *bitstart = 0; ! prev_field_is_bitfield = true; ! for (fld = TYPE_FIELDS (record_type); fld; fld = DECL_CHAIN (fld)) ! { ! tree t, offset; ! enum machine_mode mode; ! int unsignedp, volatilep; ! ! if (TREE_CODE (fld) != FIELD_DECL) ! continue; ! ! t = build3 (COMPONENT_REF, TREE_TYPE (exp), ! unshare_expr (TREE_OPERAND (exp, 0)), ! fld, NULL_TREE); ! get_inner_reference (t, &bitsize, &bitpos, &offset, ! &mode, &unsignedp, &volatilep, true); ! ! if (field == fld) ! found_field = true; ! ! if (DECL_BIT_FIELD_TYPE (fld) && bitsize > 0) ! { ! if (prev_field_is_bitfield == false) ! { ! *bitstart = bitpos; ! prev_field_is_bitfield = true; ! } ! } ! else ! { ! prev_field_is_bitfield = false; ! if (found_field) ! break; ! } ! } ! gcc_assert (found_field); ! if (fld) ! { ! /* We found the end of the bit field sequence. Include the ! padding up to the next field and be done. */ ! *bitend = bitpos - 1; ! } ! else ! { ! /* If this is the last element in the structure, include the padding ! at the end of structure. */ ! *bitend = TREE_INT_CST_LOW (TYPE_SIZE (record_type)) - 1; ! } } /* Returns true if the MEM_REF REF refers to an object that does not --- 4439,4481 ---- /* In the C++ memory model, consecutive bit fields in a structure are considered one memory location. ! Given a COMPONENT_REF EXP at bit position BITPOS, this function ! returns the bit range of consecutive bits in which this COMPONENT_REF ! belongs in. The values are returned in *BITSTART and *BITEND. ! If the access does not need to be restricted 0 is returned in ! *BITSTART and *BITEND. */ static void get_bit_range (unsigned HOST_WIDE_INT *bitstart, unsigned HOST_WIDE_INT *bitend, ! tree exp, ! HOST_WIDE_INT bitpos) { ! unsigned HOST_WIDE_INT bitoffset; ! tree field, repr, offset; gcc_assert (TREE_CODE (exp) == COMPONENT_REF); ! field = TREE_OPERAND (exp, 1); ! repr = DECL_BIT_FIELD_REPRESENTATIVE (field); ! /* If we do not have a DECL_BIT_FIELD_REPRESENTATIVE there is no ! need to limit the range we can access. */ ! if (!repr) { *bitstart = *bitend = 0; return; } ! /* Compute the adjustment to bitpos from the offset of the field ! relative to the representative. */ ! offset = size_diffop (DECL_FIELD_OFFSET (field), ! DECL_FIELD_OFFSET (repr)); ! bitoffset = (tree_low_cst (offset, 1) * BITS_PER_UNIT ! + tree_low_cst (DECL_FIELD_BIT_OFFSET (field), 1) ! - tree_low_cst (DECL_FIELD_BIT_OFFSET (repr), 1)); ! *bitstart = bitpos - bitoffset; ! *bitend = *bitstart + tree_low_cst (DECL_SIZE (repr), 1); } /* Returns true if the MEM_REF REF refers to an object that does not *************** expand_assignment (tree to, tree from, b *** 4673,4680 **** if (TREE_CODE (to) == COMPONENT_REF && DECL_BIT_FIELD_TYPE (TREE_OPERAND (to, 1))) ! get_bit_range (&bitregion_start, &bitregion_end, ! to, tem, bitpos, bitsize); /* If we are going to use store_bit_field and extract_bit_field, make sure to_rtx will be safe for multiple use. */ --- 4603,4609 ---- if (TREE_CODE (to) == COMPONENT_REF && DECL_BIT_FIELD_TYPE (TREE_OPERAND (to, 1))) ! get_bit_range (&bitregion_start, &bitregion_end, to, bitpos); /* If we are going to use store_bit_field and extract_bit_field, make sure to_rtx will be safe for multiple use. */ Index: gcc/testsuite/gcc.dg/torture/pr48124-1.c =================================================================== *** /dev/null 1970-01-01 00:00:00.000000000 +0000 --- gcc/testsuite/gcc.dg/torture/pr48124-1.c 2012-02-07 11:05:20.000000000 +0100 *************** *** 0 **** --- 1,33 ---- + /* { dg-do run } */ + /* { dg-options "-fno-toplevel-reorder" } */ + + extern void abort (void); + + struct S + { + signed a : 26; + signed b : 16; + signed c : 10; + volatile signed d : 14; + }; + + static struct S e = { 0, 0, 0, 1 }; + static int f = 1; + + void __attribute__((noinline)) + foo (void) + { + e.d = 0; + f = 2; + } + + int + main () + { + if (e.a || e.b || e.c || e.d != 1 || f != 1) + abort (); + foo (); + if (e.a || e.b || e.c || e.d || f != 2) + abort (); + return 0; + } Index: gcc/testsuite/gcc.dg/torture/pr48124-2.c =================================================================== *** /dev/null 1970-01-01 00:00:00.000000000 +0000 --- gcc/testsuite/gcc.dg/torture/pr48124-2.c 2012-02-07 11:05:20.000000000 +0100 *************** *** 0 **** --- 1,27 ---- + /* { dg-do run } */ + + extern void abort (void); + + static volatile struct S0 { + short f3[9]; + unsigned f8 : 15; + } s = {1}; + static unsigned short sh = 0x1234; + + struct S0 a, b; + int vi = 0; + + void func_4() + { + s.f8 |= 1; + sh = 15; + if (vi) a = b; + } + + int main() + { + func_4(); + if (sh != 15) + abort (); + return 0; + } Index: gcc/testsuite/gcc.dg/torture/pr48124-3.c =================================================================== *** /dev/null 1970-01-01 00:00:00.000000000 +0000 --- gcc/testsuite/gcc.dg/torture/pr48124-3.c 2012-02-07 11:05:20.000000000 +0100 *************** *** 0 **** --- 1,32 ---- + /* { dg-do run } */ + + extern void abort (void); + struct S1 + { + int f0; + int:1; + int f3; + int:1; + int:0; + int f6:1; + }; + int g_13 = 1; + volatile struct S1 g_118 = { + 1 + }; + + void __attribute__((noinline)) + func_46 () + { + for (g_13 = 0; g_13 >= 0; g_13 -= 1) + g_118.f6 = 0; + } + + int + main () + { + func_46 (); + if (g_13 != -1) + abort (); + return 0; + } Index: gcc/testsuite/gcc.dg/torture/pr48124-4.c =================================================================== *** /dev/null 1970-01-01 00:00:00.000000000 +0000 --- gcc/testsuite/gcc.dg/torture/pr48124-4.c 2012-02-07 11:05:20.000000000 +0100 *************** *** 0 **** --- 1,28 ---- + /* { dg-do run } */ + + extern void abort (void); + struct S1 { + unsigned f0, f1; + unsigned short f2, f3; + unsigned f4 : 16; + unsigned f5, f6; + volatile unsigned f7 : 28; + }; + static struct S1 g_76; + static struct S1 g_245 = {0,0,0,0,0,0,0,1}; + static signed char g_323 = 0x80; + static void func_1(void) + { + g_245.f7 &= 1; + for (g_323 = 0; g_323 <= -1; g_323 -= 2) { + g_76 = g_76; + g_76.f4 ^= 11; + } + } + int main() + { + func_1(); + if (g_323 != 0 || g_245.f7 != 1) + abort (); + return 0; + } Index: gcc/tree-streamer-in.c =================================================================== *** gcc/tree-streamer-in.c.orig 2012-02-07 11:04:21.000000000 +0100 --- gcc/tree-streamer-in.c 2012-02-07 11:05:20.000000000 +0100 *************** lto_input_ts_field_decl_tree_pointers (s *** 642,647 **** --- 642,648 ---- DECL_BIT_FIELD_TYPE (expr) = stream_read_tree (ib, data_in); DECL_QUALIFIER (expr) = stream_read_tree (ib, data_in); DECL_FIELD_BIT_OFFSET (expr) = stream_read_tree (ib, data_in); + DECL_BIT_FIELD_REPRESENTATIVE (expr) = stream_read_tree (ib, data_in); DECL_FCONTEXT (expr) = stream_read_tree (ib, data_in); } Index: gcc/tree-streamer-out.c =================================================================== *** gcc/tree-streamer-out.c.orig 2012-02-07 11:04:21.000000000 +0100 --- gcc/tree-streamer-out.c 2012-02-07 11:05:20.000000000 +0100 *************** write_ts_field_decl_tree_pointers (struc *** 554,559 **** --- 554,560 ---- stream_write_tree (ob, DECL_BIT_FIELD_TYPE (expr), ref_p); stream_write_tree (ob, DECL_QUALIFIER (expr), ref_p); stream_write_tree (ob, DECL_FIELD_BIT_OFFSET (expr), ref_p); + stream_write_tree (ob, DECL_BIT_FIELD_REPRESENTATIVE (expr), ref_p); stream_write_tree (ob, DECL_FCONTEXT (expr), ref_p); }