aboutsummaryrefslogtreecommitdiff
path: root/gcc
diff options
context:
space:
mode:
authorPhilip Herron <philip.herron@embecosm.com>2022-04-19 12:40:39 +0100
committerPhilip Herron <philip.herron@embecosm.com>2022-04-19 12:43:21 +0100
commit5528001eca60bb115e6afc94105ecc7b3820eb52 (patch)
tree439c89e149353c1e6c912ec93c06d3a2c47c6136 /gcc
parentd17e0aa7695ddb383e0a4fc43185e2ab42c81703 (diff)
downloadgcc-5528001eca60bb115e6afc94105ecc7b3820eb52.zip
gcc-5528001eca60bb115e6afc94105ecc7b3820eb52.tar.gz
gcc-5528001eca60bb115e6afc94105ecc7b3820eb52.tar.bz2
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
Diffstat (limited to 'gcc')
-rw-r--r--gcc/rust/hir/rust-ast-lower-block.h2
-rw-r--r--gcc/rust/hir/rust-ast-lower-expr.h47
-rw-r--r--gcc/rust/hir/rust-ast-lower.cc51
-rw-r--r--gcc/testsuite/rust/execute/torture/issue-858.rs32
4 files changed, 86 insertions, 46 deletions
diff --git a/gcc/rust/hir/rust-ast-lower-block.h b/gcc/rust/hir/rust-ast-lower-block.h
index b14668a..512f4709 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 bb25070..022002e 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<HIR::MatchCase> 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<std::unique_ptr<HIR::Pattern> > 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<HIR::Pattern> (ptrn));
- }
-
- HIR::MatchArm arm (std::move (match_arm_patterns), expr.get_locus (),
- std::unique_ptr<HIR::Expr> (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<HIR::Expr> (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<HIR::Expr> (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 4a344c9..64c8f36 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<HIR::MatchCase> 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<std::unique_ptr<HIR::Pattern> > 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<HIR::Pattern> (ptrn));
+ }
+
+ HIR::MatchArm arm (std::move (match_arm_patterns), expr.get_locus (),
+ std::unique_ptr<HIR::Expr> (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<HIR::Expr> (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<HIR::Expr> (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 0000000..5a43f3e
--- /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<T> {
+ 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
+}