This is the mail archive of the gcc-patches@gcc.gnu.org mailing list for the GCC project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

Re: [PR c++/83160] local ref to capture


On 01/17/2018 01:44 PM, Jason Merrill wrote:

This makes sense to me.  But I think we'd want also that flag set on
the ck_identity inside the ck_base that direct_reference_binding
creates, so setting it first rather than in an else.

Ah yes, you spotted the bit I failed to mention. (I think we get away with it because class objects always have sufficient lvalueness, but why lie?)

nathan

--
Nathan Sidwell
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.

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

Index: cp/call.c
===================================================================
--- cp/call.c	(revision 256841)
+++ cp/call.c	(working copy)
@@ -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, con
 
   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, con
 	 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, tr
 	  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: cp/cp-tree.h
===================================================================
--- cp/cp-tree.h	(revision 256841)
+++ cp/cp-tree.h	(working copy)
@@ -6328,6 +6328,9 @@ extern tree create_try_catch_expr
 
 /* 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: cp/expr.c
===================================================================
--- cp/expr.c	(revision 256841)
+++ cp/expr.c	(working copy)
@@ -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: testsuite/g++.dg/cpp0x/pr83160.C
===================================================================
--- testsuite/g++.dg/cpp0x/pr83160.C	(revision 0)
+++ testsuite/g++.dg/cpp0x/pr83160.C	(working copy)
@@ -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;
+}

Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]