parser.c (cp_parser_member_declaration): Parse attributes before colon of a bitfield...
authorJakub Jelinek <jakub@redhat.com>
Fri, 29 Sep 2017 07:49:15 +0000 (09:49 +0200)
committerJakub Jelinek <jakub@gcc.gnu.org>
Fri, 29 Sep 2017 07:49:15 +0000 (09:49 +0200)
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
gcc/cp/parser.c
gcc/testsuite/ChangeLog
gcc/testsuite/g++.dg/ext/bitfield7.C [new file with mode: 0644]
gcc/testsuite/g++.dg/ext/bitfield8.C [new file with mode: 0644]
gcc/testsuite/g++.dg/ext/bitfield9.C [new file with mode: 0644]

index 6a4d28315e99cb7cc488649c2490d4272f760697..95110b87c3c2df68f9acf3d651e037ec7f14e89d 100644 (file)
@@ -1,5 +1,8 @@
 2017-09-29  Jakub Jelinek  <jakub@redhat.com>
 
+       * 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  <jason@redhat.com>
index f22c2c091dc31ff57c814a64394cfb1623dc4e6d..71c27a40ce2c18f86fe9f86d692687d59d6cec5e 100644 (file)
@@ -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;
index e0eade336b3a4d0f5ca70d0e7b7f0f208023b974..0d637c8deabd8ab523acf34d8ecb4e5b8e8e7a15 100644 (file)
@@ -1,5 +1,9 @@
 2017-09-29  Jakub Jelinek  <jakub@redhat.com>
 
+       * 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 (file)
index 0000000..4efc9bf
--- /dev/null
@@ -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 (file)
index 0000000..688b289
--- /dev/null
@@ -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 (file)
index 0000000..4a4ebf2
--- /dev/null
@@ -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 }
+};