From 27746ca994d4be2819fd4066217b1f6394cd4646 Mon Sep 17 00:00:00 2001 From: Jakub Jelinek Date: Fri, 29 Sep 2017 09:49:15 +0200 Subject: [PATCH] parser.c (cp_parser_member_declaration): Parse attributes before colon of a bitfield in addition to after colon. cp/ * parser.c (cp_parser_member_declaration): Parse attributes before colon of a bitfield in addition to after colon. testsuite/ * g++.dg/ext/bitfield7.C: New test. * g++.dg/ext/bitfield8.C: New test. * g++.dg/ext/bitfield9.C: New test. From-SVN: r253281 --- gcc/cp/ChangeLog | 3 ++ gcc/cp/parser.c | 55 ++++++++++++++++++++++------ gcc/testsuite/ChangeLog | 4 ++ gcc/testsuite/g++.dg/ext/bitfield7.C | 12 ++++++ gcc/testsuite/g++.dg/ext/bitfield8.C | 12 ++++++ gcc/testsuite/g++.dg/ext/bitfield9.C | 10 +++++ 6 files changed, 85 insertions(+), 11 deletions(-) create mode 100644 gcc/testsuite/g++.dg/ext/bitfield7.C create mode 100644 gcc/testsuite/g++.dg/ext/bitfield8.C create mode 100644 gcc/testsuite/g++.dg/ext/bitfield9.C diff --git a/gcc/cp/ChangeLog b/gcc/cp/ChangeLog index 6a4d28315e9..95110b87c3c 100644 --- a/gcc/cp/ChangeLog +++ b/gcc/cp/ChangeLog @@ -1,5 +1,8 @@ 2017-09-29 Jakub Jelinek + * parser.c (cp_parser_member_declaration): Parse attributes before + colon of a bitfield in addition to after colon. + * Make-lang.in (check-c++-all): Test also c++2a. 2017-09-28 Jason Merrill diff --git a/gcc/cp/parser.c b/gcc/cp/parser.c index f22c2c091dc..71c27a40ce2 100644 --- a/gcc/cp/parser.c +++ b/gcc/cp/parser.c @@ -23445,35 +23445,68 @@ cp_parser_member_declaration (cp_parser* parser) { tree attributes = NULL_TREE; tree first_attribute; + bool is_bitfld = false; + bool named_bitfld = false; /* Peek at the next token. */ token = cp_lexer_peek_token (parser->lexer); + /* The following code wants to know early if it is a bit-field + or some other declaration. Attributes can appear before + the `:' token, but are hopefully rare enough that the + simplicity of the tentative lookup pays off. */ + 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); + /* Get the width of the bitfield. */ - width - = cp_parser_constant_expression (parser); + width = cp_parser_constant_expression (parser); + + /* Look for attributes that apply to the bitfield after + the `:' token and width. This is where GCC used to + parse attributes in the past, pedwarn if there is + a std attribute. */ + if (cp_next_tokens_can_be_std_attribute_p (parser)) + pedwarn (input_location, OPT_Wpedantic, + "ISO C++ allows bit-field attributes only before " + "the %<:%> token"); + + 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; diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog index e0eade336b3..0d637c8deab 100644 --- a/gcc/testsuite/ChangeLog +++ b/gcc/testsuite/ChangeLog @@ -1,5 +1,9 @@ 2017-09-29 Jakub Jelinek + * g++.dg/ext/bitfield7.C: New test. + * g++.dg/ext/bitfield8.C: New test. + * g++.dg/ext/bitfield9.C: New test. + PR c/82340 * gcc.dg/tree-ssa/pr82340.c: New test. diff --git a/gcc/testsuite/g++.dg/ext/bitfield7.C b/gcc/testsuite/g++.dg/ext/bitfield7.C new file mode 100644 index 00000000000..4efc9bf2d04 --- /dev/null +++ b/gcc/testsuite/g++.dg/ext/bitfield7.C @@ -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]; diff --git a/gcc/testsuite/g++.dg/ext/bitfield8.C b/gcc/testsuite/g++.dg/ext/bitfield8.C new file mode 100644 index 00000000000..688b28988f5 --- /dev/null +++ b/gcc/testsuite/g++.dg/ext/bitfield8.C @@ -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]; diff --git a/gcc/testsuite/g++.dg/ext/bitfield9.C b/gcc/testsuite/g++.dg/ext/bitfield9.C new file mode 100644 index 00000000000..4a4ebf23c1f --- /dev/null +++ b/gcc/testsuite/g++.dg/ext/bitfield9.C @@ -0,0 +1,10 @@ +// { dg-do compile { target c++11 } } +// { dg-options "-pedantic" } + +struct S +{ + char a:4; + char b:8 alignas(int); // { dg-warning "ISO C\\+\\+ allows bit-field attributes only before the ':' token" } + char c:8 [[gnu::aligned(8)]]; // { dg-warning "ISO C\\+\\+ allows bit-field attributes only before the ':' token" } + // { dg-error "two consecutive '\\\[' shall only introduce an attribute before '\\\[' token" "" { target *-*-* } .-1 } +}; -- 2.30.2