Commit 5a752e3f by Nathan Sidwell Committed by Nathan Sidwell

PR c++/83160] local ref to capture

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
parent 7467ab42
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> 2018-01-18 Jakub Jelinek <jakub@redhat.com>
PR c++/83824 PR c++/83824
......
...@@ -102,7 +102,8 @@ struct conversion { ...@@ -102,7 +102,8 @@ struct conversion {
being bound to an lvalue expression or an rvalue reference is being bound to an lvalue expression or an rvalue reference is
being bound to an rvalue expression. If KIND is ck_rvalue, being bound to an rvalue expression. If KIND is ck_rvalue,
true when we are treating an lvalue as an rvalue (12.8p33). If 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 rvaluedness_matches_p: 1;
BOOL_BITFIELD check_narrowing: 1; BOOL_BITFIELD check_narrowing: 1;
/* The type of the expression resulting from the conversion. */ /* The type of the expression resulting from the conversion. */
...@@ -1476,6 +1477,10 @@ direct_reference_binding (tree type, conversion *conv) ...@@ -1476,6 +1477,10 @@ direct_reference_binding (tree type, conversion *conv)
t = TREE_TYPE (type); 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] /* [over.ics.rank]
When a parameter of reference type binds directly When a parameter of reference type binds directly
...@@ -1501,6 +1506,7 @@ direct_reference_binding (tree type, conversion *conv) ...@@ -1501,6 +1506,7 @@ direct_reference_binding (tree type, conversion *conv)
That way, convert_like knows not to generate a temporary. */ That way, convert_like knows not to generate a temporary. */
conv->need_temporary_p = false; conv->need_temporary_p = false;
} }
return build_conv (ck_ref_bind, type, conv); return build_conv (ck_ref_bind, type, conv);
} }
...@@ -6800,7 +6806,9 @@ convert_like_real (conversion *convs, tree expr, tree fn, int argnum, ...@@ -6800,7 +6806,9 @@ convert_like_real (conversion *convs, tree expr, tree fn, int argnum,
else else
gcc_unreachable (); 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)) if (type_unknown_p (expr))
expr = instantiate_type (totype, expr, complain); expr = instantiate_type (totype, expr, complain);
......
...@@ -6328,6 +6328,9 @@ extern tree create_try_catch_expr (tree, tree); ...@@ -6328,6 +6328,9 @@ extern tree create_try_catch_expr (tree, tree);
/* in expr.c */ /* in expr.c */
extern tree cplus_expand_constant (tree); 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, extern tree mark_rvalue_use (tree,
location_t = UNKNOWN_LOCATION, location_t = UNKNOWN_LOCATION,
bool reject_builtin = true); bool reject_builtin = true);
......
...@@ -89,7 +89,7 @@ cplus_expand_constant (tree cst) ...@@ -89,7 +89,7 @@ cplus_expand_constant (tree cst)
/* We've seen an actual use of EXPR. Possibly replace an outer variable /* We've seen an actual use of EXPR. Possibly replace an outer variable
reference inside with its constant value or a lambda capture. */ reference inside with its constant value or a lambda capture. */
static tree tree
mark_use (tree expr, bool rvalue_p, bool read_p, mark_use (tree expr, bool rvalue_p, bool read_p,
location_t loc /* = UNKNOWN_LOCATION */, location_t loc /* = UNKNOWN_LOCATION */,
bool reject_builtin /* = true */) bool reject_builtin /* = true */)
......
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> 2018-01-18 Richard Biener <rguenther@suse.de>
PR tree-optimization/83887 PR tree-optimization/83887
......
// { 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;
}
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment