Skip to content

Commit

Permalink
AST validate unchecked nested blocks (#116)
Browse files Browse the repository at this point in the history
* AST validate unchecked nested blocks

* Update crates/sema/src/ast_passes.rs

Co-authored-by: DaniPopes <57450786+DaniPopes@users.noreply.github.com>

* Update tests/ui/typeck/unchecked_block.sol

Co-authored-by: DaniPopes <57450786+DaniPopes@users.noreply.github.com>

* Fix

* Fix2

* Fix tests

---------

Co-authored-by: DaniPopes <57450786+DaniPopes@users.noreply.github.com>
  • Loading branch information
ferranbt and DaniPopes authored Nov 14, 2024
1 parent b830214 commit f204dca
Show file tree
Hide file tree
Showing 5 changed files with 44 additions and 7 deletions.
17 changes: 14 additions & 3 deletions crates/sema/src/ast_passes.rs
Original file line number Diff line number Diff line change
Expand Up @@ -24,11 +24,12 @@ struct AstValidator<'sess> {
span: Span,
dcx: &'sess DiagCtxt,
in_loop_depth: u64,
in_unchecked_block: bool,
}

impl<'sess> AstValidator<'sess> {
fn new(sess: &'sess Session) -> Self {
Self { span: Span::DUMMY, dcx: &sess.dcx, in_loop_depth: 0 }
Self { span: Span::DUMMY, dcx: &sess.dcx, in_loop_depth: 0, in_unchecked_block: false }
}

/// Returns the diagnostics context.
Expand Down Expand Up @@ -92,19 +93,29 @@ impl<'ast> Visit<'ast> for AstValidator<'_> {
StmtKind::Break => {
if !self.in_loop() {
self.dcx()
.err("\"break\" has to be in a \"for\" or \"while\" loop.")
.err("'break' has to be in a 'for' or 'while' loop")
.span(stmt.span)
.emit();
}
}
StmtKind::Continue => {
if !self.in_loop() {
self.dcx()
.err("\"continue\" has to be in a \"for\" or \"while\" loop.")
.err("'continue' has to be in a 'for' or 'while' loop")
.span(stmt.span)
.emit();
}
}
StmtKind::UncheckedBlock(block) => {
if self.in_unchecked_block {
self.dcx().err("'unchecked' blocks cannot be nested").span(stmt.span).emit();
}

let prev = self.in_unchecked_block;
self.in_unchecked_block = true;
self.walk_block(block);
self.in_unchecked_block = prev;
}
_ => {}
}
}
Expand Down
4 changes: 2 additions & 2 deletions tests/ui/parser/break_continue_outside_loop.sol
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
contract C {
function f() {
break; //~ ERROR: "break" has to be in a "for" or "while" loop.
continue; //~ ERROR: "continue" has to be in a "for" or "while" loop.
break; //~ ERROR: 'break' has to be in a 'for' or 'while' loop
continue; //~ ERROR: 'continue' has to be in a 'for' or 'while' loop

for (uint256 i = 0; i < 10; i++) {
break;
Expand Down
4 changes: 2 additions & 2 deletions tests/ui/parser/break_continue_outside_loop.stderr
Original file line number Diff line number Diff line change
@@ -1,11 +1,11 @@
error: "break" has to be in a "for" or "while" loop.
error: 'break' has to be in a 'for' or 'while' loop
--> ROOT/tests/ui/parser/break_continue_outside_loop.sol:LL:CC
|
LL | break;
| ^^^^^^
|

error: "continue" has to be in a "for" or "while" loop.
error: 'continue' has to be in a 'for' or 'while' loop
--> ROOT/tests/ui/parser/break_continue_outside_loop.sol:LL:CC
|
LL | continue;
Expand Down
10 changes: 10 additions & 0 deletions tests/ui/typeck/unchecked_block.sol
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
contract C {
function a() public {
unchecked {}

unchecked {
unchecked {} //~ ERROR: 'unchecked' blocks cannot be nested
unchecked {} //~ ERROR: 'unchecked' blocks cannot be nested
}
}
}
16 changes: 16 additions & 0 deletions tests/ui/typeck/unchecked_block.stderr
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
error: 'unchecked' blocks cannot be nested
--> ROOT/tests/ui/typeck/unchecked_block.sol:LL:CC
|
LL | unchecked {}
| ^^^^^^^^^^^^
|

error: 'unchecked' blocks cannot be nested
--> ROOT/tests/ui/typeck/unchecked_block.sol:LL:CC
|
LL | unchecked {}
| ^^^^^^^^^^^^
|

error: aborting due to 2 previous errors

0 comments on commit f204dca

Please sign in to comment.