[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