Implement P0305R1, Selection statements with initializer.
authorMarek Polacek <polacek@redhat.com>
Wed, 5 Oct 2016 18:02:06 +0000 (18:02 +0000)
committerMarek Polacek <mpolacek@gcc.gnu.org>
Wed, 5 Oct 2016 18:02:06 +0000 (18:02 +0000)
* cp-array-notation.c (create_an_loop): Call finish_init_stmt
instead of finish_for_init_stmt.
* cp-tree.h (finish_for_init_stmt): Rename to finish_init_stmt.
* decl.c (poplevel): Adjust a comment.
* init.c (build_vec_init): Call finish_init_stmt instead of
finish_for_init_stmt.
* name-lookup.c (pushdecl_maybe_friend_1): Adjust a comment.
* name-lookup.h (enum scope_kind): Likewise.
* parser.c (cp_parser_statement): Update commentary.
(cp_parser_init_statement_p): New function.
(cp_parser_selection_statement): Parse the optional init-statement.
(cp_parser_for): Call finish_init_stmt instead of finish_for_init_stmt.
(cp_parser_c_for): Likewise.
(cp_convert_range_for): Call finish_init_stmt instead of finish_for_init_stmt.
(cp_parser_range_for_member_function): Update commentary.
(cp_parser_iteration_statement):
(cp_parser_for_init_statement): Rename to cp_parser_init_statement.
* pt.c (tsubst_omp_for_iterator): Update commentary.
(tsubst_expr): Call finish_init_stmt instead of finish_for_init_stmt.
* semantics.c (finish_for_init_stmt): Rename to finish_init_stmt.
Update commentary.

* g++.dg/cpp1z/init-statement1.C: New test.
* g++.dg/cpp1z/init-statement2.C: New test.
* g++.dg/cpp1z/init-statement3.C: New test.
* g++.dg/cpp1z/init-statement4.C: New test.
* g++.dg/cpp1z/init-statement5.C: New test.
* g++.dg/cpp1z/init-statement6.C: New test.
* g++.dg/cpp1z/init-statement7.C: New test.
* g++.dg/cpp1z/init-statement8.C: New test.

From-SVN: r240798

19 files changed:
gcc/cp/ChangeLog
gcc/cp/cp-array-notation.c
gcc/cp/cp-tree.h
gcc/cp/decl.c
gcc/cp/init.c
gcc/cp/name-lookup.c
gcc/cp/name-lookup.h
gcc/cp/parser.c
gcc/cp/pt.c
gcc/cp/semantics.c
gcc/testsuite/ChangeLog
gcc/testsuite/g++.dg/cpp1z/init-statement1.C [new file with mode: 0644]
gcc/testsuite/g++.dg/cpp1z/init-statement2.C [new file with mode: 0644]
gcc/testsuite/g++.dg/cpp1z/init-statement3.C [new file with mode: 0644]
gcc/testsuite/g++.dg/cpp1z/init-statement4.C [new file with mode: 0644]
gcc/testsuite/g++.dg/cpp1z/init-statement5.C [new file with mode: 0644]
gcc/testsuite/g++.dg/cpp1z/init-statement6.C [new file with mode: 0644]
gcc/testsuite/g++.dg/cpp1z/init-statement7.C [new file with mode: 0644]
gcc/testsuite/g++.dg/cpp1z/init-statement8.C [new file with mode: 0644]

index acd1a78696c38963556eec39867aea09621f8331..dd43d9880a90b55521fe9ecc20474dbdecc59663 100644 (file)
@@ -1,3 +1,28 @@
+2016-10-05  Marek Polacek  <polacek@redhat.com>
+
+       Implement P0305R1, Selection statements with initializer.
+       * cp-array-notation.c (create_an_loop): Call finish_init_stmt
+       instead of finish_for_init_stmt.
+       * cp-tree.h (finish_for_init_stmt): Rename to finish_init_stmt.
+       * decl.c (poplevel): Adjust a comment.
+       * init.c (build_vec_init): Call finish_init_stmt instead of
+       finish_for_init_stmt.
+       * name-lookup.c (pushdecl_maybe_friend_1): Adjust a comment.
+       * name-lookup.h (enum scope_kind): Likewise.
+       * parser.c (cp_parser_statement): Update commentary.
+       (cp_parser_init_statement_p): New function.
+       (cp_parser_selection_statement): Parse the optional init-statement.
+       (cp_parser_for): Call finish_init_stmt instead of finish_for_init_stmt.
+       (cp_parser_c_for): Likewise.
+       (cp_convert_range_for): Call finish_init_stmt instead of finish_for_init_stmt.
+       (cp_parser_range_for_member_function): Update commentary.
+       (cp_parser_iteration_statement):
+       (cp_parser_for_init_statement): Rename to cp_parser_init_statement.
+       * pt.c (tsubst_omp_for_iterator): Update commentary.
+       (tsubst_expr): Call finish_init_stmt instead of finish_for_init_stmt.
+       * semantics.c (finish_for_init_stmt): Rename to finish_init_stmt.
+       Update commentary.
+
 2016-10-04  Jason Merrill  <jason@redhat.com>
 
        PR c++/77852
index 4687ced6729c13fd2c64a808c3ffc6dc3fe3993f..633ab09102655ceb46b187817fd79c0253e556cd 100644 (file)
@@ -66,7 +66,7 @@ create_an_loop (tree init, tree cond, tree incr, tree body)
 
   finish_expr_stmt (init);
   for_stmt = begin_for_stmt (NULL_TREE, NULL_TREE);
-  finish_for_init_stmt (for_stmt);
+  finish_init_stmt (for_stmt);
   finish_for_cond (cond, for_stmt, false);
   finish_for_expr (incr, for_stmt);
   finish_expr_stmt (body);
index 3fbe1d96c66059c849e25c835fc57dc6fb5e0cc4..92e40170f5b5a20c2bef6d700f051082ff29c147 100644 (file)
@@ -6297,7 +6297,7 @@ extern void finish_do_stmt                        (tree, tree, bool);
 extern tree finish_return_stmt                 (tree);
 extern tree begin_for_scope                    (tree *);
 extern tree begin_for_stmt                     (tree, tree);
-extern void finish_for_init_stmt               (tree);
+extern void finish_init_stmt                   (tree);
 extern void finish_for_cond                    (tree, tree, bool);
 extern void finish_for_expr                    (tree, tree);
 extern void finish_for_stmt                    (tree);
index 6646062e6723eeef84cfd8c45c77926d2e65686c..6a08d8f8729b545bd4bc5973d39991216bceaf7a 100644 (file)
@@ -639,9 +639,8 @@ poplevel (int keep, int reverse, int functionbody)
       BLOCK_SUPERCONTEXT (link) = block;
 
   /* We still support the old for-scope rules, whereby the variables
-     in a for-init statement were in scope after the for-statement
-     ended.  We only use the new rules if flag_new_for_scope is
-     nonzero.  */
+     in a init statement were in scope after the for-statement ended.
+     We only use the new rules if flag_new_for_scope is nonzero.  */
   leaving_for_scope
     = current_binding_level->kind == sk_for && flag_new_for_scope == 1;
 
index 2d5877d3041bbd288dc51fd7c0073c17d3de93eb..d1c8274003cefb4dfacf846889d239523ab80f0b 100644 (file)
@@ -4052,7 +4052,7 @@ build_vec_init (tree base, tree maxindex, tree init,
       tree to;
 
       for_stmt = begin_for_stmt (NULL_TREE, NULL_TREE);
-      finish_for_init_stmt (for_stmt);
+      finish_init_stmt (for_stmt);
       finish_for_cond (build2 (GT_EXPR, boolean_type_node, iterator,
                               build_int_cst (TREE_TYPE (iterator), -1)),
                       for_stmt, false);
index 1bce63bb2dd75f8d92bb36767be361fd8e7edda3..9e84a1b1f2eeeed222a996f8df0cad4ac518273d 100644 (file)
@@ -1156,7 +1156,7 @@ pushdecl_maybe_friend_1 (tree x, bool is_friend)
                   }
                }
              /* Error if redeclaring a local declared in a
-                for-init-statement or in the condition of an if or
+                init-statement or in the condition of an if or
                 switch statement when the new declaration is in the
                 outermost block of the controlled statement.
                 Redeclaring a variable from a for or while condition is
index 2cb129caad9e92bc5cc9dac41a6e07622766b9f6..fd71038479886949824c8512666401dc40f23ad7 100644 (file)
@@ -107,7 +107,7 @@ enum scope_kind {
   sk_try,           /* A try-block.  */
   sk_catch,         /* A catch-block.  */
   sk_for,           /* The scope of the variable declared in a
-                       for-init-statement.  */
+                       init-statement.  */
   sk_cond,          /* The scope of the variable declared in the condition
                        of an if or switch statement.  */
   sk_function_parms, /* The scope containing function parameters.  */
index 683a6dda924d386427ffcc27601fe724fa3596bc..f3dc3591c7d63d16ca3f4f826eddeb25b8992a52 100644 (file)
@@ -2117,7 +2117,7 @@ static tree cp_parser_condition
   (cp_parser *);
 static tree cp_parser_iteration_statement
   (cp_parser *, bool *, bool);
-static bool cp_parser_for_init_statement
+static bool cp_parser_init_statement
   (cp_parser *, tree *decl);
 static tree cp_parser_for
   (cp_parser *, bool);
@@ -2642,6 +2642,8 @@ static bool cp_parser_compound_literal_p
   (cp_parser *);
 static bool cp_parser_array_designator_p
   (cp_parser *);
+static bool cp_parser_init_statement_p
+  (cp_parser *);
 static bool cp_parser_skip_to_closing_square_bracket
   (cp_parser *);
 
@@ -10396,6 +10398,10 @@ cp_parser_lambda_body (cp_parser* parser, tree lambda_expr)
     declaration-statement
     attribute-specifier-seq (opt) try-block
 
+  init-statement:
+    expression-statement
+    simple-declaration
+
   TM Extension:
 
    statement:
@@ -10936,12 +10942,32 @@ cp_parser_statement_seq_opt (cp_parser* parser, tree in_statement_expr)
     }
 }
 
+/* Return true if we're looking at (init; cond), false otherwise.  */
+
+static bool
+cp_parser_init_statement_p (cp_parser *parser)
+{
+  /* Save tokens so that we can put them back.  */
+  cp_lexer_save_tokens (parser->lexer);
+
+  /* Look for ';' that is not nested in () or {}.  */
+  int ret = cp_parser_skip_to_closing_parenthesis_1 (parser,
+                                                    /*recovering=*/false,
+                                                    CPP_SEMICOLON,
+                                                    /*consume_paren=*/false);
+
+  /* Roll back the tokens we skipped.  */
+  cp_lexer_rollback_tokens (parser->lexer);
+
+  return ret == -1;
+}
+
 /* Parse a selection-statement.
 
    selection-statement:
-     if ( condition ) statement
-     if ( condition ) statement else statement
-     switch ( condition ) statement
+     if ( init-statement [opt] condition ) statement
+     if ( init-statement [opt] condition ) statement else statement
+     switch ( init-statement [opt] condition ) statement
 
    Returns the new IF_STMT or SWITCH_STMT.
 
@@ -11006,6 +11032,17 @@ cp_parser_selection_statement (cp_parser* parser, bool *if_p,
        else
          statement = begin_switch_stmt ();
 
+       /* Parse the optional init-statement.  */
+       if (cp_parser_init_statement_p (parser))
+         {
+           tree decl;
+           if (cxx_dialect < cxx1z)
+             pedwarn (cp_lexer_peek_token (parser->lexer)->location, 0,
+                      "init-statement in selection statements only available "
+                      "with -std=c++1z or -std=gnu++1z");
+           cp_parser_init_statement (parser, &decl);
+         }
+
        /* Parse the condition.  */
        condition = cp_parser_condition (parser);
        /* Look for the `)'.  */
@@ -11306,7 +11343,7 @@ cp_parser_for (cp_parser *parser, bool ivdep)
   scope = begin_for_scope (&init);
 
   /* Parse the initialization.  */
-  is_range_for = cp_parser_for_init_statement (parser, &decl);
+  is_range_for = cp_parser_init_statement (parser, &decl);
 
   if (is_range_for)
     return cp_parser_range_for (parser, scope, init, decl, ivdep);
@@ -11323,9 +11360,9 @@ cp_parser_c_for (cp_parser *parser, tree scope, tree init, bool ivdep)
   tree stmt;
 
   stmt = begin_for_stmt (scope, init);
-  /* The for-init-statement has already been parsed in
-     cp_parser_for_init_statement, so no work is needed here.  */
-  finish_for_init_stmt (stmt);
+  /* The init-statement has already been parsed in
+     cp_parser_init_statement, so no work is needed here.  */
+  finish_init_stmt (stmt);
 
   /* If there's a condition, process it.  */
   if (cp_lexer_next_token_is_not (parser->lexer, CPP_SEMICOLON))
@@ -11354,7 +11391,7 @@ cp_parser_c_for (cp_parser *parser, tree scope, tree init, bool ivdep)
     decl-specifier-seq declarator : expression
 
   The decl-specifier-seq declarator and the `:' are already parsed by
-  cp_parser_for_init_statement. If processing_template_decl it returns a
+  cp_parser_init_statement.  If processing_template_decl it returns a
   newly created RANGE_FOR_STMT; if not, it is converted to a
   regular FOR_STMT.  */
 
@@ -11552,7 +11589,7 @@ cp_convert_range_for (tree statement, tree range_decl, tree range_expr,
                  /*is_constant_init*/false, NULL_TREE,
                  LOOKUP_ONLYCONVERTING);
 
-  finish_for_init_stmt (statement);
+  finish_init_stmt (statement);
 
   /* The new for condition.  */
   condition = build_x_binary_op (input_location, NE_EXPR,
@@ -11726,7 +11763,7 @@ cp_parser_range_for_member_function (tree range, tree identifier)
    iteration-statement:
      while ( condition ) statement
      do statement while ( expression ) ;
-     for ( for-init-statement condition [opt] ; expression [opt] )
+     for ( init-statement condition [opt] ; expression [opt] )
        statement
 
    Returns the new WHILE_STMT, DO_STMT, FOR_STMT or RANGE_FOR_STMT.  */
@@ -11832,15 +11869,15 @@ cp_parser_iteration_statement (cp_parser* parser, bool *if_p, bool ivdep)
   return statement;
 }
 
-/* Parse a for-init-statement or the declarator of a range-based-for.
+/* Parse a init-statement or the declarator of a range-based-for.
    Returns true if a range-based-for declaration is seen.
 
-   for-init-statement:
+   init-statement:
      expression-statement
      simple-declaration  */
 
 static bool
-cp_parser_for_init_statement (cp_parser* parser, tree *decl)
+cp_parser_init_statement (cp_parser* parser, tree *decl)
 {
   /* If the next token is a `;', then we have an empty
      expression-statement.  Grammatically, this is also a
index e6b1368daf75f47a85eb977597eae53bad8a2172..e6bacdfa5ae3636ed0c429a22bcb267e623d5083 100644 (file)
@@ -14974,7 +14974,7 @@ tsubst_omp_for_iterator (tree t, int i, tree declv, tree orig_declv,
   if (init && TREE_CODE (init) == DECL_EXPR)
     {
       /* We need to jump through some hoops to handle declarations in the
-        for-init-statement, since we might need to handle auto deduction,
+        init-statement, since we might need to handle auto deduction,
         but we need to keep control of initialization.  */
       decl_expr = init;
       init = DECL_INITIAL (DECL_EXPR_DECL (init));
@@ -15359,7 +15359,7 @@ tsubst_expr (tree t, tree args, tsubst_flags_t complain, tree in_decl,
     case FOR_STMT:
       stmt = begin_for_stmt (NULL_TREE, NULL_TREE);
       RECUR (FOR_INIT_STMT (t));
-      finish_for_init_stmt (stmt);
+      finish_init_stmt (stmt);
       tmp = RECUR (FOR_COND (t));
       finish_for_cond (tmp, stmt, false);
       tmp = RECUR (FOR_EXPR (t));
index 1d8f3369fc1b18deb106e94e7367c061679cbdb1..cae5afc0d4be747f605e9a726b4513c8be10b221 100644 (file)
@@ -953,11 +953,11 @@ begin_for_stmt (tree scope, tree init)
   return r;
 }
 
-/* Finish the for-init-statement of a for-statement, which may be
+/* Finish the init-statement of a for-statement, which may be
    given by FOR_STMT.  */
 
 void
-finish_for_init_stmt (tree for_stmt)
+finish_init_stmt (tree for_stmt)
 {
   if (processing_template_decl)
     FOR_INIT_STMT (for_stmt) = pop_stmt_list (FOR_INIT_STMT (for_stmt));
index 653dee53d9345ea7424fc7f715dd95f819423c57..6c587f69d25de347b324e776c53ddb7ec59377ae 100644 (file)
@@ -1,3 +1,14 @@
+2016-10-05  Marek Polacek  <polacek@redhat.com>
+
+       * g++.dg/cpp1z/init-statement1.C: New test.
+       * g++.dg/cpp1z/init-statement2.C: New test.
+       * g++.dg/cpp1z/init-statement3.C: New test.
+       * g++.dg/cpp1z/init-statement4.C: New test.
+       * g++.dg/cpp1z/init-statement5.C: New test.
+       * g++.dg/cpp1z/init-statement6.C: New test.
+       * g++.dg/cpp1z/init-statement7.C: New test.
+       * g++.dg/cpp1z/init-statement8.C: New test.
+
 2016-10-05  Louis Krupp  <louis.krupp@zoho.com>
 
        PR fortran/67524
diff --git a/gcc/testsuite/g++.dg/cpp1z/init-statement1.C b/gcc/testsuite/g++.dg/cpp1z/init-statement1.C
new file mode 100644 (file)
index 0000000..1cebc3f
--- /dev/null
@@ -0,0 +1,28 @@
+// { dg-do compile { target c++11 } }
+// { dg-options "" }
+
+extern int foo (void);
+extern void bar (int);
+
+void
+f (void)
+{
+  if (auto p = foo (); p > 10) // { dg-warning "init-statement" "" { target c++14_down } }
+    bar (p);
+  else
+    bar (-p);
+}
+// { dg-do compile { target c++11 } }
+// { dg-options "" }
+
+extern int foo (void);
+extern void bar (int);
+
+void
+f (void)
+{
+  if (auto p = foo (); p > 10) // { dg-warning "init-statement" "" { target c++14_down } }
+    bar (p);
+  else
+    bar (-p);
+}
diff --git a/gcc/testsuite/g++.dg/cpp1z/init-statement2.C b/gcc/testsuite/g++.dg/cpp1z/init-statement2.C
new file mode 100644 (file)
index 0000000..19d8e0c
--- /dev/null
@@ -0,0 +1,124 @@
+// { dg-options -std=c++1z }
+// Test C++17 selection statements with initializer, basic use.
+
+extern int foo (void);
+extern void bar (int);
+extern int g;
+
+void
+f (void)
+{
+  if (auto p = foo (); p > 10)
+    bar (p);
+  else
+    bar (-p);
+
+  if ((g += 2); g > 6)
+    bar (1);
+
+  if (auto a = 9, b = foo (); a + b > 10)
+    bar (a + b);
+  else
+    bar (a - b);
+
+  if (({ int a; 1;}))
+    bar (0);
+
+  if (auto i = foo (); i > 6)
+    bar (0);
+  else if (i++; i > 8)
+    bar (1);
+}
+
+extern void lock (void);
+
+void
+f2 (int i)
+{
+  if (lock (); i > 10)
+    ++i;
+  else
+    --i;
+}
+
+void
+f3 (int i)
+{
+  switch (i *= 2; auto idx = i)
+    {
+    case 4:
+      bar (3);
+      break;
+    default:
+      break;
+    }
+}
+
+void
+f4 (void)
+{
+  if constexpr (constexpr auto s = sizeof (int); s > 10)
+    foo ();
+}
+// { dg-options -std=c++1z }
+// Test C++17 selection statements with initializer, basic use.
+
+extern int foo (void);
+extern void bar (int);
+extern int g;
+
+void
+f (void)
+{
+  if (auto p = foo (); p > 10)
+    bar (p);
+  else
+    bar (-p);
+
+  if ((g += 2); g > 6)
+    bar (1);
+
+  if (auto a = 9, b = foo (); a + b > 10)
+    bar (a + b);
+  else
+    bar (a - b);
+
+  if (({ int a; 1;}))
+    bar (0);
+
+  if (auto i = foo (); i > 6)
+    bar (0);
+  else if (i++; i > 8)
+    bar (1);
+}
+
+extern void lock (void);
+
+void
+f2 (int i)
+{
+  if (lock (); i > 10)
+    ++i;
+  else
+    --i;
+}
+
+void
+f3 (int i)
+{
+  switch (i *= 2; auto idx = i)
+    {
+    case 4:
+      bar (3);
+      break;
+    default:
+      break;
+    }
+}
+
+void
+f4 (void)
+{
+  if constexpr (constexpr auto s = sizeof (int); s > 10)
+    foo ();
+}
diff --git a/gcc/testsuite/g++.dg/cpp1z/init-statement3.C b/gcc/testsuite/g++.dg/cpp1z/init-statement3.C
new file mode 100644 (file)
index 0000000..306c801
--- /dev/null
@@ -0,0 +1,32 @@
+// { dg-do run }
+// { dg-options -std=c++1z }
+// Test C++17 selection statements with initializer, side-effects.
+
+int
+main ()
+{
+  int g = 0;
+
+  if (g++; g > 1)
+    __builtin_abort ();
+  if (++g; g > 2)
+    __builtin_abort ();
+  if (g != 2)
+    __builtin_abort ();
+}
+// { dg-do run }
+// { dg-options -std=c++1z }
+// Test C++17 selection statements with initializer, side-effects.
+
+int
+main ()
+{
+  int g = 0;
+
+  if (g++; g > 1)
+    __builtin_abort ();
+  if (++g; g > 2)
+    __builtin_abort ();
+  if (g != 2)
+    __builtin_abort ();
+}
diff --git a/gcc/testsuite/g++.dg/cpp1z/init-statement4.C b/gcc/testsuite/g++.dg/cpp1z/init-statement4.C
new file mode 100644 (file)
index 0000000..2a0a7d0
--- /dev/null
@@ -0,0 +1,118 @@
+// { dg-options -std=c++1z }
+
+extern int foo (void);
+extern void bar (int), die (void);
+
+void
+f (void)
+{
+  if (auto i = foo (); i != -1)
+    bar (1);
+  else
+    die ();
+
+  i = 10; // { dg-error "not declared" }
+}
+
+void
+f2 (void)
+{
+  switch (auto i = foo (); i)
+    {
+    case 0:
+      bar (i + 1);
+      break;
+    case 1:
+      bar (i + 10);
+      break;
+    default:
+      break;
+    }
+
+  i = 10; // { dg-error "not declared" }
+}
+
+void
+f3 (void)
+{
+  if constexpr (constexpr auto i = sizeof (long); i < 2)
+    die ();
+  i = 4; // { dg-error "not declared" }
+}
+
+
+void
+f4 (void)
+{
+  {
+    if (auto i = foo (); i > -1)
+      {
+       if (i > 5)
+         bar (i);
+       if (auto j = foo (); true)
+         j++;
+       j--; // { dg-error "not declared" }
+      }
+    i = 10; // { dg-error "not declared" }
+  }
+  i = 10; // { dg-error "not declared" }
+}
+// { dg-options -std=c++1z }
+
+extern int foo (void);
+extern void bar (int), die (void);
+
+void
+f (void)
+{
+  if (auto i = foo (); i != -1)
+    bar (1);
+  else
+    die ();
+
+  i = 10; // { dg-error "not declared" }
+}
+
+void
+f2 (void)
+{
+  switch (auto i = foo (); i)
+    {
+    case 0:
+      bar (i + 1);
+      break;
+    case 1:
+      bar (i + 10);
+      break;
+    default:
+      break;
+    }
+
+  i = 10; // { dg-error "not declared" }
+}
+
+void
+f3 (void)
+{
+  if constexpr (constexpr auto i = sizeof (long); i < 2)
+    die ();
+  i = 4; // { dg-error "not declared" }
+}
+
+
+void
+f4 (void)
+{
+  {
+    if (auto i = foo (); i > -1)
+      {
+       if (i > 5)
+         bar (i);
+       if (auto j = foo (); true)
+         j++;
+       j--; // { dg-error "not declared" }
+      }
+    i = 10; // { dg-error "not declared" }
+  }
+  i = 10; // { dg-error "not declared" }
+}
diff --git a/gcc/testsuite/g++.dg/cpp1z/init-statement5.C b/gcc/testsuite/g++.dg/cpp1z/init-statement5.C
new file mode 100644 (file)
index 0000000..9445abf
--- /dev/null
@@ -0,0 +1,32 @@
+// Testcase from P0305R1
+// { dg-options -std=c++1z }
+
+enum class status_code { SUCCESS };
+extern int get_value ();
+status_code bar (int);
+status_code do_more_stuff (void);
+
+status_code
+foo ()
+{
+  int n = get_value ();
+  if (status_code c = bar (n); c != status_code::SUCCESS) { return c; }
+  if (status_code c = do_more_stuff (); c != status_code::SUCCESS) { return c; }
+  return status_code::SUCCESS;
+}
+// Testcase from P0305R1
+// { dg-options -std=c++1z }
+
+enum class status_code { SUCCESS };
+extern int get_value ();
+status_code bar (int);
+status_code do_more_stuff (void);
+
+status_code
+foo ()
+{
+  int n = get_value ();
+  if (status_code c = bar (n); c != status_code::SUCCESS) { return c; }
+  if (status_code c = do_more_stuff (); c != status_code::SUCCESS) { return c; }
+  return status_code::SUCCESS;
+}
diff --git a/gcc/testsuite/g++.dg/cpp1z/init-statement6.C b/gcc/testsuite/g++.dg/cpp1z/init-statement6.C
new file mode 100644 (file)
index 0000000..fe6518c
--- /dev/null
@@ -0,0 +1,50 @@
+// Testcase from P0305R1
+// { dg-options -std=c++1z }
+
+#include <string>
+#include <map>
+#include <algorithm>
+
+std::map<int, std::string> m;
+extern int xread (int *);
+extern void publish (int), raise (int);
+
+void
+foo ()
+{
+  if (auto it = m.find (10); it != m.end ()) { std::string s = it->second; }
+  if (char buf[10]; std::fgets(buf, 10, stdin)) { m[0] += buf; }
+  if (int s; int count = xread (&s)) { publish(count); raise(s); }
+
+  const char *s;
+  if (auto keywords = {"if", "for", "while"};
+      std::any_of(keywords.begin(), keywords.end(), [&s](const char* kw) { return s == kw; }))
+    {
+      // whatever
+    }
+}
+// Testcase from P0305R1
+// { dg-options -std=c++1z }
+
+#include <string>
+#include <map>
+#include <algorithm>
+
+std::map<int, std::string> m;
+extern int xread (int *);
+extern void publish (int), raise (int);
+
+void
+foo ()
+{
+  if (auto it = m.find (10); it != m.end ()) { std::string s = it->second; }
+  if (char buf[10]; std::fgets(buf, 10, stdin)) { m[0] += buf; }
+  if (int s; int count = xread (&s)) { publish(count); raise(s); }
+
+  const char *s;
+  if (auto keywords = {"if", "for", "while"};
+      std::any_of(keywords.begin(), keywords.end(), [&s](const char* kw) { return s == kw; }))
+    {
+      // whatever
+    }
+}
diff --git a/gcc/testsuite/g++.dg/cpp1z/init-statement7.C b/gcc/testsuite/g++.dg/cpp1z/init-statement7.C
new file mode 100644 (file)
index 0000000..0b9cb93
--- /dev/null
@@ -0,0 +1,18 @@
+// { dg-do run }
+// { dg-options -std=c++1z }
+
+int
+main ()
+{
+  if (int i = 10, &ir = i; [=]{ return ir; }() != 10)
+    __builtin_abort ();
+}
+// { dg-do run }
+// { dg-options -std=c++1z }
+
+int
+main ()
+{
+  if (int i = 10, &ir = i; [=]{ return ir; }() != 10)
+    __builtin_abort ();
+}
diff --git a/gcc/testsuite/g++.dg/cpp1z/init-statement8.C b/gcc/testsuite/g++.dg/cpp1z/init-statement8.C
new file mode 100644 (file)
index 0000000..3dccd16
--- /dev/null
@@ -0,0 +1,20 @@
+// { dg-options -std=c++1z }
+
+int
+f ()
+{
+  if (int c = 5;
+      int c = 5) // { dg-error "redeclaration" }
+    return 5;
+  return 0;
+}
+// { dg-options -std=c++1z }
+
+int
+f ()
+{
+  if (int c = 5;
+      int c = 5) // { dg-error "redeclaration" }
+    return 5;
+  return 0;
+}