Hi! The following patch implements P0386R1 - NSDMIs for bit-fields. While working on that, I've discovered our parser mishandles attributes on bitfields, already C++11 says: identifier[opt] attribute-specifier-seq[opt] : constant-expression in the grammar, but we actually parsed identifier[opt] : constant-expression attribute-specifier-seq[opt]
I had to resolve a few issues: 1) cp_parser_constant_expression doesn't actually parse a constant-expression, but a constant assignment-expression; the rationale is that it gives better diagnostics etc. For the bitfield parsing, we really need a constant expression. The patch has the parsing code inline, another option is to adjust cp_parser_constant_expression so that it has (a defaulted) bool argument strict or something similar and if that argument is true, don't call cp_parser_assignment_expression in it, but instead do inline the cp_expr expr = cp_parser_binary_expression (parser, false, false, false, PREC_NOT_OPERATOR, NULL); /* If the next token is a `?' then we're actually looking at a conditional-expression; otherwise we're done. */ if (cp_lexer_next_token_is (parser->lexer, CPP_QUERY)) expr = cp_parser_question_colon_clause (parser, expr); part. Another option is to add another argument to cp_parser_assignment_expression too and do it in there, or add cp_parser_conditional_expression and call it conditionally from cp_parser_constant_expression (based on this strict or force_conditional or whatever arg) and unconditionally from cp_parser_assignment_expression. Preferences? 2) the above attribute issue; in the patch I parse attributes in both spots unless NSDMI is present (in that case only at the right spot, since there is no need for backwards compatibility). Should there be some pedwarn or something similar if attributes appear in the old (incorrect) spot? Only for C++11 attributes or for both C++11 and GNU? 3) we were temporarily (until check_bitfield_decl) stashing the bit width expression in DECL_INITIAL, which obviously doesn't work too well when we need to stash the NSDMI there temporarily. I've tried to put it temporarily into DECL_SIZE, but that doesn't work too well, because e.g. variably_modified_type_p is called on still incomplete aggregate types and it then thinks that such incomplete type is variable length. So in the end I'm temporarily abusing DECL_BIT_FIELD_REPRESENTATIVE, which seems to work fine (the middle-end only uses it after the type is completed). 4) I hope default member initializers aren't valid for unnamed bit-fields, but am not 100% sure if the current standard wording really disallows it. There is: "A brace-or-equal-initializer shall appear only in the declaration of a data member." so, are unnamed bit-fields not data members? There is additionally "A data member is a non-function member introduced by a member-declarator." and a paragraph before says that unnamed bit-field is not a member of the class. Bootstrapped/regtested on x86_64-linux and i686-linux (including make check-c++-all), ok for trunk? Or any preferences on 1) or 2) above? 2017-09-19 Jakub Jelinek <ja...@redhat.com> P0386R1 - default member initializers for bit-fields c-family/ * c-attribs.c (handle_packed_attribute): Test DECL_C_BIT_FIELD rather than DECL_INITIAL. (common_handle_aligned_attribute): Likewise. c/ * c-decl.c (grokfield): Use SET_DECL_C_BIT_FIELD here if with is non-NULL. (finish_struct): Test DECL_C_BIT_FIELD instead of DECL_INITIAL, don't SET_DECL_C_BIT_FIELD here. cp/ * cp-tree.h (grokbitfield): Add INIT parameter. * parser.c (cp_parser_member_declaration): Parse attributes before colon of a bitfield in addition to after colon. Parse C++2A bitfield NSDMIs. Adjust grokbitfield caller. Handle DECL_INITIAL also for DECL_C_BIT_FIELDs. (cp_parser_objc_class_ivars): Adjust grokbitfield caller. * class.c (check_bitfield_decl): Retrieve and clear width from DECL_BIT_FIELD_REPRESENTATIVE rather than DECL_INITIAL. (check_field_decl): Recurse even for DECL_C_BIT_FIELDs. (check_field_decls): Test DECL_BIT_FIELD_REPRESENTATIVE rather than DECL_INITIAL. (remove_zero_width_bit_fields): Adjust comment. * decl2.c (grokbitfield): Add INIT parameter, pass it to cp_finish_decl. Stash width into DECL_BIT_FIELD_REPRESENTATIVE rather than DECL_INITIAL. * pt.c (tsubst_decl): For DECL_C_BIT_FIELD, tsubst_expr DECL_BIT_FIELD_REPRESENTATIVE rather than DECL_INITIAL for width, and handle DECL_INITIAL for all FIELD_DECLs, not just non-bitfields. * Make-lang.in (check-c++-all): Test also c++2a. objc/ * objc-act.c (check_ivars, gen_declaration): For OBJCPLUS look at DECL_BIT_FIELD_REPRESENTATIVE rather than DECL_INITIAL. testsuite/ * g++.dg/ext/bitfield6.C: New test. * g++.dg/ext/bitfield7.C: New test. * g++.dg/ext/bitfield8.C: New test. * g++.dg/cpp2a/bitfield1.C: New test. * g++.dg/cpp2a/bitfield2.C: New test. * g++.dg/cpp2a/bitfield3.C: New test. --- gcc/c-family/c-attribs.c.jj 2017-09-18 20:48:53.731871226 +0200 +++ gcc/c-family/c-attribs.c 2017-09-19 09:51:21.928612658 +0200 @@ -426,7 +426,7 @@ handle_packed_attribute (tree *node, tre { if (TYPE_ALIGN (TREE_TYPE (*node)) <= BITS_PER_UNIT /* Still pack bitfields. */ - && ! DECL_INITIAL (*node)) + && ! DECL_C_BIT_FIELD (*node)) warning (OPT_Wattributes, "%qE attribute ignored for field of type %qT", name, TREE_TYPE (*node)); @@ -1773,7 +1773,7 @@ common_handle_aligned_attribute (tree *n { if (warn_if_not_aligned_p) { - if (TREE_CODE (decl) == FIELD_DECL && !DECL_INITIAL (decl)) + if (TREE_CODE (decl) == FIELD_DECL && !DECL_C_BIT_FIELD (decl)) { SET_DECL_WARN_IF_NOT_ALIGN (decl, (1U << i) * BITS_PER_UNIT); warn_if_not_aligned_p = false; --- gcc/c/c-decl.c.jj 2017-09-12 21:57:59.000000000 +0200 +++ gcc/c/c-decl.c 2017-09-19 10:43:30.898898784 +0200 @@ -7602,6 +7602,8 @@ grokfield (location_t loc, finish_decl (value, loc, NULL_TREE, NULL_TREE, NULL_TREE); DECL_INITIAL (value) = width; + if (width) + SET_DECL_C_BIT_FIELD (value); if (warn_cxx_compat && DECL_NAME (value) != NULL_TREE) { @@ -7946,12 +7948,11 @@ finish_struct (location_t loc, tree t, t if (C_DECL_VARIABLE_SIZE (x)) C_TYPE_VARIABLE_SIZE (t) = 1; - if (DECL_INITIAL (x)) + if (DECL_C_BIT_FIELD (x)) { unsigned HOST_WIDE_INT width = tree_to_uhwi (DECL_INITIAL (x)); DECL_SIZE (x) = bitsize_int (width); DECL_BIT_FIELD (x) = 1; - SET_DECL_C_BIT_FIELD (x); } if (TYPE_PACKED (t) --- gcc/cp/cp-tree.h.jj 2017-09-18 20:48:53.539873617 +0200 +++ gcc/cp/cp-tree.h 2017-09-19 09:51:21.917612801 +0200 @@ -6151,7 +6151,7 @@ extern void check_member_template (tree extern tree grokfield (const cp_declarator *, cp_decl_specifier_seq *, tree, bool, tree, tree); extern tree grokbitfield (const cp_declarator *, cp_decl_specifier_seq *, - tree, tree); + tree, tree, tree); extern bool any_dependent_type_attributes_p (tree); extern tree cp_reconstruct_complex_type (tree, tree); extern bool attributes_naming_typedef_ok (tree); --- gcc/cp/parser.c.jj 2017-09-18 20:48:53.480874352 +0200 +++ gcc/cp/parser.c 2017-09-19 09:51:21.915612827 +0200 @@ -23412,35 +23412,133 @@ cp_parser_member_declaration (cp_parser* { tree attributes = NULL_TREE; tree first_attribute; + tree initializer; + bool is_bitfld = false; + bool named_bitfld = false; /* Peek at the next token. */ token = cp_lexer_peek_token (parser->lexer); + if (cp_next_tokens_can_be_attribute_p (parser) + || (token->type == CPP_NAME + && cp_nth_tokens_can_be_attribute_p (parser, 2) + && (named_bitfld = true))) + { + cp_parser_parse_tentatively (parser); + if (named_bitfld) + cp_lexer_consume_token (parser->lexer); + cp_parser_attributes_opt (parser); + token = cp_lexer_peek_token (parser->lexer); + is_bitfld = cp_lexer_next_token_is (parser->lexer, CPP_COLON); + cp_parser_abort_tentative_parse (parser); + } + /* Check for a bitfield declaration. */ - if (token->type == CPP_COLON + if (is_bitfld + || token->type == CPP_COLON || (token->type == CPP_NAME - && cp_lexer_peek_nth_token (parser->lexer, 2)->type - == CPP_COLON)) + && cp_lexer_nth_token_is (parser->lexer, 2, CPP_COLON) + && (named_bitfld = true))) { tree identifier; tree width; + tree late_attributes = NULL_TREE; - /* Get the name of the bitfield. Note that we cannot just - check TOKEN here because it may have been invalidated by - the call to cp_lexer_peek_nth_token above. */ - if (cp_lexer_peek_token (parser->lexer)->type != CPP_COLON) + if (named_bitfld) identifier = cp_parser_identifier (parser); else identifier = NULL_TREE; + /* Look for attributes that apply to the bitfield. */ + attributes = cp_parser_attributes_opt (parser); + /* Consume the `:' token. */ cp_lexer_consume_token (parser->lexer); + initializer = NULL_TREE; /* Get the width of the bitfield. */ - width - = cp_parser_constant_expression (parser); + if (cxx_dialect >= cxx11) + { + /* In C++2A and as extension for C++11 and above we allow + NSDMI for bit-fields. As cp_parser_constant_expression + doesn't actually parse a constant-expression, i.e. + conditional-expression, but assignment-expression, we + can't use cp_parser_constant_expression for this. */ + bool saved_integral_constant_expression_p + = parser->integral_constant_expression_p; + bool saved_allow_non_integral_constant_expression_p + = parser->allow_non_integral_constant_expression_p; + bool saved_non_integral_constant_expression_p + = parser->non_integral_constant_expression_p; + /* We are now parsing a constant-expression. */ + parser->integral_constant_expression_p = true; + parser->allow_non_integral_constant_expression_p = true; + parser->non_integral_constant_expression_p = false; + + /* Parse the binary expressions (logical-or-expression). */ + cp_expr expr + = cp_parser_binary_expression (parser, false, false, false, + PREC_NOT_OPERATOR, NULL); + /* If the next token is a `?' then we're actually looking at + a conditional-expression; otherwise we're done. */ + if (cp_lexer_next_token_is (parser->lexer, CPP_QUERY)) + expr = cp_parser_question_colon_clause (parser, expr); + + parser->integral_constant_expression_p + = saved_integral_constant_expression_p; + parser->allow_non_integral_constant_expression_p + = saved_allow_non_integral_constant_expression_p; + tree decay = expr; + if (TREE_TYPE (expr) + && TREE_CODE (TREE_TYPE (expr)) == ARRAY_TYPE) + decay = build_address (expr); + bool is_const = potential_rvalue_constant_expression (decay); + parser->non_integral_constant_expression_p = !is_const; + if (!is_const) + require_potential_rvalue_constant_expression (decay); + parser->non_integral_constant_expression_p + = saved_non_integral_constant_expression_p; + + width = expr; + + /* Now save the NSDMI if any. */ + if (cp_lexer_next_token_is (parser->lexer, CPP_EQ) + || cp_lexer_next_token_is (parser->lexer, + CPP_OPEN_BRACE)) + { + location_t loc + = cp_lexer_peek_token (parser->lexer)->location; + if (cxx_dialect < cxx2a + && !in_system_header_at (loc) + && identifier != NULL_TREE) + pedwarn (loc, 0, + "default member initializers for bit-fields " + "only available with -std=c++2a or " + "-std=gnu++2a"); + + initializer = cp_parser_save_nsdmi (parser); + if (identifier == NULL_TREE) + { + error_at (loc, "default member initializer for " + "unnamed bit-field"); + initializer = NULL_TREE; + } + } + else + /* Look for attributes that apply to the bitfield; we + used to be parsing attributes here instead of the + the standard required spot before the colon. + Only parse them here when not using NSDMI. */ + late_attributes = cp_parser_attributes_opt (parser); + } + else + { + width = cp_parser_constant_expression (parser); + /* Look for attributes that apply to the bitfield. */ + late_attributes = cp_parser_attributes_opt (parser); + } + + attributes = chainon (attributes, late_attributes); - /* Look for attributes that apply to the bitfield. */ - attributes = cp_parser_attributes_opt (parser); /* Remember which attributes are prefix attributes and which are not. */ first_attribute = attributes; @@ -23454,13 +23552,12 @@ cp_parser_member_declaration (cp_parser* sfk_none) : NULL, &decl_specifiers, - width, + width, initializer, attributes); } else { cp_declarator *declarator; - tree initializer; tree asm_specification; int ctor_dtor_or_conv_p; @@ -23679,7 +23776,6 @@ cp_parser_member_declaration (cp_parser* if (TREE_CODE (decl) == FUNCTION_DECL) cp_parser_save_default_args (parser, decl); else if (TREE_CODE (decl) == FIELD_DECL - && !DECL_C_BIT_FIELD (decl) && DECL_INITIAL (decl)) /* Add DECL to the queue of NSDMI to be parsed later. */ vec_safe_push (unparsed_nsdmis, decl); @@ -30020,10 +30116,9 @@ cp_parser_objc_class_ivars (cp_parser* p attributes = chainon (prefix_attributes, attributes); if (width) - /* Create the bitfield declaration. */ - decl = grokbitfield (declarator, &declspecs, - width, - attributes); + /* Create the bitfield declaration. */ + decl = grokbitfield (declarator, &declspecs, + width, NULL_TREE, attributes); else decl = grokfield (declarator, &declspecs, NULL_TREE, /*init_const_expr_p=*/false, --- gcc/cp/class.c.jj 2017-09-18 20:48:53.509873991 +0200 +++ gcc/cp/class.c 2017-09-19 10:31:35.435961690 +0200 @@ -3231,12 +3231,12 @@ check_bitfield_decl (tree field) tree w; /* Extract the declared width of the bitfield, which has been - temporarily stashed in DECL_INITIAL. */ - w = DECL_INITIAL (field); + temporarily stashed in DECL_BIT_FIELD_REPRESENTATIVE. */ + w = DECL_BIT_FIELD_REPRESENTATIVE (field); gcc_assert (w != NULL_TREE); /* Remove the bit-field width indicator so that the rest of the - compiler does not treat that value as an initializer. */ - DECL_INITIAL (field) = NULL_TREE; + compiler does not treat that value as a qualifier. */ + DECL_BIT_FIELD_REPRESENTATIVE (field) = NULL_TREE; /* Detect invalid bit-field type. */ if (!INTEGRAL_OR_ENUMERATION_TYPE_P (type)) @@ -3324,7 +3324,7 @@ check_field_decl (tree field, { for (tree fields = TYPE_FIELDS (type); fields; fields = DECL_CHAIN (fields)) - if (TREE_CODE (fields) == FIELD_DECL && !DECL_C_BIT_FIELD (field)) + if (TREE_CODE (fields) == FIELD_DECL) any_default_members |= check_field_decl (fields, t, cant_have_const_ctor, no_const_asn_ref); @@ -3571,7 +3571,8 @@ check_field_decls (tree t, tree *access_ DECL_PACKED (x) = 1; } - if (DECL_C_BIT_FIELD (x) && integer_zerop (DECL_INITIAL (x))) + if (DECL_C_BIT_FIELD (x) + && integer_zerop (DECL_BIT_FIELD_REPRESENTATIVE (x))) /* We don't treat zero-width bitfields as making a class non-empty. */ ; @@ -3635,10 +3636,10 @@ check_field_decls (tree t, tree *access_ /* We set DECL_C_BIT_FIELD in grokbitfield. If the type and width are valid, we'll also set DECL_BIT_FIELD. */ - if ((! DECL_C_BIT_FIELD (x) || ! check_bitfield_decl (x)) - && check_field_decl (x, t, - cant_have_const_ctor_p, - no_const_asn_ref_p)) + if (DECL_C_BIT_FIELD (x)) + check_bitfield_decl (x); + + if (check_field_decl (x, t, cant_have_const_ctor_p, no_const_asn_ref_p)) { if (any_default_members && TREE_CODE (t) == UNION_TYPE) @@ -5268,9 +5269,9 @@ remove_zero_width_bit_fields (tree t) { if (TREE_CODE (*fieldsp) == FIELD_DECL && DECL_C_BIT_FIELD (*fieldsp) - /* We should not be confused by the fact that grokbitfield + /* We should not be confused by the fact that grokbitfield temporarily sets the width of the bit field into - DECL_INITIAL (*fieldsp). + DECL_BIT_FIELD_REPRESENTATIVE (*fieldsp). check_bitfield_decl eventually sets DECL_SIZE (*fieldsp) to that width. */ && (DECL_SIZE (*fieldsp) == NULL_TREE --- gcc/cp/decl2.c.jj 2017-09-18 20:48:53.388875498 +0200 +++ gcc/cp/decl2.c 2017-09-19 10:31:45.066839694 +0200 @@ -973,10 +973,11 @@ grokfield (const cp_declarator *declarat tree grokbitfield (const cp_declarator *declarator, - cp_decl_specifier_seq *declspecs, tree width, + cp_decl_specifier_seq *declspecs, tree width, tree init, tree attrlist) { - tree value = grokdeclarator (declarator, declspecs, BITFIELD, 0, &attrlist); + tree value = grokdeclarator (declarator, declspecs, BITFIELD, + init != NULL_TREE, &attrlist); if (value == error_mark_node) return NULL_TREE; /* friends went bad. */ @@ -1031,7 +1032,11 @@ grokbitfield (const cp_declarator *decla error ("static member %qD cannot be a bit-field", value); return NULL_TREE; } - cp_finish_decl (value, NULL_TREE, false, NULL_TREE, 0); + + int flags = LOOKUP_IMPLICIT; + if (init && DIRECT_LIST_INIT_P (init)) + flags = LOOKUP_NORMAL; + cp_finish_decl (value, init, false, NULL_TREE, flags); if (width != error_mark_node) { @@ -1042,7 +1047,8 @@ grokbitfield (const cp_declarator *decla TREE_TYPE (width)); else { - DECL_INITIAL (value) = width; + /* Temporarily stash the width in DECL_BIT_FIELD_REPRESENTATIVE. */ + DECL_BIT_FIELD_REPRESENTATIVE (value) = width; SET_DECL_C_BIT_FIELD (value); } } --- gcc/cp/pt.c.jj 2017-09-18 20:48:53.435874912 +0200 +++ gcc/cp/pt.c 2017-09-19 10:31:56.250698026 +0200 @@ -12809,14 +12809,13 @@ tsubst_decl (tree t, tree args, tsubst_f cp_apply_type_quals_to_decl (cp_type_quals (type), r); if (DECL_C_BIT_FIELD (r)) - /* For bit-fields, DECL_INITIAL gives the number of bits. For - non-bit-fields DECL_INITIAL is a non-static data member - initializer, which gets deferred instantiation. */ - DECL_INITIAL (r) - = tsubst_expr (DECL_INITIAL (t), args, + /* For bit-fields, DECL_BIT_FIELD_REPRESENTATIVE gives the + number of bits. */ + DECL_BIT_FIELD_REPRESENTATIVE (r) + = tsubst_expr (DECL_BIT_FIELD_REPRESENTATIVE (t), args, complain, in_decl, /*integral_constant_expression_p=*/true); - else if (DECL_INITIAL (t)) + if (DECL_INITIAL (t)) { /* Set up DECL_TEMPLATE_INFO so that we can get at the NSDMI in perform_member_init. Still set DECL_INITIAL --- gcc/cp/Make-lang.in.jj 2017-09-18 20:48:53.592872957 +0200 +++ gcc/cp/Make-lang.in 2017-09-19 09:51:21.918612788 +0200 @@ -176,7 +176,7 @@ check-c++17: # Run the testsuite in all standard conformance levels. check-c++-all: - $(MAKE) RUNTESTFLAGS="$(RUNTESTFLAGS) --stds=98,11,14,17,concepts" check-g++ + $(MAKE) RUNTESTFLAGS="$(RUNTESTFLAGS) --stds=98,11,14,17,2a,concepts" check-g++ # Run the testsuite with garbage collection at every opportunity. check-g++-strict-gc: --- gcc/objc/objc-act.c.jj 2017-01-01 12:45:46.000000000 +0100 +++ gcc/objc/objc-act.c 2017-09-19 13:01:06.917412755 +0200 @@ -4602,8 +4602,14 @@ check_ivars (tree inter, tree imp) t1 = TREE_TYPE (intdecls); t2 = TREE_TYPE (impdecls); if (!comptypes (t1, t2) +#ifdef OBJCPLUS + || !tree_int_cst_equal (DECL_BIT_FIELD_REPRESENTATIVE (intdecls), + DECL_BIT_FIELD_REPRESENTATIVE (impdecls)) +#else || !tree_int_cst_equal (DECL_INITIAL (intdecls), - DECL_INITIAL (impdecls))) + DECL_INITIAL (impdecls)) +#endif + ) { if (DECL_NAME (intdecls) == DECL_NAME (impdecls)) { @@ -8895,10 +8901,14 @@ gen_declaration (tree decl) strcat (errbuf, IDENTIFIER_POINTER (DECL_NAME (decl))); } - if (DECL_INITIAL (decl) - && TREE_CODE (DECL_INITIAL (decl)) == INTEGER_CST) +#ifdef OBJCPLUS + tree w = DECL_BIT_FIELD_REPRESENTATIVE (decl); +#else + tree w = DECL_INITIAL (decl); +#endif + if (w && TREE_CODE (w) == INTEGER_CST) sprintf (errbuf + strlen (errbuf), ": " HOST_WIDE_INT_PRINT_DEC, - TREE_INT_CST_LOW (DECL_INITIAL (decl))); + TREE_INT_CST_LOW (w)); } return errbuf; --- gcc/testsuite/g++.dg/ext/bitfield6.C.jj 2017-09-19 10:26:48.005602981 +0200 +++ gcc/testsuite/g++.dg/ext/bitfield6.C 2017-09-19 10:25:54.000000000 +0200 @@ -0,0 +1,15 @@ +// { dg-do compile { target c++11 } } +// { dg-options "" } + +struct S { + char a [[gnu::packed]] = 1; // { dg-warning "attribute ignored for field of type" } + char b [[gnu::packed]] : 8; + char c [[gnu::packed]] : 8 = 2; // { dg-warning "default member initializers for bit-fields only available with" "" { target c++17_down } } +}; +template <typename U> +struct T { + U d [[gnu::packed]] = 1; // { dg-warning "attribute ignored for field of type" } + U e [[gnu::packed]] : 8; + U f [[gnu::packed]] : 8 = 2; // { dg-warning "default member initializers for bit-fields only available with" "" { target c++17_down } } +}; +T<char> t; --- gcc/testsuite/g++.dg/ext/bitfield7.C.jj 2017-09-19 10:27:07.128360543 +0200 +++ gcc/testsuite/g++.dg/ext/bitfield7.C 2017-09-19 10:27:21.596177128 +0200 @@ -0,0 +1,12 @@ +/* { dg-do compile } */ +/* { dg-options "" } */ +/* { dg-options "-Wno-packed-bitfield-compat -mno-ms-bitfields" { target { i?86-*-mingw* x86_64-*-mingw* } } } */ + +struct t /* { dg-message "note: offset of packed bit-field 't::b' has changed in GCC 4.4" "" { target pcc_bitfield_type_matters } } */ +{ + char a:4; + char b __attribute__ ((packed)) : 8; + char c:4; +}; + +int assrt[sizeof (struct t) == 2 ? 1 : -1]; --- gcc/testsuite/g++.dg/ext/bitfield8.C.jj 2017-09-19 10:28:06.911603108 +0200 +++ gcc/testsuite/g++.dg/ext/bitfield8.C 2017-09-19 10:28:23.663390910 +0200 @@ -0,0 +1,12 @@ +/* { dg-do compile { target c++11 } } */ +/* { dg-options "" } */ +/* { dg-options "-Wno-packed-bitfield-compat -mno-ms-bitfields" { target { i?86-*-mingw* x86_64-*-mingw* } } } */ + +struct t /* { dg-message "note: offset of packed bit-field 't::b' has changed in GCC 4.4" "" { target pcc_bitfield_type_matters } } */ +{ + char a:4; + char b [[gnu::packed]] : 8; + char c:4; +}; + +int assrt[sizeof (struct t) == 2 ? 1 : -1]; --- gcc/testsuite/g++.dg/cpp2a/bitfield1.C.jj 2017-09-19 09:51:21.927612671 +0200 +++ gcc/testsuite/g++.dg/cpp2a/bitfield1.C 2017-09-19 09:51:21.927612671 +0200 @@ -0,0 +1,77 @@ +// P0683R1 +// { dg-do run { target c++11 } } +// { dg-options "" } + +extern "C" void abort (); +int a; +const int b = 0; +struct S { + int c : 5 = 1; // { dg-warning "default member initializers for bit-fields only available with" "" { target c++17_down } } + int d : 6 { 2 }; // { dg-warning "default member initializers for bit-fields only available with" "" { target c++17_down } } + int e : true ? 7 : a = 3; + int f : (true ? 8 : b) = 4; // { dg-warning "default member initializers for bit-fields only available with" "" { target c++17_down } } + int g : (true ? 9 : b) { 5 }; // { dg-warning "default member initializers for bit-fields only available with" "" { target c++17_down } } + int h : 1 || new int { 0 }; +}; +#if __cplusplus >= 201402L +static_assert (S{}.c == 1); +static_assert (S{}.d == 2); +static_assert (S{}.e == 0); +static_assert (S{}.f == 4); +static_assert (S{}.g == 5); +static_assert (S{}.h == 0); +#endif +template <bool V, int W> +struct U { + int j : W = 7; // { dg-warning "default member initializers for bit-fields only available with" "" { target c++17_down } } + int k : W { 8 }; // { dg-warning "default member initializers for bit-fields only available with" "" { target c++17_down } } + int l : V ? 7 : a = 3; + int m : (V ? W : b) = 9; // { dg-warning "default member initializers for bit-fields only available with" "" { target c++17_down } } + int n : (V ? W : b) { 10 }; // { dg-warning "default member initializers for bit-fields only available with" "" { target c++17_down } } + int o : 1 || new int { 0 }; +}; +#if __cplusplus >= 201402L +static_assert (U<true, 12>{}.j == 7); +static_assert (U<true, 13>{}.k == 8); +static_assert (U<true, 10>{}.l == 0); +static_assert (U<true, 11>{}.m == 9); +static_assert (U<true, 8>{}.n == 10); +static_assert (U<true, 7>{}.o == 0); +#endif +S s; +U<true, 10> u; + +int +main () +{ + if (s.c != 1 || s.d != 2 || s.e != 0 || s.f != 4 || s.g != 5 || s.h != 0) + abort (); + s.c = 47; // { dg-warning "overflow in conversion from" } + s.d = 47 * 2; // { dg-warning "overflow in conversion from" } + s.e = 47 * 4; // { dg-warning "overflow in conversion from" } + s.f = 47 * 8; // { dg-warning "overflow in conversion from" } + s.g = 47 * 16; // { dg-warning "overflow in conversion from" } + s.h = 2; // { dg-warning "overflow in conversion from" } + if (s.c != 15 || s.d != 15 * 2 || s.e != 15 * 4 || s.f != 15 * 8 || s.g != 15 * 16 || s.h != 0) + abort (); + if (u.j != 7 || u.k != 8 || u.l != 0 || u.m != 9 || u.n != 10 || u.o != 0) + abort (); + u.j = 47 * 32; // { dg-warning "overflow in conversion from" } + u.k = 47 * 32; // { dg-warning "overflow in conversion from" } + u.l = 47 * 4; // { dg-warning "overflow in conversion from" } + u.m = 47 * 32; // { dg-warning "overflow in conversion from" } + u.n = 47 * 32; // { dg-warning "overflow in conversion from" } + u.o = 2; // { dg-warning "overflow in conversion from" } + if (u.j != 15 * 32 || u.k != 15 * 32 || u.l != 15 * 4 || u.m != 15 * 32 || u.n != 15 * 32 || u.o != 0) + abort (); + s.c = 15; + s.d = 15 * 2; + s.e = 15 * 4; + s.f = 16 * 8; + s.g = 15 * 16; + u.j = 15 * 32; + u.k = 15 * 32; + u.l = 15 * 4; + u.m = 15 * 32; + u.n = 15 * 32; +} --- gcc/testsuite/g++.dg/cpp2a/bitfield2.C.jj 2017-09-19 09:51:21.927612671 +0200 +++ gcc/testsuite/g++.dg/cpp2a/bitfield2.C 2017-09-19 09:51:21.927612671 +0200 @@ -0,0 +1,26 @@ +// P0683R1 +// { dg-do compile { target c++11 } } +// { dg-options "" } + +int a; +const int b = 0; +struct T { + int i : true ? 10 : b = 6; // { dg-error "assignment of read-only variable" } + int : 4 = 10; // { dg-error "default member initializer for unnamed bit-field" } + int : 5 = a + b; // { dg-error "default member initializer for unnamed bit-field" } +}; +template <bool V, int W> +struct U { + int j : W = 7; // { dg-warning "default member initializers for bit-fields only available with" "" { target c++17_down } } + int k : W { 8 }; // { dg-warning "default member initializers for bit-fields only available with" "" { target c++17_down } } + int l : V ? 7 : a = 3; // { dg-error "modification of .a. is not a constant expression" } + // { dg-error "width not an integer constant" "" { target *-*-* } .-1 } + int m : (V ? W : b) = 9; // { dg-warning "default member initializers for bit-fields only available with" "" { target c++17_down } } + // { dg-error "zero width for bit-field" "" { target *-*-* } .-1 } + int n : (V ? W : b) { 10 }; // { dg-warning "default member initializers for bit-fields only available with" "" { target c++17_down } } + // { dg-error "zero width for bit-field" "" { target *-*-* } .-1 } + int o : 1 || new int { 0 }; + int : 4 = 10; // { dg-error "default member initializer for unnamed bit-field" } + int : 5 = a + b; // { dg-error "default member initializer for unnamed bit-field" } +}; +U<false, 10> u; --- gcc/testsuite/g++.dg/cpp2a/bitfield3.C.jj 2017-09-19 09:51:21.926612684 +0200 +++ gcc/testsuite/g++.dg/cpp2a/bitfield3.C 2017-09-19 09:51:21.926612684 +0200 @@ -0,0 +1,55 @@ +// P0683R1 +// { dg-do compile { target c++11 } } +// { dg-options "" } + +extern "C" void abort (); + +int +foo () +{ + return 2; +} + +int a = foo (); +const int b = 0; +struct S { + int c : 5 = 2 * a; // { dg-warning "default member initializers for bit-fields only available with" "" { target c++17_down } } + int d : 6 { c + a }; // { dg-warning "default member initializers for bit-fields only available with" "" { target c++17_down } } + // { dg-warning "narrowing conversion of" "" { target *-*-* } .-1 } + int e : true ? 7 : a = 3; + int f : (true ? 8 : b) = d + a; // { dg-warning "default member initializers for bit-fields only available with" "" { target c++17_down } } + int g : (true ? 9 : b) { f + a }; // { dg-warning "default member initializers for bit-fields only available with" "" { target c++17_down } } + // { dg-warning "narrowing conversion of" "" { target *-*-* } .-1 } + int h : 1 || new int { 0 }; + int i = g + a; +}; +S c; +template <bool V, int W> +struct U { + int j : W = 3 * a; // { dg-warning "default member initializers for bit-fields only available with" "" { target c++17_down } } + int k : W { j + a }; // { dg-warning "default member initializers for bit-fields only available with" "" { target c++17_down } } + // { dg-warning "narrowing conversion of" "" { target *-*-* } .-1 } + int l : V ? 7 : a = 3; + int m : (V ? W : b) = k + a; // { dg-warning "default member initializers for bit-fields only available with" "" { target c++17_down } } + int n : (V ? W : b) { m + a }; // { dg-warning "default member initializers for bit-fields only available with" "" { target c++17_down } } + // { dg-warning "narrowing conversion of" "" { target *-*-* } .-1 } + int o : 1 || new int { 0 }; + int p = n + a; +}; +U<true, 10> d; + +int +main () +{ + a = 1; + if (c.c != 4 || c.d != 6 || c.e != 0 || c.f != 8 || c.g != 10 || c.h != 0 || c.i != 12) + abort (); + if (d.j != 6 || d.k != 8 || d.l != 0 || d.m != 10 || d.n != 12 || d.o != 0 || d.p != 14) + abort (); + S s; + U<true, 10> u; + if (s.c != 2 || s.d != 3 || s.f != 4 || s.g != 5 || s.i != 6) + abort (); + if (u.j != 3 || u.k != 4 || u.m != 5 || u.n != 6 || u.p != 7) + abort (); +} Jakub