[resolver] Fix nullptr dereference when validating continuing block

ast::IdentifierExpression nodes can appear outside of functions
(e.g. as initializers for module-scope variables), so we cannot assume
that current_block_ is not nullptr.

We already have several tests that do this, but for some reason the
nullptr dereference does not cause problems on our presubmits.

Change-Id: I612f3eb0d5711a0b1d0bb71663be7cca388b2b3c
Reviewed-on: https://dawn-review.googlesource.com/c/tint/+/45580
Auto-Submit: James Price <jrprice@google.com>
Reviewed-by: Ben Clayton <bclayton@google.com>
Reviewed-by: Antonio Maiorano <amaiorano@google.com>
Commit-Queue: Ben Clayton <bclayton@google.com>
Kokoro: Kokoro <noreply+kokoro@google.com>
This commit is contained in:
James Price 2021-03-22 17:25:56 +00:00 committed by Commit Bot service account
parent 91da97d6c3
commit a07d21acc5
1 changed files with 26 additions and 24 deletions

View File

@ -832,30 +832,32 @@ 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 identifier is part of a loop continuing block, make sure it doesn't if (current_block_) {
// refer to a variable that is bypassed by a continue statement in the // If identifier is part of a loop continuing block, make sure it doesn't
// loop's body block. // refer to a variable that is bypassed by a continue statement in the
if (auto* continuing_block = // loop's body block.
current_block_->FindFirstParent(BlockInfo::Type::kLoopContinuing)) { if (auto* continuing_block = current_block_->FindFirstParent(
auto* loop_block = BlockInfo::Type::kLoopContinuing)) {
continuing_block->FindFirstParent(BlockInfo::Type::kLoop); auto* loop_block =
if (loop_block->first_continue != size_t(~0)) { continuing_block->FindFirstParent(BlockInfo::Type::kLoop);
auto& decls = loop_block->decls; if (loop_block->first_continue != size_t(~0)) {
// If our identifier is in loop_block->decls, make sure its index is auto& decls = loop_block->decls;
// less than first_continue // If our identifier is in loop_block->decls, make sure its index is
auto iter = // less than first_continue
std::find_if(decls.begin(), decls.end(), auto iter = std::find_if(
[&symbol](auto* v) { return v->symbol() == symbol; }); decls.begin(), decls.end(),
if (iter != decls.end()) { [&symbol](auto* v) { return v->symbol() == symbol; });
auto var_decl_index = if (iter != decls.end()) {
static_cast<size_t>(std::distance(decls.begin(), iter)); auto var_decl_index =
if (var_decl_index >= loop_block->first_continue) { static_cast<size_t>(std::distance(decls.begin(), iter));
diagnostics_.add_error( if (var_decl_index >= loop_block->first_continue) {
"continue statement bypasses declaration of '" + diagnostics_.add_error(
builder_->Symbols().NameFor(symbol) + "continue statement bypasses declaration of '" +
"' in continuing block", builder_->Symbols().NameFor(symbol) +
expr->source()); "' in continuing block",
return false; expr->source());
return false;
}
} }
} }
} }