N3648: Allow braced and parenthesized initializers.
authorJason Merrill <jason@redhat.com>
Wed, 24 Apr 2013 15:03:51 +0000 (11:03 -0400)
committerJason Merrill <jason@gcc.gnu.org>
Wed, 24 Apr 2013 15:03:51 +0000 (11:03 -0400)
* 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
gcc/cp/cp-tree.h
gcc/cp/parser.c
gcc/cp/pt.c
gcc/cp/semantics.c
gcc/testsuite/g++.dg/cpp1y/lambda-init5.C [new file with mode: 0644]

index 1f37496e35ca7c953d0078fddfe5485a6a94b572..c63c9e21a194f8d428a6e8fcf49633ce405c0c8b 100644 (file)
@@ -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
index 339892ecea5933091bb3ef172cc2d742363c5474..78fd56bab1dd4018f1a92e17a495586e5d3fecb1 100644 (file)
@@ -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);
index 0456dd297613b802acb8d2b698cbb57b73ff2acd..cb2629204049c1310d6bb6bba1744f0b5d6a9e5a 100644 (file)
@@ -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
index 7d169b764c8a56cb0fa37f5d1baf7fd7954f5f78..57f65b3be0e4dd36d463207ec55498aa47bb738e 100644 (file)
@@ -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
index 5c0fc72480694008a2922c3b9b07bbfc609a839c..4cc22597e85a231efdaaa8c1cf4d4218e35b4ebe 100644 (file)
@@ -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 (file)
index 0000000..edada40
--- /dev/null
@@ -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();
+}