On Tue, Jun 03, 2025 at 11:02:30AM -0400, Jason Merrill wrote: > > On the potential_constant_expression_1 side, important change was to > > set *jump_target conservatively on calls that could throw for C++26 (the > > patch uses magic void_node for potential_constant_expression* instead of > > VAR_DECL, so that we don't have to create new VAR_DECLs there uselessly). > > Without that change, several methods in libstdc++ wouldn't work correctly. > > I'm not sure what exactly potential_constant_expression_1 maps to in the > > C++26 standard wording now and whether doing that is ok, because basically > > after the first call to non-noexcept function it stops checking stuff. > > I would expect that we could do better since for constexpr we need to be > able to see the definitions of all the functions and know whether or not > they can actually throw.
You mean also check TREE_NOTHROW (fndecl) which we currently propagate conservatively (if we can prove something never throws, we set it) or something else? If TREE_NOTHROW, that would be twice + tree callee_fn = cp_get_fndecl_from_callee (callee, false); if (!flag_enforce_eh_specs || type_dependent_expression_p (callee) || !POINTER_TYPE_P (TREE_TYPE (callee)) - || !type_noexcept_p (TREE_TYPE (TREE_TYPE (callee)))) + || (!type_noexcept_p (TREE_TYPE (TREE_TYPE (callee))) + && (callee_fn == NULL_TREE + || !TREE_NOTHROW (callee_fn)))) *jump_target = void_node; or so. > But that's not necessary if it's difficult; at this point > potential_constant_expression is just a conservative early filter to avoid > later trying to evaluate thigs that can't possibly succeed. > > > And, in some spots where I know potential_constant_expression_1 didn't > > check some subexpressions (e.g. the EH only cleanups or TRY_BLOCK handlers) > > I've added *potential_constant_expression* calls during cxx_eval_constant*, > > not sure if I need to do that because potential_constant_expression_1 is > > very conservative and just doesn't recurse on subexpressions in many cases. > > I think that shouldn't be necessary. Ok, I can remove those then. It is + /* potential_constant_expression_1 doesn't recurse into + TRY_BLOCK handlers, so call it now. */ + if (!ctx->quiet + ? !require_potential_constant_expression (HANDLER_BODY (h)) + : !potential_constant_expression (HANDLER_BODY (h))) + *non_constant_p = true; + else hunk and + if (CLEANUP_EH_ONLY (t) + && (!ctx->quiet + ? !require_potential_constant_expression (CLEANUP_EXPR (t)) + : !potential_constant_expression (CLEANUP_EXPR (t)))) + *non_constant_p = true; + else hunk (plus reindent the else parts of those). Jakub