aboutsummaryrefslogtreecommitdiff
path: root/gcc/cp
diff options
context:
space:
mode:
authorNathaniel Shead <nathanieloshead@gmail.com>2023-10-28 16:04:52 +1100
committerNathaniel Shead <nathanieloshead@gmail.com>2023-12-11 13:33:52 +1100
commit4719b6f5ae4d758f193a17bbd5fb6cbacd702a23 (patch)
tree8a49b8ba5c0727564bcb0743b825ce1c91cb10ba /gcc/cp
parentab3daffcbf35566d468c3028e48068a481048baf (diff)
downloadgcc-4719b6f5ae4d758f193a17bbd5fb6cbacd702a23.zip
gcc-4719b6f5ae4d758f193a17bbd5fb6cbacd702a23.tar.gz
gcc-4719b6f5ae4d758f193a17bbd5fb6cbacd702a23.tar.bz2
c++: Fix noexcept checking for trivial operations [PR96090]
This patch stops eager folding of trivial operations (construction and assignment) from occurring when checking for noexceptness. This was previously done in PR c++/53025, but only for copy/move construction, and the __is_nothrow_xible builtins did not receive the same treatment when they were added. To handle `is_nothrow_default_constructible`, the patch also ensures that when no parameters are passed we do value initialisation instead of just building the constructor call: in particular, value-initialisation doesn't necessarily actually invoke the constructor for trivial default constructors, and so we need to handle this case as well. This is contrary to the proposed resolution of CWG2820; for now we just ensure it matches the behaviour of the `noexcept` operator and create testcases formalising this, and if that issue gets accepted we can revisit. PR c++/96090 PR c++/100470 gcc/cp/ChangeLog: * call.cc (build_over_call): Prevent folding of trivial special members when checking for noexcept. * method.cc (constructible_expr): Perform value-initialisation for empty parameter lists. (is_nothrow_xible): Treat as noexcept operator. gcc/testsuite/ChangeLog: * g++.dg/cpp0x/noexcept81.C: New test. * g++.dg/ext/is_nothrow_constructible7.C: New test. * g++.dg/ext/is_nothrow_constructible8.C: New test. Signed-off-by: Nathaniel Shead <nathanieloshead@gmail.com>
Diffstat (limited to 'gcc/cp')
-rw-r--r--gcc/cp/call.cc17
-rw-r--r--gcc/cp/method.cc19
2 files changed, 22 insertions, 14 deletions
diff --git a/gcc/cp/call.cc b/gcc/cp/call.cc
index c7efc5b..4f0abf8 100644
--- a/gcc/cp/call.cc
+++ b/gcc/cp/call.cc
@@ -10247,15 +10247,16 @@ build_over_call (struct z_candidate *cand, int flags, tsubst_flags_t complain)
/* Avoid actually calling copy constructors and copy assignment operators,
if possible. */
- if (! flag_elide_constructors && !force_elide)
+ if (!force_elide
+ && (!flag_elide_constructors
+ /* It's unsafe to elide the operation when handling
+ a noexcept-expression, it may evaluate to the wrong
+ value (c++/53025, c++/96090). */
+ || cp_noexcept_operand != 0))
/* Do things the hard way. */;
- else if (cand->num_convs == 1
- && (DECL_COPY_CONSTRUCTOR_P (fn)
- || DECL_MOVE_CONSTRUCTOR_P (fn))
- /* It's unsafe to elide the constructor when handling
- a noexcept-expression, it may evaluate to the wrong
- value (c++/53025). */
- && (force_elide || cp_noexcept_operand == 0))
+ else if (cand->num_convs == 1
+ && (DECL_COPY_CONSTRUCTOR_P (fn)
+ || DECL_MOVE_CONSTRUCTOR_P (fn)))
{
tree targ;
tree arg = argarray[num_artificial_parms_for (fn)];
diff --git a/gcc/cp/method.cc b/gcc/cp/method.cc
index a70dd5d..26e6eb7 100644
--- a/gcc/cp/method.cc
+++ b/gcc/cp/method.cc
@@ -2091,6 +2091,7 @@ constructible_expr (tree to, tree from)
{
tree expr;
cp_unevaluated cp_uneval_guard;
+ const int len = TREE_VEC_LENGTH (from);
if (CLASS_TYPE_P (to))
{
tree ctype = to;
@@ -2098,11 +2099,16 @@ constructible_expr (tree to, tree from)
if (!TYPE_REF_P (to))
to = cp_build_reference_type (to, /*rval*/false);
tree ob = build_stub_object (to);
- vec_alloc (args, TREE_VEC_LENGTH (from));
- for (tree arg : tree_vec_range (from))
- args->quick_push (build_stub_object (arg));
- expr = build_special_member_call (ob, complete_ctor_identifier, &args,
- ctype, LOOKUP_NORMAL, tf_none);
+ if (len == 0)
+ expr = build_value_init (ctype, tf_none);
+ else
+ {
+ vec_alloc (args, len);
+ for (tree arg : tree_vec_range (from))
+ args->quick_push (build_stub_object (arg));
+ expr = build_special_member_call (ob, complete_ctor_identifier, &args,
+ ctype, LOOKUP_NORMAL, tf_none);
+ }
if (expr == error_mark_node)
return error_mark_node;
/* The current state of the standard vis-a-vis LWG 2116 is that
@@ -2120,7 +2126,6 @@ constructible_expr (tree to, tree from)
}
else
{
- const int len = TREE_VEC_LENGTH (from);
if (len == 0)
return build_value_init (strip_array_types (to), tf_none);
if (len > 1)
@@ -2216,7 +2221,9 @@ is_trivially_xible (enum tree_code code, tree to, tree from)
bool
is_nothrow_xible (enum tree_code code, tree to, tree from)
{
+ ++cp_noexcept_operand;
tree expr = is_xible_helper (code, to, from, /*trivial*/false);
+ --cp_noexcept_operand;
if (expr == NULL_TREE || expr == error_mark_node)
return false;
return expr_noexcept_p (expr, tf_none);