PR c++/83160] local ref to capture
authorNathan Sidwell <nathan@acm.org>
Thu, 18 Jan 2018 11:53:50 +0000 (11:53 +0000)
committerNathan Sidwell <nathan@gcc.gnu.org>
Thu, 18 Jan 2018 11:53:50 +0000 (11:53 +0000)
https://gcc.gnu.org/ml/gcc-patches/2018-01/msg01638.html
PR c++/83160
* cp-tree.h (mark_use): Declare.
* expr.c (mark_use): Make extern.
* call.c (direct_reference_binding): Set inner conv's
rvaluedness_matches_p, if it is an identity.
(convert_like_real): Mark lvalue or rvalue use for identity as
rvaledness_matches_p demands.

PR c++/83160
* g++.dg/cpp0x/pr83160.C: New.

From-SVN: r256842

gcc/cp/ChangeLog
gcc/cp/call.c
gcc/cp/cp-tree.h
gcc/cp/expr.c
gcc/testsuite/ChangeLog
gcc/testsuite/g++.dg/cpp0x/pr83160.C [new file with mode: 0644]

index 998e0b9925eb4efb197b6dba4a24b81df713a0bf..0cacefa674d158b8933b6caa0686a2eedc10d509 100644 (file)
@@ -1,3 +1,13 @@
+2018-01-18  Nathan Sidwell  <nathan@acm.org>
+
+       PR c++/83160
+       * cp-tree.h (mark_use): Declare.
+       * expr.c (mark_use): Make extern.
+       * call.c (direct_reference_binding): Set inner conv's
+       rvaluedness_matches_p, if it is an identity.
+       (convert_like_real): Mark lvalue or rvalue use for identity as
+       rvaledness_matches_p demands.
+
 2018-01-18  Jakub Jelinek  <jakub@redhat.com>
 
        PR c++/83824
index 1f326d5c1ad431e7d5245bca0dd07751d34e4cb4..e08622ce9c20f358961b1efce319dd54982cd9f7 100644 (file)
@@ -102,7 +102,8 @@ struct conversion {
      being bound to an lvalue expression or an rvalue reference is
      being bound to an rvalue expression.  If KIND is ck_rvalue,
      true when we are treating an lvalue as an rvalue (12.8p33).  If
-     KIND is ck_base, always false.  */
+     KIND is ck_base, always false.  If ck_identity, we will be
+     binding a reference directly.  */
   BOOL_BITFIELD rvaluedness_matches_p: 1;
   BOOL_BITFIELD check_narrowing: 1;
   /* The type of the expression resulting from the conversion.  */
@@ -1476,6 +1477,10 @@ direct_reference_binding (tree type, conversion *conv)
 
   t = TREE_TYPE (type);
 
+  if (conv->kind == ck_identity)
+    /* Mark the identity conv as to not decay to rvalue.  */
+    conv->rvaluedness_matches_p = true;
+
   /* [over.ics.rank]
 
      When a parameter of reference type binds directly
@@ -1501,6 +1506,7 @@ direct_reference_binding (tree type, conversion *conv)
         That way, convert_like knows not to generate a temporary.  */
       conv->need_temporary_p = false;
     }
+
   return build_conv (ck_ref_bind, type, conv);
 }
 
@@ -6800,7 +6806,9 @@ convert_like_real (conversion *convs, tree expr, tree fn, int argnum,
          else
            gcc_unreachable ();
        }
-      expr = mark_rvalue_use (expr);
+      expr = mark_use (expr, /*rvalue_p=*/!convs->rvaluedness_matches_p,
+                      /*read_p=*/true, UNKNOWN_LOCATION,
+                      /*reject_builtin=*/true);
 
       if (type_unknown_p (expr))
        expr = instantiate_type (totype, expr, complain);
index 4300d9217a8a7e7614b0491b249a6827c9bdc6c4..a8a5ab18342c43bd5ac94a274ef127657969a286 100644 (file)
@@ -6328,6 +6328,9 @@ extern tree create_try_catch_expr               (tree, tree);
 
 /* in expr.c */
 extern tree cplus_expand_constant              (tree);
+extern tree mark_use (tree expr, bool rvalue_p, bool read_p,
+                     location_t = UNKNOWN_LOCATION,
+                     bool reject_builtin = true);
 extern tree mark_rvalue_use                    (tree,
                                                  location_t = UNKNOWN_LOCATION,
                                                  bool reject_builtin = true);
index 49a17a62424ec2422c3f6c7edf4dc3cc10954be8..2e67986897061d27bbd4b368af888025d76988d6 100644 (file)
@@ -89,7 +89,7 @@ cplus_expand_constant (tree cst)
 /* We've seen an actual use of EXPR.  Possibly replace an outer variable
    reference inside with its constant value or a lambda capture.  */
 
-static tree
+tree
 mark_use (tree expr, bool rvalue_p, bool read_p,
          location_t loc /* = UNKNOWN_LOCATION */,
          bool reject_builtin /* = true */)
index 3cc5bda045461235d46500c1e0f863d773fcdfd9..df64bb05b76ea87c0f9a69f6d4806abc3b18f532 100644 (file)
@@ -1,3 +1,8 @@
+2018-01-18  Nathan Sidwell  <nathan@acm.org>
+
+       PR c++/83160
+       * g++.dg/cpp0x/pr83160.C: New.
+
 2018-01-18  Richard Biener  <rguenther@suse.de>
 
        PR tree-optimization/83887
diff --git a/gcc/testsuite/g++.dg/cpp0x/pr83160.C b/gcc/testsuite/g++.dg/cpp0x/pr83160.C
new file mode 100644 (file)
index 0000000..b3b97c7
--- /dev/null
@@ -0,0 +1,33 @@
+// { dg-do run { target c++11 } }
+// PR c++/83160 failed to capture as lvalue
+
+int main ()
+{
+  const int a = 0;
+
+  if (![&a] (const int *p)
+      {
+       const int &b = a;
+       // We should bind to the outer a
+       return &b == p;
+      } (&a))
+    return 1;
+
+  if (![&] (const int *p)
+      {
+       const int &b = a;
+       // We should bind to the outer a
+       return &b == p;
+      } (&a))
+    return 2;
+
+  if ([=] (const int *p)
+      {
+       const int &b = a;
+       // We should bind to the captured instance
+       return &b == p;
+      }(&a))
+    return 3;
+
+  return 0;
+}