Add implied return; at end of non-value-returning functions. (#2942)

Add validation that every code block in a function is terminated by a sequence of terminating instructions, and that terminators don't appear anywhere else in code blocks.

This required tracking whether we're in a reachable code block. That's done on the fly when we create a new code block; the new `SemanticsNodeBlockId::Unreachable` is used to represent the case where we're not actually creating a code block because we're in unreachable code.
This commit is contained in:
Richard Smith
2023-06-26 15:17:47 -07:00
committed by GitHub
parent 92d73985df
commit 4b69264cb1
76 changed files with 1150 additions and 302 deletions
+16 -9
View File
@@ -469,6 +469,12 @@ auto SemanticsHandleReturnStatement(SemanticsContext& context,
context.AddNode(SemanticsNode::ReturnExpression::Make(
parse_node, context.semantics_ir().GetNode(arg).type_id(), arg));
}
// Switch to a new, unreachable, empty node block. This typically won't
// contain any semantics IR, but it can do if there are statements following
// the `return` statement.
context.node_block_stack().Pop();
context.node_block_stack().PushUnreachable();
return true;
}
@@ -531,15 +537,16 @@ auto SemanticsHandleShortCircuitOperand(SemanticsContext& context,
}
// Create a block for the right-hand side and for the continuation.
auto lhs_block_id = context.node_block_stack().PopForAdd();
auto end_block_id = context.node_block_stack().PushForAdd();
auto rhs_block_id = context.node_block_stack().PushForAdd();
context.AddNodeToBlock(
lhs_block_id,
SemanticsNode::BranchIf::Make(parse_node, rhs_block_id, branch_value_id));
context.AddNodeToBlock(
lhs_block_id, SemanticsNode::BranchWithArg::Make(
parse_node, end_block_id, short_circuit_result_id));
auto rhs_block_id =
context.AddDominatedBlockAndBranchIf(parse_node, branch_value_id);
auto end_block_id = context.AddDominatedBlockAndBranchWithArg(
parse_node, short_circuit_result_id);
// Push the resumption and the right-hand side blocks, and start emitting the
// right-hand operand.
context.node_block_stack().Pop();
context.node_block_stack().Push(end_block_id);
context.node_block_stack().Push(rhs_block_id);
context.AddCurrentCodeBlockToFunction();
// Put the condition back on the stack for SemanticsHandleInfixOperator.