aboutsummaryrefslogtreecommitdiff
path: root/gcc/cp/method.cc
diff options
context:
space:
mode:
authorJason Merrill <jason@redhat.com>2022-09-17 12:04:05 +0200
committerJason Merrill <jason@redhat.com>2022-10-07 20:25:51 -0400
commit6ffbf87ca66f4ed9cd79cff675fabe2109e46e85 (patch)
treedc67518a45f51746a76021cdca31b0d4c10677ed /gcc/cp/method.cc
parent9ff6c33e2ec0d75958d3f19089519034e8f96a30 (diff)
downloadgcc-6ffbf87ca66f4ed9cd79cff675fabe2109e46e85.zip
gcc-6ffbf87ca66f4ed9cd79cff675fabe2109e46e85.tar.gz
gcc-6ffbf87ca66f4ed9cd79cff675fabe2109e46e85.tar.bz2
c++: track whether we expect a TARGET_EXPR to be elided
A discussion at Cauldron made me think that with the formalization of copy elision in C++17, we should be able to determine before optimization which TARGET_EXPRs will become temporaries and which are initializers. This patch implements that: we set TARGET_EXPR_ELIDING_P if it's used as an initializer, and later check that we were right. There's an exception in the cp_gimplify_expr check to allow extra temporaries of non-addressable type: this is used by gimplify_init_ctor_preeval to materialize subobjects of a CONSTRUCTOR on the rhs of a MODIFY_EXPR rather than materializing the whole object. If the type isn't addressable, there's no way for a program to tell the difference, so this is a valid optimization. I considered changing replace_placeholders_for_class_temp_r to check TARGET_EXPR_ELIDING_P instead of potential_prvalue_result_of, but decided that would be wrong: if we have an eliding TARGET_EXPR inside a non-eliding one, we would miss replacing its placeholders. gcc/cp/ChangeLog: * cp-tree.h (TARGET_EXPR_ELIDING_P): New. (unsafe_copy_elision_p, set_target_expr_eliding) (cp_build_init_expr): Declare. * call.cc (unsafe_copy_elision_p): No longer static. (build_over_call, build_special_member_call) (build_new_method_call): Use cp_build_init_expr. * coroutines.cc (expand_one_await_expression) (build_actor_fn, flatten_await_stmt, handle_nested_conditionals) (await_statement_walker, morph_fn_to_coro): Use cp_build_init_expr. * cp-gimplify.cc (cp_gimplify_init_expr) (cp_gimplify_expr): Check TARGET_EXPR_ELIDING_P. (cp_fold_r): Propagate it. (cp_fold): Use cp_build_init_expr. * decl.cc (check_initializer): Use cp_build_init_expr. * except.cc (build_throw): Use cp_build_init_expr. * init.cc (get_nsdmi): Call set_target_expr_eliding. (perform_member_init, expand_default_init, expand_aggr_init_1) (build_new_1, build_vec_init): Use cp_build_init_expr. * method.cc (do_build_copy_constructor): Use cp_build_init_expr. * semantics.cc (simplify_aggr_init_expr, finalize_nrv_r) (finish_omp_reduction_clause): Use cp_build_init_expr. * tree.cc (build_target_expr): Call set_target_expr_eliding. (bot_manip): Copy TARGET_EXPR_ELIDING_P. * typeck.cc (cp_build_modify_expr): Call set_target_expr_eliding. (check_return_expr): Use cp_build_modify_expr. * typeck2.cc (split_nonconstant_init_1) (split_nonconstant_init): Use cp_build_init_expr. (massage_init_elt): Call set_target_expr_eliding. (process_init_constructor_record): Clear TARGET_EXPR_ELIDING_P on unsafe copy elision. (set_target_expr_eliding, cp_build_init_expr): New.
Diffstat (limited to 'gcc/cp/method.cc')
-rw-r--r--gcc/cp/method.cc4
1 files changed, 2 insertions, 2 deletions
diff --git a/gcc/cp/method.cc b/gcc/cp/method.cc
index 622e1b9..c217d7e 100644
--- a/gcc/cp/method.cc
+++ b/gcc/cp/method.cc
@@ -680,7 +680,7 @@ do_build_copy_constructor (tree fndecl)
else if (tree_int_cst_equal (TYPE_SIZE (current_class_type),
CLASSTYPE_SIZE (current_class_type)))
{
- tree t = build2 (INIT_EXPR, void_type_node, current_class_ref, parm);
+ tree t = cp_build_init_expr (current_class_ref, parm);
finish_expr_stmt (t);
}
else
@@ -695,7 +695,7 @@ do_build_copy_constructor (tree fndecl)
current_class_ptr, alias_set);
tree rhs = build2 (MEM_REF, array_type,
TREE_OPERAND (parm, 0), alias_set);
- tree t = build2 (INIT_EXPR, void_type_node, lhs, rhs);
+ tree t = cp_build_init_expr (lhs, rhs);
finish_expr_stmt (t);
}
}