LAMBDA_EXPR_MUTABLE_P (in LAMBDA_EXPR)
DECL_FINAL_P (in FUNCTION_DECL)
QUALIFIED_NAME_IS_TEMPLATE (in SCOPE_REF)
- DECLTYPE_FOR_INIT_CAPTURE (in DECLTYPE_TYPE)
CONSTRUCTOR_IS_DEPENDENT (in CONSTRUCTOR)
TINFO_USED_TEMPLATE_ID (in TEMPLATE_INFO)
PACK_EXPANSION_SIZEOF_P (in *_PACK_EXPANSION)
(DECLTYPE_TYPE_CHECK (NODE))->type_common.string_flag
/* These flags indicate that we want different semantics from normal
- decltype: lambda capture just drops references, init capture
- uses auto semantics, lambda proxies look through implicit dereference. */
+ decltype: lambda capture just drops references,
+ lambda proxies look through implicit dereference. */
#define DECLTYPE_FOR_LAMBDA_CAPTURE(NODE) \
TREE_LANG_FLAG_0 (DECLTYPE_TYPE_CHECK (NODE))
-#define DECLTYPE_FOR_INIT_CAPTURE(NODE) \
- TREE_LANG_FLAG_1 (DECLTYPE_TYPE_CHECK (NODE))
#define DECLTYPE_FOR_LAMBDA_PROXY(NODE) \
TREE_LANG_FLAG_2 (DECLTYPE_TYPE_CHECK (NODE))
#define DECLTYPE_FOR_REF_CAPTURE(NODE) \
extern tree instantiate_decl (tree, bool, bool);
extern int comp_template_parms (const_tree, const_tree);
extern bool builtin_pack_fn_p (tree);
-extern bool uses_parameter_packs (tree);
+extern tree uses_parameter_packs (tree);
extern bool template_parameter_pack_p (const_tree);
extern bool function_parameter_pack_p (const_tree);
extern bool function_parameter_expanded_from_pack_p (tree, tree);
tree type;
bool is_this = is_this_parameter (tree_strip_nop_conversions (expr));
- if (!is_this && type_dependent_expression_p (expr))
- {
- type = cxx_make_type (DECLTYPE_TYPE);
- DECLTYPE_TYPE_EXPR (type) = expr;
- DECLTYPE_FOR_LAMBDA_CAPTURE (type) = true;
- DECLTYPE_FOR_INIT_CAPTURE (type) = explicit_init_p;
- DECLTYPE_FOR_REF_CAPTURE (type) = by_reference_p;
- SET_TYPE_STRUCTURAL_EQUALITY (type);
- }
- else if (!is_this && explicit_init_p)
+ if (!is_this && explicit_init_p)
{
tree auto_node = make_auto ();
type = build_reference_type (type);
type = do_auto_deduction (type, expr, auto_node);
}
+ else if (!is_this && type_dependent_expression_p (expr))
+ {
+ type = cxx_make_type (DECLTYPE_TYPE);
+ DECLTYPE_TYPE_EXPR (type) = expr;
+ DECLTYPE_FOR_LAMBDA_CAPTURE (type) = true;
+ DECLTYPE_FOR_REF_CAPTURE (type) = by_reference_p;
+ SET_TYPE_STRUCTURAL_EQUALITY (type);
+ }
else
{
type = non_reference (unlowered_expr_type (expr));
name = get_identifier (buf);
if (variadic)
- type = make_pack_expansion (type);
+ {
+ type = make_pack_expansion (type);
+ if (explicit_init_p)
+ /* With an explicit initializer 'type' is auto, which isn't really a
+ parameter pack in this context. We will want as many fields as we
+ have elements in the expansion of the initializer, so use its packs
+ instead. */
+ PACK_EXPANSION_PARAMETER_PACKS (type)
+ = uses_parameter_packs (initializer);
+ }
/* Make member variable. */
member = build_decl (input_location, FIELD_DECL, name, type);
}
/* Determines if the expression or type T uses any parameter packs. */
-bool
+tree
uses_parameter_packs (tree t)
{
tree parameter_packs = NULL_TREE;
ppd.type_pack_expansion_p = false;
cp_walk_tree (&t, &find_parameter_packs_r, &ppd, ppd.visited);
delete ppd.visited;
- return parameter_packs != NULL_TREE;
+ return parameter_packs;
}
/* Turn ARG, which may be an expression, type, or a TREE_LIST
ARGUMENT_PACK_SELECT_INDEX (aps) = index;
}
- // Any local specialization bindings arising from this substitution
- // cannot be reused for a different INDEX.
- local_specialization_stack lss (lss_copy);
-
/* Substitute into the PATTERN with the (possibly altered)
arguments. */
if (pattern == in_decl)
/*function_p*/false,
/*integral_constant_expression*/false);
- if (DECLTYPE_FOR_INIT_CAPTURE (t))
- {
- if (type == NULL_TREE)
- {
- if (complain & tf_error)
- error ("empty initializer in lambda init-capture");
- type = error_mark_node;
- }
- else if (TREE_CODE (type) == TREE_LIST)
- type = build_x_compound_expr_from_list (type, ELK_INIT, complain);
- }
-
--cp_unevaluated_operand;
--c_inhibit_evaluation_warnings;
if (DECLTYPE_FOR_LAMBDA_CAPTURE (t))
type = lambda_capture_field_type (type,
- DECLTYPE_FOR_INIT_CAPTURE (t),
+ false /*explicit_init*/,
DECLTYPE_FOR_REF_CAPTURE (t));
else if (DECLTYPE_FOR_LAMBDA_PROXY (t))
type = lambda_proxy_type (type);
return t;
}
+/* Subroutine of tsubst_lambda_expr: add the FIELD/INIT capture pair to the
+ LAMBDA_EXPR_CAPTURE_LIST passed in LIST. Do deduction for a previously
+ dependent init-capture. */
+
+static void
+prepend_one_capture (tree field, tree init, tree &list,
+ tsubst_flags_t complain)
+{
+ if (tree auto_node = type_uses_auto (TREE_TYPE (field)))
+ {
+ tree type = NULL_TREE;
+ if (!init)
+ {
+ if (complain & tf_error)
+ error ("empty initializer in lambda init-capture");
+ init = error_mark_node;
+ }
+ else if (TREE_CODE (init) == TREE_LIST)
+ init = build_x_compound_expr_from_list (init, ELK_INIT, complain);
+ if (!type)
+ type = do_auto_deduction (TREE_TYPE (field), init, auto_node, complain);
+ TREE_TYPE (field) = type;
+ cp_apply_type_quals_to_decl (cp_type_quals (type), field);
+ }
+ list = tree_cons (field, init, list);
+}
+
/* T is a LAMBDA_EXPR. Generate a new LAMBDA_EXPR for the current
instantiation context. Instantiating a pack expansion containing a lambda
might result in multiple lambdas all based on the same lambda in the
tree oldfn = lambda_function (t);
in_decl = oldfn;
- /* If we have already specialized this lambda expr, reuse it. See
- PR c++/87322. */
- if (local_specializations)
- if (tree r = retrieve_local_specialization (t))
- return r;
-
tree r = build_lambda_expr ();
- if (local_specializations)
- register_local_specialization (r, t);
-
LAMBDA_EXPR_LOCATION (r)
= LAMBDA_EXPR_LOCATION (t);
LAMBDA_EXPR_DEFAULT_CAPTURE_MODE (r)
gcc_assert (TREE_CODE (init) == TREE_VEC
&& TREE_VEC_LENGTH (init) == len);
for (int i = 0; i < len; ++i)
- LAMBDA_EXPR_CAPTURE_LIST (r)
- = tree_cons (TREE_VEC_ELT (field, i),
- TREE_VEC_ELT (init, i),
- LAMBDA_EXPR_CAPTURE_LIST (r));
+ prepend_one_capture (TREE_VEC_ELT (field, i),
+ TREE_VEC_ELT (init, i),
+ LAMBDA_EXPR_CAPTURE_LIST (r),
+ complain);
}
else
{
- LAMBDA_EXPR_CAPTURE_LIST (r)
- = tree_cons (field, init, LAMBDA_EXPR_CAPTURE_LIST (r));
+ prepend_one_capture (field, init, LAMBDA_EXPR_CAPTURE_LIST (r),
+ complain);
if (id_equal (DECL_NAME (field), "__this"))
LAMBDA_EXPR_THIS_CAPTURE (r) = field;
}
else
{
+ if (error_operand_p (init))
+ return error_mark_node;
+
tree parms = build_tree_list (NULL_TREE, type);
tree tparms;