c++: accepts-invalid with =delete("") [PR111840]

Message ID 20231017213826.1040138-1-polacek@redhat.com
State Accepted
Headers
Series c++: accepts-invalid with =delete("") [PR111840] |

Checks

Context Check Description
snail/gcc-patch-check success Github commit url

Commit Message

Marek Polacek Oct. 17, 2023, 9:38 p.m. UTC
  Bootstrapped/regtested on x86_64-pc-linux-gnu, ok for trunk?

-- >8 --
r6-2367 added a DECL_INITIAL check to cp_parser_simple_declaration
so that we don't emit multiple errors in g++.dg/parse/error57.C.
But that means we don't diagnose

  int f1() = delete("george_crumb");

anymore, because fn decls often have error_mark_node in their
DECL_INITIAL.  (The code may be allowed one day via https://wg21.link/P2573R0.)

I was hoping I could use cp_parser_error_occurred but that would
regress error57.C.

	PR c++/111840

gcc/cp/ChangeLog:

	* parser.cc (cp_parser_simple_declaration): Do cp_parser_error
	for FUNCTION_DECLs.

gcc/testsuite/ChangeLog:

	* g++.dg/parse/error65.C: New test.
---
 gcc/cp/parser.cc                     | 14 +++++++-------
 gcc/testsuite/g++.dg/parse/error65.C | 10 ++++++++++
 2 files changed, 17 insertions(+), 7 deletions(-)
 create mode 100644 gcc/testsuite/g++.dg/parse/error65.C


base-commit: bac21b7ea62bd3a7911e01cf803d6bf6516fbf7b
  

Comments

Jason Merrill Oct. 17, 2023, 9:42 p.m. UTC | #1
On 10/17/23 17:38, Marek Polacek wrote:
> Bootstrapped/regtested on x86_64-pc-linux-gnu, ok for trunk?

OK.

> -- >8 --
> r6-2367 added a DECL_INITIAL check to cp_parser_simple_declaration
> so that we don't emit multiple errors in g++.dg/parse/error57.C.
> But that means we don't diagnose
> 
>    int f1() = delete("george_crumb");
> 
> anymore, because fn decls often have error_mark_node in their
> DECL_INITIAL.  (The code may be allowed one day via https://wg21.link/P2573R0.)
> 
> I was hoping I could use cp_parser_error_occurred but that would
> regress error57.C.
> 
> 	PR c++/111840
> 
> gcc/cp/ChangeLog:
> 
> 	* parser.cc (cp_parser_simple_declaration): Do cp_parser_error
> 	for FUNCTION_DECLs.
> 
> gcc/testsuite/ChangeLog:
> 
> 	* g++.dg/parse/error65.C: New test.
> ---
>   gcc/cp/parser.cc                     | 14 +++++++-------
>   gcc/testsuite/g++.dg/parse/error65.C | 10 ++++++++++
>   2 files changed, 17 insertions(+), 7 deletions(-)
>   create mode 100644 gcc/testsuite/g++.dg/parse/error65.C
> 
> diff --git a/gcc/cp/parser.cc b/gcc/cp/parser.cc
> index 59b9852895e..57b62fb7363 100644
> --- a/gcc/cp/parser.cc
> +++ b/gcc/cp/parser.cc
> @@ -15669,6 +15669,7 @@ cp_parser_simple_declaration (cp_parser* parser,
>   					maybe_range_for_decl,
>   					&init_loc,
>   					&auto_result);
> +      const bool fndecl_p = TREE_CODE (decl) == FUNCTION_DECL;
>         /* If an error occurred while parsing tentatively, exit quickly.
>   	 (That usually happens when in the body of a function; each
>   	 statement is treated as a declaration-statement until proven
> @@ -15682,16 +15683,13 @@ cp_parser_simple_declaration (cp_parser* parser,
>   	     init-declarator, they shall all form declarations of
>   	     variables.  */
>   	  if (auto_function_declaration == NULL_TREE)
> -	    auto_function_declaration
> -	      = TREE_CODE (decl) == FUNCTION_DECL ? decl : error_mark_node;
> -	  else if (TREE_CODE (decl) == FUNCTION_DECL
> -		   || auto_function_declaration != error_mark_node)
> +	    auto_function_declaration = fndecl_p ? decl : error_mark_node;
> +	  else if (fndecl_p || auto_function_declaration != error_mark_node)
>   	    {
>   	      error_at (decl_specifiers.locations[ds_type_spec],
>   			"non-variable %qD in declaration with more than one "
>   			"declarator with placeholder type",
> -			TREE_CODE (decl) == FUNCTION_DECL
> -			? decl : auto_function_declaration);
> +			fndecl_p ? decl : auto_function_declaration);
>   	      auto_function_declaration = error_mark_node;
>   	    }
>   	}
> @@ -15763,7 +15761,9 @@ cp_parser_simple_declaration (cp_parser* parser,
>   	  /* If we have already issued an error message we don't need
>   	     to issue another one.  */
>   	  if ((decl != error_mark_node
> -	       && DECL_INITIAL (decl) != error_mark_node)
> +	       /* grokfndecl sets DECL_INITIAL to error_mark_node for
> +		  functions.  */
> +	       && (fndecl_p || DECL_INITIAL (decl) != error_mark_node))
>   	      || cp_parser_uncommitted_to_tentative_parse_p (parser))
>   	    cp_parser_error (parser, "expected %<,%> or %<;%>");
>   	  /* Skip tokens until we reach the end of the statement.  */
> diff --git a/gcc/testsuite/g++.dg/parse/error65.C b/gcc/testsuite/g++.dg/parse/error65.C
> new file mode 100644
> index 00000000000..d9e0a4bfbcb
> --- /dev/null
> +++ b/gcc/testsuite/g++.dg/parse/error65.C
> @@ -0,0 +1,10 @@
> +// PR c++/111840
> +// { dg-do compile { target c++11 } }
> +
> +// NB: =delete("reason") may be allowed via P2573.
> +int f1() = delete("should have a reason"); // { dg-error "expected" }
> +int f2() = delete[""]; // { dg-error "expected" }
> +int f3() = delete{""}; // { dg-error "expected" }
> +int f4() = delete""; // { dg-error "expected" }
> +int f5() = delete[{'a'""; // { dg-error "expected" }
> +int i = f5();
> 
> base-commit: bac21b7ea62bd3a7911e01cf803d6bf6516fbf7b
  

Patch

diff --git a/gcc/cp/parser.cc b/gcc/cp/parser.cc
index 59b9852895e..57b62fb7363 100644
--- a/gcc/cp/parser.cc
+++ b/gcc/cp/parser.cc
@@ -15669,6 +15669,7 @@  cp_parser_simple_declaration (cp_parser* parser,
 					maybe_range_for_decl,
 					&init_loc,
 					&auto_result);
+      const bool fndecl_p = TREE_CODE (decl) == FUNCTION_DECL;
       /* If an error occurred while parsing tentatively, exit quickly.
 	 (That usually happens when in the body of a function; each
 	 statement is treated as a declaration-statement until proven
@@ -15682,16 +15683,13 @@  cp_parser_simple_declaration (cp_parser* parser,
 	     init-declarator, they shall all form declarations of
 	     variables.  */
 	  if (auto_function_declaration == NULL_TREE)
-	    auto_function_declaration
-	      = TREE_CODE (decl) == FUNCTION_DECL ? decl : error_mark_node;
-	  else if (TREE_CODE (decl) == FUNCTION_DECL
-		   || auto_function_declaration != error_mark_node)
+	    auto_function_declaration = fndecl_p ? decl : error_mark_node;
+	  else if (fndecl_p || auto_function_declaration != error_mark_node)
 	    {
 	      error_at (decl_specifiers.locations[ds_type_spec],
 			"non-variable %qD in declaration with more than one "
 			"declarator with placeholder type",
-			TREE_CODE (decl) == FUNCTION_DECL
-			? decl : auto_function_declaration);
+			fndecl_p ? decl : auto_function_declaration);
 	      auto_function_declaration = error_mark_node;
 	    }
 	}
@@ -15763,7 +15761,9 @@  cp_parser_simple_declaration (cp_parser* parser,
 	  /* If we have already issued an error message we don't need
 	     to issue another one.  */
 	  if ((decl != error_mark_node
-	       && DECL_INITIAL (decl) != error_mark_node)
+	       /* grokfndecl sets DECL_INITIAL to error_mark_node for
+		  functions.  */
+	       && (fndecl_p || DECL_INITIAL (decl) != error_mark_node))
 	      || cp_parser_uncommitted_to_tentative_parse_p (parser))
 	    cp_parser_error (parser, "expected %<,%> or %<;%>");
 	  /* Skip tokens until we reach the end of the statement.  */
diff --git a/gcc/testsuite/g++.dg/parse/error65.C b/gcc/testsuite/g++.dg/parse/error65.C
new file mode 100644
index 00000000000..d9e0a4bfbcb
--- /dev/null
+++ b/gcc/testsuite/g++.dg/parse/error65.C
@@ -0,0 +1,10 @@ 
+// PR c++/111840
+// { dg-do compile { target c++11 } }
+
+// NB: =delete("reason") may be allowed via P2573.
+int f1() = delete("should have a reason"); // { dg-error "expected" }
+int f2() = delete[""]; // { dg-error "expected" }
+int f3() = delete{""}; // { dg-error "expected" }
+int f4() = delete""; // { dg-error "expected" }
+int f5() = delete[{'a'""; // { dg-error "expected" }
+int i = f5();