From 399bb2da17cbe7474cd38556d051e921fc74c113 Mon Sep 17 00:00:00 2001 From: Jason Merrill Date: Wed, 24 Apr 2013 11:03:51 -0400 Subject: [PATCH] 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. From-SVN: r198246 --- gcc/cp/ChangeLog | 10 ++++++++++ gcc/cp/cp-tree.h | 10 +++++++--- gcc/cp/parser.c | 13 +++++++------ gcc/cp/pt.c | 3 ++- gcc/cp/semantics.c | 17 ++++++++++++++--- gcc/testsuite/g++.dg/cpp1y/lambda-init5.C | 11 +++++++++++ 6 files changed, 51 insertions(+), 13 deletions(-) create mode 100644 gcc/testsuite/g++.dg/cpp1y/lambda-init5.C diff --git a/gcc/cp/ChangeLog b/gcc/cp/ChangeLog index 1f37496e35c..c63c9e21a19 100644 --- a/gcc/cp/ChangeLog +++ b/gcc/cp/ChangeLog @@ -1,3 +1,13 @@ +2013-04-24 Jason Merrill + + 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 PR c++/56970 diff --git a/gcc/cp/cp-tree.h b/gcc/cp/cp-tree.h index 339892ecea5..78fd56bab1d 100644 --- a/gcc/cp/cp-tree.h +++ b/gcc/cp/cp-tree.h @@ -90,6 +90,7 @@ c-common.h, not after. 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) @@ -97,6 +98,7 @@ c-common.h, not after. 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) @@ -3590,10 +3592,12 @@ more_aggr_init_expr_args_p (const aggr_init_expr_arg_iterator *iter) (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)) @@ -5781,7 +5785,7 @@ extern tree finish_trait_expr (enum cp_trait_kind, tree, tree); 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); diff --git a/gcc/cp/parser.c b/gcc/cp/parser.c index 0456dd29761..cb262920404 100644 --- a/gcc/cp/parser.c +++ b/gcc/cp/parser.c @@ -8548,17 +8548,18 @@ cp_parser_lambda_introducer (cp_parser* parser, tree lambda_expr) } /* 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 diff --git a/gcc/cp/pt.c b/gcc/cp/pt.c index 7d169b764c8..57f65b3be0e 100644 --- a/gcc/cp/pt.c +++ b/gcc/cp/pt.c @@ -11794,7 +11794,8 @@ tsubst (tree t, tree args, tsubst_flags_t complain, tree in_decl) --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 diff --git a/gcc/cp/semantics.c b/gcc/cp/semantics.c index 5c0fc724806..4cc22597e85 100644 --- a/gcc/cp/semantics.c +++ b/gcc/cp/semantics.c @@ -9127,14 +9127,22 @@ lambda_function (tree lambda) 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; @@ -9400,7 +9408,10 @@ add_capture (tree lambda, tree id, tree initializer, bool by_reference_p, 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); diff --git a/gcc/testsuite/g++.dg/cpp1y/lambda-init5.C b/gcc/testsuite/g++.dg/cpp1y/lambda-init5.C new file mode 100644 index 00000000000..edada406986 --- /dev/null +++ b/gcc/testsuite/g++.dg/cpp1y/lambda-init5.C @@ -0,0 +1,11 @@ +// Test for paren and brace initializers +// { dg-options "-std=c++1y" } +// { dg-do run } + +#include + +int main() +{ + if ([x(42)]{ return x; }() != 42) __builtin_abort(); + if ([x{1,2}]{ return x.begin()[0]; }() != 1) __builtin_abort(); +} -- 2.30.2