c++: Accept C++11 attribute-definition [PR101582]

Message ID 20210723080325.GY2380545@tucnak
State New
Headers show
Series
  • c++: Accept C++11 attribute-definition [PR101582]
Related show

Commit Message

Aldy Hernandez via Gcc-patches July 23, 2021, 8:03 a.m.
Hi!

As the following testcase shows, we don't parse properly
C++11 attribute-declaration:
https://eel.is/c++draft/dcl.dcl#nt:attribute-declaration

cp_parser_toplevel_declaration just handles empty-declaration parsing
(with diagnostics for C++98) and otherwise calls cp_parser_declaration
which on it calls cp_parser_simple_declaration and rejects it with
"does not declare anything" permerror.

The following patch instead handles it in cp_parser_toplevel_declaration
by parsing the attributes (standard ones only, we've never supported
__attribute__((...)); at namespace scope, so I'm not sure we need to
introduce that), which for C++98 emits the needed diagnostics, and then
warning if there are any attributes that we throw away on the floor.

I'll need this later for OpenMP directives at namespace scope, e.g.
[[omp::directive (requires, atomic_default_mem_order(seq_cst))]];
should be valid at namespace scope (and many other directives).

Bootstrapped/regtested on x86_64-linux and i686-linux, ok for trunk?

2021-07-23  Jakub Jelinek  <jakub@redhat.com>

	PR c++/101582
	* parser.c (cp_parser_skip_std_attribute_spec_seq): Add a forward
	declaration.
	(cp_parser_toplevel_declaration): Parse attribute-declaration.

	* g++.dg/cpp0x/gen-attrs-45.C: Expect a warning about ignored
	attributes instead of error.
	* g++.dg/cpp0x/gen-attrs-75.C: New test.


	Jakub

Comments

Aldy Hernandez via Gcc-patches July 28, 2021, 8:32 p.m. | #1
On 7/23/21 4:03 AM, Jakub Jelinek wrote:
> Hi!

> 

> As the following testcase shows, we don't parse properly

> C++11 attribute-declaration:

> https://eel.is/c++draft/dcl.dcl#nt:attribute-declaration

> 

> cp_parser_toplevel_declaration just handles empty-declaration parsing

> (with diagnostics for C++98)


This seems to be a bug: from the comments, 
cp_parser_toplevel_declaration is intended to only handle #pragma 
parsing, everything else should be in cp_parser_declaration.

As a result, we wrongly reject

extern "C" ;

So please move empty-declaration and attribute-declaration handling into 
cp_parser_declaration.

> and otherwise calls cp_parser_declaration

> which on it calls cp_parser_simple_declaration and rejects it with

> "does not declare anything" permerror.

> 

> The following patch instead handles it in cp_parser_toplevel_declaration

> by parsing the attributes (standard ones only, we've never supported

> __attribute__((...)); at namespace scope, so I'm not sure we need to

> introduce that), which for C++98 emits the needed diagnostics, and then

> warning if there are any attributes that we throw away on the floor.

> 

> I'll need this later for OpenMP directives at namespace scope, e.g.

> [[omp::directive (requires, atomic_default_mem_order(seq_cst))]];

> should be valid at namespace scope (and many other directives).

> 

> Bootstrapped/regtested on x86_64-linux and i686-linux, ok for trunk?

> 

> 2021-07-23  Jakub Jelinek  <jakub@redhat.com>

> 

> 	PR c++/101582

> 	* parser.c (cp_parser_skip_std_attribute_spec_seq): Add a forward

> 	declaration.

> 	(cp_parser_toplevel_declaration): Parse attribute-declaration.

> 

> 	* g++.dg/cpp0x/gen-attrs-45.C: Expect a warning about ignored

> 	attributes instead of error.

> 	* g++.dg/cpp0x/gen-attrs-75.C: New test.

> 

> --- gcc/cp/parser.c.jj	2021-07-22 17:47:26.025761491 +0200

> +++ gcc/cp/parser.c	2021-07-22 19:09:28.487513184 +0200

> @@ -2507,6 +2507,8 @@ static tree cp_parser_std_attribute_spec

>     (cp_parser *);

>   static tree cp_parser_std_attribute_spec_seq

>     (cp_parser *);

> +static size_t cp_parser_skip_std_attribute_spec_seq

> +  (cp_parser *, size_t);

>   static size_t cp_parser_skip_attributes_opt

>     (cp_parser *, size_t);

>   static bool cp_parser_extension_opt

> @@ -14547,6 +14549,20 @@ cp_parser_toplevel_declaration (cp_parse

>         if (cxx_dialect < cxx11)

>   	pedwarn (input_location, OPT_Wpedantic, "extra %<;%>");

>       }

> +  else if (cp_lexer_nth_token_is (parser->lexer,

> +				  cp_parser_skip_std_attribute_spec_seq (parser,

> +									 1),

> +				  CPP_SEMICOLON))

> +    {

> +      location_t attrs_loc = token->location;

> +      tree std_attrs = cp_parser_std_attribute_spec_seq (parser);

> +      if (std_attrs != NULL_TREE)

> +	warning_at (make_location (attrs_loc, attrs_loc, parser->lexer),

> +		    OPT_Wattributes,

> +		    "attributes in attribute declaration are ignored");

> +      if (cp_lexer_next_token_is (parser->lexer, CPP_SEMICOLON))

> +	cp_lexer_consume_token (parser->lexer);

> +    }

>     else

>       /* Parse the declaration itself.  */

>       cp_parser_declaration (parser, NULL_TREE);

> --- gcc/testsuite/g++.dg/cpp0x/gen-attrs-45.C.jj	2020-01-12 11:54:37.072403466 +0100

> +++ gcc/testsuite/g++.dg/cpp0x/gen-attrs-45.C	2021-07-22 19:14:38.250222344 +0200

> @@ -1,4 +1,4 @@

>   // PR c++/52906

>   // { dg-do compile { target c++11 } }

>   

> -[[gnu::deprecated]]; // { dg-error "does not declare anything" }

> +[[gnu::deprecated]]; // { dg-warning "attributes in attribute declaration are ignored" }

> --- gcc/testsuite/g++.dg/cpp0x/gen-attrs-75.C.jj	2021-07-22 19:14:58.438942693 +0200

> +++ gcc/testsuite/g++.dg/cpp0x/gen-attrs-75.C	2021-07-22 19:12:18.442158972 +0200

> @@ -0,0 +1,8 @@

> +// PR c++/101582

> +// { dg-do compile }

> +// { dg-options "" }

> +

> +;

> +[[]] [[]] [[]];	// { dg-warning "attributes only available with" "" { target c++98_only } }

> +[[foobar]];	// { dg-warning "attributes in attribute declaration are ignored" }

> +// { dg-warning "attributes only available with" "" { target c++98_only } .-1 }

> 

> 	Jakub

>

Patch

--- gcc/cp/parser.c.jj	2021-07-22 17:47:26.025761491 +0200
+++ gcc/cp/parser.c	2021-07-22 19:09:28.487513184 +0200
@@ -2507,6 +2507,8 @@  static tree cp_parser_std_attribute_spec
   (cp_parser *);
 static tree cp_parser_std_attribute_spec_seq
   (cp_parser *);
+static size_t cp_parser_skip_std_attribute_spec_seq
+  (cp_parser *, size_t);
 static size_t cp_parser_skip_attributes_opt
   (cp_parser *, size_t);
 static bool cp_parser_extension_opt
@@ -14547,6 +14549,20 @@  cp_parser_toplevel_declaration (cp_parse
       if (cxx_dialect < cxx11)
 	pedwarn (input_location, OPT_Wpedantic, "extra %<;%>");
     }
+  else if (cp_lexer_nth_token_is (parser->lexer,
+				  cp_parser_skip_std_attribute_spec_seq (parser,
+									 1),
+				  CPP_SEMICOLON))
+    {
+      location_t attrs_loc = token->location;
+      tree std_attrs = cp_parser_std_attribute_spec_seq (parser);
+      if (std_attrs != NULL_TREE)
+	warning_at (make_location (attrs_loc, attrs_loc, parser->lexer),
+		    OPT_Wattributes,
+		    "attributes in attribute declaration are ignored");
+      if (cp_lexer_next_token_is (parser->lexer, CPP_SEMICOLON))
+	cp_lexer_consume_token (parser->lexer);
+    }
   else
     /* Parse the declaration itself.  */
     cp_parser_declaration (parser, NULL_TREE);
--- gcc/testsuite/g++.dg/cpp0x/gen-attrs-45.C.jj	2020-01-12 11:54:37.072403466 +0100
+++ gcc/testsuite/g++.dg/cpp0x/gen-attrs-45.C	2021-07-22 19:14:38.250222344 +0200
@@ -1,4 +1,4 @@ 
 // PR c++/52906
 // { dg-do compile { target c++11 } }
 
-[[gnu::deprecated]]; // { dg-error "does not declare anything" }
+[[gnu::deprecated]]; // { dg-warning "attributes in attribute declaration are ignored" }
--- gcc/testsuite/g++.dg/cpp0x/gen-attrs-75.C.jj	2021-07-22 19:14:58.438942693 +0200
+++ gcc/testsuite/g++.dg/cpp0x/gen-attrs-75.C	2021-07-22 19:12:18.442158972 +0200
@@ -0,0 +1,8 @@ 
+// PR c++/101582
+// { dg-do compile }
+// { dg-options "" }
+
+;
+[[]] [[]] [[]];	// { dg-warning "attributes only available with" "" { target c++98_only } }
+[[foobar]];	// { dg-warning "attributes in attribute declaration are ignored" }
+// { dg-warning "attributes only available with" "" { target c++98_only } .-1 }