diff mbox

C++ PATCH for P0135, C++17 guaranteed copy elision

Message ID CADzB+2nUgkOKbdMM_XXL4e53HQ712TLmRszvwEJQmm591UobaQ@mail.gmail.com
State New
Headers show

Commit Message

Jason Merrill Oct. 5, 2016, 10:57 p.m. UTC
C++17 changes how we describe prvalues so that they express
initialization of an object to be named later, rather than objects
themselves.  This happens to match the front end's use of TARGET_EXPR
pretty closely, so I think we don't need to do much more than disable
the code that forces us to copy a TARGET_EXPR into another
TARGET_EXPR.

Tested x86_64-pc-linux-gnu, applying to trunk.
commit 054719b1c1f71236999ea4082cb3207c42cf883c
Author: Jason Merrill <jason@redhat.com>
Date:   Wed Oct 5 12:59:30 2016 -0400

            Implement P0135R1, Guaranteed copy elision.
    
            * c-opts.c (set_std_cxx1z): Set flag_elide_constructors to 2.
            * cvt.c (ocp_convert): Don't re-copy a TARGET_EXPR in C++17.

Comments

Pedro Alves Oct. 5, 2016, 11:15 p.m. UTC | #1
On 10/05/2016 11:57 PM, Jason Merrill wrote:
> --- a/gcc/c-family/c-opts.c
> +++ b/gcc/c-family/c-opts.c
> @@ -1579,6 +1579,7 @@ set_std_cxx1z (int iso)
>    flag_isoc94 = 1;
>    flag_isoc99 = 1;
>    flag_isoc11 = 1;
> +  flag_elide_constructors = 2;
>    cxx_dialect = cxx1z;
>    lang_hooks.name = "GNU C++14"; /* Pretend C++14 till standarization.  */

Does -fno-elide-constructors have any effect in C++17 mode?
Should it perhaps be an error, or ignored?

Thanks,
Pedro Alves
diff mbox

Patch

diff --git a/gcc/c-family/c-opts.c b/gcc/c-family/c-opts.c
index c5a699d..977348f1 100644
--- a/gcc/c-family/c-opts.c
+++ b/gcc/c-family/c-opts.c
@@ -1579,6 +1579,7 @@  set_std_cxx1z (int iso)
   flag_isoc94 = 1;
   flag_isoc99 = 1;
   flag_isoc11 = 1;
+  flag_elide_constructors = 2;
   cxx_dialect = cxx1z;
   lang_hooks.name = "GNU C++14"; /* Pretend C++14 till standarization.  */
 }
diff --git a/gcc/cp/cvt.c b/gcc/cp/cvt.c
index 2f5f15a..4de9745 100644
--- a/gcc/cp/cvt.c
+++ b/gcc/cp/cvt.c
@@ -693,8 +693,11 @@  ocp_convert (tree type, tree expr, int convtype, int flags,
   if (error_operand_p (e))
     return error_mark_node;
 
-  if (MAYBE_CLASS_TYPE_P (type) && (convtype & CONV_FORCE_TEMP))
-    /* We need a new temporary; don't take this shortcut.  */;
+  if (MAYBE_CLASS_TYPE_P (type) && (convtype & CONV_FORCE_TEMP)
+      && !(flag_elide_constructors >= 2
+	   && 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.  */;
   else if (same_type_ignoring_top_level_qualifiers_p (type, TREE_TYPE (e)))
     {
       if (same_type_p (type, TREE_TYPE (e)))
diff --git a/gcc/testsuite/g++.dg/cpp1z/elide1.C b/gcc/testsuite/g++.dg/cpp1z/elide1.C
new file mode 100644
index 0000000..a0538bb
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cpp1z/elide1.C
@@ -0,0 +1,16 @@ 
+// { dg-options -std=c++1z }
+
+struct A
+{
+  A();
+  A(const A&) = delete;
+};
+
+bool b;
+A a = A();
+A a1 = b ? A() : A();
+A a2 = (42, A());
+
+A f();
+A a3 = f();
+A a4 = b ? A() : f();