aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorPhilip Herron <philip.herron@embecosm.com>2021-02-08 10:12:43 +0000
committerPhilip Herron <herron.philip@googlemail.com>2021-02-09 09:46:54 +0000
commit9f3ddb35959606cbf7059362acfc27a9966ac3d4 (patch)
tree3cb0dd2a04c8d2166266a6bea55f285ba88a4625
parent0ccc245a06e434df2c98d7f9d6036c03e4038842 (diff)
downloadgcc-9f3ddb35959606cbf7059362acfc27a9966ac3d4.zip
gcc-9f3ddb35959606cbf7059362acfc27a9966ac3d4.tar.gz
gcc-9f3ddb35959606cbf7059362acfc27a9966ac3d4.tar.bz2
Conditional blocks with else can resolve into a non unit type expression.
When we compile if blocks the else gives us a final branch that can resolve. Single IfExpr cannot resolve as there is no final branch. This also fixes a small regression in compiling elif blocks where the gimple body was empty. Fixes #213
-rw-r--r--gcc/rust/backend/rust-compile-expr.h63
-rw-r--r--gcc/rust/typecheck/rust-hir-type-check-expr.h6
-rw-r--r--gcc/testsuite/rust.test/compilable/block_expr3.rs13
-rw-r--r--gcc/testsuite/rust.test/compilable/if_elif_else_expr1.rs13
4 files changed, 80 insertions, 15 deletions
diff --git a/gcc/rust/backend/rust-compile-expr.h b/gcc/rust/backend/rust-compile-expr.h
index 686fb7f..2dabe01 100644
--- a/gcc/rust/backend/rust-compile-expr.h
+++ b/gcc/rust/backend/rust-compile-expr.h
@@ -417,7 +417,6 @@ public:
void visit (HIR::IfExprConseqElse &expr)
{
- // this can be a return expression
TyTy::TyBase *if_type = nullptr;
if (!ctx->get_tyctx ()->lookup_type (expr.get_mappings ().get_hirid (),
&if_type))
@@ -427,27 +426,67 @@ public:
return;
}
- fncontext fnctx = ctx->peek_fn ();
- Bblock *enclosing_scope = ctx->peek_enclosing_scope ();
- Btype *block_type = TyTyResolveCompile::compile (ctx, if_type);
+ Bvariable *tmp = NULL;
+ bool needs_temp = if_type->get_kind () != TyTy::TypeKind::UNIT;
+ if (needs_temp)
+ {
+ fncontext fnctx = ctx->peek_fn ();
+ Bblock *enclosing_scope = ctx->peek_enclosing_scope ();
+ Btype *block_type = TyTyResolveCompile::compile (ctx, if_type);
- bool is_address_taken = false;
- Bstatement *ret_var_stmt = nullptr;
- Bvariable *tmp = ctx->get_backend ()->temporary_variable (
- fnctx.fndecl, enclosing_scope, block_type, NULL, is_address_taken,
- expr.get_locus (), &ret_var_stmt);
- ctx->add_statement (ret_var_stmt);
+ bool is_address_taken = false;
+ Bstatement *ret_var_stmt = nullptr;
+ tmp = ctx->get_backend ()->temporary_variable (
+ fnctx.fndecl, enclosing_scope, block_type, NULL, is_address_taken,
+ expr.get_locus (), &ret_var_stmt);
+ ctx->add_statement (ret_var_stmt);
+ }
auto stmt = CompileConditionalBlocks::compile (&expr, ctx, tmp);
ctx->add_statement (stmt);
- translated = ctx->get_backend ()->var_expression (tmp, expr.get_locus ());
+ if (tmp != NULL)
+ {
+ translated
+ = ctx->get_backend ()->var_expression (tmp, expr.get_locus ());
+ }
}
void visit (HIR::IfExprConseqIf &expr)
{
- auto stmt = CompileConditionalBlocks::compile (&expr, ctx, nullptr);
+ TyTy::TyBase *if_type = nullptr;
+ if (!ctx->get_tyctx ()->lookup_type (expr.get_mappings ().get_hirid (),
+ &if_type))
+ {
+ rust_error_at (expr.get_locus (),
+ "failed to lookup type of IfExprConseqElse");
+ return;
+ }
+
+ Bvariable *tmp = NULL;
+ bool needs_temp = if_type->get_kind () != TyTy::TypeKind::UNIT;
+ if (needs_temp)
+ {
+ fncontext fnctx = ctx->peek_fn ();
+ Bblock *enclosing_scope = ctx->peek_enclosing_scope ();
+ Btype *block_type = TyTyResolveCompile::compile (ctx, if_type);
+
+ bool is_address_taken = false;
+ Bstatement *ret_var_stmt = nullptr;
+ tmp = ctx->get_backend ()->temporary_variable (
+ fnctx.fndecl, enclosing_scope, block_type, NULL, is_address_taken,
+ expr.get_locus (), &ret_var_stmt);
+ ctx->add_statement (ret_var_stmt);
+ }
+
+ auto stmt = CompileConditionalBlocks::compile (&expr, ctx, tmp);
ctx->add_statement (stmt);
+
+ if (tmp != NULL)
+ {
+ translated
+ = ctx->get_backend ()->var_expression (tmp, expr.get_locus ());
+ }
}
void visit (HIR::BlockExpr &expr)
diff --git a/gcc/rust/typecheck/rust-hir-type-check-expr.h b/gcc/rust/typecheck/rust-hir-type-check-expr.h
index e7fa3b3..43e51c8 100644
--- a/gcc/rust/typecheck/rust-hir-type-check-expr.h
+++ b/gcc/rust/typecheck/rust-hir-type-check-expr.h
@@ -610,10 +610,10 @@ public:
void visit (HIR::IfExprConseqIf &expr)
{
TypeCheckExpr::Resolve (expr.get_if_condition ());
- TypeCheckExpr::Resolve (expr.get_if_block ());
- TypeCheckExpr::Resolve (expr.get_conseq_if_expr ());
+ auto if_blk = TypeCheckExpr::Resolve (expr.get_if_block ());
+ auto else_blk = TypeCheckExpr::Resolve (expr.get_conseq_if_expr ());
- infered = new TyTy::UnitType (expr.get_mappings ().get_hirid ());
+ infered = if_blk->combine (else_blk);
}
void visit (HIR::BlockExpr &expr);
diff --git a/gcc/testsuite/rust.test/compilable/block_expr3.rs b/gcc/testsuite/rust.test/compilable/block_expr3.rs
new file mode 100644
index 0000000..a8b2f27
--- /dev/null
+++ b/gcc/testsuite/rust.test/compilable/block_expr3.rs
@@ -0,0 +1,13 @@
+fn main() {
+ let x = 111;
+
+ let a = {
+ if x == 10 {
+ 123
+ } else if x < 10 {
+ 456
+ } else {
+ 789
+ }
+ };
+}
diff --git a/gcc/testsuite/rust.test/compilable/if_elif_else_expr1.rs b/gcc/testsuite/rust.test/compilable/if_elif_else_expr1.rs
new file mode 100644
index 0000000..eda6d17
--- /dev/null
+++ b/gcc/testsuite/rust.test/compilable/if_elif_else_expr1.rs
@@ -0,0 +1,13 @@
+fn test(x: i32) -> i32 {
+ if x == 10 {
+ 123
+ } else if x < 10 {
+ 456
+ } else {
+ 789
+ }
+}
+
+fn main() {
+ let a = test(1);
+}