Commit 4bf07f3f by Nathan Sidwell Committed by Nathan Sidwell

re PR c++/66735 ([C++14] lambda init-capture fails for const references)

	cp/
	PR c++/66735
	* cp-tree.h (DECLTYPE_FOR_REF_CAPTURE): New.
	(lambda_capture_field_type): Update prototype.
	* lambda.c (lambda_capture_field_type): Add is_reference parm.
	Add referenceness here.
	(add_capture): Adjust lambda_capture_field_type call, refactor
	error checking.
	* pt.c (tsubst): Adjust lambda_capture_field_type call.

	testsuite/
	PR c++/66735
	* g++.dg/cpp1y/pr66735.C: New.

From-SVN: r244056
parent 65793e42
2017-01-04 Nathan Sidwell <nathan@acm.org>
PR c++/66735
* cp-tree.h (DECLTYPE_FOR_REF_CAPTURE): New.
(lambda_capture_field_type): Update prototype.
* lambda.c (lambda_capture_field_type): Add is_reference parm.
Add referenceness here.
(add_capture): Adjust lambda_capture_field_type call, refactor
error checking.
* pt.c (tsubst): Adjust lambda_capture_field_type call.
2017-01-01 Jakub Jelinek <jakub@redhat.com> 2017-01-01 Jakub Jelinek <jakub@redhat.com>
Update copyright years. Update copyright years.
......
...@@ -181,6 +181,7 @@ operator == (const cp_expr &lhs, tree rhs) ...@@ -181,6 +181,7 @@ operator == (const cp_expr &lhs, tree rhs)
BIND_EXPR_BODY_BLOCK (in BIND_EXPR) BIND_EXPR_BODY_BLOCK (in BIND_EXPR)
DECL_NON_TRIVIALLY_INITIALIZED_P (in VAR_DECL) DECL_NON_TRIVIALLY_INITIALIZED_P (in VAR_DECL)
CALL_EXPR_ORDERED_ARGS (in CALL_EXPR, AGGR_INIT_EXPR) CALL_EXPR_ORDERED_ARGS (in CALL_EXPR, AGGR_INIT_EXPR)
DECLTYPE_FOR_REF_CAPTURE (in DECLTYPE_TYPE)
4: TREE_HAS_CONSTRUCTOR (in INDIRECT_REF, SAVE_EXPR, CONSTRUCTOR, 4: TREE_HAS_CONSTRUCTOR (in INDIRECT_REF, SAVE_EXPR, CONSTRUCTOR,
CALL_EXPR, or FIELD_DECL). CALL_EXPR, or FIELD_DECL).
IDENTIFIER_TYPENAME_P (in IDENTIFIER_NODE) IDENTIFIER_TYPENAME_P (in IDENTIFIER_NODE)
...@@ -4103,6 +4104,8 @@ more_aggr_init_expr_args_p (const aggr_init_expr_arg_iterator *iter) ...@@ -4103,6 +4104,8 @@ more_aggr_init_expr_args_p (const aggr_init_expr_arg_iterator *iter)
TREE_LANG_FLAG_1 (DECLTYPE_TYPE_CHECK (NODE)) TREE_LANG_FLAG_1 (DECLTYPE_TYPE_CHECK (NODE))
#define DECLTYPE_FOR_LAMBDA_PROXY(NODE) \ #define DECLTYPE_FOR_LAMBDA_PROXY(NODE) \
TREE_LANG_FLAG_2 (DECLTYPE_TYPE_CHECK (NODE)) TREE_LANG_FLAG_2 (DECLTYPE_TYPE_CHECK (NODE))
#define DECLTYPE_FOR_REF_CAPTURE(NODE) \
TREE_LANG_FLAG_3 (DECLTYPE_TYPE_CHECK (NODE))
/* Nonzero for VAR_DECL and FUNCTION_DECL node means that `extern' was /* Nonzero for VAR_DECL and FUNCTION_DECL node means that `extern' was
specified in its declaration. This can also be set for an specified in its declaration. This can also be set for an
...@@ -6528,7 +6531,7 @@ extern tree finish_trait_expr (enum cp_trait_kind, tree, tree); ...@@ -6528,7 +6531,7 @@ extern tree finish_trait_expr (enum cp_trait_kind, tree, tree);
extern tree build_lambda_expr (void); extern tree build_lambda_expr (void);
extern tree build_lambda_object (tree); extern tree build_lambda_object (tree);
extern tree begin_lambda_type (tree); extern tree begin_lambda_type (tree);
extern tree lambda_capture_field_type (tree, bool); extern tree lambda_capture_field_type (tree, bool, bool);
extern tree lambda_return_type (tree); extern tree lambda_return_type (tree);
extern tree lambda_proxy_type (tree); extern tree lambda_proxy_type (tree);
extern tree lambda_function (tree); extern tree lambda_function (tree);
......
...@@ -211,29 +211,45 @@ lambda_function (tree lambda) ...@@ -211,29 +211,45 @@ lambda_function (tree lambda)
} }
/* Returns the type to use for the FIELD_DECL corresponding to the /* Returns the type to use for the FIELD_DECL corresponding to the
capture of EXPR. capture of EXPR. EXPLICIT_INIT_P indicates whether this is a
The caller should add REFERENCE_TYPE for capture by reference. */ C++14 init capture, and BY_REFERENCE_P indicates whether we're
capturing by reference. */
tree tree
lambda_capture_field_type (tree expr, bool explicit_init_p) lambda_capture_field_type (tree expr, bool explicit_init_p,
bool by_reference_p)
{ {
tree type; tree type;
bool is_this = is_this_parameter (tree_strip_nop_conversions (expr)); bool is_this = is_this_parameter (tree_strip_nop_conversions (expr));
if (!is_this && type_dependent_expression_p (expr)) if (!is_this && type_dependent_expression_p (expr))
{ {
type = cxx_make_type (DECLTYPE_TYPE); type = cxx_make_type (DECLTYPE_TYPE);
DECLTYPE_TYPE_EXPR (type) = expr; DECLTYPE_TYPE_EXPR (type) = expr;
DECLTYPE_FOR_LAMBDA_CAPTURE (type) = true; DECLTYPE_FOR_LAMBDA_CAPTURE (type) = true;
DECLTYPE_FOR_INIT_CAPTURE (type) = explicit_init_p; DECLTYPE_FOR_INIT_CAPTURE (type) = explicit_init_p;
DECLTYPE_FOR_REF_CAPTURE (type) = by_reference_p;
SET_TYPE_STRUCTURAL_EQUALITY (type); SET_TYPE_STRUCTURAL_EQUALITY (type);
} }
else if (!is_this && explicit_init_p) else if (!is_this && explicit_init_p)
{ {
type = make_auto (); tree auto_node = make_auto ();
type = do_auto_deduction (type, expr, type);
type = auto_node;
if (by_reference_p)
/* Add the reference now, so deduction doesn't lose
outermost CV qualifiers of EXPR. */
type = build_reference_type (type);
type = do_auto_deduction (type, expr, auto_node);
} }
else else
type = non_reference (unlowered_expr_type (expr)); {
type = non_reference (unlowered_expr_type (expr));
if (!is_this && by_reference_p)
type = build_reference_type (type);
}
return type; return type;
} }
...@@ -504,9 +520,11 @@ add_capture (tree lambda, tree id, tree orig_init, bool by_reference_p, ...@@ -504,9 +520,11 @@ add_capture (tree lambda, tree id, tree orig_init, bool by_reference_p,
} }
else else
{ {
type = lambda_capture_field_type (initializer, explicit_init_p); type = lambda_capture_field_type (initializer, explicit_init_p,
by_reference_p);
if (type == error_mark_node) if (type == error_mark_node)
return error_mark_node; return error_mark_node;
if (id == this_identifier && !by_reference_p) if (id == this_identifier && !by_reference_p)
{ {
gcc_assert (POINTER_TYPE_P (type)); gcc_assert (POINTER_TYPE_P (type));
...@@ -514,17 +532,19 @@ add_capture (tree lambda, tree id, tree orig_init, bool by_reference_p, ...@@ -514,17 +532,19 @@ add_capture (tree lambda, tree id, tree orig_init, bool by_reference_p,
initializer = cp_build_indirect_ref (initializer, RO_NULL, initializer = cp_build_indirect_ref (initializer, RO_NULL,
tf_warning_or_error); tf_warning_or_error);
} }
if (id != this_identifier && by_reference_p)
if (dependent_type_p (type))
;
else if (id != this_identifier && by_reference_p)
{ {
type = build_reference_type (type); if (!lvalue_p (initializer))
if (!dependent_type_p (type) && !lvalue_p (initializer))
error ("cannot capture %qE by reference", initializer); error ("cannot capture %qE by reference", initializer);
} }
else else
{ {
/* Capture by copy requires a complete type. */ /* Capture by copy requires a complete type. */
type = complete_type (type); type = complete_type (type);
if (!dependent_type_p (type) && !COMPLETE_TYPE_P (type)) if (!COMPLETE_TYPE_P (type))
{ {
error ("capture by copy of incomplete type %qT", type); error ("capture by copy of incomplete type %qT", type);
cxx_incomplete_type_inform (type); cxx_incomplete_type_inform (type);
......
...@@ -13988,7 +13988,8 @@ tsubst (tree t, tree args, tsubst_flags_t complain, tree in_decl) ...@@ -13988,7 +13988,8 @@ tsubst (tree t, tree args, tsubst_flags_t complain, tree in_decl)
if (DECLTYPE_FOR_LAMBDA_CAPTURE (t)) if (DECLTYPE_FOR_LAMBDA_CAPTURE (t))
type = lambda_capture_field_type (type, type = lambda_capture_field_type (type,
DECLTYPE_FOR_INIT_CAPTURE (t)); DECLTYPE_FOR_INIT_CAPTURE (t),
DECLTYPE_FOR_REF_CAPTURE (t));
else if (DECLTYPE_FOR_LAMBDA_PROXY (t)) else if (DECLTYPE_FOR_LAMBDA_PROXY (t))
type = lambda_proxy_type (type); type = lambda_proxy_type (type);
else else
......
2017-01-04 Nathan Sidwell <nathan@acm.org>
PR c++/66735
* g++.dg/cpp1y/pr66735.C: New.
2017-01-04 Jakub Jelinek <jakub@redhat.com> 2017-01-04 Jakub Jelinek <jakub@redhat.com>
PR tree-optimization/71563 PR tree-optimization/71563
......
// { dg-do compile { target c++14 } }
// PR c++/66735, lost constness on reference capture
template <typename T> void Foo ()
{
T const x = 5;
auto l = [&rx = x]() {};
l ();
}
void Baz ()
{
int const x = 5;
auto l = [&rx = x]() {};
l ();
Foo<int> ();
}
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