diff --git a/gcc/cp/coroutines.cc b/gcc/cp/coroutines.cc
index edb3b706ddc..2e88fb99d7d 100644
--- a/gcc/cp/coroutines.cc
+++ b/gcc/cp/coroutines.cc
@@ -2586,6 +2586,7 @@ struct susp_frame_data
   bool captures_temporary;	 /* This expr captures temps by ref.  */
   bool needs_truth_if_exp;	 /* We must expand a truth_if expression.  */
   bool has_awaiter_init;	 /* We must handle initializing an awaiter.  */
+  tree *fn_body;		 /* Original function body */
 };
 
 /* If this is an await expression, then count it (both uniquely within the
@@ -3326,6 +3327,33 @@ add_var_to_bind (tree& bind, tree var_type,
   return newvar;
 }
 
+/* Helper to ensure we have at least one bind to add vars to. */
+static bool
+maybe_add_bind(susp_frame_data *awpts, tree *stmt, location_t sloc)
+{
+  /* bind_stack is already asserted to be nonempty */
+  tree &bind = awpts->bind_stack->last();
+  gcc_checking_assert(TREE_CODE (*awpts->fn_body) == BIND_EXPR);
+  if (BIND_EXPR_VARS (bind) != BIND_EXPR_VARS (*awpts->fn_body))
+    {
+      /* Alright, we have a unique (enough) scope, bail early. */
+      return false;
+    }
+
+  /* In this case, we'd be pushing variables to the start of the coroutine
+   * unless we add a new BIND_EXPR here.
+   */
+  tree ifsw_bind = build3_loc (sloc, BIND_EXPR, void_type_node,
+			     NULL, NULL, NULL);
+  BIND_EXPR_BODY (ifsw_bind) = *stmt;
+  *stmt = ifsw_bind;
+  /* We don't push this BIND_EXPR to the walkers bind stack, it will be handled
+   * by a call to cp_walk_tree, since we start the next walk off from this
+   * bind node.
+   */
+  return true;
+}
+
 /* Helper to build and add if (!cond) break;  */
 
 static void
@@ -3456,6 +3484,12 @@ await_statement_walker (tree *stmt, int *do_subtree, void *d)
 	      return NULL_TREE; /* Nothing special to do here.  */
 
 	    gcc_checking_assert (!awpts->bind_stack->is_empty());
+	    location_t sloc = EXPR_LOCATION (IF_COND (if_stmt));
+	    if (maybe_add_bind (awpts, stmt, sloc))
+              {
+		*do_subtree = false; /* Done inside maybe_add_bind. */
+		return cp_walk_tree (stmt, await_statement_walker, awpts, NULL);
+              }
 	    tree& bind_expr = awpts->bind_stack->last ();
 	    tree newvar = add_var_to_bind (bind_expr, boolean_type_node,
 					   "ifcd", awpts->cond_number++);
@@ -3464,7 +3498,6 @@ await_statement_walker (tree *stmt, int *do_subtree, void *d)
 	    if (TREE_CODE (cond_inner) == CLEANUP_POINT_EXPR)
 	      cond_inner = TREE_OPERAND (cond_inner, 0);
 	    add_decl_expr (newvar);
-	    location_t sloc = EXPR_LOCATION (IF_COND (if_stmt));
 	    /* We want to initialize the new variable with the expression
 	       that contains the await(s) and potentially also needs to
 	       have truth_if expressions expanded.  */
@@ -3640,6 +3673,12 @@ await_statement_walker (tree *stmt, int *do_subtree, void *d)
 	      return NULL_TREE; /* Nothing special to do here.  */
 
 	    gcc_checking_assert (!awpts->bind_stack->is_empty());
+	    location_t sloc = EXPR_LOCATION (SWITCH_STMT_COND (sw_stmt));
+	    if (maybe_add_bind (awpts, stmt, sloc))
+              {
+		*do_subtree = false; /* Done inside maybe_add_bind. */
+		return cp_walk_tree (stmt, await_statement_walker, awpts, NULL);
+              }
 	    /* Build a variable to hold the condition, this will be
 		   included in the frame as a local var.  */
 	    tree& bind_expr = awpts->bind_stack->last ();
@@ -3652,7 +3691,6 @@ await_statement_walker (tree *stmt, int *do_subtree, void *d)
 	    tree cond_inner = SWITCH_STMT_COND (sw_stmt);
 	    if (TREE_CODE (cond_inner) == CLEANUP_POINT_EXPR)
 	      cond_inner = TREE_OPERAND (cond_inner, 0);
-	    location_t sloc = EXPR_LOCATION (SWITCH_STMT_COND (sw_stmt));
 	    tree new_s = build2_loc (sloc, INIT_EXPR, sw_type, newvar,
 				     cond_inner);
 	    finish_expr_stmt (new_s);
@@ -4477,7 +4515,8 @@ morph_fn_to_coro (tree orig, tree *resumer, tree *destroyer)
      vars) they will get added to the coro frame along with other locals.  */
   susp_frame_data body_aw_points
     = {&field_list, handle_type, fs_label, NULL, NULL, 0, 0,
-       hash_set<tree> (), NULL, NULL, 0, false, false, false};
+       hash_set<tree> (), NULL, NULL, 0, false, false, false,
+       &fnbody};
   body_aw_points.block_stack = make_tree_vector ();
   body_aw_points.bind_stack = make_tree_vector ();
   body_aw_points.to_replace = make_tree_vector ();
diff --git a/gcc/testsuite/g++.dg/coroutines/pr106188.C b/gcc/testsuite/g++.dg/coroutines/pr106188.C
new file mode 100644
index 00000000000..1de3d4cceca
--- /dev/null
+++ b/gcc/testsuite/g++.dg/coroutines/pr106188.C
@@ -0,0 +1,35 @@
+//  { dg-additional-options "-std=c++20 -w" }
+//  { dg-do run }
+// test case from pr106188, w/o workaround
+#include <coroutine>
+
+struct task {
+  struct promise_type {
+    task get_return_object() { return task{}; }
+    void return_void() {}
+    void unhandled_exception() {}
+    auto initial_suspend() noexcept { return std::suspend_never{}; }
+    auto final_suspend() noexcept { return std::suspend_never{}; }
+  };
+};
+
+struct suspend_and_resume {
+  bool await_ready() const { return false; }
+  void await_suspend(std::coroutine_handle<> h) { h.resume(); }
+  void await_resume() {}
+};
+
+task f() {
+  if (co_await suspend_and_resume{}, false) {}
+}
+
+task g() {
+  switch (co_await suspend_and_resume{}, 0) {
+    default: break;
+  }
+}
+
+int main() {
+  f();
+  g();
+}
