arg = adjust_temp_type (type, arg);
if (!TREE_CONSTANT (arg))
*non_constant_args = true;
+ else if (TYPE_HAS_NONTRIVIAL_DESTRUCTOR (type))
+ /* The destructor needs to see any modifications the callee makes
+ to the argument. */
+ *non_constant_args = true;
+
/* For virtual calls, adjust the this argument, so that it is
the object on which the method is called, rather than
one of its bases. */
problems with verify_gimple. */
arg = unshare_expr_without_location (arg);
TREE_VEC_ELT (bound, i) = arg;
+
+ /* And then unshare again so the callee doesn't change the
+ argument values in the hash table. XXX Could we unshare
+ lazily in cxx_eval_store_expression? */
+ arg = unshare_constructor (arg);
+ if (TREE_CODE (arg) == CONSTRUCTOR)
+ vec_safe_push (ctors, arg);
}
- /* Don't share a CONSTRUCTOR that might be changed. This is not
- redundant with the unshare just above; we also don't want to
- change the argument values in the hash table. XXX Could we
- unshare lazily in cxx_eval_store_expression? */
- arg = unshare_constructor (arg);
- if (TREE_CODE (arg) == CONSTRUCTOR)
- vec_safe_push (ctors, arg);
ctx->global->values.put (remapped, arg);
remapped = DECL_CHAIN (remapped);
}
--- /dev/null
+// PR c++/97388
+// { dg-do compile { target c++20 } }
+
+struct S {
+ int m;
+ constexpr S () : m(1) {}
+ constexpr ~S () noexcept (false) { if (m == 1) { throw; } }
+};
+
+constexpr bool
+foo (S v)
+{
+ v.m = 2;
+ return true;
+}
+
+constexpr bool
+bar ()
+{
+ return foo (S ());
+}
+
+constexpr bool
+baz ()
+{
+ foo (S ());
+ return foo (S ());
+}
+
+static_assert (foo (S ()));
+static_assert (bar ());
+static_assert (baz ());
+constexpr bool x = foo (S ());
+constexpr bool y = bar ();
+constexpr bool z = baz ();
--- /dev/null
+// PR c++/97388
+// { dg-do compile { target c++20 } }
+
+struct S {
+ int *s;
+ constexpr S () : s(new int ()) {}
+ constexpr S (S &&x) noexcept : s(x.s) { x.s = nullptr; }
+ constexpr ~S () noexcept { delete s; }
+};
+
+constexpr bool
+foo (S v)
+{
+ auto x = static_cast<S &&> (v);
+ return true;
+}
+
+constexpr bool
+bar ()
+{
+ return foo (S ());
+}
+
+constexpr bool
+baz ()
+{
+ foo (S ());
+ return foo (S ());
+}
+
+static_assert (foo (S ()));
+static_assert (bar ());
+static_assert (baz ());
+constexpr bool x = foo (S ());
+constexpr bool y = bar ();
+constexpr bool z = baz ();
--- /dev/null
+// PR c++/97388
+// { dg-do compile { target c++20 } }
+
+struct S {
+ int *s;
+ constexpr S () : s(new int) {} // { dg-error "is not a constant expression because allocated storage has not been deallocated" }
+ S (const S &) = delete;
+ S &operator= (const S &) = delete;
+ constexpr ~S () { delete s; }
+};
+
+constexpr bool
+foo (S v)
+{
+ v.s = nullptr;
+ return true;
+}
+
+static_assert (foo (S ())); // { dg-error "non-constant condition for static assertion" }