From 5528001eca60bb115e6afc94105ecc7b3820eb52 Mon Sep 17 00:00:00 2001 From: Philip Herron Date: Tue, 19 Apr 2022 12:40:39 +0100 Subject: [PATCH] Fix ICE during HIR lowering of ExprWithBlock MatchExpr When we are lowering blocks using the visitor pattern we must use the BaseClass of ExprWithBlock to abstract away the notion that this expr has a block such that we can handle cases like a block expr vs expressions with a block. This makes the usage of hir lowering of match expressions to be recursive, if we had more fine grained visitors in the AST we could fix these types of problems with compile time enforced interfaces. Fixes #858 --- gcc/rust/hir/rust-ast-lower-block.h | 2 + gcc/rust/hir/rust-ast-lower-expr.h | 47 +---------------- gcc/rust/hir/rust-ast-lower.cc | 51 +++++++++++++++++++ .../rust/execute/torture/issue-858.rs | 32 ++++++++++++ 4 files changed, 86 insertions(+), 46 deletions(-) create mode 100644 gcc/testsuite/rust/execute/torture/issue-858.rs diff --git a/gcc/rust/hir/rust-ast-lower-block.h b/gcc/rust/hir/rust-ast-lower-block.h index b14668a78fd..512f4709c6d 100644 --- a/gcc/rust/hir/rust-ast-lower-block.h +++ b/gcc/rust/hir/rust-ast-lower-block.h @@ -191,6 +191,8 @@ public: void visit (AST::WhileLoopExpr &expr) override; + void visit (AST::MatchExpr &expr) override; + private: ASTLoweringExprWithBlock () : ASTLoweringBase (), translated (nullptr), terminated (false) diff --git a/gcc/rust/hir/rust-ast-lower-expr.h b/gcc/rust/hir/rust-ast-lower-expr.h index bb2507039d1..022002e18e2 100644 --- a/gcc/rust/hir/rust-ast-lower-expr.h +++ b/gcc/rust/hir/rust-ast-lower-expr.h @@ -674,52 +674,7 @@ public: void visit (AST::MatchExpr &expr) override { - HIR::Expr *branch_value - = ASTLoweringExpr::translate (expr.get_scrutinee_expr ().get ()); - - std::vector match_arms; - for (auto &match_case : expr.get_match_cases ()) - { - HIR::Expr *kase_expr - = ASTLoweringExpr::translate (match_case.get_expr ().get ()); - - HIR::Expr *kase_guard_expr = nullptr; - if (match_case.get_arm ().has_match_arm_guard ()) - { - kase_guard_expr = ASTLoweringExpr::translate ( - match_case.get_arm ().get_guard_expr ().get ()); - } - - std::vector > match_arm_patterns; - for (auto &pattern : match_case.get_arm ().get_patterns ()) - { - HIR::Pattern *ptrn = ASTLoweringPattern::translate (pattern.get ()); - match_arm_patterns.push_back (std::unique_ptr (ptrn)); - } - - HIR::MatchArm arm (std::move (match_arm_patterns), expr.get_locus (), - std::unique_ptr (kase_guard_expr), - match_case.get_arm ().get_outer_attrs ()); - - auto crate_num = mappings->get_current_crate (); - Analysis::NodeMapping mapping (crate_num, expr.get_node_id (), - mappings->get_next_hir_id (crate_num), - UNKNOWN_LOCAL_DEFID); - - HIR::MatchCase kase (std::move (mapping), std::move (arm), - std::unique_ptr (kase_expr)); - match_arms.push_back (std::move (kase)); - } - - auto crate_num = mappings->get_current_crate (); - Analysis::NodeMapping mapping (crate_num, expr.get_node_id (), - mappings->get_next_hir_id (crate_num), - UNKNOWN_LOCAL_DEFID); - - translated - = new HIR::MatchExpr (mapping, std::unique_ptr (branch_value), - std::move (match_arms), expr.get_inner_attrs (), - expr.get_outer_attrs (), expr.get_locus ()); + translated = ASTLoweringExprWithBlock::translate (&expr, &terminated); } void visit (AST::RangeFromToExpr &expr) override diff --git a/gcc/rust/hir/rust-ast-lower.cc b/gcc/rust/hir/rust-ast-lower.cc index 4a344c9f5ab..64c8f367102 100644 --- a/gcc/rust/hir/rust-ast-lower.cc +++ b/gcc/rust/hir/rust-ast-lower.cc @@ -299,6 +299,57 @@ ASTLoweringExprWithBlock::visit (AST::WhileLoopExpr &expr) expr.get_outer_attrs ()); } +void +ASTLoweringExprWithBlock::visit (AST::MatchExpr &expr) +{ + HIR::Expr *branch_value + = ASTLoweringExpr::translate (expr.get_scrutinee_expr ().get ()); + + std::vector match_arms; + for (auto &match_case : expr.get_match_cases ()) + { + HIR::Expr *kase_expr + = ASTLoweringExpr::translate (match_case.get_expr ().get ()); + + HIR::Expr *kase_guard_expr = nullptr; + if (match_case.get_arm ().has_match_arm_guard ()) + { + kase_guard_expr = ASTLoweringExpr::translate ( + match_case.get_arm ().get_guard_expr ().get ()); + } + + std::vector > match_arm_patterns; + for (auto &pattern : match_case.get_arm ().get_patterns ()) + { + HIR::Pattern *ptrn = ASTLoweringPattern::translate (pattern.get ()); + match_arm_patterns.push_back (std::unique_ptr (ptrn)); + } + + HIR::MatchArm arm (std::move (match_arm_patterns), expr.get_locus (), + std::unique_ptr (kase_guard_expr), + match_case.get_arm ().get_outer_attrs ()); + + auto crate_num = mappings->get_current_crate (); + Analysis::NodeMapping mapping (crate_num, expr.get_node_id (), + mappings->get_next_hir_id (crate_num), + UNKNOWN_LOCAL_DEFID); + + HIR::MatchCase kase (std::move (mapping), std::move (arm), + std::unique_ptr (kase_expr)); + match_arms.push_back (std::move (kase)); + } + + auto crate_num = mappings->get_current_crate (); + Analysis::NodeMapping mapping (crate_num, expr.get_node_id (), + mappings->get_next_hir_id (crate_num), + UNKNOWN_LOCAL_DEFID); + + translated + = new HIR::MatchExpr (mapping, std::unique_ptr (branch_value), + std::move (match_arms), expr.get_inner_attrs (), + expr.get_outer_attrs (), expr.get_locus ()); +} + // rust-ast-lower-expr.h void diff --git a/gcc/testsuite/rust/execute/torture/issue-858.rs b/gcc/testsuite/rust/execute/torture/issue-858.rs new file mode 100644 index 00000000000..5a43f3e1b1a --- /dev/null +++ b/gcc/testsuite/rust/execute/torture/issue-858.rs @@ -0,0 +1,32 @@ +/* { dg-output "Result: 123\n" } */ +extern "C" { + fn printf(s: *const i8, ...); +} + +enum Foo { + A, + B(T), +} + +fn main() -> i32 { + let result = Foo::B(123); + + match result { + Foo::A => unsafe { + let a = "A\n\0"; + let b = a as *const str; + let c = b as *const i8; + + printf(c); + }, + Foo::B(x) => unsafe { + let a = "Result: %i\n\0"; + let b = a as *const str; + let c = b as *const i8; + + printf(c, x); + }, + } + + 0 +}