diff --git a/toolchain/diagnostics/diagnostic_kind.def b/toolchain/diagnostics/diagnostic_kind.def index 832a3535fe15..8fb84b6ef4e9 100644 --- a/toolchain/diagnostics/diagnostic_kind.def +++ b/toolchain/diagnostics/diagnostic_kind.def @@ -102,6 +102,7 @@ CARBON_DIAGNOSTIC_KIND(PreviousDefinition) CARBON_DIAGNOSTIC_KIND(NoMatchingCall) CARBON_DIAGNOSTIC_KIND(CallArgCountMismatch) CARBON_DIAGNOSTIC_KIND(CallArgTypeMismatch) +CARBON_DIAGNOSTIC_KIND(MissingReturnStatement) CARBON_DIAGNOSTIC_KIND(ReturnStatementDisallowExpression) CARBON_DIAGNOSTIC_KIND(ReturnStatementImplicitNote) CARBON_DIAGNOSTIC_KIND(ReturnStatementMissingExpression) diff --git a/toolchain/lowering/testdata/function/call/empty_struct.carbon b/toolchain/lowering/testdata/function/call/empty_struct.carbon index 8d83682b0c27..30d8488e84f5 100644 --- a/toolchain/lowering/testdata/function/call/empty_struct.carbon +++ b/toolchain/lowering/testdata/function/call/empty_struct.carbon @@ -22,6 +22,7 @@ // CHECK:STDOUT: %1 = load %StructLiteralType, ptr %StructLiteralValue1, align 1 // CHECK:STDOUT: %Echo = call %StructLiteralType @Echo(%StructLiteralType %1) // CHECK:STDOUT: store %StructLiteralType %Echo, ptr %var, align 1 +// CHECK:STDOUT: ret void // CHECK:STDOUT: } fn Echo(a: {}) -> {} { diff --git a/toolchain/lowering/testdata/function/call/i32.carbon b/toolchain/lowering/testdata/function/call/i32.carbon index 79c2bc6a76ef..d3ebf47fa278 100644 --- a/toolchain/lowering/testdata/function/call/i32.carbon +++ b/toolchain/lowering/testdata/function/call/i32.carbon @@ -16,6 +16,7 @@ // CHECK:STDOUT: %var = alloca i32, align 4 // CHECK:STDOUT: %Echo = call i32 @Echo(i32 1) // CHECK:STDOUT: store i32 %Echo, ptr %var, align 4 +// CHECK:STDOUT: ret void // CHECK:STDOUT: } fn Echo(a: i32) -> i32 { diff --git a/toolchain/lowering/testdata/function/call/params_one.carbon b/toolchain/lowering/testdata/function/call/params_one.carbon index 87f8392c15b8..a1442c908722 100644 --- a/toolchain/lowering/testdata/function/call/params_one.carbon +++ b/toolchain/lowering/testdata/function/call/params_one.carbon @@ -9,10 +9,12 @@ // CHECK:STDOUT: %EmptyTupleType = type {} // CHECK:STDOUT: // CHECK:STDOUT: define %EmptyTupleType @Foo(i32 %a) { +// CHECK:STDOUT: ret void // CHECK:STDOUT: } // CHECK:STDOUT: // CHECK:STDOUT: define %EmptyTupleType @Main() { // CHECK:STDOUT: %Foo = call %EmptyTupleType @Foo(i32 1) +// CHECK:STDOUT: ret void // CHECK:STDOUT: } fn Foo(a: i32) {} diff --git a/toolchain/lowering/testdata/function/call/params_one_comma.carbon b/toolchain/lowering/testdata/function/call/params_one_comma.carbon index c529c36e118d..5c772dd732ca 100644 --- a/toolchain/lowering/testdata/function/call/params_one_comma.carbon +++ b/toolchain/lowering/testdata/function/call/params_one_comma.carbon @@ -9,11 +9,13 @@ // CHECK:STDOUT: %EmptyTupleType = type {} // CHECK:STDOUT: // CHECK:STDOUT: define %EmptyTupleType @Foo(i32 %a) { +// CHECK:STDOUT: ret void // CHECK:STDOUT: } // CHECK:STDOUT: // CHECK:STDOUT: define %EmptyTupleType @Main() { // CHECK:STDOUT: %Foo = call %EmptyTupleType @Foo(i32 1) // CHECK:STDOUT: %Foo1 = call %EmptyTupleType @Foo(i32 1) +// CHECK:STDOUT: ret void // CHECK:STDOUT: } fn Foo(a: i32,) {} diff --git a/toolchain/lowering/testdata/function/call/params_two.carbon b/toolchain/lowering/testdata/function/call/params_two.carbon index c40e4605459d..6182e7931692 100644 --- a/toolchain/lowering/testdata/function/call/params_two.carbon +++ b/toolchain/lowering/testdata/function/call/params_two.carbon @@ -9,10 +9,12 @@ // CHECK:STDOUT: %EmptyTupleType = type {} // CHECK:STDOUT: // CHECK:STDOUT: define %EmptyTupleType @Foo(i32 %a, i32 %b) { +// CHECK:STDOUT: ret void // CHECK:STDOUT: } // CHECK:STDOUT: // CHECK:STDOUT: define %EmptyTupleType @Main() { // CHECK:STDOUT: %Foo = call %EmptyTupleType @Foo(i32 1, i32 2) +// CHECK:STDOUT: ret void // CHECK:STDOUT: } fn Foo(a: i32, b: i32) {} diff --git a/toolchain/lowering/testdata/function/call/params_two_comma.carbon b/toolchain/lowering/testdata/function/call/params_two_comma.carbon index 883024e23a4c..f65ebd4fb7b5 100644 --- a/toolchain/lowering/testdata/function/call/params_two_comma.carbon +++ b/toolchain/lowering/testdata/function/call/params_two_comma.carbon @@ -9,11 +9,13 @@ // CHECK:STDOUT: %EmptyTupleType = type {} // CHECK:STDOUT: // CHECK:STDOUT: define %EmptyTupleType @Foo(i32 %a, i32 %b) { +// CHECK:STDOUT: ret void // CHECK:STDOUT: } // CHECK:STDOUT: // CHECK:STDOUT: define %EmptyTupleType @Main() { // CHECK:STDOUT: %Foo = call %EmptyTupleType @Foo(i32 1, i32 2) // CHECK:STDOUT: %Foo1 = call %EmptyTupleType @Foo(i32 1, i32 2) +// CHECK:STDOUT: ret void // CHECK:STDOUT: } fn Foo(a: i32, b: i32,) {} diff --git a/toolchain/lowering/testdata/function/call/params_zero.carbon b/toolchain/lowering/testdata/function/call/params_zero.carbon index 7c0a6bd3cb2f..f16003c3833c 100644 --- a/toolchain/lowering/testdata/function/call/params_zero.carbon +++ b/toolchain/lowering/testdata/function/call/params_zero.carbon @@ -9,10 +9,12 @@ // CHECK:STDOUT: %EmptyTupleType = type {} // CHECK:STDOUT: // CHECK:STDOUT: define %EmptyTupleType @Foo() { +// CHECK:STDOUT: ret void // CHECK:STDOUT: } // CHECK:STDOUT: // CHECK:STDOUT: define %EmptyTupleType @Main() { // CHECK:STDOUT: %Foo = call %EmptyTupleType @Foo() +// CHECK:STDOUT: ret void // CHECK:STDOUT: } fn Foo() {} diff --git a/toolchain/lowering/testdata/function/call/var_param.carbon b/toolchain/lowering/testdata/function/call/var_param.carbon index 2cac6168de68..66e765a0b2d5 100644 --- a/toolchain/lowering/testdata/function/call/var_param.carbon +++ b/toolchain/lowering/testdata/function/call/var_param.carbon @@ -9,6 +9,7 @@ // CHECK:STDOUT: %EmptyTupleType = type {} // CHECK:STDOUT: // CHECK:STDOUT: define %EmptyTupleType @DoNothing(i32 %a) { +// CHECK:STDOUT: ret void // CHECK:STDOUT: } // CHECK:STDOUT: // CHECK:STDOUT: define %EmptyTupleType @Main() { @@ -16,6 +17,7 @@ // CHECK:STDOUT: store i32 0, ptr %var, align 4 // CHECK:STDOUT: %1 = load i32, ptr %var, align 4 // CHECK:STDOUT: %DoNothing = call %EmptyTupleType @DoNothing(i32 %1) +// CHECK:STDOUT: ret void // CHECK:STDOUT: } fn DoNothing(a: i32) {} diff --git a/toolchain/lowering/testdata/function/definition/empty_struct.carbon b/toolchain/lowering/testdata/function/definition/empty_struct.carbon index 6661561e27d3..a32ae3ab7489 100644 --- a/toolchain/lowering/testdata/function/definition/empty_struct.carbon +++ b/toolchain/lowering/testdata/function/definition/empty_struct.carbon @@ -10,6 +10,7 @@ // CHECK:STDOUT: %StructLiteralType = type {} // CHECK:STDOUT: // CHECK:STDOUT: define %EmptyTupleType @Echo(%StructLiteralType %a) { +// CHECK:STDOUT: ret void // CHECK:STDOUT: } fn Echo(a: {}) { diff --git a/toolchain/lowering/testdata/function/definition/params_one.carbon b/toolchain/lowering/testdata/function/definition/params_one.carbon index ee5842ebaa0d..22fac8ed45ad 100644 --- a/toolchain/lowering/testdata/function/definition/params_one.carbon +++ b/toolchain/lowering/testdata/function/definition/params_one.carbon @@ -9,6 +9,7 @@ // CHECK:STDOUT: %EmptyTupleType = type {} // CHECK:STDOUT: // CHECK:STDOUT: define %EmptyTupleType @Foo(i32 %a) { +// CHECK:STDOUT: ret void // CHECK:STDOUT: } fn Foo(a: i32) {} diff --git a/toolchain/lowering/testdata/function/definition/params_two.carbon b/toolchain/lowering/testdata/function/definition/params_two.carbon index d65d5f612811..6afd53193f5e 100644 --- a/toolchain/lowering/testdata/function/definition/params_two.carbon +++ b/toolchain/lowering/testdata/function/definition/params_two.carbon @@ -9,6 +9,7 @@ // CHECK:STDOUT: %EmptyTupleType = type {} // CHECK:STDOUT: // CHECK:STDOUT: define %EmptyTupleType @Foo(i32 %a, i32 %b) { +// CHECK:STDOUT: ret void // CHECK:STDOUT: } fn Foo(a: i32, b: i32) {} diff --git a/toolchain/lowering/testdata/function/definition/params_zero.carbon b/toolchain/lowering/testdata/function/definition/params_zero.carbon index 32c5109a3b0a..a80bdcde059c 100644 --- a/toolchain/lowering/testdata/function/definition/params_zero.carbon +++ b/toolchain/lowering/testdata/function/definition/params_zero.carbon @@ -9,6 +9,7 @@ // CHECK:STDOUT: %EmptyTupleType = type {} // CHECK:STDOUT: // CHECK:STDOUT: define %EmptyTupleType @Foo() { +// CHECK:STDOUT: ret void // CHECK:STDOUT: } fn Foo() {} diff --git a/toolchain/lowering/testdata/if/else.carbon b/toolchain/lowering/testdata/if/else.carbon index 7b0729f3b276..653679267319 100644 --- a/toolchain/lowering/testdata/if/else.carbon +++ b/toolchain/lowering/testdata/if/else.carbon @@ -9,12 +9,15 @@ // CHECK:STDOUT: %EmptyTupleType = type {} // CHECK:STDOUT: // CHECK:STDOUT: define %EmptyTupleType @F() { +// CHECK:STDOUT: ret void // CHECK:STDOUT: } // CHECK:STDOUT: // CHECK:STDOUT: define %EmptyTupleType @G() { +// CHECK:STDOUT: ret void // CHECK:STDOUT: } // CHECK:STDOUT: // CHECK:STDOUT: define %EmptyTupleType @H() { +// CHECK:STDOUT: ret void // CHECK:STDOUT: } // CHECK:STDOUT: // CHECK:STDOUT: define %EmptyTupleType @If(i1 %b) { @@ -30,6 +33,7 @@ // CHECK:STDOUT: // CHECK:STDOUT: 3: ; preds = %2, %1 // CHECK:STDOUT: %H = call %EmptyTupleType @H() +// CHECK:STDOUT: ret void // CHECK:STDOUT: } fn F() {} diff --git a/toolchain/lowering/testdata/if/no_else.carbon b/toolchain/lowering/testdata/if/no_else.carbon index 44e6c4ca4fb1..4c13e480c1db 100644 --- a/toolchain/lowering/testdata/if/no_else.carbon +++ b/toolchain/lowering/testdata/if/no_else.carbon @@ -9,9 +9,11 @@ // CHECK:STDOUT: %EmptyTupleType = type {} // CHECK:STDOUT: // CHECK:STDOUT: define %EmptyTupleType @F() { +// CHECK:STDOUT: ret void // CHECK:STDOUT: } // CHECK:STDOUT: // CHECK:STDOUT: define %EmptyTupleType @G() { +// CHECK:STDOUT: ret void // CHECK:STDOUT: } // CHECK:STDOUT: // CHECK:STDOUT: define %EmptyTupleType @If(i1 %b) { @@ -23,6 +25,7 @@ // CHECK:STDOUT: // CHECK:STDOUT: 2: ; preds = %1, %0 // CHECK:STDOUT: %G = call %EmptyTupleType @G() +// CHECK:STDOUT: ret void // CHECK:STDOUT: } fn F() {} diff --git a/toolchain/lowering/testdata/return/code_after_return.carbon b/toolchain/lowering/testdata/return/code_after_return.carbon new file mode 100644 index 000000000000..9e7608c3d089 --- /dev/null +++ b/toolchain/lowering/testdata/return/code_after_return.carbon @@ -0,0 +1,24 @@ +// Part of the Carbon Language project, under the Apache License v2.0 with LLVM +// Exceptions. See /LICENSE for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +// AUTOUPDATE +// CHECK:STDOUT: ; ModuleID = 'code_after_return.carbon' +// CHECK:STDOUT: source_filename = "code_after_return.carbon" +// CHECK:STDOUT: +// CHECK:STDOUT: %EmptyTupleType = type {} +// CHECK:STDOUT: +// CHECK:STDOUT: define %EmptyTupleType @F() { +// CHECK:STDOUT: ret void +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: define %EmptyTupleType @Main() { +// CHECK:STDOUT: ret void +// CHECK:STDOUT: } + +fn F() {} + +fn Main() { + return; + F(); +} diff --git a/toolchain/semantics/BUILD b/toolchain/semantics/BUILD index c649ebfbfb77..8e56772bfd71 100644 --- a/toolchain/semantics/BUILD +++ b/toolchain/semantics/BUILD @@ -32,24 +32,12 @@ cc_library( ":semantics_node_kind", "//common:check", "//common:ostream", + "//toolchain/common:index_base", "//toolchain/parser:parse_tree", "@llvm-project//llvm:Support", ], ) -cc_library( - name = "semantics_node_block_stack", - srcs = ["semantics_node_block_stack.cpp"], - hdrs = ["semantics_node_block_stack.h"], - deps = [ - ":semantics_node", - "//common:check", - "//common:ostream", - "//common:vlog", - "@llvm-project//llvm:Support", - ], -) - cc_library( name = "semantics_node_stack", srcs = ["semantics_node_stack.cpp"], @@ -70,6 +58,7 @@ cc_library( srcs = [ "semantics_ir.cpp", "semantics_context.cpp", + "semantics_node_block_stack.cpp", ] + # Glob handler files to avoid missing anyway. glob([ @@ -78,11 +67,11 @@ cc_library( hdrs = [ "semantics_context.h", "semantics_ir.h", + "semantics_node_block_stack.h", ], deps = [ ":semantics_builtin_kind", ":semantics_node", - ":semantics_node_block_stack", ":semantics_node_stack", "//common:check", "//common:ostream", diff --git a/toolchain/semantics/semantics_context.cpp b/toolchain/semantics/semantics_context.cpp index 8d6b6e969fcd..004bfd6d20bc 100644 --- a/toolchain/semantics/semantics_context.cpp +++ b/toolchain/semantics/semantics_context.cpp @@ -28,11 +28,9 @@ SemanticsContext::SemanticsContext(const TokenizedBuffer& tokens, semantics_ir_(&semantics_ir), vlog_stream_(vlog_stream), node_stack_(parse_tree, vlog_stream), - node_block_stack_("node_block_stack_", semantics_ir.node_blocks(), - vlog_stream), - params_or_args_stack_("params_or_args_stack_", semantics_ir.node_blocks(), - vlog_stream), - args_type_info_stack_("args_type_info_stack_", semantics_ir.node_blocks(), + node_block_stack_("node_block_stack_", semantics_ir, vlog_stream), + params_or_args_stack_("params_or_args_stack_", semantics_ir, vlog_stream), + args_type_info_stack_("args_type_info_stack_", semantics_ir, vlog_stream) { // Inserts the "Invalid" and "Type" types as "used types" so that // canonicalization can skip them. We don't emit either for lowering. @@ -130,11 +128,92 @@ auto SemanticsContext::PopScope() -> void { } } +template +static auto AddDominatedBlockAndBranchImpl(SemanticsContext& context, + ParseTree::Node parse_node, + Args... args) + -> SemanticsNodeBlockId { + if (!context.node_block_stack().is_current_block_reachable()) { + return SemanticsNodeBlockId::Unreachable; + } + auto block_id = context.semantics_ir().AddNodeBlock(); + context.AddNode(BranchNode::Make(parse_node, block_id, args...)); + return block_id; +} + +auto SemanticsContext::AddDominatedBlockAndBranch(ParseTree::Node parse_node) + -> SemanticsNodeBlockId { + return AddDominatedBlockAndBranchImpl(*this, + parse_node); +} + +auto SemanticsContext::AddDominatedBlockAndBranchWithArg( + ParseTree::Node parse_node, SemanticsNodeId arg_id) + -> SemanticsNodeBlockId { + return AddDominatedBlockAndBranchImpl( + *this, parse_node, arg_id); +} + +auto SemanticsContext::AddDominatedBlockAndBranchIf(ParseTree::Node parse_node, + SemanticsNodeId cond_id) + -> SemanticsNodeBlockId { + return AddDominatedBlockAndBranchImpl( + *this, parse_node, cond_id); +} + +auto SemanticsContext::AddConvergenceBlockAndPush( + ParseTree::Node parse_node, + std::initializer_list blocks) -> void { + CARBON_CHECK(blocks.size() >= 2) << "no convergence"; + + SemanticsNodeBlockId new_block_id = SemanticsNodeBlockId::Unreachable; + for (SemanticsNodeBlockId block_id : blocks) { + if (block_id != SemanticsNodeBlockId::Unreachable) { + if (new_block_id == SemanticsNodeBlockId::Unreachable) { + new_block_id = semantics_ir().AddNodeBlock(); + } + AddNodeToBlock(block_id, + SemanticsNode::Branch::Make(parse_node, new_block_id)); + } + } + node_block_stack().Push(new_block_id); +} + +auto SemanticsContext::AddConvergenceBlockWithArgAndPush( + ParseTree::Node parse_node, + std::initializer_list> + blocks_and_args) -> SemanticsNodeId { + CARBON_CHECK(blocks_and_args.size() >= 2) << "no convergence"; + + SemanticsNodeBlockId new_block_id = SemanticsNodeBlockId::Unreachable; + for (auto [block_id, arg_id] : blocks_and_args) { + if (block_id != SemanticsNodeBlockId::Unreachable) { + if (new_block_id == SemanticsNodeBlockId::Unreachable) { + new_block_id = semantics_ir().AddNodeBlock(); + } + AddNodeToBlock(block_id, SemanticsNode::BranchWithArg::Make( + parse_node, new_block_id, arg_id)); + } + } + node_block_stack().Push(new_block_id); + + // Acquire the result value. + SemanticsTypeId result_type_id = + semantics_ir().GetNode(blocks_and_args.begin()->second).type_id(); + return AddNode( + SemanticsNode::BlockArg::Make(parse_node, result_type_id, new_block_id)); +} + // Add the current code block to the enclosing function. auto SemanticsContext::AddCurrentCodeBlockToFunction() -> void { CARBON_CHECK(!node_block_stack().empty()) << "no current code block"; CARBON_CHECK(!return_scope_stack().empty()) << "no current function"; + if (!node_block_stack().is_current_block_reachable()) { + // Don't include unreachable blocks in the function. + return; + } + auto function_id = semantics_ir() .GetNode(return_scope_stack().back()) .GetAsFunctionDeclaration(); @@ -143,6 +222,28 @@ auto SemanticsContext::AddCurrentCodeBlockToFunction() -> void { .body_block_ids.push_back(node_block_stack().PeekForAdd()); } +auto SemanticsContext::is_current_position_reachable() -> bool { + switch (auto block_id = node_block_stack().Peek(); block_id.index) { + case SemanticsNodeBlockId::Unreachable.index: { + return false; + } + case SemanticsNodeBlockId::Invalid.index: { + return true; + } + default: { + // Our current position is at the end of a real block. That position is + // reachable unless the previous instruction is a terminator instruction. + const auto& block_contents = semantics_ir().GetNodeBlock(block_id); + if (block_contents.empty()) { + return true; + } + const auto& last_node = semantics_ir().GetNode(block_contents.back()); + return last_node.kind().terminator_kind() != + SemanticsTerminatorKind::Terminator; + } + } +} + auto SemanticsContext::ImplicitAsForArgs( SemanticsNodeBlockId arg_refs_id, ParseTree::Node param_parse_node, SemanticsNodeBlockId param_refs_id, diff --git a/toolchain/semantics/semantics_context.h b/toolchain/semantics/semantics_context.h index 922c907cd003..805af9268ad7 100644 --- a/toolchain/semantics/semantics_context.h +++ b/toolchain/semantics/semantics_context.h @@ -57,9 +57,48 @@ class SemanticsContext { // Pops the top scope from scope_stack_, cleaning up names from name_lookup_. auto PopScope() -> void; + // Adds a `Branch` node branching to a new node block, and returns the ID of + // the new block. All paths to the branch target must go through the current + // block, though not necessarily through this branch. + auto AddDominatedBlockAndBranch(ParseTree::Node parse_node) + -> SemanticsNodeBlockId; + + // Adds a `Branch` node branching to a new node block with a value, and + // returns the ID of the new block. All paths to the branch target must go + // through the current block. + auto AddDominatedBlockAndBranchWithArg(ParseTree::Node parse_node, + SemanticsNodeId arg_id) + -> SemanticsNodeBlockId; + + // Adds a `BranchIf` node branching to a new node block, and returns the ID + // of the new block. All paths to the branch target must go through the + // current block. + auto AddDominatedBlockAndBranchIf(ParseTree::Node parse_node, + SemanticsNodeId cond_id) + -> SemanticsNodeBlockId; + + // Adds branches from the given list of blocks to a new block, for + // reconvergence of control flow, and pushes the new block onto the node + // block stack. + auto AddConvergenceBlockAndPush( + ParseTree::Node parse_tree, + std::initializer_list blocks) -> void; + + // Adds branches from the given list of blocks and values to a new block, for + // reconvergence of control flow with a result value, and pushes the new + // block onto the node block stack. Returns a node referring to the result + // value. + auto AddConvergenceBlockWithArgAndPush( + ParseTree::Node parse_node, + std::initializer_list> + blocks_and_args) -> SemanticsNodeId; + // Add the current code block to the enclosing function. auto AddCurrentCodeBlockToFunction() -> void; + // Returns whether the current position in the current block is reachable. + auto is_current_position_reachable() -> bool; + // Runs ImplicitAsImpl for a set of arguments and parameters. // // This will eventually need to support checking against multiple possible diff --git a/toolchain/semantics/semantics_handle.cpp b/toolchain/semantics/semantics_handle.cpp index 2acaa11ad1aa..0de23a1cc491 100644 --- a/toolchain/semantics/semantics_handle.cpp +++ b/toolchain/semantics/semantics_handle.cpp @@ -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. diff --git a/toolchain/semantics/semantics_handle_function.cpp b/toolchain/semantics/semantics_handle_function.cpp index d8f392701d08..e1706417ff38 100644 --- a/toolchain/semantics/semantics_handle_function.cpp +++ b/toolchain/semantics/semantics_handle_function.cpp @@ -12,8 +12,25 @@ auto SemanticsHandleFunctionDeclaration(SemanticsContext& context, } auto SemanticsHandleFunctionDefinition(SemanticsContext& context, - ParseTree::Node /*parse_node*/) -> bool { - context.node_stack().PopAndDiscardId(ParseNodeKind::FunctionDefinitionStart); + ParseTree::Node parse_node) -> bool { + auto function_id = context.node_stack().Pop( + ParseNodeKind::FunctionDefinitionStart); + + // If the `}` of the function is reachable, reject if we need a return value + // and otherwise add an implicit `return;`. + if (context.is_current_position_reachable()) { + if (context.semantics_ir() + .GetFunction(function_id) + .return_type_id.is_valid()) { + CARBON_DIAGNOSTIC( + MissingReturnStatement, Error, + "Missing `return` at end of function with declared return type."); + context.emitter().Emit(parse_node, MissingReturnStatement); + } else { + context.AddNode(SemanticsNode::Return::Make(parse_node)); + } + } + context.return_scope_stack().pop_back(); context.PopScope(); context.node_block_stack().Pop(); diff --git a/toolchain/semantics/semantics_handle_if.cpp b/toolchain/semantics/semantics_handle_if.cpp index d0c5ebcf27e6..0cb8d938dec1 100644 --- a/toolchain/semantics/semantics_handle_if.cpp +++ b/toolchain/semantics/semantics_handle_if.cpp @@ -18,19 +18,17 @@ auto SemanticsHandleIfCondition(SemanticsContext& context, auto cond_value_id = context.node_stack().Pop(); cond_value_id = context.ImplicitAsBool(parse_node, cond_value_id); - // Create the else block and the then block, and branch to the right one. If + // Create the then block and the else block, and branch to the right one. If // there is no `else`, the then block will terminate with a branch to the // else block, which will be reused as the resumption block. - auto if_block_id = context.node_block_stack().PopForAdd(); - auto else_block_id = context.node_block_stack().PushForAdd(); - auto then_block_id = context.node_block_stack().PushForAdd(); + auto then_block_id = + context.AddDominatedBlockAndBranchIf(parse_node, cond_value_id); + auto else_block_id = context.AddDominatedBlockAndBranch(parse_node); - // Branch to the appropriate block. - context.AddNodeToBlock( - if_block_id, - SemanticsNode::BranchIf::Make(parse_node, then_block_id, cond_value_id)); - context.AddNodeToBlock( - if_block_id, SemanticsNode::Branch::Make(parse_node, else_block_id)); + // Push the else and then blocks, and start emitting code in the then block. + context.node_block_stack().Pop(); + context.node_block_stack().Push(else_block_id); + context.node_block_stack().Push(then_block_id); context.AddCurrentCodeBlockToFunction(); context.node_stack().Push(parse_node); @@ -71,11 +69,8 @@ auto SemanticsHandleIfStatement(SemanticsContext& context, // Branch from the then and else blocks to a new resumption block. auto then_block_id = context.node_stack().Pop( ParseNodeKind::IfStatementElse); - auto resume_block_id = context.node_block_stack().PushForAdd(); - context.AddNodeToBlock(then_block_id, SemanticsNode::Branch::Make( - parse_node, resume_block_id)); - context.AddNodeToBlock(sub_block_id, SemanticsNode::Branch::Make( - parse_node, resume_block_id)); + context.AddConvergenceBlockAndPush(parse_node, + {then_block_id, sub_block_id}); break; } diff --git a/toolchain/semantics/semantics_handle_if_expression.cpp b/toolchain/semantics/semantics_handle_if_expression.cpp index a86dcbf9d4aa..25cb8ad8eb8b 100644 --- a/toolchain/semantics/semantics_handle_if_expression.cpp +++ b/toolchain/semantics/semantics_handle_if_expression.cpp @@ -12,24 +12,16 @@ auto SemanticsHandleIfExpressionIf(SemanticsContext& context, context.node_stack().Push(if_node); - // Convert the condition to `bool`. + // Convert the condition to `bool`, and branch on it. cond_value_id = context.ImplicitAsBool(if_node, cond_value_id); + auto then_block_id = + context.AddDominatedBlockAndBranchIf(if_node, cond_value_id); + auto else_block_id = context.AddDominatedBlockAndBranch(if_node); - // Stop emitting the current block. We'll add some branch instructions to it - // later, but we don't want it on the stack any more. - auto if_block_id = context.node_block_stack().PeekForAdd(); + // Push the `else` block and `then` block, and start emitting the `then`. context.node_block_stack().Pop(); - - // Create the resumption block, `else` block, and `then` block, and branches - // to them. - context.node_block_stack().Push(); - auto else_block_id = context.node_block_stack().PushForAdd(); - auto then_block_id = context.node_block_stack().PushForAdd(); - context.AddNodeToBlock( - if_block_id, - SemanticsNode::BranchIf::Make(if_node, then_block_id, cond_value_id)); - context.AddNodeToBlock(if_block_id, - SemanticsNode::Branch::Make(if_node, else_block_id)); + context.node_block_stack().Push(else_block_id); + context.node_block_stack().Push(then_block_id); context.AddCurrentCodeBlockToFunction(); return true; } @@ -59,20 +51,14 @@ auto SemanticsHandleIfExpressionElse(SemanticsContext& context, context.ImplicitAsRequired(else_node, else_value_id, result_type_id); auto else_end_block_id = context.node_block_stack().Pop(); - // Create branches to the resumption block. - auto resume_block_id = context.node_block_stack().PeekForAdd(); - context.AddNodeToBlock(then_end_block_id, - SemanticsNode::BranchWithArg::Make( - then_node, resume_block_id, then_value_id)); - context.AddNodeToBlock(else_end_block_id, - SemanticsNode::BranchWithArg::Make( - else_node, resume_block_id, else_value_id)); + // Create a resumption block and branches to it. + auto chosen_value_id = context.AddConvergenceBlockWithArgAndPush( + if_node, + {{then_end_block_id, then_value_id}, {else_end_block_id, else_value_id}}); context.AddCurrentCodeBlockToFunction(); - // Obtain the value in the resumption block and push it. - context.AddNodeAndPush( - if_node, - SemanticsNode::BlockArg::Make(if_node, result_type_id, resume_block_id)); + // Push the result value. + context.node_stack().Push(if_node, chosen_value_id); return true; } diff --git a/toolchain/semantics/semantics_ir.cpp b/toolchain/semantics/semantics_ir.cpp index f708899b301f..022361963ad0 100644 --- a/toolchain/semantics/semantics_ir.cpp +++ b/toolchain/semantics/semantics_ir.cpp @@ -92,9 +92,55 @@ auto SemanticsIR::MakeFromParseTree(const SemanticsIR& builtin_ir, context.VerifyOnFinish(); semantics_ir.has_errors_ = err_tracker.seen_error(); + +#ifndef NDEBUG + if (auto verify = semantics_ir.Verify(); !verify.ok()) { + CARBON_FATAL() << semantics_ir + << "Built invalid semantics IR: " << verify.error() << "\n"; + } +#endif + return semantics_ir; } +auto SemanticsIR::Verify() const -> ErrorOr { + // Invariants don't necessarily hold for invalid IR. + if (has_errors_) { + return Success(); + } + + // Check that every code block has a terminator sequence that appears at the + // end of the block. + for (const SemanticsFunction& function : functions_) { + for (SemanticsNodeBlockId block_id : function.body_block_ids) { + SemanticsTerminatorKind prior_kind = + SemanticsTerminatorKind::NotTerminator; + for (SemanticsNodeId node_id : GetNodeBlock(block_id)) { + SemanticsTerminatorKind node_kind = + GetNode(node_id).kind().terminator_kind(); + if (prior_kind == SemanticsTerminatorKind::Terminator) { + return Error(llvm::formatv("Node {0} in block {1} follows terminator", + node_id, block_id)); + } + if (prior_kind > node_kind) { + return Error( + llvm::formatv("Non-terminator node {0} in block {1} follows " + "terminator sequence", + node_id, block_id)); + } + prior_kind = node_kind; + } + if (prior_kind != SemanticsTerminatorKind::Terminator) { + return Error(llvm::formatv("No terminator in block {0}", block_id)); + } + } + } + + // TODO: Check that a node only references other nodes that are either global + // or that dominate it. + return Success(); +} + static constexpr int Indent = 2; template diff --git a/toolchain/semantics/semantics_ir.h b/toolchain/semantics/semantics_ir.h index 95f41e04605a..d7ec44f4f56d 100644 --- a/toolchain/semantics/semantics_ir.h +++ b/toolchain/semantics/semantics_ir.h @@ -36,9 +36,9 @@ struct SemanticsFunction { SemanticsNodeBlockId param_refs_id; // The return type. This will be invalid if the return type wasn't specified. SemanticsTypeId return_type_id; - // A list of the code blocks in the body of the function, in lexical order. - // The first block is the entry block. This will be empty for declarations - // that don't have a visible definition. + // A list of the statically reachable code blocks in the body of the + // function, in lexical order. The first block is the entry block. This will + // be empty for declarations that don't have a visible definition. llvm::SmallVector body_block_ids; }; @@ -69,6 +69,9 @@ class SemanticsIR { DiagnosticConsumer& consumer, llvm::raw_ostream* vlog_stream) -> SemanticsIR; + // Verifies that invariants of the semantics IR hold. + auto Verify() const -> ErrorOr; + // Prints the full IR. Allow omitting builtins so that unrelated changes are // less likely to alternate test golden files. // TODO: In the future, the things to print may change, for example by adding @@ -115,7 +118,9 @@ class SemanticsIR { -> SemanticsNodeId { SemanticsNodeId node_id(nodes_.size()); nodes_.push_back(node); - node_blocks_[block_id.index].push_back(node_id); + if (block_id != SemanticsNodeBlockId::Unreachable) { + node_blocks_[block_id.index].push_back(node_id); + } return node_id; } @@ -124,15 +129,24 @@ class SemanticsIR { return nodes_[node_id.index]; } + // Adds an empty node block, returning an ID to reference it. + auto AddNodeBlock() -> SemanticsNodeBlockId { + SemanticsNodeBlockId id(node_blocks_.size()); + node_blocks_.push_back({}); + return id; + } + // Returns the requested node block. auto GetNodeBlock(SemanticsNodeBlockId block_id) const -> const llvm::SmallVector& { + CARBON_CHECK(block_id != SemanticsNodeBlockId::Unreachable); return node_blocks_[block_id.index]; } // Returns the requested node block. auto GetNodeBlock(SemanticsNodeBlockId block_id) -> llvm::SmallVector& { + CARBON_CHECK(block_id != SemanticsNodeBlockId::Unreachable); return node_blocks_[block_id.index]; } diff --git a/toolchain/semantics/semantics_node.h b/toolchain/semantics/semantics_node.h index d94ff92035af..925c398a2e58 100644 --- a/toolchain/semantics/semantics_node.h +++ b/toolchain/semantics/semantics_node.h @@ -9,6 +9,7 @@ #include "common/check.h" #include "common/ostream.h" +#include "toolchain/common/index_base.h" #include "toolchain/parser/parse_tree.h" #include "toolchain/semantics/semantics_builtin_kind.h" #include "toolchain/semantics/semantics_node_kind.h" @@ -108,10 +109,17 @@ struct SemanticsNodeBlockId : public IndexBase { // An explicitly invalid ID. static const SemanticsNodeBlockId Invalid; + // An ID for unreachable code. + static const SemanticsNodeBlockId Unreachable; + using IndexBase::IndexBase; auto Print(llvm::raw_ostream& out) const -> void { - out << "block"; - IndexBase::Print(out); + if (index == Unreachable.index) { + out << "unreachable"; + } else { + out << "block"; + IndexBase::Print(out); + } } }; @@ -119,6 +127,8 @@ constexpr SemanticsNodeBlockId SemanticsNodeBlockId::Empty = SemanticsNodeBlockId(0); constexpr SemanticsNodeBlockId SemanticsNodeBlockId::Invalid = SemanticsNodeBlockId(SemanticsNodeBlockId::InvalidIndex); +constexpr SemanticsNodeBlockId SemanticsNodeBlockId::Unreachable = + SemanticsNodeBlockId(SemanticsNodeBlockId::InvalidIndex - 1); // The ID of a real literal. struct SemanticsRealLiteralId : public IndexBase { diff --git a/toolchain/semantics/semantics_node_block_stack.cpp b/toolchain/semantics/semantics_node_block_stack.cpp index 769425a0b6b2..7a8e75dfbee6 100644 --- a/toolchain/semantics/semantics_node_block_stack.cpp +++ b/toolchain/semantics/semantics_node_block_stack.cpp @@ -9,20 +9,18 @@ namespace Carbon { -auto SemanticsNodeBlockStack::Push() -> void { +auto SemanticsNodeBlockStack::Push(SemanticsNodeBlockId id) -> void { CARBON_VLOG() << name_ << " Push " << stack_.size() << "\n"; CARBON_CHECK(stack_.size() < (1 << 20)) << "Excessive stack size: likely infinite loop"; - stack_.push_back(SemanticsNodeBlockId::Invalid); + stack_.push_back(id); } auto SemanticsNodeBlockStack::PeekForAdd() -> SemanticsNodeBlockId { - CARBON_CHECK(!stack_.empty()); + CARBON_CHECK(!stack_.empty()) << "no current block"; auto& back = stack_.back(); if (!back.is_valid()) { - SemanticsNodeBlockId block_id(node_blocks_->size()); - node_blocks_->resize(block_id.index + 1); - back = block_id; + back = semantics_ir_->AddNodeBlock(); CARBON_VLOG() << name_ << " Add " << stack_.size() - 1 << ": " << back << "\n"; } @@ -30,6 +28,7 @@ auto SemanticsNodeBlockStack::PeekForAdd() -> SemanticsNodeBlockId { } auto SemanticsNodeBlockStack::Pop() -> SemanticsNodeBlockId { + CARBON_CHECK(!stack_.empty()) << "no current block"; auto back = stack_.pop_back_val(); CARBON_VLOG() << name_ << " Pop " << stack_.size() << ": " << back << "\n"; if (!back.is_valid()) { diff --git a/toolchain/semantics/semantics_node_block_stack.h b/toolchain/semantics/semantics_node_block_stack.h index 0615fc577ac7..fc972d8e7720 100644 --- a/toolchain/semantics/semantics_node_block_stack.h +++ b/toolchain/semantics/semantics_node_block_stack.h @@ -8,6 +8,7 @@ #include #include "llvm/ADT/SmallVector.h" +#include "toolchain/semantics/semantics_ir.h" #include "toolchain/semantics/semantics_node.h" namespace Carbon { @@ -17,15 +18,20 @@ namespace Carbon { // All pushes and pops will be vlogged. class SemanticsNodeBlockStack { public: - explicit SemanticsNodeBlockStack( - llvm::StringLiteral name, - llvm::SmallVector>& node_blocks, - llvm::raw_ostream* vlog_stream) - : name_(name), node_blocks_(&node_blocks), vlog_stream_(vlog_stream) {} + explicit SemanticsNodeBlockStack(llvm::StringLiteral name, + SemanticsIR& semantics_ir, + llvm::raw_ostream* vlog_stream) + : name_(name), semantics_ir_(&semantics_ir), vlog_stream_(vlog_stream) {} + + // Pushes an existing node block. + auto Push(SemanticsNodeBlockId id) -> void; // Pushes a new node block. It will be invalid unless PeekForAdd is called in // order to support lazy allocation. - auto Push() -> void; + auto Push() -> void { Push(SemanticsNodeBlockId::Invalid); } + + // Pushes a new unreachable code block. + auto PushUnreachable() -> void { Push(SemanticsNodeBlockId::Unreachable); } // Allocates and pushes a new node block. auto PushForAdd() -> SemanticsNodeBlockId { @@ -35,7 +41,10 @@ class SemanticsNodeBlockStack { // Peeks at the top node block. This does not trigger lazy allocation, so the // returned node block may be invalid. - auto Peek() -> SemanticsNodeBlockId { return stack_.back(); } + auto Peek() -> SemanticsNodeBlockId { + CARBON_CHECK(!stack_.empty()) << "no current block"; + return stack_.back(); + } // Returns the top node block, allocating one if it's still invalid. auto PeekForAdd() -> SemanticsNodeBlockId; @@ -51,6 +60,11 @@ class SemanticsNodeBlockStack { return Pop(); } + // Returns whether the current block is statically reachable. + auto is_current_block_reachable() -> bool { + return Peek() != SemanticsNodeBlockId::Unreachable; + } + // Prints the stack for a stack dump. auto PrintForStackDump(llvm::raw_ostream& output) const -> void; @@ -61,8 +75,8 @@ class SemanticsNodeBlockStack { // A name for debugging. llvm::StringLiteral name_; - // The underlying node block storage on SemanticsIR. Always non-null. - llvm::SmallVector>* const node_blocks_; + // The underlying SemanticsIR instance. Always non-null. + SemanticsIR* semantics_ir_; // Whether to print verbose output. llvm::raw_ostream* vlog_stream_; diff --git a/toolchain/semantics/semantics_node_kind.cpp b/toolchain/semantics/semantics_node_kind.cpp index b8c068bcf2eb..56a5cbc45db4 100644 --- a/toolchain/semantics/semantics_node_kind.cpp +++ b/toolchain/semantics/semantics_node_kind.cpp @@ -11,4 +11,16 @@ CARBON_DEFINE_ENUM_CLASS_NAMES(SemanticsNodeKind) = { #include "toolchain/semantics/semantics_node_kind.def" }; +auto SemanticsNodeKind::terminator_kind() const -> SemanticsTerminatorKind { + static constexpr SemanticsTerminatorKind Table[] = { +#define CARBON_SEMANTICS_NODE_KIND(Name) SemanticsTerminatorKind::NotTerminator, +#define CARBON_SEMANTICS_TERMINATOR_SEQUENCE_KIND(Name) \ + SemanticsTerminatorKind::TerminatorSequence, +#define CARBON_SEMANTICS_TERMINATOR_KIND(Name) \ + SemanticsTerminatorKind::Terminator, +#include "toolchain/semantics/semantics_node_kind.def" + }; + return Table[AsInt()]; +} + } // namespace Carbon diff --git a/toolchain/semantics/semantics_node_kind.def b/toolchain/semantics/semantics_node_kind.def index 6abeeefb9e32..f3f0e88af4af 100644 --- a/toolchain/semantics/semantics_node_kind.def +++ b/toolchain/semantics/semantics_node_kind.def @@ -10,11 +10,27 @@ // Supported x-macros are: // - CARBON_SEMANTICS_NODE_KIND(Name) // Defines a node kind. +// - CARBON_SEMANTICS_TERMINATOR_SEQUENCE_KIND(Name) +// Defines a node kind for a node in the terminator sequence, such as +// BranchIf. These nodes can only appear at the end of a block, after all +// nodes that are not in the terminator sequence, before the terminator. +// - CARBON_SEMANTICS_TERMINATOR_KIND(Name) +// Defines a node kind for a terminator node. #ifndef CARBON_SEMANTICS_NODE_KIND #error "Must define the x-macro to use this file." #endif +#ifndef CARBON_SEMANTICS_TERMINATOR_SEQUENCE_KIND +#define CARBON_SEMANTICS_TERMINATOR_SEQUENCE_KIND(Name) \ + CARBON_SEMANTICS_NODE_KIND(Name) +#endif + +#ifndef CARBON_SEMANTICS_TERMINATOR_KIND +#define CARBON_SEMANTICS_TERMINATOR_KIND(Name) \ + CARBON_SEMANTICS_TERMINATOR_SEQUENCE_KIND(Name) +#endif + CARBON_SEMANTICS_NODE_KIND(Invalid) // A cross-reference between IRs. @@ -25,16 +41,16 @@ CARBON_SEMANTICS_NODE_KIND(BinaryOperatorAdd) CARBON_SEMANTICS_NODE_KIND(BindName) CARBON_SEMANTICS_NODE_KIND(BlockArg) CARBON_SEMANTICS_NODE_KIND(BoolLiteral) -CARBON_SEMANTICS_NODE_KIND(Branch) -CARBON_SEMANTICS_NODE_KIND(BranchIf) -CARBON_SEMANTICS_NODE_KIND(BranchWithArg) +CARBON_SEMANTICS_TERMINATOR_KIND(Branch) +CARBON_SEMANTICS_TERMINATOR_SEQUENCE_KIND(BranchIf) +CARBON_SEMANTICS_TERMINATOR_KIND(BranchWithArg) CARBON_SEMANTICS_NODE_KIND(Builtin) CARBON_SEMANTICS_NODE_KIND(Call) CARBON_SEMANTICS_NODE_KIND(FunctionDeclaration) CARBON_SEMANTICS_NODE_KIND(IntegerLiteral) CARBON_SEMANTICS_NODE_KIND(RealLiteral) -CARBON_SEMANTICS_NODE_KIND(Return) -CARBON_SEMANTICS_NODE_KIND(ReturnExpression) +CARBON_SEMANTICS_TERMINATOR_KIND(Return) +CARBON_SEMANTICS_TERMINATOR_KIND(ReturnExpression) CARBON_SEMANTICS_NODE_KIND(StringLiteral) CARBON_SEMANTICS_NODE_KIND(StructMemberAccess) CARBON_SEMANTICS_NODE_KIND(StructType) @@ -44,4 +60,6 @@ CARBON_SEMANTICS_NODE_KIND(StubReference) CARBON_SEMANTICS_NODE_KIND(UnaryOperatorNot) CARBON_SEMANTICS_NODE_KIND(VarStorage) +#undef CARBON_SEMANTICS_TERMINATOR_SEQUENCE_KIND +#undef CARBON_SEMANTICS_TERMINATOR_KIND #undef CARBON_SEMANTICS_NODE_KIND diff --git a/toolchain/semantics/semantics_node_kind.h b/toolchain/semantics/semantics_node_kind.h index 7c0f4c57d09e..421c08e19f58 100644 --- a/toolchain/semantics/semantics_node_kind.h +++ b/toolchain/semantics/semantics_node_kind.h @@ -16,12 +16,32 @@ CARBON_DEFINE_RAW_ENUM_CLASS(SemanticsNodeKind, uint8_t) { #include "toolchain/semantics/semantics_node_kind.def" }; +// Whether a node is a terminator or part of the terminator sequence. The nodes +// in a block appear in the order NotTerminator, then TerminatorSequence, then +// Terminator, which is also the numerical order of these values. +enum class SemanticsTerminatorKind { + // This node is not a terminator. + NotTerminator, + // This node is not itself a terminator, but forms part of a terminator + // sequence. + TerminatorSequence, + // This node is a terminator. + Terminator, +}; + class SemanticsNodeKind : public CARBON_ENUM_BASE(SemanticsNodeKind) { public: #define CARBON_SEMANTICS_NODE_KIND(Name) CARBON_ENUM_CONSTANT_DECLARATION(Name) #include "toolchain/semantics/semantics_node_kind.def" using EnumBase::Create; + + // Returns whether this node kind is a code block terminator, such as an + // unconditional branch instruction, or part of the termination sequence, + // such as a conditional branch instruction. The termination sequence of a + // code block appears after all other instructions, and ends with a + // terminator instruction. + [[nodiscard]] auto terminator_kind() const -> SemanticsTerminatorKind; }; #define CARBON_SEMANTICS_NODE_KIND(Name) \ diff --git a/toolchain/semantics/testdata/basics/fail_name_lookup.carbon b/toolchain/semantics/testdata/basics/fail_name_lookup.carbon index 41db925fdc7a..2f235bef5737 100644 --- a/toolchain/semantics/testdata/basics/fail_name_lookup.carbon +++ b/toolchain/semantics/testdata/basics/fail_name_lookup.carbon @@ -19,6 +19,7 @@ // CHECK:STDOUT: ] // CHECK:STDOUT: nodes: [ // CHECK:STDOUT: {kind: FunctionDeclaration, arg0: function0}, +// CHECK:STDOUT: {kind: Return}, // CHECK:STDOUT: ] // CHECK:STDOUT: node_blocks: [ // CHECK:STDOUT: [ @@ -27,6 +28,7 @@ // CHECK:STDOUT: node+0, // CHECK:STDOUT: ], // CHECK:STDOUT: [ +// CHECK:STDOUT: node+1, // CHECK:STDOUT: ], // CHECK:STDOUT: ] diff --git a/toolchain/semantics/testdata/function/call/empty_struct.carbon b/toolchain/semantics/testdata/function/call/empty_struct.carbon index ca60e0850c1c..22d50fc41c53 100644 --- a/toolchain/semantics/testdata/function/call/empty_struct.carbon +++ b/toolchain/semantics/testdata/function/call/empty_struct.carbon @@ -33,6 +33,7 @@ // CHECK:STDOUT: {kind: StructValue, arg0: block0, type: type0}, // CHECK:STDOUT: {kind: StubReference, arg0: node+8, type: type0}, // CHECK:STDOUT: {kind: Call, arg0: block6, arg1: function0, type: type0}, +// CHECK:STDOUT: {kind: Return}, // CHECK:STDOUT: ] // CHECK:STDOUT: node_blocks: [ // CHECK:STDOUT: [ @@ -58,6 +59,7 @@ // CHECK:STDOUT: node+8, // CHECK:STDOUT: node+9, // CHECK:STDOUT: node+10, +// CHECK:STDOUT: node+11, // CHECK:STDOUT: ], // CHECK:STDOUT: [ // CHECK:STDOUT: node+9, diff --git a/toolchain/semantics/testdata/function/call/fail_param_count.carbon b/toolchain/semantics/testdata/function/call/fail_param_count.carbon index e2360cd86be2..251879f4130a 100644 --- a/toolchain/semantics/testdata/function/call/fail_param_count.carbon +++ b/toolchain/semantics/testdata/function/call/fail_param_count.carbon @@ -34,64 +34,68 @@ // CHECK:STDOUT: ] // CHECK:STDOUT: nodes: [ // CHECK:STDOUT: {kind: FunctionDeclaration, arg0: function0}, +// CHECK:STDOUT: {kind: Return}, // CHECK:STDOUT: {kind: VarStorage, type: type1}, -// CHECK:STDOUT: {kind: BindName, arg0: str2, arg1: node+1, type: type1}, +// CHECK:STDOUT: {kind: BindName, arg0: str2, arg1: node+2, type: type1}, // CHECK:STDOUT: {kind: FunctionDeclaration, arg0: function1}, +// CHECK:STDOUT: {kind: Return}, // CHECK:STDOUT: {kind: VarStorage, type: type1}, -// CHECK:STDOUT: {kind: BindName, arg0: str2, arg1: node+4, type: type1}, +// CHECK:STDOUT: {kind: BindName, arg0: str2, arg1: node+6, type: type1}, // CHECK:STDOUT: {kind: VarStorage, type: type1}, -// CHECK:STDOUT: {kind: BindName, arg0: str4, arg1: node+6, type: type1}, +// CHECK:STDOUT: {kind: BindName, arg0: str4, arg1: node+8, type: type1}, // CHECK:STDOUT: {kind: FunctionDeclaration, arg0: function2}, +// CHECK:STDOUT: {kind: Return}, // CHECK:STDOUT: {kind: FunctionDeclaration, arg0: function3}, // CHECK:STDOUT: {kind: IntegerLiteral, arg0: int0, type: type1}, -// CHECK:STDOUT: {kind: StubReference, arg0: node+10, type: type1}, +// CHECK:STDOUT: {kind: StubReference, arg0: node+13, type: type1}, // CHECK:STDOUT: {kind: IntegerLiteral, arg0: int1, type: type1}, -// CHECK:STDOUT: {kind: StubReference, arg0: node+12, type: type1}, +// CHECK:STDOUT: {kind: StubReference, arg0: node+15, type: type1}, // CHECK:STDOUT: {kind: IntegerLiteral, arg0: int2, type: type1}, -// CHECK:STDOUT: {kind: StubReference, arg0: node+14, type: type1}, +// CHECK:STDOUT: {kind: StubReference, arg0: node+17, type: type1}, // CHECK:STDOUT: {kind: IntegerLiteral, arg0: int3, type: type1}, -// CHECK:STDOUT: {kind: StubReference, arg0: node+16, type: type1}, +// CHECK:STDOUT: {kind: StubReference, arg0: node+19, type: type1}, // CHECK:STDOUT: {kind: IntegerLiteral, arg0: int4, type: type1}, -// CHECK:STDOUT: {kind: StubReference, arg0: node+18, type: type1}, +// CHECK:STDOUT: {kind: StubReference, arg0: node+21, type: type1}, // CHECK:STDOUT: {kind: IntegerLiteral, arg0: int5, type: type1}, -// CHECK:STDOUT: {kind: StubReference, arg0: node+20, type: type1}, +// CHECK:STDOUT: {kind: StubReference, arg0: node+23, type: type1}, +// CHECK:STDOUT: {kind: Return}, // CHECK:STDOUT: ] // CHECK:STDOUT: node_blocks: [ // CHECK:STDOUT: [ // CHECK:STDOUT: ], // CHECK:STDOUT: [ // CHECK:STDOUT: node+0, +// CHECK:STDOUT: node+4, +// CHECK:STDOUT: node+10, +// CHECK:STDOUT: node+12, +// CHECK:STDOUT: ], +// CHECK:STDOUT: [ +// CHECK:STDOUT: node+1, +// CHECK:STDOUT: ], +// CHECK:STDOUT: [ +// CHECK:STDOUT: node+2, // CHECK:STDOUT: node+3, +// CHECK:STDOUT: ], +// CHECK:STDOUT: [ +// CHECK:STDOUT: node+3, +// CHECK:STDOUT: ], +// CHECK:STDOUT: [ +// CHECK:STDOUT: node+5, +// CHECK:STDOUT: ], +// CHECK:STDOUT: [ +// CHECK:STDOUT: node+6, +// CHECK:STDOUT: node+7, // CHECK:STDOUT: node+8, // CHECK:STDOUT: node+9, // CHECK:STDOUT: ], // CHECK:STDOUT: [ -// CHECK:STDOUT: ], -// CHECK:STDOUT: [ -// CHECK:STDOUT: node+1, -// CHECK:STDOUT: node+2, -// CHECK:STDOUT: ], -// CHECK:STDOUT: [ -// CHECK:STDOUT: node+2, -// CHECK:STDOUT: ], -// CHECK:STDOUT: [ -// CHECK:STDOUT: ], -// CHECK:STDOUT: [ -// CHECK:STDOUT: node+4, -// CHECK:STDOUT: node+5, -// CHECK:STDOUT: node+6, // CHECK:STDOUT: node+7, +// CHECK:STDOUT: node+9, // CHECK:STDOUT: ], // CHECK:STDOUT: [ -// CHECK:STDOUT: node+5, -// CHECK:STDOUT: node+7, -// CHECK:STDOUT: ], -// CHECK:STDOUT: [ -// CHECK:STDOUT: ], -// CHECK:STDOUT: [ -// CHECK:STDOUT: node+10, // CHECK:STDOUT: node+11, -// CHECK:STDOUT: node+12, +// CHECK:STDOUT: ], +// CHECK:STDOUT: [ // CHECK:STDOUT: node+13, // CHECK:STDOUT: node+14, // CHECK:STDOUT: node+15, @@ -101,20 +105,24 @@ // CHECK:STDOUT: node+19, // CHECK:STDOUT: node+20, // CHECK:STDOUT: node+21, +// CHECK:STDOUT: node+22, +// CHECK:STDOUT: node+23, +// CHECK:STDOUT: node+24, +// CHECK:STDOUT: node+25, // CHECK:STDOUT: ], // CHECK:STDOUT: [ -// CHECK:STDOUT: node+11, +// CHECK:STDOUT: node+14, // CHECK:STDOUT: ], // CHECK:STDOUT: [ -// CHECK:STDOUT: node+13, -// CHECK:STDOUT: node+15, +// CHECK:STDOUT: node+16, +// CHECK:STDOUT: node+18, // CHECK:STDOUT: ], // CHECK:STDOUT: [ -// CHECK:STDOUT: node+17, -// CHECK:STDOUT: node+19, +// CHECK:STDOUT: node+20, +// CHECK:STDOUT: node+22, // CHECK:STDOUT: ], // CHECK:STDOUT: [ -// CHECK:STDOUT: node+21, +// CHECK:STDOUT: node+24, // CHECK:STDOUT: ], // CHECK:STDOUT: ] diff --git a/toolchain/semantics/testdata/function/call/fail_param_type.carbon b/toolchain/semantics/testdata/function/call/fail_param_type.carbon index c04184a2e185..43925f736375 100644 --- a/toolchain/semantics/testdata/function/call/fail_param_type.carbon +++ b/toolchain/semantics/testdata/function/call/fail_param_type.carbon @@ -27,9 +27,11 @@ // CHECK:STDOUT: {kind: VarStorage, type: type0}, // CHECK:STDOUT: {kind: BindName, arg0: str1, arg1: node+0, type: type0}, // CHECK:STDOUT: {kind: FunctionDeclaration, arg0: function0}, +// CHECK:STDOUT: {kind: Return}, // CHECK:STDOUT: {kind: FunctionDeclaration, arg0: function1}, // CHECK:STDOUT: {kind: RealLiteral, arg0: real0, type: type2}, -// CHECK:STDOUT: {kind: StubReference, arg0: node+4, type: type2}, +// CHECK:STDOUT: {kind: StubReference, arg0: node+5, type: type2}, +// CHECK:STDOUT: {kind: Return}, // CHECK:STDOUT: ] // CHECK:STDOUT: node_blocks: [ // CHECK:STDOUT: [ @@ -43,16 +45,18 @@ // CHECK:STDOUT: ], // CHECK:STDOUT: [ // CHECK:STDOUT: node+2, +// CHECK:STDOUT: node+4, +// CHECK:STDOUT: ], +// CHECK:STDOUT: [ // CHECK:STDOUT: node+3, // CHECK:STDOUT: ], // CHECK:STDOUT: [ +// CHECK:STDOUT: node+5, +// CHECK:STDOUT: node+6, +// CHECK:STDOUT: node+7, // CHECK:STDOUT: ], // CHECK:STDOUT: [ -// CHECK:STDOUT: node+4, -// CHECK:STDOUT: node+5, -// CHECK:STDOUT: ], -// CHECK:STDOUT: [ -// CHECK:STDOUT: node+5, +// CHECK:STDOUT: node+6, // CHECK:STDOUT: ], // CHECK:STDOUT: ] diff --git a/toolchain/semantics/testdata/function/call/fail_return_type_mismatch.carbon b/toolchain/semantics/testdata/function/call/fail_return_type_mismatch.carbon index aab17229aa68..2b0812a79c90 100644 --- a/toolchain/semantics/testdata/function/call/fail_return_type_mismatch.carbon +++ b/toolchain/semantics/testdata/function/call/fail_return_type_mismatch.carbon @@ -32,6 +32,7 @@ // CHECK:STDOUT: {kind: BindName, arg0: str2, arg1: node+4, type: type2}, // CHECK:STDOUT: {kind: Call, arg0: block0, arg1: function0, type: type0}, // CHECK:STDOUT: {kind: Assign, arg0: node+4, arg1: nodeInvalidType, type: typeInvalidType}, +// CHECK:STDOUT: {kind: Return}, // CHECK:STDOUT: ] // CHECK:STDOUT: node_blocks: [ // CHECK:STDOUT: [ @@ -49,6 +50,7 @@ // CHECK:STDOUT: node+5, // CHECK:STDOUT: node+6, // CHECK:STDOUT: node+7, +// CHECK:STDOUT: node+8, // CHECK:STDOUT: ], // CHECK:STDOUT: ] diff --git a/toolchain/semantics/testdata/function/call/i32.carbon b/toolchain/semantics/testdata/function/call/i32.carbon index 3769769f9291..e3c09a1659d9 100644 --- a/toolchain/semantics/testdata/function/call/i32.carbon +++ b/toolchain/semantics/testdata/function/call/i32.carbon @@ -35,6 +35,7 @@ // CHECK:STDOUT: {kind: StubReference, arg0: node+7, type: type0}, // CHECK:STDOUT: {kind: Call, arg0: block6, arg1: function0, type: type0}, // CHECK:STDOUT: {kind: Assign, arg0: node+5, arg1: node+9, type: type0}, +// CHECK:STDOUT: {kind: Return}, // CHECK:STDOUT: ] // CHECK:STDOUT: node_blocks: [ // CHECK:STDOUT: [ @@ -60,6 +61,7 @@ // CHECK:STDOUT: node+8, // CHECK:STDOUT: node+9, // CHECK:STDOUT: node+10, +// CHECK:STDOUT: node+11, // CHECK:STDOUT: ], // CHECK:STDOUT: [ // CHECK:STDOUT: node+8, diff --git a/toolchain/semantics/testdata/function/call/more_param_ir.carbon b/toolchain/semantics/testdata/function/call/more_param_ir.carbon index 4004509f4426..90856688a91b 100644 --- a/toolchain/semantics/testdata/function/call/more_param_ir.carbon +++ b/toolchain/semantics/testdata/function/call/more_param_ir.carbon @@ -37,20 +37,22 @@ // CHECK:STDOUT: {kind: VarStorage, type: type0}, // CHECK:STDOUT: {kind: BindName, arg0: str3, arg1: node+4, type: type0}, // CHECK:STDOUT: {kind: FunctionDeclaration, arg0: function0}, +// CHECK:STDOUT: {kind: Return}, // CHECK:STDOUT: {kind: FunctionDeclaration, arg0: function1}, // CHECK:STDOUT: {kind: IntegerLiteral, arg0: int0, type: type0}, // CHECK:STDOUT: {kind: IntegerLiteral, arg0: int1, type: type0}, -// CHECK:STDOUT: {kind: BinaryOperatorAdd, arg0: node+8, arg1: node+9, type: type0}, +// CHECK:STDOUT: {kind: BinaryOperatorAdd, arg0: node+9, arg1: node+10, type: type0}, // CHECK:STDOUT: {kind: IntegerLiteral, arg0: int2, type: type0}, -// CHECK:STDOUT: {kind: BinaryOperatorAdd, arg0: node+10, arg1: node+11, type: type0}, -// CHECK:STDOUT: {kind: StubReference, arg0: node+12, type: type0}, +// CHECK:STDOUT: {kind: BinaryOperatorAdd, arg0: node+11, arg1: node+12, type: type0}, +// CHECK:STDOUT: {kind: StubReference, arg0: node+13, type: type0}, // CHECK:STDOUT: {kind: IntegerLiteral, arg0: int3, type: type0}, // CHECK:STDOUT: {kind: IntegerLiteral, arg0: int4, type: type0}, -// CHECK:STDOUT: {kind: BinaryOperatorAdd, arg0: node+14, arg1: node+15, type: type0}, -// CHECK:STDOUT: {kind: StubReference, arg0: node+16, type: type0}, +// CHECK:STDOUT: {kind: BinaryOperatorAdd, arg0: node+15, arg1: node+16, type: type0}, +// CHECK:STDOUT: {kind: StubReference, arg0: node+17, type: type0}, // CHECK:STDOUT: {kind: IntegerLiteral, arg0: int5, type: type0}, -// CHECK:STDOUT: {kind: StubReference, arg0: node+18, type: type0}, +// CHECK:STDOUT: {kind: StubReference, arg0: node+19, type: type0}, // CHECK:STDOUT: {kind: Call, arg0: block6, arg1: function0}, +// CHECK:STDOUT: {kind: Return}, // CHECK:STDOUT: ] // CHECK:STDOUT: node_blocks: [ // CHECK:STDOUT: [ @@ -70,12 +72,12 @@ // CHECK:STDOUT: ], // CHECK:STDOUT: [ // CHECK:STDOUT: node+6, +// CHECK:STDOUT: node+8, +// CHECK:STDOUT: ], +// CHECK:STDOUT: [ // CHECK:STDOUT: node+7, // CHECK:STDOUT: ], // CHECK:STDOUT: [ -// CHECK:STDOUT: ], -// CHECK:STDOUT: [ -// CHECK:STDOUT: node+8, // CHECK:STDOUT: node+9, // CHECK:STDOUT: node+10, // CHECK:STDOUT: node+11, @@ -88,11 +90,13 @@ // CHECK:STDOUT: node+18, // CHECK:STDOUT: node+19, // CHECK:STDOUT: node+20, +// CHECK:STDOUT: node+21, +// CHECK:STDOUT: node+22, // CHECK:STDOUT: ], // CHECK:STDOUT: [ -// CHECK:STDOUT: node+13, -// CHECK:STDOUT: node+17, -// CHECK:STDOUT: node+19, +// CHECK:STDOUT: node+14, +// CHECK:STDOUT: node+18, +// CHECK:STDOUT: node+20, // CHECK:STDOUT: ], // CHECK:STDOUT: ] diff --git a/toolchain/semantics/testdata/function/call/params_one.carbon b/toolchain/semantics/testdata/function/call/params_one.carbon index 634b3c8f36b6..c57e81a21e42 100644 --- a/toolchain/semantics/testdata/function/call/params_one.carbon +++ b/toolchain/semantics/testdata/function/call/params_one.carbon @@ -26,10 +26,12 @@ // CHECK:STDOUT: {kind: VarStorage, type: type0}, // CHECK:STDOUT: {kind: BindName, arg0: str1, arg1: node+0, type: type0}, // CHECK:STDOUT: {kind: FunctionDeclaration, arg0: function0}, +// CHECK:STDOUT: {kind: Return}, // CHECK:STDOUT: {kind: FunctionDeclaration, arg0: function1}, // CHECK:STDOUT: {kind: IntegerLiteral, arg0: int0, type: type0}, -// CHECK:STDOUT: {kind: StubReference, arg0: node+4, type: type0}, +// CHECK:STDOUT: {kind: StubReference, arg0: node+5, type: type0}, // CHECK:STDOUT: {kind: Call, arg0: block6, arg1: function0}, +// CHECK:STDOUT: {kind: Return}, // CHECK:STDOUT: ] // CHECK:STDOUT: node_blocks: [ // CHECK:STDOUT: [ @@ -43,17 +45,19 @@ // CHECK:STDOUT: ], // CHECK:STDOUT: [ // CHECK:STDOUT: node+2, +// CHECK:STDOUT: node+4, +// CHECK:STDOUT: ], +// CHECK:STDOUT: [ // CHECK:STDOUT: node+3, // CHECK:STDOUT: ], // CHECK:STDOUT: [ -// CHECK:STDOUT: ], -// CHECK:STDOUT: [ -// CHECK:STDOUT: node+4, // CHECK:STDOUT: node+5, // CHECK:STDOUT: node+6, +// CHECK:STDOUT: node+7, +// CHECK:STDOUT: node+8, // CHECK:STDOUT: ], // CHECK:STDOUT: [ -// CHECK:STDOUT: node+5, +// CHECK:STDOUT: node+6, // CHECK:STDOUT: ], // CHECK:STDOUT: ] diff --git a/toolchain/semantics/testdata/function/call/params_one_comma.carbon b/toolchain/semantics/testdata/function/call/params_one_comma.carbon index c0f01e6830e3..4caeb0f76d57 100644 --- a/toolchain/semantics/testdata/function/call/params_one_comma.carbon +++ b/toolchain/semantics/testdata/function/call/params_one_comma.carbon @@ -27,13 +27,15 @@ // CHECK:STDOUT: {kind: VarStorage, type: type0}, // CHECK:STDOUT: {kind: BindName, arg0: str1, arg1: node+0, type: type0}, // CHECK:STDOUT: {kind: FunctionDeclaration, arg0: function0}, +// CHECK:STDOUT: {kind: Return}, // CHECK:STDOUT: {kind: FunctionDeclaration, arg0: function1}, // CHECK:STDOUT: {kind: IntegerLiteral, arg0: int0, type: type0}, -// CHECK:STDOUT: {kind: StubReference, arg0: node+4, type: type0}, +// CHECK:STDOUT: {kind: StubReference, arg0: node+5, type: type0}, // CHECK:STDOUT: {kind: Call, arg0: block6, arg1: function0}, // CHECK:STDOUT: {kind: IntegerLiteral, arg0: int1, type: type0}, -// CHECK:STDOUT: {kind: StubReference, arg0: node+7, type: type0}, +// CHECK:STDOUT: {kind: StubReference, arg0: node+8, type: type0}, // CHECK:STDOUT: {kind: Call, arg0: block7, arg1: function0}, +// CHECK:STDOUT: {kind: Return}, // CHECK:STDOUT: ] // CHECK:STDOUT: node_blocks: [ // CHECK:STDOUT: [ @@ -47,23 +49,25 @@ // CHECK:STDOUT: ], // CHECK:STDOUT: [ // CHECK:STDOUT: node+2, +// CHECK:STDOUT: node+4, +// CHECK:STDOUT: ], +// CHECK:STDOUT: [ // CHECK:STDOUT: node+3, // CHECK:STDOUT: ], // CHECK:STDOUT: [ -// CHECK:STDOUT: ], -// CHECK:STDOUT: [ -// CHECK:STDOUT: node+4, // CHECK:STDOUT: node+5, // CHECK:STDOUT: node+6, // CHECK:STDOUT: node+7, // CHECK:STDOUT: node+8, // CHECK:STDOUT: node+9, +// CHECK:STDOUT: node+10, +// CHECK:STDOUT: node+11, // CHECK:STDOUT: ], // CHECK:STDOUT: [ -// CHECK:STDOUT: node+5, +// CHECK:STDOUT: node+6, // CHECK:STDOUT: ], // CHECK:STDOUT: [ -// CHECK:STDOUT: node+8, +// CHECK:STDOUT: node+9, // CHECK:STDOUT: ], // CHECK:STDOUT: ] diff --git a/toolchain/semantics/testdata/function/call/params_two.carbon b/toolchain/semantics/testdata/function/call/params_two.carbon index 893f1db00758..eb4d2f9fda36 100644 --- a/toolchain/semantics/testdata/function/call/params_two.carbon +++ b/toolchain/semantics/testdata/function/call/params_two.carbon @@ -30,12 +30,14 @@ // CHECK:STDOUT: {kind: VarStorage, type: type0}, // CHECK:STDOUT: {kind: BindName, arg0: str2, arg1: node+2, type: type0}, // CHECK:STDOUT: {kind: FunctionDeclaration, arg0: function0}, +// CHECK:STDOUT: {kind: Return}, // CHECK:STDOUT: {kind: FunctionDeclaration, arg0: function1}, // CHECK:STDOUT: {kind: IntegerLiteral, arg0: int0, type: type0}, -// CHECK:STDOUT: {kind: StubReference, arg0: node+6, type: type0}, +// CHECK:STDOUT: {kind: StubReference, arg0: node+7, type: type0}, // CHECK:STDOUT: {kind: IntegerLiteral, arg0: int1, type: type0}, -// CHECK:STDOUT: {kind: StubReference, arg0: node+8, type: type0}, +// CHECK:STDOUT: {kind: StubReference, arg0: node+9, type: type0}, // CHECK:STDOUT: {kind: Call, arg0: block6, arg1: function0}, +// CHECK:STDOUT: {kind: Return}, // CHECK:STDOUT: ] // CHECK:STDOUT: node_blocks: [ // CHECK:STDOUT: [ @@ -52,20 +54,22 @@ // CHECK:STDOUT: ], // CHECK:STDOUT: [ // CHECK:STDOUT: node+4, +// CHECK:STDOUT: node+6, +// CHECK:STDOUT: ], +// CHECK:STDOUT: [ // CHECK:STDOUT: node+5, // CHECK:STDOUT: ], // CHECK:STDOUT: [ -// CHECK:STDOUT: ], -// CHECK:STDOUT: [ -// CHECK:STDOUT: node+6, // CHECK:STDOUT: node+7, // CHECK:STDOUT: node+8, // CHECK:STDOUT: node+9, // CHECK:STDOUT: node+10, +// CHECK:STDOUT: node+11, +// CHECK:STDOUT: node+12, // CHECK:STDOUT: ], // CHECK:STDOUT: [ -// CHECK:STDOUT: node+7, -// CHECK:STDOUT: node+9, +// CHECK:STDOUT: node+8, +// CHECK:STDOUT: node+10, // CHECK:STDOUT: ], // CHECK:STDOUT: ] diff --git a/toolchain/semantics/testdata/function/call/params_two_comma.carbon b/toolchain/semantics/testdata/function/call/params_two_comma.carbon index 52082dde2a39..64842c3ab69b 100644 --- a/toolchain/semantics/testdata/function/call/params_two_comma.carbon +++ b/toolchain/semantics/testdata/function/call/params_two_comma.carbon @@ -32,17 +32,19 @@ // CHECK:STDOUT: {kind: VarStorage, type: type0}, // CHECK:STDOUT: {kind: BindName, arg0: str2, arg1: node+2, type: type0}, // CHECK:STDOUT: {kind: FunctionDeclaration, arg0: function0}, +// CHECK:STDOUT: {kind: Return}, // CHECK:STDOUT: {kind: FunctionDeclaration, arg0: function1}, // CHECK:STDOUT: {kind: IntegerLiteral, arg0: int0, type: type0}, -// CHECK:STDOUT: {kind: StubReference, arg0: node+6, type: type0}, +// CHECK:STDOUT: {kind: StubReference, arg0: node+7, type: type0}, // CHECK:STDOUT: {kind: IntegerLiteral, arg0: int1, type: type0}, -// CHECK:STDOUT: {kind: StubReference, arg0: node+8, type: type0}, +// CHECK:STDOUT: {kind: StubReference, arg0: node+9, type: type0}, // CHECK:STDOUT: {kind: Call, arg0: block6, arg1: function0}, // CHECK:STDOUT: {kind: IntegerLiteral, arg0: int2, type: type0}, -// CHECK:STDOUT: {kind: StubReference, arg0: node+11, type: type0}, +// CHECK:STDOUT: {kind: StubReference, arg0: node+12, type: type0}, // CHECK:STDOUT: {kind: IntegerLiteral, arg0: int3, type: type0}, -// CHECK:STDOUT: {kind: StubReference, arg0: node+13, type: type0}, +// CHECK:STDOUT: {kind: StubReference, arg0: node+14, type: type0}, // CHECK:STDOUT: {kind: Call, arg0: block7, arg1: function0}, +// CHECK:STDOUT: {kind: Return}, // CHECK:STDOUT: ] // CHECK:STDOUT: node_blocks: [ // CHECK:STDOUT: [ @@ -59,12 +61,12 @@ // CHECK:STDOUT: ], // CHECK:STDOUT: [ // CHECK:STDOUT: node+4, +// CHECK:STDOUT: node+6, +// CHECK:STDOUT: ], +// CHECK:STDOUT: [ // CHECK:STDOUT: node+5, // CHECK:STDOUT: ], // CHECK:STDOUT: [ -// CHECK:STDOUT: ], -// CHECK:STDOUT: [ -// CHECK:STDOUT: node+6, // CHECK:STDOUT: node+7, // CHECK:STDOUT: node+8, // CHECK:STDOUT: node+9, @@ -74,14 +76,16 @@ // CHECK:STDOUT: node+13, // CHECK:STDOUT: node+14, // CHECK:STDOUT: node+15, +// CHECK:STDOUT: node+16, +// CHECK:STDOUT: node+17, // CHECK:STDOUT: ], // CHECK:STDOUT: [ -// CHECK:STDOUT: node+7, -// CHECK:STDOUT: node+9, +// CHECK:STDOUT: node+8, +// CHECK:STDOUT: node+10, // CHECK:STDOUT: ], // CHECK:STDOUT: [ -// CHECK:STDOUT: node+12, -// CHECK:STDOUT: node+14, +// CHECK:STDOUT: node+13, +// CHECK:STDOUT: node+15, // CHECK:STDOUT: ], // CHECK:STDOUT: ] diff --git a/toolchain/semantics/testdata/function/call/params_zero.carbon b/toolchain/semantics/testdata/function/call/params_zero.carbon index ba47b6cf0223..8a0a6ad15fb5 100644 --- a/toolchain/semantics/testdata/function/call/params_zero.carbon +++ b/toolchain/semantics/testdata/function/call/params_zero.carbon @@ -21,20 +21,24 @@ // CHECK:STDOUT: ] // CHECK:STDOUT: nodes: [ // CHECK:STDOUT: {kind: FunctionDeclaration, arg0: function0}, +// CHECK:STDOUT: {kind: Return}, // CHECK:STDOUT: {kind: FunctionDeclaration, arg0: function1}, // CHECK:STDOUT: {kind: Call, arg0: block0, arg1: function0}, +// CHECK:STDOUT: {kind: Return}, // CHECK:STDOUT: ] // CHECK:STDOUT: node_blocks: [ // CHECK:STDOUT: [ // CHECK:STDOUT: ], // CHECK:STDOUT: [ // CHECK:STDOUT: node+0, +// CHECK:STDOUT: node+2, +// CHECK:STDOUT: ], +// CHECK:STDOUT: [ // CHECK:STDOUT: node+1, // CHECK:STDOUT: ], // CHECK:STDOUT: [ -// CHECK:STDOUT: ], -// CHECK:STDOUT: [ -// CHECK:STDOUT: node+2, +// CHECK:STDOUT: node+3, +// CHECK:STDOUT: node+4, // CHECK:STDOUT: ], // CHECK:STDOUT: ] diff --git a/toolchain/semantics/testdata/function/definition/fail_param_name_conflict.carbon b/toolchain/semantics/testdata/function/definition/fail_param_name_conflict.carbon index 2691ad495b3d..1c2c5ad3fc5e 100644 --- a/toolchain/semantics/testdata/function/definition/fail_param_name_conflict.carbon +++ b/toolchain/semantics/testdata/function/definition/fail_param_name_conflict.carbon @@ -25,6 +25,7 @@ // CHECK:STDOUT: {kind: VarStorage, type: type0}, // CHECK:STDOUT: {kind: BindName, arg0: str1, arg1: node+2, type: type0}, // CHECK:STDOUT: {kind: FunctionDeclaration, arg0: function0}, +// CHECK:STDOUT: {kind: Return}, // CHECK:STDOUT: ] // CHECK:STDOUT: node_blocks: [ // CHECK:STDOUT: [ @@ -43,6 +44,7 @@ // CHECK:STDOUT: node+4, // CHECK:STDOUT: ], // CHECK:STDOUT: [ +// CHECK:STDOUT: node+5, // CHECK:STDOUT: ], // CHECK:STDOUT: ] diff --git a/toolchain/semantics/testdata/function/definition/order.carbon b/toolchain/semantics/testdata/function/definition/order.carbon index b0d4a7c33673..94bd2aa695fe 100644 --- a/toolchain/semantics/testdata/function/definition/order.carbon +++ b/toolchain/semantics/testdata/function/definition/order.carbon @@ -23,22 +23,28 @@ // CHECK:STDOUT: ] // CHECK:STDOUT: nodes: [ // CHECK:STDOUT: {kind: FunctionDeclaration, arg0: function0}, +// CHECK:STDOUT: {kind: Return}, // CHECK:STDOUT: {kind: FunctionDeclaration, arg0: function1}, +// CHECK:STDOUT: {kind: Return}, // CHECK:STDOUT: {kind: FunctionDeclaration, arg0: function2}, +// CHECK:STDOUT: {kind: Return}, // CHECK:STDOUT: ] // CHECK:STDOUT: node_blocks: [ // CHECK:STDOUT: [ // CHECK:STDOUT: ], // CHECK:STDOUT: [ // CHECK:STDOUT: node+0, -// CHECK:STDOUT: node+1, // CHECK:STDOUT: node+2, +// CHECK:STDOUT: node+4, // CHECK:STDOUT: ], // CHECK:STDOUT: [ +// CHECK:STDOUT: node+1, // CHECK:STDOUT: ], // CHECK:STDOUT: [ +// CHECK:STDOUT: node+3, // CHECK:STDOUT: ], // CHECK:STDOUT: [ +// CHECK:STDOUT: node+5, // CHECK:STDOUT: ], // CHECK:STDOUT: ] diff --git a/toolchain/semantics/testdata/function/definition/params_one.carbon b/toolchain/semantics/testdata/function/definition/params_one.carbon index ec93f6453d61..6ad93f8d8e3e 100644 --- a/toolchain/semantics/testdata/function/definition/params_one.carbon +++ b/toolchain/semantics/testdata/function/definition/params_one.carbon @@ -23,6 +23,7 @@ // CHECK:STDOUT: {kind: VarStorage, type: type0}, // CHECK:STDOUT: {kind: BindName, arg0: str1, arg1: node+0, type: type0}, // CHECK:STDOUT: {kind: FunctionDeclaration, arg0: function0}, +// CHECK:STDOUT: {kind: Return}, // CHECK:STDOUT: ] // CHECK:STDOUT: node_blocks: [ // CHECK:STDOUT: [ @@ -38,6 +39,7 @@ // CHECK:STDOUT: node+2, // CHECK:STDOUT: ], // CHECK:STDOUT: [ +// CHECK:STDOUT: node+3, // CHECK:STDOUT: ], // CHECK:STDOUT: ] diff --git a/toolchain/semantics/testdata/function/definition/params_one_comma.carbon b/toolchain/semantics/testdata/function/definition/params_one_comma.carbon index d703aa47c1d8..01fd8fd75b33 100644 --- a/toolchain/semantics/testdata/function/definition/params_one_comma.carbon +++ b/toolchain/semantics/testdata/function/definition/params_one_comma.carbon @@ -23,6 +23,7 @@ // CHECK:STDOUT: {kind: VarStorage, type: type0}, // CHECK:STDOUT: {kind: BindName, arg0: str1, arg1: node+0, type: type0}, // CHECK:STDOUT: {kind: FunctionDeclaration, arg0: function0}, +// CHECK:STDOUT: {kind: Return}, // CHECK:STDOUT: ] // CHECK:STDOUT: node_blocks: [ // CHECK:STDOUT: [ @@ -38,6 +39,7 @@ // CHECK:STDOUT: node+2, // CHECK:STDOUT: ], // CHECK:STDOUT: [ +// CHECK:STDOUT: node+3, // CHECK:STDOUT: ], // CHECK:STDOUT: ] diff --git a/toolchain/semantics/testdata/function/definition/params_two.carbon b/toolchain/semantics/testdata/function/definition/params_two.carbon index f4e84cdb3aa1..ef3a2ef10d10 100644 --- a/toolchain/semantics/testdata/function/definition/params_two.carbon +++ b/toolchain/semantics/testdata/function/definition/params_two.carbon @@ -26,6 +26,7 @@ // CHECK:STDOUT: {kind: VarStorage, type: type0}, // CHECK:STDOUT: {kind: BindName, arg0: str2, arg1: node+2, type: type0}, // CHECK:STDOUT: {kind: FunctionDeclaration, arg0: function0}, +// CHECK:STDOUT: {kind: Return}, // CHECK:STDOUT: ] // CHECK:STDOUT: node_blocks: [ // CHECK:STDOUT: [ @@ -44,6 +45,7 @@ // CHECK:STDOUT: node+4, // CHECK:STDOUT: ], // CHECK:STDOUT: [ +// CHECK:STDOUT: node+5, // CHECK:STDOUT: ], // CHECK:STDOUT: ] diff --git a/toolchain/semantics/testdata/function/definition/params_two_comma.carbon b/toolchain/semantics/testdata/function/definition/params_two_comma.carbon index 2a876e6953fb..2266ae5d90ff 100644 --- a/toolchain/semantics/testdata/function/definition/params_two_comma.carbon +++ b/toolchain/semantics/testdata/function/definition/params_two_comma.carbon @@ -26,6 +26,7 @@ // CHECK:STDOUT: {kind: VarStorage, type: type0}, // CHECK:STDOUT: {kind: BindName, arg0: str2, arg1: node+2, type: type0}, // CHECK:STDOUT: {kind: FunctionDeclaration, arg0: function0}, +// CHECK:STDOUT: {kind: Return}, // CHECK:STDOUT: ] // CHECK:STDOUT: node_blocks: [ // CHECK:STDOUT: [ @@ -44,6 +45,7 @@ // CHECK:STDOUT: node+4, // CHECK:STDOUT: ], // CHECK:STDOUT: [ +// CHECK:STDOUT: node+5, // CHECK:STDOUT: ], // CHECK:STDOUT: ] diff --git a/toolchain/semantics/testdata/function/definition/params_zero.carbon b/toolchain/semantics/testdata/function/definition/params_zero.carbon index 93d9c47a51c8..3d563729dfc7 100644 --- a/toolchain/semantics/testdata/function/definition/params_zero.carbon +++ b/toolchain/semantics/testdata/function/definition/params_zero.carbon @@ -19,6 +19,7 @@ // CHECK:STDOUT: ] // CHECK:STDOUT: nodes: [ // CHECK:STDOUT: {kind: FunctionDeclaration, arg0: function0}, +// CHECK:STDOUT: {kind: Return}, // CHECK:STDOUT: ] // CHECK:STDOUT: node_blocks: [ // CHECK:STDOUT: [ @@ -27,6 +28,7 @@ // CHECK:STDOUT: node+0, // CHECK:STDOUT: ], // CHECK:STDOUT: [ +// CHECK:STDOUT: node+1, // CHECK:STDOUT: ], // CHECK:STDOUT: ] diff --git a/toolchain/semantics/testdata/function/definition/same_param_name.carbon b/toolchain/semantics/testdata/function/definition/same_param_name.carbon index a6463c5bf990..3244f4099983 100644 --- a/toolchain/semantics/testdata/function/definition/same_param_name.carbon +++ b/toolchain/semantics/testdata/function/definition/same_param_name.carbon @@ -25,9 +25,11 @@ // CHECK:STDOUT: {kind: VarStorage, type: type0}, // CHECK:STDOUT: {kind: BindName, arg0: str1, arg1: node+0, type: type0}, // CHECK:STDOUT: {kind: FunctionDeclaration, arg0: function0}, +// CHECK:STDOUT: {kind: Return}, // CHECK:STDOUT: {kind: VarStorage, type: type0}, -// CHECK:STDOUT: {kind: BindName, arg0: str1, arg1: node+3, type: type0}, +// CHECK:STDOUT: {kind: BindName, arg0: str1, arg1: node+4, type: type0}, // CHECK:STDOUT: {kind: FunctionDeclaration, arg0: function1}, +// CHECK:STDOUT: {kind: Return}, // CHECK:STDOUT: ] // CHECK:STDOUT: node_blocks: [ // CHECK:STDOUT: [ @@ -41,18 +43,20 @@ // CHECK:STDOUT: ], // CHECK:STDOUT: [ // CHECK:STDOUT: node+2, -// CHECK:STDOUT: node+5, -// CHECK:STDOUT: ], -// CHECK:STDOUT: [ +// CHECK:STDOUT: node+6, // CHECK:STDOUT: ], // CHECK:STDOUT: [ // CHECK:STDOUT: node+3, -// CHECK:STDOUT: node+4, // CHECK:STDOUT: ], // CHECK:STDOUT: [ // CHECK:STDOUT: node+4, +// CHECK:STDOUT: node+5, // CHECK:STDOUT: ], // CHECK:STDOUT: [ +// CHECK:STDOUT: node+5, +// CHECK:STDOUT: ], +// CHECK:STDOUT: [ +// CHECK:STDOUT: node+7, // CHECK:STDOUT: ], // CHECK:STDOUT: ] diff --git a/toolchain/semantics/testdata/if/else.carbon b/toolchain/semantics/testdata/if/else.carbon index 78fdd85b6426..66f37ede3585 100644 --- a/toolchain/semantics/testdata/if/else.carbon +++ b/toolchain/semantics/testdata/if/else.carbon @@ -8,7 +8,7 @@ // CHECK:STDOUT: {name: str0, param_refs: block0, body: {block2}}}, // CHECK:STDOUT: {name: str1, param_refs: block0, body: {block3}}}, // CHECK:STDOUT: {name: str2, param_refs: block0, body: {block4}}}, -// CHECK:STDOUT: {name: str3, param_refs: block6, body: {block7, block9, block8, block10}}}, +// CHECK:STDOUT: {name: str3, param_refs: block6, body: {block7, block8, block9, block10}}}, // CHECK:STDOUT: ] // CHECK:STDOUT: integer_literals: [ // CHECK:STDOUT: ] @@ -27,55 +27,63 @@ // CHECK:STDOUT: ] // CHECK:STDOUT: nodes: [ // CHECK:STDOUT: {kind: FunctionDeclaration, arg0: function0}, +// CHECK:STDOUT: {kind: Return}, // CHECK:STDOUT: {kind: FunctionDeclaration, arg0: function1}, +// CHECK:STDOUT: {kind: Return}, // CHECK:STDOUT: {kind: FunctionDeclaration, arg0: function2}, +// CHECK:STDOUT: {kind: Return}, // CHECK:STDOUT: {kind: VarStorage, type: type1}, -// CHECK:STDOUT: {kind: BindName, arg0: str4, arg1: node+3, type: type1}, +// CHECK:STDOUT: {kind: BindName, arg0: str4, arg1: node+6, type: type1}, // CHECK:STDOUT: {kind: FunctionDeclaration, arg0: function3}, -// CHECK:STDOUT: {kind: BranchIf, arg0: block9, arg1: node+3}, -// CHECK:STDOUT: {kind: Branch, arg0: block8}, +// CHECK:STDOUT: {kind: BranchIf, arg0: block8, arg1: node+6}, +// CHECK:STDOUT: {kind: Branch, arg0: block9}, // CHECK:STDOUT: {kind: Call, arg0: block0, arg1: function0}, // CHECK:STDOUT: {kind: Call, arg0: block0, arg1: function1}, // CHECK:STDOUT: {kind: Branch, arg0: block10}, // CHECK:STDOUT: {kind: Branch, arg0: block10}, // CHECK:STDOUT: {kind: Call, arg0: block0, arg1: function2}, +// CHECK:STDOUT: {kind: Return}, // CHECK:STDOUT: ] // CHECK:STDOUT: node_blocks: [ // CHECK:STDOUT: [ // CHECK:STDOUT: ], // CHECK:STDOUT: [ // CHECK:STDOUT: node+0, -// CHECK:STDOUT: node+1, // CHECK:STDOUT: node+2, -// CHECK:STDOUT: node+5, -// CHECK:STDOUT: ], -// CHECK:STDOUT: [ -// CHECK:STDOUT: ], -// CHECK:STDOUT: [ +// CHECK:STDOUT: node+4, +// CHECK:STDOUT: node+8, // CHECK:STDOUT: ], // CHECK:STDOUT: [ +// CHECK:STDOUT: node+1, // CHECK:STDOUT: ], // CHECK:STDOUT: [ // CHECK:STDOUT: node+3, -// CHECK:STDOUT: node+4, // CHECK:STDOUT: ], // CHECK:STDOUT: [ -// CHECK:STDOUT: node+4, +// CHECK:STDOUT: node+5, // CHECK:STDOUT: ], // CHECK:STDOUT: [ // CHECK:STDOUT: node+6, // CHECK:STDOUT: node+7, // CHECK:STDOUT: ], // CHECK:STDOUT: [ -// CHECK:STDOUT: node+9, -// CHECK:STDOUT: node+11, +// CHECK:STDOUT: node+7, // CHECK:STDOUT: ], // CHECK:STDOUT: [ -// CHECK:STDOUT: node+8, +// CHECK:STDOUT: node+9, // CHECK:STDOUT: node+10, // CHECK:STDOUT: ], // CHECK:STDOUT: [ +// CHECK:STDOUT: node+11, +// CHECK:STDOUT: node+13, +// CHECK:STDOUT: ], +// CHECK:STDOUT: [ // CHECK:STDOUT: node+12, +// CHECK:STDOUT: node+14, +// CHECK:STDOUT: ], +// CHECK:STDOUT: [ +// CHECK:STDOUT: node+15, +// CHECK:STDOUT: node+16, // CHECK:STDOUT: ], // CHECK:STDOUT: ] diff --git a/toolchain/semantics/testdata/if/fail_reachable_fallthrough.carbon b/toolchain/semantics/testdata/if/fail_reachable_fallthrough.carbon new file mode 100644 index 000000000000..08d642c6c55f --- /dev/null +++ b/toolchain/semantics/testdata/if/fail_reachable_fallthrough.carbon @@ -0,0 +1,143 @@ +// Part of the Carbon Language project, under the Apache License v2.0 with LLVM +// Exceptions. See /LICENSE for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +// AUTOUPDATE +// CHECK:STDOUT: cross_reference_irs_size: 1 +// CHECK:STDOUT: functions: [ +// CHECK:STDOUT: {name: str0, param_refs: block2, return_type: type1, body: {block4, block5, block6, block7}}}, +// CHECK:STDOUT: {name: str2, param_refs: block9, return_type: type1, body: {block10, block11, block12, block13}}}, +// CHECK:STDOUT: {name: str3, param_refs: block15, return_type: type1, body: {block16, block17, block18}}}, +// CHECK:STDOUT: ] +// CHECK:STDOUT: integer_literals: [ +// CHECK:STDOUT: 1, +// CHECK:STDOUT: 2, +// CHECK:STDOUT: 1, +// CHECK:STDOUT: ] +// CHECK:STDOUT: real_literals: [ +// CHECK:STDOUT: ] +// CHECK:STDOUT: strings: [ +// CHECK:STDOUT: If1, +// CHECK:STDOUT: b, +// CHECK:STDOUT: If2, +// CHECK:STDOUT: If3, +// CHECK:STDOUT: ] +// CHECK:STDOUT: types: [ +// CHECK:STDOUT: nodeBoolType, +// CHECK:STDOUT: nodeIntegerType, +// CHECK:STDOUT: ] +// CHECK:STDOUT: nodes: [ +// CHECK:STDOUT: {kind: VarStorage, type: type0}, +// CHECK:STDOUT: {kind: BindName, arg0: str1, arg1: node+0, type: type0}, +// CHECK:STDOUT: {kind: FunctionDeclaration, arg0: function0}, +// CHECK:STDOUT: {kind: BranchIf, arg0: block5, arg1: node+0}, +// CHECK:STDOUT: {kind: Branch, arg0: block6}, +// CHECK:STDOUT: {kind: IntegerLiteral, arg0: int0, type: type1}, +// CHECK:STDOUT: {kind: ReturnExpression, arg0: node+5, type: type1}, +// CHECK:STDOUT: {kind: Branch, arg0: block7}, +// CHECK:STDOUT: {kind: VarStorage, type: type0}, +// CHECK:STDOUT: {kind: BindName, arg0: str1, arg1: node+8, type: type0}, +// CHECK:STDOUT: {kind: FunctionDeclaration, arg0: function1}, +// CHECK:STDOUT: {kind: BranchIf, arg0: block11, arg1: node+8}, +// CHECK:STDOUT: {kind: Branch, arg0: block12}, +// CHECK:STDOUT: {kind: IntegerLiteral, arg0: int1, type: type1}, +// CHECK:STDOUT: {kind: ReturnExpression, arg0: node+13, type: type1}, +// CHECK:STDOUT: {kind: Branch, arg0: block13}, +// CHECK:STDOUT: {kind: VarStorage, type: type0}, +// CHECK:STDOUT: {kind: BindName, arg0: str1, arg1: node+16, type: type0}, +// CHECK:STDOUT: {kind: FunctionDeclaration, arg0: function2}, +// CHECK:STDOUT: {kind: BranchIf, arg0: block17, arg1: node+16}, +// CHECK:STDOUT: {kind: Branch, arg0: block18}, +// CHECK:STDOUT: {kind: IntegerLiteral, arg0: int2, type: type1}, +// CHECK:STDOUT: {kind: ReturnExpression, arg0: node+21, type: type1}, +// CHECK:STDOUT: {kind: Branch, arg0: block18}, +// CHECK:STDOUT: ] +// CHECK:STDOUT: node_blocks: [ +// CHECK:STDOUT: [ +// CHECK:STDOUT: ], +// CHECK:STDOUT: [ +// CHECK:STDOUT: node+0, +// CHECK:STDOUT: node+1, +// CHECK:STDOUT: ], +// CHECK:STDOUT: [ +// CHECK:STDOUT: node+1, +// CHECK:STDOUT: ], +// CHECK:STDOUT: [ +// CHECK:STDOUT: node+2, +// CHECK:STDOUT: node+10, +// CHECK:STDOUT: node+18, +// CHECK:STDOUT: ], +// CHECK:STDOUT: [ +// CHECK:STDOUT: node+3, +// CHECK:STDOUT: node+4, +// CHECK:STDOUT: ], +// CHECK:STDOUT: [ +// CHECK:STDOUT: node+5, +// CHECK:STDOUT: node+6, +// CHECK:STDOUT: ], +// CHECK:STDOUT: [ +// CHECK:STDOUT: node+7, +// CHECK:STDOUT: ], +// CHECK:STDOUT: [ +// CHECK:STDOUT: ], +// CHECK:STDOUT: [ +// CHECK:STDOUT: node+8, +// CHECK:STDOUT: node+9, +// CHECK:STDOUT: ], +// CHECK:STDOUT: [ +// CHECK:STDOUT: node+9, +// CHECK:STDOUT: ], +// CHECK:STDOUT: [ +// CHECK:STDOUT: node+11, +// CHECK:STDOUT: node+12, +// CHECK:STDOUT: ], +// CHECK:STDOUT: [ +// CHECK:STDOUT: node+15, +// CHECK:STDOUT: ], +// CHECK:STDOUT: [ +// CHECK:STDOUT: node+13, +// CHECK:STDOUT: node+14, +// CHECK:STDOUT: ], +// CHECK:STDOUT: [ +// CHECK:STDOUT: ], +// CHECK:STDOUT: [ +// CHECK:STDOUT: node+16, +// CHECK:STDOUT: node+17, +// CHECK:STDOUT: ], +// CHECK:STDOUT: [ +// CHECK:STDOUT: node+17, +// CHECK:STDOUT: ], +// CHECK:STDOUT: [ +// CHECK:STDOUT: node+19, +// CHECK:STDOUT: node+20, +// CHECK:STDOUT: ], +// CHECK:STDOUT: [ +// CHECK:STDOUT: node+21, +// CHECK:STDOUT: node+22, +// CHECK:STDOUT: ], +// CHECK:STDOUT: [ +// CHECK:STDOUT: ], +// CHECK:STDOUT: ] + +fn If1(b: bool) -> i32 { + if (b) { + return 1; + } else { + } +// CHECK:STDERR: fail_reachable_fallthrough.carbon:[[@LINE+1]]:1: Missing `return` at end of function with declared return type. +} + +fn If2(b: bool) -> i32 { + if (b) { + } else { + return 2; + } +// CHECK:STDERR: fail_reachable_fallthrough.carbon:[[@LINE+1]]:1: Missing `return` at end of function with declared return type. +} + +fn If3(b: bool) -> i32 { + if (b) { + return 1; + } +// CHECK:STDERR: fail_reachable_fallthrough.carbon:[[@LINE+1]]:1: Missing `return` at end of function with declared return type. +} diff --git a/toolchain/semantics/testdata/if/fail_scope.carbon b/toolchain/semantics/testdata/if/fail_scope.carbon index 668e4ac5adf0..e54effa722f9 100644 --- a/toolchain/semantics/testdata/if/fail_scope.carbon +++ b/toolchain/semantics/testdata/if/fail_scope.carbon @@ -5,7 +5,7 @@ // AUTOUPDATE // CHECK:STDOUT: cross_reference_irs_size: 1 // CHECK:STDOUT: functions: [ -// CHECK:STDOUT: {name: str0, param_refs: block2, return_type: type1, body: {block4, block6, block5}}}, +// CHECK:STDOUT: {name: str0, param_refs: block2, return_type: type1, body: {block4, block5, block6}}}, // CHECK:STDOUT: ] // CHECK:STDOUT: integer_literals: [ // CHECK:STDOUT: 2, @@ -25,14 +25,14 @@ // CHECK:STDOUT: {kind: VarStorage, type: type0}, // CHECK:STDOUT: {kind: BindName, arg0: str1, arg1: node+0, type: type0}, // CHECK:STDOUT: {kind: FunctionDeclaration, arg0: function0}, -// CHECK:STDOUT: {kind: BranchIf, arg0: block6, arg1: node+0}, -// CHECK:STDOUT: {kind: Branch, arg0: block5}, +// CHECK:STDOUT: {kind: BranchIf, arg0: block5, arg1: node+0}, +// CHECK:STDOUT: {kind: Branch, arg0: block6}, // CHECK:STDOUT: {kind: VarStorage, type: type1}, // CHECK:STDOUT: {kind: BindName, arg0: str2, arg1: node+5, type: type1}, // CHECK:STDOUT: {kind: IntegerLiteral, arg0: int0, type: type1}, // CHECK:STDOUT: {kind: Assign, arg0: node+5, arg1: node+7, type: type1}, // CHECK:STDOUT: {kind: ReturnExpression, arg0: node+5, type: type1}, -// CHECK:STDOUT: {kind: Branch, arg0: block5}, +// CHECK:STDOUT: {kind: Branch, arg0: block6}, // CHECK:STDOUT: {kind: ReturnExpression, arg0: nodeInvalidType, type: typeInvalidType}, // CHECK:STDOUT: ] // CHECK:STDOUT: node_blocks: [ @@ -53,15 +53,14 @@ // CHECK:STDOUT: node+4, // CHECK:STDOUT: ], // CHECK:STDOUT: [ -// CHECK:STDOUT: node+11, -// CHECK:STDOUT: ], -// CHECK:STDOUT: [ // CHECK:STDOUT: node+5, // CHECK:STDOUT: node+6, // CHECK:STDOUT: node+7, // CHECK:STDOUT: node+8, // CHECK:STDOUT: node+9, -// CHECK:STDOUT: node+10, +// CHECK:STDOUT: ], +// CHECK:STDOUT: [ +// CHECK:STDOUT: node+11, // CHECK:STDOUT: ], // CHECK:STDOUT: ] diff --git a/toolchain/semantics/testdata/if/no_else.carbon b/toolchain/semantics/testdata/if/no_else.carbon index 1c72ed43418b..3c23ab994d3a 100644 --- a/toolchain/semantics/testdata/if/no_else.carbon +++ b/toolchain/semantics/testdata/if/no_else.carbon @@ -7,7 +7,7 @@ // CHECK:STDOUT: functions: [ // CHECK:STDOUT: {name: str0, param_refs: block0, body: {block2}}}, // CHECK:STDOUT: {name: str1, param_refs: block0, body: {block3}}}, -// CHECK:STDOUT: {name: str2, param_refs: block5, body: {block6, block8, block7}}}, +// CHECK:STDOUT: {name: str2, param_refs: block5, body: {block6, block7, block8}}}, // CHECK:STDOUT: ] // CHECK:STDOUT: integer_literals: [ // CHECK:STDOUT: ] @@ -25,46 +25,52 @@ // CHECK:STDOUT: ] // CHECK:STDOUT: nodes: [ // CHECK:STDOUT: {kind: FunctionDeclaration, arg0: function0}, +// CHECK:STDOUT: {kind: Return}, // CHECK:STDOUT: {kind: FunctionDeclaration, arg0: function1}, +// CHECK:STDOUT: {kind: Return}, // CHECK:STDOUT: {kind: VarStorage, type: type1}, -// CHECK:STDOUT: {kind: BindName, arg0: str3, arg1: node+2, type: type1}, +// CHECK:STDOUT: {kind: BindName, arg0: str3, arg1: node+4, type: type1}, // CHECK:STDOUT: {kind: FunctionDeclaration, arg0: function2}, -// CHECK:STDOUT: {kind: BranchIf, arg0: block8, arg1: node+2}, -// CHECK:STDOUT: {kind: Branch, arg0: block7}, +// CHECK:STDOUT: {kind: BranchIf, arg0: block7, arg1: node+4}, +// CHECK:STDOUT: {kind: Branch, arg0: block8}, // CHECK:STDOUT: {kind: Call, arg0: block0, arg1: function0}, -// CHECK:STDOUT: {kind: Branch, arg0: block7}, +// CHECK:STDOUT: {kind: Branch, arg0: block8}, // CHECK:STDOUT: {kind: Call, arg0: block0, arg1: function1}, +// CHECK:STDOUT: {kind: Return}, // CHECK:STDOUT: ] // CHECK:STDOUT: node_blocks: [ // CHECK:STDOUT: [ // CHECK:STDOUT: ], // CHECK:STDOUT: [ // CHECK:STDOUT: node+0, -// CHECK:STDOUT: node+1, -// CHECK:STDOUT: node+4, -// CHECK:STDOUT: ], -// CHECK:STDOUT: [ -// CHECK:STDOUT: ], -// CHECK:STDOUT: [ -// CHECK:STDOUT: ], -// CHECK:STDOUT: [ // CHECK:STDOUT: node+2, -// CHECK:STDOUT: node+3, -// CHECK:STDOUT: ], -// CHECK:STDOUT: [ -// CHECK:STDOUT: node+3, -// CHECK:STDOUT: ], -// CHECK:STDOUT: [ -// CHECK:STDOUT: node+5, // CHECK:STDOUT: node+6, // CHECK:STDOUT: ], // CHECK:STDOUT: [ -// CHECK:STDOUT: node+9, +// CHECK:STDOUT: node+1, +// CHECK:STDOUT: ], +// CHECK:STDOUT: [ +// CHECK:STDOUT: node+3, +// CHECK:STDOUT: ], +// CHECK:STDOUT: [ +// CHECK:STDOUT: node+4, +// CHECK:STDOUT: node+5, +// CHECK:STDOUT: ], +// CHECK:STDOUT: [ +// CHECK:STDOUT: node+5, // CHECK:STDOUT: ], // CHECK:STDOUT: [ // CHECK:STDOUT: node+7, // CHECK:STDOUT: node+8, // CHECK:STDOUT: ], +// CHECK:STDOUT: [ +// CHECK:STDOUT: node+9, +// CHECK:STDOUT: node+10, +// CHECK:STDOUT: ], +// CHECK:STDOUT: [ +// CHECK:STDOUT: node+11, +// CHECK:STDOUT: node+12, +// CHECK:STDOUT: ], // CHECK:STDOUT: ] fn F() {} diff --git a/toolchain/semantics/testdata/if/unreachable_fallthrough.carbon b/toolchain/semantics/testdata/if/unreachable_fallthrough.carbon new file mode 100644 index 000000000000..e81934388b42 --- /dev/null +++ b/toolchain/semantics/testdata/if/unreachable_fallthrough.carbon @@ -0,0 +1,69 @@ +// Part of the Carbon Language project, under the Apache License v2.0 with LLVM +// Exceptions. See /LICENSE for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +// AUTOUPDATE +// CHECK:STDOUT: cross_reference_irs_size: 1 +// CHECK:STDOUT: functions: [ +// CHECK:STDOUT: {name: str0, param_refs: block2, return_type: type1, body: {block4, block5, block6}}}, +// CHECK:STDOUT: ] +// CHECK:STDOUT: integer_literals: [ +// CHECK:STDOUT: 1, +// CHECK:STDOUT: 2, +// CHECK:STDOUT: ] +// CHECK:STDOUT: real_literals: [ +// CHECK:STDOUT: ] +// CHECK:STDOUT: strings: [ +// CHECK:STDOUT: If, +// CHECK:STDOUT: b, +// CHECK:STDOUT: ] +// CHECK:STDOUT: types: [ +// CHECK:STDOUT: nodeBoolType, +// CHECK:STDOUT: nodeIntegerType, +// CHECK:STDOUT: ] +// CHECK:STDOUT: nodes: [ +// CHECK:STDOUT: {kind: VarStorage, type: type0}, +// CHECK:STDOUT: {kind: BindName, arg0: str1, arg1: node+0, type: type0}, +// CHECK:STDOUT: {kind: FunctionDeclaration, arg0: function0}, +// CHECK:STDOUT: {kind: BranchIf, arg0: block5, arg1: node+0}, +// CHECK:STDOUT: {kind: Branch, arg0: block6}, +// CHECK:STDOUT: {kind: IntegerLiteral, arg0: int0, type: type1}, +// CHECK:STDOUT: {kind: ReturnExpression, arg0: node+5, type: type1}, +// CHECK:STDOUT: {kind: IntegerLiteral, arg0: int1, type: type1}, +// CHECK:STDOUT: {kind: ReturnExpression, arg0: node+7, type: type1}, +// CHECK:STDOUT: ] +// CHECK:STDOUT: node_blocks: [ +// CHECK:STDOUT: [ +// CHECK:STDOUT: ], +// CHECK:STDOUT: [ +// CHECK:STDOUT: node+0, +// CHECK:STDOUT: node+1, +// CHECK:STDOUT: ], +// CHECK:STDOUT: [ +// CHECK:STDOUT: node+1, +// CHECK:STDOUT: ], +// CHECK:STDOUT: [ +// CHECK:STDOUT: node+2, +// CHECK:STDOUT: ], +// CHECK:STDOUT: [ +// CHECK:STDOUT: node+3, +// CHECK:STDOUT: node+4, +// CHECK:STDOUT: ], +// CHECK:STDOUT: [ +// CHECK:STDOUT: node+5, +// CHECK:STDOUT: node+6, +// CHECK:STDOUT: ], +// CHECK:STDOUT: [ +// CHECK:STDOUT: node+7, +// CHECK:STDOUT: node+8, +// CHECK:STDOUT: ], +// CHECK:STDOUT: ] + +fn If(b: bool) -> i32 { + if (b) { + return 1; + } else { + return 2; + } + // Missing return here is OK. +} diff --git a/toolchain/semantics/testdata/if_expression/basic.carbon b/toolchain/semantics/testdata/if_expression/basic.carbon index d06fe0908f2f..cc83b51b48e3 100644 --- a/toolchain/semantics/testdata/if_expression/basic.carbon +++ b/toolchain/semantics/testdata/if_expression/basic.carbon @@ -5,7 +5,7 @@ // AUTOUPDATE // CHECK:STDOUT: cross_reference_irs_size: 1 // CHECK:STDOUT: functions: [ -// CHECK:STDOUT: {name: str0, param_refs: block2, return_type: type1, body: {block4, block6, block5, block7}}}, +// CHECK:STDOUT: {name: str0, param_refs: block2, return_type: type1, body: {block4, block5, block6, block7}}}, // CHECK:STDOUT: ] // CHECK:STDOUT: integer_literals: [ // CHECK:STDOUT: ] @@ -29,8 +29,8 @@ // CHECK:STDOUT: {kind: VarStorage, type: type1}, // CHECK:STDOUT: {kind: BindName, arg0: str3, arg1: node+4, type: type1}, // CHECK:STDOUT: {kind: FunctionDeclaration, arg0: function0}, -// CHECK:STDOUT: {kind: BranchIf, arg0: block6, arg1: node+0}, -// CHECK:STDOUT: {kind: Branch, arg0: block5}, +// CHECK:STDOUT: {kind: BranchIf, arg0: block5, arg1: node+0}, +// CHECK:STDOUT: {kind: Branch, arg0: block6}, // CHECK:STDOUT: {kind: BinaryOperatorAdd, arg0: node+2, arg1: node+4, type: type1}, // CHECK:STDOUT: {kind: BinaryOperatorAdd, arg0: node+4, arg1: node+2, type: type1}, // CHECK:STDOUT: {kind: BranchWithArg, arg0: block7, arg1: node+9}, @@ -62,14 +62,14 @@ // CHECK:STDOUT: node+8, // CHECK:STDOUT: ], // CHECK:STDOUT: [ -// CHECK:STDOUT: node+10, -// CHECK:STDOUT: node+12, -// CHECK:STDOUT: ], -// CHECK:STDOUT: [ // CHECK:STDOUT: node+9, // CHECK:STDOUT: node+11, // CHECK:STDOUT: ], // CHECK:STDOUT: [ +// CHECK:STDOUT: node+10, +// CHECK:STDOUT: node+12, +// CHECK:STDOUT: ], +// CHECK:STDOUT: [ // CHECK:STDOUT: node+13, // CHECK:STDOUT: node+14, // CHECK:STDOUT: ], diff --git a/toolchain/semantics/testdata/if_expression/constant_condition.carbon b/toolchain/semantics/testdata/if_expression/constant_condition.carbon index 399ea351e142..ac9f9afb9312 100644 --- a/toolchain/semantics/testdata/if_expression/constant_condition.carbon +++ b/toolchain/semantics/testdata/if_expression/constant_condition.carbon @@ -7,8 +7,8 @@ // CHECK:STDOUT: functions: [ // CHECK:STDOUT: {name: str0, param_refs: block0, return_type: type0, body: {block2}}}, // CHECK:STDOUT: {name: str1, param_refs: block0, return_type: type0, body: {block3}}}, -// CHECK:STDOUT: {name: str2, param_refs: block0, return_type: type0, body: {block4, block6, block5, block7}}}, -// CHECK:STDOUT: {name: str3, param_refs: block0, return_type: type0, body: {block8, block10, block9, block11}}}, +// CHECK:STDOUT: {name: str2, param_refs: block0, return_type: type0, body: {block4, block5, block6, block7}}}, +// CHECK:STDOUT: {name: str3, param_refs: block0, return_type: type0, body: {block8, block9, block10, block11}}}, // CHECK:STDOUT: ] // CHECK:STDOUT: integer_literals: [ // CHECK:STDOUT: 1, @@ -35,8 +35,8 @@ // CHECK:STDOUT: {kind: ReturnExpression, arg0: node+4, type: type0}, // CHECK:STDOUT: {kind: FunctionDeclaration, arg0: function2}, // CHECK:STDOUT: {kind: BoolLiteral, arg0: true, type: type1}, -// CHECK:STDOUT: {kind: BranchIf, arg0: block6, arg1: node+7}, -// CHECK:STDOUT: {kind: Branch, arg0: block5}, +// CHECK:STDOUT: {kind: BranchIf, arg0: block5, arg1: node+7}, +// CHECK:STDOUT: {kind: Branch, arg0: block6}, // CHECK:STDOUT: {kind: Call, arg0: block0, arg1: function0, type: type0}, // CHECK:STDOUT: {kind: Call, arg0: block0, arg1: function1, type: type0}, // CHECK:STDOUT: {kind: BranchWithArg, arg0: block7, arg1: node+10}, @@ -45,8 +45,8 @@ // CHECK:STDOUT: {kind: ReturnExpression, arg0: node+14, type: type0}, // CHECK:STDOUT: {kind: FunctionDeclaration, arg0: function3}, // CHECK:STDOUT: {kind: BoolLiteral, arg0: false, type: type1}, -// CHECK:STDOUT: {kind: BranchIf, arg0: block10, arg1: node+17}, -// CHECK:STDOUT: {kind: Branch, arg0: block9}, +// CHECK:STDOUT: {kind: BranchIf, arg0: block9, arg1: node+17}, +// CHECK:STDOUT: {kind: Branch, arg0: block10}, // CHECK:STDOUT: {kind: Call, arg0: block0, arg1: function0, type: type0}, // CHECK:STDOUT: {kind: Call, arg0: block0, arg1: function1, type: type0}, // CHECK:STDOUT: {kind: BranchWithArg, arg0: block11, arg1: node+20}, @@ -77,14 +77,14 @@ // CHECK:STDOUT: node+9, // CHECK:STDOUT: ], // CHECK:STDOUT: [ -// CHECK:STDOUT: node+11, -// CHECK:STDOUT: node+13, -// CHECK:STDOUT: ], -// CHECK:STDOUT: [ // CHECK:STDOUT: node+10, // CHECK:STDOUT: node+12, // CHECK:STDOUT: ], // CHECK:STDOUT: [ +// CHECK:STDOUT: node+11, +// CHECK:STDOUT: node+13, +// CHECK:STDOUT: ], +// CHECK:STDOUT: [ // CHECK:STDOUT: node+14, // CHECK:STDOUT: node+15, // CHECK:STDOUT: ], @@ -94,14 +94,14 @@ // CHECK:STDOUT: node+19, // CHECK:STDOUT: ], // CHECK:STDOUT: [ -// CHECK:STDOUT: node+21, -// CHECK:STDOUT: node+23, -// CHECK:STDOUT: ], -// CHECK:STDOUT: [ // CHECK:STDOUT: node+20, // CHECK:STDOUT: node+22, // CHECK:STDOUT: ], // CHECK:STDOUT: [ +// CHECK:STDOUT: node+21, +// CHECK:STDOUT: node+23, +// CHECK:STDOUT: ], +// CHECK:STDOUT: [ // CHECK:STDOUT: node+24, // CHECK:STDOUT: node+25, // CHECK:STDOUT: ], diff --git a/toolchain/semantics/testdata/if_expression/control_flow.carbon b/toolchain/semantics/testdata/if_expression/control_flow.carbon index 3e1812e05318..28999d77fcb8 100644 --- a/toolchain/semantics/testdata/if_expression/control_flow.carbon +++ b/toolchain/semantics/testdata/if_expression/control_flow.carbon @@ -7,7 +7,7 @@ // CHECK:STDOUT: functions: [ // CHECK:STDOUT: {name: str0, param_refs: block0, return_type: type0, body: {block2}}}, // CHECK:STDOUT: {name: str1, param_refs: block0, return_type: type0, body: {block3}}}, -// CHECK:STDOUT: {name: str2, param_refs: block5, return_type: type0, body: {block6, block8, block7, block9}}}, +// CHECK:STDOUT: {name: str2, param_refs: block5, return_type: type0, body: {block6, block7, block8, block9}}}, // CHECK:STDOUT: ] // CHECK:STDOUT: integer_literals: [ // CHECK:STDOUT: 1, @@ -35,8 +35,8 @@ // CHECK:STDOUT: {kind: VarStorage, type: type1}, // CHECK:STDOUT: {kind: BindName, arg0: str3, arg1: node+6, type: type1}, // CHECK:STDOUT: {kind: FunctionDeclaration, arg0: function2}, -// CHECK:STDOUT: {kind: BranchIf, arg0: block8, arg1: node+6}, -// CHECK:STDOUT: {kind: Branch, arg0: block7}, +// CHECK:STDOUT: {kind: BranchIf, arg0: block7, arg1: node+6}, +// CHECK:STDOUT: {kind: Branch, arg0: block8}, // CHECK:STDOUT: {kind: Call, arg0: block0, arg1: function0, type: type0}, // CHECK:STDOUT: {kind: Call, arg0: block0, arg1: function1, type: type0}, // CHECK:STDOUT: {kind: BranchWithArg, arg0: block9, arg1: node+11}, @@ -72,14 +72,14 @@ // CHECK:STDOUT: node+10, // CHECK:STDOUT: ], // CHECK:STDOUT: [ -// CHECK:STDOUT: node+12, -// CHECK:STDOUT: node+14, -// CHECK:STDOUT: ], -// CHECK:STDOUT: [ // CHECK:STDOUT: node+11, // CHECK:STDOUT: node+13, // CHECK:STDOUT: ], // CHECK:STDOUT: [ +// CHECK:STDOUT: node+12, +// CHECK:STDOUT: node+14, +// CHECK:STDOUT: ], +// CHECK:STDOUT: [ // CHECK:STDOUT: node+15, // CHECK:STDOUT: node+16, // CHECK:STDOUT: ], diff --git a/toolchain/semantics/testdata/if_expression/nested.carbon b/toolchain/semantics/testdata/if_expression/nested.carbon index 22c88841bb07..faf654107ba1 100644 --- a/toolchain/semantics/testdata/if_expression/nested.carbon +++ b/toolchain/semantics/testdata/if_expression/nested.carbon @@ -5,7 +5,7 @@ // AUTOUPDATE // CHECK:STDOUT: cross_reference_irs_size: 1 // CHECK:STDOUT: functions: [ -// CHECK:STDOUT: {name: str0, param_refs: block2, return_type: type1, body: {block4, block6, block8, block7, block9, block5, block11, block10, block12, block13}}}, +// CHECK:STDOUT: {name: str0, param_refs: block2, return_type: type1, body: {block4, block5, block7, block8, block9, block6, block10, block11, block12, block13}}}, // CHECK:STDOUT: ] // CHECK:STDOUT: integer_literals: [ // CHECK:STDOUT: 1, @@ -33,17 +33,17 @@ // CHECK:STDOUT: {kind: VarStorage, type: type0}, // CHECK:STDOUT: {kind: BindName, arg0: str3, arg1: node+4, type: type0}, // CHECK:STDOUT: {kind: FunctionDeclaration, arg0: function0}, -// CHECK:STDOUT: {kind: BranchIf, arg0: block6, arg1: node+0}, -// CHECK:STDOUT: {kind: Branch, arg0: block5}, -// CHECK:STDOUT: {kind: BranchIf, arg0: block8, arg1: node+2}, -// CHECK:STDOUT: {kind: Branch, arg0: block7}, +// CHECK:STDOUT: {kind: BranchIf, arg0: block5, arg1: node+0}, +// CHECK:STDOUT: {kind: Branch, arg0: block6}, +// CHECK:STDOUT: {kind: BranchIf, arg0: block7, arg1: node+2}, +// CHECK:STDOUT: {kind: Branch, arg0: block8}, // CHECK:STDOUT: {kind: IntegerLiteral, arg0: int0, type: type1}, // CHECK:STDOUT: {kind: IntegerLiteral, arg0: int1, type: type1}, // CHECK:STDOUT: {kind: BranchWithArg, arg0: block9, arg1: node+11}, // CHECK:STDOUT: {kind: BranchWithArg, arg0: block9, arg1: node+12}, // CHECK:STDOUT: {kind: BlockArg, arg0: block9, type: type1}, -// CHECK:STDOUT: {kind: BranchIf, arg0: block11, arg1: node+4}, -// CHECK:STDOUT: {kind: Branch, arg0: block10}, +// CHECK:STDOUT: {kind: BranchIf, arg0: block10, arg1: node+4}, +// CHECK:STDOUT: {kind: Branch, arg0: block11}, // CHECK:STDOUT: {kind: IntegerLiteral, arg0: int2, type: type1}, // CHECK:STDOUT: {kind: IntegerLiteral, arg0: int3, type: type1}, // CHECK:STDOUT: {kind: BranchWithArg, arg0: block12, arg1: node+18}, @@ -78,34 +78,34 @@ // CHECK:STDOUT: node+8, // CHECK:STDOUT: ], // CHECK:STDOUT: [ -// CHECK:STDOUT: node+16, -// CHECK:STDOUT: node+17, -// CHECK:STDOUT: ], -// CHECK:STDOUT: [ // CHECK:STDOUT: node+9, // CHECK:STDOUT: node+10, // CHECK:STDOUT: ], // CHECK:STDOUT: [ -// CHECK:STDOUT: node+12, -// CHECK:STDOUT: node+14, +// CHECK:STDOUT: node+16, +// CHECK:STDOUT: node+17, // CHECK:STDOUT: ], // CHECK:STDOUT: [ // CHECK:STDOUT: node+11, // CHECK:STDOUT: node+13, // CHECK:STDOUT: ], // CHECK:STDOUT: [ +// CHECK:STDOUT: node+12, +// CHECK:STDOUT: node+14, +// CHECK:STDOUT: ], +// CHECK:STDOUT: [ // CHECK:STDOUT: node+15, // CHECK:STDOUT: node+23, // CHECK:STDOUT: ], // CHECK:STDOUT: [ -// CHECK:STDOUT: node+19, -// CHECK:STDOUT: node+21, -// CHECK:STDOUT: ], -// CHECK:STDOUT: [ // CHECK:STDOUT: node+18, // CHECK:STDOUT: node+20, // CHECK:STDOUT: ], // CHECK:STDOUT: [ +// CHECK:STDOUT: node+19, +// CHECK:STDOUT: node+21, +// CHECK:STDOUT: ], +// CHECK:STDOUT: [ // CHECK:STDOUT: node+22, // CHECK:STDOUT: node+24, // CHECK:STDOUT: ], diff --git a/toolchain/semantics/testdata/operators/and.carbon b/toolchain/semantics/testdata/operators/and.carbon index babe1564c4d1..44e30572a3f6 100644 --- a/toolchain/semantics/testdata/operators/and.carbon +++ b/toolchain/semantics/testdata/operators/and.carbon @@ -7,7 +7,7 @@ // CHECK:STDOUT: functions: [ // CHECK:STDOUT: {name: str0, param_refs: block0, return_type: type0, body: {block2}}}, // CHECK:STDOUT: {name: str1, param_refs: block0, return_type: type0, body: {block3}}}, -// CHECK:STDOUT: {name: str2, param_refs: block0, return_type: type0, body: {block4, block6, block5}}}, +// CHECK:STDOUT: {name: str2, param_refs: block0, return_type: type0, body: {block4, block5, block6}}}, // CHECK:STDOUT: ] // CHECK:STDOUT: integer_literals: [ // CHECK:STDOUT: ] @@ -31,11 +31,11 @@ // CHECK:STDOUT: {kind: FunctionDeclaration, arg0: function2}, // CHECK:STDOUT: {kind: Call, arg0: block0, arg1: function0, type: type0}, // CHECK:STDOUT: {kind: BoolLiteral, arg0: false, type: type0}, -// CHECK:STDOUT: {kind: BranchIf, arg0: block6, arg1: node+7}, -// CHECK:STDOUT: {kind: BranchWithArg, arg0: block5, arg1: node+8}, +// CHECK:STDOUT: {kind: BranchIf, arg0: block5, arg1: node+7}, +// CHECK:STDOUT: {kind: BranchWithArg, arg0: block6, arg1: node+8}, // CHECK:STDOUT: {kind: Call, arg0: block0, arg1: function1, type: type0}, -// CHECK:STDOUT: {kind: BranchWithArg, arg0: block5, arg1: node+11}, -// CHECK:STDOUT: {kind: BlockArg, arg0: block5, type: type0}, +// CHECK:STDOUT: {kind: BranchWithArg, arg0: block6, arg1: node+11}, +// CHECK:STDOUT: {kind: BlockArg, arg0: block6, type: type0}, // CHECK:STDOUT: {kind: ReturnExpression, arg0: node+13, type: type0}, // CHECK:STDOUT: ] // CHECK:STDOUT: node_blocks: [ @@ -61,13 +61,13 @@ // CHECK:STDOUT: node+10, // CHECK:STDOUT: ], // CHECK:STDOUT: [ -// CHECK:STDOUT: node+13, -// CHECK:STDOUT: node+14, -// CHECK:STDOUT: ], -// CHECK:STDOUT: [ // CHECK:STDOUT: node+11, // CHECK:STDOUT: node+12, // CHECK:STDOUT: ], +// CHECK:STDOUT: [ +// CHECK:STDOUT: node+13, +// CHECK:STDOUT: node+14, +// CHECK:STDOUT: ], // CHECK:STDOUT: ] fn F() -> bool { return true; } diff --git a/toolchain/semantics/testdata/operators/or.carbon b/toolchain/semantics/testdata/operators/or.carbon index 8b64ffa3946b..d1814045283e 100644 --- a/toolchain/semantics/testdata/operators/or.carbon +++ b/toolchain/semantics/testdata/operators/or.carbon @@ -7,7 +7,7 @@ // CHECK:STDOUT: functions: [ // CHECK:STDOUT: {name: str0, param_refs: block0, return_type: type0, body: {block2}}}, // CHECK:STDOUT: {name: str1, param_refs: block0, return_type: type0, body: {block3}}}, -// CHECK:STDOUT: {name: str2, param_refs: block0, return_type: type0, body: {block4, block6, block5}}}, +// CHECK:STDOUT: {name: str2, param_refs: block0, return_type: type0, body: {block4, block5, block6}}}, // CHECK:STDOUT: ] // CHECK:STDOUT: integer_literals: [ // CHECK:STDOUT: ] @@ -32,11 +32,11 @@ // CHECK:STDOUT: {kind: Call, arg0: block0, arg1: function0, type: type0}, // CHECK:STDOUT: {kind: UnaryOperatorNot, arg0: node+7, type: type0}, // CHECK:STDOUT: {kind: BoolLiteral, arg0: true, type: type0}, -// CHECK:STDOUT: {kind: BranchIf, arg0: block6, arg1: node+8}, -// CHECK:STDOUT: {kind: BranchWithArg, arg0: block5, arg1: node+9}, +// CHECK:STDOUT: {kind: BranchIf, arg0: block5, arg1: node+8}, +// CHECK:STDOUT: {kind: BranchWithArg, arg0: block6, arg1: node+9}, // CHECK:STDOUT: {kind: Call, arg0: block0, arg1: function1, type: type0}, -// CHECK:STDOUT: {kind: BranchWithArg, arg0: block5, arg1: node+12}, -// CHECK:STDOUT: {kind: BlockArg, arg0: block5, type: type0}, +// CHECK:STDOUT: {kind: BranchWithArg, arg0: block6, arg1: node+12}, +// CHECK:STDOUT: {kind: BlockArg, arg0: block6, type: type0}, // CHECK:STDOUT: {kind: ReturnExpression, arg0: node+14, type: type0}, // CHECK:STDOUT: ] // CHECK:STDOUT: node_blocks: [ @@ -63,13 +63,13 @@ // CHECK:STDOUT: node+11, // CHECK:STDOUT: ], // CHECK:STDOUT: [ -// CHECK:STDOUT: node+14, -// CHECK:STDOUT: node+15, -// CHECK:STDOUT: ], -// CHECK:STDOUT: [ // CHECK:STDOUT: node+12, // CHECK:STDOUT: node+13, // CHECK:STDOUT: ], +// CHECK:STDOUT: [ +// CHECK:STDOUT: node+14, +// CHECK:STDOUT: node+15, +// CHECK:STDOUT: ], // CHECK:STDOUT: ] fn F() -> bool { return true; } diff --git a/toolchain/semantics/testdata/return/code_after_return.carbon b/toolchain/semantics/testdata/return/code_after_return.carbon new file mode 100644 index 000000000000..b4f4c292c392 --- /dev/null +++ b/toolchain/semantics/testdata/return/code_after_return.carbon @@ -0,0 +1,48 @@ +// Part of the Carbon Language project, under the Apache License v2.0 with LLVM +// Exceptions. See /LICENSE for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +// AUTOUPDATE +// CHECK:STDOUT: cross_reference_irs_size: 1 +// CHECK:STDOUT: functions: [ +// CHECK:STDOUT: {name: str0, param_refs: block0, body: {block2}}}, +// CHECK:STDOUT: ] +// CHECK:STDOUT: integer_literals: [ +// CHECK:STDOUT: 1, +// CHECK:STDOUT: 1, +// CHECK:STDOUT: ] +// CHECK:STDOUT: real_literals: [ +// CHECK:STDOUT: ] +// CHECK:STDOUT: strings: [ +// CHECK:STDOUT: Main, +// CHECK:STDOUT: n, +// CHECK:STDOUT: ] +// CHECK:STDOUT: types: [ +// CHECK:STDOUT: nodeEmptyTupleType, +// CHECK:STDOUT: nodeIntegerType, +// CHECK:STDOUT: ] +// CHECK:STDOUT: nodes: [ +// CHECK:STDOUT: {kind: FunctionDeclaration, arg0: function0}, +// CHECK:STDOUT: {kind: Return}, +// CHECK:STDOUT: {kind: VarStorage, type: type1}, +// CHECK:STDOUT: {kind: BindName, arg0: str1, arg1: node+2, type: type1}, +// CHECK:STDOUT: {kind: IntegerLiteral, arg0: int0, type: type1}, +// CHECK:STDOUT: {kind: IntegerLiteral, arg0: int1, type: type1}, +// CHECK:STDOUT: {kind: BinaryOperatorAdd, arg0: node+4, arg1: node+5, type: type1}, +// CHECK:STDOUT: {kind: Assign, arg0: node+2, arg1: node+6, type: type1}, +// CHECK:STDOUT: ] +// CHECK:STDOUT: node_blocks: [ +// CHECK:STDOUT: [ +// CHECK:STDOUT: ], +// CHECK:STDOUT: [ +// CHECK:STDOUT: node+0, +// CHECK:STDOUT: ], +// CHECK:STDOUT: [ +// CHECK:STDOUT: node+1, +// CHECK:STDOUT: ], +// CHECK:STDOUT: ] + +fn Main() { + return; + var n: i32 = 1 + 1; +} diff --git a/toolchain/semantics/testdata/return/code_after_return_value.carbon b/toolchain/semantics/testdata/return/code_after_return_value.carbon new file mode 100644 index 000000000000..b550d4f3f5c3 --- /dev/null +++ b/toolchain/semantics/testdata/return/code_after_return_value.carbon @@ -0,0 +1,76 @@ +// Part of the Carbon Language project, under the Apache License v2.0 with LLVM +// Exceptions. See /LICENSE for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +// AUTOUPDATE +// CHECK:STDOUT: cross_reference_irs_size: 1 +// CHECK:STDOUT: functions: [ +// CHECK:STDOUT: {name: str0, param_refs: block2, return_type: type1, body: {block4}}}, +// CHECK:STDOUT: ] +// CHECK:STDOUT: integer_literals: [ +// CHECK:STDOUT: 0, +// CHECK:STDOUT: 1, +// CHECK:STDOUT: 2, +// CHECK:STDOUT: ] +// CHECK:STDOUT: real_literals: [ +// CHECK:STDOUT: ] +// CHECK:STDOUT: strings: [ +// CHECK:STDOUT: F, +// CHECK:STDOUT: b, +// CHECK:STDOUT: n, +// CHECK:STDOUT: ] +// CHECK:STDOUT: types: [ +// CHECK:STDOUT: nodeBoolType, +// CHECK:STDOUT: nodeIntegerType, +// CHECK:STDOUT: ] +// CHECK:STDOUT: nodes: [ +// CHECK:STDOUT: {kind: VarStorage, type: type0}, +// CHECK:STDOUT: {kind: BindName, arg0: str1, arg1: node+0, type: type0}, +// CHECK:STDOUT: {kind: FunctionDeclaration, arg0: function0}, +// CHECK:STDOUT: {kind: IntegerLiteral, arg0: int0, type: type1}, +// CHECK:STDOUT: {kind: ReturnExpression, arg0: node+3, type: type1}, +// CHECK:STDOUT: {kind: VarStorage, type: type1}, +// CHECK:STDOUT: {kind: BindName, arg0: str2, arg1: node+5, type: type1}, +// CHECK:STDOUT: {kind: IntegerLiteral, arg0: int1, type: type1}, +// CHECK:STDOUT: {kind: IntegerLiteral, arg0: int2, type: type1}, +// CHECK:STDOUT: {kind: BlockArg, arg0: unreachable, type: type1}, +// CHECK:STDOUT: {kind: Assign, arg0: node+5, arg1: node+9, type: type1}, +// CHECK:STDOUT: {kind: BoolLiteral, arg0: false, type: type0}, +// CHECK:STDOUT: {kind: UnaryOperatorNot, arg0: node+0, type: type0}, +// CHECK:STDOUT: {kind: BoolLiteral, arg0: true, type: type0}, +// CHECK:STDOUT: {kind: BranchWithArg, arg0: unreachable, arg1: node+0}, +// CHECK:STDOUT: {kind: BlockArg, arg0: unreachable, type: type0}, +// CHECK:STDOUT: {kind: BranchWithArg, arg0: unreachable, arg1: node+15}, +// CHECK:STDOUT: {kind: BlockArg, arg0: unreachable, type: type0}, +// CHECK:STDOUT: {kind: Branch, arg0: unreachable}, +// CHECK:STDOUT: ] +// CHECK:STDOUT: node_blocks: [ +// CHECK:STDOUT: [ +// CHECK:STDOUT: ], +// CHECK:STDOUT: [ +// CHECK:STDOUT: node+0, +// CHECK:STDOUT: node+1, +// CHECK:STDOUT: ], +// CHECK:STDOUT: [ +// CHECK:STDOUT: node+1, +// CHECK:STDOUT: ], +// CHECK:STDOUT: [ +// CHECK:STDOUT: node+2, +// CHECK:STDOUT: ], +// CHECK:STDOUT: [ +// CHECK:STDOUT: node+3, +// CHECK:STDOUT: node+4, +// CHECK:STDOUT: ], +// CHECK:STDOUT: ] + +fn F(b: bool) -> i32 { + return 0; + + // Exercise various forms of control flow to check that we still consider the + // end of the function unreachable after them. + var n: i32 = if b then 1 else 2; + if (b and (b or b)) { } + if (b) { } else { } + + // Unreachable, no error on missing return. +} diff --git a/toolchain/semantics/testdata/return/fail_missing_return.carbon b/toolchain/semantics/testdata/return/fail_missing_return.carbon new file mode 100644 index 000000000000..f12ae075c595 --- /dev/null +++ b/toolchain/semantics/testdata/return/fail_missing_return.carbon @@ -0,0 +1,35 @@ +// Part of the Carbon Language project, under the Apache License v2.0 with LLVM +// Exceptions. See /LICENSE for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +// AUTOUPDATE +// CHECK:STDOUT: cross_reference_irs_size: 1 +// CHECK:STDOUT: functions: [ +// CHECK:STDOUT: {name: str0, param_refs: block0, return_type: type0, body: {block2}}}, +// CHECK:STDOUT: ] +// CHECK:STDOUT: integer_literals: [ +// CHECK:STDOUT: ] +// CHECK:STDOUT: real_literals: [ +// CHECK:STDOUT: ] +// CHECK:STDOUT: strings: [ +// CHECK:STDOUT: Main, +// CHECK:STDOUT: ] +// CHECK:STDOUT: types: [ +// CHECK:STDOUT: nodeIntegerType, +// CHECK:STDOUT: ] +// CHECK:STDOUT: nodes: [ +// CHECK:STDOUT: {kind: FunctionDeclaration, arg0: function0}, +// CHECK:STDOUT: ] +// CHECK:STDOUT: node_blocks: [ +// CHECK:STDOUT: [ +// CHECK:STDOUT: ], +// CHECK:STDOUT: [ +// CHECK:STDOUT: node+0, +// CHECK:STDOUT: ], +// CHECK:STDOUT: [ +// CHECK:STDOUT: ], +// CHECK:STDOUT: ] + +fn Main() -> i32 { +// CHECK:STDERR: fail_missing_return.carbon:[[@LINE+1]]:1: Missing `return` at end of function with declared return type. +} diff --git a/toolchain/semantics/testdata/return/fail_missing_return_empty_tuple.carbon b/toolchain/semantics/testdata/return/fail_missing_return_empty_tuple.carbon new file mode 100644 index 000000000000..5847198f3a23 --- /dev/null +++ b/toolchain/semantics/testdata/return/fail_missing_return_empty_tuple.carbon @@ -0,0 +1,27 @@ +// Part of the Carbon Language project, under the Apache License v2.0 with LLVM +// Exceptions. See /LICENSE for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +// AUTOUPDATE +// CHECK:STDOUT: cross_reference_irs_size: 1 +// CHECK:STDOUT: functions: [ +// CHECK:STDOUT: ] +// CHECK:STDOUT: integer_literals: [ +// CHECK:STDOUT: ] +// CHECK:STDOUT: real_literals: [ +// CHECK:STDOUT: ] +// CHECK:STDOUT: strings: [ +// CHECK:STDOUT: F, +// CHECK:STDOUT: ] +// CHECK:STDOUT: types: [ +// CHECK:STDOUT: ] +// CHECK:STDOUT: nodes: [ +// CHECK:STDOUT: ] +// CHECK:STDOUT: node_blocks: [ +// CHECK:STDOUT: [ +// CHECK:STDOUT: ], +// CHECK:STDOUT: ] + +// CHECK:STDERR: fail_missing_return_empty_tuple.carbon:[[@LINE+1]]:12: Semantics TODO: HandleTupleLiteral +fn F() -> () { +} diff --git a/toolchain/semantics/testdata/return/missing_return_no_return_type.carbon b/toolchain/semantics/testdata/return/missing_return_no_return_type.carbon new file mode 100644 index 000000000000..f94e7771fd86 --- /dev/null +++ b/toolchain/semantics/testdata/return/missing_return_no_return_type.carbon @@ -0,0 +1,36 @@ +// Part of the Carbon Language project, under the Apache License v2.0 with LLVM +// Exceptions. See /LICENSE for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +// AUTOUPDATE +// CHECK:STDOUT: cross_reference_irs_size: 1 +// CHECK:STDOUT: functions: [ +// CHECK:STDOUT: {name: str0, param_refs: block0, body: {block2}}}, +// CHECK:STDOUT: ] +// CHECK:STDOUT: integer_literals: [ +// CHECK:STDOUT: ] +// CHECK:STDOUT: real_literals: [ +// CHECK:STDOUT: ] +// CHECK:STDOUT: strings: [ +// CHECK:STDOUT: F, +// CHECK:STDOUT: ] +// CHECK:STDOUT: types: [ +// CHECK:STDOUT: nodeEmptyTupleType, +// CHECK:STDOUT: ] +// CHECK:STDOUT: nodes: [ +// CHECK:STDOUT: {kind: FunctionDeclaration, arg0: function0}, +// CHECK:STDOUT: {kind: Return}, +// CHECK:STDOUT: ] +// CHECK:STDOUT: node_blocks: [ +// CHECK:STDOUT: [ +// CHECK:STDOUT: ], +// CHECK:STDOUT: [ +// CHECK:STDOUT: node+0, +// CHECK:STDOUT: ], +// CHECK:STDOUT: [ +// CHECK:STDOUT: node+1, +// CHECK:STDOUT: ], +// CHECK:STDOUT: ] + +fn F() { +} diff --git a/toolchain/semantics/testdata/var/decl.carbon b/toolchain/semantics/testdata/var/decl.carbon index abce74aa048a..df17f24b949e 100644 --- a/toolchain/semantics/testdata/var/decl.carbon +++ b/toolchain/semantics/testdata/var/decl.carbon @@ -23,6 +23,7 @@ // CHECK:STDOUT: {kind: FunctionDeclaration, arg0: function0}, // CHECK:STDOUT: {kind: VarStorage, type: type1}, // CHECK:STDOUT: {kind: BindName, arg0: str1, arg1: node+1, type: type1}, +// CHECK:STDOUT: {kind: Return}, // CHECK:STDOUT: ] // CHECK:STDOUT: node_blocks: [ // CHECK:STDOUT: [ @@ -33,6 +34,7 @@ // CHECK:STDOUT: [ // CHECK:STDOUT: node+1, // CHECK:STDOUT: node+2, +// CHECK:STDOUT: node+3, // CHECK:STDOUT: ], // CHECK:STDOUT: ] diff --git a/toolchain/semantics/testdata/var/decl_with_init.carbon b/toolchain/semantics/testdata/var/decl_with_init.carbon index 3d304fd7f423..e393eb4c09cb 100644 --- a/toolchain/semantics/testdata/var/decl_with_init.carbon +++ b/toolchain/semantics/testdata/var/decl_with_init.carbon @@ -26,6 +26,7 @@ // CHECK:STDOUT: {kind: BindName, arg0: str1, arg1: node+1, type: type1}, // CHECK:STDOUT: {kind: IntegerLiteral, arg0: int0, type: type1}, // CHECK:STDOUT: {kind: Assign, arg0: node+1, arg1: node+3, type: type1}, +// CHECK:STDOUT: {kind: Return}, // CHECK:STDOUT: ] // CHECK:STDOUT: node_blocks: [ // CHECK:STDOUT: [ @@ -38,6 +39,7 @@ // CHECK:STDOUT: node+2, // CHECK:STDOUT: node+3, // CHECK:STDOUT: node+4, +// CHECK:STDOUT: node+5, // CHECK:STDOUT: ], // CHECK:STDOUT: ] diff --git a/toolchain/semantics/testdata/var/fail_duplicate_decl.carbon b/toolchain/semantics/testdata/var/fail_duplicate_decl.carbon index 4e798a595443..17b9c287ef10 100644 --- a/toolchain/semantics/testdata/var/fail_duplicate_decl.carbon +++ b/toolchain/semantics/testdata/var/fail_duplicate_decl.carbon @@ -31,6 +31,7 @@ // CHECK:STDOUT: {kind: BindName, arg0: str1, arg1: node+5, type: type1}, // CHECK:STDOUT: {kind: IntegerLiteral, arg0: int1, type: type1}, // CHECK:STDOUT: {kind: Assign, arg0: node+5, arg1: node+7, type: type1}, +// CHECK:STDOUT: {kind: Return}, // CHECK:STDOUT: ] // CHECK:STDOUT: node_blocks: [ // CHECK:STDOUT: [ @@ -47,6 +48,7 @@ // CHECK:STDOUT: node+6, // CHECK:STDOUT: node+7, // CHECK:STDOUT: node+8, +// CHECK:STDOUT: node+9, // CHECK:STDOUT: ], // CHECK:STDOUT: ] diff --git a/toolchain/semantics/testdata/var/fail_init_type_mismatch.carbon b/toolchain/semantics/testdata/var/fail_init_type_mismatch.carbon index 84085dbda003..92d1f9ccf82b 100644 --- a/toolchain/semantics/testdata/var/fail_init_type_mismatch.carbon +++ b/toolchain/semantics/testdata/var/fail_init_type_mismatch.carbon @@ -27,6 +27,7 @@ // CHECK:STDOUT: {kind: BindName, arg0: str1, arg1: node+1, type: type1}, // CHECK:STDOUT: {kind: RealLiteral, arg0: real0, type: type2}, // CHECK:STDOUT: {kind: Assign, arg0: node+1, arg1: nodeInvalidType, type: typeInvalidType}, +// CHECK:STDOUT: {kind: Return}, // CHECK:STDOUT: ] // CHECK:STDOUT: node_blocks: [ // CHECK:STDOUT: [ @@ -39,6 +40,7 @@ // CHECK:STDOUT: node+2, // CHECK:STDOUT: node+3, // CHECK:STDOUT: node+4, +// CHECK:STDOUT: node+5, // CHECK:STDOUT: ], // CHECK:STDOUT: ] diff --git a/toolchain/semantics/testdata/var/fail_init_with_self.carbon b/toolchain/semantics/testdata/var/fail_init_with_self.carbon index e412dae4b5a0..6d48d4ce8af9 100644 --- a/toolchain/semantics/testdata/var/fail_init_with_self.carbon +++ b/toolchain/semantics/testdata/var/fail_init_with_self.carbon @@ -24,6 +24,7 @@ // CHECK:STDOUT: {kind: VarStorage, type: type1}, // CHECK:STDOUT: {kind: BindName, arg0: str1, arg1: node+1, type: type1}, // CHECK:STDOUT: {kind: Assign, arg0: node+1, arg1: nodeInvalidType, type: typeInvalidType}, +// CHECK:STDOUT: {kind: Return}, // CHECK:STDOUT: ] // CHECK:STDOUT: node_blocks: [ // CHECK:STDOUT: [ @@ -35,6 +36,7 @@ // CHECK:STDOUT: node+1, // CHECK:STDOUT: node+2, // CHECK:STDOUT: node+3, +// CHECK:STDOUT: node+4, // CHECK:STDOUT: ], // CHECK:STDOUT: ] diff --git a/toolchain/semantics/testdata/var/fail_lookup_outside_scope.carbon b/toolchain/semantics/testdata/var/fail_lookup_outside_scope.carbon index d2627d2a83a7..7be851a90eea 100644 --- a/toolchain/semantics/testdata/var/fail_lookup_outside_scope.carbon +++ b/toolchain/semantics/testdata/var/fail_lookup_outside_scope.carbon @@ -24,22 +24,24 @@ // CHECK:STDOUT: {kind: FunctionDeclaration, arg0: function0}, // CHECK:STDOUT: {kind: VarStorage, type: type1}, // CHECK:STDOUT: {kind: BindName, arg0: str1, arg1: node+1, type: type1}, +// CHECK:STDOUT: {kind: Return}, // CHECK:STDOUT: {kind: VarStorage, type: type1}, -// CHECK:STDOUT: {kind: BindName, arg0: str2, arg1: node+3, type: type1}, -// CHECK:STDOUT: {kind: Assign, arg0: node+3, arg1: nodeInvalidType, type: typeInvalidType}, +// CHECK:STDOUT: {kind: BindName, arg0: str2, arg1: node+4, type: type1}, +// CHECK:STDOUT: {kind: Assign, arg0: node+4, arg1: nodeInvalidType, type: typeInvalidType}, // CHECK:STDOUT: ] // CHECK:STDOUT: node_blocks: [ // CHECK:STDOUT: [ // CHECK:STDOUT: ], // CHECK:STDOUT: [ // CHECK:STDOUT: node+0, -// CHECK:STDOUT: node+3, // CHECK:STDOUT: node+4, // CHECK:STDOUT: node+5, +// CHECK:STDOUT: node+6, // CHECK:STDOUT: ], // CHECK:STDOUT: [ // CHECK:STDOUT: node+1, // CHECK:STDOUT: node+2, +// CHECK:STDOUT: node+3, // CHECK:STDOUT: ], // CHECK:STDOUT: ] diff --git a/toolchain/semantics/testdata/var/fail_storage_is_literal.carbon b/toolchain/semantics/testdata/var/fail_storage_is_literal.carbon index 6319595e33c5..bde1601a1b1e 100644 --- a/toolchain/semantics/testdata/var/fail_storage_is_literal.carbon +++ b/toolchain/semantics/testdata/var/fail_storage_is_literal.carbon @@ -28,6 +28,7 @@ // CHECK:STDOUT: {kind: BindName, arg0: str1, arg1: node+2, type: typeInvalidType}, // CHECK:STDOUT: {kind: IntegerLiteral, arg0: int1, type: type1}, // CHECK:STDOUT: {kind: Assign, arg0: node+2, arg1: nodeInvalidType, type: typeInvalidType}, +// CHECK:STDOUT: {kind: Return}, // CHECK:STDOUT: ] // CHECK:STDOUT: node_blocks: [ // CHECK:STDOUT: [ @@ -41,6 +42,7 @@ // CHECK:STDOUT: node+3, // CHECK:STDOUT: node+4, // CHECK:STDOUT: node+5, +// CHECK:STDOUT: node+6, // CHECK:STDOUT: ], // CHECK:STDOUT: ] diff --git a/toolchain/semantics/testdata/var/global_lookup_in_scope.carbon b/toolchain/semantics/testdata/var/global_lookup_in_scope.carbon index 567752b4fbb5..dfc8903ed538 100644 --- a/toolchain/semantics/testdata/var/global_lookup_in_scope.carbon +++ b/toolchain/semantics/testdata/var/global_lookup_in_scope.carbon @@ -30,6 +30,7 @@ // CHECK:STDOUT: {kind: VarStorage, type: type0}, // CHECK:STDOUT: {kind: BindName, arg0: str2, arg1: node+5, type: type0}, // CHECK:STDOUT: {kind: Assign, arg0: node+5, arg1: node+0, type: type0}, +// CHECK:STDOUT: {kind: Return}, // CHECK:STDOUT: ] // CHECK:STDOUT: node_blocks: [ // CHECK:STDOUT: [ @@ -45,6 +46,7 @@ // CHECK:STDOUT: node+5, // CHECK:STDOUT: node+6, // CHECK:STDOUT: node+7, +// CHECK:STDOUT: node+8, // CHECK:STDOUT: ], // CHECK:STDOUT: ] diff --git a/toolchain/semantics/testdata/var/lookup.carbon b/toolchain/semantics/testdata/var/lookup.carbon index 8b14ffab2d69..59ba687f10e5 100644 --- a/toolchain/semantics/testdata/var/lookup.carbon +++ b/toolchain/semantics/testdata/var/lookup.carbon @@ -26,6 +26,7 @@ // CHECK:STDOUT: {kind: BindName, arg0: str1, arg1: node+1, type: type1}, // CHECK:STDOUT: {kind: IntegerLiteral, arg0: int0, type: type1}, // CHECK:STDOUT: {kind: Assign, arg0: node+1, arg1: node+3, type: type1}, +// CHECK:STDOUT: {kind: Return}, // CHECK:STDOUT: ] // CHECK:STDOUT: node_blocks: [ // CHECK:STDOUT: [ @@ -38,6 +39,7 @@ // CHECK:STDOUT: node+2, // CHECK:STDOUT: node+3, // CHECK:STDOUT: node+4, +// CHECK:STDOUT: node+5, // CHECK:STDOUT: ], // CHECK:STDOUT: ]