[PATCH] c++: Fix up attribute rollbacks in cp_parser_statement
Jason Merrill
jason@redhat.com
Fri Jul 30 15:02:49 GMT 2021
On 7/30/21 6:44 AM, Jakub Jelinek wrote:
> Hi!
>
> During the OpenMP directives using C++ attribute syntax work, I've noticed
> that cp_parser_statement when parsing various block declarations that do
> not allow attribute-specifier-seq at the start rolls back the attributes
> only if std_attrs is non-NULL (i.e. some attributes have been parsed),
> but doesn't roll back if some tokens were parsed as attribute-specifier-seq,
> but didn't yield any attributes (e.g. [[]][[]][[]][[]]), which means
> we accept those empty attributes even in places where they don't appear
> in the grammar.
>
> The following patch fixes that by instead checking if there are any
> tokens to roll back. This makes the parsing handle the first
> function the same as the second one (where some attribute appears).
>
> The testcase contains two xfails, using namespace ... apparently
> allows attributes at the start and the attributes shall appeartain to
> using in that case. To be fixed incrementally.
>
> Bootstrapped/regtested on x86_64-linux and i686-linux, ok for trunk?
OK.
> 2021-07-30 Jakub Jelinek <jakub@redhat.com>
>
> * parser.c (cp_parser_statement): Rollback attributes not just
> when std_attrs is non-NULL, but whenever
> cp_parser_std_attribute_spec_seq parsed any tokens.
>
> * g++.dg/cpp0x/gen-attrs-76.C: New test.
>
> --- gcc/cp/parser.c.jj 2021-07-30 11:19:39.431614703 +0200
> +++ gcc/cp/parser.c 2021-07-30 12:22:16.995130642 +0200
> @@ -11909,6 +11909,7 @@ cp_parser_statement (cp_parser* parser,
> cp_token *token;
> location_t statement_location, attrs_loc;
> bool in_omp_attribute_pragma = parser->lexer->in_omp_attribute_pragma;
> + bool has_std_attrs;
>
> restart:
> if (if_p != NULL)
> @@ -11917,7 +11918,8 @@ cp_parser_statement (cp_parser* parser,
> statement = NULL_TREE;
>
> saved_token_sentinel saved_tokens (parser->lexer);
> - attrs_loc = cp_lexer_peek_token (parser->lexer)->location;
> + token = cp_lexer_peek_token (parser->lexer);
> + attrs_loc = token->location;
> if (c_dialect_objc ())
> /* In obj-c++, seeing '[[' might be the either the beginning of
> c++11 attributes, or a nested objc-message-expression. So
> @@ -11931,6 +11933,7 @@ cp_parser_statement (cp_parser* parser,
> if (!cp_parser_parse_definitely (parser))
> std_attrs = NULL_TREE;
> }
> + has_std_attrs = cp_lexer_peek_token (parser->lexer) != token;
>
> if (std_attrs && (flag_openmp || flag_openmp_simd))
> std_attrs = cp_parser_handle_statement_omp_attributes (parser, std_attrs);
> @@ -11999,7 +12002,7 @@ cp_parser_statement (cp_parser* parser,
>
> case RID_NAMESPACE:
> /* This must be a namespace alias definition. */
> - if (std_attrs != NULL_TREE)
> + if (has_std_attrs)
> {
> /* Attributes should be parsed as part of the
> declaration, so let's un-parse them. */
> @@ -12104,7 +12107,7 @@ cp_parser_statement (cp_parser* parser,
> {
> if (cp_lexer_next_token_is_not (parser->lexer, CPP_SEMICOLON))
> {
> - if (std_attrs != NULL_TREE)
> + if (has_std_attrs)
> /* Attributes should be parsed as part of the declaration,
> so let's un-parse them. */
> saved_tokens.rollback();
> @@ -12116,7 +12119,7 @@ cp_parser_statement (cp_parser* parser,
> if (cp_parser_parse_definitely (parser))
> return;
> /* It didn't work, restore the post-attribute position. */
> - if (std_attrs)
> + if (has_std_attrs)
> cp_lexer_set_token_position (parser->lexer, statement_token);
> }
> /* All preceding labels have been parsed at this point. */
> --- gcc/testsuite/g++.dg/cpp0x/gen-attrs-76.C.jj 2021-07-30 12:16:59.472477365 +0200
> +++ gcc/testsuite/g++.dg/cpp0x/gen-attrs-76.C 2021-07-30 12:21:32.440740569 +0200
> @@ -0,0 +1,31 @@
> +// { dg-do compile { target c++11 } }
> +// { dg-options "-Wno-attributes" }
> +
> +namespace N {}
> +namespace O { typedef int T; };
> +
> +void
> +foo ()
> +{
> + [[]] asm (""); // { dg-error "expected" }
> + [[]] __extension__ asm (""); // { dg-error "expected" }
> + __extension__ [[]] asm (""); // { dg-error "expected" }
> + [[]] namespace M = ::N; // { dg-error "expected" }
> + [[]] using namespace N; // { dg-bogus "expected" "" { xfail *-*-* } }
> + [[]] using O::T; // { dg-error "expected" }
> + [[]] __label__ foo; // { dg-error "expected" }
> + [[]] static_assert (true, ""); // { dg-error "expected" }
> +}
> +
> +void
> +bar ()
> +{
> + [[gnu::unused]] asm (""); // { dg-error "expected" }
> + [[gnu::unused]] __extension__ asm (""); // { dg-error "expected" }
> + __extension__ [[gnu::unused]] asm (""); // { dg-error "expected" }
> + [[gnu::unused]] namespace M = ::N; // { dg-error "expected" }
> + [[gnu::unused]] using namespace N; // { dg-bogus "expected" "" { xfail *-*-* } }
> + [[gnu::unused]] using O::T; // { dg-error "expected" }
> + [[gnu::unused]] __label__ foo; // { dg-error "expected" }
> + [[gnu::unused]] static_assert (true, ""); // { dg-error "expected" }
> +}
>
> Jakub
>
More information about the Gcc-patches
mailing list