tint: Resolve empty loop continuing blocks

Otherwise, calling `Sem().Get()` on an empty loop continuing block
will return nullptr, which causes issues when inspecting the semantic
information of ast::BlockStatement nodes generically.

Change-Id: Ib3665b750c96eda02355fa879cf6300b8d69293a
Reviewed-on: https://dawn-review.googlesource.com/c/dawn/+/89721
Kokoro: Kokoro <noreply+kokoro@google.com>
Reviewed-by: Ben Clayton <bclayton@google.com>
This commit is contained in:
James Price 2022-05-11 13:50:33 +00:00
parent 2cf32b13d7
commit 8e68f0aad7
2 changed files with 37 additions and 10 deletions

View File

@ -144,6 +144,35 @@ TEST_F(ResolverCompoundStatementTest, Loop) {
} }
} }
TEST_F(ResolverCompoundStatementTest, Loop_EmptyContinuing) {
// fn F() {
// loop {
// break;
// continuing {
// }
// }
// }
auto* brk = Break();
auto* loop = Loop(Block(brk), Block());
Func("F", {}, ty.void_(), {loop});
ASSERT_TRUE(r()->Resolve()) << r()->error();
{
auto* s = Sem().Get(loop);
ASSERT_NE(s, nullptr);
EXPECT_TRUE(s->Is<sem::LoopStatement>());
EXPECT_EQ(s->Parent(), s->FindFirstParent<sem::FunctionBlockStatement>());
EXPECT_EQ(s->Parent(), s->Block());
}
{
auto* s = Sem().Get(loop->continuing);
ASSERT_NE(s, nullptr);
EXPECT_TRUE(Is<sem::LoopContinuingBlockStatement>(s));
EXPECT_TRUE(Is<sem::LoopStatement>(s->Parent()->Parent()));
}
}
TEST_F(ResolverCompoundStatementTest, ForLoop) { TEST_F(ResolverCompoundStatementTest, ForLoop) {
// fn F() { // fn F() {
// for (var i : u32; true; i = i + 1u) { // for (var i : u32; true; i = i + 1u) {

View File

@ -935,17 +935,15 @@ sem::LoopStatement* Resolver::LoopStatement(const ast::LoopStatement* stmt) {
if (stmt->continuing) { if (stmt->continuing) {
Mark(stmt->continuing); Mark(stmt->continuing);
if (!stmt->continuing->Empty()) { auto* continuing = StatementScope(
auto* continuing = StatementScope( stmt->continuing,
stmt->continuing, builder_->create<sem::LoopContinuingBlockStatement>(
builder_->create<sem::LoopContinuingBlockStatement>( stmt->continuing, current_compound_statement_, current_function_),
stmt->continuing, current_compound_statement_, current_function_), [&] { return Statements(stmt->continuing->statements); });
[&] { return Statements(stmt->continuing->statements); }); if (!continuing) {
if (!continuing) { return false;
return false;
}
behaviors.Add(continuing->Behaviors());
} }
behaviors.Add(continuing->Behaviors());
} }
if (behaviors.Contains(sem::Behavior::kBreak)) { // Does the loop exit? if (behaviors.Contains(sem::Behavior::kBreak)) { // Does the loop exit?