[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);
set_referenced_from_function_if_needed(var, true);
// 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_->FindFirstParent(BlockInfo::Type::kLoopContinuing)) {
auto* loop_block =
continuing_block->FindFirstParent(BlockInfo::Type::kLoop);
if (loop_block->first_continue != size_t(~0)) {
auto& decls = loop_block->decls;
// If our identifier is in loop_block->decls, make sure its index is
// less than first_continue
auto iter =
std::find_if(decls.begin(), decls.end(),
[&symbol](auto* v) { return v->symbol() == symbol; });
if (iter != decls.end()) {
auto var_decl_index =
static_cast<size_t>(std::distance(decls.begin(), iter));
if (var_decl_index >= loop_block->first_continue) {
diagnostics_.add_error(
"continue statement bypasses declaration of '" +
builder_->Symbols().NameFor(symbol) +
"' in continuing block",
expr->source());
return false;
if (current_block_) {
// 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_->FindFirstParent(
BlockInfo::Type::kLoopContinuing)) {
auto* loop_block =
continuing_block->FindFirstParent(BlockInfo::Type::kLoop);
if (loop_block->first_continue != size_t(~0)) {
auto& decls = loop_block->decls;
// If our identifier is in loop_block->decls, make sure its index is
// less than first_continue
auto iter = std::find_if(
decls.begin(), decls.end(),
[&symbol](auto* v) { return v->symbol() == symbol; });
if (iter != decls.end()) {
auto var_decl_index =
static_cast<size_t>(std::distance(decls.begin(), iter));
if (var_decl_index >= loop_block->first_continue) {
diagnostics_.add_error(
"continue statement bypasses declaration of '" +
builder_->Symbols().NameFor(symbol) +
"' in continuing block",
expr->source());
return false;
}
}
}
}