On 8/25/25 2:48 AM, Jakub Jelinek wrote:
Hi!
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.
Bootstrapped/regtested on x86_64-linux and i686-linux, ok for trunk?
OK.
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.
--- gcc/cp/constexpr.cc.jj 2025-08-23 15:00:04.185789011 +0200
+++ gcc/cp/constexpr.cc 2025-08-23 15:06:40.170528383 +0200
@@ -2694,6 +2694,8 @@ cxx_bind_parameters_in_call (const const
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 const
/* 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;
--- gcc/testsuite/g++.dg/cpp26/constexpr-eh16.C.jj 2025-08-23
15:14:50.589013243 +0200
+++ gcc/testsuite/g++.dg/cpp26/constexpr-eh16.C 2025-08-23 15:19:29.653305666
+0200
@@ -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 }
Jakub