Tested on x86_64-pc-linux-gnu, no regression.

OK for trunk?

TIA, have a lovely day.
---------- >8 ----------
Previously, we were building and inserting case_labels manually, which
lead to them not being added into the currently running switch via
c_add_case_label.  This lead to false diagnostics that the user could
not act on.

The use of temp_override on current_function_decl is a temporary hack,
as we intend to factor out generating the outlined functions (including
the actor) to happen later in finish_function, when we can create a new
function using the standard routines for that, similar to
finish_function_contracts.

PR c++/109867 - -Wswitch-default reports missing default in coroutine

gcc/cp/ChangeLog:

        PR c++/109867
        * coroutines.cc (expand_one_await_expression): Replace uses of
        build_case_label with finish_case_label.
        (build_actor_fn): Ditto.  Also adjust current_function_decl.
        (create_anon_label_with_ctx): Remove now-unused function.

gcc/testsuite/ChangeLog:

        PR c++/109867
        * g++.dg/coroutines/torture/pr109867.C: New test.
---
 gcc/cp/coroutines.cc                          | 57 +++++--------------
 .../g++.dg/coroutines/torture/pr109867.C      | 23 ++++++++
 2 files changed, 38 insertions(+), 42 deletions(-)
 create mode 100644 gcc/testsuite/g++.dg/coroutines/torture/pr109867.C

diff --git a/gcc/cp/coroutines.cc b/gcc/cp/coroutines.cc
index 91bbe6b0a0eb..9e8382269ed0 100644
--- a/gcc/cp/coroutines.cc
+++ b/gcc/cp/coroutines.cc
@@ -1629,22 +1629,8 @@ coro_build_artificial_var (location_t loc, const char 
*name, tree type,
                                    type, ctx, init);
 }
 
-/* Helpers for label creation:
-   1. Create a named label in the specified context.  */
 
-static tree
-create_anon_label_with_ctx (location_t loc, tree ctx)
-{
-  tree lab = build_decl (loc, LABEL_DECL, NULL_TREE, void_type_node);
-
-  DECL_CONTEXT (lab) = ctx;
-  DECL_ARTIFICIAL (lab) = true;
-  DECL_IGNORED_P (lab) = true;
-  TREE_USED (lab) = true;
-  return lab;
-}
-
-/*  2. Create a named label in the specified context.  */
+/* Creates a named label in the specified context.  */
 
 static tree
 create_named_label_with_ctx (location_t loc, const char *name, tree ctx)
@@ -1856,22 +1842,16 @@ expand_one_await_expression (tree *stmt, tree 
*await_expr, void *d)
                                    data->coro_fp);
   r = cp_build_init_expr (cond, r);
   finish_switch_cond (r, sw);
-  r = build_case_label (integer_zero_node, NULL_TREE,
-                       create_anon_label_with_ctx (loc, actor));
-  add_stmt (r); /* case 0: */
+  finish_case_label (loc, integer_zero_node, NULL_TREE); /*  case 0: */
   /* Implement the suspend, a scope exit without clean ups.  */
   r = build_call_expr_internal_loc (loc, IFN_CO_SUSPN, void_type_node, 1,
                                    is_cont ? cont : susp);
   r = coro_build_cvt_void_expr_stmt (r, loc);
   add_stmt (r); /*   goto ret;  */
-  r = build_case_label (integer_one_node, NULL_TREE,
-                       create_anon_label_with_ctx (loc, actor));
-  add_stmt (r); /* case 1:  */
+  finish_case_label (loc, integer_one_node, NULL_TREE); /*  case 1:  */
   r = build1_loc (loc, GOTO_EXPR, void_type_node, resume_label);
   add_stmt (r); /*  goto resume;  */
-  r = build_case_label (NULL_TREE, NULL_TREE,
-                       create_anon_label_with_ctx (loc, actor));
-  add_stmt (r); /* default:;  */
+  finish_case_label (loc, NULL_TREE, NULL_TREE); /* default:;  */
   r = build1_loc (loc, GOTO_EXPR, void_type_node, destroy_label);
   add_stmt (r); /* goto destroy;  */
 
@@ -2250,6 +2230,9 @@ build_actor_fn (location_t loc, tree coro_frame_type, 
tree actor, tree fnbody,
   tree top_block = make_node (BLOCK);
   BIND_EXPR_BLOCK (actor_bind) = top_block;
 
+  /* From here on, we're generating code for the actor.  */
+  auto cfdo = make_temp_override (current_function_decl, actor);
+
   tree continuation = coro_build_artificial_var (loc, coro_actor_continue_id,
                                                 void_coro_handle_type, actor,
                                                 NULL_TREE);
@@ -2303,9 +2286,7 @@ build_actor_fn (location_t loc, tree coro_frame_type, 
tree actor, tree fnbody,
 
   tree destroy_dispatcher = begin_switch_stmt ();
   finish_switch_cond (rat, destroy_dispatcher);
-  tree ddeflab = build_case_label (NULL_TREE, NULL_TREE,
-                                  create_anon_label_with_ctx (loc, actor));
-  add_stmt (ddeflab);
+  tree ddeflab = finish_case_label (loc, NULL_TREE, NULL_TREE);
   tree b = build_call_expr_loc (loc, builtin_decl_explicit (BUILT_IN_TRAP), 0);
   b = coro_build_cvt_void_expr_stmt (b, loc);
   add_stmt (b);
@@ -2316,18 +2297,15 @@ build_actor_fn (location_t loc, tree coro_frame_type, 
tree actor, tree fnbody,
      frame itself.  */
   tree del_promise_label
     = create_named_label_with_ctx (loc, "coro.delete.promise", actor);
-  b = build_case_label (build_int_cst (short_unsigned_type_node, 1), NULL_TREE,
-                       create_anon_label_with_ctx (loc, actor));
-  add_stmt (b);
+  finish_case_label (loc, build_int_cst (short_unsigned_type_node, 1),
+                    NULL_TREE);
   add_stmt (build_stmt (loc, GOTO_EXPR, del_promise_label));
 
   short unsigned lab_num = 3;
   for (unsigned destr_pt = 0; destr_pt < body_count; destr_pt++)
     {
       tree l_num = build_int_cst (short_unsigned_type_node, lab_num);
-      b = build_case_label (l_num, NULL_TREE,
-                           create_anon_label_with_ctx (loc, actor));
-      add_stmt (b);
+      finish_case_label (loc, l_num, NULL_TREE);
       b = build_call_expr_internal_loc (loc, IFN_CO_ACTOR, void_type_node, 1,
                                        l_num);
       b = coro_build_cvt_void_expr_stmt (b, loc);
@@ -2345,15 +2323,12 @@ build_actor_fn (location_t loc, tree coro_frame_type, 
tree actor, tree fnbody,
 
   tree dispatcher = begin_switch_stmt ();
   finish_switch_cond (rat, dispatcher);
-  b = build_case_label (build_int_cst (short_unsigned_type_node, 0), NULL_TREE,
-                       create_anon_label_with_ctx (loc, actor));
-  add_stmt (b);
+  finish_case_label (loc, build_int_cst (short_unsigned_type_node, 0),
+                    NULL_TREE);
   b = build1 (GOTO_EXPR, void_type_node, actor_begin_label);
   add_stmt (b);
 
-  tree rdeflab = build_case_label (NULL_TREE, NULL_TREE,
-                                  create_anon_label_with_ctx (loc, actor));
-  add_stmt (rdeflab);
+  tree rdeflab = finish_case_label (loc, NULL_TREE, NULL_TREE);
   b = build_call_expr_loc (loc, builtin_decl_explicit (BUILT_IN_TRAP), 0);
   b = coro_build_cvt_void_expr_stmt (b, loc);
   add_stmt (b);
@@ -2365,9 +2340,7 @@ build_actor_fn (location_t loc, tree coro_frame_type, 
tree actor, tree fnbody,
   for (unsigned resu_pt = 0; resu_pt < body_count; resu_pt++)
     {
       tree l_num = build_int_cst (short_unsigned_type_node, lab_num);
-      b = build_case_label (l_num, NULL_TREE,
-                           create_anon_label_with_ctx (loc, actor));
-      add_stmt (b);
+      finish_case_label (loc, l_num, NULL_TREE);
       b = build_call_expr_internal_loc (loc, IFN_CO_ACTOR, void_type_node, 1,
                                        l_num);
       b = coro_build_cvt_void_expr_stmt (b, loc);
diff --git a/gcc/testsuite/g++.dg/coroutines/torture/pr109867.C 
b/gcc/testsuite/g++.dg/coroutines/torture/pr109867.C
new file mode 100644
index 000000000000..d4663771ea40
--- /dev/null
+++ b/gcc/testsuite/g++.dg/coroutines/torture/pr109867.C
@@ -0,0 +1,23 @@
+// https://gcc.gnu.org/PR109867
+// { dg-additional-options "-Werror=switch-default" }
+#include <coroutine>
+
+struct task
+{
+    struct promise_type
+    {
+        std::suspend_always initial_suspend();
+        std::suspend_always final_suspend() noexcept;
+        void unhandled_exception();
+        task get_return_object();
+        void return_value(int);
+    };
+};
+
+int main()
+{
+    auto t = []() -> task
+    {
+        co_return 2;
+    }();
+}
-- 
2.45.2

Reply via email to