https://gcc.gnu.org/g:52c29a6a9dac6caec24b75cae17ecb3558c39504

commit r16-3368-g52c29a6a9dac6caec24b75cae17ecb3558c39504
Author: Jakub Jelinek <ja...@redhat.com>
Date:   Mon Aug 25 16:27:35 2025 +0200

    c++: Check for *jump_target earlier in cxx_bind_parameters_in_call 
[PR121601]
    
    The following testcase ICEs, because the
          /* Check we aren't dereferencing a null pointer when calling a 
non-static
             member function, which is undefined behaviour.  */
          if (i == 0 && DECL_OBJECT_MEMBER_FUNCTION_P (fun)
              && integer_zerop (arg)
              /* But ignore calls from within compiler-generated code, to handle
                 cases like lambda function pointer conversion operator thunks
                 which pass NULL as the 'this' pointer.  */
              && !(TREE_CODE (t) == CALL_EXPR && CALL_FROM_THUNK_P (t)))
            {
              if (!ctx->quiet)
                error_at (cp_expr_loc_or_input_loc (x),
                          "dereferencing a null pointer");
              *non_constant_p = true;
            }
    checking is done before testing if (*jump_target).  Especially when
    throws (jump_target), arg can be (and is on this testcase) NULL_TREE,
    so calling integer_zerop on it ICEs.
    
    Fixed by moving the if (*jump_target) test earlier.
    
    2025-08-25  Jakub Jelinek  <ja...@redhat.com>
    
            PR c++/121601
            * constexpr.cc (cxx_bind_parameters_in_call): Move break
            if *jump_target before the check for null this object pointer.
    
            * g++.dg/cpp26/constexpr-eh16.C: New test.

Diff:
---
 gcc/cp/constexpr.cc                         |  4 ++--
 gcc/testsuite/g++.dg/cpp26/constexpr-eh16.C | 19 +++++++++++++++++++
 2 files changed, 21 insertions(+), 2 deletions(-)

diff --git a/gcc/cp/constexpr.cc b/gcc/cp/constexpr.cc
index e5438b25478a..701420ca8ec0 100644
--- a/gcc/cp/constexpr.cc
+++ b/gcc/cp/constexpr.cc
@@ -2694,6 +2694,8 @@ cxx_bind_parameters_in_call (const constexpr_ctx *ctx, 
tree t, tree fun,
        arg = cxx_eval_constant_expression (ctx, x, vc_prvalue,
                                            non_constant_p, overflow_p,
                                            jump_target);
+      if (*jump_target)
+       break;
       /* Check we aren't dereferencing a null pointer when calling a non-static
         member function, which is undefined behaviour.  */
       if (i == 0 && DECL_OBJECT_MEMBER_FUNCTION_P (fun)
@@ -2711,8 +2713,6 @@ cxx_bind_parameters_in_call (const constexpr_ctx *ctx, 
tree t, tree fun,
       /* Don't VERIFY_CONSTANT here.  */
       if (*non_constant_p && ctx->quiet)
        break;
-      if (*jump_target)
-       break;
       /* Just discard ellipsis args after checking their constantitude.  */
       if (!parms)
        continue;
diff --git a/gcc/testsuite/g++.dg/cpp26/constexpr-eh16.C 
b/gcc/testsuite/g++.dg/cpp26/constexpr-eh16.C
new file mode 100644
index 000000000000..790a2b70d998
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cpp26/constexpr-eh16.C
@@ -0,0 +1,19 @@
+// PR c++/121601
+// { dg-do compile { target c++11 } }
+// { dg-options "" }
+
+struct A {
+  constexpr const char *data () const noexcept { return "abc"; }
+  constexpr unsigned size () const noexcept { return 3; }
+};
+
+constexpr A
+foo ()
+{
+  return true ? throw 42 : A {}; // { dg-warning "expression 
'<throw-expression>' is not a constant expression" "" { target c++20_down } }
+}                               // { dg-error "expression '<throw-expression>' 
is not a constant expression" "" { target c++23_only } .-1 }
+
+static_assert (false, foo ());  // { dg-warning "'static_assert' with 
non-string message only available with" "" { target c++23_down } }
+// { dg-error "'constexpr A foo\\\(\\\)' called in a constant expression" "" { 
target c++23_down } .-1 }
+// { dg-error "constexpr string 'size\\\(\\\)' must be a constant expression" 
"" { target *-*-* } .-2 }
+// { dg-error "uncaught exception '42'" "" { target c++26 } .-3 }

Reply via email to