diff options
author | bors[bot] <26634292+bors[bot]@users.noreply.github.com> | 2021-04-25 15:10:08 +0000 |
---|---|---|
committer | GitHub <noreply@github.com> | 2021-04-25 15:10:08 +0000 |
commit | 041003da86f895ba5b00ae4a683996131d0441bf (patch) | |
tree | a51292d9a0d11909025d31a17b69771b498f7d1f /gcc | |
parent | de9af784e79926d01e8c030e999becc4b8bfad0f (diff) | |
parent | f48c7e87c5b9f7adbce961a0b081f59a5da999ab (diff) | |
download | gcc-041003da86f895ba5b00ae4a683996131d0441bf.zip gcc-041003da86f895ba5b00ae4a683996131d0441bf.tar.gz gcc-041003da86f895ba5b00ae4a683996131d0441bf.tar.bz2 |
Merge #387
387: Don't remove unreachable statements at HIR lowering r=philberty a=lrh2000
This is a legal code segment:
```rust
fn foo() -> i32 {
return 1;
let a = 1;
a
}
```
And this is illegal:
```rust
fn foo() -> i32 {
return 1;
let a = 1.5;
a
}
```
So we shouldn't remove unreachable statements at HIR lowering. We can issue warnings for them, but they need to be kept so that their types can be checked.
*(Original in https://github.com/Rust-GCC/gccrs/pull/364)*
Co-authored-by: lrh2000 <lrh2000@pku.edu.cn>
Diffstat (limited to 'gcc')
-rw-r--r-- | gcc/rust/ast/rust-stmt.h | 4 | ||||
-rw-r--r-- | gcc/rust/hir/rust-ast-lower.cc | 25 | ||||
-rw-r--r-- | gcc/testsuite/rust.test/compile/deadcode2.rs | 10 | ||||
-rw-r--r-- | gcc/testsuite/rust.test/xfail_compile/deadcode_err1.rs | 11 | ||||
-rw-r--r-- | gcc/testsuite/rust.test/xfail_compile/deadcode_err2.rs | 16 |
5 files changed, 50 insertions, 16 deletions
diff --git a/gcc/rust/ast/rust-stmt.h b/gcc/rust/ast/rust-stmt.h index 7294677..61854a0 100644 --- a/gcc/rust/ast/rust-stmt.h +++ b/gcc/rust/ast/rust-stmt.h @@ -38,6 +38,8 @@ public: EmptyStmt (Location locus) : locus (locus) {} + Location get_locus_slow () const final override { return get_locus (); } + Location get_locus () const { return locus; } void accept_vis (ASTVisitor &vis) override; @@ -135,6 +137,8 @@ public: LetStmt (LetStmt &&other) = default; LetStmt &operator= (LetStmt &&other) = default; + Location get_locus_slow () const final override { return get_locus (); } + Location get_locus () const { return locus; } void accept_vis (ASTVisitor &vis) override; diff --git a/gcc/rust/hir/rust-ast-lower.cc b/gcc/rust/hir/rust-ast-lower.cc index 86b10d5..7ba5d32 100644 --- a/gcc/rust/hir/rust-ast-lower.cc +++ b/gcc/rust/hir/rust-ast-lower.cc @@ -71,26 +71,16 @@ ASTLoweringBlock::visit (AST::BlockExpr &expr) std::vector<std::unique_ptr<HIR::Stmt> > block_stmts; bool block_did_terminate = false; expr.iterate_stmts ([&] (AST::Stmt *s) mutable -> bool { + if (block_did_terminate) + rust_warning_at (s->get_locus_slow (), 0, "unreachable statement"); + bool terminated = false; auto translated_stmt = ASTLoweringStmt::translate (s, &terminated); block_stmts.push_back (std::unique_ptr<HIR::Stmt> (translated_stmt)); - block_did_terminate = terminated; - return !block_did_terminate; - }); - - // if there was a return expression everything after that becomes - // unreachable code. This can be detected for any AST NodeIDs that have no - // associated HIR Mappings - expr.iterate_stmts ([&] (AST::Stmt *s) -> bool { - HirId ref; - if (!mappings->lookup_node_to_hir (mappings->get_current_crate (), - s->get_node_id (), &ref)) - rust_warning_at (s->get_locus_slow (), 0, "unreachable statement"); - + block_did_terminate |= terminated; return true; }); - bool tail_reachable = !block_did_terminate; if (expr.has_tail_expr () && block_did_terminate) { // warning unreachable tail expressions @@ -101,10 +91,13 @@ ASTLoweringBlock::visit (AST::BlockExpr &expr) HIR::ExprWithoutBlock *tail_expr = nullptr; if (expr.has_tail_expr ()) { - tail_expr = (HIR::ExprWithoutBlock *) ASTLoweringExpr::translate ( - expr.get_tail_expr ().get ()); + bool terminated = false; + tail_expr = (HIR::ExprWithoutBlock *) + ASTLoweringExpr::translate (expr.get_tail_expr ().get (), &terminated); + block_did_terminate |= terminated; } + bool tail_reachable = !block_did_terminate; auto crate_num = mappings->get_current_crate (); Analysis::NodeMapping mapping (crate_num, expr.get_node_id (), mappings->get_next_hir_id (crate_num), diff --git a/gcc/testsuite/rust.test/compile/deadcode2.rs b/gcc/testsuite/rust.test/compile/deadcode2.rs new file mode 100644 index 0000000..ba7d5f0 --- /dev/null +++ b/gcc/testsuite/rust.test/compile/deadcode2.rs @@ -0,0 +1,10 @@ +fn foo() -> i32 { + return 1; + + let a = -1; // { dg-warning "unreachable statement" } + a // { dg-warning "unreachable expression" } +} + +fn main() { + foo(); +} diff --git a/gcc/testsuite/rust.test/xfail_compile/deadcode_err1.rs b/gcc/testsuite/rust.test/xfail_compile/deadcode_err1.rs new file mode 100644 index 0000000..8283231 --- /dev/null +++ b/gcc/testsuite/rust.test/xfail_compile/deadcode_err1.rs @@ -0,0 +1,11 @@ +fn foo() -> i32 { + return 1; + + let mut a = 1; // { dg-warning "unreachable statement" } + a = 1.1; // { dg-warning "unreachable statement" } + // { dg-error "expected .<integer>. got .<float>." "" { target { *-*-* } } .-1 } +} + +fn main() { + foo(); +} diff --git a/gcc/testsuite/rust.test/xfail_compile/deadcode_err2.rs b/gcc/testsuite/rust.test/xfail_compile/deadcode_err2.rs new file mode 100644 index 0000000..8c0eb46 --- /dev/null +++ b/gcc/testsuite/rust.test/xfail_compile/deadcode_err2.rs @@ -0,0 +1,16 @@ +fn foo() -> i32 { + return 1; + return 1.5; // { dg-error "expected .i32. got .<float>." } + // { dg-warning "unreachable statement" "" { target *-*-* } .-1 } +} + +fn bar() -> i32 { + return 1.5; // { dg-error "expected .i32. got .<float>." } + return 1; + // { dg-warning "unreachable statement" "" { target *-*-* } .-1 } +} + +fn main() { + foo(); + bar(); +} |