https://gcc.gnu.org/g:3d287bff14885598c75c1cb16b08e0ba4ba05bce

commit r16-1063-g3d287bff14885598c75c1cb16b08e0ba4ba05bce
Author: Jason Merrill <ja...@redhat.com>
Date:   Mon Jun 2 14:58:42 2025 -0400

    c++: more __is_destructible fixes [PR107600]
    
            PR c++/107600
    
    gcc/cp/ChangeLog:
    
            * method.cc (destructible_expr): Fix refs and arrays of unknown
            bound.
    
    gcc/testsuite/ChangeLog:
    
            * g++.dg/ext/is_destructible2.C: Add more cases.

Diff:
---
 gcc/cp/method.cc                            | 11 ++++++++++-
 gcc/testsuite/g++.dg/ext/is_destructible2.C |  9 +++++++++
 2 files changed, 19 insertions(+), 1 deletion(-)

diff --git a/gcc/cp/method.cc b/gcc/cp/method.cc
index bb6790f13cdb..67a80a387ba7 100644
--- a/gcc/cp/method.cc
+++ b/gcc/cp/method.cc
@@ -2332,13 +2332,22 @@ constructible_expr (tree to, tree from)
   return expr;
 }
 
-/* Return declval<T>().~T() treated as an unevaluated operand.  */
+/* Valid if "Either T is a reference type, or T is a complete object type for
+   which the expression declval<U&>().~U() is well-formed when treated as an
+   unevaluated operand ([expr.context]), where U is remove_all_extents_t<T>."
+
+   For a class U, return the destructor call; otherwise return void_node if
+   valid or error_mark_node if not.  */
 
 static tree
 destructible_expr (tree to)
 {
   cp_unevaluated cp_uneval_guard;
   int flags = LOOKUP_NORMAL|LOOKUP_DESTRUCTOR;
+  if (TYPE_REF_P (to))
+    return void_node;
+  if (!COMPLETE_TYPE_P (complete_type (to)))
+    return error_mark_node;
   to = strip_array_types (to);
   if (CLASS_TYPE_P (to))
     {
diff --git a/gcc/testsuite/g++.dg/ext/is_destructible2.C 
b/gcc/testsuite/g++.dg/ext/is_destructible2.C
index 7f15fc786848..2edf440ef44b 100644
--- a/gcc/testsuite/g++.dg/ext/is_destructible2.C
+++ b/gcc/testsuite/g++.dg/ext/is_destructible2.C
@@ -13,3 +13,12 @@ static_assert( __is_assignable(A, A) );
 static_assert( not __is_destructible(int()) );
 static_assert( not __is_nothrow_destructible(int()) );
 static_assert( not __is_trivially_destructible(int()) );
+static_assert( __is_destructible(int&) );
+static_assert( __is_destructible(int&&) );
+static_assert( __is_destructible(int(&)[1]) );
+static_assert( __is_destructible(const int(&)[1]) );
+static_assert( __is_destructible(void(&)()) );
+static_assert( not __is_destructible(int[]) );
+static_assert( not __is_destructible(const int[]) );
+static_assert( not __is_destructible(int[][1]) );
+static_assert( not __is_destructible(const int[][1]) );

Reply via email to