c++: ICE with operator new[] in constexpr [PR118775]

Here we ICE since r11-7740 because we no longer say that (long)&a
(where a is a global var) is non_constant_p.  So VERIFY_CONSTANT
does not return and we crash on tree_to_uhwi.  We should check
tree_fits_uhwi_p before calling tree_to_uhwi.

	PR c++/118775

gcc/cp/ChangeLog:

	* constexpr.cc (cxx_eval_call_expression): Check tree_fits_uhwi_p.

gcc/testsuite/ChangeLog:

	* g++.dg/cpp2a/constexpr-new24.C: New test.
	* g++.dg/cpp2a/constexpr-new25.C: New test.

Reviewed-by: Jason Merrill <jason@redhat.com>
This commit is contained in:
Marek Polacek 2025-02-11 15:43:40 -05:00
parent c781da2c10
commit aa55a6a30b
3 changed files with 63 additions and 0 deletions

View file

@ -2928,6 +2928,17 @@ cxx_eval_call_expression (const constexpr_ctx *ctx, tree t,
gcc_assert (arg0);
if (new_op_p)
{
/* FIXME: We should not get here; the VERIFY_CONSTANT above
should have already caught it. But currently a conversion
from pointer type to arithmetic type is only considered
non-constant for CONVERT_EXPRs, not NOP_EXPRs. */
if (!tree_fits_uhwi_p (arg0))
{
if (!ctx->quiet)
error_at (loc, "cannot allocate array: size not constant");
*non_constant_p = true;
return t;
}
tree type = build_array_type_nelts (char_type_node,
tree_to_uhwi (arg0));
tree var = build_decl (loc, VAR_DECL,

View file

@ -0,0 +1,25 @@
// PR c++/118775
// { dg-do compile { target c++20 } }
int a;
constexpr char *
f1 ()
{
constexpr auto p = new char[(long int) &a]; // { dg-error "size not constant" }
return p;
}
constexpr char *
f2 ()
{
auto p = new char[(long int) &a]; // { dg-error "size not constant" }
return p;
}
void
g ()
{
auto r1 = f2 ();
constexpr auto r2 = f2 (); // { dg-message "in .constexpr. expansion" }
}

View file

@ -0,0 +1,27 @@
// PR c++/118775
// { dg-do compile { target c++20 } }
namespace std {
struct __uniq_ptr_impl {
constexpr __uniq_ptr_impl(char *) {}
};
template <typename> struct unique_ptr {
__uniq_ptr_impl _M_t;
constexpr ~unique_ptr() {}
};
template <typename> struct _MakeUniq;
template <typename _Tp> struct _MakeUniq<_Tp[]> {
typedef unique_ptr<_Tp[]> __array;
};
template <typename _Tp> using __unique_ptr_array_t = _MakeUniq<_Tp>::__array;
constexpr __unique_ptr_array_t<char[]> make_unique(long __num) {
return unique_ptr<char[]>(new char[__num]);
}
} // namespace std
int a;
int
main ()
{
std::unique_ptr p = std::make_unique((long)&a);
constexpr std::unique_ptr p2 = std::make_unique((long)&a); // { dg-error "conversion" }
}