public inbox for gcc-patches@gcc.gnu.org
 help / color / mirror / Atom feed
* [PATCH] c++: Implement C++ DR 2262 - Attributes for asm-definition [PR110734]
@ 2023-12-05  7:40 Jakub Jelinek
  2023-12-05 16:01 ` Jason Merrill
  0 siblings, 1 reply; 7+ messages in thread
From: Jakub Jelinek @ 2023-12-05  7:40 UTC (permalink / raw)
  To: Jason Merrill; +Cc: gcc-patches, Marek Polacek

Hi!

Seems in 2017 attribute-specifier-seq[opt] was added to asm-declaration
and the change was voted in as a DR.

The following patch implements it by parsing the attributes and warning
about them.

I found one attribute parsing bug I'll send a fix for momentarily.

And there is another thing I wonder about: with -Wno-attributes= we are
supposed to ignore the attributes altogether, but we are actually still
warning about them when we emit these generic warnings about ignoring
all attributes which appertain to this and that (perhaps with some
exceptions we first remove from the attribute chain), like:
void foo () { [[foo::bar]]; }
with -Wattributes -Wno-attributes=foo::bar
Shouldn't we call some helper function in cases like this and warn
not when std_attrs (or how the attribute chain var is called) is non-NULL,
but if it is non-NULL and contains at least one non-attribute_ignored_p
attribute?  cp_parser_declaration at least tries:
      if (std_attrs != NULL_TREE && !attribute_ignored_p (std_attrs))
        warning_at (make_location (attrs_loc, attrs_loc, parser->lexer),
                    OPT_Wattributes, "attribute ignored");
but attribute_ignored_p here checks the first attribute rather than the
whole chain.  So it will incorrectly not warn if there is an ignored
attribute followed by non-ignored.

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

2023-12-05  Jakub Jelinek  <jakub@redhat.com>

	PR c++/110734
	* parser.cc (cp_parser_block_declaration): Implement C++ DR 2262
	- Attributes for asm-definition.  Call cp_parser_asm_definition
	even if RID_ASM token is only seen after sequence of standard
	attributes.
	(cp_parser_asm_definition): Parse standard attributes before
	RID_ASM token and warn for them with -Wattributes.

	* g++.dg/DRs/dr2262.C: New test.
	* g++.dg/cpp0x/gen-attrs-76.C (foo, bar): Don't expect errors
	on attributes on asm definitions.
	* g++.dg/gomp/attrs-11.C: Remove 2 expected errors.

--- gcc/cp/parser.cc.jj	2023-12-04 08:59:06.871357329 +0100
+++ gcc/cp/parser.cc	2023-12-04 20:23:53.225009856 +0100
@@ -15398,7 +15398,6 @@ cp_parser_block_declaration (cp_parser *
   /* Peek at the next token to figure out which kind of declaration is
      present.  */
   cp_token *token1 = cp_lexer_peek_token (parser->lexer);
-  size_t attr_idx;
 
   /* If the next keyword is `asm', we have an asm-definition.  */
   if (token1->keyword == RID_ASM)
@@ -15452,22 +15451,36 @@ cp_parser_block_declaration (cp_parser *
   /* If the next token is `static_assert' we have a static assertion.  */
   else if (token1->keyword == RID_STATIC_ASSERT)
     cp_parser_static_assert (parser, /*member_p=*/false);
-  /* If the next tokens after attributes is `using namespace', then we have
-     a using-directive.  */
-  else if ((attr_idx = cp_parser_skip_std_attribute_spec_seq (parser, 1)) != 1
-	   && cp_lexer_nth_token_is_keyword (parser->lexer, attr_idx,
-					     RID_USING)
-	   && cp_lexer_nth_token_is_keyword (parser->lexer, attr_idx + 1,
-					     RID_NAMESPACE))
+  else
     {
-      if (statement_p)
-	cp_parser_commit_to_tentative_parse (parser);
-      cp_parser_using_directive (parser);
+      size_t attr_idx = cp_parser_skip_std_attribute_spec_seq (parser, 1);
+      cp_token *after_attr = NULL;
+      if (attr_idx != 1)
+	after_attr = cp_lexer_peek_nth_token (parser->lexer, attr_idx);
+      /* If the next tokens after attributes is `using namespace', then we have
+	 a using-directive.  */
+      if (after_attr
+	  && after_attr->keyword == RID_USING
+	  && cp_lexer_nth_token_is_keyword (parser->lexer, attr_idx + 1,
+					    RID_NAMESPACE))
+	{
+	  if (statement_p)
+	    cp_parser_commit_to_tentative_parse (parser);
+	  cp_parser_using_directive (parser);
+	}
+      /* If the next token after attributes is `asm', then we have
+	 an asm-definition.  */
+      else if (after_attr && after_attr->keyword == RID_ASM)
+	{
+	  if (statement_p)
+	    cp_parser_commit_to_tentative_parse (parser);
+	  cp_parser_asm_definition (parser);
+	}
+      /* Anything else must be a simple-declaration.  */
+      else
+	cp_parser_simple_declaration (parser, !statement_p,
+				      /*maybe_range_for_decl*/NULL);
     }
-  /* Anything else must be a simple-declaration.  */
-  else
-    cp_parser_simple_declaration (parser, !statement_p,
-				  /*maybe_range_for_decl*/NULL);
 }
 
 /* Parse a simple-declaration.
@@ -22424,6 +22437,7 @@ cp_parser_asm_definition (cp_parser* par
   bool invalid_inputs_p = false;
   bool invalid_outputs_p = false;
   required_token missing = RT_NONE;
+  tree std_attrs = cp_parser_std_attribute_spec_seq (parser);
   location_t asm_loc = cp_lexer_peek_token (parser->lexer)->location;
 
   /* Look for the `asm' keyword.  */
@@ -22657,6 +22671,10 @@ cp_parser_asm_definition (cp_parser* par
       else
 	symtab->finalize_toplevel_asm (string);
     }
+
+  if (std_attrs)
+    warning_at (asm_loc, OPT_Wattributes,
+		"attributes ignored on %<asm%> declaration");
 }
 
 /* Given the type TYPE of a declaration with declarator DECLARATOR, return the
--- gcc/testsuite/g++.dg/DRs/dr2262.C.jj	2023-12-04 19:58:06.433811915 +0100
+++ gcc/testsuite/g++.dg/DRs/dr2262.C	2023-12-04 20:23:01.655737020 +0100
@@ -0,0 +1,16 @@
+// DR 2262 - Attributes for asm-definition
+// { dg-do compile { target c++11 } }
+// { dg-options "-Wattributes" }
+
+[[]] asm ("nop");
+[[foo::bar]] asm ("nop");	// { dg-warning "attributes ignored on 'asm' declaration" }
+
+void
+foo ()
+{
+  int i = 42;
+  [[]] asm ("nop");
+  [[foo::bar]] asm ("nop");	// { dg-warning "attributes ignored on 'asm' declaration" }
+  [[]] asm ("nop" : "+r" (i));
+  [[foo::bar]] [[bar::baz]] asm ("nop" : "+r" (i));	// { dg-warning "attributes ignored on 'asm' declaration" }
+}
--- gcc/testsuite/g++.dg/cpp0x/gen-attrs-76.C.jj	2021-08-12 09:34:16.094246634 +0200
+++ gcc/testsuite/g++.dg/cpp0x/gen-attrs-76.C	2023-12-04 20:43:45.002188817 +0100
@@ -8,9 +8,9 @@ namespace P {}
 void
 foo ()
 {
-  [[]] asm ("");				// { dg-error "expected" }
+  [[]] asm ("");
   [[]] __extension__ asm ("");			// { dg-error "expected" }
-  __extension__ [[]] asm ("");			// { dg-error "expected" }
+  __extension__ [[]] asm ("");
   [[]] namespace M = ::N;			// { dg-error "expected" }
   [[]] using namespace N;			// { dg-bogus "expected" }
   using namespace P [[]];			// { dg-error "expected" }
@@ -22,9 +22,9 @@ foo ()
 void
 bar ()
 {
-  [[gnu::unused]] asm ("");			// { dg-error "expected" }
+  [[gnu::unused]] asm ("");
   [[gnu::unused]] __extension__ asm ("");	// { dg-error "expected" }
-  __extension__ [[gnu::unused]] asm ("");	// { dg-error "expected" }
+  __extension__ [[gnu::unused]] asm ("");
   [[gnu::unused]] namespace M = ::N;		// { dg-error "expected" }
   [[gnu::unused]] using namespace N;		// { dg-bogus "expected" }
   using namespace P [[gnu::unused]];		// { dg-error "expected" }
--- gcc/testsuite/g++.dg/gomp/attrs-11.C.jj	2021-08-12 09:34:16.720237822 +0200
+++ gcc/testsuite/g++.dg/gomp/attrs-11.C	2023-12-05 07:47:03.336641204 +0100
@@ -7,9 +7,9 @@ namespace O { typedef int T; };
 void
 foo ()
 {
-  [[omp::directive (parallel)]] asm ("");			// { dg-error "expected" }
+  [[omp::directive (parallel)]] asm ("");
   [[omp::directive (parallel)]] __extension__ asm ("");		// { dg-error "expected" }
-  __extension__ [[omp::directive (parallel)]] asm ("");		// { dg-error "expected" }
+  __extension__ [[omp::directive (parallel)]] asm ("");
   [[omp::directive (parallel)]] namespace M = ::N;		// { dg-error "expected" }
   [[omp::directive (parallel)]] using namespace N;		// { dg-error "not allowed to be specified in this context" }
   [[omp::directive (parallel)]] using O::T;			// { dg-error "expected" }

	Jakub


^ permalink raw reply	[flat|nested] 7+ messages in thread

* Re: [PATCH] c++: Implement C++ DR 2262 - Attributes for asm-definition [PR110734]
  2023-12-05  7:40 [PATCH] c++: Implement C++ DR 2262 - Attributes for asm-definition [PR110734] Jakub Jelinek
@ 2023-12-05 16:01 ` Jason Merrill
  2023-12-06 14:10   ` [PATCH] c++: Don't diagnose ignoring of attributes if all ignored attributes are attribute_ignored_p Jakub Jelinek
  0 siblings, 1 reply; 7+ messages in thread
From: Jason Merrill @ 2023-12-05 16:01 UTC (permalink / raw)
  To: Jakub Jelinek; +Cc: gcc-patches, Marek Polacek

On 12/5/23 02:40, Jakub Jelinek wrote:
> Hi!
> 
> Seems in 2017 attribute-specifier-seq[opt] was added to asm-declaration
> and the change was voted in as a DR.
> 
> The following patch implements it by parsing the attributes and warning
> about them.
> 
> I found one attribute parsing bug I'll send a fix for momentarily.
> 
> And there is another thing I wonder about: with -Wno-attributes= we are
> supposed to ignore the attributes altogether, but we are actually still
> warning about them when we emit these generic warnings about ignoring
> all attributes which appertain to this and that (perhaps with some
> exceptions we first remove from the attribute chain), like:
> void foo () { [[foo::bar]]; }
> with -Wattributes -Wno-attributes=foo::bar
> Shouldn't we call some helper function in cases like this and warn
> not when std_attrs (or how the attribute chain var is called) is non-NULL,
> but if it is non-NULL and contains at least one non-attribute_ignored_p
> attribute?

Sounds good.

> cp_parser_declaration at least tries:
>        if (std_attrs != NULL_TREE && !attribute_ignored_p (std_attrs))
>          warning_at (make_location (attrs_loc, attrs_loc, parser->lexer),
>                      OPT_Wattributes, "attribute ignored");
> but attribute_ignored_p here checks the first attribute rather than the
> whole chain.  So it will incorrectly not warn if there is an ignored
> attribute followed by non-ignored.

I agree.

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

OK.

> 2023-12-05  Jakub Jelinek  <jakub@redhat.com>
> 
> 	PR c++/110734
> 	* parser.cc (cp_parser_block_declaration): Implement C++ DR 2262
> 	- Attributes for asm-definition.  Call cp_parser_asm_definition
> 	even if RID_ASM token is only seen after sequence of standard
> 	attributes.
> 	(cp_parser_asm_definition): Parse standard attributes before
> 	RID_ASM token and warn for them with -Wattributes.
> 
> 	* g++.dg/DRs/dr2262.C: New test.
> 	* g++.dg/cpp0x/gen-attrs-76.C (foo, bar): Don't expect errors
> 	on attributes on asm definitions.
> 	* g++.dg/gomp/attrs-11.C: Remove 2 expected errors.
> 
> --- gcc/cp/parser.cc.jj	2023-12-04 08:59:06.871357329 +0100
> +++ gcc/cp/parser.cc	2023-12-04 20:23:53.225009856 +0100
> @@ -15398,7 +15398,6 @@ cp_parser_block_declaration (cp_parser *
>     /* Peek at the next token to figure out which kind of declaration is
>        present.  */
>     cp_token *token1 = cp_lexer_peek_token (parser->lexer);
> -  size_t attr_idx;
>   
>     /* If the next keyword is `asm', we have an asm-definition.  */
>     if (token1->keyword == RID_ASM)
> @@ -15452,22 +15451,36 @@ cp_parser_block_declaration (cp_parser *
>     /* If the next token is `static_assert' we have a static assertion.  */
>     else if (token1->keyword == RID_STATIC_ASSERT)
>       cp_parser_static_assert (parser, /*member_p=*/false);
> -  /* If the next tokens after attributes is `using namespace', then we have
> -     a using-directive.  */
> -  else if ((attr_idx = cp_parser_skip_std_attribute_spec_seq (parser, 1)) != 1
> -	   && cp_lexer_nth_token_is_keyword (parser->lexer, attr_idx,
> -					     RID_USING)
> -	   && cp_lexer_nth_token_is_keyword (parser->lexer, attr_idx + 1,
> -					     RID_NAMESPACE))
> +  else
>       {
> -      if (statement_p)
> -	cp_parser_commit_to_tentative_parse (parser);
> -      cp_parser_using_directive (parser);
> +      size_t attr_idx = cp_parser_skip_std_attribute_spec_seq (parser, 1);
> +      cp_token *after_attr = NULL;
> +      if (attr_idx != 1)
> +	after_attr = cp_lexer_peek_nth_token (parser->lexer, attr_idx);
> +      /* If the next tokens after attributes is `using namespace', then we have
> +	 a using-directive.  */
> +      if (after_attr
> +	  && after_attr->keyword == RID_USING
> +	  && cp_lexer_nth_token_is_keyword (parser->lexer, attr_idx + 1,
> +					    RID_NAMESPACE))
> +	{
> +	  if (statement_p)
> +	    cp_parser_commit_to_tentative_parse (parser);
> +	  cp_parser_using_directive (parser);
> +	}
> +      /* If the next token after attributes is `asm', then we have
> +	 an asm-definition.  */
> +      else if (after_attr && after_attr->keyword == RID_ASM)
> +	{
> +	  if (statement_p)
> +	    cp_parser_commit_to_tentative_parse (parser);
> +	  cp_parser_asm_definition (parser);
> +	}
> +      /* Anything else must be a simple-declaration.  */
> +      else
> +	cp_parser_simple_declaration (parser, !statement_p,
> +				      /*maybe_range_for_decl*/NULL);
>       }
> -  /* Anything else must be a simple-declaration.  */
> -  else
> -    cp_parser_simple_declaration (parser, !statement_p,
> -				  /*maybe_range_for_decl*/NULL);
>   }
>   
>   /* Parse a simple-declaration.
> @@ -22424,6 +22437,7 @@ cp_parser_asm_definition (cp_parser* par
>     bool invalid_inputs_p = false;
>     bool invalid_outputs_p = false;
>     required_token missing = RT_NONE;
> +  tree std_attrs = cp_parser_std_attribute_spec_seq (parser);
>     location_t asm_loc = cp_lexer_peek_token (parser->lexer)->location;
>   
>     /* Look for the `asm' keyword.  */
> @@ -22657,6 +22671,10 @@ cp_parser_asm_definition (cp_parser* par
>         else
>   	symtab->finalize_toplevel_asm (string);
>       }
> +
> +  if (std_attrs)
> +    warning_at (asm_loc, OPT_Wattributes,
> +		"attributes ignored on %<asm%> declaration");
>   }
>   
>   /* Given the type TYPE of a declaration with declarator DECLARATOR, return the
> --- gcc/testsuite/g++.dg/DRs/dr2262.C.jj	2023-12-04 19:58:06.433811915 +0100
> +++ gcc/testsuite/g++.dg/DRs/dr2262.C	2023-12-04 20:23:01.655737020 +0100
> @@ -0,0 +1,16 @@
> +// DR 2262 - Attributes for asm-definition
> +// { dg-do compile { target c++11 } }
> +// { dg-options "-Wattributes" }
> +
> +[[]] asm ("nop");
> +[[foo::bar]] asm ("nop");	// { dg-warning "attributes ignored on 'asm' declaration" }
> +
> +void
> +foo ()
> +{
> +  int i = 42;
> +  [[]] asm ("nop");
> +  [[foo::bar]] asm ("nop");	// { dg-warning "attributes ignored on 'asm' declaration" }
> +  [[]] asm ("nop" : "+r" (i));
> +  [[foo::bar]] [[bar::baz]] asm ("nop" : "+r" (i));	// { dg-warning "attributes ignored on 'asm' declaration" }
> +}
> --- gcc/testsuite/g++.dg/cpp0x/gen-attrs-76.C.jj	2021-08-12 09:34:16.094246634 +0200
> +++ gcc/testsuite/g++.dg/cpp0x/gen-attrs-76.C	2023-12-04 20:43:45.002188817 +0100
> @@ -8,9 +8,9 @@ namespace P {}
>   void
>   foo ()
>   {
> -  [[]] asm ("");				// { dg-error "expected" }
> +  [[]] asm ("");
>     [[]] __extension__ asm ("");			// { dg-error "expected" }
> -  __extension__ [[]] asm ("");			// { dg-error "expected" }
> +  __extension__ [[]] asm ("");
>     [[]] namespace M = ::N;			// { dg-error "expected" }
>     [[]] using namespace N;			// { dg-bogus "expected" }
>     using namespace P [[]];			// { dg-error "expected" }
> @@ -22,9 +22,9 @@ foo ()
>   void
>   bar ()
>   {
> -  [[gnu::unused]] asm ("");			// { dg-error "expected" }
> +  [[gnu::unused]] asm ("");
>     [[gnu::unused]] __extension__ asm ("");	// { dg-error "expected" }
> -  __extension__ [[gnu::unused]] asm ("");	// { dg-error "expected" }
> +  __extension__ [[gnu::unused]] asm ("");
>     [[gnu::unused]] namespace M = ::N;		// { dg-error "expected" }
>     [[gnu::unused]] using namespace N;		// { dg-bogus "expected" }
>     using namespace P [[gnu::unused]];		// { dg-error "expected" }
> --- gcc/testsuite/g++.dg/gomp/attrs-11.C.jj	2021-08-12 09:34:16.720237822 +0200
> +++ gcc/testsuite/g++.dg/gomp/attrs-11.C	2023-12-05 07:47:03.336641204 +0100
> @@ -7,9 +7,9 @@ namespace O { typedef int T; };
>   void
>   foo ()
>   {
> -  [[omp::directive (parallel)]] asm ("");			// { dg-error "expected" }
> +  [[omp::directive (parallel)]] asm ("");
>     [[omp::directive (parallel)]] __extension__ asm ("");		// { dg-error "expected" }
> -  __extension__ [[omp::directive (parallel)]] asm ("");		// { dg-error "expected" }
> +  __extension__ [[omp::directive (parallel)]] asm ("");
>     [[omp::directive (parallel)]] namespace M = ::N;		// { dg-error "expected" }
>     [[omp::directive (parallel)]] using namespace N;		// { dg-error "not allowed to be specified in this context" }
>     [[omp::directive (parallel)]] using O::T;			// { dg-error "expected" }
> 
> 	Jakub
> 


^ permalink raw reply	[flat|nested] 7+ messages in thread

* [PATCH] c++: Don't diagnose ignoring of attributes if all ignored attributes are attribute_ignored_p
  2023-12-05 16:01 ` Jason Merrill
@ 2023-12-06 14:10   ` Jakub Jelinek
  2023-12-07  7:47     ` Jakub Jelinek
  2023-12-08 17:06     ` Jason Merrill
  0 siblings, 2 replies; 7+ messages in thread
From: Jakub Jelinek @ 2023-12-06 14:10 UTC (permalink / raw)
  To: Jason Merrill; +Cc: gcc-patches

On Tue, Dec 05, 2023 at 11:01:20AM -0500, Jason Merrill wrote:
> > And there is another thing I wonder about: with -Wno-attributes= we are
> > supposed to ignore the attributes altogether, but we are actually still
> > warning about them when we emit these generic warnings about ignoring
> > all attributes which appertain to this and that (perhaps with some
> > exceptions we first remove from the attribute chain), like:
> > void foo () { [[foo::bar]]; }
> > with -Wattributes -Wno-attributes=foo::bar
> > Shouldn't we call some helper function in cases like this and warn
> > not when std_attrs (or how the attribute chain var is called) is non-NULL,
> > but if it is non-NULL and contains at least one non-attribute_ignored_p
> > attribute?
> 
> Sounds good.

The following patch implements it.
I've kept warnings for cases where the C++ standard says explicitly any
attributes aren't ok - 
"If an attribute-specifier-seq appertains to a friend declaration, that
declaration shall be a definition."

For some changes I haven't figured out how could I cover it in the
testsuite.

So far tested with
GXX_TESTSUITE_STDS=98,11,14,17,20,23,26 make check-g++ RUNTESTFLAGS="dg.exp=Wno-attributes* ubsan.exp=Wno-attributes*"
(which is all tests that use -Wno-attributes=), ok for trunk if it passes
full bootstrap/regtest?

Note, C uses a different strategy, it has c_warn_unused_attributes
function which warns about all the attributes one by one unless they
are ignored (or allowed in certain position).
Though that is just a single diagnostic wording, while C++ FE just warns
that there are some ignored attributes and doesn't name them individually
(except for namespace and using namespace) and uses different wordings in
different spots.

2023-12-06  Jakub Jelinek  <jakub@redhat.com>

gcc/
	* attribs.h (any_nonignored_attribute_p): Declare.
	* attribs.cc (any_nonignored_attribute_p): New function.
gcc/cp/
	* parser.cc (cp_parser_statement, cp_parser_expression_statement,
	cp_parser_declaration, cp_parser_elaborated_type_specifier,
	cp_parser_asm_definition): Don't diagnose ignored attributes
	if !any_nonignored_attribute_p.
	* decl.cc (grokdeclarator): Likewise.
	* name-lookup.cc (handle_namespace_attrs, finish_using_directive):
	Don't diagnose ignoring of attr_ignored_p attributes.
gcc/testsuite/
	* g++.dg/warn/Wno-attributes-1.C: New test.

--- gcc/attribs.h.jj	2023-12-06 12:03:27.421176109 +0100
+++ gcc/attribs.h	2023-12-06 12:36:55.704884514 +0100
@@ -48,6 +48,7 @@ extern void apply_tm_attr (tree, tree);
 extern tree make_attribute (const char *, const char *, tree);
 extern bool attribute_ignored_p (tree);
 extern bool attribute_ignored_p (const attribute_spec *const);
+extern bool any_nonignored_attribute_p (tree);
 
 extern struct scoped_attributes *
   register_scoped_attributes (const scoped_attribute_specs &, bool = false);
--- gcc/attribs.cc.jj	2023-12-06 12:03:27.386176602 +0100
+++ gcc/attribs.cc	2023-12-06 12:36:55.704884514 +0100
@@ -584,6 +584,19 @@ attribute_ignored_p (const attribute_spe
   return as->max_length == -2;
 }
 
+/* Return true if the ATTRS chain contains at least one attribute which
+   is not ignored.  */
+
+bool
+any_nonignored_attribute_p (tree attrs)
+{
+  for (tree attr = attrs; attr; attr = TREE_CHAIN (attr))
+    if (!attribute_ignored_p (attr))
+      return true;
+
+  return false;
+}
+
 /* See whether LIST contains at least one instance of attribute ATTR
    (possibly with different arguments).  Return the first such attribute
    if so, otherwise return null.  */
--- gcc/cp/parser.cc.jj	2023-12-06 12:03:27.502174967 +0100
+++ gcc/cp/parser.cc	2023-12-06 12:36:55.704884514 +0100
@@ -12778,9 +12778,8 @@ cp_parser_statement (cp_parser* parser,
     SET_EXPR_LOCATION (statement, statement_location);
 
   /* Allow "[[fallthrough]];" or "[[assume(cond)]];", but warn otherwise.  */
-  if (std_attrs != NULL_TREE)
-    warning_at (attrs_loc,
-		OPT_Wattributes,
+  if (std_attrs != NULL_TREE && any_nonignored_attribute_p (std_attrs))
+    warning_at (attrs_loc, OPT_Wattributes,
 		"attributes at the beginning of statement are ignored");
 }
 
@@ -12986,7 +12985,7 @@ cp_parser_expression_statement (cp_parse
     }
 
   /* Allow "[[fallthrough]];", but warn otherwise.  */
-  if (attr != NULL_TREE)
+  if (attr != NULL_TREE && any_nonignored_attribute_p (attr))
     warning_at (loc, OPT_Wattributes,
 		"attributes at the beginning of statement are ignored");
 
@@ -15191,7 +15190,7 @@ cp_parser_declaration (cp_parser* parser
 	    }
 	}
 
-      if (std_attrs != NULL_TREE && !attribute_ignored_p (std_attrs))
+      if (std_attrs != NULL_TREE && any_nonignored_attribute_p (std_attrs))
 	warning_at (make_location (attrs_loc, attrs_loc, parser->lexer),
 		    OPT_Wattributes, "attribute ignored");
       if (cp_lexer_next_token_is (parser->lexer, CPP_SEMICOLON))
@@ -21095,14 +21094,20 @@ cp_parser_elaborated_type_specifier (cp_
   if (attributes)
     {
       if (TREE_CODE (type) == TYPENAME_TYPE)
-	warning (OPT_Wattributes,
-		 "attributes ignored on uninstantiated type");
+	{
+	  if (any_nonignored_attribute_p (attributes))
+	    warning (OPT_Wattributes,
+		     "attributes ignored on uninstantiated type");
+	}
       else if (tag_type != enum_type
 	       && TREE_CODE (type) != BOUND_TEMPLATE_TEMPLATE_PARM
 	       && CLASSTYPE_TEMPLATE_INSTANTIATION (type)
 	       && ! processing_explicit_instantiation)
-	warning (OPT_Wattributes,
-		 "attributes ignored on template instantiation");
+	{
+	  if (any_nonignored_attribute_p (attributes))
+	    warning (OPT_Wattributes,
+		     "attributes ignored on template instantiation");
+	}
       else if (is_friend && cxx11_attribute_p (attributes))
 	{
 	  if (warning (OPT_Wattributes, "attribute ignored"))
@@ -21111,7 +21116,7 @@ cp_parser_elaborated_type_specifier (cp_
 	}
       else if (is_declaration && cp_parser_declares_only_class_p (parser))
 	cplus_decl_attributes (&type, attributes, (int) ATTR_FLAG_TYPE_IN_PLACE);
-      else
+      else if (any_nonignored_attribute_p (attributes))
 	warning (OPT_Wattributes,
 		 "attributes ignored on elaborated-type-specifier that is "
 		 "not a forward declaration");
@@ -22672,7 +22677,7 @@ cp_parser_asm_definition (cp_parser* par
 	symtab->finalize_toplevel_asm (string);
     }
 
-  if (std_attrs)
+  if (std_attrs && any_nonignored_attribute_p (std_attrs))
     warning_at (asm_loc, OPT_Wattributes,
 		"attributes ignored on %<asm%> declaration");
 }
--- gcc/cp/decl.cc.jj	2023-12-06 12:03:27.483175235 +0100
+++ gcc/cp/decl.cc	2023-12-06 12:36:55.698884598 +0100
@@ -13058,7 +13058,8 @@ grokdeclarator (const cp_declarator *dec
       && !diagnose_misapplied_contracts (declspecs->std_attributes))
     {
       location_t attr_loc = declspecs->locations[ds_std_attribute];
-      if (warning_at (attr_loc, OPT_Wattributes, "attribute ignored"))
+      if (any_nonignored_attribute_p (declspecs->std_attributes)
+	  && warning_at (attr_loc, OPT_Wattributes, "attribute ignored"))
 	inform (attr_loc, "an attribute that appertains to a type-specifier "
 		"is ignored");
     }
--- gcc/cp/name-lookup.cc.jj	2023-12-06 12:03:27.495175066 +0100
+++ gcc/cp/name-lookup.cc	2023-12-06 12:36:55.695884641 +0100
@@ -6356,7 +6356,7 @@ handle_namespace_attrs (tree ns, tree at
 	    DECL_ATTRIBUTES (ns) = tree_cons (name, args,
 					      DECL_ATTRIBUTES (ns));
 	}
-      else
+      else if (!attribute_ignored_p (d))
 	{
 	  warning (OPT_Wattributes, "%qD attribute directive ignored",
 		   name);
@@ -8703,7 +8703,7 @@ finish_using_directive (tree target, tre
 		diagnosed = true;
 	      }
 	  }
-	else
+	else if (!attribute_ignored_p (a))
 	  warning (OPT_Wattributes, "%qD attribute directive ignored", name);
       }
 }
--- gcc/testsuite/g++.dg/warn/Wno-attributes-1.C.jj	2023-12-06 14:27:29.006249075 +0100
+++ gcc/testsuite/g++.dg/warn/Wno-attributes-1.C	2023-12-06 14:45:32.475056797 +0100
@@ -0,0 +1,46 @@
+// { dg-do compile { target c++11 } }
+// { dg-options "-Wno-attributes=bar:: -Wno-attributes=baz::qux" }
+
+[[foo::bar]];				// { dg-warning "attribute ignored" }
+[[bar::foo, foo::bar, baz::qux]];	// { dg-warning "attribute ignored" }
+[[bar::foo, bar::bar, baz::qux]];	// { dg-bogus "attribute ignored" }
+
+namespace [[foo::bar]] N {		// { dg-warning "'bar' attribute directive ignored" }
+  int n;
+}
+namespace [[bar::foo, foo::bar, baz::qux]] O { // { dg-warning "'bar' attribute directive ignored" }
+  int o;
+}
+namespace [[bar::foo, bar::bar, baz::qux]] P { // { dg-bogus "attribute directive ignored" }
+  int p;
+}
+
+void
+foo ()
+{
+  int i = 0;
+  [[foo::bar]];				// { dg-warning "attributes at the beginning of statement are ignored" }
+  [[bar::foo, foo::bar, baz::qux]];	// { dg-warning "attributes at the beginning of statement are ignored" }
+  [[bar::foo, bar::bar, baz::qux]];	// { dg-bogus "attributes at the beginning of statement are ignored" }
+  [[foo::bar]] ++i;			// { dg-warning "attributes at the beginning of statement are ignored" }
+  [[bar::foo, foo::bar, baz::qux]] ++i;	// { dg-warning "attributes at the beginning of statement are ignored" }
+  [[bar::foo, bar::bar, baz::qux]] ++i;	// { dg-bogus "attributes at the beginning of statement are ignored" }
+  [[foo::bar]] asm ("");		// { dg-warning "attributes ignored on 'asm' declaration" }
+  [[bar::foo, foo::bar, baz::qux]] asm (""); // { dg-warning "attributes ignored on 'asm' declaration" }
+  [[bar::foo, bar::bar, baz::qux]] asm (""); // { dg-bogus "attributes ignored on 'asm' declaration" }
+  [[foo::bar]] using namespace N;	// { dg-warning "'bar' attribute directive ignored" }
+  [[bar::foo, foo::bar, baz::qux]] using namespace O; // { dg-warning "'bar' attribute directive ignored" }
+  [[bar::foo, bar::bar, baz::qux]] using namespace P; // { dg-bogus "attribute directive ignored" }
+}
+
+class S
+{
+  [[foo::bar]] friend int bar (S &);	// { dg-warning "attribute ignored" }
+					// { dsg-message "an attribute that appertains to a friend declaration that is not a definition is ignored" "" { target *-*-* } .-1 }
+  [[bar::foo, foo::bar, baz::qux]] friend int baz (S &); // { dg-warning "attribute ignored" }
+					// { dsg-message "an attribute that appertains to a friend declaration that is not a definition is ignored" "" { target *-*-* } .-1 }
+  [[bar::foo, bar::bar, baz::qux]] friend int qux (S &); // { dg-warning "attribute ignored" }
+					// { dsg-message "an attribute that appertains to a friend declaration that is not a definition is ignored" "" { target *-*-* } .-1 }
+public:
+  int s;
+};

	Jakub


^ permalink raw reply	[flat|nested] 7+ messages in thread

* Re: [PATCH] c++: Don't diagnose ignoring of attributes if all ignored attributes are attribute_ignored_p
  2023-12-06 14:10   ` [PATCH] c++: Don't diagnose ignoring of attributes if all ignored attributes are attribute_ignored_p Jakub Jelinek
@ 2023-12-07  7:47     ` Jakub Jelinek
  2023-12-08 17:06     ` Jason Merrill
  1 sibling, 0 replies; 7+ messages in thread
From: Jakub Jelinek @ 2023-12-07  7:47 UTC (permalink / raw)
  To: Jason Merrill, gcc-patches

On Wed, Dec 06, 2023 at 03:10:41PM +0100, Jakub Jelinek wrote:
> So far tested with
> GXX_TESTSUITE_STDS=98,11,14,17,20,23,26 make check-g++ RUNTESTFLAGS="dg.exp=Wno-attributes* ubsan.exp=Wno-attributes*"
> (which is all tests that use -Wno-attributes=), ok for trunk if it passes
> full bootstrap/regtest?

Successfully bootstrapped/regtested on x86_64-linux and i686-linux.

> 2023-12-06  Jakub Jelinek  <jakub@redhat.com>
> 
> gcc/
> 	* attribs.h (any_nonignored_attribute_p): Declare.
> 	* attribs.cc (any_nonignored_attribute_p): New function.
> gcc/cp/
> 	* parser.cc (cp_parser_statement, cp_parser_expression_statement,
> 	cp_parser_declaration, cp_parser_elaborated_type_specifier,
> 	cp_parser_asm_definition): Don't diagnose ignored attributes
> 	if !any_nonignored_attribute_p.
> 	* decl.cc (grokdeclarator): Likewise.
> 	* name-lookup.cc (handle_namespace_attrs, finish_using_directive):
> 	Don't diagnose ignoring of attr_ignored_p attributes.
> gcc/testsuite/
> 	* g++.dg/warn/Wno-attributes-1.C: New test.

	Jakub


^ permalink raw reply	[flat|nested] 7+ messages in thread

* Re: [PATCH] c++: Don't diagnose ignoring of attributes if all ignored attributes are attribute_ignored_p
  2023-12-06 14:10   ` [PATCH] c++: Don't diagnose ignoring of attributes if all ignored attributes are attribute_ignored_p Jakub Jelinek
  2023-12-07  7:47     ` Jakub Jelinek
@ 2023-12-08 17:06     ` Jason Merrill
  2023-12-08 17:53       ` [PATCH] c++, v2: " Jakub Jelinek
  1 sibling, 1 reply; 7+ messages in thread
From: Jason Merrill @ 2023-12-08 17:06 UTC (permalink / raw)
  To: Jakub Jelinek; +Cc: gcc-patches

On 12/6/23 09:10, Jakub Jelinek wrote:
> On Tue, Dec 05, 2023 at 11:01:20AM -0500, Jason Merrill wrote:
>>> And there is another thing I wonder about: with -Wno-attributes= we are
>>> supposed to ignore the attributes altogether, but we are actually still
>>> warning about them when we emit these generic warnings about ignoring
>>> all attributes which appertain to this and that (perhaps with some
>>> exceptions we first remove from the attribute chain), like:
>>> void foo () { [[foo::bar]]; }
>>> with -Wattributes -Wno-attributes=foo::bar
>>> Shouldn't we call some helper function in cases like this and warn
>>> not when std_attrs (or how the attribute chain var is called) is non-NULL,
>>> but if it is non-NULL and contains at least one non-attribute_ignored_p
>>> attribute?
>>
>> Sounds good.
> 
> The following patch implements it.
> I've kept warnings for cases where the C++ standard says explicitly any
> attributes aren't ok -
> "If an attribute-specifier-seq appertains to a friend declaration, that
> declaration shall be a definition."
> 
> For some changes I haven't figured out how could I cover it in the
> testsuite.
> 
> So far tested with
> GXX_TESTSUITE_STDS=98,11,14,17,20,23,26 make check-g++ RUNTESTFLAGS="dg.exp=Wno-attributes* ubsan.exp=Wno-attributes*"
> (which is all tests that use -Wno-attributes=), ok for trunk if it passes
> full bootstrap/regtest?
> 
> Note, C uses a different strategy, it has c_warn_unused_attributes
> function which warns about all the attributes one by one unless they
> are ignored (or allowed in certain position).
> Though that is just a single diagnostic wording, while C++ FE just warns
> that there are some ignored attributes and doesn't name them individually
> (except for namespace and using namespace) and uses different wordings in
> different spots.
> 
> 2023-12-06  Jakub Jelinek  <jakub@redhat.com>
> 
> gcc/
> 	* attribs.h (any_nonignored_attribute_p): Declare.
> 	* attribs.cc (any_nonignored_attribute_p): New function.
> gcc/cp/
> 	* parser.cc (cp_parser_statement, cp_parser_expression_statement,
> 	cp_parser_declaration, cp_parser_elaborated_type_specifier,
> 	cp_parser_asm_definition): Don't diagnose ignored attributes
> 	if !any_nonignored_attribute_p.
> 	* decl.cc (grokdeclarator): Likewise.
> 	* name-lookup.cc (handle_namespace_attrs, finish_using_directive):
> 	Don't diagnose ignoring of attr_ignored_p attributes.
> gcc/testsuite/
> 	* g++.dg/warn/Wno-attributes-1.C: New test.
> 
> --- gcc/cp/parser.cc.jj	2023-12-06 12:03:27.502174967 +0100
> +++ gcc/cp/parser.cc	2023-12-06 12:36:55.704884514 +0100
> @@ -21095,14 +21094,20 @@ cp_parser_elaborated_type_specifier (cp_
>     if (attributes)
>       {
>         if (TREE_CODE (type) == TYPENAME_TYPE)
> -	warning (OPT_Wattributes,
> -		 "attributes ignored on uninstantiated type");
> +	{
> +	  if (any_nonignored_attribute_p (attributes))
> +	    warning (OPT_Wattributes,
> +		     "attributes ignored on uninstantiated type");
> +	}
>         else if (tag_type != enum_type
>   	       && TREE_CODE (type) != BOUND_TEMPLATE_TEMPLATE_PARM
>   	       && CLASSTYPE_TEMPLATE_INSTANTIATION (type)
>   	       && ! processing_explicit_instantiation)
> -	warning (OPT_Wattributes,
> -		 "attributes ignored on template instantiation");
> +	{
> +	  if (any_nonignored_attribute_p (attributes))
> +	    warning (OPT_Wattributes,
> +		     "attributes ignored on template instantiation");
> +	}
>         else if (is_friend && cxx11_attribute_p (attributes))
>   	{
>   	  if (warning (OPT_Wattributes, "attribute ignored"))
> @@ -21111,7 +21116,7 @@ cp_parser_elaborated_type_specifier (cp_
>   	}
>         else if (is_declaration && cp_parser_declares_only_class_p (parser))
>   	cplus_decl_attributes (&type, attributes, (int) ATTR_FLAG_TYPE_IN_PLACE);
> -      else
> +      else if (any_nonignored_attribute_p (attributes))
>   	warning (OPT_Wattributes,
>   		 "attributes ignored on elaborated-type-specifier that is "
>   		 "not a forward declaration");

I believe this is also prohibited by
https://eel.is/c++draft/dcl.type.elab#3

so I would leave all the warnings in this function alone.

> @@ -22672,7 +22677,7 @@ cp_parser_asm_definition (cp_parser* par
>   	symtab->finalize_toplevel_asm (string);
>       }
>   
> -  if (std_attrs)
> +  if (std_attrs && any_nonignored_attribute_p (std_attrs))
>       warning_at (asm_loc, OPT_Wattributes,
>   		"attributes ignored on %<asm%> declaration");
>   }
> --- gcc/cp/decl.cc.jj	2023-12-06 12:03:27.483175235 +0100
> +++ gcc/cp/decl.cc	2023-12-06 12:36:55.698884598 +0100
> @@ -13058,7 +13058,8 @@ grokdeclarator (const cp_declarator *dec
>         && !diagnose_misapplied_contracts (declspecs->std_attributes))
>       {
>         location_t attr_loc = declspecs->locations[ds_std_attribute];
> -      if (warning_at (attr_loc, OPT_Wattributes, "attribute ignored"))
> +      if (any_nonignored_attribute_p (declspecs->std_attributes)
> +	  && warning_at (attr_loc, OPT_Wattributes, "attribute ignored"))
>   	inform (attr_loc, "an attribute that appertains to a type-specifier "
>   		"is ignored");
>       }

This seems untested, e.g.

int [[foo::bar]] i;

Jason


^ permalink raw reply	[flat|nested] 7+ messages in thread

* [PATCH] c++, v2: Don't diagnose ignoring of attributes if all ignored attributes are attribute_ignored_p
  2023-12-08 17:06     ` Jason Merrill
@ 2023-12-08 17:53       ` Jakub Jelinek
  2023-12-08 19:48         ` Jason Merrill
  0 siblings, 1 reply; 7+ messages in thread
From: Jakub Jelinek @ 2023-12-08 17:53 UTC (permalink / raw)
  To: Jason Merrill; +Cc: gcc-patches

On Fri, Dec 08, 2023 at 12:06:01PM -0500, Jason Merrill wrote:
> > @@ -21111,7 +21116,7 @@ cp_parser_elaborated_type_specifier (cp_
> >   	}
> >         else if (is_declaration && cp_parser_declares_only_class_p (parser))
> >   	cplus_decl_attributes (&type, attributes, (int) ATTR_FLAG_TYPE_IN_PLACE);
> > -      else
> > +      else if (any_nonignored_attribute_p (attributes))
> >   	warning (OPT_Wattributes,
> >   		 "attributes ignored on elaborated-type-specifier that is "
> >   		 "not a forward declaration");
> 
> I believe this is also prohibited by
> https://eel.is/c++draft/dcl.type.elab#3

You're right and there is also
https://eel.is/c++draft/temp.spec#temp.explicit-3
which prohibits it for explicit template instantiations.

> so I would leave all the warnings in this function alone.

Ok.

> >         location_t attr_loc = declspecs->locations[ds_std_attribute];
> > -      if (warning_at (attr_loc, OPT_Wattributes, "attribute ignored"))
> > +      if (any_nonignored_attribute_p (declspecs->std_attributes)
> > +	  && warning_at (attr_loc, OPT_Wattributes, "attribute ignored"))
> >   	inform (attr_loc, "an attribute that appertains to a type-specifier "
> >   		"is ignored");
> >       }
> 
> This seems untested, e.g.
> 
> int [[foo::bar]] i;

Thanks.

Here is an updated patch, so far tested with
GXX_TESTSUITE_STDS=98,11,14,17,20,23,26 make check-g++ RUNTESTFLAGS="dg.exp='Wno-attributes*' ubsan.exp=Wno-attributes*"
Ok for trunk if it passes full bootstrap/regtest?

2023-12-08  Jakub Jelinek  <jakub@redhat.com>

gcc/
	* attribs.h (any_nonignored_attribute_p): Declare.
	* attribs.cc (any_nonignored_attribute_p): New function.
gcc/cp/
	* parser.cc (cp_parser_statement, cp_parser_expression_statement,
	cp_parser_declaration, cp_parser_asm_definition): Don't diagnose
	ignored attributes if !any_nonignored_attribute_p.
	* decl.cc (grokdeclarator): Likewise.
	* name-lookup.cc (handle_namespace_attrs, finish_using_directive):
	Don't diagnose ignoring of attr_ignored_p attributes.
gcc/testsuite/
	* g++.dg/warn/Wno-attributes-1.C: New test.

--- gcc/attribs.h.jj	2023-12-06 12:03:27.421176109 +0100
+++ gcc/attribs.h	2023-12-06 12:36:55.704884514 +0100
@@ -48,6 +48,7 @@ extern void apply_tm_attr (tree, tree);
 extern tree make_attribute (const char *, const char *, tree);
 extern bool attribute_ignored_p (tree);
 extern bool attribute_ignored_p (const attribute_spec *const);
+extern bool any_nonignored_attribute_p (tree);
 
 extern struct scoped_attributes *
   register_scoped_attributes (const scoped_attribute_specs &, bool = false);
--- gcc/attribs.cc.jj	2023-12-06 12:03:27.386176602 +0100
+++ gcc/attribs.cc	2023-12-06 12:36:55.704884514 +0100
@@ -584,6 +584,19 @@ attribute_ignored_p (const attribute_spe
   return as->max_length == -2;
 }
 
+/* Return true if the ATTRS chain contains at least one attribute which
+   is not ignored.  */
+
+bool
+any_nonignored_attribute_p (tree attrs)
+{
+  for (tree attr = attrs; attr; attr = TREE_CHAIN (attr))
+    if (!attribute_ignored_p (attr))
+      return true;
+
+  return false;
+}
+
 /* See whether LIST contains at least one instance of attribute ATTR
    (possibly with different arguments).  Return the first such attribute
    if so, otherwise return null.  */
--- gcc/cp/parser.cc.jj	2023-12-06 12:03:27.502174967 +0100
+++ gcc/cp/parser.cc	2023-12-06 12:36:55.704884514 +0100
@@ -12778,9 +12778,8 @@ cp_parser_statement (cp_parser* parser,
     SET_EXPR_LOCATION (statement, statement_location);
 
   /* Allow "[[fallthrough]];" or "[[assume(cond)]];", but warn otherwise.  */
-  if (std_attrs != NULL_TREE)
-    warning_at (attrs_loc,
-		OPT_Wattributes,
+  if (std_attrs != NULL_TREE && any_nonignored_attribute_p (std_attrs))
+    warning_at (attrs_loc, OPT_Wattributes,
 		"attributes at the beginning of statement are ignored");
 }
 
@@ -12986,7 +12985,7 @@ cp_parser_expression_statement (cp_parse
     }
 
   /* Allow "[[fallthrough]];", but warn otherwise.  */
-  if (attr != NULL_TREE)
+  if (attr != NULL_TREE && any_nonignored_attribute_p (attr))
     warning_at (loc, OPT_Wattributes,
 		"attributes at the beginning of statement are ignored");
 
@@ -15191,7 +15190,7 @@ cp_parser_declaration (cp_parser* parser
 	    }
 	}
 
-      if (std_attrs != NULL_TREE && !attribute_ignored_p (std_attrs))
+      if (std_attrs != NULL_TREE && any_nonignored_attribute_p (std_attrs))
 	warning_at (make_location (attrs_loc, attrs_loc, parser->lexer),
 		    OPT_Wattributes, "attribute ignored");
       if (cp_lexer_next_token_is (parser->lexer, CPP_SEMICOLON))
@@ -22672,7 +22671,7 @@ cp_parser_asm_definition (cp_parser* par
 	symtab->finalize_toplevel_asm (string);
     }
 
-  if (std_attrs)
+  if (std_attrs && any_nonignored_attribute_p (std_attrs))
     warning_at (asm_loc, OPT_Wattributes,
 		"attributes ignored on %<asm%> declaration");
 }
--- gcc/cp/decl.cc.jj	2023-12-06 12:03:27.483175235 +0100
+++ gcc/cp/decl.cc	2023-12-06 12:36:55.698884598 +0100
@@ -13058,7 +13058,8 @@ grokdeclarator (const cp_declarator *dec
       && !diagnose_misapplied_contracts (declspecs->std_attributes))
     {
       location_t attr_loc = declspecs->locations[ds_std_attribute];
-      if (warning_at (attr_loc, OPT_Wattributes, "attribute ignored"))
+      if (any_nonignored_attribute_p (declspecs->std_attributes)
+	  && warning_at (attr_loc, OPT_Wattributes, "attribute ignored"))
 	inform (attr_loc, "an attribute that appertains to a type-specifier "
 		"is ignored");
     }
--- gcc/cp/name-lookup.cc.jj	2023-12-06 12:03:27.495175066 +0100
+++ gcc/cp/name-lookup.cc	2023-12-06 12:36:55.695884641 +0100
@@ -6356,7 +6356,7 @@ handle_namespace_attrs (tree ns, tree at
 	    DECL_ATTRIBUTES (ns) = tree_cons (name, args,
 					      DECL_ATTRIBUTES (ns));
 	}
-      else
+      else if (!attribute_ignored_p (d))
 	{
 	  warning (OPT_Wattributes, "%qD attribute directive ignored",
 		   name);
@@ -8703,7 +8703,7 @@ finish_using_directive (tree target, tre
 		diagnosed = true;
 	      }
 	  }
-	else
+	else if (!attribute_ignored_p (a))
 	  warning (OPT_Wattributes, "%qD attribute directive ignored", name);
       }
 }
--- gcc/testsuite/g++.dg/warn/Wno-attributes-1.C.jj	2023-12-06 14:27:29.006249075 +0100
+++ gcc/testsuite/g++.dg/warn/Wno-attributes-1.C	2023-12-08 18:50:36.077628959 +0100
@@ -0,0 +1,52 @@
+// { dg-do compile { target c++11 } }
+// { dg-options "-Wno-attributes=bar:: -Wno-attributes=baz::qux" }
+
+[[foo::bar]];				// { dg-warning "attribute ignored" }
+[[bar::foo, foo::bar, baz::qux]];	// { dg-warning "attribute ignored" }
+[[bar::foo, bar::bar, baz::qux]];	// { dg-bogus "attribute ignored" }
+
+namespace [[foo::bar]] N {		// { dg-warning "'bar' attribute directive ignored" }
+  int n;
+}
+namespace [[bar::foo, foo::bar, baz::qux]] O { // { dg-warning "'bar' attribute directive ignored" }
+  int o;
+}
+namespace [[bar::foo, bar::bar, baz::qux]] P { // { dg-bogus "attribute directive ignored" }
+  int p;
+}
+
+void
+foo ()
+{
+  int i = 0;
+  [[foo::bar]];				// { dg-warning "attributes at the beginning of statement are ignored" }
+  [[bar::foo, foo::bar, baz::qux]];	// { dg-warning "attributes at the beginning of statement are ignored" }
+  [[bar::foo, bar::bar, baz::qux]];	// { dg-bogus "attributes at the beginning of statement are ignored" }
+  [[foo::bar]] ++i;			// { dg-warning "attributes at the beginning of statement are ignored" }
+  [[bar::foo, foo::bar, baz::qux]] ++i;	// { dg-warning "attributes at the beginning of statement are ignored" }
+  [[bar::foo, bar::bar, baz::qux]] ++i;	// { dg-bogus "attributes at the beginning of statement are ignored" }
+  [[foo::bar]] asm ("");		// { dg-warning "attributes ignored on 'asm' declaration" }
+  [[bar::foo, foo::bar, baz::qux]] asm (""); // { dg-warning "attributes ignored on 'asm' declaration" }
+  [[bar::foo, bar::bar, baz::qux]] asm (""); // { dg-bogus "attributes ignored on 'asm' declaration" }
+  [[foo::bar]] using namespace N;	// { dg-warning "'bar' attribute directive ignored" }
+  [[bar::foo, foo::bar, baz::qux]] using namespace O; // { dg-warning "'bar' attribute directive ignored" }
+  [[bar::foo, bar::bar, baz::qux]] using namespace P; // { dg-bogus "attribute directive ignored" }
+}
+
+class S
+{
+  [[foo::bar]] friend int bar (S &);	// { dg-warning "attribute ignored" }
+					// { dsg-message "an attribute that appertains to a friend declaration that is not a definition is ignored" "" { target *-*-* } .-1 }
+  [[bar::foo, foo::bar, baz::qux]] friend int baz (S &); // { dg-warning "attribute ignored" }
+					// { dsg-message "an attribute that appertains to a friend declaration that is not a definition is ignored" "" { target *-*-* } .-1 }
+  [[bar::foo, bar::bar, baz::qux]] friend int qux (S &); // { dg-warning "attribute ignored" }
+					// { dsg-message "an attribute that appertains to a friend declaration that is not a definition is ignored" "" { target *-*-* } .-1 }
+public:
+  int s;
+};
+
+int [[foo::bar]] i;			// { dg-warning "attribute ignored" }
+					// { dg-message "an attribute that appertains to a type-specifier is ignored" "" { target *-*-* } .-1 }
+int [[bar::foo, foo::bar, baz::qux]] j;	// { dg-warning "attribute ignored" }
+					// { dg-message "an attribute that appertains to a type-specifier is ignored" "" { target *-*-* } .-1 }
+int [[bar::foo, bar::bar, baz::qux]] k;	// { dg-bogus "attribute ignored" }


	Jakub


^ permalink raw reply	[flat|nested] 7+ messages in thread

* Re: [PATCH] c++, v2: Don't diagnose ignoring of attributes if all ignored attributes are attribute_ignored_p
  2023-12-08 17:53       ` [PATCH] c++, v2: " Jakub Jelinek
@ 2023-12-08 19:48         ` Jason Merrill
  0 siblings, 0 replies; 7+ messages in thread
From: Jason Merrill @ 2023-12-08 19:48 UTC (permalink / raw)
  To: Jakub Jelinek; +Cc: gcc-patches

On 12/8/23 12:53, Jakub Jelinek wrote:
> On Fri, Dec 08, 2023 at 12:06:01PM -0500, Jason Merrill wrote:
>>> @@ -21111,7 +21116,7 @@ cp_parser_elaborated_type_specifier (cp_
>>>    	}
>>>          else if (is_declaration && cp_parser_declares_only_class_p (parser))
>>>    	cplus_decl_attributes (&type, attributes, (int) ATTR_FLAG_TYPE_IN_PLACE);
>>> -      else
>>> +      else if (any_nonignored_attribute_p (attributes))
>>>    	warning (OPT_Wattributes,
>>>    		 "attributes ignored on elaborated-type-specifier that is "
>>>    		 "not a forward declaration");
>>
>> I believe this is also prohibited by
>> https://eel.is/c++draft/dcl.type.elab#3
> 
> You're right and there is also
> https://eel.is/c++draft/temp.spec#temp.explicit-3
> which prohibits it for explicit template instantiations.
> 
>> so I would leave all the warnings in this function alone.
> 
> Ok.
> 
>>>          location_t attr_loc = declspecs->locations[ds_std_attribute];
>>> -      if (warning_at (attr_loc, OPT_Wattributes, "attribute ignored"))
>>> +      if (any_nonignored_attribute_p (declspecs->std_attributes)
>>> +	  && warning_at (attr_loc, OPT_Wattributes, "attribute ignored"))
>>>    	inform (attr_loc, "an attribute that appertains to a type-specifier "
>>>    		"is ignored");
>>>        }
>>
>> This seems untested, e.g.
>>
>> int [[foo::bar]] i;
> 
> Thanks.
> 
> Here is an updated patch, so far tested with
> GXX_TESTSUITE_STDS=98,11,14,17,20,23,26 make check-g++ RUNTESTFLAGS="dg.exp='Wno-attributes*' ubsan.exp=Wno-attributes*"
> Ok for trunk if it passes full bootstrap/regtest?

OK.

> 2023-12-08  Jakub Jelinek  <jakub@redhat.com>
> 
> gcc/
> 	* attribs.h (any_nonignored_attribute_p): Declare.
> 	* attribs.cc (any_nonignored_attribute_p): New function.
> gcc/cp/
> 	* parser.cc (cp_parser_statement, cp_parser_expression_statement,
> 	cp_parser_declaration, cp_parser_asm_definition): Don't diagnose
> 	ignored attributes if !any_nonignored_attribute_p.
> 	* decl.cc (grokdeclarator): Likewise.
> 	* name-lookup.cc (handle_namespace_attrs, finish_using_directive):
> 	Don't diagnose ignoring of attr_ignored_p attributes.
> gcc/testsuite/
> 	* g++.dg/warn/Wno-attributes-1.C: New test.
> 
> --- gcc/attribs.h.jj	2023-12-06 12:03:27.421176109 +0100
> +++ gcc/attribs.h	2023-12-06 12:36:55.704884514 +0100
> @@ -48,6 +48,7 @@ extern void apply_tm_attr (tree, tree);
>   extern tree make_attribute (const char *, const char *, tree);
>   extern bool attribute_ignored_p (tree);
>   extern bool attribute_ignored_p (const attribute_spec *const);
> +extern bool any_nonignored_attribute_p (tree);
>   
>   extern struct scoped_attributes *
>     register_scoped_attributes (const scoped_attribute_specs &, bool = false);
> --- gcc/attribs.cc.jj	2023-12-06 12:03:27.386176602 +0100
> +++ gcc/attribs.cc	2023-12-06 12:36:55.704884514 +0100
> @@ -584,6 +584,19 @@ attribute_ignored_p (const attribute_spe
>     return as->max_length == -2;
>   }
>   
> +/* Return true if the ATTRS chain contains at least one attribute which
> +   is not ignored.  */
> +
> +bool
> +any_nonignored_attribute_p (tree attrs)
> +{
> +  for (tree attr = attrs; attr; attr = TREE_CHAIN (attr))
> +    if (!attribute_ignored_p (attr))
> +      return true;
> +
> +  return false;
> +}
> +
>   /* See whether LIST contains at least one instance of attribute ATTR
>      (possibly with different arguments).  Return the first such attribute
>      if so, otherwise return null.  */
> --- gcc/cp/parser.cc.jj	2023-12-06 12:03:27.502174967 +0100
> +++ gcc/cp/parser.cc	2023-12-06 12:36:55.704884514 +0100
> @@ -12778,9 +12778,8 @@ cp_parser_statement (cp_parser* parser,
>       SET_EXPR_LOCATION (statement, statement_location);
>   
>     /* Allow "[[fallthrough]];" or "[[assume(cond)]];", but warn otherwise.  */
> -  if (std_attrs != NULL_TREE)
> -    warning_at (attrs_loc,
> -		OPT_Wattributes,
> +  if (std_attrs != NULL_TREE && any_nonignored_attribute_p (std_attrs))
> +    warning_at (attrs_loc, OPT_Wattributes,
>   		"attributes at the beginning of statement are ignored");
>   }
>   
> @@ -12986,7 +12985,7 @@ cp_parser_expression_statement (cp_parse
>       }
>   
>     /* Allow "[[fallthrough]];", but warn otherwise.  */
> -  if (attr != NULL_TREE)
> +  if (attr != NULL_TREE && any_nonignored_attribute_p (attr))
>       warning_at (loc, OPT_Wattributes,
>   		"attributes at the beginning of statement are ignored");
>   
> @@ -15191,7 +15190,7 @@ cp_parser_declaration (cp_parser* parser
>   	    }
>   	}
>   
> -      if (std_attrs != NULL_TREE && !attribute_ignored_p (std_attrs))
> +      if (std_attrs != NULL_TREE && any_nonignored_attribute_p (std_attrs))
>   	warning_at (make_location (attrs_loc, attrs_loc, parser->lexer),
>   		    OPT_Wattributes, "attribute ignored");
>         if (cp_lexer_next_token_is (parser->lexer, CPP_SEMICOLON))
> @@ -22672,7 +22671,7 @@ cp_parser_asm_definition (cp_parser* par
>   	symtab->finalize_toplevel_asm (string);
>       }
>   
> -  if (std_attrs)
> +  if (std_attrs && any_nonignored_attribute_p (std_attrs))
>       warning_at (asm_loc, OPT_Wattributes,
>   		"attributes ignored on %<asm%> declaration");
>   }
> --- gcc/cp/decl.cc.jj	2023-12-06 12:03:27.483175235 +0100
> +++ gcc/cp/decl.cc	2023-12-06 12:36:55.698884598 +0100
> @@ -13058,7 +13058,8 @@ grokdeclarator (const cp_declarator *dec
>         && !diagnose_misapplied_contracts (declspecs->std_attributes))
>       {
>         location_t attr_loc = declspecs->locations[ds_std_attribute];
> -      if (warning_at (attr_loc, OPT_Wattributes, "attribute ignored"))
> +      if (any_nonignored_attribute_p (declspecs->std_attributes)
> +	  && warning_at (attr_loc, OPT_Wattributes, "attribute ignored"))
>   	inform (attr_loc, "an attribute that appertains to a type-specifier "
>   		"is ignored");
>       }
> --- gcc/cp/name-lookup.cc.jj	2023-12-06 12:03:27.495175066 +0100
> +++ gcc/cp/name-lookup.cc	2023-12-06 12:36:55.695884641 +0100
> @@ -6356,7 +6356,7 @@ handle_namespace_attrs (tree ns, tree at
>   	    DECL_ATTRIBUTES (ns) = tree_cons (name, args,
>   					      DECL_ATTRIBUTES (ns));
>   	}
> -      else
> +      else if (!attribute_ignored_p (d))
>   	{
>   	  warning (OPT_Wattributes, "%qD attribute directive ignored",
>   		   name);
> @@ -8703,7 +8703,7 @@ finish_using_directive (tree target, tre
>   		diagnosed = true;
>   	      }
>   	  }
> -	else
> +	else if (!attribute_ignored_p (a))
>   	  warning (OPT_Wattributes, "%qD attribute directive ignored", name);
>         }
>   }
> --- gcc/testsuite/g++.dg/warn/Wno-attributes-1.C.jj	2023-12-06 14:27:29.006249075 +0100
> +++ gcc/testsuite/g++.dg/warn/Wno-attributes-1.C	2023-12-08 18:50:36.077628959 +0100
> @@ -0,0 +1,52 @@
> +// { dg-do compile { target c++11 } }
> +// { dg-options "-Wno-attributes=bar:: -Wno-attributes=baz::qux" }
> +
> +[[foo::bar]];				// { dg-warning "attribute ignored" }
> +[[bar::foo, foo::bar, baz::qux]];	// { dg-warning "attribute ignored" }
> +[[bar::foo, bar::bar, baz::qux]];	// { dg-bogus "attribute ignored" }
> +
> +namespace [[foo::bar]] N {		// { dg-warning "'bar' attribute directive ignored" }
> +  int n;
> +}
> +namespace [[bar::foo, foo::bar, baz::qux]] O { // { dg-warning "'bar' attribute directive ignored" }
> +  int o;
> +}
> +namespace [[bar::foo, bar::bar, baz::qux]] P { // { dg-bogus "attribute directive ignored" }
> +  int p;
> +}
> +
> +void
> +foo ()
> +{
> +  int i = 0;
> +  [[foo::bar]];				// { dg-warning "attributes at the beginning of statement are ignored" }
> +  [[bar::foo, foo::bar, baz::qux]];	// { dg-warning "attributes at the beginning of statement are ignored" }
> +  [[bar::foo, bar::bar, baz::qux]];	// { dg-bogus "attributes at the beginning of statement are ignored" }
> +  [[foo::bar]] ++i;			// { dg-warning "attributes at the beginning of statement are ignored" }
> +  [[bar::foo, foo::bar, baz::qux]] ++i;	// { dg-warning "attributes at the beginning of statement are ignored" }
> +  [[bar::foo, bar::bar, baz::qux]] ++i;	// { dg-bogus "attributes at the beginning of statement are ignored" }
> +  [[foo::bar]] asm ("");		// { dg-warning "attributes ignored on 'asm' declaration" }
> +  [[bar::foo, foo::bar, baz::qux]] asm (""); // { dg-warning "attributes ignored on 'asm' declaration" }
> +  [[bar::foo, bar::bar, baz::qux]] asm (""); // { dg-bogus "attributes ignored on 'asm' declaration" }
> +  [[foo::bar]] using namespace N;	// { dg-warning "'bar' attribute directive ignored" }
> +  [[bar::foo, foo::bar, baz::qux]] using namespace O; // { dg-warning "'bar' attribute directive ignored" }
> +  [[bar::foo, bar::bar, baz::qux]] using namespace P; // { dg-bogus "attribute directive ignored" }
> +}
> +
> +class S
> +{
> +  [[foo::bar]] friend int bar (S &);	// { dg-warning "attribute ignored" }
> +					// { dsg-message "an attribute that appertains to a friend declaration that is not a definition is ignored" "" { target *-*-* } .-1 }
> +  [[bar::foo, foo::bar, baz::qux]] friend int baz (S &); // { dg-warning "attribute ignored" }
> +					// { dsg-message "an attribute that appertains to a friend declaration that is not a definition is ignored" "" { target *-*-* } .-1 }
> +  [[bar::foo, bar::bar, baz::qux]] friend int qux (S &); // { dg-warning "attribute ignored" }
> +					// { dsg-message "an attribute that appertains to a friend declaration that is not a definition is ignored" "" { target *-*-* } .-1 }
> +public:
> +  int s;
> +};
> +
> +int [[foo::bar]] i;			// { dg-warning "attribute ignored" }
> +					// { dg-message "an attribute that appertains to a type-specifier is ignored" "" { target *-*-* } .-1 }
> +int [[bar::foo, foo::bar, baz::qux]] j;	// { dg-warning "attribute ignored" }
> +					// { dg-message "an attribute that appertains to a type-specifier is ignored" "" { target *-*-* } .-1 }
> +int [[bar::foo, bar::bar, baz::qux]] k;	// { dg-bogus "attribute ignored" }
> 
> 
> 	Jakub
> 


^ permalink raw reply	[flat|nested] 7+ messages in thread

end of thread, other threads:[~2023-12-08 19:48 UTC | newest]

Thread overview: 7+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2023-12-05  7:40 [PATCH] c++: Implement C++ DR 2262 - Attributes for asm-definition [PR110734] Jakub Jelinek
2023-12-05 16:01 ` Jason Merrill
2023-12-06 14:10   ` [PATCH] c++: Don't diagnose ignoring of attributes if all ignored attributes are attribute_ignored_p Jakub Jelinek
2023-12-07  7:47     ` Jakub Jelinek
2023-12-08 17:06     ` Jason Merrill
2023-12-08 17:53       ` [PATCH] c++, v2: " Jakub Jelinek
2023-12-08 19:48         ` Jason Merrill

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).