validation: Fix continue-bypasses-decl check
An expression that is inside an if-statement condition does not have a "current block", which is what we were using to see if the usage was inside a continuing block. Use the current statement to find the containing block instead. Fixed: chromium:1251664 Change-Id: Icc808ca1cf6a1b51757da8303901fa5ecb693e83 Reviewed-on: https://dawn-review.googlesource.com/c/tint/+/65520 Kokoro: Kokoro <noreply+kokoro@google.com> Reviewed-by: Ben Clayton <bclayton@google.com>
This commit is contained in:
parent
1ca6fbad8f
commit
7166f6ba93
|
@ -2971,12 +2971,12 @@ bool Resolver::Identifier(ast::IdentifierExpression* expr) {
|
||||||
var->users.push_back(expr);
|
var->users.push_back(expr);
|
||||||
set_referenced_from_function_if_needed(var, true);
|
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
|
// 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
|
// doesn't refer to a variable that is bypassed by a continue statement
|
||||||
// in the loop's body block.
|
// in the loop's body block.
|
||||||
if (auto* continuing_block =
|
if (auto* continuing_block =
|
||||||
current_block_
|
current_statement_
|
||||||
->FindFirstParent<sem::LoopContinuingBlockStatement>()) {
|
->FindFirstParent<sem::LoopContinuingBlockStatement>()) {
|
||||||
auto* loop_block =
|
auto* loop_block =
|
||||||
continuing_block->FindFirstParent<sem::LoopBlockStatement>();
|
continuing_block->FindFirstParent<sem::LoopBlockStatement>();
|
||||||
|
|
|
@ -615,6 +615,36 @@ TEST_F(
|
||||||
"continuing block");
|
"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<ast::ContinueStatement>())),
|
||||||
|
Decl(Var("z", ty.i32(), ast::StorageClass::kNone)));
|
||||||
|
auto* compare = create<ast::BinaryExpression>(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,
|
TEST_F(ResolverValidationTest,
|
||||||
Stmt_Loop_ContinueInLoopBodySubscopeBeforeDecl_UsageInContinuingLoop) {
|
Stmt_Loop_ContinueInLoopBodySubscopeBeforeDecl_UsageInContinuingLoop) {
|
||||||
// loop {
|
// loop {
|
||||||
|
|
Loading…
Reference in New Issue