* parser.c (cp_parser_lambda_introducer): Use cp_parser_initializer.
* pt.c (tsubst) [DECLTYPE_TYPE]: Handle DECLTYPE_FOR_INIT_CAPTURE.
* semantics.c (lambda_capture_field_type): Use do_auto_deduction.
(add_capture): Collapse a parenthesized initializer into a single
expression.
* cp-tree.h (DECLTYPE_FOR_INIT_CAPTURE): New.
From-SVN: r198246
+2013-04-24 Jason Merrill <jason@redhat.com>
+
+ N3648: Allow braced and parenthesized initializers.
+ * parser.c (cp_parser_lambda_introducer): Use cp_parser_initializer.
+ * pt.c (tsubst) [DECLTYPE_TYPE]: Handle DECLTYPE_FOR_INIT_CAPTURE.
+ * semantics.c (lambda_capture_field_type): Use do_auto_deduction.
+ (add_capture): Collapse a parenthesized initializer into a single
+ expression.
+ * cp-tree.h (DECLTYPE_FOR_INIT_CAPTURE): New.
+
2013-04-24 Paolo Carlini <paolo.carlini@oracle.com>
PR c++/56970
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)
2: IDENTIFIER_OPNAME_P (in IDENTIFIER_NODE)
ICS_THIS_FLAG (in _CONV)
DECL_INITIALIZED_BY_CONSTANT_EXPRESSION_P (in VAR_DECL)
TYPENAME_IS_RESOLVING_P (in TYPE_NAME_TYPE)
TARGET_EXPR_DIRECT_INIT_P (in TARGET_EXPR)
FNDECL_USED_AUTO (in FUNCTION_DECL)
+ DECLTYPE_FOR_LAMBDA_PROXY (in DECLTYPE_TYPE)
3: (TREE_REFERENCE_EXPR) (in NON_LVALUE_EXPR) (commented-out).
ICS_BAD_FLAG (in _CONV)
FN_TRY_BLOCK_P (in TRY_BLOCK)
(DECLTYPE_TYPE_CHECK (NODE))->type_common.string_flag
/* These flags indicate that we want different semantics from normal
- decltype: lambda capture just drops references, lambda proxies look
- through implicit dereference. */
+ decltype: lambda capture just drops references, init capture
+ uses auto semantics, 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))
extern tree build_lambda_expr (void);
extern tree build_lambda_object (tree);
extern tree begin_lambda_type (tree);
-extern tree lambda_capture_field_type (tree);
+extern tree lambda_capture_field_type (tree, bool);
extern tree lambda_return_type (tree);
extern tree lambda_proxy_type (tree);
extern tree lambda_function (tree);
}
/* Find the initializer for this capture. */
- if (cp_lexer_next_token_is (parser->lexer, CPP_EQ))
+ if (cp_lexer_next_token_is (parser->lexer, CPP_EQ)
+ || cp_lexer_next_token_is (parser->lexer, CPP_OPEN_PAREN)
+ || cp_lexer_next_token_is (parser->lexer, CPP_OPEN_BRACE))
{
- /* An explicit expression exists. */
- cp_lexer_consume_token (parser->lexer);
+ bool direct, non_constant;
+ /* An explicit initializer exists. */
if (cxx_dialect < cxx1y)
pedwarn (input_location, 0,
"lambda capture initializers "
"only available with -std=c++1y or -std=gnu++1y");
- capture_init_expr = cp_parser_assignment_expression (parser,
- /*cast_p=*/true,
- &idk);
+ capture_init_expr = cp_parser_initializer (parser, &direct,
+ &non_constant);
explicit_init_p = true;
}
else
--c_inhibit_evaluation_warnings;
if (DECLTYPE_FOR_LAMBDA_CAPTURE (t))
- type = lambda_capture_field_type (type);
+ type = lambda_capture_field_type (type,
+ DECLTYPE_FOR_INIT_CAPTURE (t));
else if (DECLTYPE_FOR_LAMBDA_PROXY (t))
type = lambda_proxy_type (type);
else
The caller should add REFERENCE_TYPE for capture by reference. */
tree
-lambda_capture_field_type (tree expr)
+lambda_capture_field_type (tree expr, bool explicit_init_p)
{
- tree type = non_reference (unlowered_expr_type (expr));
+ tree type;
+ if (explicit_init_p)
+ {
+ type = make_auto ();
+ type = do_auto_deduction (type, expr, type);
+ }
+ else
+ type = non_reference (unlowered_expr_type (expr));
if (!type || WILDCARD_TYPE_P (type))
{
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;
SET_TYPE_STRUCTURAL_EQUALITY (type);
}
return type;
char *buf;
tree type, member, name;
- type = lambda_capture_field_type (initializer);
+ if (TREE_CODE (initializer) == TREE_LIST)
+ initializer = build_x_compound_expr_from_list (initializer, ELK_INIT,
+ tf_warning_or_error);
+ type = lambda_capture_field_type (initializer, explicit_init_p);
if (by_reference_p)
{
type = build_reference_type (type);
--- /dev/null
+// Test for paren and brace initializers
+// { dg-options "-std=c++1y" }
+// { dg-do run }
+
+#include <initializer_list>
+
+int main()
+{
+ if ([x(42)]{ return x; }() != 42) __builtin_abort();
+ if ([x{1,2}]{ return x.begin()[0]; }() != 1) __builtin_abort();
+}