diff --git a/src/resolver/resolver.cc b/src/resolver/resolver.cc index ba66017ba2..14f5abbdae 100644 --- a/src/resolver/resolver.cc +++ b/src/resolver/resolver.cc @@ -2971,12 +2971,12 @@ bool Resolver::Identifier(ast::IdentifierExpression* expr) { var->users.push_back(expr); set_referenced_from_function_if_needed(var, true); - if (current_block_) { + if (current_statement_) { // If identifier is part of a loop continuing block, make sure it // doesn't refer to a variable that is bypassed by a continue statement // in the loop's body block. if (auto* continuing_block = - current_block_ + current_statement_ ->FindFirstParent()) { auto* loop_block = continuing_block->FindFirstParent(); diff --git a/src/resolver/validation_test.cc b/src/resolver/validation_test.cc index 06cc2bb5d1..1ee8f6f460 100644 --- a/src/resolver/validation_test.cc +++ b/src/resolver/validation_test.cc @@ -615,6 +615,36 @@ TEST_F( "continuing block"); } +TEST_F(ResolverValidationTest, + Stmt_Loop_ContinueInLoopBodySubscopeBeforeDecl_UsageOutsideBlock) { + // loop { + // if (true) { + // continue; // bypasses z decl (if we reach here) + // } + // var z : i32; + // continuing { + // // Must fail even if z is used in an expression that isn't + // // directly contained inside a block. + // if (z < 2) { + // } + // } + // } + + auto error_loc = Source{Source::Location{12, 34}}; + auto* body = Block(If(Expr(true), Block(create())), + Decl(Var("z", ty.i32(), ast::StorageClass::kNone))); + auto* compare = create(ast::BinaryOp::kLessThan, + Expr(error_loc, "z"), Expr(2)); + auto* continuing = Block(If(compare, Block())); + auto* loop_stmt = Loop(body, continuing); + WrapInFunction(loop_stmt); + + EXPECT_FALSE(r()->Resolve()) << r()->error(); + EXPECT_EQ(r()->error(), + "12:34 error: continue statement bypasses declaration of 'z' in " + "continuing block"); +} + TEST_F(ResolverValidationTest, Stmt_Loop_ContinueInLoopBodySubscopeBeforeDecl_UsageInContinuingLoop) { // loop {