[gcc r14-6187] c++: Implement C++ DR 2262 - Attributes for asm-definition [PR110734]

Jakub Jelinek jakub@gcc.gnu.org
Tue Dec 5 16:39:46 GMT 2023


https://gcc.gnu.org/g:e5153e7d63b4cd9a3df490809c4f3fe1e94d3d37

commit r14-6187-ge5153e7d63b4cd9a3df490809c4f3fe1e94d3d37
Author: Jakub Jelinek <jakub@redhat.com>
Date:   Tue Dec 5 17:38:46 2023 +0100

    c++: Implement C++ DR 2262 - Attributes for asm-definition [PR110734]
    
    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.
    
    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.

Diff:
---
 gcc/cp/parser.cc                          | 48 +++++++++++++++++++++----------
 gcc/testsuite/g++.dg/DRs/dr2262.C         | 16 +++++++++++
 gcc/testsuite/g++.dg/cpp0x/gen-attrs-76.C |  8 +++---
 gcc/testsuite/g++.dg/gomp/attrs-11.C      |  4 +--
 4 files changed, 55 insertions(+), 21 deletions(-)

diff --git a/gcc/cp/parser.cc b/gcc/cp/parser.cc
index 676edf47276..1049a75b384 100644
--- a/gcc/cp/parser.cc
+++ b/gcc/cp/parser.cc
@@ -15398,7 +15398,6 @@ cp_parser_block_declaration (cp_parser *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 *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* parser)
   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* parser)
       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
diff --git a/gcc/testsuite/g++.dg/DRs/dr2262.C b/gcc/testsuite/g++.dg/DRs/dr2262.C
new file mode 100644
index 00000000000..88b8a31e962
--- /dev/null
+++ b/gcc/testsuite/g++.dg/DRs/dr2262.C
@@ -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" }
+}
diff --git a/gcc/testsuite/g++.dg/cpp0x/gen-attrs-76.C b/gcc/testsuite/g++.dg/cpp0x/gen-attrs-76.C
index 72cd4b33e93..eba88fbaaf4 100644
--- a/gcc/testsuite/g++.dg/cpp0x/gen-attrs-76.C
+++ b/gcc/testsuite/g++.dg/cpp0x/gen-attrs-76.C
@@ -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" }
diff --git a/gcc/testsuite/g++.dg/gomp/attrs-11.C b/gcc/testsuite/g++.dg/gomp/attrs-11.C
index 44e025e7540..6cc02d43a25 100644
--- a/gcc/testsuite/g++.dg/gomp/attrs-11.C
+++ b/gcc/testsuite/g++.dg/gomp/attrs-11.C
@@ -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" }


More information about the Gcc-cvs mailing list