c++, v2: Reject attributes without arguments used as pack expansion [PR109756]

Message ID ZFqdnW1JY7nR1bii@tucnak
State Unresolved
Headers
Series c++, v2: Reject attributes without arguments used as pack expansion [PR109756] |

Checks

Context Check Description
snail/gcc-patch-check warning Git am fail log

Commit Message

Jakub Jelinek May 9, 2023, 7:23 p.m. UTC
  On Tue, May 09, 2023 at 01:17:09PM -0400, Jason Merrill wrote:
> How about changing cp_parser_std_attribute to set TREE_VALUE to
> error_mark_node if it skips arguments?

In limited testing that seems to work (tried
GXX_TESTSUITE_STDS=98,11,14,17,20,2b make -j32 -k check-g++ RUNTESTFLAGS='dg.exp=*attr*'
so far with it).

Will bootstrap/regtest it tonight.

Ok if it passes?

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

	PR c++/109756
	* parser.cc (cp_parser_std_attribute): For unknown attributes with
	arguments set TREE_VALUE (attribute) to error_mark_node after skipping
	the balanced tokens.
	(cp_parser_std_attribute_list): If ... is used after attribute without
	arguments, diagnose it and return error_mark_node.  If
	TREE_VALUE (attribute) is error_mark_node, don't call
	make_pack_expansion nor return early error_mark_node.

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



	Jakub
  

Comments

Jason Merrill May 9, 2023, 8:38 p.m. UTC | #1
On 5/9/23 15:23, Jakub Jelinek wrote:
> On Tue, May 09, 2023 at 01:17:09PM -0400, Jason Merrill wrote:
>> How about changing cp_parser_std_attribute to set TREE_VALUE to
>> error_mark_node if it skips arguments?
> 
> In limited testing that seems to work (tried
> GXX_TESTSUITE_STDS=98,11,14,17,20,2b make -j32 -k check-g++ RUNTESTFLAGS='dg.exp=*attr*'
> so far with it).
> 
> Will bootstrap/regtest it tonight.
> 
> Ok if it passes?

OK.

> 2023-05-09  Jakub Jelinek  <jakub@redhat.com>
> 
> 	PR c++/109756
> 	* parser.cc (cp_parser_std_attribute): For unknown attributes with
> 	arguments set TREE_VALUE (attribute) to error_mark_node after skipping
> 	the balanced tokens.
> 	(cp_parser_std_attribute_list): If ... is used after attribute without
> 	arguments, diagnose it and return error_mark_node.  If
> 	TREE_VALUE (attribute) is error_mark_node, don't call
> 	make_pack_expansion nor return early error_mark_node.
> 
> 	* g++.dg/cpp0x/gen-attrs-78.C: New test.
> 
> --- gcc/cp/parser.cc.jj	2023-04-25 16:40:42.010723809 +0200
> +++ gcc/cp/parser.cc	2023-05-09 20:22:42.025601924 +0200
> @@ -29468,9 +29468,12 @@ cp_parser_std_attribute (cp_parser *pars
>   	  }
>   
>   	/* For unknown attributes, just skip balanced tokens instead of
> -	   trying to parse the arguments.  */
> +	   trying to parse the arguments.  Set TREE_VALUE (attribute) to
> +	   error_mark_node to distinguish skipped arguments from attributes
> +	   with no arguments.  */
>   	for (size_t n = cp_parser_skip_balanced_tokens (parser, 1) - 1; n; --n)
>   	  cp_lexer_consume_token (parser->lexer);
> +	TREE_VALUE (attribute) = error_mark_node;
>   	return attribute;
>         }
>   
> @@ -29562,7 +29565,13 @@ cp_parser_std_attribute_list (cp_parser
>   	  if (attribute == NULL_TREE)
>   	    error_at (token->location,
>   		      "expected attribute before %<...%>");
> -	  else
> +	  else if (TREE_VALUE (attribute) == NULL_TREE)
> +	    {
> +	      error_at (token->location, "attribute with no arguments "
> +					 "contains no parameter packs");
> +	      return error_mark_node;
> +	    }
> +	  else if (TREE_VALUE (attribute) != error_mark_node)
>   	    {
>   	      tree pack = make_pack_expansion (TREE_VALUE (attribute));
>   	      if (pack == error_mark_node)
> --- gcc/testsuite/g++.dg/cpp0x/gen-attrs-78.C.jj	2023-05-08 12:33:13.387581760 +0200
> +++ gcc/testsuite/g++.dg/cpp0x/gen-attrs-78.C	2023-05-08 12:32:23.146301128 +0200
> @@ -0,0 +1,29 @@
> +// PR c++/109756
> +// { dg-do compile { target c++11 } }
> +// { dg-options "-Wno-attributes" }
> +
> +template <int ...args>
> +[[noreturn...]]					// { dg-error "attribute with no arguments contains no parameter packs" }
> +[[deprecated...]]				// { dg-error "attribute with no arguments contains no parameter packs" }
> +[[nodiscard...]]				// { dg-error "attribute with no arguments contains no parameter packs" }
> +int foo (int x)
> +{
> +  switch (x)
> +    {
> +    case 1:
> +      [[likely...]];				// { dg-error "attribute with no arguments contains no parameter packs" }
> +      [[fallthrough...]];			// { dg-error "attribute with no arguments contains no parameter packs" }
> +    case 2:
> +      [[unlikely...]];				// { dg-error "attribute with no arguments contains no parameter packs" }
> +
> +      break;
> +    default:
> +      break;
> +    }
> +  struct T {};
> +  struct S { [[no_unique_address...]] T t; };	// { dg-error "attribute with no arguments contains no parameter packs" }
> +  for (;;)
> +    ;
> +}
> +
> +int a = foo <1, 2, 3> (4);
> 
> 
> 	Jakub
>
  

Patch

--- gcc/cp/parser.cc.jj	2023-04-25 16:40:42.010723809 +0200
+++ gcc/cp/parser.cc	2023-05-09 20:22:42.025601924 +0200
@@ -29468,9 +29468,12 @@  cp_parser_std_attribute (cp_parser *pars
 	  }
 
 	/* For unknown attributes, just skip balanced tokens instead of
-	   trying to parse the arguments.  */
+	   trying to parse the arguments.  Set TREE_VALUE (attribute) to
+	   error_mark_node to distinguish skipped arguments from attributes
+	   with no arguments.  */
 	for (size_t n = cp_parser_skip_balanced_tokens (parser, 1) - 1; n; --n)
 	  cp_lexer_consume_token (parser->lexer);
+	TREE_VALUE (attribute) = error_mark_node;
 	return attribute;
       }
 
@@ -29562,7 +29565,13 @@  cp_parser_std_attribute_list (cp_parser
 	  if (attribute == NULL_TREE)
 	    error_at (token->location,
 		      "expected attribute before %<...%>");
-	  else
+	  else if (TREE_VALUE (attribute) == NULL_TREE)
+	    {
+	      error_at (token->location, "attribute with no arguments "
+					 "contains no parameter packs");
+	      return error_mark_node;
+	    }
+	  else if (TREE_VALUE (attribute) != error_mark_node)
 	    {
 	      tree pack = make_pack_expansion (TREE_VALUE (attribute));
 	      if (pack == error_mark_node)
--- gcc/testsuite/g++.dg/cpp0x/gen-attrs-78.C.jj	2023-05-08 12:33:13.387581760 +0200
+++ gcc/testsuite/g++.dg/cpp0x/gen-attrs-78.C	2023-05-08 12:32:23.146301128 +0200
@@ -0,0 +1,29 @@ 
+// PR c++/109756
+// { dg-do compile { target c++11 } }
+// { dg-options "-Wno-attributes" }
+
+template <int ...args>
+[[noreturn...]]					// { dg-error "attribute with no arguments contains no parameter packs" }
+[[deprecated...]]				// { dg-error "attribute with no arguments contains no parameter packs" }
+[[nodiscard...]]				// { dg-error "attribute with no arguments contains no parameter packs" }
+int foo (int x)
+{
+  switch (x)
+    {
+    case 1:
+      [[likely...]];				// { dg-error "attribute with no arguments contains no parameter packs" }
+      [[fallthrough...]];			// { dg-error "attribute with no arguments contains no parameter packs" }
+    case 2:
+      [[unlikely...]];				// { dg-error "attribute with no arguments contains no parameter packs" }
+
+      break;
+    default:
+      break;
+    }
+  struct T {};
+  struct S { [[no_unique_address...]] T t; };	// { dg-error "attribute with no arguments contains no parameter packs" }
+  for (;;)
+    ;
+}
+
+int a = foo <1, 2, 3> (4);