aboutsummaryrefslogtreecommitdiff
path: root/gcc
diff options
context:
space:
mode:
authorJason Merrill <jason@redhat.com>2013-04-24 11:03:51 -0400
committerJason Merrill <jason@gcc.gnu.org>2013-04-24 11:03:51 -0400
commit399bb2da17cbe7474cd38556d051e921fc74c113 (patch)
tree4a74df96c106fa41190e45e0d69fd4efc617e763 /gcc
parent98bdfa5050997aaa055a899f80ff6c14734edd7d (diff)
downloadgcc-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
Diffstat (limited to 'gcc')
-rw-r--r--gcc/cp/ChangeLog10
-rw-r--r--gcc/cp/cp-tree.h10
-rw-r--r--gcc/cp/parser.c13
-rw-r--r--gcc/cp/pt.c3
-rw-r--r--gcc/cp/semantics.c17
-rw-r--r--gcc/testsuite/g++.dg/cpp1y/lambda-init5.C11
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();
+}