c++: make finish_pseudo_destructor_expr SFINAE-aware [PR116417]

Message ID 20250113162525.1472634-1-ppalka@redhat.com
State Committed
Commit 232d3a73e18d6886f0a5781048a78da293fbb014
Headers
Series c++: make finish_pseudo_destructor_expr SFINAE-aware [PR116417] |

Checks

Context Check Description
linaro-tcwg-bot/tcwg_gcc_build--master-aarch64 success Build passed
linaro-tcwg-bot/tcwg_gcc_check--master-aarch64 success Test passed
linaro-tcwg-bot/tcwg_gcc_build--master-arm success Build passed
linaro-tcwg-bot/tcwg_gcc_check--master-arm success Test passed

Commit Message

Patrick Palka Jan. 13, 2025, 4:25 p.m. UTC
  Bootstrapped and regtested on x86_64-pc-linux-gnu, does this look
OK for trunk?

-- >8 --

	PR c++/116417

gcc/cp/ChangeLog:

	* cp-tree.h (finish_pseudo_destructor_expr): Add complain
	parameter.
	* parser.cc (cp_parser_postfix_dot_deref_expression): Pass
	complain=tf_warning_or_error to finish_pseudo_destructor_expr.
	* pt.cc (tsubst_expr): Pass complain to
	finish_pseudo_destructor_expr.
	* semantics.cc (finish_pseudo_destructor_expr): Check complain
	before issuing a diagnostic.

gcc/testsuite/ChangeLog:

	* g++.dg/template/pseudodtor7.C: New test.
---
 gcc/cp/cp-tree.h                            |  2 +-
 gcc/cp/parser.cc                            |  3 ++-
 gcc/cp/pt.cc                                |  4 ++--
 gcc/cp/semantics.cc                         | 15 +++++++++------
 gcc/testsuite/g++.dg/template/pseudodtor7.C | 15 +++++++++++++++
 5 files changed, 29 insertions(+), 10 deletions(-)
 create mode 100644 gcc/testsuite/g++.dg/template/pseudodtor7.C
  

Comments

Marek Polacek Jan. 13, 2025, 7:57 p.m. UTC | #1
On Mon, Jan 13, 2025 at 11:25:25AM -0500, Patrick Palka wrote:
> Bootstrapped and regtested on x86_64-pc-linux-gnu, does this look
> OK for trunk?

Looks okay to me.
 
> -- >8 --
> 
> 	PR c++/116417
> 
> gcc/cp/ChangeLog:
> 
> 	* cp-tree.h (finish_pseudo_destructor_expr): Add complain
> 	parameter.
> 	* parser.cc (cp_parser_postfix_dot_deref_expression): Pass
> 	complain=tf_warning_or_error to finish_pseudo_destructor_expr.
> 	* pt.cc (tsubst_expr): Pass complain to
> 	finish_pseudo_destructor_expr.
> 	* semantics.cc (finish_pseudo_destructor_expr): Check complain
> 	before issuing a diagnostic.
> 
> gcc/testsuite/ChangeLog:
> 
> 	* g++.dg/template/pseudodtor7.C: New test.
> ---
>  gcc/cp/cp-tree.h                            |  2 +-
>  gcc/cp/parser.cc                            |  3 ++-
>  gcc/cp/pt.cc                                |  4 ++--
>  gcc/cp/semantics.cc                         | 15 +++++++++------
>  gcc/testsuite/g++.dg/template/pseudodtor7.C | 15 +++++++++++++++
>  5 files changed, 29 insertions(+), 10 deletions(-)
>  create mode 100644 gcc/testsuite/g++.dg/template/pseudodtor7.C
> 
> diff --git a/gcc/cp/cp-tree.h b/gcc/cp/cp-tree.h
> index aed58523b16..1b42e8ba7d8 100644
> --- a/gcc/cp/cp-tree.h
> +++ b/gcc/cp/cp-tree.h
> @@ -7966,7 +7966,7 @@ extern tree lookup_and_finish_template_variable (tree, tree, tsubst_flags_t = tf
>  extern tree finish_template_variable		(tree, tsubst_flags_t = tf_warning_or_error);
>  extern cp_expr finish_increment_expr		(cp_expr, enum tree_code);
>  extern tree finish_this_expr			(void);
> -extern tree finish_pseudo_destructor_expr       (tree, tree, tree, location_t);
> +extern tree finish_pseudo_destructor_expr       (tree, tree, tree, location_t, tsubst_flags_t);
>  extern cp_expr finish_unary_op_expr		(location_t, enum tree_code, cp_expr,
>  						 tsubst_flags_t);
>  /* Whether this call to finish_compound_literal represents a C++11 functional
> diff --git a/gcc/cp/parser.cc b/gcc/cp/parser.cc
> index f548dc31c2b..7f4340537c9 100644
> --- a/gcc/cp/parser.cc
> +++ b/gcc/cp/parser.cc
> @@ -8847,7 +8847,8 @@ cp_parser_postfix_dot_deref_expression (cp_parser *parser,
>  	  pseudo_destructor_p = true;
>  	  postfix_expression
>  	    = finish_pseudo_destructor_expr (postfix_expression,
> -					     s, type, location);
> +					     s, type, location,
> +					     tf_warning_or_error);
>  	}
>      }
>  
> diff --git a/gcc/cp/pt.cc b/gcc/cp/pt.cc
> index a141de56446..537e4c4a494 100644
> --- a/gcc/cp/pt.cc
> +++ b/gcc/cp/pt.cc
> @@ -21537,7 +21537,7 @@ tsubst_expr (tree t, tree args, tsubst_flags_t complain, tree in_decl)
>  	tree op1 = RECUR (TREE_OPERAND (t, 1));
>  	tree op2 = tsubst (TREE_OPERAND (t, 2), args, complain, in_decl);
>  	RETURN (finish_pseudo_destructor_expr (op0, op1, op2,
> -					       input_location));
> +					       input_location, complain));
>        }
>  
>      case TREE_LIST:
> @@ -21601,7 +21601,7 @@ tsubst_expr (tree t, tree args, tsubst_flags_t complain, tree in_decl)
>  		    dtor = TREE_OPERAND (dtor, 0);
>  		    if (TYPE_P (dtor))
>  		      RETURN (finish_pseudo_destructor_expr
> -			      (object, s, dtor, input_location));
> +			      (object, s, dtor, input_location, complain));
>  		  }
>  	      }
>  	  }
> diff --git a/gcc/cp/semantics.cc b/gcc/cp/semantics.cc
> index 15840e10620..76c79c6a8cc 100644
> --- a/gcc/cp/semantics.cc
> +++ b/gcc/cp/semantics.cc
> @@ -3527,7 +3527,7 @@ finish_this_expr (void)
>  
>  tree
>  finish_pseudo_destructor_expr (tree object, tree scope, tree destructor,
> -			       location_t loc)
> +			       location_t loc, tsubst_flags_t complain)
>  {
>    if (object == error_mark_node || destructor == error_mark_node)
>      return error_mark_node;
> @@ -3538,16 +3538,18 @@ finish_pseudo_destructor_expr (tree object, tree scope, tree destructor,
>      {
>        if (scope == error_mark_node)
>  	{
> -	  error_at (loc, "invalid qualifying scope in pseudo-destructor name");
> +	  if (complain & tf_error)
> +	    error_at (loc, "invalid qualifying scope in pseudo-destructor name");
>  	  return error_mark_node;
>  	}
>        if (is_auto (destructor))
>  	destructor = TREE_TYPE (object);
>        if (scope && TYPE_P (scope) && !check_dtor_name (scope, destructor))
>  	{
> -	  error_at (loc,
> -		    "qualified type %qT does not match destructor name ~%qT",
> -		    scope, destructor);
> +	  if (complain & tf_error)
> +	    error_at (loc,
> +		      "qualified type %qT does not match destructor name ~%qT",
> +		      scope, destructor);
>  	  return error_mark_node;
>  	}
>  
> @@ -3568,7 +3570,8 @@ finish_pseudo_destructor_expr (tree object, tree scope, tree destructor,
>        if (!same_type_ignoring_top_level_qualifiers_p (TREE_TYPE (object),
>  						      destructor))
>  	{
> -	  error_at (loc, "%qE is not of type %qT", object, destructor);
> +	  if (complain & tf_error)
> +	    error_at (loc, "%qE is not of type %qT", object, destructor);
>  	  return error_mark_node;
>  	}
>      }
> diff --git a/gcc/testsuite/g++.dg/template/pseudodtor7.C b/gcc/testsuite/g++.dg/template/pseudodtor7.C
> new file mode 100644
> index 00000000000..302b8c96625
> --- /dev/null
> +++ b/gcc/testsuite/g++.dg/template/pseudodtor7.C
> @@ -0,0 +1,15 @@
> +// PR c++/116417
> +// { dg-do compile { target c++11 } }
> +
> +template<class T>
> +T&& declval();
> +
> +template<class T, class = decltype(declval<T>().~T())>
> +void f(int) = delete;
> +
> +template<class T>
> +void f(...);
> +
> +int main() {
> +  f<int&>(0);
> +}
> -- 
> 2.48.0.rc1.35.g1b4e9a5f8b
> 

Marek
  
Jason Merrill Jan. 14, 2025, 1:20 a.m. UTC | #2
On 1/13/25 2:57 PM, Marek Polacek wrote:
> On Mon, Jan 13, 2025 at 11:25:25AM -0500, Patrick Palka wrote:
>> Bootstrapped and regtested on x86_64-pc-linux-gnu, does this look
>> OK for trunk?
> 
> Looks okay to me.

OK.

>> -- >8 --
>>
>> 	PR c++/116417
>>
>> gcc/cp/ChangeLog:
>>
>> 	* cp-tree.h (finish_pseudo_destructor_expr): Add complain
>> 	parameter.
>> 	* parser.cc (cp_parser_postfix_dot_deref_expression): Pass
>> 	complain=tf_warning_or_error to finish_pseudo_destructor_expr.
>> 	* pt.cc (tsubst_expr): Pass complain to
>> 	finish_pseudo_destructor_expr.
>> 	* semantics.cc (finish_pseudo_destructor_expr): Check complain
>> 	before issuing a diagnostic.
>>
>> gcc/testsuite/ChangeLog:
>>
>> 	* g++.dg/template/pseudodtor7.C: New test.
>> ---
>>   gcc/cp/cp-tree.h                            |  2 +-
>>   gcc/cp/parser.cc                            |  3 ++-
>>   gcc/cp/pt.cc                                |  4 ++--
>>   gcc/cp/semantics.cc                         | 15 +++++++++------
>>   gcc/testsuite/g++.dg/template/pseudodtor7.C | 15 +++++++++++++++
>>   5 files changed, 29 insertions(+), 10 deletions(-)
>>   create mode 100644 gcc/testsuite/g++.dg/template/pseudodtor7.C
>>
>> diff --git a/gcc/cp/cp-tree.h b/gcc/cp/cp-tree.h
>> index aed58523b16..1b42e8ba7d8 100644
>> --- a/gcc/cp/cp-tree.h
>> +++ b/gcc/cp/cp-tree.h
>> @@ -7966,7 +7966,7 @@ extern tree lookup_and_finish_template_variable (tree, tree, tsubst_flags_t = tf
>>   extern tree finish_template_variable		(tree, tsubst_flags_t = tf_warning_or_error);
>>   extern cp_expr finish_increment_expr		(cp_expr, enum tree_code);
>>   extern tree finish_this_expr			(void);
>> -extern tree finish_pseudo_destructor_expr       (tree, tree, tree, location_t);
>> +extern tree finish_pseudo_destructor_expr       (tree, tree, tree, location_t, tsubst_flags_t);
>>   extern cp_expr finish_unary_op_expr		(location_t, enum tree_code, cp_expr,
>>   						 tsubst_flags_t);
>>   /* Whether this call to finish_compound_literal represents a C++11 functional
>> diff --git a/gcc/cp/parser.cc b/gcc/cp/parser.cc
>> index f548dc31c2b..7f4340537c9 100644
>> --- a/gcc/cp/parser.cc
>> +++ b/gcc/cp/parser.cc
>> @@ -8847,7 +8847,8 @@ cp_parser_postfix_dot_deref_expression (cp_parser *parser,
>>   	  pseudo_destructor_p = true;
>>   	  postfix_expression
>>   	    = finish_pseudo_destructor_expr (postfix_expression,
>> -					     s, type, location);
>> +					     s, type, location,
>> +					     tf_warning_or_error);
>>   	}
>>       }
>>   
>> diff --git a/gcc/cp/pt.cc b/gcc/cp/pt.cc
>> index a141de56446..537e4c4a494 100644
>> --- a/gcc/cp/pt.cc
>> +++ b/gcc/cp/pt.cc
>> @@ -21537,7 +21537,7 @@ tsubst_expr (tree t, tree args, tsubst_flags_t complain, tree in_decl)
>>   	tree op1 = RECUR (TREE_OPERAND (t, 1));
>>   	tree op2 = tsubst (TREE_OPERAND (t, 2), args, complain, in_decl);
>>   	RETURN (finish_pseudo_destructor_expr (op0, op1, op2,
>> -					       input_location));
>> +					       input_location, complain));
>>         }
>>   
>>       case TREE_LIST:
>> @@ -21601,7 +21601,7 @@ tsubst_expr (tree t, tree args, tsubst_flags_t complain, tree in_decl)
>>   		    dtor = TREE_OPERAND (dtor, 0);
>>   		    if (TYPE_P (dtor))
>>   		      RETURN (finish_pseudo_destructor_expr
>> -			      (object, s, dtor, input_location));
>> +			      (object, s, dtor, input_location, complain));
>>   		  }
>>   	      }
>>   	  }
>> diff --git a/gcc/cp/semantics.cc b/gcc/cp/semantics.cc
>> index 15840e10620..76c79c6a8cc 100644
>> --- a/gcc/cp/semantics.cc
>> +++ b/gcc/cp/semantics.cc
>> @@ -3527,7 +3527,7 @@ finish_this_expr (void)
>>   
>>   tree
>>   finish_pseudo_destructor_expr (tree object, tree scope, tree destructor,
>> -			       location_t loc)
>> +			       location_t loc, tsubst_flags_t complain)
>>   {
>>     if (object == error_mark_node || destructor == error_mark_node)
>>       return error_mark_node;
>> @@ -3538,16 +3538,18 @@ finish_pseudo_destructor_expr (tree object, tree scope, tree destructor,
>>       {
>>         if (scope == error_mark_node)
>>   	{
>> -	  error_at (loc, "invalid qualifying scope in pseudo-destructor name");
>> +	  if (complain & tf_error)
>> +	    error_at (loc, "invalid qualifying scope in pseudo-destructor name");
>>   	  return error_mark_node;
>>   	}
>>         if (is_auto (destructor))
>>   	destructor = TREE_TYPE (object);
>>         if (scope && TYPE_P (scope) && !check_dtor_name (scope, destructor))
>>   	{
>> -	  error_at (loc,
>> -		    "qualified type %qT does not match destructor name ~%qT",
>> -		    scope, destructor);
>> +	  if (complain & tf_error)
>> +	    error_at (loc,
>> +		      "qualified type %qT does not match destructor name ~%qT",
>> +		      scope, destructor);
>>   	  return error_mark_node;
>>   	}
>>   
>> @@ -3568,7 +3570,8 @@ finish_pseudo_destructor_expr (tree object, tree scope, tree destructor,
>>         if (!same_type_ignoring_top_level_qualifiers_p (TREE_TYPE (object),
>>   						      destructor))
>>   	{
>> -	  error_at (loc, "%qE is not of type %qT", object, destructor);
>> +	  if (complain & tf_error)
>> +	    error_at (loc, "%qE is not of type %qT", object, destructor);
>>   	  return error_mark_node;
>>   	}
>>       }
>> diff --git a/gcc/testsuite/g++.dg/template/pseudodtor7.C b/gcc/testsuite/g++.dg/template/pseudodtor7.C
>> new file mode 100644
>> index 00000000000..302b8c96625
>> --- /dev/null
>> +++ b/gcc/testsuite/g++.dg/template/pseudodtor7.C
>> @@ -0,0 +1,15 @@
>> +// PR c++/116417
>> +// { dg-do compile { target c++11 } }
>> +
>> +template<class T>
>> +T&& declval();
>> +
>> +template<class T, class = decltype(declval<T>().~T())>
>> +void f(int) = delete;
>> +
>> +template<class T>
>> +void f(...);
>> +
>> +int main() {
>> +  f<int&>(0);
>> +}
>> -- 
>> 2.48.0.rc1.35.g1b4e9a5f8b
>>
> 
> Marek
>
  

Patch

diff --git a/gcc/cp/cp-tree.h b/gcc/cp/cp-tree.h
index aed58523b16..1b42e8ba7d8 100644
--- a/gcc/cp/cp-tree.h
+++ b/gcc/cp/cp-tree.h
@@ -7966,7 +7966,7 @@  extern tree lookup_and_finish_template_variable (tree, tree, tsubst_flags_t = tf
 extern tree finish_template_variable		(tree, tsubst_flags_t = tf_warning_or_error);
 extern cp_expr finish_increment_expr		(cp_expr, enum tree_code);
 extern tree finish_this_expr			(void);
-extern tree finish_pseudo_destructor_expr       (tree, tree, tree, location_t);
+extern tree finish_pseudo_destructor_expr       (tree, tree, tree, location_t, tsubst_flags_t);
 extern cp_expr finish_unary_op_expr		(location_t, enum tree_code, cp_expr,
 						 tsubst_flags_t);
 /* Whether this call to finish_compound_literal represents a C++11 functional
diff --git a/gcc/cp/parser.cc b/gcc/cp/parser.cc
index f548dc31c2b..7f4340537c9 100644
--- a/gcc/cp/parser.cc
+++ b/gcc/cp/parser.cc
@@ -8847,7 +8847,8 @@  cp_parser_postfix_dot_deref_expression (cp_parser *parser,
 	  pseudo_destructor_p = true;
 	  postfix_expression
 	    = finish_pseudo_destructor_expr (postfix_expression,
-					     s, type, location);
+					     s, type, location,
+					     tf_warning_or_error);
 	}
     }
 
diff --git a/gcc/cp/pt.cc b/gcc/cp/pt.cc
index a141de56446..537e4c4a494 100644
--- a/gcc/cp/pt.cc
+++ b/gcc/cp/pt.cc
@@ -21537,7 +21537,7 @@  tsubst_expr (tree t, tree args, tsubst_flags_t complain, tree in_decl)
 	tree op1 = RECUR (TREE_OPERAND (t, 1));
 	tree op2 = tsubst (TREE_OPERAND (t, 2), args, complain, in_decl);
 	RETURN (finish_pseudo_destructor_expr (op0, op1, op2,
-					       input_location));
+					       input_location, complain));
       }
 
     case TREE_LIST:
@@ -21601,7 +21601,7 @@  tsubst_expr (tree t, tree args, tsubst_flags_t complain, tree in_decl)
 		    dtor = TREE_OPERAND (dtor, 0);
 		    if (TYPE_P (dtor))
 		      RETURN (finish_pseudo_destructor_expr
-			      (object, s, dtor, input_location));
+			      (object, s, dtor, input_location, complain));
 		  }
 	      }
 	  }
diff --git a/gcc/cp/semantics.cc b/gcc/cp/semantics.cc
index 15840e10620..76c79c6a8cc 100644
--- a/gcc/cp/semantics.cc
+++ b/gcc/cp/semantics.cc
@@ -3527,7 +3527,7 @@  finish_this_expr (void)
 
 tree
 finish_pseudo_destructor_expr (tree object, tree scope, tree destructor,
-			       location_t loc)
+			       location_t loc, tsubst_flags_t complain)
 {
   if (object == error_mark_node || destructor == error_mark_node)
     return error_mark_node;
@@ -3538,16 +3538,18 @@  finish_pseudo_destructor_expr (tree object, tree scope, tree destructor,
     {
       if (scope == error_mark_node)
 	{
-	  error_at (loc, "invalid qualifying scope in pseudo-destructor name");
+	  if (complain & tf_error)
+	    error_at (loc, "invalid qualifying scope in pseudo-destructor name");
 	  return error_mark_node;
 	}
       if (is_auto (destructor))
 	destructor = TREE_TYPE (object);
       if (scope && TYPE_P (scope) && !check_dtor_name (scope, destructor))
 	{
-	  error_at (loc,
-		    "qualified type %qT does not match destructor name ~%qT",
-		    scope, destructor);
+	  if (complain & tf_error)
+	    error_at (loc,
+		      "qualified type %qT does not match destructor name ~%qT",
+		      scope, destructor);
 	  return error_mark_node;
 	}
 
@@ -3568,7 +3570,8 @@  finish_pseudo_destructor_expr (tree object, tree scope, tree destructor,
       if (!same_type_ignoring_top_level_qualifiers_p (TREE_TYPE (object),
 						      destructor))
 	{
-	  error_at (loc, "%qE is not of type %qT", object, destructor);
+	  if (complain & tf_error)
+	    error_at (loc, "%qE is not of type %qT", object, destructor);
 	  return error_mark_node;
 	}
     }
diff --git a/gcc/testsuite/g++.dg/template/pseudodtor7.C b/gcc/testsuite/g++.dg/template/pseudodtor7.C
new file mode 100644
index 00000000000..302b8c96625
--- /dev/null
+++ b/gcc/testsuite/g++.dg/template/pseudodtor7.C
@@ -0,0 +1,15 @@ 
+// PR c++/116417
+// { dg-do compile { target c++11 } }
+
+template<class T>
+T&& declval();
+
+template<class T, class = decltype(declval<T>().~T())>
+void f(int) = delete;
+
+template<class T>
+void f(...);
+
+int main() {
+  f<int&>(0);
+}