diff --git a/spec/compiler/codegen/next_spec.cr b/spec/compiler/codegen/next_spec.cr index 92a5b6f43a49c1de6f4f6e20b2565392430f1ba9..c7570a56ad8913ed09699ae12f5fd64169e6c650 100644 --- a/spec/compiler/codegen/next_spec.cr +++ b/spec/compiler/codegen/next_spec.cr @@ -136,4 +136,22 @@ describe "Code gen: next" do end ").to_i.should eq(30) end + + it "codegens next without expressions" do + run(" + struct Nil; def to_i; 0; end; end + + def foo + yield + end + + foo do + if 1 == 1 + 1 + else + next + end + end.to_i + ").to_i.should eq(1) + end end diff --git a/src/compiler/crystal/codegen.cr b/src/compiler/crystal/codegen.cr index 512500677e7ad1b874cfd7c568872eb1c44fabdb..4325bcccb9e6f15c7f929ef4ef2405c3af5d6f62 100644 --- a/src/compiler/crystal/codegen.cr +++ b/src/compiler/crystal/codegen.cr @@ -783,7 +783,9 @@ module Crystal false end - def end_visit(node : Return) + def visit(node : Return) + node_type = accept_control_expression(node) + if handler = @exception_handlers.last? if node_ensure = handler.node.ensure old_last = @last @@ -795,7 +797,9 @@ module Crystal end end - context.return_phi.add @last, control_expression_type(node) + context.return_phi.add @last, node_type + + false end def visit(node : ClassDef) @@ -892,14 +896,10 @@ module Crystal end def visit(node : Break) - if node.exps.empty? - @last = llvm_nil - else - accept node.exps.first - end + node_type = accept_control_expression(node) if break_phi = context.break_phi - break_phi.add @last, control_expression_type(node) + break_phi.add @last, node_type elsif while_exit_block = context.while_exit_block br while_exit_block else @@ -909,18 +909,29 @@ module Crystal false end - def end_visit(node : Next) + def visit(node : Next) + node_type = accept_control_expression(node) + if next_phi = context.next_phi - next_phi.add @last, control_expression_type(node) + next_phi.add @last, node_type elsif while_block = context.while_block br while_block else node.raise "Bug: unknown exit for next" end + + false end - def control_expression_type(node) - node.exps.first?.try &.type? || @mod.nil + def accept_control_expression(node) + if node.exps.empty? + @last = llvm_nil + @mod.nil + else + exp = node.exps.first + accept exp + exp.type? + end end def visit(node : Assign)