From f48c7e87c5b9f7adbce961a0b081f59a5da999ab Mon Sep 17 00:00:00 2001 From: lrh2000 Date: Fri, 16 Apr 2021 07:54:34 +0800 Subject: [PATCH] Don't remove unreachable statements at HIR lowering --- gcc/rust/ast/rust-stmt.h | 4 +++ gcc/rust/hir/rust-ast-lower.cc | 25 +++++++------------ gcc/testsuite/rust.test/compile/deadcode2.rs | 10 ++++++++ .../rust.test/xfail_compile/deadcode_err1.rs | 11 ++++++++ .../rust.test/xfail_compile/deadcode_err2.rs | 16 ++++++++++++ 5 files changed, 50 insertions(+), 16 deletions(-) create mode 100644 gcc/testsuite/rust.test/compile/deadcode2.rs create mode 100644 gcc/testsuite/rust.test/xfail_compile/deadcode_err1.rs create mode 100644 gcc/testsuite/rust.test/xfail_compile/deadcode_err2.rs diff --git a/gcc/rust/ast/rust-stmt.h b/gcc/rust/ast/rust-stmt.h index 72946774a1f3..61854a07cefc 100644 --- a/gcc/rust/ast/rust-stmt.h +++ b/gcc/rust/ast/rust-stmt.h @@ -38,6 +38,8 @@ class EmptyStmt : public Stmt 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 @@ class LetStmt : public Stmt 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 86b10d5b39c9..7ba5d32607a5 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 > 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 (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 000000000000..ba7d5f015e96 --- /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 000000000000..8283231e45be --- /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 .. got .." "" { 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 000000000000..8c0eb4617a76 --- /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 .." } + // { dg-warning "unreachable statement" "" { target *-*-* } .-1 } +} + +fn bar() -> i32 { + return 1.5; // { dg-error "expected .i32. got .." } + return 1; + // { dg-warning "unreachable statement" "" { target *-*-* } .-1 } +} + +fn main() { + foo(); + bar(); +}