diff options
author | Jason Merrill <jason@redhat.com> | 2013-04-24 11:03:51 -0400 |
---|---|---|
committer | Jason Merrill <jason@gcc.gnu.org> | 2013-04-24 11:03:51 -0400 |
commit | 399bb2da17cbe7474cd38556d051e921fc74c113 (patch) | |
tree | 4a74df96c106fa41190e45e0d69fd4efc617e763 | |
parent | 98bdfa5050997aaa055a899f80ff6c14734edd7d (diff) | |
download | gcc-399bb2da17cbe7474cd38556d051e921fc74c113.zip gcc-399bb2da17cbe7474cd38556d051e921fc74c113.tar.gz gcc-399bb2da17cbe7474cd38556d051e921fc74c113.tar.bz2 |
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
-rw-r--r-- | gcc/cp/ChangeLog | 10 | ||||
-rw-r--r-- | gcc/cp/cp-tree.h | 10 | ||||
-rw-r--r-- | gcc/cp/parser.c | 13 | ||||
-rw-r--r-- | gcc/cp/pt.c | 3 | ||||
-rw-r--r-- | gcc/cp/semantics.c | 17 | ||||
-rw-r--r-- | gcc/testsuite/g++.dg/cpp1y/lambda-init5.C | 11 |
6 files changed, 51 insertions, 13 deletions
diff --git a/gcc/cp/ChangeLog b/gcc/cp/ChangeLog index 1f37496..c63c9e2 100644 --- a/gcc/cp/ChangeLog +++ b/gcc/cp/ChangeLog @@ -1,3 +1,13 @@ +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 diff --git a/gcc/cp/cp-tree.h b/gcc/cp/cp-tree.h index 339892e..78fd56b 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 0456dd2..cb26292 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 7d169b7..57f65b3 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 5c0fc72..4cc2259 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 0000000..edada40 --- /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 <initializer_list> + +int main() +{ + if ([x(42)]{ return x; }() != 42) __builtin_abort(); + if ([x{1,2}]{ return x.begin()[0]; }() != 1) __builtin_abort(); +} |