Index: src/Concurrency/Waituntil.cpp
===================================================================
--- src/Concurrency/Waituntil.cpp	(revision d464b791d5bd75566b03d39595db6a7a316a6884)
+++ src/Concurrency/Waituntil.cpp	(revision 70f97c8afc8f67948e201bda2e96e6de8bd31a31)
@@ -142,4 +142,5 @@
     UniqueName namer_target = "__clause_target_"s;
     UniqueName namer_when = "__when_cond_"s;
+    UniqueName namer_label = "__waituntil_label_"s;
 
     string idxName = "__CFA_clause_idx_";
@@ -173,5 +174,5 @@
     void addPredicates( const WaitUntilStmt * stmt, string & satName, string & runName );
     void setUpClause( const WhenClause * clause, ClauseData * data, string & pCountName, CompoundStmt * body );
-    ForStmt * genStatusCheckFor( const WaitUntilStmt * stmt, vector<ClauseData *> & clauseData, string & predName );
+    CompoundStmt * genStatusCheckFor( const WaitUntilStmt * stmt, vector<ClauseData *> & clauseData, string & predName );
     Expr * genSelectTraitCall( const WhenClause * clause, const ClauseData * data, string fnName );
     CompoundStmt * genStmtBlock( const WhenClause * clause, const ClauseData * data );
@@ -653,7 +654,9 @@
     }
 }*/
-ForStmt * GenerateWaitUntilCore::genStatusCheckFor( const WaitUntilStmt * stmt, vector<ClauseData *> & clauseData, string & predName ) {
+CompoundStmt * GenerateWaitUntilCore::genStatusCheckFor( const WaitUntilStmt * stmt, vector<ClauseData *> & clauseData, string & predName ) {
     CompoundStmt * ifBody = new CompoundStmt( stmt->location );
     const CodeLocation & loc = stmt->location;
+
+    string switchLabel = namer_label.newName();
 
     /* generates:
@@ -707,5 +710,5 @@
                                 )
                             ),
-                            new BranchStmt( cLoc, BranchStmt::Kind::Break, Label( cLoc ) )
+                            new BranchStmt( cLoc, BranchStmt::Kind::Break, Label( cLoc, switchLabel ) )
                         }
                     )
@@ -719,5 +722,6 @@
         new SwitchStmt( loc,
             new NameExpr( loc, idxName ),
-            std::move( switchCases )
+            std::move( switchCases ),
+            { Label( loc, switchLabel ) }
         )
     );
@@ -744,5 +748,8 @@
     );
 
-    return new ForStmt( loc,
+    string forLabel = namer_label.newName();
+
+    // we hoist init here so that this pass can happen after hoistdecls pass
+    return new CompoundStmt( loc,
         {
             new DeclStmt( loc,
@@ -752,29 +759,33 @@
                     new SingleInit( loc, ConstantExpr::from_int( loc, 0 ) )
                 )
-            )
-        },  // inits
-        new UntypedExpr ( loc,
-            new NameExpr( loc, "?<?" ),
-            {
-                new NameExpr( loc, idxName ),
-                ConstantExpr::from_int( loc, stmt->clauses.size() )
-            }
-        ),  // cond
-        new UntypedExpr ( loc,
-            new NameExpr( loc, "?++" ),
-            { new NameExpr( loc, idxName ) }
-        ),  // inc
-        new CompoundStmt( loc,
-            {
-                new IfStmt( loc,
-                    new UntypedExpr ( loc,
-                        new NameExpr( loc, predName ),
-                        { new NameExpr( loc, clauseData.at(0)->statusName ) }
-                    ),
-                    new BranchStmt( loc, BranchStmt::Kind::Break, Label( loc ) )
-                ),
-                ifSwitch
-            }
-        )   // body
+            ),
+            new ForStmt( loc,
+                {},  // inits
+                new UntypedExpr ( loc,
+                    new NameExpr( loc, "?<?" ),
+                    {
+                        new NameExpr( loc, idxName ),
+                        ConstantExpr::from_int( loc, stmt->clauses.size() )
+                    }
+                ),  // cond
+                new UntypedExpr ( loc,
+                    new NameExpr( loc, "?++" ),
+                    { new NameExpr( loc, idxName ) }
+                ),  // inc
+                new CompoundStmt( loc,
+                    {
+                        new IfStmt( loc,
+                            new UntypedExpr ( loc,
+                                new NameExpr( loc, predName ),
+                                { new NameExpr( loc, clauseData.at(0)->statusName ) }
+                            ),
+                            new BranchStmt( loc, BranchStmt::Kind::Break, Label( loc, forLabel ) )
+                        ),
+                        ifSwitch
+                    }
+                ),   // body
+                { Label( loc, forLabel ) }
+            )
+        }
     );
 }
@@ -870,4 +881,14 @@
                         new BasicType( BasicType::Kind::Bool ),
                         new SingleInit( cLoc, ast::deepCopy( stmt->clauses.at(i)->when_cond ) )
+                    )
+                )
+            );
+        else // we reuse the when_cond bools later during unregister so init to false if initially unused
+            body->push_back(
+                new DeclStmt( cLoc,
+                    new ObjectDecl( cLoc,
+                        currClause->whenName,
+                        new BasicType( BasicType::Kind::Bool ),
+                        new SingleInit( cLoc, ConstantExpr::from_bool( cLoc, false ) )
                     )
                 )
@@ -1277,16 +1298,25 @@
     }
 
+    // Collection of unregister calls on resources to be put in finally clause
+    // for each clause: 
+    // when_cond_i = (!__CFA_has_clause_run( clause_statuses[i] )) && unregister_select( ... , clausei );
+    // OR if when( ... ) defined on resource
+    // if ( when_cond_i ) 
+    //   when_cond_i =  (!__CFA_has_clause_run( clause_statuses[i] )) && unregister_select( ... , clausei );
     CompoundStmt * unregisters = new CompoundStmt( loc );
-    // generates for each clause: 
-    // if ( !has_run( clause_statuses[i] ) ) 
-    // OR if when_cond defined
-    // if ( when_cond_i && !has_run( clause_statuses[i] ) )
-    // body of if is:
-    // { if (unregister_select(A, clause1) && on_selected(A, clause1)) clause1->stmt; } // this conditionally runs the block unregister_select returns true (needed by some primitives)
-    Expr * ifCond;
-    UntypedExpr * statusExpr; // !clause_statuses[i]
+
+    // Collection of optional statement executions following finally clause
+    // for each clause:
+    // if ( when_cond_i ) clausei->stmt;
+    // when_cond_i is repurposed in the finally to store if any statements need to be run after unregisters
+    // the statements need to be run outside a finally clause since they may contain non-local transfers
+    CompoundStmt * unregisterStmts = new CompoundStmt( loc );
+
+    UntypedExpr * statusExpr; // !__CFA_has_clause_run( clause_statuses[i] )
+    ExprStmt * assignStmt; // when_cond_i = (!__CFA_has_clause_run( clause_statuses[i] )) && unregister_select( ... , clausei );
     for ( int i = 0; i < numClauses; i++ ) {
         const CodeLocation & cLoc = stmt->clauses.at(i)->location;
 
+        // Generates: !__CFA_has_clause_run( clause_statuses[i] )
         statusExpr = new UntypedExpr ( cLoc,
             new NameExpr( cLoc, "!?" ),
@@ -1300,34 +1330,38 @@
             }
         );
-
-        if ( stmt->clauses.at(i)->when_cond ) {
-            // generates: if( when_cond_i && !has_run(clause_statuses[i]) )
-            ifCond = new LogicalExpr( cLoc,
-                new CastExpr( cLoc,
-                    new NameExpr( cLoc, clauseData.at(i)->whenName ), 
-                    new BasicType( BasicType::Kind::Bool ), GeneratedFlag::ExplicitCast 
-                ),
-                new CastExpr( cLoc,
-                    statusExpr,
-                    new BasicType( BasicType::Kind::Bool ), GeneratedFlag::ExplicitCast 
-                ),
-                LogicalFlag::AndExpr
+        
+        // Generates:
+        // when_cond_i = (!__CFA_has_clause_run( clause_statuses[i] )) && unregister_select( ... , clausei );
+        assignStmt = new ExprStmt( cLoc, 
+            UntypedExpr::createAssign( cLoc,
+                new NameExpr( cLoc, clauseData.at(i)->whenName ),
+                new LogicalExpr( cLoc,
+                    new CastExpr( cLoc,
+                        statusExpr, 
+                        new BasicType( BasicType::Kind::Bool ), GeneratedFlag::ExplicitCast 
+                    ),
+                    new CastExpr( cLoc,
+                        genSelectTraitCall( stmt->clauses.at(i), clauseData.at(i), "unregister_select" ),
+                        new BasicType( BasicType::Kind::Bool ), GeneratedFlag::ExplicitCast 
+                    ),
+                    LogicalFlag::AndExpr
+                )
+            )
+        );
+
+        if ( stmt->clauses.at(i)->when_cond ) // if ( when_cond_i ) assignStmt
+            unregisters->push_back( 
+                new IfStmt( cLoc,
+                    new NameExpr( cLoc, clauseData.at(i)->whenName ),
+                    new CompoundStmt( cLoc, { assignStmt } )
+                )
             );
-        } else // generates: if( !clause_statuses[i] )
-            ifCond = statusExpr;
-        
-        unregisters->push_back( 
+        else
+            unregisters->push_back( assignStmt );
+
+        unregisterStmts->push_back(
             new IfStmt( cLoc,
-                ifCond,
-                new CompoundStmt( cLoc,
-                    {
-                        new IfStmt( cLoc,
-                            genSelectTraitCall( stmt->clauses.at(i), clauseData.at(i), "unregister_select" ),
-                            // ast::deepCopy( stmt->clauses.at(i)->stmt )
-                            genStmtBlock( stmt->clauses.at(i), clauseData.at(i) )
-                        )
-                    }
-                )
-                
+                new NameExpr( cLoc, clauseData.at(i)->whenName ),
+                genStmtBlock( stmt->clauses.at(i), clauseData.at(i) )
             )
         );
@@ -1342,4 +1376,7 @@
         )
     );
+
+    body->push_back( unregisterStmts );
+    
 
     for ( ClauseData * datum : clauseData )
