aboutsummaryrefslogtreecommitdiff
path: root/gcc/cp/cvt.c
diff options
context:
space:
mode:
authorJason Merrill <jason@redhat.com>2016-10-06 17:24:40 -0400
committerJason Merrill <jason@gcc.gnu.org>2016-10-06 17:24:40 -0400
commitb7558a2c1f87e374c48fa2be8e3ab93e1b3c68b0 (patch)
treec9167e38db4b5297835f67da69fdb6b691450d9f /gcc/cp/cvt.c
parent937ec71aba5b3c633bd5979d6346254e83f46d1c (diff)
downloadgcc-b7558a2c1f87e374c48fa2be8e3ab93e1b3c68b0.zip
gcc-b7558a2c1f87e374c48fa2be8e3ab93e1b3c68b0.tar.gz
gcc-b7558a2c1f87e374c48fa2be8e3ab93e1b3c68b0.tar.bz2
C++17 copy elision improvements.
* call.c (build_temp, convert_like_real): Don't re-copy TARGET_EXPR. Handle packed fields. (build_x_va_arg): Wrap it in a TARGET_EXPR. (build_over_call): Add sanity check. * cvt.c (early_elide_copy): New. (ocp_convert): Use it. * except.c (build_throw): Use it. * init.c (get_nsdmi): Put back the TARGET_EXPR. (expand_default_init): Call early_elide_copy. * typeck.c (cp_build_modify_expr): Call early_elide_copy. From-SVN: r240845
Diffstat (limited to 'gcc/cp/cvt.c')
-rw-r--r--gcc/cp/cvt.c27
1 files changed, 23 insertions, 4 deletions
diff --git a/gcc/cp/cvt.c b/gcc/cp/cvt.c
index ecc8ef8..063457f 100644
--- a/gcc/cp/cvt.c
+++ b/gcc/cp/cvt.c
@@ -658,6 +658,27 @@ cp_convert_and_check (tree type, tree expr, tsubst_flags_t complain)
return result;
}
+/* Returns true if we should avoid even doing overload resolution for copying
+ EXPR to initialize a TYPE. */
+
+bool
+early_elide_copy (tree type, tree expr)
+{
+ if (TREE_CODE (expr) != TARGET_EXPR)
+ return false;
+ /* List-initialization and direct-initialization don't involve a copy. */
+ if (TARGET_EXPR_LIST_INIT_P (expr)
+ || TARGET_EXPR_DIRECT_INIT_P (expr))
+ return true;
+ /* In C++17, "If the initializer expression is a prvalue and the
+ cv-unqualified version of the source type is the same class as the class
+ of the destination, the initializer expression is used to initialize the
+ destination object." */
+ return (cxx_dialect >= cxx1z
+ && (same_type_ignoring_top_level_qualifiers_p
+ (type, TREE_TYPE (expr))));
+}
+
/* Conversion...
FLAGS indicates how we should behave. */
@@ -694,10 +715,8 @@ ocp_convert (tree type, tree expr, int convtype, int flags,
return error_mark_node;
if (MAYBE_CLASS_TYPE_P (type) && (convtype & CONV_FORCE_TEMP)
- && !(cxx_dialect >= cxx1z
- && TREE_CODE (e) == TARGET_EXPR))
- /* We need a new temporary; don't take this shortcut. But in C++17, don't
- force a temporary if we already have one. */;
+ && !early_elide_copy (type, e))
+ /* We need a new temporary; don't take this shortcut. */;
else if (same_type_ignoring_top_level_qualifiers_p (type, TREE_TYPE (e)))
{
if (same_type_p (type, TREE_TYPE (e)))