diff mbox

C++ PATCH for c++/57437 (wrong code with mutable lambda)

Message ID 51DC4BDF.9070706@redhat.com
State New
Headers show

Commit Message

Jason Merrill July 9, 2013, 5:43 p.m. UTC
Here, we were wrongly treating a lambda capture proxy as a local 
variable for the purpose of C++11 return by move.  Fixed by preventing 
it for proxy variables of all kinds.

Tested x86_64-pc-linux-gnu, applying to trunk, 4.8, 4.7.
diff mbox

Patch

commit a7dc31796b5a7aab2818fa9cb7e0f345ecc8fdf0
Author: Jason Merrill <jason@redhat.com>
Date:   Tue Jul 9 02:51:34 2013 -0400

    	PR c++/57437
    	* typeck.c (check_return_expr): Lambda proxies aren't eligible
    	for nrv or return by move.

diff --git a/gcc/cp/typeck.c b/gcc/cp/typeck.c
index 462abdd..6f7d489 100644
--- a/gcc/cp/typeck.c
+++ b/gcc/cp/typeck.c
@@ -8399,7 +8399,8 @@  check_return_expr (tree retval, bool *no_warning)
      && VAR_P (retval)
      && DECL_CONTEXT (retval) == current_function_decl
      && ! TREE_STATIC (retval)
-     && ! DECL_ANON_UNION_VAR_P (retval)
+     /* And not a lambda or anonymous union proxy.  */
+     && !DECL_HAS_VALUE_EXPR_P (retval)
      && (DECL_ALIGN (retval) <= DECL_ALIGN (result))
      /* The cv-unqualified type of the returned value must be the
         same as the cv-unqualified return type of the
@@ -8444,7 +8445,7 @@  check_return_expr (tree retval, bool *no_warning)
          Note that these conditions are similar to, but not as strict as,
 	 the conditions for the named return value optimization.  */
       if ((cxx_dialect != cxx98)
-          && (VAR_P (retval)
+          && ((VAR_P (retval) && !DECL_HAS_VALUE_EXPR_P (retval))
 	      || TREE_CODE (retval) == PARM_DECL)
 	  && DECL_CONTEXT (retval) == current_function_decl
 	  && !TREE_STATIC (retval)
diff --git a/gcc/testsuite/g++.dg/cpp0x/lambda/lambda-return1.C b/gcc/testsuite/g++.dg/cpp0x/lambda/lambda-return1.C
new file mode 100644
index 0000000..4b353b6
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cpp0x/lambda/lambda-return1.C
@@ -0,0 +1,26 @@ 
+// PR c++/57437
+// { dg-require-effective-target c++11 }
+
+struct A {
+  int i;
+
+  A(): i(42) {}
+  A(const A&) = default;
+  A(A&& a): i(a.i) { a.i = 0; }
+};
+
+int main()
+{
+  A x;
+
+  auto y = [x] () mutable {
+    x.i++;
+    return x;
+  };
+
+  if (y().i != 43)
+    __builtin_abort ();
+
+  if (y().i != 44)
+    __builtin_abort ();
+}