Просмотр исходного кода

Format the decl block for a declaration as a trailing block. (#3731)

Previously we used the default inst block formatting, which writes out a
parenthesized list of references, which would always be 'unexpected
instref's because nothing else prints the instructions in the decl
block.

In addition, track the decl block for function declarations like we do
for other kinds of declaration. This means that the parameter
declarations for a function are now properly rendered into the formatted
IR. Note that this adds a lot of verbosity to `function_decl`, but it
does accurately reflect the IR, and we'll probably want this information
to be printed once we start supporting more complex generic function
declarations.

This removes almost all the 'unexpected instref's in our formatted
output. There are remaining cases when a declarative scope contains
multiple blocks, where we only track one of those blocks. That happens
when there is control flow within declarative scopes, and for error
recovery when a class or interface or similar is defined more than once.

As requested in #3730.
Richard Smith 2 лет назад
Родитель
Сommit
5f4e6c768a
100 измененных файлов с 1188 добавлено и 420 удалено
  1. 2 9
      toolchain/check/handle_function.cpp
  2. 3 3
      toolchain/check/import_ref.cpp
  3. 3 1
      toolchain/check/testdata/alias/fail_local_in_namespace.carbon
  4. 1 1
      toolchain/check/testdata/alias/fail_not_constant.carbon
  5. 7 3
      toolchain/check/testdata/alias/in_namespace.carbon
  6. 3 1
      toolchain/check/testdata/alias/local.carbon
  7. 6 2
      toolchain/check/testdata/array/array_in_place.carbon
  8. 1 1
      toolchain/check/testdata/array/array_vs_tuple.carbon
  9. 6 2
      toolchain/check/testdata/array/assign_return_value.carbon
  10. 1 1
      toolchain/check/testdata/array/fail_incomplete_element.carbon
  11. 12 2
      toolchain/check/testdata/array/function_param.carbon
  12. 3 1
      toolchain/check/testdata/as/basic.carbon
  13. 17 5
      toolchain/check/testdata/as/identity.carbon
  14. 7 4
      toolchain/check/testdata/as/tuple.carbon
  15. 3 1
      toolchain/check/testdata/basics/fail_bad_run.carbon
  16. 4 1
      toolchain/check/testdata/basics/fail_bad_run_2.carbon
  17. 1 1
      toolchain/check/testdata/basics/fail_name_lookup.carbon
  18. 2 2
      toolchain/check/testdata/basics/multifile.carbon
  19. 4 4
      toolchain/check/testdata/basics/multifile_raw_and_textual_ir.carbon
  20. 2 2
      toolchain/check/testdata/basics/multifile_raw_ir.carbon
  21. 1 1
      toolchain/check/testdata/basics/numeric_literals.carbon
  22. 8 2
      toolchain/check/testdata/basics/raw_and_textual_ir.carbon
  23. 15 3
      toolchain/check/testdata/basics/raw_identifier.carbon
  24. 1 1
      toolchain/check/testdata/basics/raw_ir.carbon
  25. 1 1
      toolchain/check/testdata/basics/run.carbon
  26. 3 1
      toolchain/check/testdata/basics/run_i32.carbon
  27. 7 1
      toolchain/check/testdata/basics/textual_ir.carbon
  28. 14 4
      toolchain/check/testdata/class/base.carbon
  29. 10 3
      toolchain/check/testdata/class/base_field.carbon
  30. 6 6
      toolchain/check/testdata/class/base_function_unqualified.carbon
  31. 22 5
      toolchain/check/testdata/class/base_method.carbon
  32. 46 11
      toolchain/check/testdata/class/base_method_shadow.carbon
  33. 21 7
      toolchain/check/testdata/class/basic.carbon
  34. 45 9
      toolchain/check/testdata/class/derived_to_base.carbon
  35. 14 4
      toolchain/check/testdata/class/fail_abstract.carbon
  36. 15 5
      toolchain/check/testdata/class/fail_addr_not_self.carbon
  37. 25 6
      toolchain/check/testdata/class/fail_addr_self.carbon
  38. 112 23
      toolchain/check/testdata/class/fail_base_bad_type.carbon
  39. 7 7
      toolchain/check/testdata/class/fail_base_method_define.carbon
  40. 5 5
      toolchain/check/testdata/class/fail_base_modifiers.carbon
  41. 2 2
      toolchain/check/testdata/class/fail_base_no_extend.carbon
  42. 4 4
      toolchain/check/testdata/class/fail_base_repeated.carbon
  43. 2 2
      toolchain/check/testdata/class/fail_base_unbound.carbon
  44. 5 2
      toolchain/check/testdata/class/fail_convert_to_invalid.carbon
  45. 22 6
      toolchain/check/testdata/class/fail_derived_to_base.carbon
  46. 1 1
      toolchain/check/testdata/class/fail_field_modifiers.carbon
  47. 6 4
      toolchain/check/testdata/class/fail_import_misuses.carbon
  48. 45 12
      toolchain/check/testdata/class/fail_incomplete.carbon
  49. 2 2
      toolchain/check/testdata/class/fail_init.carbon
  50. 8 3
      toolchain/check/testdata/class/fail_init_as_inplace.carbon
  51. 19 5
      toolchain/check/testdata/class/fail_memaccess_category.carbon
  52. 5 3
      toolchain/check/testdata/class/fail_member_of_let.carbon
  53. 14 6
      toolchain/check/testdata/class/fail_method.carbon
  54. 33 13
      toolchain/check/testdata/class/fail_method_modifiers.carbon
  55. 6 6
      toolchain/check/testdata/class/fail_modifiers.carbon
  56. 2 2
      toolchain/check/testdata/class/fail_out_of_line_decl.carbon
  57. 15 15
      toolchain/check/testdata/class/fail_redeclaration_introducer.carbon
  58. 9 9
      toolchain/check/testdata/class/fail_redeclaration_scope.carbon
  59. 7 7
      toolchain/check/testdata/class/fail_redefinition.carbon
  60. 7 3
      toolchain/check/testdata/class/fail_reorder.carbon
  61. 7 3
      toolchain/check/testdata/class/fail_scope.carbon
  62. 31 9
      toolchain/check/testdata/class/fail_self.carbon
  63. 1 1
      toolchain/check/testdata/class/fail_todo_generic.carbon
  64. 18 5
      toolchain/check/testdata/class/fail_todo_generic_method.carbon
  65. 4 2
      toolchain/check/testdata/class/fail_todo_import_forward_decl.carbon
  66. 10 10
      toolchain/check/testdata/class/fail_todo_modifiers.carbon
  67. 7 3
      toolchain/check/testdata/class/fail_unbound_field.carbon
  68. 7 2
      toolchain/check/testdata/class/fail_unknown_member.carbon
  69. 2 2
      toolchain/check/testdata/class/field_access.carbon
  70. 2 2
      toolchain/check/testdata/class/field_access_in_value.carbon
  71. 10 2
      toolchain/check/testdata/class/forward_declared.carbon
  72. 24 14
      toolchain/check/testdata/class/import.carbon
  73. 17 9
      toolchain/check/testdata/class/import_base.carbon
  74. 3 3
      toolchain/check/testdata/class/import_member_cycle.carbon
  75. 4 4
      toolchain/check/testdata/class/import_struct_cyle.carbon
  76. 21 3
      toolchain/check/testdata/class/init.carbon
  77. 4 2
      toolchain/check/testdata/class/init_as.carbon
  78. 10 4
      toolchain/check/testdata/class/init_nested.carbon
  79. 64 14
      toolchain/check/testdata/class/method.carbon
  80. 8 3
      toolchain/check/testdata/class/nested.carbon
  81. 14 4
      toolchain/check/testdata/class/nested_name.carbon
  82. 39 5
      toolchain/check/testdata/class/raw_self.carbon
  83. 2 2
      toolchain/check/testdata/class/raw_self_type.carbon
  84. 4 4
      toolchain/check/testdata/class/redeclaration.carbon
  85. 6 6
      toolchain/check/testdata/class/redeclaration_introducer.carbon
  86. 10 4
      toolchain/check/testdata/class/reenter_scope.carbon
  87. 11 5
      toolchain/check/testdata/class/scope.carbon
  88. 29 5
      toolchain/check/testdata/class/self.carbon
  89. 36 8
      toolchain/check/testdata/class/self_conversion.carbon
  90. 14 4
      toolchain/check/testdata/class/self_type.carbon
  91. 7 3
      toolchain/check/testdata/class/static_method.carbon
  92. 20 2
      toolchain/check/testdata/const/basic.carbon
  93. 12 1
      toolchain/check/testdata/const/collapse.carbon
  94. 11 1
      toolchain/check/testdata/const/fail_collapse.carbon
  95. 4 1
      toolchain/check/testdata/const/import.carbon
  96. 4 1
      toolchain/check/testdata/eval/fail_symbolic.carbon
  97. 4 1
      toolchain/check/testdata/eval/symbolic.carbon
  98. 13 3
      toolchain/check/testdata/expr_category/in_place_tuple_init.carbon
  99. 4 2
      toolchain/check/testdata/function/call/alias.carbon
  100. 10 2
      toolchain/check/testdata/function/call/empty_struct.carbon

+ 2 - 9
toolchain/check/handle_function.cpp

@@ -60,14 +60,7 @@ static auto BuildFunctionDecl(Context& context,
                               Parse::AnyFunctionDeclId parse_node,
                               Parse::AnyFunctionDeclId parse_node,
                               bool is_definition)
                               bool is_definition)
     -> std::pair<SemIR::FunctionId, SemIR::InstId> {
     -> std::pair<SemIR::FunctionId, SemIR::InstId> {
-  // TODO: This contains the IR block for the parameters and return type. At
-  // present, it's just loose, but it's not strictly required for parameter
-  // refs; we should either stop constructing it completely or, if it turns out
-  // to be needed, store it. Note, the underlying issue is that the LLVM IR has
-  // nowhere clear to emit, so changing storage would require addressing that
-  // problem. For comparison with function calls, the IR needs to be emitted
-  // prior to the call.
-  context.inst_block_stack().Pop();
+  auto decl_block_id = context.inst_block_stack().Pop();
 
 
   auto return_type_id = SemIR::TypeId::Invalid;
   auto return_type_id = SemIR::TypeId::Invalid;
   auto return_slot_id = SemIR::InstId::Invalid;
   auto return_slot_id = SemIR::InstId::Invalid;
@@ -123,7 +116,7 @@ static auto BuildFunctionDecl(Context& context,
   // Add the function declaration.
   // Add the function declaration.
   auto function_decl = SemIR::FunctionDecl{
   auto function_decl = SemIR::FunctionDecl{
       context.GetBuiltinType(SemIR::BuiltinKind::FunctionType),
       context.GetBuiltinType(SemIR::BuiltinKind::FunctionType),
-      SemIR::FunctionId::Invalid};
+      SemIR::FunctionId::Invalid, decl_block_id};
   auto function_decl_id =
   auto function_decl_id =
       context.AddPlaceholderInst({parse_node, function_decl});
       context.AddPlaceholderInst({parse_node, function_decl});
 
 

+ 3 - 3
toolchain/check/import_ref.cpp

@@ -550,9 +550,9 @@ class ImportRefResolver {
     }
     }
 
 
     // Add the function declaration.
     // Add the function declaration.
-    auto function_decl =
-        SemIR::FunctionDecl{context_.GetTypeIdForTypeConstant(type_const_id),
-                            SemIR::FunctionId::Invalid};
+    auto function_decl = SemIR::FunctionDecl{
+        context_.GetTypeIdForTypeConstant(type_const_id),
+        SemIR::FunctionId::Invalid, SemIR::InstBlockId::Empty};
     auto function_decl_id = context_.AddPlaceholderInstInNoBlock(
     auto function_decl_id = context_.AddPlaceholderInstInNoBlock(
         {Parse::NodeId::Invalid, function_decl});
         {Parse::NodeId::Invalid, function_decl});
 
 

+ 3 - 1
toolchain/check/testdata/alias/fail_local_in_namespace.carbon

@@ -29,7 +29,9 @@ fn F() -> bool {
 // CHECK:STDOUT: file {
 // CHECK:STDOUT: file {
 // CHECK:STDOUT:   package: <namespace> = namespace {.NS = %.loc7, .F = %F} [template]
 // CHECK:STDOUT:   package: <namespace> = namespace {.NS = %.loc7, .F = %F} [template]
 // CHECK:STDOUT:   %.loc7: <namespace> = namespace {} [template]
 // CHECK:STDOUT:   %.loc7: <namespace> = namespace {} [template]
-// CHECK:STDOUT:   %F: <function> = fn_decl @F [template]
+// CHECK:STDOUT:   %F: <function> = fn_decl @F {
+// CHECK:STDOUT:     %return.var: ref bool = var <return slot>
+// CHECK:STDOUT:   } [template]
 // CHECK:STDOUT: }
 // CHECK:STDOUT: }
 // CHECK:STDOUT:
 // CHECK:STDOUT:
 // CHECK:STDOUT: fn @F() -> bool {
 // CHECK:STDOUT: fn @F() -> bool {

+ 1 - 1
toolchain/check/testdata/alias/fail_not_constant.carbon

@@ -22,7 +22,7 @@ fn F() {
 // CHECK:STDOUT:
 // CHECK:STDOUT:
 // CHECK:STDOUT: file {
 // CHECK:STDOUT: file {
 // CHECK:STDOUT:   package: <namespace> = namespace {.F = %F} [template]
 // CHECK:STDOUT:   package: <namespace> = namespace {.F = %F} [template]
-// CHECK:STDOUT:   %F: <function> = fn_decl @F [template]
+// CHECK:STDOUT:   %F: <function> = fn_decl @F {} [template]
 // CHECK:STDOUT: }
 // CHECK:STDOUT: }
 // CHECK:STDOUT:
 // CHECK:STDOUT:
 // CHECK:STDOUT: fn @F() {
 // CHECK:STDOUT: fn @F() {

+ 7 - 3
toolchain/check/testdata/alias/in_namespace.carbon

@@ -23,11 +23,15 @@ fn F() -> NS.a {
 // CHECK:STDOUT:   package: <namespace> = namespace {.NS = %.loc7, .F = %F} [template]
 // CHECK:STDOUT:   package: <namespace> = namespace {.NS = %.loc7, .F = %F} [template]
 // CHECK:STDOUT:   %.loc7: <namespace> = namespace {.a = %a} [template]
 // CHECK:STDOUT:   %.loc7: <namespace> = namespace {.a = %a} [template]
 // CHECK:STDOUT:   %a: type = bind_alias a, bool [template = bool]
 // CHECK:STDOUT:   %a: type = bind_alias a, bool [template = bool]
-// CHECK:STDOUT:   %NS.ref: <namespace> = name_ref NS, %.loc7 [template = %.loc7]
-// CHECK:STDOUT:   %a.ref: type = name_ref a, %a [template = bool]
+// CHECK:STDOUT:   %NS.ref.loc10: <namespace> = name_ref NS, %.loc7 [template = %.loc7]
+// CHECK:STDOUT:   %a.ref.loc10: type = name_ref a, %a [template = bool]
 // CHECK:STDOUT:   %.loc10: bool = bool_literal false [template = constants.%.1]
 // CHECK:STDOUT:   %.loc10: bool = bool_literal false [template = constants.%.1]
 // CHECK:STDOUT:   %b: bool = bind_name b, %.loc10
 // CHECK:STDOUT:   %b: bool = bind_name b, %.loc10
-// CHECK:STDOUT:   %F: <function> = fn_decl @F [template]
+// CHECK:STDOUT:   %F: <function> = fn_decl @F {
+// CHECK:STDOUT:     %NS.ref.loc12: <namespace> = name_ref NS, %.loc7 [template = %.loc7]
+// CHECK:STDOUT:     %a.ref.loc12: type = name_ref a, %a [template = bool]
+// CHECK:STDOUT:     %return.var: ref bool = var <return slot>
+// CHECK:STDOUT:   } [template]
 // CHECK:STDOUT: }
 // CHECK:STDOUT: }
 // CHECK:STDOUT:
 // CHECK:STDOUT:
 // CHECK:STDOUT: fn @F() -> bool {
 // CHECK:STDOUT: fn @F() -> bool {

+ 3 - 1
toolchain/check/testdata/alias/local.carbon

@@ -18,7 +18,9 @@ fn F() -> i32 {
 // CHECK:STDOUT:
 // CHECK:STDOUT:
 // CHECK:STDOUT: file {
 // CHECK:STDOUT: file {
 // CHECK:STDOUT:   package: <namespace> = namespace {.F = %F} [template]
 // CHECK:STDOUT:   package: <namespace> = namespace {.F = %F} [template]
-// CHECK:STDOUT:   %F: <function> = fn_decl @F [template]
+// CHECK:STDOUT:   %F: <function> = fn_decl @F {
+// CHECK:STDOUT:     %return.var: ref i32 = var <return slot>
+// CHECK:STDOUT:   } [template]
 // CHECK:STDOUT: }
 // CHECK:STDOUT: }
 // CHECK:STDOUT:
 // CHECK:STDOUT:
 // CHECK:STDOUT: fn @F() -> i32 {
 // CHECK:STDOUT: fn @F() -> i32 {

+ 6 - 2
toolchain/check/testdata/array/array_in_place.carbon

@@ -26,8 +26,12 @@ fn G() {
 // CHECK:STDOUT:
 // CHECK:STDOUT:
 // CHECK:STDOUT: file {
 // CHECK:STDOUT: file {
 // CHECK:STDOUT:   package: <namespace> = namespace {.F = %F, .G = %G} [template]
 // CHECK:STDOUT:   package: <namespace> = namespace {.F = %F, .G = %G} [template]
-// CHECK:STDOUT:   %F: <function> = fn_decl @F [template]
-// CHECK:STDOUT:   %G: <function> = fn_decl @G [template]
+// CHECK:STDOUT:   %F: <function> = fn_decl @F {
+// CHECK:STDOUT:     %.loc7_25.1: (type, type, type) = tuple_literal (i32, i32, i32)
+// CHECK:STDOUT:     %.loc7_25.2: type = converted %.loc7_25.1, constants.%.2 [template = constants.%.2]
+// CHECK:STDOUT:     @F.%return: ref (i32, i32, i32) = var <return slot>
+// CHECK:STDOUT:   } [template]
+// CHECK:STDOUT:   %G: <function> = fn_decl @G {} [template]
 // CHECK:STDOUT: }
 // CHECK:STDOUT: }
 // CHECK:STDOUT:
 // CHECK:STDOUT:
 // CHECK:STDOUT: fn @F() -> %return: (i32, i32, i32);
 // CHECK:STDOUT: fn @F() -> %return: (i32, i32, i32);

+ 1 - 1
toolchain/check/testdata/array/array_vs_tuple.carbon

@@ -30,7 +30,7 @@ fn G() {
 // CHECK:STDOUT:
 // CHECK:STDOUT:
 // CHECK:STDOUT: file {
 // CHECK:STDOUT: file {
 // CHECK:STDOUT:   package: <namespace> = namespace {.G = %G} [template]
 // CHECK:STDOUT:   package: <namespace> = namespace {.G = %G} [template]
-// CHECK:STDOUT:   %G: <function> = fn_decl @G [template]
+// CHECK:STDOUT:   %G: <function> = fn_decl @G {} [template]
 // CHECK:STDOUT: }
 // CHECK:STDOUT: }
 // CHECK:STDOUT:
 // CHECK:STDOUT:
 // CHECK:STDOUT: fn @G() {
 // CHECK:STDOUT: fn @G() {

+ 6 - 2
toolchain/check/testdata/array/assign_return_value.carbon

@@ -25,8 +25,12 @@ fn Run() {
 // CHECK:STDOUT:
 // CHECK:STDOUT:
 // CHECK:STDOUT: file {
 // CHECK:STDOUT: file {
 // CHECK:STDOUT:   package: <namespace> = namespace {.F = %F, .Run = %Run} [template]
 // CHECK:STDOUT:   package: <namespace> = namespace {.F = %F, .Run = %Run} [template]
-// CHECK:STDOUT:   %F: <function> = fn_decl @F [template]
-// CHECK:STDOUT:   %Run: <function> = fn_decl @Run [template]
+// CHECK:STDOUT:   %F: <function> = fn_decl @F {
+// CHECK:STDOUT:     %.loc7_16.1: (type,) = tuple_literal (i32)
+// CHECK:STDOUT:     %.loc7_16.2: type = converted %.loc7_16.1, constants.%.2 [template = constants.%.2]
+// CHECK:STDOUT:     %return.var: ref (i32,) = var <return slot>
+// CHECK:STDOUT:   } [template]
+// CHECK:STDOUT:   %Run: <function> = fn_decl @Run {} [template]
 // CHECK:STDOUT: }
 // CHECK:STDOUT: }
 // CHECK:STDOUT:
 // CHECK:STDOUT:
 // CHECK:STDOUT: fn @F() -> (i32,) {
 // CHECK:STDOUT: fn @F() -> (i32,) {

+ 1 - 1
toolchain/check/testdata/array/fail_incomplete_element.carbon

@@ -28,7 +28,7 @@ var p: Incomplete* = &a[0];
 // CHECK:STDOUT:
 // CHECK:STDOUT:
 // CHECK:STDOUT: file {
 // CHECK:STDOUT: file {
 // CHECK:STDOUT:   package: <namespace> = namespace {.Incomplete = %Incomplete.decl, .a = %a, .p = %p} [template]
 // CHECK:STDOUT:   package: <namespace> = namespace {.Incomplete = %Incomplete.decl, .a = %a, .p = %p} [template]
-// CHECK:STDOUT:   %Incomplete.decl = class_decl @Incomplete, () [template = constants.%Incomplete]
+// CHECK:STDOUT:   %Incomplete.decl = class_decl @Incomplete {} [template = constants.%Incomplete]
 // CHECK:STDOUT:   %Incomplete.ref.loc15: type = name_ref Incomplete, %Incomplete.decl [template = constants.%Incomplete]
 // CHECK:STDOUT:   %Incomplete.ref.loc15: type = name_ref Incomplete, %Incomplete.decl [template = constants.%Incomplete]
 // CHECK:STDOUT:   %.loc15_21: i32 = int_literal 1 [template = constants.%.1]
 // CHECK:STDOUT:   %.loc15_21: i32 = int_literal 1 [template = constants.%.1]
 // CHECK:STDOUT:   %.loc15_22: type = array_type %.loc15_21, Incomplete [template = constants.%.2]
 // CHECK:STDOUT:   %.loc15_22: type = array_type %.loc15_21, Incomplete [template = constants.%.2]

+ 12 - 2
toolchain/check/testdata/array/function_param.carbon

@@ -29,8 +29,18 @@ fn G() -> i32 {
 // CHECK:STDOUT:
 // CHECK:STDOUT:
 // CHECK:STDOUT: file {
 // CHECK:STDOUT: file {
 // CHECK:STDOUT:   package: <namespace> = namespace {.F = %F, .G = %G} [template]
 // CHECK:STDOUT:   package: <namespace> = namespace {.F = %F, .G = %G} [template]
-// CHECK:STDOUT:   %F: <function> = fn_decl @F [template]
-// CHECK:STDOUT:   %G: <function> = fn_decl @G [template]
+// CHECK:STDOUT:   %F: <function> = fn_decl @F {
+// CHECK:STDOUT:     %.loc7_17: i32 = int_literal 3 [template = constants.%.1]
+// CHECK:STDOUT:     %.loc7_18: type = array_type %.loc7_17, i32 [template = constants.%.2]
+// CHECK:STDOUT:     %arr.loc7_6.1: [i32; 3] = param arr
+// CHECK:STDOUT:     @F.%arr: [i32; 3] = bind_name arr, %arr.loc7_6.1
+// CHECK:STDOUT:     %i.loc7_21.1: i32 = param i
+// CHECK:STDOUT:     @F.%i: i32 = bind_name i, %i.loc7_21.1
+// CHECK:STDOUT:     %return.var.loc7: ref i32 = var <return slot>
+// CHECK:STDOUT:   } [template]
+// CHECK:STDOUT:   %G: <function> = fn_decl @G {
+// CHECK:STDOUT:     %return.var.loc11: ref i32 = var <return slot>
+// CHECK:STDOUT:   } [template]
 // CHECK:STDOUT: }
 // CHECK:STDOUT: }
 // CHECK:STDOUT:
 // CHECK:STDOUT:
 // CHECK:STDOUT: fn @F(%arr: [i32; 3], %i: i32) -> i32 {
 // CHECK:STDOUT: fn @F(%arr: [i32; 3], %i: i32) -> i32 {

+ 3 - 1
toolchain/check/testdata/as/basic.carbon

@@ -16,7 +16,9 @@ fn Main() -> i32 {
 // CHECK:STDOUT:
 // CHECK:STDOUT:
 // CHECK:STDOUT: file {
 // CHECK:STDOUT: file {
 // CHECK:STDOUT:   package: <namespace> = namespace {.Main = %Main} [template]
 // CHECK:STDOUT:   package: <namespace> = namespace {.Main = %Main} [template]
-// CHECK:STDOUT:   %Main: <function> = fn_decl @Main [template]
+// CHECK:STDOUT:   %Main: <function> = fn_decl @Main {
+// CHECK:STDOUT:     %return.var: ref i32 = var <return slot>
+// CHECK:STDOUT:   } [template]
 // CHECK:STDOUT: }
 // CHECK:STDOUT: }
 // CHECK:STDOUT:
 // CHECK:STDOUT:
 // CHECK:STDOUT: fn @Main() -> i32 {
 // CHECK:STDOUT: fn @Main() -> i32 {

+ 17 - 5
toolchain/check/testdata/as/identity.carbon

@@ -36,11 +36,23 @@ fn Initializing() {
 // CHECK:STDOUT:
 // CHECK:STDOUT:
 // CHECK:STDOUT: file {
 // CHECK:STDOUT: file {
 // CHECK:STDOUT:   package: <namespace> = namespace {.X = %X.decl, .Value = %Value, .Reference = %Reference, .Make = %Make, .Initializing = %Initializing} [template]
 // CHECK:STDOUT:   package: <namespace> = namespace {.X = %X.decl, .Value = %Value, .Reference = %Reference, .Make = %Make, .Initializing = %Initializing} [template]
-// CHECK:STDOUT:   %X.decl = class_decl @X, () [template = constants.%X]
-// CHECK:STDOUT:   %Value: <function> = fn_decl @Value [template]
-// CHECK:STDOUT:   %Reference: <function> = fn_decl @Reference [template]
-// CHECK:STDOUT:   %Make: <function> = fn_decl @Make [template]
-// CHECK:STDOUT:   %Initializing: <function> = fn_decl @Initializing [template]
+// CHECK:STDOUT:   %X.decl = class_decl @X {} [template = constants.%X]
+// CHECK:STDOUT:   %Value: <function> = fn_decl @Value {
+// CHECK:STDOUT:     %X.ref.loc13: type = name_ref X, %X.decl [template = constants.%X]
+// CHECK:STDOUT:     %n.loc13_10.1: X = param n
+// CHECK:STDOUT:     @Value.%n: X = bind_name n, %n.loc13_10.1
+// CHECK:STDOUT:   } [template]
+// CHECK:STDOUT:   %Reference: <function> = fn_decl @Reference {
+// CHECK:STDOUT:     %X.ref.loc17: type = name_ref X, %X.decl [template = constants.%X]
+// CHECK:STDOUT:     %.loc17: type = ptr_type X [template = constants.%.4]
+// CHECK:STDOUT:     %p.loc17_14.1: X* = param p
+// CHECK:STDOUT:     @Reference.%p: X* = bind_name p, %p.loc17_14.1
+// CHECK:STDOUT:   } [template]
+// CHECK:STDOUT:   %Make: <function> = fn_decl @Make {
+// CHECK:STDOUT:     %X.ref.loc21: type = name_ref X, %X.decl [template = constants.%X]
+// CHECK:STDOUT:     @Make.%return: ref X = var <return slot>
+// CHECK:STDOUT:   } [template]
+// CHECK:STDOUT:   %Initializing: <function> = fn_decl @Initializing {} [template]
 // CHECK:STDOUT: }
 // CHECK:STDOUT: }
 // CHECK:STDOUT:
 // CHECK:STDOUT:
 // CHECK:STDOUT: class @X {
 // CHECK:STDOUT: class @X {

+ 7 - 4
toolchain/check/testdata/as/tuple.carbon

@@ -35,10 +35,13 @@ fn Var() {
 // CHECK:STDOUT:
 // CHECK:STDOUT:
 // CHECK:STDOUT: file {
 // CHECK:STDOUT: file {
 // CHECK:STDOUT:   package: <namespace> = namespace {.X = %X.decl, .Make = %Make, .Let = %Let, .Var = %Var} [template]
 // CHECK:STDOUT:   package: <namespace> = namespace {.X = %X.decl, .Make = %Make, .Let = %Let, .Var = %Var} [template]
-// CHECK:STDOUT:   %X.decl = class_decl @X, () [template = constants.%X]
-// CHECK:STDOUT:   %Make: <function> = fn_decl @Make [template]
-// CHECK:STDOUT:   %Let: <function> = fn_decl @Let [template]
-// CHECK:STDOUT:   %Var: <function> = fn_decl @Var [template]
+// CHECK:STDOUT:   %X.decl = class_decl @X {} [template = constants.%X]
+// CHECK:STDOUT:   %Make: <function> = fn_decl @Make {
+// CHECK:STDOUT:     %X.ref: type = name_ref X, %X.decl [template = constants.%X]
+// CHECK:STDOUT:     @Make.%return: ref X = var <return slot>
+// CHECK:STDOUT:   } [template]
+// CHECK:STDOUT:   %Let: <function> = fn_decl @Let {} [template]
+// CHECK:STDOUT:   %Var: <function> = fn_decl @Var {} [template]
 // CHECK:STDOUT: }
 // CHECK:STDOUT: }
 // CHECK:STDOUT:
 // CHECK:STDOUT:
 // CHECK:STDOUT: class @X {
 // CHECK:STDOUT: class @X {

+ 3 - 1
toolchain/check/testdata/basics/fail_bad_run.carbon

@@ -21,7 +21,9 @@ fn Run() -> String {}
 // CHECK:STDOUT:
 // CHECK:STDOUT:
 // CHECK:STDOUT: file {
 // CHECK:STDOUT: file {
 // CHECK:STDOUT:   package: <namespace> = namespace {.Run = %Run} [template]
 // CHECK:STDOUT:   package: <namespace> = namespace {.Run = %Run} [template]
-// CHECK:STDOUT:   %Run: <function> = fn_decl @Run [template]
+// CHECK:STDOUT:   %Run: <function> = fn_decl @Run {
+// CHECK:STDOUT:     @Run.%return: ref String = var <return slot>
+// CHECK:STDOUT:   } [template]
 // CHECK:STDOUT: }
 // CHECK:STDOUT: }
 // CHECK:STDOUT:
 // CHECK:STDOUT:
 // CHECK:STDOUT: fn @Run() -> %return: String {
 // CHECK:STDOUT: fn @Run() -> %return: String {

+ 4 - 1
toolchain/check/testdata/basics/fail_bad_run_2.carbon

@@ -13,7 +13,10 @@ fn Run(n: i32) {}
 // CHECK:STDOUT:
 // CHECK:STDOUT:
 // CHECK:STDOUT: file {
 // CHECK:STDOUT: file {
 // CHECK:STDOUT:   package: <namespace> = namespace {.Run = %Run} [template]
 // CHECK:STDOUT:   package: <namespace> = namespace {.Run = %Run} [template]
-// CHECK:STDOUT:   %Run: <function> = fn_decl @Run [template]
+// CHECK:STDOUT:   %Run: <function> = fn_decl @Run {
+// CHECK:STDOUT:     %n.loc10_8.1: i32 = param n
+// CHECK:STDOUT:     @Run.%n: i32 = bind_name n, %n.loc10_8.1
+// CHECK:STDOUT:   } [template]
 // CHECK:STDOUT: }
 // CHECK:STDOUT: }
 // CHECK:STDOUT:
 // CHECK:STDOUT:
 // CHECK:STDOUT: fn @Run(%n: i32) {
 // CHECK:STDOUT: fn @Run(%n: i32) {

+ 1 - 1
toolchain/check/testdata/basics/fail_name_lookup.carbon

@@ -15,7 +15,7 @@ fn Main() {
 // CHECK:STDOUT:
 // CHECK:STDOUT:
 // CHECK:STDOUT: file {
 // CHECK:STDOUT: file {
 // CHECK:STDOUT:   package: <namespace> = namespace {.Main = %Main} [template]
 // CHECK:STDOUT:   package: <namespace> = namespace {.Main = %Main} [template]
-// CHECK:STDOUT:   %Main: <function> = fn_decl @Main [template]
+// CHECK:STDOUT:   %Main: <function> = fn_decl @Main {} [template]
 // CHECK:STDOUT: }
 // CHECK:STDOUT: }
 // CHECK:STDOUT:
 // CHECK:STDOUT:
 // CHECK:STDOUT: fn @Main() {
 // CHECK:STDOUT: fn @Main() {

+ 2 - 2
toolchain/check/testdata/basics/multifile.carbon

@@ -18,7 +18,7 @@ fn B() {}
 // CHECK:STDOUT:
 // CHECK:STDOUT:
 // CHECK:STDOUT: file {
 // CHECK:STDOUT: file {
 // CHECK:STDOUT:   package: <namespace> = namespace {.A = %A} [template]
 // CHECK:STDOUT:   package: <namespace> = namespace {.A = %A} [template]
-// CHECK:STDOUT:   %A: <function> = fn_decl @A [template]
+// CHECK:STDOUT:   %A: <function> = fn_decl @A {} [template]
 // CHECK:STDOUT: }
 // CHECK:STDOUT: }
 // CHECK:STDOUT:
 // CHECK:STDOUT:
 // CHECK:STDOUT: fn @A() {
 // CHECK:STDOUT: fn @A() {
@@ -30,7 +30,7 @@ fn B() {}
 // CHECK:STDOUT:
 // CHECK:STDOUT:
 // CHECK:STDOUT: file {
 // CHECK:STDOUT: file {
 // CHECK:STDOUT:   package: <namespace> = namespace {.B = %B} [template]
 // CHECK:STDOUT:   package: <namespace> = namespace {.B = %B} [template]
-// CHECK:STDOUT:   %B: <function> = fn_decl @B [template]
+// CHECK:STDOUT:   %B: <function> = fn_decl @B {} [template]
 // CHECK:STDOUT: }
 // CHECK:STDOUT: }
 // CHECK:STDOUT:
 // CHECK:STDOUT:
 // CHECK:STDOUT: fn @B() {
 // CHECK:STDOUT: fn @B() {

+ 4 - 4
toolchain/check/testdata/basics/multifile_raw_and_textual_ir.carbon

@@ -34,7 +34,7 @@ fn B() {}
 // CHECK:STDOUT:   type_blocks:     {}
 // CHECK:STDOUT:   type_blocks:     {}
 // CHECK:STDOUT:   insts:
 // CHECK:STDOUT:   insts:
 // CHECK:STDOUT:     inst+0:          {kind: Namespace, arg0: name_scope0, arg1: inst<invalid>, type: type0}
 // CHECK:STDOUT:     inst+0:          {kind: Namespace, arg0: name_scope0, arg1: inst<invalid>, type: type0}
-// CHECK:STDOUT:     inst+1:          {kind: FunctionDecl, arg0: function0, type: type1}
+// CHECK:STDOUT:     inst+1:          {kind: FunctionDecl, arg0: function0, arg1: empty, type: type1}
 // CHECK:STDOUT:     inst+2:          {kind: Return}
 // CHECK:STDOUT:     inst+2:          {kind: Return}
 // CHECK:STDOUT:   constant_values:
 // CHECK:STDOUT:   constant_values:
 // CHECK:STDOUT:     inst+0:          template inst+0
 // CHECK:STDOUT:     inst+0:          template inst+0
@@ -55,7 +55,7 @@ fn B() {}
 // CHECK:STDOUT:
 // CHECK:STDOUT:
 // CHECK:STDOUT: file {
 // CHECK:STDOUT: file {
 // CHECK:STDOUT:   package: <namespace> = namespace {.A = %A} [template]
 // CHECK:STDOUT:   package: <namespace> = namespace {.A = %A} [template]
-// CHECK:STDOUT:   %A: <function> = fn_decl @A [template]
+// CHECK:STDOUT:   %A: <function> = fn_decl @A {} [template]
 // CHECK:STDOUT: }
 // CHECK:STDOUT: }
 // CHECK:STDOUT:
 // CHECK:STDOUT:
 // CHECK:STDOUT: fn @A() {
 // CHECK:STDOUT: fn @A() {
@@ -79,7 +79,7 @@ fn B() {}
 // CHECK:STDOUT:   type_blocks:     {}
 // CHECK:STDOUT:   type_blocks:     {}
 // CHECK:STDOUT:   insts:
 // CHECK:STDOUT:   insts:
 // CHECK:STDOUT:     inst+0:          {kind: Namespace, arg0: name_scope0, arg1: inst<invalid>, type: type0}
 // CHECK:STDOUT:     inst+0:          {kind: Namespace, arg0: name_scope0, arg1: inst<invalid>, type: type0}
-// CHECK:STDOUT:     inst+1:          {kind: FunctionDecl, arg0: function0, type: type1}
+// CHECK:STDOUT:     inst+1:          {kind: FunctionDecl, arg0: function0, arg1: empty, type: type1}
 // CHECK:STDOUT:     inst+2:          {kind: Return}
 // CHECK:STDOUT:     inst+2:          {kind: Return}
 // CHECK:STDOUT:   constant_values:
 // CHECK:STDOUT:   constant_values:
 // CHECK:STDOUT:     inst+0:          template inst+0
 // CHECK:STDOUT:     inst+0:          template inst+0
@@ -100,7 +100,7 @@ fn B() {}
 // CHECK:STDOUT:
 // CHECK:STDOUT:
 // CHECK:STDOUT: file {
 // CHECK:STDOUT: file {
 // CHECK:STDOUT:   package: <namespace> = namespace {.B = %B} [template]
 // CHECK:STDOUT:   package: <namespace> = namespace {.B = %B} [template]
-// CHECK:STDOUT:   %B: <function> = fn_decl @B [template]
+// CHECK:STDOUT:   %B: <function> = fn_decl @B {} [template]
 // CHECK:STDOUT: }
 // CHECK:STDOUT: }
 // CHECK:STDOUT:
 // CHECK:STDOUT:
 // CHECK:STDOUT: fn @B() {
 // CHECK:STDOUT: fn @B() {

+ 2 - 2
toolchain/check/testdata/basics/multifile_raw_ir.carbon

@@ -34,7 +34,7 @@ fn B() {}
 // CHECK:STDOUT:   type_blocks:     {}
 // CHECK:STDOUT:   type_blocks:     {}
 // CHECK:STDOUT:   insts:
 // CHECK:STDOUT:   insts:
 // CHECK:STDOUT:     inst+0:          {kind: Namespace, arg0: name_scope0, arg1: inst<invalid>, type: type0}
 // CHECK:STDOUT:     inst+0:          {kind: Namespace, arg0: name_scope0, arg1: inst<invalid>, type: type0}
-// CHECK:STDOUT:     inst+1:          {kind: FunctionDecl, arg0: function0, type: type1}
+// CHECK:STDOUT:     inst+1:          {kind: FunctionDecl, arg0: function0, arg1: empty, type: type1}
 // CHECK:STDOUT:     inst+2:          {kind: Return}
 // CHECK:STDOUT:     inst+2:          {kind: Return}
 // CHECK:STDOUT:   constant_values:
 // CHECK:STDOUT:   constant_values:
 // CHECK:STDOUT:     inst+0:          template inst+0
 // CHECK:STDOUT:     inst+0:          template inst+0
@@ -66,7 +66,7 @@ fn B() {}
 // CHECK:STDOUT:   type_blocks:     {}
 // CHECK:STDOUT:   type_blocks:     {}
 // CHECK:STDOUT:   insts:
 // CHECK:STDOUT:   insts:
 // CHECK:STDOUT:     inst+0:          {kind: Namespace, arg0: name_scope0, arg1: inst<invalid>, type: type0}
 // CHECK:STDOUT:     inst+0:          {kind: Namespace, arg0: name_scope0, arg1: inst<invalid>, type: type0}
-// CHECK:STDOUT:     inst+1:          {kind: FunctionDecl, arg0: function0, type: type1}
+// CHECK:STDOUT:     inst+1:          {kind: FunctionDecl, arg0: function0, arg1: empty, type: type1}
 // CHECK:STDOUT:     inst+2:          {kind: Return}
 // CHECK:STDOUT:     inst+2:          {kind: Return}
 // CHECK:STDOUT:   constant_values:
 // CHECK:STDOUT:   constant_values:
 // CHECK:STDOUT:     inst+0:          template inst+0
 // CHECK:STDOUT:     inst+0:          template inst+0

+ 1 - 1
toolchain/check/testdata/basics/numeric_literals.carbon

@@ -59,7 +59,7 @@ fn F() {
 // CHECK:STDOUT:
 // CHECK:STDOUT:
 // CHECK:STDOUT: file {
 // CHECK:STDOUT: file {
 // CHECK:STDOUT:   package: <namespace> = namespace {.F = %F} [template]
 // CHECK:STDOUT:   package: <namespace> = namespace {.F = %F} [template]
-// CHECK:STDOUT:   %F: <function> = fn_decl @F [template]
+// CHECK:STDOUT:   %F: <function> = fn_decl @F {} [template]
 // CHECK:STDOUT: }
 // CHECK:STDOUT: }
 // CHECK:STDOUT:
 // CHECK:STDOUT:
 // CHECK:STDOUT: fn @F() {
 // CHECK:STDOUT: fn @F() {

+ 8 - 2
toolchain/check/testdata/basics/raw_and_textual_ir.carbon

@@ -54,7 +54,7 @@ fn Foo(n: i32) -> (i32, i32, f64) {
 // CHECK:STDOUT:     inst+6:          {kind: Converted, arg0: inst+4, arg1: inst+5, type: typeTypeType}
 // CHECK:STDOUT:     inst+6:          {kind: Converted, arg0: inst+4, arg1: inst+5, type: typeTypeType}
 // CHECK:STDOUT:     inst+7:          {kind: VarStorage, arg0: nameReturnSlot, type: type4}
 // CHECK:STDOUT:     inst+7:          {kind: VarStorage, arg0: nameReturnSlot, type: type4}
 // CHECK:STDOUT:     inst+8:          {kind: PointerType, arg0: type4, type: typeTypeType}
 // CHECK:STDOUT:     inst+8:          {kind: PointerType, arg0: type4, type: typeTypeType}
-// CHECK:STDOUT:     inst+9:          {kind: FunctionDecl, arg0: function0, type: type6}
+// CHECK:STDOUT:     inst+9:          {kind: FunctionDecl, arg0: function0, arg1: block5, type: type6}
 // CHECK:STDOUT:     inst+10:         {kind: NameRef, arg0: name1, arg1: inst+2, type: type1}
 // CHECK:STDOUT:     inst+10:         {kind: NameRef, arg0: name1, arg1: inst+2, type: type1}
 // CHECK:STDOUT:     inst+11:         {kind: IntLiteral, arg0: int4, type: type1}
 // CHECK:STDOUT:     inst+11:         {kind: IntLiteral, arg0: int4, type: type1}
 // CHECK:STDOUT:     inst+12:         {kind: IntLiteral, arg0: int4, type: type1}
 // CHECK:STDOUT:     inst+12:         {kind: IntLiteral, arg0: int4, type: type1}
@@ -139,7 +139,13 @@ fn Foo(n: i32) -> (i32, i32, f64) {
 // CHECK:STDOUT:
 // CHECK:STDOUT:
 // CHECK:STDOUT: file {
 // CHECK:STDOUT: file {
 // CHECK:STDOUT:   package: <namespace> = namespace {.Foo = %Foo} [template]
 // CHECK:STDOUT:   package: <namespace> = namespace {.Foo = %Foo} [template]
-// CHECK:STDOUT:   %Foo: <function> = fn_decl @Foo [template]
+// CHECK:STDOUT:   %Foo: <function> = fn_decl @Foo {
+// CHECK:STDOUT:     %n.loc11_8.1: i32 = param n
+// CHECK:STDOUT:     @Foo.%n: i32 = bind_name n, %n.loc11_8.1
+// CHECK:STDOUT:     %.loc11_33.1: (type, type, type) = tuple_literal (i32, i32, f64)
+// CHECK:STDOUT:     %.loc11_33.2: type = converted %.loc11_33.1, constants.%.2 [template = constants.%.2]
+// CHECK:STDOUT:     @Foo.%return: ref (i32, i32, f64) = var <return slot>
+// CHECK:STDOUT:   } [template]
 // CHECK:STDOUT: }
 // CHECK:STDOUT: }
 // CHECK:STDOUT:
 // CHECK:STDOUT:
 // CHECK:STDOUT: fn @Foo(%n: i32) -> %return: (i32, i32, f64) {
 // CHECK:STDOUT: fn @Foo(%n: i32) -> %return: (i32, i32, f64) {

+ 15 - 3
toolchain/check/testdata/basics/raw_identifier.carbon

@@ -24,9 +24,21 @@ fn C(r#if: i32) -> i32 {
 // CHECK:STDOUT:
 // CHECK:STDOUT:
 // CHECK:STDOUT: file {
 // CHECK:STDOUT: file {
 // CHECK:STDOUT:   package: <namespace> = namespace {.A = %A, .B = %B, .C = %C} [template]
 // CHECK:STDOUT:   package: <namespace> = namespace {.A = %A, .B = %B, .C = %C} [template]
-// CHECK:STDOUT:   %A: <function> = fn_decl @A [template]
-// CHECK:STDOUT:   %B: <function> = fn_decl @B [template]
-// CHECK:STDOUT:   %C: <function> = fn_decl @C [template]
+// CHECK:STDOUT:   %A: <function> = fn_decl @A {
+// CHECK:STDOUT:     %n.loc11_6.1: i32 = param n
+// CHECK:STDOUT:     @A.%n: i32 = bind_name n, %n.loc11_6.1
+// CHECK:STDOUT:     %return.var.loc11: ref i32 = var <return slot>
+// CHECK:STDOUT:   } [template]
+// CHECK:STDOUT:   %B: <function> = fn_decl @B {
+// CHECK:STDOUT:     %n.loc15_6.1: i32 = param n
+// CHECK:STDOUT:     @B.%n: i32 = bind_name n, %n.loc15_6.1
+// CHECK:STDOUT:     %return.var.loc15: ref i32 = var <return slot>
+// CHECK:STDOUT:   } [template]
+// CHECK:STDOUT:   %C: <function> = fn_decl @C {
+// CHECK:STDOUT:     %if.loc19_6.1: i32 = param r#if
+// CHECK:STDOUT:     @C.%if: i32 = bind_name r#if, %if.loc19_6.1
+// CHECK:STDOUT:     %return.var.loc19: ref i32 = var <return slot>
+// CHECK:STDOUT:   } [template]
 // CHECK:STDOUT: }
 // CHECK:STDOUT: }
 // CHECK:STDOUT:
 // CHECK:STDOUT:
 // CHECK:STDOUT: fn @A(%n: i32) -> i32 {
 // CHECK:STDOUT: fn @A(%n: i32) -> i32 {

+ 1 - 1
toolchain/check/testdata/basics/raw_ir.carbon

@@ -54,7 +54,7 @@ fn Foo(n: i32) -> (i32, i32, f64) {
 // CHECK:STDOUT:     inst+6:          {kind: Converted, arg0: inst+4, arg1: inst+5, type: typeTypeType}
 // CHECK:STDOUT:     inst+6:          {kind: Converted, arg0: inst+4, arg1: inst+5, type: typeTypeType}
 // CHECK:STDOUT:     inst+7:          {kind: VarStorage, arg0: nameReturnSlot, type: type4}
 // CHECK:STDOUT:     inst+7:          {kind: VarStorage, arg0: nameReturnSlot, type: type4}
 // CHECK:STDOUT:     inst+8:          {kind: PointerType, arg0: type4, type: typeTypeType}
 // CHECK:STDOUT:     inst+8:          {kind: PointerType, arg0: type4, type: typeTypeType}
-// CHECK:STDOUT:     inst+9:          {kind: FunctionDecl, arg0: function0, type: type6}
+// CHECK:STDOUT:     inst+9:          {kind: FunctionDecl, arg0: function0, arg1: block5, type: type6}
 // CHECK:STDOUT:     inst+10:         {kind: NameRef, arg0: name1, arg1: inst+2, type: type1}
 // CHECK:STDOUT:     inst+10:         {kind: NameRef, arg0: name1, arg1: inst+2, type: type1}
 // CHECK:STDOUT:     inst+11:         {kind: IntLiteral, arg0: int4, type: type1}
 // CHECK:STDOUT:     inst+11:         {kind: IntLiteral, arg0: int4, type: type1}
 // CHECK:STDOUT:     inst+12:         {kind: IntLiteral, arg0: int4, type: type1}
 // CHECK:STDOUT:     inst+12:         {kind: IntLiteral, arg0: int4, type: type1}

+ 1 - 1
toolchain/check/testdata/basics/run.carbon

@@ -10,7 +10,7 @@ fn Run() {}
 // CHECK:STDOUT:
 // CHECK:STDOUT:
 // CHECK:STDOUT: file {
 // CHECK:STDOUT: file {
 // CHECK:STDOUT:   package: <namespace> = namespace {.Run = %Run} [template]
 // CHECK:STDOUT:   package: <namespace> = namespace {.Run = %Run} [template]
-// CHECK:STDOUT:   %Run: <function> = fn_decl @Run [template]
+// CHECK:STDOUT:   %Run: <function> = fn_decl @Run {} [template]
 // CHECK:STDOUT: }
 // CHECK:STDOUT: }
 // CHECK:STDOUT:
 // CHECK:STDOUT:
 // CHECK:STDOUT: fn @Run() {
 // CHECK:STDOUT: fn @Run() {

+ 3 - 1
toolchain/check/testdata/basics/run_i32.carbon

@@ -14,7 +14,9 @@ fn Run() -> i32 { return 0; }
 // CHECK:STDOUT:
 // CHECK:STDOUT:
 // CHECK:STDOUT: file {
 // CHECK:STDOUT: file {
 // CHECK:STDOUT:   package: <namespace> = namespace {.Run = %Run} [template]
 // CHECK:STDOUT:   package: <namespace> = namespace {.Run = %Run} [template]
-// CHECK:STDOUT:   %Run: <function> = fn_decl @Run [template]
+// CHECK:STDOUT:   %Run: <function> = fn_decl @Run {
+// CHECK:STDOUT:     %return.var: ref i32 = var <return slot>
+// CHECK:STDOUT:   } [template]
 // CHECK:STDOUT: }
 // CHECK:STDOUT: }
 // CHECK:STDOUT:
 // CHECK:STDOUT:
 // CHECK:STDOUT: fn @Run() -> i32 {
 // CHECK:STDOUT: fn @Run() -> i32 {

+ 7 - 1
toolchain/check/testdata/basics/textual_ir.carbon

@@ -24,7 +24,13 @@ fn Foo(n: i32) -> (i32, i32, f64) {
 // CHECK:STDOUT:
 // CHECK:STDOUT:
 // CHECK:STDOUT: file {
 // CHECK:STDOUT: file {
 // CHECK:STDOUT:   package: <namespace> = namespace {.Foo = %Foo} [template]
 // CHECK:STDOUT:   package: <namespace> = namespace {.Foo = %Foo} [template]
-// CHECK:STDOUT:   %Foo: <function> = fn_decl @Foo [template]
+// CHECK:STDOUT:   %Foo: <function> = fn_decl @Foo {
+// CHECK:STDOUT:     %n.loc11_8.1: i32 = param n
+// CHECK:STDOUT:     @Foo.%n: i32 = bind_name n, %n.loc11_8.1
+// CHECK:STDOUT:     %.loc11_33.1: (type, type, type) = tuple_literal (i32, i32, f64)
+// CHECK:STDOUT:     %.loc11_33.2: type = converted %.loc11_33.1, constants.%.2 [template = constants.%.2]
+// CHECK:STDOUT:     @Foo.%return: ref (i32, i32, f64) = var <return slot>
+// CHECK:STDOUT:   } [template]
 // CHECK:STDOUT: }
 // CHECK:STDOUT: }
 // CHECK:STDOUT:
 // CHECK:STDOUT:
 // CHECK:STDOUT: fn @Foo(%n: i32) -> %return: (i32, i32, f64) {
 // CHECK:STDOUT: fn @Foo(%n: i32) -> %return: (i32, i32, f64) {

+ 14 - 4
toolchain/check/testdata/class/base.carbon

@@ -48,10 +48,20 @@ fn Access(d: Derived) -> (i32, i32) {
 // CHECK:STDOUT:
 // CHECK:STDOUT:
 // CHECK:STDOUT: file {
 // CHECK:STDOUT: file {
 // CHECK:STDOUT:   package: <namespace> = namespace {.Base = %Base.decl, .Derived = %Derived.decl, .Make = %Make, .Access = %Access} [template]
 // CHECK:STDOUT:   package: <namespace> = namespace {.Base = %Base.decl, .Derived = %Derived.decl, .Make = %Make, .Access = %Access} [template]
-// CHECK:STDOUT:   %Base.decl = class_decl @Base, () [template = constants.%Base]
-// CHECK:STDOUT:   %Derived.decl = class_decl @Derived, () [template = constants.%Derived]
-// CHECK:STDOUT:   %Make: <function> = fn_decl @Make [template]
-// CHECK:STDOUT:   %Access: <function> = fn_decl @Access [template]
+// CHECK:STDOUT:   %Base.decl = class_decl @Base {} [template = constants.%Base]
+// CHECK:STDOUT:   %Derived.decl = class_decl @Derived {} [template = constants.%Derived]
+// CHECK:STDOUT:   %Make: <function> = fn_decl @Make {
+// CHECK:STDOUT:     %Derived.ref.loc17: type = name_ref Derived, %Derived.decl [template = constants.%Derived]
+// CHECK:STDOUT:     @Make.%return: ref Derived = var <return slot>
+// CHECK:STDOUT:   } [template]
+// CHECK:STDOUT:   %Access: <function> = fn_decl @Access {
+// CHECK:STDOUT:     %Derived.ref.loc21: type = name_ref Derived, %Derived.decl [template = constants.%Derived]
+// CHECK:STDOUT:     %d.loc21_11.1: Derived = param d
+// CHECK:STDOUT:     @Access.%d: Derived = bind_name d, %d.loc21_11.1
+// CHECK:STDOUT:     %.loc21_35.1: (type, type) = tuple_literal (i32, i32)
+// CHECK:STDOUT:     %.loc21_35.2: type = converted %.loc21_35.1, constants.%.16 [template = constants.%.16]
+// CHECK:STDOUT:     @Access.%return: ref (i32, i32) = var <return slot>
+// CHECK:STDOUT:   } [template]
 // CHECK:STDOUT: }
 // CHECK:STDOUT: }
 // CHECK:STDOUT:
 // CHECK:STDOUT:
 // CHECK:STDOUT: class @Base {
 // CHECK:STDOUT: class @Base {

+ 10 - 3
toolchain/check/testdata/class/base_field.carbon

@@ -41,9 +41,16 @@ fn Access(p: Derived*) -> i32* {
 // CHECK:STDOUT:
 // CHECK:STDOUT:
 // CHECK:STDOUT: file {
 // CHECK:STDOUT: file {
 // CHECK:STDOUT:   package: <namespace> = namespace {.Base = %Base.decl, .Derived = %Derived.decl, .Access = %Access} [template]
 // CHECK:STDOUT:   package: <namespace> = namespace {.Base = %Base.decl, .Derived = %Derived.decl, .Access = %Access} [template]
-// CHECK:STDOUT:   %Base.decl = class_decl @Base, () [template = constants.%Base]
-// CHECK:STDOUT:   %Derived.decl = class_decl @Derived, () [template = constants.%Derived]
-// CHECK:STDOUT:   %Access: <function> = fn_decl @Access [template]
+// CHECK:STDOUT:   %Base.decl = class_decl @Base {} [template = constants.%Base]
+// CHECK:STDOUT:   %Derived.decl = class_decl @Derived {} [template = constants.%Derived]
+// CHECK:STDOUT:   %Access: <function> = fn_decl @Access {
+// CHECK:STDOUT:     %Derived.ref: type = name_ref Derived, %Derived.decl [template = constants.%Derived]
+// CHECK:STDOUT:     %.loc20_21: type = ptr_type Derived [template = constants.%.7]
+// CHECK:STDOUT:     %p.loc20_11.1: Derived* = param p
+// CHECK:STDOUT:     @Access.%p: Derived* = bind_name p, %p.loc20_11.1
+// CHECK:STDOUT:     %.loc20_30: type = ptr_type i32 [template = constants.%.8]
+// CHECK:STDOUT:     %return.var: ref i32* = var <return slot>
+// CHECK:STDOUT:   } [template]
 // CHECK:STDOUT: }
 // CHECK:STDOUT: }
 // CHECK:STDOUT:
 // CHECK:STDOUT:
 // CHECK:STDOUT: class @Base {
 // CHECK:STDOUT: class @Base {

+ 6 - 6
toolchain/check/testdata/class/base_function_unqualified.carbon

@@ -33,13 +33,13 @@ fn Derived.H() {
 // CHECK:STDOUT:
 // CHECK:STDOUT:
 // CHECK:STDOUT: file {
 // CHECK:STDOUT: file {
 // CHECK:STDOUT:   package: <namespace> = namespace {.Base = %Base.decl, .Derived = %Derived.decl} [template]
 // CHECK:STDOUT:   package: <namespace> = namespace {.Base = %Base.decl, .Derived = %Derived.decl} [template]
-// CHECK:STDOUT:   %Base.decl = class_decl @Base, () [template = constants.%Base]
-// CHECK:STDOUT:   %Derived.decl = class_decl @Derived, () [template = constants.%Derived]
-// CHECK:STDOUT:   %H: <function> = fn_decl @H [template]
+// CHECK:STDOUT:   %Base.decl = class_decl @Base {} [template = constants.%Base]
+// CHECK:STDOUT:   %Derived.decl = class_decl @Derived {} [template = constants.%Derived]
+// CHECK:STDOUT:   %H: <function> = fn_decl @H {} [template]
 // CHECK:STDOUT: }
 // CHECK:STDOUT: }
 // CHECK:STDOUT:
 // CHECK:STDOUT:
 // CHECK:STDOUT: class @Base {
 // CHECK:STDOUT: class @Base {
-// CHECK:STDOUT:   %F: <function> = fn_decl @F [template]
+// CHECK:STDOUT:   %F: <function> = fn_decl @F {} [template]
 // CHECK:STDOUT:
 // CHECK:STDOUT:
 // CHECK:STDOUT: !members:
 // CHECK:STDOUT: !members:
 // CHECK:STDOUT:   .F = %F
 // CHECK:STDOUT:   .F = %F
@@ -48,8 +48,8 @@ fn Derived.H() {
 // CHECK:STDOUT: class @Derived {
 // CHECK:STDOUT: class @Derived {
 // CHECK:STDOUT:   %Base.ref: type = name_ref Base, file.%Base.decl [template = constants.%Base]
 // CHECK:STDOUT:   %Base.ref: type = name_ref Base, file.%Base.decl [template = constants.%Base]
 // CHECK:STDOUT:   %.loc12: <unbound element of class Derived> = base_decl Base, element0 [template]
 // CHECK:STDOUT:   %.loc12: <unbound element of class Derived> = base_decl Base, element0 [template]
-// CHECK:STDOUT:   %G: <function> = fn_decl @G [template]
-// CHECK:STDOUT:   %H: <function> = fn_decl @H [template]
+// CHECK:STDOUT:   %G: <function> = fn_decl @G {} [template]
+// CHECK:STDOUT:   %H: <function> = fn_decl @H {} [template]
 // CHECK:STDOUT:
 // CHECK:STDOUT:
 // CHECK:STDOUT: !members:
 // CHECK:STDOUT: !members:
 // CHECK:STDOUT:   .base = %.loc12
 // CHECK:STDOUT:   .base = %.loc12

+ 22 - 5
toolchain/check/testdata/class/base_method.carbon

@@ -42,15 +42,32 @@ fn Call(p: Derived*) {
 // CHECK:STDOUT:
 // CHECK:STDOUT:
 // CHECK:STDOUT: file {
 // CHECK:STDOUT: file {
 // CHECK:STDOUT:   package: <namespace> = namespace {.Base = %Base.decl, .Derived = %Derived.decl, .Call = %Call} [template]
 // CHECK:STDOUT:   package: <namespace> = namespace {.Base = %Base.decl, .Derived = %Derived.decl, .Call = %Call} [template]
-// CHECK:STDOUT:   %Base.decl = class_decl @Base, () [template = constants.%Base]
-// CHECK:STDOUT:   %F: <function> = fn_decl @F [template]
-// CHECK:STDOUT:   %Derived.decl = class_decl @Derived, () [template = constants.%Derived]
-// CHECK:STDOUT:   %Call: <function> = fn_decl @Call [template]
+// CHECK:STDOUT:   %Base.decl = class_decl @Base {} [template = constants.%Base]
+// CHECK:STDOUT:   %F: <function> = fn_decl @F {
+// CHECK:STDOUT:     %Base.ref: type = name_ref Base, %Base.decl [template = constants.%Base]
+// CHECK:STDOUT:     %.loc13_26: type = ptr_type Base [template = constants.%.2]
+// CHECK:STDOUT:     %self.loc13_16.1: Base* = param self
+// CHECK:STDOUT:     @F.%self: Base* = bind_name self, %self.loc13_16.1
+// CHECK:STDOUT:     @F.%.loc13: Base* = addr_pattern @F.%self
+// CHECK:STDOUT:   } [template]
+// CHECK:STDOUT:   %Derived.decl = class_decl @Derived {} [template = constants.%Derived]
+// CHECK:STDOUT:   %Call: <function> = fn_decl @Call {
+// CHECK:STDOUT:     %Derived.ref: type = name_ref Derived, %Derived.decl [template = constants.%Derived]
+// CHECK:STDOUT:     %.loc21: type = ptr_type Derived [template = constants.%.8]
+// CHECK:STDOUT:     %p.loc21_9.1: Derived* = param p
+// CHECK:STDOUT:     @Call.%p: Derived* = bind_name p, %p.loc21_9.1
+// CHECK:STDOUT:   } [template]
 // CHECK:STDOUT: }
 // CHECK:STDOUT: }
 // CHECK:STDOUT:
 // CHECK:STDOUT:
 // CHECK:STDOUT: class @Base {
 // CHECK:STDOUT: class @Base {
 // CHECK:STDOUT:   %.loc8: <unbound element of class Base> = field_decl a, element0 [template]
 // CHECK:STDOUT:   %.loc8: <unbound element of class Base> = field_decl a, element0 [template]
-// CHECK:STDOUT:   %F: <function> = fn_decl @F [template]
+// CHECK:STDOUT:   %F: <function> = fn_decl @F {
+// CHECK:STDOUT:     %Self.ref: type = name_ref Self, constants.%Base [template = constants.%Base]
+// CHECK:STDOUT:     %.loc10_23: type = ptr_type Base [template = constants.%.2]
+// CHECK:STDOUT:     %self.loc10_13.1: Base* = param self
+// CHECK:STDOUT:     %self.loc10_13.3: Base* = bind_name self, %self.loc10_13.1
+// CHECK:STDOUT:     %.loc10_8: Base* = addr_pattern %self.loc10_13.3
+// CHECK:STDOUT:   } [template]
 // CHECK:STDOUT:
 // CHECK:STDOUT:
 // CHECK:STDOUT: !members:
 // CHECK:STDOUT: !members:
 // CHECK:STDOUT:   .a = %.loc8
 // CHECK:STDOUT:   .a = %.loc8

+ 46 - 11
toolchain/check/testdata/class/base_method_shadow.carbon

@@ -56,15 +56,38 @@ fn Call(a: A*, b: B*, c: C*, d: D*) {
 // CHECK:STDOUT:
 // CHECK:STDOUT:
 // CHECK:STDOUT: file {
 // CHECK:STDOUT: file {
 // CHECK:STDOUT:   package: <namespace> = namespace {.A = %A.decl, .B = %B.decl, .C = %C.decl, .D = %D.decl, .Call = %Call} [template]
 // CHECK:STDOUT:   package: <namespace> = namespace {.A = %A.decl, .B = %B.decl, .C = %C.decl, .D = %D.decl, .Call = %Call} [template]
-// CHECK:STDOUT:   %A.decl = class_decl @A, () [template = constants.%A]
-// CHECK:STDOUT:   %B.decl = class_decl @B, () [template = constants.%B]
-// CHECK:STDOUT:   %C.decl = class_decl @C, () [template = constants.%C]
-// CHECK:STDOUT:   %D.decl = class_decl @D, () [template = constants.%D]
-// CHECK:STDOUT:   %Call: <function> = fn_decl @Call [template]
+// CHECK:STDOUT:   %A.decl = class_decl @A {} [template = constants.%A]
+// CHECK:STDOUT:   %B.decl = class_decl @B {} [template = constants.%B]
+// CHECK:STDOUT:   %C.decl = class_decl @C {} [template = constants.%C]
+// CHECK:STDOUT:   %D.decl = class_decl @D {} [template = constants.%D]
+// CHECK:STDOUT:   %Call: <function> = fn_decl @Call {
+// CHECK:STDOUT:     %A.ref: type = name_ref A, %A.decl [template = constants.%A]
+// CHECK:STDOUT:     %.loc25_13: type = ptr_type A [template = constants.%.1]
+// CHECK:STDOUT:     %a.loc25_9.1: A* = param a
+// CHECK:STDOUT:     @Call.%a: A* = bind_name a, %a.loc25_9.1
+// CHECK:STDOUT:     %B.ref: type = name_ref B, %B.decl [template = constants.%B]
+// CHECK:STDOUT:     %.loc25_20: type = ptr_type B [template = constants.%.6]
+// CHECK:STDOUT:     %b.loc25_16.1: B* = param b
+// CHECK:STDOUT:     @Call.%b: B* = bind_name b, %b.loc25_16.1
+// CHECK:STDOUT:     %C.ref: type = name_ref C, %C.decl [template = constants.%C]
+// CHECK:STDOUT:     %.loc25_27: type = ptr_type C [template = constants.%.11]
+// CHECK:STDOUT:     %c.loc25_23.1: C* = param c
+// CHECK:STDOUT:     @Call.%c: C* = bind_name c, %c.loc25_23.1
+// CHECK:STDOUT:     %D.ref: type = name_ref D, %D.decl [template = constants.%D]
+// CHECK:STDOUT:     %.loc25_34: type = ptr_type D [template = constants.%.14]
+// CHECK:STDOUT:     %d.loc25_30.1: D* = param d
+// CHECK:STDOUT:     @Call.%d: D* = bind_name d, %d.loc25_30.1
+// CHECK:STDOUT:   } [template]
 // CHECK:STDOUT: }
 // CHECK:STDOUT: }
 // CHECK:STDOUT:
 // CHECK:STDOUT:
 // CHECK:STDOUT: class @A {
 // CHECK:STDOUT: class @A {
-// CHECK:STDOUT:   %F: <function> = fn_decl @F.1 [template]
+// CHECK:STDOUT:   %F: <function> = fn_decl @F.1 {
+// CHECK:STDOUT:     %Self.ref: type = name_ref Self, constants.%A [template = constants.%A]
+// CHECK:STDOUT:     %.loc8_23: type = ptr_type A [template = constants.%.1]
+// CHECK:STDOUT:     %self.loc8_13.1: A* = param self
+// CHECK:STDOUT:     %self.loc8_13.3: A* = bind_name self, %self.loc8_13.1
+// CHECK:STDOUT:     %.loc8_8: A* = addr_pattern %self.loc8_13.3
+// CHECK:STDOUT:   } [template]
 // CHECK:STDOUT:
 // CHECK:STDOUT:
 // CHECK:STDOUT: !members:
 // CHECK:STDOUT: !members:
 // CHECK:STDOUT:   .F = %F
 // CHECK:STDOUT:   .F = %F
@@ -73,7 +96,13 @@ fn Call(a: A*, b: B*, c: C*, d: D*) {
 // CHECK:STDOUT: class @B {
 // CHECK:STDOUT: class @B {
 // CHECK:STDOUT:   %A.ref: type = name_ref A, file.%A.decl [template = constants.%A]
 // CHECK:STDOUT:   %A.ref: type = name_ref A, file.%A.decl [template = constants.%A]
 // CHECK:STDOUT:   %.loc12: <unbound element of class B> = base_decl A, element0 [template]
 // CHECK:STDOUT:   %.loc12: <unbound element of class B> = base_decl A, element0 [template]
-// CHECK:STDOUT:   %F: <function> = fn_decl @F.2 [template]
+// CHECK:STDOUT:   %F: <function> = fn_decl @F.2 {
+// CHECK:STDOUT:     %Self.ref: type = name_ref Self, constants.%B [template = constants.%B]
+// CHECK:STDOUT:     %.loc13_23: type = ptr_type B [template = constants.%.6]
+// CHECK:STDOUT:     %self.loc13_13.1: B* = param self
+// CHECK:STDOUT:     %self.loc13_13.3: B* = bind_name self, %self.loc13_13.1
+// CHECK:STDOUT:     %.loc13_8: B* = addr_pattern %self.loc13_13.3
+// CHECK:STDOUT:   } [template]
 // CHECK:STDOUT:
 // CHECK:STDOUT:
 // CHECK:STDOUT: !members:
 // CHECK:STDOUT: !members:
 // CHECK:STDOUT:   .base = %.loc12
 // CHECK:STDOUT:   .base = %.loc12
@@ -84,7 +113,13 @@ fn Call(a: A*, b: B*, c: C*, d: D*) {
 // CHECK:STDOUT: class @C {
 // CHECK:STDOUT: class @C {
 // CHECK:STDOUT:   %B.ref: type = name_ref B, file.%B.decl [template = constants.%B]
 // CHECK:STDOUT:   %B.ref: type = name_ref B, file.%B.decl [template = constants.%B]
 // CHECK:STDOUT:   %.loc17: <unbound element of class C> = base_decl B, element0 [template]
 // CHECK:STDOUT:   %.loc17: <unbound element of class C> = base_decl B, element0 [template]
-// CHECK:STDOUT:   %F: <function> = fn_decl @F.3 [template]
+// CHECK:STDOUT:   %F: <function> = fn_decl @F.3 {
+// CHECK:STDOUT:     %Self.ref: type = name_ref Self, constants.%C [template = constants.%C]
+// CHECK:STDOUT:     %.loc18_23: type = ptr_type C [template = constants.%.11]
+// CHECK:STDOUT:     %self.loc18_13.1: C* = param self
+// CHECK:STDOUT:     %self.loc18_13.3: C* = bind_name self, %self.loc18_13.1
+// CHECK:STDOUT:     %.loc18_8: C* = addr_pattern %self.loc18_13.3
+// CHECK:STDOUT:   } [template]
 // CHECK:STDOUT:
 // CHECK:STDOUT:
 // CHECK:STDOUT: !members:
 // CHECK:STDOUT: !members:
 // CHECK:STDOUT:   .base = %.loc17
 // CHECK:STDOUT:   .base = %.loc17
@@ -101,11 +136,11 @@ fn Call(a: A*, b: B*, c: C*, d: D*) {
 // CHECK:STDOUT:   extend name_scope2
 // CHECK:STDOUT:   extend name_scope2
 // CHECK:STDOUT: }
 // CHECK:STDOUT: }
 // CHECK:STDOUT:
 // CHECK:STDOUT:
-// CHECK:STDOUT: fn @F.1[addr %self: A*]();
+// CHECK:STDOUT: fn @F.1[addr @A.%self.loc8_13.3: A*]();
 // CHECK:STDOUT:
 // CHECK:STDOUT:
-// CHECK:STDOUT: fn @F.2[addr %self: B*]();
+// CHECK:STDOUT: fn @F.2[addr @B.%self.loc13_13.3: B*]();
 // CHECK:STDOUT:
 // CHECK:STDOUT:
-// CHECK:STDOUT: fn @F.3[addr %self: C*]();
+// CHECK:STDOUT: fn @F.3[addr @C.%self.loc18_13.3: C*]();
 // CHECK:STDOUT:
 // CHECK:STDOUT:
 // CHECK:STDOUT: fn @Call(%a: A*, %b: B*, %c: C*, %d: D*) {
 // CHECK:STDOUT: fn @Call(%a: A*, %b: B*, %c: C*, %d: D*) {
 // CHECK:STDOUT: !entry:
 // CHECK:STDOUT: !entry:

+ 21 - 7
toolchain/check/testdata/class/basic.carbon

@@ -33,14 +33,28 @@ fn Run() -> i32 {
 // CHECK:STDOUT:
 // CHECK:STDOUT:
 // CHECK:STDOUT: file {
 // CHECK:STDOUT: file {
 // CHECK:STDOUT:   package: <namespace> = namespace {.Class = %Class.decl, .Run = %Run} [template]
 // CHECK:STDOUT:   package: <namespace> = namespace {.Class = %Class.decl, .Run = %Run} [template]
-// CHECK:STDOUT:   %Class.decl = class_decl @Class, () [template = constants.%Class]
-// CHECK:STDOUT:   %G: <function> = fn_decl @G [template]
-// CHECK:STDOUT:   %Run: <function> = fn_decl @Run [template]
+// CHECK:STDOUT:   %Class.decl = class_decl @Class {} [template = constants.%Class]
+// CHECK:STDOUT:   %G: <function> = fn_decl @G {
+// CHECK:STDOUT:     %n.loc17_12.1: i32 = param n
+// CHECK:STDOUT:     @G.%n: i32 = bind_name n, %n.loc17_12.1
+// CHECK:STDOUT:     %return.var.loc17: ref i32 = var <return slot>
+// CHECK:STDOUT:   } [template]
+// CHECK:STDOUT:   %Run: <function> = fn_decl @Run {
+// CHECK:STDOUT:     %return.var.loc21: ref i32 = var <return slot>
+// CHECK:STDOUT:   } [template]
 // CHECK:STDOUT: }
 // CHECK:STDOUT: }
 // CHECK:STDOUT:
 // CHECK:STDOUT:
 // CHECK:STDOUT: class @Class {
 // CHECK:STDOUT: class @Class {
-// CHECK:STDOUT:   %F: <function> = fn_decl @F [template]
-// CHECK:STDOUT:   %G: <function> = fn_decl @G [template]
+// CHECK:STDOUT:   %F: <function> = fn_decl @F {
+// CHECK:STDOUT:     %n.loc8_8.1: i32 = param n
+// CHECK:STDOUT:     %n.loc8_8.2: i32 = bind_name n, %n.loc8_8.1
+// CHECK:STDOUT:     %return.var.loc8: ref i32 = var <return slot>
+// CHECK:STDOUT:   } [template]
+// CHECK:STDOUT:   %G: <function> = fn_decl @G {
+// CHECK:STDOUT:     %n.loc12_8.1: i32 = param n
+// CHECK:STDOUT:     %n.loc12_8.2: i32 = bind_name n, %n.loc12_8.1
+// CHECK:STDOUT:     %return.var.loc12: ref i32 = var <return slot>
+// CHECK:STDOUT:   } [template]
 // CHECK:STDOUT:   %.loc14: <unbound element of class Class> = field_decl k, element0 [template]
 // CHECK:STDOUT:   %.loc14: <unbound element of class Class> = field_decl k, element0 [template]
 // CHECK:STDOUT:
 // CHECK:STDOUT:
 // CHECK:STDOUT: !members:
 // CHECK:STDOUT: !members:
@@ -49,9 +63,9 @@ fn Run() -> i32 {
 // CHECK:STDOUT:   .k = %.loc14
 // CHECK:STDOUT:   .k = %.loc14
 // CHECK:STDOUT: }
 // CHECK:STDOUT: }
 // CHECK:STDOUT:
 // CHECK:STDOUT:
-// CHECK:STDOUT: fn @F(%n: i32) -> i32 {
+// CHECK:STDOUT: fn @F(@Class.%n.loc8_8.2: i32) -> i32 {
 // CHECK:STDOUT: !entry:
 // CHECK:STDOUT: !entry:
-// CHECK:STDOUT:   %n.ref: i32 = name_ref n, %n
+// CHECK:STDOUT:   %n.ref: i32 = name_ref n, @Class.%n.loc8_8.2
 // CHECK:STDOUT:   return %n.ref
 // CHECK:STDOUT:   return %n.ref
 // CHECK:STDOUT: }
 // CHECK:STDOUT: }
 // CHECK:STDOUT:
 // CHECK:STDOUT:

+ 45 - 9
toolchain/check/testdata/class/derived_to_base.carbon

@@ -70,15 +70,51 @@ fn ConvertInit() {
 // CHECK:STDOUT:
 // CHECK:STDOUT:
 // CHECK:STDOUT: file {
 // CHECK:STDOUT: file {
 // CHECK:STDOUT:   package: <namespace> = namespace {.A = %A.decl, .B = %B.decl, .C = %C.decl, .ConvertCToB = %ConvertCToB, .ConvertBToA = %ConvertBToA, .ConvertCToA = %ConvertCToA, .ConvertValue = %ConvertValue, .ConvertRef = %ConvertRef, .ConvertInit = %ConvertInit} [template]
 // CHECK:STDOUT:   package: <namespace> = namespace {.A = %A.decl, .B = %B.decl, .C = %C.decl, .ConvertCToB = %ConvertCToB, .ConvertBToA = %ConvertBToA, .ConvertCToA = %ConvertCToA, .ConvertValue = %ConvertValue, .ConvertRef = %ConvertRef, .ConvertInit = %ConvertInit} [template]
-// CHECK:STDOUT:   %A.decl = class_decl @A, () [template = constants.%A]
-// CHECK:STDOUT:   %B.decl = class_decl @B, () [template = constants.%B]
-// CHECK:STDOUT:   %C.decl = class_decl @C, () [template = constants.%C]
-// CHECK:STDOUT:   %ConvertCToB: <function> = fn_decl @ConvertCToB [template]
-// CHECK:STDOUT:   %ConvertBToA: <function> = fn_decl @ConvertBToA [template]
-// CHECK:STDOUT:   %ConvertCToA: <function> = fn_decl @ConvertCToA [template]
-// CHECK:STDOUT:   %ConvertValue: <function> = fn_decl @ConvertValue [template]
-// CHECK:STDOUT:   %ConvertRef: <function> = fn_decl @ConvertRef [template]
-// CHECK:STDOUT:   %ConvertInit: <function> = fn_decl @ConvertInit [template]
+// CHECK:STDOUT:   %A.decl = class_decl @A {} [template = constants.%A]
+// CHECK:STDOUT:   %B.decl = class_decl @B {} [template = constants.%B]
+// CHECK:STDOUT:   %C.decl = class_decl @C {} [template = constants.%C]
+// CHECK:STDOUT:   %ConvertCToB: <function> = fn_decl @ConvertCToB {
+// CHECK:STDOUT:     %C.ref.loc21: type = name_ref C, %C.decl [template = constants.%C]
+// CHECK:STDOUT:     %.loc21_20: type = ptr_type C [template = constants.%.13]
+// CHECK:STDOUT:     %p.loc21_16.1: C* = param p
+// CHECK:STDOUT:     @ConvertCToB.%p: C* = bind_name p, %p.loc21_16.1
+// CHECK:STDOUT:     %B.ref.loc21: type = name_ref B, %B.decl [template = constants.%B]
+// CHECK:STDOUT:     %.loc21_27: type = ptr_type B [template = constants.%.14]
+// CHECK:STDOUT:     %return.var.loc21: ref B* = var <return slot>
+// CHECK:STDOUT:   } [template]
+// CHECK:STDOUT:   %ConvertBToA: <function> = fn_decl @ConvertBToA {
+// CHECK:STDOUT:     %B.ref.loc22: type = name_ref B, %B.decl [template = constants.%B]
+// CHECK:STDOUT:     %.loc22_20: type = ptr_type B [template = constants.%.14]
+// CHECK:STDOUT:     %p.loc22_16.1: B* = param p
+// CHECK:STDOUT:     @ConvertBToA.%p: B* = bind_name p, %p.loc22_16.1
+// CHECK:STDOUT:     %A.ref.loc22: type = name_ref A, %A.decl [template = constants.%A]
+// CHECK:STDOUT:     %.loc22_27: type = ptr_type A [template = constants.%.18]
+// CHECK:STDOUT:     %return.var.loc22: ref A* = var <return slot>
+// CHECK:STDOUT:   } [template]
+// CHECK:STDOUT:   %ConvertCToA: <function> = fn_decl @ConvertCToA {
+// CHECK:STDOUT:     %C.ref.loc23: type = name_ref C, %C.decl [template = constants.%C]
+// CHECK:STDOUT:     %.loc23_20: type = ptr_type C [template = constants.%.13]
+// CHECK:STDOUT:     %p.loc23_16.1: C* = param p
+// CHECK:STDOUT:     @ConvertCToA.%p: C* = bind_name p, %p.loc23_16.1
+// CHECK:STDOUT:     %A.ref.loc23: type = name_ref A, %A.decl [template = constants.%A]
+// CHECK:STDOUT:     %.loc23_27: type = ptr_type A [template = constants.%.18]
+// CHECK:STDOUT:     %return.var.loc23: ref A* = var <return slot>
+// CHECK:STDOUT:   } [template]
+// CHECK:STDOUT:   %ConvertValue: <function> = fn_decl @ConvertValue {
+// CHECK:STDOUT:     %C.ref.loc25: type = name_ref C, %C.decl [template = constants.%C]
+// CHECK:STDOUT:     %c.loc25_17.1: C = param c
+// CHECK:STDOUT:     @ConvertValue.%c: C = bind_name c, %c.loc25_17.1
+// CHECK:STDOUT:   } [template]
+// CHECK:STDOUT:   %ConvertRef: <function> = fn_decl @ConvertRef {
+// CHECK:STDOUT:     %C.ref.loc29: type = name_ref C, %C.decl [template = constants.%C]
+// CHECK:STDOUT:     %.loc29_19: type = ptr_type C [template = constants.%.13]
+// CHECK:STDOUT:     %c.loc29_15.1: C* = param c
+// CHECK:STDOUT:     @ConvertRef.%c: C* = bind_name c, %c.loc29_15.1
+// CHECK:STDOUT:     %A.ref.loc29: type = name_ref A, %A.decl [template = constants.%A]
+// CHECK:STDOUT:     %.loc29_26: type = ptr_type A [template = constants.%.18]
+// CHECK:STDOUT:     %return.var.loc29: ref A* = var <return slot>
+// CHECK:STDOUT:   } [template]
+// CHECK:STDOUT:   %ConvertInit: <function> = fn_decl @ConvertInit {} [template]
 // CHECK:STDOUT: }
 // CHECK:STDOUT: }
 // CHECK:STDOUT:
 // CHECK:STDOUT:
 // CHECK:STDOUT: class @A {
 // CHECK:STDOUT: class @A {

+ 14 - 4
toolchain/check/testdata/class/fail_abstract.carbon

@@ -50,10 +50,20 @@ fn Access(d: Derived) -> (i32, i32) {
 // CHECK:STDOUT:
 // CHECK:STDOUT:
 // CHECK:STDOUT: file {
 // CHECK:STDOUT: file {
 // CHECK:STDOUT:   package: <namespace> = namespace {.Abstract = %Abstract.decl, .Derived = %Derived.decl, .Make = %Make, .Access = %Access} [template]
 // CHECK:STDOUT:   package: <namespace> = namespace {.Abstract = %Abstract.decl, .Derived = %Derived.decl, .Make = %Make, .Access = %Access} [template]
-// CHECK:STDOUT:   %Abstract.decl = class_decl @Abstract, () [template = constants.%Abstract]
-// CHECK:STDOUT:   %Derived.decl = class_decl @Derived, () [template = constants.%Derived]
-// CHECK:STDOUT:   %Make: <function> = fn_decl @Make [template]
-// CHECK:STDOUT:   %Access: <function> = fn_decl @Access [template]
+// CHECK:STDOUT:   %Abstract.decl = class_decl @Abstract {} [template = constants.%Abstract]
+// CHECK:STDOUT:   %Derived.decl = class_decl @Derived {} [template = constants.%Derived]
+// CHECK:STDOUT:   %Make: <function> = fn_decl @Make {
+// CHECK:STDOUT:     %Derived.ref.loc17: type = name_ref Derived, %Derived.decl [template = constants.%Derived]
+// CHECK:STDOUT:     @Make.%return: ref Derived = var <return slot>
+// CHECK:STDOUT:   } [template]
+// CHECK:STDOUT:   %Access: <function> = fn_decl @Access {
+// CHECK:STDOUT:     %Derived.ref.loc25: type = name_ref Derived, %Derived.decl [template = constants.%Derived]
+// CHECK:STDOUT:     %d.loc25_11.1: Derived = param d
+// CHECK:STDOUT:     @Access.%d: Derived = bind_name d, %d.loc25_11.1
+// CHECK:STDOUT:     %.loc25_35.1: (type, type) = tuple_literal (i32, i32)
+// CHECK:STDOUT:     %.loc25_35.2: type = converted %.loc25_35.1, constants.%.14 [template = constants.%.14]
+// CHECK:STDOUT:     @Access.%return: ref (i32, i32) = var <return slot>
+// CHECK:STDOUT:   } [template]
 // CHECK:STDOUT: }
 // CHECK:STDOUT: }
 // CHECK:STDOUT:
 // CHECK:STDOUT:
 // CHECK:STDOUT: class @Abstract {
 // CHECK:STDOUT: class @Abstract {

+ 15 - 5
toolchain/check/testdata/class/fail_addr_not_self.carbon

@@ -26,19 +26,29 @@ class Class {
 // CHECK:STDOUT:
 // CHECK:STDOUT:
 // CHECK:STDOUT: file {
 // CHECK:STDOUT: file {
 // CHECK:STDOUT:   package: <namespace> = namespace {.Class = %Class.decl} [template]
 // CHECK:STDOUT:   package: <namespace> = namespace {.Class = %Class.decl} [template]
-// CHECK:STDOUT:   %Class.decl = class_decl @Class, () [template = constants.%Class]
+// CHECK:STDOUT:   %Class.decl = class_decl @Class {} [template = constants.%Class]
 // CHECK:STDOUT: }
 // CHECK:STDOUT: }
 // CHECK:STDOUT:
 // CHECK:STDOUT:
 // CHECK:STDOUT: class @Class {
 // CHECK:STDOUT: class @Class {
-// CHECK:STDOUT:   %F: <function> = fn_decl @F [template]
-// CHECK:STDOUT:   %G: <function> = fn_decl @G [template]
+// CHECK:STDOUT:   %F: <function> = fn_decl @F {
+// CHECK:STDOUT:     %Class.ref.loc11: type = name_ref Class, file.%Class.decl [template = constants.%Class]
+// CHECK:STDOUT:     %.loc11: type = ptr_type Class [template = constants.%.1]
+// CHECK:STDOUT:     %a.loc11_13.1: Class* = param a
+// CHECK:STDOUT:     %a.loc11_13.2: Class* = bind_name a, %a.loc11_13.1
+// CHECK:STDOUT:   } [template]
+// CHECK:STDOUT:   %G: <function> = fn_decl @G {
+// CHECK:STDOUT:     %Class.ref.loc16: type = name_ref Class, file.%Class.decl [template = constants.%Class]
+// CHECK:STDOUT:     %.loc16: type = ptr_type Class [template = constants.%.1]
+// CHECK:STDOUT:     %b.loc16_13.1: Class* = param b
+// CHECK:STDOUT:     %b.loc16_13.2: Class* = bind_name b, %b.loc16_13.1
+// CHECK:STDOUT:   } [template]
 // CHECK:STDOUT:
 // CHECK:STDOUT:
 // CHECK:STDOUT: !members:
 // CHECK:STDOUT: !members:
 // CHECK:STDOUT:   .F = %F
 // CHECK:STDOUT:   .F = %F
 // CHECK:STDOUT:   .G = %G
 // CHECK:STDOUT:   .G = %G
 // CHECK:STDOUT: }
 // CHECK:STDOUT: }
 // CHECK:STDOUT:
 // CHECK:STDOUT:
-// CHECK:STDOUT: fn @F[%a: Class*]();
+// CHECK:STDOUT: fn @F[@Class.%a.loc11_13.2: Class*]();
 // CHECK:STDOUT:
 // CHECK:STDOUT:
-// CHECK:STDOUT: fn @G(%b: Class*);
+// CHECK:STDOUT: fn @G(@Class.%b.loc16_13.2: Class*);
 // CHECK:STDOUT:
 // CHECK:STDOUT:

+ 25 - 6
toolchain/check/testdata/class/fail_addr_self.carbon

@@ -50,22 +50,41 @@ fn F(c: Class, p: Class*) {
 // CHECK:STDOUT:
 // CHECK:STDOUT:
 // CHECK:STDOUT: file {
 // CHECK:STDOUT: file {
 // CHECK:STDOUT:   package: <namespace> = namespace {.Class = %Class.decl, .F = %F} [template]
 // CHECK:STDOUT:   package: <namespace> = namespace {.Class = %Class.decl, .F = %F} [template]
-// CHECK:STDOUT:   %Class.decl = class_decl @Class, () [template = constants.%Class]
-// CHECK:STDOUT:   %F: <function> = fn_decl @F.2 [template]
+// CHECK:STDOUT:   %Class.decl = class_decl @Class {} [template = constants.%Class]
+// CHECK:STDOUT:   %F: <function> = fn_decl @F.2 {
+// CHECK:STDOUT:     %Class.ref.loc12_9: type = name_ref Class, %Class.decl [template = constants.%Class]
+// CHECK:STDOUT:     %c.loc12_6.1: Class = param c
+// CHECK:STDOUT:     @F.2.%c: Class = bind_name c, %c.loc12_6.1
+// CHECK:STDOUT:     %Class.ref.loc12_19: type = name_ref Class, %Class.decl [template = constants.%Class]
+// CHECK:STDOUT:     %.loc12: type = ptr_type Class [template = constants.%.1]
+// CHECK:STDOUT:     %p.loc12_16.1: Class* = param p
+// CHECK:STDOUT:     @F.2.%p: Class* = bind_name p, %p.loc12_16.1
+// CHECK:STDOUT:   } [template]
 // CHECK:STDOUT: }
 // CHECK:STDOUT: }
 // CHECK:STDOUT:
 // CHECK:STDOUT:
 // CHECK:STDOUT: class @Class {
 // CHECK:STDOUT: class @Class {
-// CHECK:STDOUT:   %F: <function> = fn_decl @F.1 [template]
-// CHECK:STDOUT:   %G: <function> = fn_decl @G [template]
+// CHECK:STDOUT:   %F: <function> = fn_decl @F.1 {
+// CHECK:STDOUT:     %Class.ref.loc8: type = name_ref Class, file.%Class.decl [template = constants.%Class]
+// CHECK:STDOUT:     %.loc8_24: type = ptr_type Class [template = constants.%.1]
+// CHECK:STDOUT:     %self.loc8_13.1: Class* = param self
+// CHECK:STDOUT:     %self.loc8_13.3: Class* = bind_name self, %self.loc8_13.1
+// CHECK:STDOUT:     %.loc8_8: Class* = addr_pattern %self.loc8_13.3
+// CHECK:STDOUT:   } [template]
+// CHECK:STDOUT:   %G: <function> = fn_decl @G {
+// CHECK:STDOUT:     %Class.ref.loc9: type = name_ref Class, file.%Class.decl [template = constants.%Class]
+// CHECK:STDOUT:     %self.loc9_13.1: Class = param self
+// CHECK:STDOUT:     %self.loc9_13.3: Class = bind_name self, %self.loc9_13.1
+// CHECK:STDOUT:     %.loc9: Class = addr_pattern %self.loc9_13.3
+// CHECK:STDOUT:   } [template]
 // CHECK:STDOUT:
 // CHECK:STDOUT:
 // CHECK:STDOUT: !members:
 // CHECK:STDOUT: !members:
 // CHECK:STDOUT:   .F = %F
 // CHECK:STDOUT:   .F = %F
 // CHECK:STDOUT:   .G = %G
 // CHECK:STDOUT:   .G = %G
 // CHECK:STDOUT: }
 // CHECK:STDOUT: }
 // CHECK:STDOUT:
 // CHECK:STDOUT:
-// CHECK:STDOUT: fn @F.1[addr %self: Class*]();
+// CHECK:STDOUT: fn @F.1[addr @Class.%self.loc8_13.3: Class*]();
 // CHECK:STDOUT:
 // CHECK:STDOUT:
-// CHECK:STDOUT: fn @G[addr %self: Class]();
+// CHECK:STDOUT: fn @G[addr @Class.%self.loc9_13.3: Class]();
 // CHECK:STDOUT:
 // CHECK:STDOUT:
 // CHECK:STDOUT: fn @F.2(%c: Class, %p: Class*) {
 // CHECK:STDOUT: fn @F.2(%c: Class, %p: Class*) {
 // CHECK:STDOUT: !entry:
 // CHECK:STDOUT: !entry:

+ 112 - 23
toolchain/check/testdata/class/fail_base_bad_type.carbon

@@ -161,29 +161,118 @@ fn AccessMemberWithInvalidBaseFinal_NoMember(p: DeriveFromFinal*) -> i32 {
 // CHECK:STDOUT:
 // CHECK:STDOUT:
 // CHECK:STDOUT: file {
 // CHECK:STDOUT: file {
 // CHECK:STDOUT:   package: <namespace> = namespace {.Base = %Base.decl, .Final = %Final.decl, .DeriveFromError = %DeriveFromError.decl, .AccessMemberWithInvalidBaseError = %AccessMemberWithInvalidBaseError, .DeriveFromNonType = %DeriveFromNonType.decl, .AccessMemberWithInvalidBasNonType = %AccessMemberWithInvalidBasNonType, .DeriveFromi32 = %DeriveFromi32.decl, .ConvertToBadBasei32 = %ConvertToBadBasei32, .AccessMemberWithInvalidBasei32 = %AccessMemberWithInvalidBasei32, .DeriveFromTuple = %DeriveFromTuple.decl, .ConvertToBadBaseTuple = %ConvertToBadBaseTuple, .AccessMemberWithInvalidBaseTuple = %AccessMemberWithInvalidBaseTuple, .DeriveFromStruct = %DeriveFromStruct.decl, .ConvertToBadBaseStruct = %ConvertToBadBaseStruct, .AccessMemberWithInvalidBaseStruct = %AccessMemberWithInvalidBaseStruct, .Incomplete = %Incomplete.decl, .DeriveFromIncomplete = %DeriveFromIncomplete.decl, .ConvertToBadBaseIncomplete = %ConvertToBadBaseIncomplete, .AccessMemberWithInvalidBaseIncomplete = %AccessMemberWithInvalidBaseIncomplete, .DeriveFromFinal = %DeriveFromFinal.decl, .ConvertToBadBaseFinal = %ConvertToBadBaseFinal, .AccessMemberWithInvalidBaseFinal_WithMember = %AccessMemberWithInvalidBaseFinal_WithMember, .AccessMemberWithInvalidBaseFinal_NoMember = %AccessMemberWithInvalidBaseFinal_NoMember} [template]
 // CHECK:STDOUT:   package: <namespace> = namespace {.Base = %Base.decl, .Final = %Final.decl, .DeriveFromError = %DeriveFromError.decl, .AccessMemberWithInvalidBaseError = %AccessMemberWithInvalidBaseError, .DeriveFromNonType = %DeriveFromNonType.decl, .AccessMemberWithInvalidBasNonType = %AccessMemberWithInvalidBasNonType, .DeriveFromi32 = %DeriveFromi32.decl, .ConvertToBadBasei32 = %ConvertToBadBasei32, .AccessMemberWithInvalidBasei32 = %AccessMemberWithInvalidBasei32, .DeriveFromTuple = %DeriveFromTuple.decl, .ConvertToBadBaseTuple = %ConvertToBadBaseTuple, .AccessMemberWithInvalidBaseTuple = %AccessMemberWithInvalidBaseTuple, .DeriveFromStruct = %DeriveFromStruct.decl, .ConvertToBadBaseStruct = %ConvertToBadBaseStruct, .AccessMemberWithInvalidBaseStruct = %AccessMemberWithInvalidBaseStruct, .Incomplete = %Incomplete.decl, .DeriveFromIncomplete = %DeriveFromIncomplete.decl, .ConvertToBadBaseIncomplete = %ConvertToBadBaseIncomplete, .AccessMemberWithInvalidBaseIncomplete = %AccessMemberWithInvalidBaseIncomplete, .DeriveFromFinal = %DeriveFromFinal.decl, .ConvertToBadBaseFinal = %ConvertToBadBaseFinal, .AccessMemberWithInvalidBaseFinal_WithMember = %AccessMemberWithInvalidBaseFinal_WithMember, .AccessMemberWithInvalidBaseFinal_NoMember = %AccessMemberWithInvalidBaseFinal_NoMember} [template]
-// CHECK:STDOUT:   %Base.decl = class_decl @Base, () [template = constants.%Base]
-// CHECK:STDOUT:   %Final.decl = class_decl @Final, () [template = constants.%Final]
-// CHECK:STDOUT:   %DeriveFromError.decl = class_decl @DeriveFromError, () [template = constants.%DeriveFromError]
-// CHECK:STDOUT:   %AccessMemberWithInvalidBaseError: <function> = fn_decl @AccessMemberWithInvalidBaseError [template]
-// CHECK:STDOUT:   %DeriveFromNonType.decl = class_decl @DeriveFromNonType, () [template = constants.%DeriveFromNonType]
-// CHECK:STDOUT:   %AccessMemberWithInvalidBasNonType: <function> = fn_decl @AccessMemberWithInvalidBasNonType [template]
-// CHECK:STDOUT:   %DeriveFromi32.decl = class_decl @DeriveFromi32, () [template = constants.%DeriveFromi32]
-// CHECK:STDOUT:   %ConvertToBadBasei32: <function> = fn_decl @ConvertToBadBasei32 [template]
-// CHECK:STDOUT:   %AccessMemberWithInvalidBasei32: <function> = fn_decl @AccessMemberWithInvalidBasei32 [template]
-// CHECK:STDOUT:   %DeriveFromTuple.decl = class_decl @DeriveFromTuple, () [template = constants.%DeriveFromTuple]
-// CHECK:STDOUT:   %ConvertToBadBaseTuple: <function> = fn_decl @ConvertToBadBaseTuple [template]
-// CHECK:STDOUT:   %AccessMemberWithInvalidBaseTuple: <function> = fn_decl @AccessMemberWithInvalidBaseTuple [template]
-// CHECK:STDOUT:   %DeriveFromStruct.decl = class_decl @DeriveFromStruct, () [template = constants.%DeriveFromStruct]
-// CHECK:STDOUT:   %ConvertToBadBaseStruct: <function> = fn_decl @ConvertToBadBaseStruct [template]
-// CHECK:STDOUT:   %AccessMemberWithInvalidBaseStruct: <function> = fn_decl @AccessMemberWithInvalidBaseStruct [template]
-// CHECK:STDOUT:   %Incomplete.decl = class_decl @Incomplete, () [template = constants.%Incomplete]
-// CHECK:STDOUT:   %DeriveFromIncomplete.decl = class_decl @DeriveFromIncomplete, () [template = constants.%DeriveFromIncomplete]
-// CHECK:STDOUT:   %ConvertToBadBaseIncomplete: <function> = fn_decl @ConvertToBadBaseIncomplete [template]
-// CHECK:STDOUT:   %AccessMemberWithInvalidBaseIncomplete: <function> = fn_decl @AccessMemberWithInvalidBaseIncomplete [template]
-// CHECK:STDOUT:   %DeriveFromFinal.decl = class_decl @DeriveFromFinal, () [template = constants.%DeriveFromFinal]
-// CHECK:STDOUT:   %ConvertToBadBaseFinal: <function> = fn_decl @ConvertToBadBaseFinal [template]
-// CHECK:STDOUT:   %AccessMemberWithInvalidBaseFinal_WithMember: <function> = fn_decl @AccessMemberWithInvalidBaseFinal_WithMember [template]
-// CHECK:STDOUT:   %AccessMemberWithInvalidBaseFinal_NoMember: <function> = fn_decl @AccessMemberWithInvalidBaseFinal_NoMember [template]
+// CHECK:STDOUT:   %Base.decl = class_decl @Base {} [template = constants.%Base]
+// CHECK:STDOUT:   %Final.decl = class_decl @Final {} [template = constants.%Final]
+// CHECK:STDOUT:   %DeriveFromError.decl = class_decl @DeriveFromError {} [template = constants.%DeriveFromError]
+// CHECK:STDOUT:   %AccessMemberWithInvalidBaseError: <function> = fn_decl @AccessMemberWithInvalidBaseError {
+// CHECK:STDOUT:     %DeriveFromError.ref: type = name_ref DeriveFromError, %DeriveFromError.decl [template = constants.%DeriveFromError]
+// CHECK:STDOUT:     %.loc20: type = ptr_type DeriveFromError [template = constants.%.4]
+// CHECK:STDOUT:     %p.loc20_37.1: DeriveFromError* = param p
+// CHECK:STDOUT:     @AccessMemberWithInvalidBaseError.%p: DeriveFromError* = bind_name p, %p.loc20_37.1
+// CHECK:STDOUT:     %return.var.loc20: ref i32 = var <return slot>
+// CHECK:STDOUT:   } [template]
+// CHECK:STDOUT:   %DeriveFromNonType.decl = class_decl @DeriveFromNonType {} [template = constants.%DeriveFromNonType]
+// CHECK:STDOUT:   %AccessMemberWithInvalidBasNonType: <function> = fn_decl @AccessMemberWithInvalidBasNonType {
+// CHECK:STDOUT:     %DeriveFromNonType.ref: type = name_ref DeriveFromNonType, %DeriveFromNonType.decl [template = constants.%DeriveFromNonType]
+// CHECK:STDOUT:     %.loc29: type = ptr_type DeriveFromNonType [template = constants.%.6]
+// CHECK:STDOUT:     %p.loc29_38.1: DeriveFromNonType* = param p
+// CHECK:STDOUT:     @AccessMemberWithInvalidBasNonType.%p: DeriveFromNonType* = bind_name p, %p.loc29_38.1
+// CHECK:STDOUT:     %return.var.loc29: ref i32 = var <return slot>
+// CHECK:STDOUT:   } [template]
+// CHECK:STDOUT:   %DeriveFromi32.decl = class_decl @DeriveFromi32 {} [template = constants.%DeriveFromi32]
+// CHECK:STDOUT:   %ConvertToBadBasei32: <function> = fn_decl @ConvertToBadBasei32 {
+// CHECK:STDOUT:     %DeriveFromi32.ref.loc43: type = name_ref DeriveFromi32, %DeriveFromi32.decl [template = constants.%DeriveFromi32]
+// CHECK:STDOUT:     %.loc43_40: type = ptr_type DeriveFromi32 [template = constants.%.7]
+// CHECK:STDOUT:     %p.loc43_24.1: DeriveFromi32* = param p
+// CHECK:STDOUT:     @ConvertToBadBasei32.%p: DeriveFromi32* = bind_name p, %p.loc43_24.1
+// CHECK:STDOUT:     %.loc43_49: type = ptr_type i32 [template = constants.%.8]
+// CHECK:STDOUT:     %return.var.loc43: ref i32* = var <return slot>
+// CHECK:STDOUT:   } [template]
+// CHECK:STDOUT:   %AccessMemberWithInvalidBasei32: <function> = fn_decl @AccessMemberWithInvalidBasei32 {
+// CHECK:STDOUT:     %DeriveFromi32.ref.loc45: type = name_ref DeriveFromi32, %DeriveFromi32.decl [template = constants.%DeriveFromi32]
+// CHECK:STDOUT:     %.loc45: type = ptr_type DeriveFromi32 [template = constants.%.7]
+// CHECK:STDOUT:     %p.loc45_35.1: DeriveFromi32* = param p
+// CHECK:STDOUT:     @AccessMemberWithInvalidBasei32.%p: DeriveFromi32* = bind_name p, %p.loc45_35.1
+// CHECK:STDOUT:     %return.var.loc45: ref i32 = var <return slot>
+// CHECK:STDOUT:   } [template]
+// CHECK:STDOUT:   %DeriveFromTuple.decl = class_decl @DeriveFromTuple {} [template = constants.%DeriveFromTuple]
+// CHECK:STDOUT:   %ConvertToBadBaseTuple: <function> = fn_decl @ConvertToBadBaseTuple {
+// CHECK:STDOUT:     %DeriveFromTuple.ref.loc57: type = name_ref DeriveFromTuple, %DeriveFromTuple.decl [template = constants.%DeriveFromTuple]
+// CHECK:STDOUT:     %.loc57_44: type = ptr_type DeriveFromTuple [template = constants.%.14]
+// CHECK:STDOUT:     %p.loc57_26.1: DeriveFromTuple* = param p
+// CHECK:STDOUT:     @ConvertToBadBaseTuple.%p: DeriveFromTuple* = bind_name p, %p.loc57_26.1
+// CHECK:STDOUT:     %Base.ref: type = name_ref Base, %Base.decl [template = constants.%Base]
+// CHECK:STDOUT:     %.loc57_56.1: (type,) = tuple_literal (%Base.ref)
+// CHECK:STDOUT:     %.loc57_56.2: type = converted %.loc57_56.1, constants.%.10 [template = constants.%.10]
+// CHECK:STDOUT:     %.loc57_57: type = ptr_type (Base,) [template = constants.%.15]
+// CHECK:STDOUT:     %return.var.loc57: ref (Base,)* = var <return slot>
+// CHECK:STDOUT:   } [template]
+// CHECK:STDOUT:   %AccessMemberWithInvalidBaseTuple: <function> = fn_decl @AccessMemberWithInvalidBaseTuple {
+// CHECK:STDOUT:     %DeriveFromTuple.ref.loc59: type = name_ref DeriveFromTuple, %DeriveFromTuple.decl [template = constants.%DeriveFromTuple]
+// CHECK:STDOUT:     %.loc59: type = ptr_type DeriveFromTuple [template = constants.%.14]
+// CHECK:STDOUT:     %p.loc59_37.1: DeriveFromTuple* = param p
+// CHECK:STDOUT:     @AccessMemberWithInvalidBaseTuple.%p: DeriveFromTuple* = bind_name p, %p.loc59_37.1
+// CHECK:STDOUT:     %return.var.loc59: ref i32 = var <return slot>
+// CHECK:STDOUT:   } [template]
+// CHECK:STDOUT:   %DeriveFromStruct.decl = class_decl @DeriveFromStruct {} [template = constants.%DeriveFromStruct]
+// CHECK:STDOUT:   %ConvertToBadBaseStruct: <function> = fn_decl @ConvertToBadBaseStruct {
+// CHECK:STDOUT:     %DeriveFromStruct.ref.loc73: type = name_ref DeriveFromStruct, %DeriveFromStruct.decl [template = constants.%DeriveFromStruct]
+// CHECK:STDOUT:     %.loc73_46: type = ptr_type DeriveFromStruct [template = constants.%.18]
+// CHECK:STDOUT:     %p.loc73_27.1: DeriveFromStruct* = param p
+// CHECK:STDOUT:     @ConvertToBadBaseStruct.%p: DeriveFromStruct* = bind_name p, %p.loc73_27.1
+// CHECK:STDOUT:     %.loc73_69: type = struct_type {.a: i32, .b: i32} [template = constants.%.16]
+// CHECK:STDOUT:     %.loc73_70: type = ptr_type {.a: i32, .b: i32} [template = constants.%.17]
+// CHECK:STDOUT:     %return.var.loc73: ref {.a: i32, .b: i32}* = var <return slot>
+// CHECK:STDOUT:   } [template]
+// CHECK:STDOUT:   %AccessMemberWithInvalidBaseStruct: <function> = fn_decl @AccessMemberWithInvalidBaseStruct {
+// CHECK:STDOUT:     %DeriveFromStruct.ref.loc76: type = name_ref DeriveFromStruct, %DeriveFromStruct.decl [template = constants.%DeriveFromStruct]
+// CHECK:STDOUT:     %.loc76: type = ptr_type DeriveFromStruct [template = constants.%.18]
+// CHECK:STDOUT:     %p.loc76_38.1: DeriveFromStruct* = param p
+// CHECK:STDOUT:     @AccessMemberWithInvalidBaseStruct.%p: DeriveFromStruct* = bind_name p, %p.loc76_38.1
+// CHECK:STDOUT:     %return.var.loc76: ref i32 = var <return slot>
+// CHECK:STDOUT:   } [template]
+// CHECK:STDOUT:   %Incomplete.decl = class_decl @Incomplete {} [template = constants.%Incomplete]
+// CHECK:STDOUT:   %DeriveFromIncomplete.decl = class_decl @DeriveFromIncomplete {} [template = constants.%DeriveFromIncomplete]
+// CHECK:STDOUT:   %ConvertToBadBaseIncomplete: <function> = fn_decl @ConvertToBadBaseIncomplete {
+// CHECK:STDOUT:     %DeriveFromIncomplete.ref.loc93: type = name_ref DeriveFromIncomplete, %DeriveFromIncomplete.decl [template = constants.%DeriveFromIncomplete]
+// CHECK:STDOUT:     %.loc93_54: type = ptr_type DeriveFromIncomplete [template = constants.%.19]
+// CHECK:STDOUT:     %p.loc93_31.1: DeriveFromIncomplete* = param p
+// CHECK:STDOUT:     @ConvertToBadBaseIncomplete.%p: DeriveFromIncomplete* = bind_name p, %p.loc93_31.1
+// CHECK:STDOUT:     %Incomplete.ref: type = name_ref Incomplete, %Incomplete.decl [template = constants.%Incomplete]
+// CHECK:STDOUT:     %.loc93_70: type = ptr_type Incomplete [template = constants.%.20]
+// CHECK:STDOUT:     %return.var.loc93: ref Incomplete* = var <return slot>
+// CHECK:STDOUT:   } [template]
+// CHECK:STDOUT:   %AccessMemberWithInvalidBaseIncomplete: <function> = fn_decl @AccessMemberWithInvalidBaseIncomplete {
+// CHECK:STDOUT:     %DeriveFromIncomplete.ref.loc95: type = name_ref DeriveFromIncomplete, %DeriveFromIncomplete.decl [template = constants.%DeriveFromIncomplete]
+// CHECK:STDOUT:     %.loc95: type = ptr_type DeriveFromIncomplete [template = constants.%.19]
+// CHECK:STDOUT:     %p.loc95_42.1: DeriveFromIncomplete* = param p
+// CHECK:STDOUT:     @AccessMemberWithInvalidBaseIncomplete.%p: DeriveFromIncomplete* = bind_name p, %p.loc95_42.1
+// CHECK:STDOUT:     %return.var.loc95: ref i32 = var <return slot>
+// CHECK:STDOUT:   } [template]
+// CHECK:STDOUT:   %DeriveFromFinal.decl = class_decl @DeriveFromFinal {} [template = constants.%DeriveFromFinal]
+// CHECK:STDOUT:   %ConvertToBadBaseFinal: <function> = fn_decl @ConvertToBadBaseFinal {
+// CHECK:STDOUT:     %DeriveFromFinal.ref.loc105: type = name_ref DeriveFromFinal, %DeriveFromFinal.decl [template = constants.%DeriveFromFinal]
+// CHECK:STDOUT:     %.loc105_44: type = ptr_type DeriveFromFinal [template = constants.%.24]
+// CHECK:STDOUT:     %p.loc105_26.1: DeriveFromFinal* = param p
+// CHECK:STDOUT:     @ConvertToBadBaseFinal.%p: DeriveFromFinal* = bind_name p, %p.loc105_26.1
+// CHECK:STDOUT:     %Final.ref: type = name_ref Final, %Final.decl [template = constants.%Final]
+// CHECK:STDOUT:     %.loc105_55: type = ptr_type Final [template = constants.%.25]
+// CHECK:STDOUT:     %return.var.loc105: ref Final* = var <return slot>
+// CHECK:STDOUT:   } [template]
+// CHECK:STDOUT:   %AccessMemberWithInvalidBaseFinal_WithMember: <function> = fn_decl @AccessMemberWithInvalidBaseFinal_WithMember {
+// CHECK:STDOUT:     %DeriveFromFinal.ref.loc109: type = name_ref DeriveFromFinal, %DeriveFromFinal.decl [template = constants.%DeriveFromFinal]
+// CHECK:STDOUT:     %.loc109: type = ptr_type DeriveFromFinal [template = constants.%.24]
+// CHECK:STDOUT:     %p.loc109_48.1: DeriveFromFinal* = param p
+// CHECK:STDOUT:     @AccessMemberWithInvalidBaseFinal_WithMember.%p: DeriveFromFinal* = bind_name p, %p.loc109_48.1
+// CHECK:STDOUT:     %return.var.loc109: ref i32 = var <return slot>
+// CHECK:STDOUT:   } [template]
+// CHECK:STDOUT:   %AccessMemberWithInvalidBaseFinal_NoMember: <function> = fn_decl @AccessMemberWithInvalidBaseFinal_NoMember {
+// CHECK:STDOUT:     %DeriveFromFinal.ref.loc113: type = name_ref DeriveFromFinal, %DeriveFromFinal.decl [template = constants.%DeriveFromFinal]
+// CHECK:STDOUT:     %.loc113: type = ptr_type DeriveFromFinal [template = constants.%.24]
+// CHECK:STDOUT:     %p.loc113_46.1: DeriveFromFinal* = param p
+// CHECK:STDOUT:     @AccessMemberWithInvalidBaseFinal_NoMember.%p: DeriveFromFinal* = bind_name p, %p.loc113_46.1
+// CHECK:STDOUT:     %return.var.loc113: ref i32 = var <return slot>
+// CHECK:STDOUT:   } [template]
 // CHECK:STDOUT: }
 // CHECK:STDOUT: }
 // CHECK:STDOUT:
 // CHECK:STDOUT:
 // CHECK:STDOUT: class @Base {
 // CHECK:STDOUT: class @Base {

+ 7 - 7
toolchain/check/testdata/class/fail_base_method_define.carbon

@@ -41,15 +41,15 @@ fn D.C.F() {}
 // CHECK:STDOUT:
 // CHECK:STDOUT:
 // CHECK:STDOUT: file {
 // CHECK:STDOUT: file {
 // CHECK:STDOUT:   package: <namespace> = namespace {.B = %B.decl, .D = %D.decl} [template]
 // CHECK:STDOUT:   package: <namespace> = namespace {.B = %B.decl, .D = %D.decl} [template]
-// CHECK:STDOUT:   %B.decl = class_decl @B, () [template = constants.%B]
-// CHECK:STDOUT:   %D.decl = class_decl @D, () [template = constants.%D]
-// CHECK:STDOUT:   %F: <function> = fn_decl @F.3 [template]
-// CHECK:STDOUT:   %.loc27: <function> = fn_decl @.1 [template]
+// CHECK:STDOUT:   %B.decl = class_decl @B {} [template = constants.%B]
+// CHECK:STDOUT:   %D.decl = class_decl @D {} [template = constants.%D]
+// CHECK:STDOUT:   %F: <function> = fn_decl @F.3 {} [template]
+// CHECK:STDOUT:   %.loc27: <function> = fn_decl @.1 {} [template]
 // CHECK:STDOUT: }
 // CHECK:STDOUT: }
 // CHECK:STDOUT:
 // CHECK:STDOUT:
 // CHECK:STDOUT: class @B {
 // CHECK:STDOUT: class @B {
-// CHECK:STDOUT:   %F: <function> = fn_decl @F.1 [template]
-// CHECK:STDOUT:   %C.decl = class_decl @C, () [template = constants.%C]
+// CHECK:STDOUT:   %F: <function> = fn_decl @F.1 {} [template]
+// CHECK:STDOUT:   %C.decl = class_decl @C {} [template = constants.%C]
 // CHECK:STDOUT:
 // CHECK:STDOUT:
 // CHECK:STDOUT: !members:
 // CHECK:STDOUT: !members:
 // CHECK:STDOUT:   .F = %F
 // CHECK:STDOUT:   .F = %F
@@ -57,7 +57,7 @@ fn D.C.F() {}
 // CHECK:STDOUT: }
 // CHECK:STDOUT: }
 // CHECK:STDOUT:
 // CHECK:STDOUT:
 // CHECK:STDOUT: class @C {
 // CHECK:STDOUT: class @C {
-// CHECK:STDOUT:   %F: <function> = fn_decl @F.2 [template]
+// CHECK:STDOUT:   %F: <function> = fn_decl @F.2 {} [template]
 // CHECK:STDOUT:
 // CHECK:STDOUT:
 // CHECK:STDOUT: !members:
 // CHECK:STDOUT: !members:
 // CHECK:STDOUT:   .F = %F
 // CHECK:STDOUT:   .F = %F

+ 5 - 5
toolchain/check/testdata/class/fail_base_modifiers.carbon

@@ -63,11 +63,11 @@ class C4 {
 // CHECK:STDOUT:
 // CHECK:STDOUT:
 // CHECK:STDOUT: file {
 // CHECK:STDOUT: file {
 // CHECK:STDOUT:   package: <namespace> = namespace {.B = %B.decl, .C1 = %C1.decl, .C2 = %C2.decl, .C3 = %C3.decl, .C4 = %C4.decl} [template]
 // CHECK:STDOUT:   package: <namespace> = namespace {.B = %B.decl, .C1 = %C1.decl, .C2 = %C2.decl, .C3 = %C3.decl, .C4 = %C4.decl} [template]
-// CHECK:STDOUT:   %B.decl = class_decl @B, () [template = constants.%B]
-// CHECK:STDOUT:   %C1.decl = class_decl @C1, () [template = constants.%C1]
-// CHECK:STDOUT:   %C2.decl = class_decl @C2, () [template = constants.%C2]
-// CHECK:STDOUT:   %C3.decl = class_decl @C3, () [template = constants.%C3]
-// CHECK:STDOUT:   %C4.decl = class_decl @C4, () [template = constants.%C4]
+// CHECK:STDOUT:   %B.decl = class_decl @B {} [template = constants.%B]
+// CHECK:STDOUT:   %C1.decl = class_decl @C1 {} [template = constants.%C1]
+// CHECK:STDOUT:   %C2.decl = class_decl @C2 {} [template = constants.%C2]
+// CHECK:STDOUT:   %C3.decl = class_decl @C3 {} [template = constants.%C3]
+// CHECK:STDOUT:   %C4.decl = class_decl @C4 {} [template = constants.%C4]
 // CHECK:STDOUT: }
 // CHECK:STDOUT: }
 // CHECK:STDOUT:
 // CHECK:STDOUT:
 // CHECK:STDOUT: class @B {
 // CHECK:STDOUT: class @B {

+ 2 - 2
toolchain/check/testdata/class/fail_base_no_extend.carbon

@@ -27,8 +27,8 @@ class C {
 // CHECK:STDOUT:
 // CHECK:STDOUT:
 // CHECK:STDOUT: file {
 // CHECK:STDOUT: file {
 // CHECK:STDOUT:   package: <namespace> = namespace {.B = %B.decl, .C = %C.decl} [template]
 // CHECK:STDOUT:   package: <namespace> = namespace {.B = %B.decl, .C = %C.decl} [template]
-// CHECK:STDOUT:   %B.decl = class_decl @B, () [template = constants.%B]
-// CHECK:STDOUT:   %C.decl = class_decl @C, () [template = constants.%C]
+// CHECK:STDOUT:   %B.decl = class_decl @B {} [template = constants.%B]
+// CHECK:STDOUT:   %C.decl = class_decl @C {} [template = constants.%C]
 // CHECK:STDOUT: }
 // CHECK:STDOUT: }
 // CHECK:STDOUT:
 // CHECK:STDOUT:
 // CHECK:STDOUT: class @B {
 // CHECK:STDOUT: class @B {

+ 4 - 4
toolchain/check/testdata/class/fail_base_repeated.carbon

@@ -47,10 +47,10 @@ class D {
 // CHECK:STDOUT:
 // CHECK:STDOUT:
 // CHECK:STDOUT: file {
 // CHECK:STDOUT: file {
 // CHECK:STDOUT:   package: <namespace> = namespace {.B1 = %B1.decl, .B2 = %B2.decl, .C = %C.decl, .D = %D.decl} [template]
 // CHECK:STDOUT:   package: <namespace> = namespace {.B1 = %B1.decl, .B2 = %B2.decl, .C = %C.decl, .D = %D.decl} [template]
-// CHECK:STDOUT:   %B1.decl = class_decl @B1, () [template = constants.%B1]
-// CHECK:STDOUT:   %B2.decl = class_decl @B2, () [template = constants.%B2]
-// CHECK:STDOUT:   %C.decl = class_decl @C, () [template = constants.%C]
-// CHECK:STDOUT:   %D.decl = class_decl @D, () [template = constants.%D]
+// CHECK:STDOUT:   %B1.decl = class_decl @B1 {} [template = constants.%B1]
+// CHECK:STDOUT:   %B2.decl = class_decl @B2 {} [template = constants.%B2]
+// CHECK:STDOUT:   %C.decl = class_decl @C {} [template = constants.%C]
+// CHECK:STDOUT:   %D.decl = class_decl @D {} [template = constants.%D]
 // CHECK:STDOUT: }
 // CHECK:STDOUT: }
 // CHECK:STDOUT:
 // CHECK:STDOUT:
 // CHECK:STDOUT: class @B1 {
 // CHECK:STDOUT: class @B1 {

+ 2 - 2
toolchain/check/testdata/class/fail_base_unbound.carbon

@@ -29,8 +29,8 @@ let b: B = C.base;
 // CHECK:STDOUT:
 // CHECK:STDOUT:
 // CHECK:STDOUT: file {
 // CHECK:STDOUT: file {
 // CHECK:STDOUT:   package: <namespace> = namespace {.B = %B.decl, .C = %C.decl} [template]
 // CHECK:STDOUT:   package: <namespace> = namespace {.B = %B.decl, .C = %C.decl} [template]
-// CHECK:STDOUT:   %B.decl = class_decl @B, () [template = constants.%B]
-// CHECK:STDOUT:   %C.decl = class_decl @C, () [template = constants.%C]
+// CHECK:STDOUT:   %B.decl = class_decl @B {} [template = constants.%B]
+// CHECK:STDOUT:   %C.decl = class_decl @C {} [template = constants.%C]
 // CHECK:STDOUT:   %B.ref: type = name_ref B, %B.decl [template = constants.%B]
 // CHECK:STDOUT:   %B.ref: type = name_ref B, %B.decl [template = constants.%B]
 // CHECK:STDOUT:   %C.ref: type = name_ref C, %C.decl [template = constants.%C]
 // CHECK:STDOUT:   %C.ref: type = name_ref C, %C.decl [template = constants.%C]
 // CHECK:STDOUT:   %base.ref: <unbound element of class C> = name_ref base, @C.%.loc10 [template = @C.%.loc10]
 // CHECK:STDOUT:   %base.ref: <unbound element of class C> = name_ref base, @C.%.loc10 [template = @C.%.loc10]

+ 5 - 2
toolchain/check/testdata/class/fail_convert_to_invalid.carbon

@@ -25,8 +25,11 @@ fn Make() -> C {
 // CHECK:STDOUT:
 // CHECK:STDOUT:
 // CHECK:STDOUT: file {
 // CHECK:STDOUT: file {
 // CHECK:STDOUT:   package: <namespace> = namespace {.C = %C.decl, .Make = %Make} [template]
 // CHECK:STDOUT:   package: <namespace> = namespace {.C = %C.decl, .Make = %Make} [template]
-// CHECK:STDOUT:   %C.decl = class_decl @C, () [template = constants.%C]
-// CHECK:STDOUT:   %Make: <function> = fn_decl @Make [template]
+// CHECK:STDOUT:   %C.decl = class_decl @C {} [template = constants.%C]
+// CHECK:STDOUT:   %Make: <function> = fn_decl @Make {
+// CHECK:STDOUT:     %C.ref: type = name_ref C, %C.decl [template = constants.%C]
+// CHECK:STDOUT:     @Make.%return: ref C = var <return slot>
+// CHECK:STDOUT:   } [template]
 // CHECK:STDOUT: }
 // CHECK:STDOUT: }
 // CHECK:STDOUT:
 // CHECK:STDOUT:
 // CHECK:STDOUT: class @C {
 // CHECK:STDOUT: class @C {

+ 22 - 6
toolchain/check/testdata/class/fail_derived_to_base.carbon

@@ -54,12 +54,28 @@ fn ConvertIncomplete(p: Incomplete*) -> A2* { return p; }
 // CHECK:STDOUT:
 // CHECK:STDOUT:
 // CHECK:STDOUT: file {
 // CHECK:STDOUT: file {
 // CHECK:STDOUT:   package: <namespace> = namespace {.A1 = %A1.decl, .A2 = %A2.decl, .B2 = %B2.decl, .ConvertUnrelated = %ConvertUnrelated, .Incomplete = %Incomplete.decl, .ConvertIncomplete = %ConvertIncomplete} [template]
 // CHECK:STDOUT:   package: <namespace> = namespace {.A1 = %A1.decl, .A2 = %A2.decl, .B2 = %B2.decl, .ConvertUnrelated = %ConvertUnrelated, .Incomplete = %Incomplete.decl, .ConvertIncomplete = %ConvertIncomplete} [template]
-// CHECK:STDOUT:   %A1.decl = class_decl @A1, () [template = constants.%A1]
-// CHECK:STDOUT:   %A2.decl = class_decl @A2, () [template = constants.%A2]
-// CHECK:STDOUT:   %B2.decl = class_decl @B2, () [template = constants.%B2]
-// CHECK:STDOUT:   %ConvertUnrelated: <function> = fn_decl @ConvertUnrelated [template]
-// CHECK:STDOUT:   %Incomplete.decl = class_decl @Incomplete, () [template = constants.%Incomplete]
-// CHECK:STDOUT:   %ConvertIncomplete: <function> = fn_decl @ConvertIncomplete [template]
+// CHECK:STDOUT:   %A1.decl = class_decl @A1 {} [template = constants.%A1]
+// CHECK:STDOUT:   %A2.decl = class_decl @A2 {} [template = constants.%A2]
+// CHECK:STDOUT:   %B2.decl = class_decl @B2 {} [template = constants.%B2]
+// CHECK:STDOUT:   %ConvertUnrelated: <function> = fn_decl @ConvertUnrelated {
+// CHECK:STDOUT:     %B2.ref: type = name_ref B2, %B2.decl [template = constants.%B2]
+// CHECK:STDOUT:     %.loc23_26: type = ptr_type B2 [template = constants.%.8]
+// CHECK:STDOUT:     %p.loc23_21.1: B2* = param p
+// CHECK:STDOUT:     @ConvertUnrelated.%p: B2* = bind_name p, %p.loc23_21.1
+// CHECK:STDOUT:     %A1.ref: type = name_ref A1, %A1.decl [template = constants.%A1]
+// CHECK:STDOUT:     %.loc23_34: type = ptr_type A1 [template = constants.%.9]
+// CHECK:STDOUT:     %return.var.loc23: ref A1* = var <return slot>
+// CHECK:STDOUT:   } [template]
+// CHECK:STDOUT:   %Incomplete.decl = class_decl @Incomplete {} [template = constants.%Incomplete]
+// CHECK:STDOUT:   %ConvertIncomplete: <function> = fn_decl @ConvertIncomplete {
+// CHECK:STDOUT:     %Incomplete.ref: type = name_ref Incomplete, %Incomplete.decl [template = constants.%Incomplete]
+// CHECK:STDOUT:     %.loc30_35: type = ptr_type Incomplete [template = constants.%.13]
+// CHECK:STDOUT:     %p.loc30_22.1: Incomplete* = param p
+// CHECK:STDOUT:     @ConvertIncomplete.%p: Incomplete* = bind_name p, %p.loc30_22.1
+// CHECK:STDOUT:     %A2.ref: type = name_ref A2, %A2.decl [template = constants.%A2]
+// CHECK:STDOUT:     %.loc30_43: type = ptr_type A2 [template = constants.%.14]
+// CHECK:STDOUT:     %return.var.loc30: ref A2* = var <return slot>
+// CHECK:STDOUT:   } [template]
 // CHECK:STDOUT: }
 // CHECK:STDOUT: }
 // CHECK:STDOUT:
 // CHECK:STDOUT:
 // CHECK:STDOUT: class @A1 {
 // CHECK:STDOUT: class @A1 {

+ 1 - 1
toolchain/check/testdata/class/fail_field_modifiers.carbon

@@ -39,7 +39,7 @@ class Class {
 // CHECK:STDOUT:
 // CHECK:STDOUT:
 // CHECK:STDOUT: file {
 // CHECK:STDOUT: file {
 // CHECK:STDOUT:   package: <namespace> = namespace {.Class = %Class.decl} [template]
 // CHECK:STDOUT:   package: <namespace> = namespace {.Class = %Class.decl} [template]
-// CHECK:STDOUT:   %Class.decl = class_decl @Class, () [template = constants.%Class]
+// CHECK:STDOUT:   %Class.decl = class_decl @Class {} [template = constants.%Class]
 // CHECK:STDOUT: }
 // CHECK:STDOUT: }
 // CHECK:STDOUT:
 // CHECK:STDOUT:
 // CHECK:STDOUT: class @Class {
 // CHECK:STDOUT: class @Class {

+ 6 - 4
toolchain/check/testdata/class/fail_import_misuses.carbon

@@ -44,8 +44,8 @@ var a: Incomplete;
 // CHECK:STDOUT:
 // CHECK:STDOUT:
 // CHECK:STDOUT: file {
 // CHECK:STDOUT: file {
 // CHECK:STDOUT:   package: <namespace> = namespace {.Empty = %Empty.decl, .Incomplete = %Incomplete.decl} [template]
 // CHECK:STDOUT:   package: <namespace> = namespace {.Empty = %Empty.decl, .Incomplete = %Incomplete.decl} [template]
-// CHECK:STDOUT:   %Empty.decl = class_decl @Empty, () [template = constants.%Empty]
-// CHECK:STDOUT:   %Incomplete.decl = class_decl @Incomplete, () [template = constants.%Incomplete]
+// CHECK:STDOUT:   %Empty.decl = class_decl @Empty {} [template = constants.%Empty]
+// CHECK:STDOUT:   %Incomplete.decl = class_decl @Incomplete {} [template = constants.%Incomplete]
 // CHECK:STDOUT: }
 // CHECK:STDOUT: }
 // CHECK:STDOUT:
 // CHECK:STDOUT:
 // CHECK:STDOUT: class @Empty {
 // CHECK:STDOUT: class @Empty {
@@ -68,8 +68,10 @@ var a: Incomplete;
 // CHECK:STDOUT:   package: <namespace> = namespace {.Empty = %import_ref.1, .Incomplete = %import_ref.2, .a = %a} [template]
 // CHECK:STDOUT:   package: <namespace> = namespace {.Empty = %import_ref.1, .Incomplete = %import_ref.2, .a = %a} [template]
 // CHECK:STDOUT:   %import_ref.1: type = import_ref ir1, inst+1, used [template = constants.%Empty]
 // CHECK:STDOUT:   %import_ref.1: type = import_ref ir1, inst+1, used [template = constants.%Empty]
 // CHECK:STDOUT:   %import_ref.2: type = import_ref ir1, inst+4, used [template = constants.%Incomplete]
 // CHECK:STDOUT:   %import_ref.2: type = import_ref ir1, inst+4, used [template = constants.%Incomplete]
-// CHECK:STDOUT:   %.decl = class_decl @.1, (<unexpected instref inst+3>) [template = constants.%.2]
-// CHECK:STDOUT:   %Incomplete.decl = class_decl @Incomplete, () [template = constants.%Incomplete]
+// CHECK:STDOUT:   %.decl = class_decl @.1 {
+// CHECK:STDOUT:     %Empty.decl = class_decl @Empty {} [template = constants.%Empty]
+// CHECK:STDOUT:   } [template = constants.%.2]
+// CHECK:STDOUT:   %Incomplete.decl = class_decl @Incomplete {} [template = constants.%Incomplete]
 // CHECK:STDOUT:   %Incomplete.ref: type = name_ref Incomplete, %import_ref.2 [template = constants.%Incomplete]
 // CHECK:STDOUT:   %Incomplete.ref: type = name_ref Incomplete, %import_ref.2 [template = constants.%Incomplete]
 // CHECK:STDOUT:   %a.var: ref <error> = var a
 // CHECK:STDOUT:   %a.var: ref <error> = var a
 // CHECK:STDOUT:   %a: ref <error> = bind_name a, %a.var
 // CHECK:STDOUT:   %a: ref <error> = bind_name a, %a.var

+ 45 - 12
toolchain/check/testdata/class/fail_incomplete.carbon

@@ -126,20 +126,53 @@ fn CallReturnIncomplete() {
 // CHECK:STDOUT:
 // CHECK:STDOUT:
 // CHECK:STDOUT: file {
 // CHECK:STDOUT: file {
 // CHECK:STDOUT:   package: <namespace> = namespace {.Class = %Class.decl, .CallClassFunction = %CallClassFunction, .global_var = %global_var, .ConvertFromStruct = %ConvertFromStruct, .MemberAccess = %MemberAccess, .Copy = %Copy, .Let = %Let, .TakeIncomplete = %TakeIncomplete, .ReturnIncomplete = %ReturnIncomplete, .CallTakeIncomplete = %CallTakeIncomplete, .CallReturnIncomplete = %CallReturnIncomplete} [template]
 // CHECK:STDOUT:   package: <namespace> = namespace {.Class = %Class.decl, .CallClassFunction = %CallClassFunction, .global_var = %global_var, .ConvertFromStruct = %ConvertFromStruct, .MemberAccess = %MemberAccess, .Copy = %Copy, .Let = %Let, .TakeIncomplete = %TakeIncomplete, .ReturnIncomplete = %ReturnIncomplete, .CallTakeIncomplete = %CallTakeIncomplete, .CallReturnIncomplete = %CallReturnIncomplete} [template]
-// CHECK:STDOUT:   %Class.decl = class_decl @Class, () [template = constants.%Class]
-// CHECK:STDOUT:   %.loc15: <function> = fn_decl @.1 [template]
-// CHECK:STDOUT:   %CallClassFunction: <function> = fn_decl @CallClassFunction [template]
-// CHECK:STDOUT:   %Class.ref: type = name_ref Class, %Class.decl [template = constants.%Class]
+// CHECK:STDOUT:   %Class.decl = class_decl @Class {} [template = constants.%Class]
+// CHECK:STDOUT:   %.loc15: <function> = fn_decl @.1 {} [template]
+// CHECK:STDOUT:   %CallClassFunction: <function> = fn_decl @CallClassFunction {} [template]
+// CHECK:STDOUT:   %Class.ref.loc33: type = name_ref Class, %Class.decl [template = constants.%Class]
 // CHECK:STDOUT:   %global_var.var: ref <error> = var global_var
 // CHECK:STDOUT:   %global_var.var: ref <error> = var global_var
 // CHECK:STDOUT:   %global_var: ref <error> = bind_name global_var, %global_var.var
 // CHECK:STDOUT:   %global_var: ref <error> = bind_name global_var, %global_var.var
-// CHECK:STDOUT:   %ConvertFromStruct: <function> = fn_decl @ConvertFromStruct [template]
-// CHECK:STDOUT:   %MemberAccess: <function> = fn_decl @MemberAccess [template]
-// CHECK:STDOUT:   %Copy: <function> = fn_decl @Copy [template]
-// CHECK:STDOUT:   %Let: <function> = fn_decl @Let [template]
-// CHECK:STDOUT:   %TakeIncomplete: <function> = fn_decl @TakeIncomplete [template]
-// CHECK:STDOUT:   %ReturnIncomplete: <function> = fn_decl @ReturnIncomplete [template]
-// CHECK:STDOUT:   %CallTakeIncomplete: <function> = fn_decl @CallTakeIncomplete [template]
-// CHECK:STDOUT:   %CallReturnIncomplete: <function> = fn_decl @CallReturnIncomplete [template]
+// CHECK:STDOUT:   %ConvertFromStruct: <function> = fn_decl @ConvertFromStruct {
+// CHECK:STDOUT:     %Class.ref.loc41: type = name_ref Class, %Class.decl [template = constants.%Class]
+// CHECK:STDOUT:     %return.var.loc41: ref Class = var <return slot>
+// CHECK:STDOUT:   } [template]
+// CHECK:STDOUT:   %MemberAccess: <function> = fn_decl @MemberAccess {
+// CHECK:STDOUT:     %Class.ref.loc48: type = name_ref Class, %Class.decl [template = constants.%Class]
+// CHECK:STDOUT:     %.loc48: type = ptr_type Class [template = constants.%.2]
+// CHECK:STDOUT:     %p.loc48_17.1: Class* = param p
+// CHECK:STDOUT:     @MemberAccess.%p: Class* = bind_name p, %p.loc48_17.1
+// CHECK:STDOUT:     %return.var.loc48: ref i32 = var <return slot>
+// CHECK:STDOUT:   } [template]
+// CHECK:STDOUT:   %Copy: <function> = fn_decl @Copy {
+// CHECK:STDOUT:     %Class.ref.loc64_12: type = name_ref Class, %Class.decl [template = constants.%Class]
+// CHECK:STDOUT:     %.loc64: type = ptr_type Class [template = constants.%.2]
+// CHECK:STDOUT:     %p.loc64_9.1: Class* = param p
+// CHECK:STDOUT:     @Copy.%p: Class* = bind_name p, %p.loc64_9.1
+// CHECK:STDOUT:     %Class.ref.loc64_23: type = name_ref Class, %Class.decl [template = constants.%Class]
+// CHECK:STDOUT:     %return.var.loc64: ref Class = var <return slot>
+// CHECK:STDOUT:   } [template]
+// CHECK:STDOUT:   %Let: <function> = fn_decl @Let {
+// CHECK:STDOUT:     %Class.ref.loc68: type = name_ref Class, %Class.decl [template = constants.%Class]
+// CHECK:STDOUT:     %.loc68: type = ptr_type Class [template = constants.%.2]
+// CHECK:STDOUT:     %p.loc68_8.1: Class* = param p
+// CHECK:STDOUT:     @Let.%p: Class* = bind_name p, %p.loc68_8.1
+// CHECK:STDOUT:   } [template]
+// CHECK:STDOUT:   %TakeIncomplete: <function> = fn_decl @TakeIncomplete {
+// CHECK:STDOUT:     %Class.ref.loc78: type = name_ref Class, %Class.decl [template = constants.%Class]
+// CHECK:STDOUT:     %c.loc78_19.1: Class = param c
+// CHECK:STDOUT:     @TakeIncomplete.%c: Class = bind_name c, %c.loc78_19.1
+// CHECK:STDOUT:   } [template]
+// CHECK:STDOUT:   %ReturnIncomplete: <function> = fn_decl @ReturnIncomplete {
+// CHECK:STDOUT:     %Class.ref.loc88: type = name_ref Class, %Class.decl [template = constants.%Class]
+// CHECK:STDOUT:     %return.var.loc88: ref Class = var <return slot>
+// CHECK:STDOUT:   } [template]
+// CHECK:STDOUT:   %CallTakeIncomplete: <function> = fn_decl @CallTakeIncomplete {
+// CHECK:STDOUT:     %Class.ref.loc90: type = name_ref Class, %Class.decl [template = constants.%Class]
+// CHECK:STDOUT:     %.loc90: type = ptr_type Class [template = constants.%.2]
+// CHECK:STDOUT:     %p.loc90_23.1: Class* = param p
+// CHECK:STDOUT:     @CallTakeIncomplete.%p: Class* = bind_name p, %p.loc90_23.1
+// CHECK:STDOUT:   } [template]
+// CHECK:STDOUT:   %CallReturnIncomplete: <function> = fn_decl @CallReturnIncomplete {} [template]
 // CHECK:STDOUT: }
 // CHECK:STDOUT: }
 // CHECK:STDOUT:
 // CHECK:STDOUT:
 // CHECK:STDOUT: class @Class;
 // CHECK:STDOUT: class @Class;

+ 2 - 2
toolchain/check/testdata/class/fail_init.carbon

@@ -41,8 +41,8 @@ fn F() {
 // CHECK:STDOUT:
 // CHECK:STDOUT:
 // CHECK:STDOUT: file {
 // CHECK:STDOUT: file {
 // CHECK:STDOUT:   package: <namespace> = namespace {.Class = %Class.decl, .F = %F} [template]
 // CHECK:STDOUT:   package: <namespace> = namespace {.Class = %Class.decl, .F = %F} [template]
-// CHECK:STDOUT:   %Class.decl = class_decl @Class, () [template = constants.%Class]
-// CHECK:STDOUT:   %F: <function> = fn_decl @F [template]
+// CHECK:STDOUT:   %Class.decl = class_decl @Class {} [template = constants.%Class]
+// CHECK:STDOUT:   %F: <function> = fn_decl @F {} [template]
 // CHECK:STDOUT: }
 // CHECK:STDOUT: }
 // CHECK:STDOUT:
 // CHECK:STDOUT:
 // CHECK:STDOUT: class @Class {
 // CHECK:STDOUT: class @Class {

+ 8 - 3
toolchain/check/testdata/class/fail_init_as_inplace.carbon

@@ -38,9 +38,14 @@ fn F() {
 // CHECK:STDOUT:
 // CHECK:STDOUT:
 // CHECK:STDOUT: file {
 // CHECK:STDOUT: file {
 // CHECK:STDOUT:   package: <namespace> = namespace {.Class = %Class.decl, .G = %G, .F = %F} [template]
 // CHECK:STDOUT:   package: <namespace> = namespace {.Class = %Class.decl, .G = %G, .F = %F} [template]
-// CHECK:STDOUT:   %Class.decl = class_decl @Class, () [template = constants.%Class]
-// CHECK:STDOUT:   %G: <function> = fn_decl @G [template]
-// CHECK:STDOUT:   %F: <function> = fn_decl @F [template]
+// CHECK:STDOUT:   %Class.decl = class_decl @Class {} [template = constants.%Class]
+// CHECK:STDOUT:   %G: <function> = fn_decl @G {
+// CHECK:STDOUT:     %Class.ref: type = name_ref Class, %Class.decl [template = constants.%Class]
+// CHECK:STDOUT:     %.loc12: type = ptr_type Class [template = constants.%.3]
+// CHECK:STDOUT:     %p.loc12_6.1: Class* = param p
+// CHECK:STDOUT:     @G.%p: Class* = bind_name p, %p.loc12_6.1
+// CHECK:STDOUT:   } [template]
+// CHECK:STDOUT:   %F: <function> = fn_decl @F {} [template]
 // CHECK:STDOUT: }
 // CHECK:STDOUT: }
 // CHECK:STDOUT:
 // CHECK:STDOUT:
 // CHECK:STDOUT: class @Class {
 // CHECK:STDOUT: class @Class {

+ 19 - 5
toolchain/check/testdata/class/fail_memaccess_category.carbon

@@ -50,13 +50,27 @@ fn F(s: {.a: A}, b: B) {
 // CHECK:STDOUT:
 // CHECK:STDOUT:
 // CHECK:STDOUT: file {
 // CHECK:STDOUT: file {
 // CHECK:STDOUT:   package: <namespace> = namespace {.A = %A.decl, .B = %B.decl, .F = %F} [template]
 // CHECK:STDOUT:   package: <namespace> = namespace {.A = %A.decl, .B = %B.decl, .F = %F} [template]
-// CHECK:STDOUT:   %A.decl = class_decl @A, () [template = constants.%A]
-// CHECK:STDOUT:   %B.decl = class_decl @B, () [template = constants.%B]
-// CHECK:STDOUT:   %F: <function> = fn_decl @F.2 [template]
+// CHECK:STDOUT:   %A.decl = class_decl @A {} [template = constants.%A]
+// CHECK:STDOUT:   %B.decl = class_decl @B {} [template = constants.%B]
+// CHECK:STDOUT:   %F: <function> = fn_decl @F.2 {
+// CHECK:STDOUT:     %A.ref: type = name_ref A, %A.decl [template = constants.%A]
+// CHECK:STDOUT:     %.loc15: type = struct_type {.a: A} [template = constants.%.6]
+// CHECK:STDOUT:     %s.loc15_6.1: {.a: A} = param s
+// CHECK:STDOUT:     @F.2.%s: {.a: A} = bind_name s, %s.loc15_6.1
+// CHECK:STDOUT:     %B.ref: type = name_ref B, %B.decl [template = constants.%B]
+// CHECK:STDOUT:     %b.loc15_18.1: B = param b
+// CHECK:STDOUT:     @F.2.%b: B = bind_name b, %b.loc15_18.1
+// CHECK:STDOUT:   } [template]
 // CHECK:STDOUT: }
 // CHECK:STDOUT: }
 // CHECK:STDOUT:
 // CHECK:STDOUT:
 // CHECK:STDOUT: class @A {
 // CHECK:STDOUT: class @A {
-// CHECK:STDOUT:   %F: <function> = fn_decl @F.1 [template]
+// CHECK:STDOUT:   %F: <function> = fn_decl @F.1 {
+// CHECK:STDOUT:     %A.ref: type = name_ref A, file.%A.decl [template = constants.%A]
+// CHECK:STDOUT:     %.loc8_20: type = ptr_type A [template = constants.%.1]
+// CHECK:STDOUT:     %self.loc8_13.1: A* = param self
+// CHECK:STDOUT:     %self.loc8_13.3: A* = bind_name self, %self.loc8_13.1
+// CHECK:STDOUT:     %.loc8_8: A* = addr_pattern %self.loc8_13.3
+// CHECK:STDOUT:   } [template]
 // CHECK:STDOUT:
 // CHECK:STDOUT:
 // CHECK:STDOUT: !members:
 // CHECK:STDOUT: !members:
 // CHECK:STDOUT:   .F = %F
 // CHECK:STDOUT:   .F = %F
@@ -70,7 +84,7 @@ fn F(s: {.a: A}, b: B) {
 // CHECK:STDOUT:   .a = %.loc12
 // CHECK:STDOUT:   .a = %.loc12
 // CHECK:STDOUT: }
 // CHECK:STDOUT: }
 // CHECK:STDOUT:
 // CHECK:STDOUT:
-// CHECK:STDOUT: fn @F.1[addr %self: A*]();
+// CHECK:STDOUT: fn @F.1[addr @A.%self.loc8_13.3: A*]();
 // CHECK:STDOUT:
 // CHECK:STDOUT:
 // CHECK:STDOUT: fn @F.2(%s: {.a: A}, %b: B) {
 // CHECK:STDOUT: fn @F.2(%s: {.a: A}, %b: B) {
 // CHECK:STDOUT: !entry:
 // CHECK:STDOUT: !entry:

+ 5 - 3
toolchain/check/testdata/class/fail_member_of_let.carbon

@@ -27,14 +27,16 @@ fn T.F() {}
 // CHECK:STDOUT:
 // CHECK:STDOUT:
 // CHECK:STDOUT: file {
 // CHECK:STDOUT: file {
 // CHECK:STDOUT:   package: <namespace> = namespace {.Class = %Class.decl} [template]
 // CHECK:STDOUT:   package: <namespace> = namespace {.Class = %Class.decl} [template]
-// CHECK:STDOUT:   %Class.decl = class_decl @Class, () [template = constants.%Class]
+// CHECK:STDOUT:   %Class.decl = class_decl @Class {} [template = constants.%Class]
 // CHECK:STDOUT:   %Class.ref: type = name_ref Class, %Class.decl [template = constants.%Class]
 // CHECK:STDOUT:   %Class.ref: type = name_ref Class, %Class.decl [template = constants.%Class]
 // CHECK:STDOUT:   %T: type = bind_name T, %Class.ref
 // CHECK:STDOUT:   %T: type = bind_name T, %Class.ref
-// CHECK:STDOUT:   %.loc19: <function> = fn_decl @.1 [template]
+// CHECK:STDOUT:   %.loc19: <function> = fn_decl @.1 {} [template]
 // CHECK:STDOUT: }
 // CHECK:STDOUT: }
 // CHECK:STDOUT:
 // CHECK:STDOUT:
 // CHECK:STDOUT: class @Class {
 // CHECK:STDOUT: class @Class {
-// CHECK:STDOUT:   %F: <function> = fn_decl @F [template]
+// CHECK:STDOUT:   %F: <function> = fn_decl @F {
+// CHECK:STDOUT:     %return.var: ref i32 = var <return slot>
+// CHECK:STDOUT:   } [template]
 // CHECK:STDOUT:
 // CHECK:STDOUT:
 // CHECK:STDOUT: !members:
 // CHECK:STDOUT: !members:
 // CHECK:STDOUT:   .F = %F
 // CHECK:STDOUT:   .F = %F

+ 14 - 6
toolchain/check/testdata/class/fail_method.carbon

@@ -51,16 +51,24 @@ fn F(c: Class) {
 // CHECK:STDOUT:
 // CHECK:STDOUT:
 // CHECK:STDOUT: file {
 // CHECK:STDOUT: file {
 // CHECK:STDOUT:   package: <namespace> = namespace {.Class = %Class.decl, .A = %A, .F = %F} [template]
 // CHECK:STDOUT:   package: <namespace> = namespace {.Class = %Class.decl, .A = %A, .F = %F} [template]
-// CHECK:STDOUT:   %Class.decl = class_decl @Class, () [template = constants.%Class]
-// CHECK:STDOUT:   %Class.ref: type = name_ref Class, %Class.decl [template = constants.%Class]
+// CHECK:STDOUT:   %Class.decl = class_decl @Class {} [template = constants.%Class]
+// CHECK:STDOUT:   %Class.ref.loc12: type = name_ref Class, %Class.decl [template = constants.%Class]
 // CHECK:STDOUT:   %WithSelf.ref: <function> = name_ref WithSelf, @Class.%WithSelf [template = @Class.%WithSelf]
 // CHECK:STDOUT:   %WithSelf.ref: <function> = name_ref WithSelf, @Class.%WithSelf [template = @Class.%WithSelf]
 // CHECK:STDOUT:   %A: <function> = bind_alias A, @Class.%WithSelf [template = @Class.%WithSelf]
 // CHECK:STDOUT:   %A: <function> = bind_alias A, @Class.%WithSelf [template = @Class.%WithSelf]
-// CHECK:STDOUT:   %F: <function> = fn_decl @F [template]
+// CHECK:STDOUT:   %F: <function> = fn_decl @F {
+// CHECK:STDOUT:     %Class.ref.loc14: type = name_ref Class, %Class.decl [template = constants.%Class]
+// CHECK:STDOUT:     %c.loc14_6.1: Class = param c
+// CHECK:STDOUT:     @F.%c: Class = bind_name c, %c.loc14_6.1
+// CHECK:STDOUT:   } [template]
 // CHECK:STDOUT: }
 // CHECK:STDOUT: }
 // CHECK:STDOUT:
 // CHECK:STDOUT:
 // CHECK:STDOUT: class @Class {
 // CHECK:STDOUT: class @Class {
-// CHECK:STDOUT:   %NoSelf: <function> = fn_decl @NoSelf [template]
-// CHECK:STDOUT:   %WithSelf: <function> = fn_decl @WithSelf [template]
+// CHECK:STDOUT:   %NoSelf: <function> = fn_decl @NoSelf {} [template]
+// CHECK:STDOUT:   %WithSelf: <function> = fn_decl @WithSelf {
+// CHECK:STDOUT:     %Class.ref: type = name_ref Class, file.%Class.decl [template = constants.%Class]
+// CHECK:STDOUT:     %self.loc9_15.1: Class = param self
+// CHECK:STDOUT:     %self.loc9_15.2: Class = bind_name self, %self.loc9_15.1
+// CHECK:STDOUT:   } [template]
 // CHECK:STDOUT:
 // CHECK:STDOUT:
 // CHECK:STDOUT: !members:
 // CHECK:STDOUT: !members:
 // CHECK:STDOUT:   .NoSelf = %NoSelf
 // CHECK:STDOUT:   .NoSelf = %NoSelf
@@ -69,7 +77,7 @@ fn F(c: Class) {
 // CHECK:STDOUT:
 // CHECK:STDOUT:
 // CHECK:STDOUT: fn @NoSelf();
 // CHECK:STDOUT: fn @NoSelf();
 // CHECK:STDOUT:
 // CHECK:STDOUT:
-// CHECK:STDOUT: fn @WithSelf[%self: Class]();
+// CHECK:STDOUT: fn @WithSelf[@Class.%self.loc9_15.2: Class]();
 // CHECK:STDOUT:
 // CHECK:STDOUT:
 // CHECK:STDOUT: fn @F(%c: Class) {
 // CHECK:STDOUT: fn @F(%c: Class) {
 // CHECK:STDOUT: !entry:
 // CHECK:STDOUT: !entry:

+ 33 - 13
toolchain/check/testdata/class/fail_method_modifiers.carbon

@@ -58,14 +58,22 @@ base class BaseClass {
 // CHECK:STDOUT:
 // CHECK:STDOUT:
 // CHECK:STDOUT: file {
 // CHECK:STDOUT: file {
 // CHECK:STDOUT:   package: <namespace> = namespace {.FinalClass = %FinalClass.decl, .AbstractClass = %AbstractClass.decl, .BaseClass = %BaseClass.decl} [template]
 // CHECK:STDOUT:   package: <namespace> = namespace {.FinalClass = %FinalClass.decl, .AbstractClass = %AbstractClass.decl, .BaseClass = %BaseClass.decl} [template]
-// CHECK:STDOUT:   %FinalClass.decl = class_decl @FinalClass, () [template = constants.%FinalClass]
-// CHECK:STDOUT:   %AbstractClass.decl = class_decl @AbstractClass, () [template = constants.%AbstractClass]
-// CHECK:STDOUT:   %BaseClass.decl = class_decl @BaseClass, () [template = constants.%BaseClass]
+// CHECK:STDOUT:   %FinalClass.decl = class_decl @FinalClass {} [template = constants.%FinalClass]
+// CHECK:STDOUT:   %AbstractClass.decl = class_decl @AbstractClass {} [template = constants.%AbstractClass]
+// CHECK:STDOUT:   %BaseClass.decl = class_decl @BaseClass {} [template = constants.%BaseClass]
 // CHECK:STDOUT: }
 // CHECK:STDOUT: }
 // CHECK:STDOUT:
 // CHECK:STDOUT:
 // CHECK:STDOUT: class @FinalClass {
 // CHECK:STDOUT: class @FinalClass {
-// CHECK:STDOUT:   %Abstract: <function> = fn_decl @Abstract.1 [template]
-// CHECK:STDOUT:   %Virtual: <function> = fn_decl @Virtual [template]
+// CHECK:STDOUT:   %Abstract: <function> = fn_decl @Abstract.1 {
+// CHECK:STDOUT:     %Self.ref.loc15: type = name_ref Self, constants.%FinalClass [template = constants.%FinalClass]
+// CHECK:STDOUT:     %self.loc15_24.1: FinalClass = param self
+// CHECK:STDOUT:     %self.loc15_24.2: FinalClass = bind_name self, %self.loc15_24.1
+// CHECK:STDOUT:   } [template]
+// CHECK:STDOUT:   %Virtual: <function> = fn_decl @Virtual {
+// CHECK:STDOUT:     %Self.ref.loc23: type = name_ref Self, constants.%FinalClass [template = constants.%FinalClass]
+// CHECK:STDOUT:     %self.loc23_22.1: FinalClass = param self
+// CHECK:STDOUT:     %self.loc23_22.2: FinalClass = bind_name self, %self.loc23_22.1
+// CHECK:STDOUT:   } [template]
 // CHECK:STDOUT:
 // CHECK:STDOUT:
 // CHECK:STDOUT: !members:
 // CHECK:STDOUT: !members:
 // CHECK:STDOUT:   .Abstract = %Abstract
 // CHECK:STDOUT:   .Abstract = %Abstract
@@ -73,8 +81,16 @@ base class BaseClass {
 // CHECK:STDOUT: }
 // CHECK:STDOUT: }
 // CHECK:STDOUT:
 // CHECK:STDOUT:
 // CHECK:STDOUT: class @AbstractClass {
 // CHECK:STDOUT: class @AbstractClass {
-// CHECK:STDOUT:   %Default: <function> = fn_decl @Default [template]
-// CHECK:STDOUT:   %Final: <function> = fn_decl @Final [template]
+// CHECK:STDOUT:   %Default: <function> = fn_decl @Default {
+// CHECK:STDOUT:     %Self.ref.loc31: type = name_ref Self, constants.%AbstractClass [template = constants.%AbstractClass]
+// CHECK:STDOUT:     %self.loc31_22.1: AbstractClass = param self
+// CHECK:STDOUT:     %self.loc31_22.2: AbstractClass = bind_name self, %self.loc31_22.1
+// CHECK:STDOUT:   } [template]
+// CHECK:STDOUT:   %Final: <function> = fn_decl @Final {
+// CHECK:STDOUT:     %Self.ref.loc36: type = name_ref Self, constants.%AbstractClass [template = constants.%AbstractClass]
+// CHECK:STDOUT:     %self.loc36_18.1: AbstractClass = param self
+// CHECK:STDOUT:     %self.loc36_18.2: AbstractClass = bind_name self, %self.loc36_18.1
+// CHECK:STDOUT:   } [template]
 // CHECK:STDOUT:
 // CHECK:STDOUT:
 // CHECK:STDOUT: !members:
 // CHECK:STDOUT: !members:
 // CHECK:STDOUT:   .Default = %Default
 // CHECK:STDOUT:   .Default = %Default
@@ -82,19 +98,23 @@ base class BaseClass {
 // CHECK:STDOUT: }
 // CHECK:STDOUT: }
 // CHECK:STDOUT:
 // CHECK:STDOUT:
 // CHECK:STDOUT: class @BaseClass {
 // CHECK:STDOUT: class @BaseClass {
-// CHECK:STDOUT:   %Abstract: <function> = fn_decl @Abstract.2 [template]
+// CHECK:STDOUT:   %Abstract: <function> = fn_decl @Abstract.2 {
+// CHECK:STDOUT:     %Self.ref: type = name_ref Self, constants.%BaseClass [template = constants.%BaseClass]
+// CHECK:STDOUT:     %self.loc47_24.1: BaseClass = param self
+// CHECK:STDOUT:     %self.loc47_24.2: BaseClass = bind_name self, %self.loc47_24.1
+// CHECK:STDOUT:   } [template]
 // CHECK:STDOUT:
 // CHECK:STDOUT:
 // CHECK:STDOUT: !members:
 // CHECK:STDOUT: !members:
 // CHECK:STDOUT:   .Abstract = %Abstract
 // CHECK:STDOUT:   .Abstract = %Abstract
 // CHECK:STDOUT: }
 // CHECK:STDOUT: }
 // CHECK:STDOUT:
 // CHECK:STDOUT:
-// CHECK:STDOUT: fn @Abstract.1[%self: FinalClass]();
+// CHECK:STDOUT: fn @Abstract.1[@FinalClass.%self.loc15_24.2: FinalClass]();
 // CHECK:STDOUT:
 // CHECK:STDOUT:
-// CHECK:STDOUT: fn @Virtual[%self: FinalClass]();
+// CHECK:STDOUT: fn @Virtual[@FinalClass.%self.loc23_22.2: FinalClass]();
 // CHECK:STDOUT:
 // CHECK:STDOUT:
-// CHECK:STDOUT: fn @Default[%self: AbstractClass]();
+// CHECK:STDOUT: fn @Default[@AbstractClass.%self.loc31_22.2: AbstractClass]();
 // CHECK:STDOUT:
 // CHECK:STDOUT:
-// CHECK:STDOUT: fn @Final[%self: AbstractClass]();
+// CHECK:STDOUT: fn @Final[@AbstractClass.%self.loc36_18.2: AbstractClass]();
 // CHECK:STDOUT:
 // CHECK:STDOUT:
-// CHECK:STDOUT: fn @Abstract.2[%self: BaseClass]();
+// CHECK:STDOUT: fn @Abstract.2[@BaseClass.%self.loc47_24.2: BaseClass]();
 // CHECK:STDOUT:
 // CHECK:STDOUT:

+ 6 - 6
toolchain/check/testdata/class/fail_modifiers.carbon

@@ -78,12 +78,12 @@ abstract base class AbstractAndBase {}
 // CHECK:STDOUT:
 // CHECK:STDOUT:
 // CHECK:STDOUT: file {
 // CHECK:STDOUT: file {
 // CHECK:STDOUT:   package: <namespace> = namespace {.DuplicatePrivate = %DuplicatePrivate.decl, .TwoAccess = %TwoAccess.decl, .TwoAbstract = %TwoAbstract.decl, .Virtual = %Virtual.decl, .WrongOrder = %WrongOrder.decl, .AbstractAndBase = %AbstractAndBase.decl} [template]
 // CHECK:STDOUT:   package: <namespace> = namespace {.DuplicatePrivate = %DuplicatePrivate.decl, .TwoAccess = %TwoAccess.decl, .TwoAbstract = %TwoAbstract.decl, .Virtual = %Virtual.decl, .WrongOrder = %WrongOrder.decl, .AbstractAndBase = %AbstractAndBase.decl} [template]
-// CHECK:STDOUT:   %DuplicatePrivate.decl = class_decl @DuplicatePrivate, () [template = constants.%DuplicatePrivate]
-// CHECK:STDOUT:   %TwoAccess.decl = class_decl @TwoAccess, () [template = constants.%TwoAccess]
-// CHECK:STDOUT:   %TwoAbstract.decl = class_decl @TwoAbstract, () [template = constants.%TwoAbstract]
-// CHECK:STDOUT:   %Virtual.decl = class_decl @Virtual, () [template = constants.%Virtual]
-// CHECK:STDOUT:   %WrongOrder.decl = class_decl @WrongOrder, () [template = constants.%WrongOrder]
-// CHECK:STDOUT:   %AbstractAndBase.decl = class_decl @AbstractAndBase, () [template = constants.%AbstractAndBase]
+// CHECK:STDOUT:   %DuplicatePrivate.decl = class_decl @DuplicatePrivate {} [template = constants.%DuplicatePrivate]
+// CHECK:STDOUT:   %TwoAccess.decl = class_decl @TwoAccess {} [template = constants.%TwoAccess]
+// CHECK:STDOUT:   %TwoAbstract.decl = class_decl @TwoAbstract {} [template = constants.%TwoAbstract]
+// CHECK:STDOUT:   %Virtual.decl = class_decl @Virtual {} [template = constants.%Virtual]
+// CHECK:STDOUT:   %WrongOrder.decl = class_decl @WrongOrder {} [template = constants.%WrongOrder]
+// CHECK:STDOUT:   %AbstractAndBase.decl = class_decl @AbstractAndBase {} [template = constants.%AbstractAndBase]
 // CHECK:STDOUT: }
 // CHECK:STDOUT: }
 // CHECK:STDOUT:
 // CHECK:STDOUT:
 // CHECK:STDOUT: class @DuplicatePrivate;
 // CHECK:STDOUT: class @DuplicatePrivate;

+ 2 - 2
toolchain/check/testdata/class/fail_out_of_line_decl.carbon

@@ -20,8 +20,8 @@ fn C.F() {}
 // CHECK:STDOUT:
 // CHECK:STDOUT:
 // CHECK:STDOUT: file {
 // CHECK:STDOUT: file {
 // CHECK:STDOUT:   package: <namespace> = namespace {.C = %C.decl} [template]
 // CHECK:STDOUT:   package: <namespace> = namespace {.C = %C.decl} [template]
-// CHECK:STDOUT:   %C.decl = class_decl @C, () [template = constants.%C]
-// CHECK:STDOUT:   %F: <function> = fn_decl @F [template]
+// CHECK:STDOUT:   %C.decl = class_decl @C {} [template = constants.%C]
+// CHECK:STDOUT:   %F: <function> = fn_decl @F {} [template]
 // CHECK:STDOUT: }
 // CHECK:STDOUT: }
 // CHECK:STDOUT:
 // CHECK:STDOUT:
 // CHECK:STDOUT: class @C {
 // CHECK:STDOUT: class @C {

+ 15 - 15
toolchain/check/testdata/class/fail_redeclaration_introducer.carbon

@@ -89,21 +89,21 @@ base class G;
 // CHECK:STDOUT:
 // CHECK:STDOUT:
 // CHECK:STDOUT: file {
 // CHECK:STDOUT: file {
 // CHECK:STDOUT:   package: <namespace> = namespace {.A = %A.decl.loc7, .B = %B.decl.loc16, .C = %C.decl.loc25, .D = %D.decl.loc34, .E = %E.decl.loc43, .F = %F.decl.loc52, .G = %G.decl.loc61} [template]
 // CHECK:STDOUT:   package: <namespace> = namespace {.A = %A.decl.loc7, .B = %B.decl.loc16, .C = %C.decl.loc25, .D = %D.decl.loc34, .E = %E.decl.loc43, .F = %F.decl.loc52, .G = %G.decl.loc61} [template]
-// CHECK:STDOUT:   %A.decl.loc7 = class_decl @A, () [template = constants.%A]
-// CHECK:STDOUT:   %A.decl.loc14 = class_decl @A, () [template = constants.%A]
-// CHECK:STDOUT:   %B.decl.loc16 = class_decl @B, () [template = constants.%B]
-// CHECK:STDOUT:   %B.decl.loc23 = class_decl @B, () [template = constants.%B]
-// CHECK:STDOUT:   %C.decl.loc25 = class_decl @C, () [template = constants.%C]
-// CHECK:STDOUT:   %C.decl.loc32 = class_decl @C, () [template = constants.%C]
-// CHECK:STDOUT:   %D.decl.loc34 = class_decl @D, () [template = constants.%D]
-// CHECK:STDOUT:   %D.decl.loc41 = class_decl @D, () [template = constants.%D]
-// CHECK:STDOUT:   %E.decl.loc43 = class_decl @E, () [template = constants.%E]
-// CHECK:STDOUT:   %E.decl.loc50 = class_decl @E, () [template = constants.%E]
-// CHECK:STDOUT:   %F.decl.loc52 = class_decl @F, () [template = constants.%F]
-// CHECK:STDOUT:   %F.decl.loc59 = class_decl @F, () [template = constants.%F]
-// CHECK:STDOUT:   %G.decl.loc61 = class_decl @G, () [template = constants.%G]
-// CHECK:STDOUT:   %G.decl.loc68 = class_decl @G, () [template = constants.%G]
-// CHECK:STDOUT:   %G.decl.loc75 = class_decl @G, () [template = constants.%G]
+// CHECK:STDOUT:   %A.decl.loc7 = class_decl @A {} [template = constants.%A]
+// CHECK:STDOUT:   %A.decl.loc14 = class_decl @A {} [template = constants.%A]
+// CHECK:STDOUT:   %B.decl.loc16 = class_decl @B {} [template = constants.%B]
+// CHECK:STDOUT:   %B.decl.loc23 = class_decl @B {} [template = constants.%B]
+// CHECK:STDOUT:   %C.decl.loc25 = class_decl @C {} [template = constants.%C]
+// CHECK:STDOUT:   %C.decl.loc32 = class_decl @C {} [template = constants.%C]
+// CHECK:STDOUT:   %D.decl.loc34 = class_decl @D {} [template = constants.%D]
+// CHECK:STDOUT:   %D.decl.loc41 = class_decl @D {} [template = constants.%D]
+// CHECK:STDOUT:   %E.decl.loc43 = class_decl @E {} [template = constants.%E]
+// CHECK:STDOUT:   %E.decl.loc50 = class_decl @E {} [template = constants.%E]
+// CHECK:STDOUT:   %F.decl.loc52 = class_decl @F {} [template = constants.%F]
+// CHECK:STDOUT:   %F.decl.loc59 = class_decl @F {} [template = constants.%F]
+// CHECK:STDOUT:   %G.decl.loc61 = class_decl @G {} [template = constants.%G]
+// CHECK:STDOUT:   %G.decl.loc68 = class_decl @G {} [template = constants.%G]
+// CHECK:STDOUT:   %G.decl.loc75 = class_decl @G {} [template = constants.%G]
 // CHECK:STDOUT: }
 // CHECK:STDOUT: }
 // CHECK:STDOUT:
 // CHECK:STDOUT:
 // CHECK:STDOUT: class @A {
 // CHECK:STDOUT: class @A {

+ 9 - 9
toolchain/check/testdata/class/fail_redeclaration_scope.carbon

@@ -36,29 +36,29 @@ class Y {
 // CHECK:STDOUT:
 // CHECK:STDOUT:
 // CHECK:STDOUT: file {
 // CHECK:STDOUT: file {
 // CHECK:STDOUT:   package: <namespace> = namespace {.A = %A.decl.loc7, .X = %X.decl, .Y = %Y.decl} [template]
 // CHECK:STDOUT:   package: <namespace> = namespace {.A = %A.decl.loc7, .X = %X.decl, .Y = %Y.decl} [template]
-// CHECK:STDOUT:   %A.decl.loc7 = class_decl @A.1, () [template = constants.%A.1]
-// CHECK:STDOUT:   %X.decl = class_decl @X, () [template = constants.%X]
-// CHECK:STDOUT:   %A.decl.loc15 = class_decl @A.1, () [template = constants.%A.1]
-// CHECK:STDOUT:   %Y.decl = class_decl @Y, () [template = constants.%Y]
+// CHECK:STDOUT:   %A.decl.loc7 = class_decl @A.1 {} [template = constants.%A.1]
+// CHECK:STDOUT:   %X.decl = class_decl @X {} [template = constants.%X]
+// CHECK:STDOUT:   %A.decl.loc15 = class_decl @A.1 {} [template = constants.%A.1]
+// CHECK:STDOUT:   %Y.decl = class_decl @Y {} [template = constants.%Y]
 // CHECK:STDOUT: }
 // CHECK:STDOUT: }
 // CHECK:STDOUT:
 // CHECK:STDOUT:
 // CHECK:STDOUT: class @A.1 {
 // CHECK:STDOUT: class @A.1 {
-// CHECK:STDOUT:   %B.decl = class_decl @B.2, () [template = constants.%B.2]
+// CHECK:STDOUT:   %B.decl = class_decl @B.2 {} [template = constants.%B.2]
 // CHECK:STDOUT:
 // CHECK:STDOUT:
 // CHECK:STDOUT: !members:
 // CHECK:STDOUT: !members:
 // CHECK:STDOUT:   .B = %B.decl
 // CHECK:STDOUT:   .B = %B.decl
 // CHECK:STDOUT: }
 // CHECK:STDOUT: }
 // CHECK:STDOUT:
 // CHECK:STDOUT:
 // CHECK:STDOUT: class @X {
 // CHECK:STDOUT: class @X {
-// CHECK:STDOUT:   %A.decl = class_decl @A.2, () [template = constants.%A.2]
-// CHECK:STDOUT:   %B.decl = class_decl @B.1, () [template = constants.%B.1]
+// CHECK:STDOUT:   %A.decl = class_decl @A.2 {} [template = constants.%A.2]
+// CHECK:STDOUT:   %B.decl = class_decl @B.1 {} [template = constants.%B.1]
 // CHECK:STDOUT:
 // CHECK:STDOUT:
 // CHECK:STDOUT: !members:
 // CHECK:STDOUT: !members:
 // CHECK:STDOUT:   .A = %A.decl
 // CHECK:STDOUT:   .A = %A.decl
 // CHECK:STDOUT: }
 // CHECK:STDOUT: }
 // CHECK:STDOUT:
 // CHECK:STDOUT:
 // CHECK:STDOUT: class @A.2 {
 // CHECK:STDOUT: class @A.2 {
-// CHECK:STDOUT:   %B.decl = class_decl @B.1, () [template = constants.%B.1]
+// CHECK:STDOUT:   %B.decl = class_decl @B.1 {} [template = constants.%B.1]
 // CHECK:STDOUT:
 // CHECK:STDOUT:
 // CHECK:STDOUT: !members:
 // CHECK:STDOUT: !members:
 // CHECK:STDOUT:   .B = %B.decl
 // CHECK:STDOUT:   .B = %B.decl
@@ -72,7 +72,7 @@ class Y {
 // CHECK:STDOUT: class @B.2;
 // CHECK:STDOUT: class @B.2;
 // CHECK:STDOUT:
 // CHECK:STDOUT:
 // CHECK:STDOUT: class @Y {
 // CHECK:STDOUT: class @Y {
-// CHECK:STDOUT:   %.decl = class_decl @.1, () [template = constants.%.2]
+// CHECK:STDOUT:   %.decl = class_decl @.1 {} [template = constants.%.2]
 // CHECK:STDOUT:
 // CHECK:STDOUT:
 // CHECK:STDOUT: !members:
 // CHECK:STDOUT: !members:
 // CHECK:STDOUT: }
 // CHECK:STDOUT: }

+ 7 - 7
toolchain/check/testdata/class/fail_redefinition.carbon

@@ -33,16 +33,16 @@ fn Class.H() {}
 // CHECK:STDOUT:
 // CHECK:STDOUT:
 // CHECK:STDOUT: file {
 // CHECK:STDOUT: file {
 // CHECK:STDOUT:   package: <namespace> = namespace {.Class = %Class.decl.loc7} [template]
 // CHECK:STDOUT:   package: <namespace> = namespace {.Class = %Class.decl.loc7} [template]
-// CHECK:STDOUT:   %Class.decl.loc7 = class_decl @Class, () [template = constants.%Class]
-// CHECK:STDOUT:   %Class.decl.loc18 = class_decl @Class, () [template = constants.%Class]
-// CHECK:STDOUT:   %F: <function> = fn_decl @F [template]
-// CHECK:STDOUT:   %G: <function> = fn_decl @G [template]
-// CHECK:STDOUT:   %H: <function> = fn_decl @H [template]
+// CHECK:STDOUT:   %Class.decl.loc7 = class_decl @Class {} [template = constants.%Class]
+// CHECK:STDOUT:   %Class.decl.loc18 = class_decl @Class {} [template = constants.%Class]
+// CHECK:STDOUT:   %F: <function> = fn_decl @F {} [template]
+// CHECK:STDOUT:   %G: <function> = fn_decl @G {} [template]
+// CHECK:STDOUT:   %H: <function> = fn_decl @H {} [template]
 // CHECK:STDOUT: }
 // CHECK:STDOUT: }
 // CHECK:STDOUT:
 // CHECK:STDOUT:
 // CHECK:STDOUT: class @Class {
 // CHECK:STDOUT: class @Class {
-// CHECK:STDOUT:   %G: <function> = fn_decl @G [template]
-// CHECK:STDOUT:   %H: <function> = fn_decl @H [template]
+// CHECK:STDOUT:   %G: <function> = fn_decl @G {} [template]
+// CHECK:STDOUT:   %H: <function> = fn_decl @H {} [template]
 // CHECK:STDOUT:
 // CHECK:STDOUT:
 // CHECK:STDOUT: !members:
 // CHECK:STDOUT: !members:
 // CHECK:STDOUT:   .F = <unexpected instref inst+3>
 // CHECK:STDOUT:   .F = <unexpected instref inst+3>

+ 7 - 3
toolchain/check/testdata/class/fail_reorder.carbon

@@ -35,12 +35,16 @@ class Class {
 // CHECK:STDOUT:
 // CHECK:STDOUT:
 // CHECK:STDOUT: file {
 // CHECK:STDOUT: file {
 // CHECK:STDOUT:   package: <namespace> = namespace {.Class = %Class.decl} [template]
 // CHECK:STDOUT:   package: <namespace> = namespace {.Class = %Class.decl} [template]
-// CHECK:STDOUT:   %Class.decl = class_decl @Class, () [template = constants.%Class]
+// CHECK:STDOUT:   %Class.decl = class_decl @Class {} [template = constants.%Class]
 // CHECK:STDOUT: }
 // CHECK:STDOUT: }
 // CHECK:STDOUT:
 // CHECK:STDOUT:
 // CHECK:STDOUT: class @Class {
 // CHECK:STDOUT: class @Class {
-// CHECK:STDOUT:   %G: <function> = fn_decl @G [template]
-// CHECK:STDOUT:   %F: <function> = fn_decl @F [template]
+// CHECK:STDOUT:   %G: <function> = fn_decl @G {
+// CHECK:STDOUT:     %return.var.loc8: ref i32 = var <return slot>
+// CHECK:STDOUT:   } [template]
+// CHECK:STDOUT:   %F: <function> = fn_decl @F {
+// CHECK:STDOUT:     %return.var.loc23: ref i32 = var <return slot>
+// CHECK:STDOUT:   } [template]
 // CHECK:STDOUT:
 // CHECK:STDOUT:
 // CHECK:STDOUT: !members:
 // CHECK:STDOUT: !members:
 // CHECK:STDOUT:   .G = %G
 // CHECK:STDOUT:   .G = %G

+ 7 - 3
toolchain/check/testdata/class/fail_scope.carbon

@@ -27,12 +27,16 @@ fn G() -> i32 {
 // CHECK:STDOUT:
 // CHECK:STDOUT:
 // CHECK:STDOUT: file {
 // CHECK:STDOUT: file {
 // CHECK:STDOUT:   package: <namespace> = namespace {.Class = %Class.decl, .G = %G} [template]
 // CHECK:STDOUT:   package: <namespace> = namespace {.Class = %Class.decl, .G = %G} [template]
-// CHECK:STDOUT:   %Class.decl = class_decl @Class, () [template = constants.%Class]
-// CHECK:STDOUT:   %G: <function> = fn_decl @G [template]
+// CHECK:STDOUT:   %Class.decl = class_decl @Class {} [template = constants.%Class]
+// CHECK:STDOUT:   %G: <function> = fn_decl @G {
+// CHECK:STDOUT:     %return.var: ref i32 = var <return slot>
+// CHECK:STDOUT:   } [template]
 // CHECK:STDOUT: }
 // CHECK:STDOUT: }
 // CHECK:STDOUT:
 // CHECK:STDOUT:
 // CHECK:STDOUT: class @Class {
 // CHECK:STDOUT: class @Class {
-// CHECK:STDOUT:   %F: <function> = fn_decl @F [template]
+// CHECK:STDOUT:   %F: <function> = fn_decl @F {
+// CHECK:STDOUT:     %return.var: ref i32 = var <return slot>
+// CHECK:STDOUT:   } [template]
 // CHECK:STDOUT:
 // CHECK:STDOUT:
 // CHECK:STDOUT: !members:
 // CHECK:STDOUT: !members:
 // CHECK:STDOUT:   .F = %F
 // CHECK:STDOUT:   .F = %F

+ 31 - 9
toolchain/check/testdata/class/fail_self.carbon

@@ -62,16 +62,34 @@ fn CallWrongSelf(ws: WrongSelf) {
 // CHECK:STDOUT:
 // CHECK:STDOUT:
 // CHECK:STDOUT: file {
 // CHECK:STDOUT: file {
 // CHECK:STDOUT:   package: <namespace> = namespace {.Class = %Class.decl, .WrongSelf = %WrongSelf.decl, .CallWrongSelf = %CallWrongSelf} [template]
 // CHECK:STDOUT:   package: <namespace> = namespace {.Class = %Class.decl, .WrongSelf = %WrongSelf.decl, .CallWrongSelf = %CallWrongSelf} [template]
-// CHECK:STDOUT:   %Class.decl = class_decl @Class, () [template = constants.%Class]
-// CHECK:STDOUT:   %F: <function> = fn_decl @F.1 [template]
-// CHECK:STDOUT:   %G: <function> = fn_decl @G [template]
-// CHECK:STDOUT:   %WrongSelf.decl = class_decl @WrongSelf, () [template = constants.%WrongSelf]
-// CHECK:STDOUT:   %CallWrongSelf: <function> = fn_decl @CallWrongSelf [template]
+// CHECK:STDOUT:   %Class.decl = class_decl @Class {} [template = constants.%Class]
+// CHECK:STDOUT:   %F: <function> = fn_decl @F.1 {
+// CHECK:STDOUT:     %Class.ref.loc25: type = name_ref Class, %Class.decl [template = constants.%Class]
+// CHECK:STDOUT:     %self.loc25_12.1: Class = param self
+// CHECK:STDOUT:     @F.1.%self: Class = bind_name self, %self.loc25_12.1
+// CHECK:STDOUT:   } [template]
+// CHECK:STDOUT:   %G: <function> = fn_decl @G {
+// CHECK:STDOUT:     %Class.ref.loc28: type = name_ref Class, %Class.decl [template = constants.%Class]
+// CHECK:STDOUT:     @G.%return: ref Class = var <return slot>
+// CHECK:STDOUT:   } [template]
+// CHECK:STDOUT:   %WrongSelf.decl = class_decl @WrongSelf {} [template = constants.%WrongSelf]
+// CHECK:STDOUT:   %CallWrongSelf: <function> = fn_decl @CallWrongSelf {
+// CHECK:STDOUT:     %WrongSelf.ref: type = name_ref WrongSelf, %WrongSelf.decl [template = constants.%WrongSelf]
+// CHECK:STDOUT:     %ws.loc43_18.1: WrongSelf = param ws
+// CHECK:STDOUT:     @CallWrongSelf.%ws: WrongSelf = bind_name ws, %ws.loc43_18.1
+// CHECK:STDOUT:   } [template]
 // CHECK:STDOUT: }
 // CHECK:STDOUT: }
 // CHECK:STDOUT:
 // CHECK:STDOUT:
 // CHECK:STDOUT: class @Class {
 // CHECK:STDOUT: class @Class {
-// CHECK:STDOUT:   %F: <function> = fn_decl @F.1 [template]
-// CHECK:STDOUT:   %G: <function> = fn_decl @G [template]
+// CHECK:STDOUT:   %F: <function> = fn_decl @F.1 {
+// CHECK:STDOUT:     %Class.ref.loc11: type = name_ref Class, file.%Class.decl [template = constants.%Class]
+// CHECK:STDOUT:     %self.loc11_8.1: Class = param self
+// CHECK:STDOUT:     %self.loc11_8.2: Class = bind_name self, %self.loc11_8.1
+// CHECK:STDOUT:   } [template]
+// CHECK:STDOUT:   %G: <function> = fn_decl @G {
+// CHECK:STDOUT:     %Class.ref.loc19: type = name_ref Class, file.%Class.decl [template = constants.%Class]
+// CHECK:STDOUT:     %return.var: ref Class = var <return slot>
+// CHECK:STDOUT:   } [template]
 // CHECK:STDOUT:
 // CHECK:STDOUT:
 // CHECK:STDOUT: !members:
 // CHECK:STDOUT: !members:
 // CHECK:STDOUT:   .F = %F
 // CHECK:STDOUT:   .F = %F
@@ -79,7 +97,11 @@ fn CallWrongSelf(ws: WrongSelf) {
 // CHECK:STDOUT: }
 // CHECK:STDOUT: }
 // CHECK:STDOUT:
 // CHECK:STDOUT:
 // CHECK:STDOUT: class @WrongSelf {
 // CHECK:STDOUT: class @WrongSelf {
-// CHECK:STDOUT:   %F: <function> = fn_decl @F.2 [template]
+// CHECK:STDOUT:   %F: <function> = fn_decl @F.2 {
+// CHECK:STDOUT:     %Class.ref: type = name_ref Class, file.%Class.decl [template = constants.%Class]
+// CHECK:STDOUT:     %self.loc40_8.1: Class = param self
+// CHECK:STDOUT:     %self.loc40_8.2: Class = bind_name self, %self.loc40_8.1
+// CHECK:STDOUT:   } [template]
 // CHECK:STDOUT:
 // CHECK:STDOUT:
 // CHECK:STDOUT: !members:
 // CHECK:STDOUT: !members:
 // CHECK:STDOUT:   .F = %F
 // CHECK:STDOUT:   .F = %F
@@ -100,7 +122,7 @@ fn CallWrongSelf(ws: WrongSelf) {
 // CHECK:STDOUT:   return <error>
 // CHECK:STDOUT:   return <error>
 // CHECK:STDOUT: }
 // CHECK:STDOUT: }
 // CHECK:STDOUT:
 // CHECK:STDOUT:
-// CHECK:STDOUT: fn @F.2[%self: Class]();
+// CHECK:STDOUT: fn @F.2[@WrongSelf.%self.loc40_8.2: Class]();
 // CHECK:STDOUT:
 // CHECK:STDOUT:
 // CHECK:STDOUT: fn @CallWrongSelf(%ws: WrongSelf) {
 // CHECK:STDOUT: fn @CallWrongSelf(%ws: WrongSelf) {
 // CHECK:STDOUT: !entry:
 // CHECK:STDOUT: !entry:

+ 1 - 1
toolchain/check/testdata/class/fail_todo_generic.carbon

@@ -20,7 +20,7 @@ class C[]();
 // CHECK:STDOUT:
 // CHECK:STDOUT:
 // CHECK:STDOUT: file {
 // CHECK:STDOUT: file {
 // CHECK:STDOUT:   package: <namespace> = namespace {.C = %C.decl} [template]
 // CHECK:STDOUT:   package: <namespace> = namespace {.C = %C.decl} [template]
-// CHECK:STDOUT:   %C.decl = class_decl @C, () [template = constants.%C]
+// CHECK:STDOUT:   %C.decl = class_decl @C {} [template = constants.%C]
 // CHECK:STDOUT: }
 // CHECK:STDOUT: }
 // CHECK:STDOUT:
 // CHECK:STDOUT:
 // CHECK:STDOUT: class @C;
 // CHECK:STDOUT: class @C;

+ 18 - 5
toolchain/check/testdata/class/fail_todo_generic_method.carbon

@@ -33,21 +33,34 @@ fn Class(T:! type).F[self: Self](n: T) {}
 // CHECK:STDOUT:
 // CHECK:STDOUT:
 // CHECK:STDOUT: file {
 // CHECK:STDOUT: file {
 // CHECK:STDOUT:   package: <namespace> = namespace {.Class = %Class.decl} [template]
 // CHECK:STDOUT:   package: <namespace> = namespace {.Class = %Class.decl} [template]
-// CHECK:STDOUT:   %Class.decl = class_decl @Class, (<unexpected instref inst+1>, <unexpected instref inst+2>) [template = constants.%Class]
-// CHECK:STDOUT:   %.loc24: <function> = fn_decl @.1 [template]
+// CHECK:STDOUT:   %Class.decl = class_decl @Class {
+// CHECK:STDOUT:     %T.loc10_13.1: type = param T
+// CHECK:STDOUT:     %T.loc10_13.2: type = bind_symbolic_name T, %T.loc10_13.1 [symbolic]
+// CHECK:STDOUT:   } [template = constants.%Class]
+// CHECK:STDOUT:   %.loc24: <function> = fn_decl @.1 {
+// CHECK:STDOUT:     %T.loc24_10.1: type = param T
+// CHECK:STDOUT:     @.1.%T: type = bind_symbolic_name T, %T.loc24_10.1 [symbolic]
+// CHECK:STDOUT:   } [template]
 // CHECK:STDOUT: }
 // CHECK:STDOUT: }
 // CHECK:STDOUT:
 // CHECK:STDOUT:
 // CHECK:STDOUT: class @Class {
 // CHECK:STDOUT: class @Class {
-// CHECK:STDOUT:   %T.ref: type = name_ref T, <unexpected instref inst+2> [symbolic = <unexpected instref inst+2>]
+// CHECK:STDOUT:   %T.ref.loc11: type = name_ref T, file.%T.loc10_13.2 [symbolic = file.%T.loc10_13.2]
 // CHECK:STDOUT:   %.loc11: <unbound element of class Class> = field_decl a, element0 [template]
 // CHECK:STDOUT:   %.loc11: <unbound element of class Class> = field_decl a, element0 [template]
-// CHECK:STDOUT:   %F: <function> = fn_decl @F [template]
+// CHECK:STDOUT:   %F: <function> = fn_decl @F {
+// CHECK:STDOUT:     %Self.ref: type = name_ref Self, constants.%Class [template = constants.%Class]
+// CHECK:STDOUT:     %self.loc12_8.1: Class = param self
+// CHECK:STDOUT:     %self.loc12_8.2: Class = bind_name self, %self.loc12_8.1
+// CHECK:STDOUT:     %T.ref.loc12: type = name_ref T, file.%T.loc10_13.2 [symbolic = file.%T.loc10_13.2]
+// CHECK:STDOUT:     %n.loc12_20.1: T = param n
+// CHECK:STDOUT:     %n.loc12_20.2: T = bind_name n, %n.loc12_20.1
+// CHECK:STDOUT:   } [template]
 // CHECK:STDOUT:
 // CHECK:STDOUT:
 // CHECK:STDOUT: !members:
 // CHECK:STDOUT: !members:
 // CHECK:STDOUT:   .a = %.loc11
 // CHECK:STDOUT:   .a = %.loc11
 // CHECK:STDOUT:   .F = %F
 // CHECK:STDOUT:   .F = %F
 // CHECK:STDOUT: }
 // CHECK:STDOUT: }
 // CHECK:STDOUT:
 // CHECK:STDOUT:
-// CHECK:STDOUT: fn @F[%self: Class](%n: T);
+// CHECK:STDOUT: fn @F[@Class.%self.loc12_8.2: Class](@Class.%n.loc12_20.2: T);
 // CHECK:STDOUT:
 // CHECK:STDOUT:
 // CHECK:STDOUT: fn @.1(%T: type);
 // CHECK:STDOUT: fn @.1(%T: type);
 // CHECK:STDOUT:
 // CHECK:STDOUT:

+ 4 - 2
toolchain/check/testdata/class/fail_todo_import_forward_decl.carbon

@@ -34,7 +34,7 @@ class ForwardDecl {
 // CHECK:STDOUT:
 // CHECK:STDOUT:
 // CHECK:STDOUT: file {
 // CHECK:STDOUT: file {
 // CHECK:STDOUT:   package: <namespace> = namespace {.ForwardDecl = %ForwardDecl.decl} [template]
 // CHECK:STDOUT:   package: <namespace> = namespace {.ForwardDecl = %ForwardDecl.decl} [template]
-// CHECK:STDOUT:   %ForwardDecl.decl = class_decl @ForwardDecl, () [template = constants.%ForwardDecl]
+// CHECK:STDOUT:   %ForwardDecl.decl = class_decl @ForwardDecl {} [template = constants.%ForwardDecl]
 // CHECK:STDOUT: }
 // CHECK:STDOUT: }
 // CHECK:STDOUT:
 // CHECK:STDOUT:
 // CHECK:STDOUT: class @ForwardDecl;
 // CHECK:STDOUT: class @ForwardDecl;
@@ -50,7 +50,9 @@ class ForwardDecl {
 // CHECK:STDOUT: file {
 // CHECK:STDOUT: file {
 // CHECK:STDOUT:   package: <namespace> = namespace {.ForwardDecl = %import_ref} [template]
 // CHECK:STDOUT:   package: <namespace> = namespace {.ForwardDecl = %import_ref} [template]
 // CHECK:STDOUT:   %import_ref: type = import_ref ir1, inst+1, used [template = constants.%ForwardDecl]
 // CHECK:STDOUT:   %import_ref: type = import_ref ir1, inst+1, used [template = constants.%ForwardDecl]
-// CHECK:STDOUT:   %.decl = class_decl @.1, (<unexpected instref inst+2>) [template = constants.%.1]
+// CHECK:STDOUT:   %.decl = class_decl @.1 {
+// CHECK:STDOUT:     %ForwardDecl.decl = class_decl @ForwardDecl {} [template = constants.%ForwardDecl]
+// CHECK:STDOUT:   } [template = constants.%.1]
 // CHECK:STDOUT: }
 // CHECK:STDOUT: }
 // CHECK:STDOUT:
 // CHECK:STDOUT:
 // CHECK:STDOUT: class @ForwardDecl;
 // CHECK:STDOUT: class @ForwardDecl;

+ 10 - 10
toolchain/check/testdata/class/fail_todo_modifiers.carbon

@@ -71,14 +71,14 @@ abstract class Abstract {
 // CHECK:STDOUT:
 // CHECK:STDOUT:
 // CHECK:STDOUT: file {
 // CHECK:STDOUT: file {
 // CHECK:STDOUT:   package: <namespace> = namespace {.Access = %Access.decl, .Base = %Base.decl, .Abstract = %Abstract.decl} [template]
 // CHECK:STDOUT:   package: <namespace> = namespace {.Access = %Access.decl, .Base = %Base.decl, .Abstract = %Abstract.decl} [template]
-// CHECK:STDOUT:   %Access.decl = class_decl @Access, () [template = constants.%Access]
-// CHECK:STDOUT:   %Base.decl = class_decl @Base, () [template = constants.%Base]
-// CHECK:STDOUT:   %Abstract.decl = class_decl @Abstract, () [template = constants.%Abstract]
+// CHECK:STDOUT:   %Access.decl = class_decl @Access {} [template = constants.%Access]
+// CHECK:STDOUT:   %Base.decl = class_decl @Base {} [template = constants.%Base]
+// CHECK:STDOUT:   %Abstract.decl = class_decl @Abstract {} [template = constants.%Abstract]
 // CHECK:STDOUT: }
 // CHECK:STDOUT: }
 // CHECK:STDOUT:
 // CHECK:STDOUT:
 // CHECK:STDOUT: class @Access {
 // CHECK:STDOUT: class @Access {
-// CHECK:STDOUT:   %F: <function> = fn_decl @F [template]
-// CHECK:STDOUT:   %G: <function> = fn_decl @G [template]
+// CHECK:STDOUT:   %F: <function> = fn_decl @F {} [template]
+// CHECK:STDOUT:   %G: <function> = fn_decl @G {} [template]
 // CHECK:STDOUT:   %.loc22: <unbound element of class Access> = field_decl k, element0 [template]
 // CHECK:STDOUT:   %.loc22: <unbound element of class Access> = field_decl k, element0 [template]
 // CHECK:STDOUT:   %.loc27: <unbound element of class Access> = field_decl l, element1 [template]
 // CHECK:STDOUT:   %.loc27: <unbound element of class Access> = field_decl l, element1 [template]
 // CHECK:STDOUT:
 // CHECK:STDOUT:
@@ -90,8 +90,8 @@ abstract class Abstract {
 // CHECK:STDOUT: }
 // CHECK:STDOUT: }
 // CHECK:STDOUT:
 // CHECK:STDOUT:
 // CHECK:STDOUT: class @Base {
 // CHECK:STDOUT: class @Base {
-// CHECK:STDOUT:   %H: <function> = fn_decl @H [template]
-// CHECK:STDOUT:   %I: <function> = fn_decl @I [template]
+// CHECK:STDOUT:   %H: <function> = fn_decl @H {} [template]
+// CHECK:STDOUT:   %I: <function> = fn_decl @I {} [template]
 // CHECK:STDOUT:
 // CHECK:STDOUT:
 // CHECK:STDOUT: !members:
 // CHECK:STDOUT: !members:
 // CHECK:STDOUT:   .H = %H
 // CHECK:STDOUT:   .H = %H
@@ -99,9 +99,9 @@ abstract class Abstract {
 // CHECK:STDOUT: }
 // CHECK:STDOUT: }
 // CHECK:STDOUT:
 // CHECK:STDOUT:
 // CHECK:STDOUT: class @Abstract {
 // CHECK:STDOUT: class @Abstract {
-// CHECK:STDOUT:   %J: <function> = fn_decl @J [template]
-// CHECK:STDOUT:   %K: <function> = fn_decl @K [template]
-// CHECK:STDOUT:   %L: <function> = fn_decl @L [template]
+// CHECK:STDOUT:   %J: <function> = fn_decl @J {} [template]
+// CHECK:STDOUT:   %K: <function> = fn_decl @K {} [template]
+// CHECK:STDOUT:   %L: <function> = fn_decl @L {} [template]
 // CHECK:STDOUT:
 // CHECK:STDOUT:
 // CHECK:STDOUT: !members:
 // CHECK:STDOUT: !members:
 // CHECK:STDOUT:   .J = %J
 // CHECK:STDOUT:   .J = %J

+ 7 - 3
toolchain/check/testdata/class/fail_unbound_field.carbon

@@ -31,13 +31,17 @@ fn G() -> i32 {
 // CHECK:STDOUT:
 // CHECK:STDOUT:
 // CHECK:STDOUT: file {
 // CHECK:STDOUT: file {
 // CHECK:STDOUT:   package: <namespace> = namespace {.Class = %Class.decl, .G = %G} [template]
 // CHECK:STDOUT:   package: <namespace> = namespace {.Class = %Class.decl, .G = %G} [template]
-// CHECK:STDOUT:   %Class.decl = class_decl @Class, () [template = constants.%Class]
-// CHECK:STDOUT:   %G: <function> = fn_decl @G [template]
+// CHECK:STDOUT:   %Class.decl = class_decl @Class {} [template = constants.%Class]
+// CHECK:STDOUT:   %G: <function> = fn_decl @G {
+// CHECK:STDOUT:     %return.var: ref i32 = var <return slot>
+// CHECK:STDOUT:   } [template]
 // CHECK:STDOUT: }
 // CHECK:STDOUT: }
 // CHECK:STDOUT:
 // CHECK:STDOUT:
 // CHECK:STDOUT: class @Class {
 // CHECK:STDOUT: class @Class {
 // CHECK:STDOUT:   %.loc8: <unbound element of class Class> = field_decl field, element0 [template]
 // CHECK:STDOUT:   %.loc8: <unbound element of class Class> = field_decl field, element0 [template]
-// CHECK:STDOUT:   %F: <function> = fn_decl @F [template]
+// CHECK:STDOUT:   %F: <function> = fn_decl @F {
+// CHECK:STDOUT:     %return.var: ref i32 = var <return slot>
+// CHECK:STDOUT:   } [template]
 // CHECK:STDOUT:
 // CHECK:STDOUT:
 // CHECK:STDOUT: !members:
 // CHECK:STDOUT: !members:
 // CHECK:STDOUT:   .field = %.loc8
 // CHECK:STDOUT:   .field = %.loc8

+ 7 - 2
toolchain/check/testdata/class/fail_unknown_member.carbon

@@ -27,8 +27,13 @@ fn G(c: Class) -> i32 {
 // CHECK:STDOUT:
 // CHECK:STDOUT:
 // CHECK:STDOUT: file {
 // CHECK:STDOUT: file {
 // CHECK:STDOUT:   package: <namespace> = namespace {.Class = %Class.decl, .G = %G} [template]
 // CHECK:STDOUT:   package: <namespace> = namespace {.Class = %Class.decl, .G = %G} [template]
-// CHECK:STDOUT:   %Class.decl = class_decl @Class, () [template = constants.%Class]
-// CHECK:STDOUT:   %G: <function> = fn_decl @G [template]
+// CHECK:STDOUT:   %Class.decl = class_decl @Class {} [template = constants.%Class]
+// CHECK:STDOUT:   %G: <function> = fn_decl @G {
+// CHECK:STDOUT:     %Class.ref: type = name_ref Class, %Class.decl [template = constants.%Class]
+// CHECK:STDOUT:     %c.loc11_6.1: Class = param c
+// CHECK:STDOUT:     @G.%c: Class = bind_name c, %c.loc11_6.1
+// CHECK:STDOUT:     %return.var: ref i32 = var <return slot>
+// CHECK:STDOUT:   } [template]
 // CHECK:STDOUT: }
 // CHECK:STDOUT: }
 // CHECK:STDOUT:
 // CHECK:STDOUT:
 // CHECK:STDOUT: class @Class {
 // CHECK:STDOUT: class @Class {

+ 2 - 2
toolchain/check/testdata/class/field_access.carbon

@@ -30,8 +30,8 @@ fn Run() {
 // CHECK:STDOUT:
 // CHECK:STDOUT:
 // CHECK:STDOUT: file {
 // CHECK:STDOUT: file {
 // CHECK:STDOUT:   package: <namespace> = namespace {.Class = %Class.decl, .Run = %Run} [template]
 // CHECK:STDOUT:   package: <namespace> = namespace {.Class = %Class.decl, .Run = %Run} [template]
-// CHECK:STDOUT:   %Class.decl = class_decl @Class, () [template = constants.%Class]
-// CHECK:STDOUT:   %Run: <function> = fn_decl @Run [template]
+// CHECK:STDOUT:   %Class.decl = class_decl @Class {} [template = constants.%Class]
+// CHECK:STDOUT:   %Run: <function> = fn_decl @Run {} [template]
 // CHECK:STDOUT: }
 // CHECK:STDOUT: }
 // CHECK:STDOUT:
 // CHECK:STDOUT:
 // CHECK:STDOUT: class @Class {
 // CHECK:STDOUT: class @Class {

+ 2 - 2
toolchain/check/testdata/class/field_access_in_value.carbon

@@ -31,8 +31,8 @@ fn Test() {
 // CHECK:STDOUT:
 // CHECK:STDOUT:
 // CHECK:STDOUT: file {
 // CHECK:STDOUT: file {
 // CHECK:STDOUT:   package: <namespace> = namespace {.Class = %Class.decl, .Test = %Test} [template]
 // CHECK:STDOUT:   package: <namespace> = namespace {.Class = %Class.decl, .Test = %Test} [template]
-// CHECK:STDOUT:   %Class.decl = class_decl @Class, () [template = constants.%Class]
-// CHECK:STDOUT:   %Test: <function> = fn_decl @Test [template]
+// CHECK:STDOUT:   %Class.decl = class_decl @Class {} [template = constants.%Class]
+// CHECK:STDOUT:   %Test: <function> = fn_decl @Test {} [template]
 // CHECK:STDOUT: }
 // CHECK:STDOUT: }
 // CHECK:STDOUT:
 // CHECK:STDOUT:
 // CHECK:STDOUT: class @Class {
 // CHECK:STDOUT: class @Class {

+ 10 - 2
toolchain/check/testdata/class/forward_declared.carbon

@@ -17,8 +17,16 @@ fn F(p: Class*) -> Class* { return p; }
 // CHECK:STDOUT:
 // CHECK:STDOUT:
 // CHECK:STDOUT: file {
 // CHECK:STDOUT: file {
 // CHECK:STDOUT:   package: <namespace> = namespace {.Class = %Class.decl, .F = %F} [template]
 // CHECK:STDOUT:   package: <namespace> = namespace {.Class = %Class.decl, .F = %F} [template]
-// CHECK:STDOUT:   %Class.decl = class_decl @Class, () [template = constants.%Class]
-// CHECK:STDOUT:   %F: <function> = fn_decl @F [template]
+// CHECK:STDOUT:   %Class.decl = class_decl @Class {} [template = constants.%Class]
+// CHECK:STDOUT:   %F: <function> = fn_decl @F {
+// CHECK:STDOUT:     %Class.ref.loc9_9: type = name_ref Class, %Class.decl [template = constants.%Class]
+// CHECK:STDOUT:     %.loc9_14: type = ptr_type Class [template = constants.%.1]
+// CHECK:STDOUT:     %p.loc9_6.1: Class* = param p
+// CHECK:STDOUT:     @F.%p: Class* = bind_name p, %p.loc9_6.1
+// CHECK:STDOUT:     %Class.ref.loc9_20: type = name_ref Class, %Class.decl [template = constants.%Class]
+// CHECK:STDOUT:     %.loc9_25: type = ptr_type Class [template = constants.%.1]
+// CHECK:STDOUT:     %return.var: ref Class* = var <return slot>
+// CHECK:STDOUT:   } [template]
 // CHECK:STDOUT: }
 // CHECK:STDOUT: }
 // CHECK:STDOUT:
 // CHECK:STDOUT:
 // CHECK:STDOUT: class @Class;
 // CHECK:STDOUT: class @Class;

+ 24 - 14
toolchain/check/testdata/class/import.carbon

@@ -60,11 +60,11 @@ fn Run() {
 // CHECK:STDOUT:
 // CHECK:STDOUT:
 // CHECK:STDOUT: file {
 // CHECK:STDOUT: file {
 // CHECK:STDOUT:   package: <namespace> = namespace {.Empty = %Empty.decl, .Field = %Field.decl, .ForwardDeclared = %ForwardDeclared.decl.loc11, .Incomplete = %Incomplete.decl} [template]
 // CHECK:STDOUT:   package: <namespace> = namespace {.Empty = %Empty.decl, .Field = %Field.decl, .ForwardDeclared = %ForwardDeclared.decl.loc11, .Incomplete = %Incomplete.decl} [template]
-// CHECK:STDOUT:   %Empty.decl = class_decl @Empty, () [template = constants.%Empty]
-// CHECK:STDOUT:   %Field.decl = class_decl @Field, () [template = constants.%Field]
-// CHECK:STDOUT:   %ForwardDeclared.decl.loc11 = class_decl @ForwardDeclared, () [template = constants.%ForwardDeclared]
-// CHECK:STDOUT:   %ForwardDeclared.decl.loc13 = class_decl @ForwardDeclared, () [template = constants.%ForwardDeclared]
-// CHECK:STDOUT:   %Incomplete.decl = class_decl @Incomplete, () [template = constants.%Incomplete]
+// CHECK:STDOUT:   %Empty.decl = class_decl @Empty {} [template = constants.%Empty]
+// CHECK:STDOUT:   %Field.decl = class_decl @Field {} [template = constants.%Field]
+// CHECK:STDOUT:   %ForwardDeclared.decl.loc11 = class_decl @ForwardDeclared {} [template = constants.%ForwardDeclared]
+// CHECK:STDOUT:   %ForwardDeclared.decl.loc13 = class_decl @ForwardDeclared {} [template = constants.%ForwardDeclared]
+// CHECK:STDOUT:   %Incomplete.decl = class_decl @Incomplete {} [template = constants.%Incomplete]
 // CHECK:STDOUT: }
 // CHECK:STDOUT: }
 // CHECK:STDOUT:
 // CHECK:STDOUT:
 // CHECK:STDOUT: class @Empty {
 // CHECK:STDOUT: class @Empty {
@@ -80,8 +80,18 @@ fn Run() {
 // CHECK:STDOUT: }
 // CHECK:STDOUT: }
 // CHECK:STDOUT:
 // CHECK:STDOUT:
 // CHECK:STDOUT: class @ForwardDeclared {
 // CHECK:STDOUT: class @ForwardDeclared {
-// CHECK:STDOUT:   %F: <function> = fn_decl @F [template]
-// CHECK:STDOUT:   %G: <function> = fn_decl @G [template]
+// CHECK:STDOUT:   %F: <function> = fn_decl @F {
+// CHECK:STDOUT:     %Self.ref.loc14: type = name_ref Self, constants.%ForwardDeclared [template = constants.%ForwardDeclared]
+// CHECK:STDOUT:     %self.loc14_8.1: ForwardDeclared = param self
+// CHECK:STDOUT:     %self.loc14_8.2: ForwardDeclared = bind_name self, %self.loc14_8.1
+// CHECK:STDOUT:   } [template]
+// CHECK:STDOUT:   %G: <function> = fn_decl @G {
+// CHECK:STDOUT:     %Self.ref.loc15: type = name_ref Self, constants.%ForwardDeclared [template = constants.%ForwardDeclared]
+// CHECK:STDOUT:     %.loc15_23: type = ptr_type ForwardDeclared [template = constants.%.4]
+// CHECK:STDOUT:     %self.loc15_13.1: ForwardDeclared* = param self
+// CHECK:STDOUT:     %self.loc15_13.3: ForwardDeclared* = bind_name self, %self.loc15_13.1
+// CHECK:STDOUT:     %.loc15_8: ForwardDeclared* = addr_pattern %self.loc15_13.3
+// CHECK:STDOUT:   } [template]
 // CHECK:STDOUT:
 // CHECK:STDOUT:
 // CHECK:STDOUT: !members:
 // CHECK:STDOUT: !members:
 // CHECK:STDOUT:   .F = %F
 // CHECK:STDOUT:   .F = %F
@@ -90,9 +100,9 @@ fn Run() {
 // CHECK:STDOUT:
 // CHECK:STDOUT:
 // CHECK:STDOUT: class @Incomplete;
 // CHECK:STDOUT: class @Incomplete;
 // CHECK:STDOUT:
 // CHECK:STDOUT:
-// CHECK:STDOUT: fn @F[%self: ForwardDeclared]();
+// CHECK:STDOUT: fn @F[@ForwardDeclared.%self.loc14_8.2: ForwardDeclared]();
 // CHECK:STDOUT:
 // CHECK:STDOUT:
-// CHECK:STDOUT: fn @G[addr %self: ForwardDeclared*]();
+// CHECK:STDOUT: fn @G[addr @ForwardDeclared.%self.loc15_13.3: ForwardDeclared*]();
 // CHECK:STDOUT:
 // CHECK:STDOUT:
 // CHECK:STDOUT: --- b.carbon
 // CHECK:STDOUT: --- b.carbon
 // CHECK:STDOUT:
 // CHECK:STDOUT:
@@ -122,7 +132,7 @@ fn Run() {
 // CHECK:STDOUT:   %import_ref.2: type = import_ref ir1, inst+4, used [template = constants.%Field]
 // CHECK:STDOUT:   %import_ref.2: type = import_ref ir1, inst+4, used [template = constants.%Field]
 // CHECK:STDOUT:   %import_ref.3: type = import_ref ir1, inst+11, used [template = constants.%ForwardDeclared]
 // CHECK:STDOUT:   %import_ref.3: type = import_ref ir1, inst+11, used [template = constants.%ForwardDeclared]
 // CHECK:STDOUT:   %import_ref.4: type = import_ref ir1, inst+25, used [template = constants.%Incomplete]
 // CHECK:STDOUT:   %import_ref.4: type = import_ref ir1, inst+25, used [template = constants.%Incomplete]
-// CHECK:STDOUT:   %Run: <function> = fn_decl @Run [template]
+// CHECK:STDOUT:   %Run: <function> = fn_decl @Run {} [template]
 // CHECK:STDOUT: }
 // CHECK:STDOUT: }
 // CHECK:STDOUT:
 // CHECK:STDOUT:
 // CHECK:STDOUT: class @Empty {
 // CHECK:STDOUT: class @Empty {
@@ -150,7 +160,7 @@ fn Run() {
 // CHECK:STDOUT:
 // CHECK:STDOUT:
 // CHECK:STDOUT: fn @Run() {
 // CHECK:STDOUT: fn @Run() {
 // CHECK:STDOUT: !entry:
 // CHECK:STDOUT: !entry:
-// CHECK:STDOUT:   %Empty.decl = class_decl @Empty, () [template = constants.%Empty]
+// CHECK:STDOUT:   %Empty.decl = class_decl @Empty {} [template = constants.%Empty]
 // CHECK:STDOUT:   %Empty.ref: type = name_ref Empty, file.%import_ref.1 [template = constants.%Empty]
 // CHECK:STDOUT:   %Empty.ref: type = name_ref Empty, file.%import_ref.1 [template = constants.%Empty]
 // CHECK:STDOUT:   %a.var: ref Empty = var a
 // CHECK:STDOUT:   %a.var: ref Empty = var a
 // CHECK:STDOUT:   %a: ref Empty = bind_name a, %a.var
 // CHECK:STDOUT:   %a: ref Empty = bind_name a, %a.var
@@ -158,7 +168,7 @@ fn Run() {
 // CHECK:STDOUT:   %.loc7_19.2: init Empty = class_init (), %a.var [template = constants.%.4]
 // CHECK:STDOUT:   %.loc7_19.2: init Empty = class_init (), %a.var [template = constants.%.4]
 // CHECK:STDOUT:   %.loc7_19.3: init Empty = converted %.loc7_19.1, %.loc7_19.2 [template = constants.%.4]
 // CHECK:STDOUT:   %.loc7_19.3: init Empty = converted %.loc7_19.1, %.loc7_19.2 [template = constants.%.4]
 // CHECK:STDOUT:   assign %a.var, %.loc7_19.3
 // CHECK:STDOUT:   assign %a.var, %.loc7_19.3
-// CHECK:STDOUT:   %Field.decl = class_decl @Field, () [template = constants.%Field]
+// CHECK:STDOUT:   %Field.decl = class_decl @Field {} [template = constants.%Field]
 // CHECK:STDOUT:   %Field.ref: type = name_ref Field, file.%import_ref.2 [template = constants.%Field]
 // CHECK:STDOUT:   %Field.ref: type = name_ref Field, file.%import_ref.2 [template = constants.%Field]
 // CHECK:STDOUT:   %b.var: ref Field = var b
 // CHECK:STDOUT:   %b.var: ref Field = var b
 // CHECK:STDOUT:   %b: ref Field = bind_name b, %b.var
 // CHECK:STDOUT:   %b: ref Field = bind_name b, %b.var
@@ -173,7 +183,7 @@ fn Run() {
 // CHECK:STDOUT:   %.loc10_4: ref i32 = class_element_access %b.ref, element0
 // CHECK:STDOUT:   %.loc10_4: ref i32 = class_element_access %b.ref, element0
 // CHECK:STDOUT:   %.loc10_9: i32 = int_literal 2 [template = constants.%.10]
 // CHECK:STDOUT:   %.loc10_9: i32 = int_literal 2 [template = constants.%.10]
 // CHECK:STDOUT:   assign %.loc10_4, %.loc10_9
 // CHECK:STDOUT:   assign %.loc10_4, %.loc10_9
-// CHECK:STDOUT:   %ForwardDeclared.decl = class_decl @ForwardDeclared, () [template = constants.%ForwardDeclared]
+// CHECK:STDOUT:   %ForwardDeclared.decl = class_decl @ForwardDeclared {} [template = constants.%ForwardDeclared]
 // CHECK:STDOUT:   %ForwardDeclared.ref.loc12: type = name_ref ForwardDeclared, file.%import_ref.3 [template = constants.%ForwardDeclared]
 // CHECK:STDOUT:   %ForwardDeclared.ref.loc12: type = name_ref ForwardDeclared, file.%import_ref.3 [template = constants.%ForwardDeclared]
 // CHECK:STDOUT:   %c.var: ref ForwardDeclared = var c
 // CHECK:STDOUT:   %c.var: ref ForwardDeclared = var c
 // CHECK:STDOUT:   %c: ref ForwardDeclared = bind_name c, %c.var
 // CHECK:STDOUT:   %c: ref ForwardDeclared = bind_name c, %c.var
@@ -196,7 +206,7 @@ fn Run() {
 // CHECK:STDOUT:   %c.ref.loc16: ref ForwardDeclared = name_ref c, %c
 // CHECK:STDOUT:   %c.ref.loc16: ref ForwardDeclared = name_ref c, %c
 // CHECK:STDOUT:   %.loc16_29: ForwardDeclared* = addr_of %c.ref.loc16
 // CHECK:STDOUT:   %.loc16_29: ForwardDeclared* = addr_of %c.ref.loc16
 // CHECK:STDOUT:   assign %d.var, %.loc16_29
 // CHECK:STDOUT:   assign %d.var, %.loc16_29
-// CHECK:STDOUT:   %Incomplete.decl = class_decl @Incomplete, () [template = constants.%Incomplete]
+// CHECK:STDOUT:   %Incomplete.decl = class_decl @Incomplete {} [template = constants.%Incomplete]
 // CHECK:STDOUT:   %Incomplete.ref: type = name_ref Incomplete, file.%import_ref.4 [template = constants.%Incomplete]
 // CHECK:STDOUT:   %Incomplete.ref: type = name_ref Incomplete, file.%import_ref.4 [template = constants.%Incomplete]
 // CHECK:STDOUT:   %.loc18: type = ptr_type Incomplete [template = constants.%.13]
 // CHECK:STDOUT:   %.loc18: type = ptr_type Incomplete [template = constants.%.13]
 // CHECK:STDOUT:   %e.var: ref Incomplete* = var e
 // CHECK:STDOUT:   %e.var: ref Incomplete* = var e

+ 17 - 9
toolchain/check/testdata/class/import_base.carbon

@@ -46,13 +46,21 @@ fn Run() {
 // CHECK:STDOUT:
 // CHECK:STDOUT:
 // CHECK:STDOUT: file {
 // CHECK:STDOUT: file {
 // CHECK:STDOUT:   package: <namespace> = namespace {.Base = %Base.decl, .Child = %Child.decl} [template]
 // CHECK:STDOUT:   package: <namespace> = namespace {.Base = %Base.decl, .Child = %Child.decl} [template]
-// CHECK:STDOUT:   %Base.decl = class_decl @Base, () [template = constants.%Base]
-// CHECK:STDOUT:   %Child.decl = class_decl @Child, () [template = constants.%Child]
+// CHECK:STDOUT:   %Base.decl = class_decl @Base {} [template = constants.%Base]
+// CHECK:STDOUT:   %Child.decl = class_decl @Child {} [template = constants.%Child]
 // CHECK:STDOUT: }
 // CHECK:STDOUT: }
 // CHECK:STDOUT:
 // CHECK:STDOUT:
 // CHECK:STDOUT: class @Base {
 // CHECK:STDOUT: class @Base {
-// CHECK:STDOUT:   %F: <function> = fn_decl @F [template]
-// CHECK:STDOUT:   %Unused: <function> = fn_decl @Unused [template]
+// CHECK:STDOUT:   %F: <function> = fn_decl @F {
+// CHECK:STDOUT:     %Self.ref.loc5: type = name_ref Self, constants.%Base [template = constants.%Base]
+// CHECK:STDOUT:     %self.loc5_8.1: Base = param self
+// CHECK:STDOUT:     %self.loc5_8.2: Base = bind_name self, %self.loc5_8.1
+// CHECK:STDOUT:   } [template]
+// CHECK:STDOUT:   %Unused: <function> = fn_decl @Unused {
+// CHECK:STDOUT:     %Self.ref.loc6: type = name_ref Self, constants.%Base [template = constants.%Base]
+// CHECK:STDOUT:     %self.loc6_13.1: Base = param self
+// CHECK:STDOUT:     %self.loc6_13.2: Base = bind_name self, %self.loc6_13.1
+// CHECK:STDOUT:   } [template]
 // CHECK:STDOUT:   %.loc8: <unbound element of class Base> = field_decl x, element0 [template]
 // CHECK:STDOUT:   %.loc8: <unbound element of class Base> = field_decl x, element0 [template]
 // CHECK:STDOUT:   %.loc9: <unbound element of class Base> = field_decl unused, element1 [template]
 // CHECK:STDOUT:   %.loc9: <unbound element of class Base> = field_decl unused, element1 [template]
 // CHECK:STDOUT:
 // CHECK:STDOUT:
@@ -72,9 +80,9 @@ fn Run() {
 // CHECK:STDOUT:   extend name_scope1
 // CHECK:STDOUT:   extend name_scope1
 // CHECK:STDOUT: }
 // CHECK:STDOUT: }
 // CHECK:STDOUT:
 // CHECK:STDOUT:
-// CHECK:STDOUT: fn @F[%self: Base]();
+// CHECK:STDOUT: fn @F[@Base.%self.loc5_8.2: Base]();
 // CHECK:STDOUT:
 // CHECK:STDOUT:
-// CHECK:STDOUT: fn @Unused[%self: Base]();
+// CHECK:STDOUT: fn @Unused[@Base.%self.loc6_13.2: Base]();
 // CHECK:STDOUT:
 // CHECK:STDOUT:
 // CHECK:STDOUT: --- b.carbon
 // CHECK:STDOUT: --- b.carbon
 // CHECK:STDOUT:
 // CHECK:STDOUT:
@@ -101,7 +109,7 @@ fn Run() {
 // CHECK:STDOUT:   package: <namespace> = namespace {.Base = %import_ref.1, .Child = %import_ref.2, .Run = %Run} [template]
 // CHECK:STDOUT:   package: <namespace> = namespace {.Base = %import_ref.1, .Child = %import_ref.2, .Run = %Run} [template]
 // CHECK:STDOUT:   %import_ref.1 = import_ref ir1, inst+1, unused
 // CHECK:STDOUT:   %import_ref.1 = import_ref ir1, inst+1, unused
 // CHECK:STDOUT:   %import_ref.2: type = import_ref ir1, inst+19, used [template = constants.%Child]
 // CHECK:STDOUT:   %import_ref.2: type = import_ref ir1, inst+19, used [template = constants.%Child]
-// CHECK:STDOUT:   %Run: <function> = fn_decl @Run [template]
+// CHECK:STDOUT:   %Run: <function> = fn_decl @Run {} [template]
 // CHECK:STDOUT: }
 // CHECK:STDOUT: }
 // CHECK:STDOUT:
 // CHECK:STDOUT:
 // CHECK:STDOUT: class @Child {
 // CHECK:STDOUT: class @Child {
@@ -127,8 +135,8 @@ fn Run() {
 // CHECK:STDOUT:
 // CHECK:STDOUT:
 // CHECK:STDOUT: fn @Run() {
 // CHECK:STDOUT: fn @Run() {
 // CHECK:STDOUT: !entry:
 // CHECK:STDOUT: !entry:
-// CHECK:STDOUT:   %Child.decl = class_decl @Child, () [template = constants.%Child]
-// CHECK:STDOUT:   %Base.decl = class_decl @Base, () [template = constants.%Base]
+// CHECK:STDOUT:   %Child.decl = class_decl @Child {} [template = constants.%Child]
+// CHECK:STDOUT:   %Base.decl = class_decl @Base {} [template = constants.%Base]
 // CHECK:STDOUT:   %Child.ref: type = name_ref Child, file.%import_ref.2 [template = constants.%Child]
 // CHECK:STDOUT:   %Child.ref: type = name_ref Child, file.%import_ref.2 [template = constants.%Child]
 // CHECK:STDOUT:   %a.var: ref Child = var a
 // CHECK:STDOUT:   %a.var: ref Child = var a
 // CHECK:STDOUT:   %a: ref Child = bind_name a, %a.var
 // CHECK:STDOUT:   %a: ref Child = bind_name a, %a.var

+ 3 - 3
toolchain/check/testdata/class/import_member_cycle.carbon

@@ -33,7 +33,7 @@ fn Run() {
 // CHECK:STDOUT:
 // CHECK:STDOUT:
 // CHECK:STDOUT: file {
 // CHECK:STDOUT: file {
 // CHECK:STDOUT:   package: <namespace> = namespace {.Cycle = %Cycle.decl} [template]
 // CHECK:STDOUT:   package: <namespace> = namespace {.Cycle = %Cycle.decl} [template]
-// CHECK:STDOUT:   %Cycle.decl = class_decl @Cycle, () [template = constants.%Cycle]
+// CHECK:STDOUT:   %Cycle.decl = class_decl @Cycle {} [template = constants.%Cycle]
 // CHECK:STDOUT: }
 // CHECK:STDOUT: }
 // CHECK:STDOUT:
 // CHECK:STDOUT:
 // CHECK:STDOUT: class @Cycle {
 // CHECK:STDOUT: class @Cycle {
@@ -56,7 +56,7 @@ fn Run() {
 // CHECK:STDOUT: file {
 // CHECK:STDOUT: file {
 // CHECK:STDOUT:   package: <namespace> = namespace {.Cycle = %import_ref, .Run = %Run} [template]
 // CHECK:STDOUT:   package: <namespace> = namespace {.Cycle = %import_ref, .Run = %Run} [template]
 // CHECK:STDOUT:   %import_ref: type = import_ref ir1, inst+1, used [template = constants.%Cycle]
 // CHECK:STDOUT:   %import_ref: type = import_ref ir1, inst+1, used [template = constants.%Cycle]
-// CHECK:STDOUT:   %Run: <function> = fn_decl @Run [template]
+// CHECK:STDOUT:   %Run: <function> = fn_decl @Run {} [template]
 // CHECK:STDOUT: }
 // CHECK:STDOUT: }
 // CHECK:STDOUT:
 // CHECK:STDOUT:
 // CHECK:STDOUT: class @Cycle {
 // CHECK:STDOUT: class @Cycle {
@@ -68,7 +68,7 @@ fn Run() {
 // CHECK:STDOUT:
 // CHECK:STDOUT:
 // CHECK:STDOUT: fn @Run() {
 // CHECK:STDOUT: fn @Run() {
 // CHECK:STDOUT: !entry:
 // CHECK:STDOUT: !entry:
-// CHECK:STDOUT:   %Cycle.decl = class_decl @Cycle, () [template = constants.%Cycle]
+// CHECK:STDOUT:   %Cycle.decl = class_decl @Cycle {} [template = constants.%Cycle]
 // CHECK:STDOUT:   %Cycle.ref: type = name_ref Cycle, file.%import_ref [template = constants.%Cycle]
 // CHECK:STDOUT:   %Cycle.ref: type = name_ref Cycle, file.%import_ref [template = constants.%Cycle]
 // CHECK:STDOUT:   %.loc7: type = ptr_type Cycle [template = constants.%.1]
 // CHECK:STDOUT:   %.loc7: type = ptr_type Cycle [template = constants.%.1]
 // CHECK:STDOUT:   %a.var: ref Cycle* = var a
 // CHECK:STDOUT:   %a.var: ref Cycle* = var a

+ 4 - 4
toolchain/check/testdata/class/import_struct_cyle.carbon

@@ -39,13 +39,13 @@ fn Run() {
 // CHECK:STDOUT:
 // CHECK:STDOUT:
 // CHECK:STDOUT: file {
 // CHECK:STDOUT: file {
 // CHECK:STDOUT:   package: <namespace> = namespace {.Cycle = %Cycle.decl.loc4, .a = %a} [template]
 // CHECK:STDOUT:   package: <namespace> = namespace {.Cycle = %Cycle.decl.loc4, .a = %a} [template]
-// CHECK:STDOUT:   %Cycle.decl.loc4 = class_decl @Cycle, () [template = constants.%Cycle]
+// CHECK:STDOUT:   %Cycle.decl.loc4 = class_decl @Cycle {} [template = constants.%Cycle]
 // CHECK:STDOUT:   %Cycle.ref: type = name_ref Cycle, %Cycle.decl.loc4 [template = constants.%Cycle]
 // CHECK:STDOUT:   %Cycle.ref: type = name_ref Cycle, %Cycle.decl.loc4 [template = constants.%Cycle]
 // CHECK:STDOUT:   %.loc6_18: type = ptr_type Cycle [template = constants.%.1]
 // CHECK:STDOUT:   %.loc6_18: type = ptr_type Cycle [template = constants.%.1]
 // CHECK:STDOUT:   %.loc6_19: type = struct_type {.b: Cycle*} [template = constants.%.2]
 // CHECK:STDOUT:   %.loc6_19: type = struct_type {.b: Cycle*} [template = constants.%.2]
 // CHECK:STDOUT:   %a.var: ref {.b: Cycle*} = var a
 // CHECK:STDOUT:   %a.var: ref {.b: Cycle*} = var a
 // CHECK:STDOUT:   %a: ref {.b: Cycle*} = bind_name a, %a.var
 // CHECK:STDOUT:   %a: ref {.b: Cycle*} = bind_name a, %a.var
-// CHECK:STDOUT:   %Cycle.decl.loc8 = class_decl @Cycle, () [template = constants.%Cycle]
+// CHECK:STDOUT:   %Cycle.decl.loc8 = class_decl @Cycle {} [template = constants.%Cycle]
 // CHECK:STDOUT: }
 // CHECK:STDOUT: }
 // CHECK:STDOUT:
 // CHECK:STDOUT:
 // CHECK:STDOUT: class @Cycle {
 // CHECK:STDOUT: class @Cycle {
@@ -73,7 +73,7 @@ fn Run() {
 // CHECK:STDOUT:   package: <namespace> = namespace {.Cycle = %import_ref.1, .a = %import_ref.2, .Run = %Run} [template]
 // CHECK:STDOUT:   package: <namespace> = namespace {.Cycle = %import_ref.1, .a = %import_ref.2, .Run = %Run} [template]
 // CHECK:STDOUT:   %import_ref.1 = import_ref ir1, inst+1, unused
 // CHECK:STDOUT:   %import_ref.1 = import_ref ir1, inst+1, unused
 // CHECK:STDOUT:   %import_ref.2: ref {.b: Cycle*} = import_ref ir1, inst+11, used
 // CHECK:STDOUT:   %import_ref.2: ref {.b: Cycle*} = import_ref ir1, inst+11, used
-// CHECK:STDOUT:   %Run: <function> = fn_decl @Run [template]
+// CHECK:STDOUT:   %Run: <function> = fn_decl @Run {} [template]
 // CHECK:STDOUT: }
 // CHECK:STDOUT: }
 // CHECK:STDOUT:
 // CHECK:STDOUT:
 // CHECK:STDOUT: class @Cycle {
 // CHECK:STDOUT: class @Cycle {
@@ -85,7 +85,7 @@ fn Run() {
 // CHECK:STDOUT:
 // CHECK:STDOUT:
 // CHECK:STDOUT: fn @Run() {
 // CHECK:STDOUT: fn @Run() {
 // CHECK:STDOUT: !entry:
 // CHECK:STDOUT: !entry:
-// CHECK:STDOUT:   %Cycle.decl = class_decl @Cycle, () [template = constants.%Cycle]
+// CHECK:STDOUT:   %Cycle.decl = class_decl @Cycle {} [template = constants.%Cycle]
 // CHECK:STDOUT:   %a.ref.loc7_3: ref {.b: Cycle*} = name_ref a, file.%import_ref.2
 // CHECK:STDOUT:   %a.ref.loc7_3: ref {.b: Cycle*} = name_ref a, file.%import_ref.2
 // CHECK:STDOUT:   %.loc7_4: ref Cycle* = struct_access %a.ref.loc7_3, element0
 // CHECK:STDOUT:   %.loc7_4: ref Cycle* = struct_access %a.ref.loc7_3, element0
 // CHECK:STDOUT:   %a.ref.loc7_11: ref {.b: Cycle*} = name_ref a, file.%import_ref.2
 // CHECK:STDOUT:   %a.ref.loc7_11: ref {.b: Cycle*} = name_ref a, file.%import_ref.2

+ 21 - 3
toolchain/check/testdata/class/init.carbon

@@ -31,9 +31,27 @@ fn MakeReorder(n: i32, next: Class*) -> Class {
 // CHECK:STDOUT:
 // CHECK:STDOUT:
 // CHECK:STDOUT: file {
 // CHECK:STDOUT: file {
 // CHECK:STDOUT:   package: <namespace> = namespace {.Class = %Class.decl, .Make = %Make, .MakeReorder = %MakeReorder} [template]
 // CHECK:STDOUT:   package: <namespace> = namespace {.Class = %Class.decl, .Make = %Make, .MakeReorder = %MakeReorder} [template]
-// CHECK:STDOUT:   %Class.decl = class_decl @Class, () [template = constants.%Class]
-// CHECK:STDOUT:   %Make: <function> = fn_decl @Make [template]
-// CHECK:STDOUT:   %MakeReorder: <function> = fn_decl @MakeReorder [template]
+// CHECK:STDOUT:   %Class.decl = class_decl @Class {} [template = constants.%Class]
+// CHECK:STDOUT:   %Make: <function> = fn_decl @Make {
+// CHECK:STDOUT:     %n.loc12_9.1: i32 = param n
+// CHECK:STDOUT:     @Make.%n: i32 = bind_name n, %n.loc12_9.1
+// CHECK:STDOUT:     %Class.ref.loc12_23: type = name_ref Class, %Class.decl [template = constants.%Class]
+// CHECK:STDOUT:     %.loc12: type = ptr_type Class [template = constants.%.2]
+// CHECK:STDOUT:     %next.loc12_17.1: Class* = param next
+// CHECK:STDOUT:     @Make.%next: Class* = bind_name next, %next.loc12_17.1
+// CHECK:STDOUT:     %Class.ref.loc12_34: type = name_ref Class, %Class.decl [template = constants.%Class]
+// CHECK:STDOUT:     @Make.%return: ref Class = var <return slot>
+// CHECK:STDOUT:   } [template]
+// CHECK:STDOUT:   %MakeReorder: <function> = fn_decl @MakeReorder {
+// CHECK:STDOUT:     %n.loc16_16.1: i32 = param n
+// CHECK:STDOUT:     @MakeReorder.%n: i32 = bind_name n, %n.loc16_16.1
+// CHECK:STDOUT:     %Class.ref.loc16_30: type = name_ref Class, %Class.decl [template = constants.%Class]
+// CHECK:STDOUT:     %.loc16: type = ptr_type Class [template = constants.%.2]
+// CHECK:STDOUT:     %next.loc16_24.1: Class* = param next
+// CHECK:STDOUT:     @MakeReorder.%next: Class* = bind_name next, %next.loc16_24.1
+// CHECK:STDOUT:     %Class.ref.loc16_41: type = name_ref Class, %Class.decl [template = constants.%Class]
+// CHECK:STDOUT:     @MakeReorder.%return: ref Class = var <return slot>
+// CHECK:STDOUT:   } [template]
 // CHECK:STDOUT: }
 // CHECK:STDOUT: }
 // CHECK:STDOUT:
 // CHECK:STDOUT:
 // CHECK:STDOUT: class @Class {
 // CHECK:STDOUT: class @Class {

+ 4 - 2
toolchain/check/testdata/class/init_as.carbon

@@ -27,8 +27,10 @@ fn F() -> i32 {
 // CHECK:STDOUT:
 // CHECK:STDOUT:
 // CHECK:STDOUT: file {
 // CHECK:STDOUT: file {
 // CHECK:STDOUT:   package: <namespace> = namespace {.Class = %Class.decl, .F = %F} [template]
 // CHECK:STDOUT:   package: <namespace> = namespace {.Class = %Class.decl, .F = %F} [template]
-// CHECK:STDOUT:   %Class.decl = class_decl @Class, () [template = constants.%Class]
-// CHECK:STDOUT:   %F: <function> = fn_decl @F [template]
+// CHECK:STDOUT:   %Class.decl = class_decl @Class {} [template = constants.%Class]
+// CHECK:STDOUT:   %F: <function> = fn_decl @F {
+// CHECK:STDOUT:     %return.var: ref i32 = var <return slot>
+// CHECK:STDOUT:   } [template]
 // CHECK:STDOUT: }
 // CHECK:STDOUT: }
 // CHECK:STDOUT:
 // CHECK:STDOUT:
 // CHECK:STDOUT: class @Class {
 // CHECK:STDOUT: class @Class {

+ 10 - 4
toolchain/check/testdata/class/init_nested.carbon

@@ -37,10 +37,16 @@ fn MakeOuter() -> Outer {
 // CHECK:STDOUT:
 // CHECK:STDOUT:
 // CHECK:STDOUT: file {
 // CHECK:STDOUT: file {
 // CHECK:STDOUT:   package: <namespace> = namespace {.Inner = %Inner.decl, .MakeInner = %MakeInner, .Outer = %Outer.decl, .MakeOuter = %MakeOuter} [template]
 // CHECK:STDOUT:   package: <namespace> = namespace {.Inner = %Inner.decl, .MakeInner = %MakeInner, .Outer = %Outer.decl, .MakeOuter = %MakeOuter} [template]
-// CHECK:STDOUT:   %Inner.decl = class_decl @Inner, () [template = constants.%Inner]
-// CHECK:STDOUT:   %MakeInner: <function> = fn_decl @MakeInner [template]
-// CHECK:STDOUT:   %Outer.decl = class_decl @Outer, () [template = constants.%Outer]
-// CHECK:STDOUT:   %MakeOuter: <function> = fn_decl @MakeOuter [template]
+// CHECK:STDOUT:   %Inner.decl = class_decl @Inner {} [template = constants.%Inner]
+// CHECK:STDOUT:   %MakeInner: <function> = fn_decl @MakeInner {
+// CHECK:STDOUT:     %Inner.ref: type = name_ref Inner, %Inner.decl [template = constants.%Inner]
+// CHECK:STDOUT:     @MakeInner.%return: ref Inner = var <return slot>
+// CHECK:STDOUT:   } [template]
+// CHECK:STDOUT:   %Outer.decl = class_decl @Outer {} [template = constants.%Outer]
+// CHECK:STDOUT:   %MakeOuter: <function> = fn_decl @MakeOuter {
+// CHECK:STDOUT:     %Outer.ref: type = name_ref Outer, %Outer.decl [template = constants.%Outer]
+// CHECK:STDOUT:     @MakeOuter.%return: ref Outer = var <return slot>
+// CHECK:STDOUT:   } [template]
 // CHECK:STDOUT: }
 // CHECK:STDOUT: }
 // CHECK:STDOUT:
 // CHECK:STDOUT:
 // CHECK:STDOUT: class @Inner {
 // CHECK:STDOUT: class @Inner {

+ 64 - 14
toolchain/check/testdata/class/method.carbon

@@ -68,22 +68,72 @@ fn CallGOnInitializingExpr() -> i32 {
 // CHECK:STDOUT:
 // CHECK:STDOUT:
 // CHECK:STDOUT: file {
 // CHECK:STDOUT: file {
 // CHECK:STDOUT:   package: <namespace> = namespace {.Class = %Class.decl, .Call = %Call, .CallAlias = %CallAlias, .CallOnConstBoundMethod = %CallOnConstBoundMethod, .CallWithAddr = %CallWithAddr, .CallFThroughPointer = %CallFThroughPointer, .CallGThroughPointer = %CallGThroughPointer, .Make = %Make, .CallFOnInitializingExpr = %CallFOnInitializingExpr, .CallGOnInitializingExpr = %CallGOnInitializingExpr} [template]
 // CHECK:STDOUT:   package: <namespace> = namespace {.Class = %Class.decl, .Call = %Call, .CallAlias = %CallAlias, .CallOnConstBoundMethod = %CallOnConstBoundMethod, .CallWithAddr = %CallWithAddr, .CallFThroughPointer = %CallFThroughPointer, .CallGThroughPointer = %CallGThroughPointer, .Make = %Make, .CallFOnInitializingExpr = %CallFOnInitializingExpr, .CallGOnInitializingExpr = %CallGOnInitializingExpr} [template]
-// CHECK:STDOUT:   %Class.decl = class_decl @Class, () [template = constants.%Class]
-// CHECK:STDOUT:   %F: <function> = fn_decl @F [template]
-// CHECK:STDOUT:   %Call: <function> = fn_decl @Call [template]
-// CHECK:STDOUT:   %CallAlias: <function> = fn_decl @CallAlias [template]
-// CHECK:STDOUT:   %CallOnConstBoundMethod: <function> = fn_decl @CallOnConstBoundMethod [template]
-// CHECK:STDOUT:   %CallWithAddr: <function> = fn_decl @CallWithAddr [template]
-// CHECK:STDOUT:   %CallFThroughPointer: <function> = fn_decl @CallFThroughPointer [template]
-// CHECK:STDOUT:   %CallGThroughPointer: <function> = fn_decl @CallGThroughPointer [template]
-// CHECK:STDOUT:   %Make: <function> = fn_decl @Make [template]
-// CHECK:STDOUT:   %CallFOnInitializingExpr: <function> = fn_decl @CallFOnInitializingExpr [template]
-// CHECK:STDOUT:   %CallGOnInitializingExpr: <function> = fn_decl @CallGOnInitializingExpr [template]
+// CHECK:STDOUT:   %Class.decl = class_decl @Class {} [template = constants.%Class]
+// CHECK:STDOUT:   %F: <function> = fn_decl @F {
+// CHECK:STDOUT:     %Class.ref.loc16: type = name_ref Class, %Class.decl [template = constants.%Class]
+// CHECK:STDOUT:     %self.loc16_12.1: Class = param self
+// CHECK:STDOUT:     @F.%self: Class = bind_name self, %self.loc16_12.1
+// CHECK:STDOUT:     %return.var.loc16: ref i32 = var <return slot>
+// CHECK:STDOUT:   } [template]
+// CHECK:STDOUT:   %Call: <function> = fn_decl @Call {
+// CHECK:STDOUT:     %Class.ref.loc20: type = name_ref Class, %Class.decl [template = constants.%Class]
+// CHECK:STDOUT:     %c.loc20_9.1: Class = param c
+// CHECK:STDOUT:     @Call.%c: Class = bind_name c, %c.loc20_9.1
+// CHECK:STDOUT:     %return.var.loc20: ref i32 = var <return slot>
+// CHECK:STDOUT:   } [template]
+// CHECK:STDOUT:   %CallAlias: <function> = fn_decl @CallAlias {
+// CHECK:STDOUT:     %Class.ref.loc26: type = name_ref Class, %Class.decl [template = constants.%Class]
+// CHECK:STDOUT:     %c.loc26_14.1: Class = param c
+// CHECK:STDOUT:     @CallAlias.%c: Class = bind_name c, %c.loc26_14.1
+// CHECK:STDOUT:     %return.var.loc26: ref i32 = var <return slot>
+// CHECK:STDOUT:   } [template]
+// CHECK:STDOUT:   %CallOnConstBoundMethod: <function> = fn_decl @CallOnConstBoundMethod {
+// CHECK:STDOUT:     %return.var.loc30: ref i32 = var <return slot>
+// CHECK:STDOUT:   } [template]
+// CHECK:STDOUT:   %CallWithAddr: <function> = fn_decl @CallWithAddr {
+// CHECK:STDOUT:     %return.var.loc34: ref i32 = var <return slot>
+// CHECK:STDOUT:   } [template]
+// CHECK:STDOUT:   %CallFThroughPointer: <function> = fn_decl @CallFThroughPointer {
+// CHECK:STDOUT:     %Class.ref.loc39: type = name_ref Class, %Class.decl [template = constants.%Class]
+// CHECK:STDOUT:     %.loc39: type = ptr_type Class [template = constants.%.1]
+// CHECK:STDOUT:     %p.loc39_24.1: Class* = param p
+// CHECK:STDOUT:     @CallFThroughPointer.%p: Class* = bind_name p, %p.loc39_24.1
+// CHECK:STDOUT:     %return.var.loc39: ref i32 = var <return slot>
+// CHECK:STDOUT:   } [template]
+// CHECK:STDOUT:   %CallGThroughPointer: <function> = fn_decl @CallGThroughPointer {
+// CHECK:STDOUT:     %Class.ref.loc43: type = name_ref Class, %Class.decl [template = constants.%Class]
+// CHECK:STDOUT:     %.loc43: type = ptr_type Class [template = constants.%.1]
+// CHECK:STDOUT:     %p.loc43_24.1: Class* = param p
+// CHECK:STDOUT:     @CallGThroughPointer.%p: Class* = bind_name p, %p.loc43_24.1
+// CHECK:STDOUT:     %return.var.loc43: ref i32 = var <return slot>
+// CHECK:STDOUT:   } [template]
+// CHECK:STDOUT:   %Make: <function> = fn_decl @Make {
+// CHECK:STDOUT:     %Class.ref.loc47: type = name_ref Class, %Class.decl [template = constants.%Class]
+// CHECK:STDOUT:     @Make.%return: ref Class = var <return slot>
+// CHECK:STDOUT:   } [template]
+// CHECK:STDOUT:   %CallFOnInitializingExpr: <function> = fn_decl @CallFOnInitializingExpr {
+// CHECK:STDOUT:     %return.var.loc49: ref i32 = var <return slot>
+// CHECK:STDOUT:   } [template]
+// CHECK:STDOUT:   %CallGOnInitializingExpr: <function> = fn_decl @CallGOnInitializingExpr {
+// CHECK:STDOUT:     %return.var.loc53: ref i32 = var <return slot>
+// CHECK:STDOUT:   } [template]
 // CHECK:STDOUT: }
 // CHECK:STDOUT: }
 // CHECK:STDOUT:
 // CHECK:STDOUT:
 // CHECK:STDOUT: class @Class {
 // CHECK:STDOUT: class @Class {
-// CHECK:STDOUT:   %F: <function> = fn_decl @F [template]
-// CHECK:STDOUT:   %G: <function> = fn_decl @G [template]
+// CHECK:STDOUT:   %F: <function> = fn_decl @F {
+// CHECK:STDOUT:     %Class.ref.loc8: type = name_ref Class, file.%Class.decl [template = constants.%Class]
+// CHECK:STDOUT:     %self.loc8_8.1: Class = param self
+// CHECK:STDOUT:     %self.loc8_8.2: Class = bind_name self, %self.loc8_8.1
+// CHECK:STDOUT:     %return.var.loc8: ref i32 = var <return slot>
+// CHECK:STDOUT:   } [template]
+// CHECK:STDOUT:   %G: <function> = fn_decl @G {
+// CHECK:STDOUT:     %Class.ref.loc9: type = name_ref Class, file.%Class.decl [template = constants.%Class]
+// CHECK:STDOUT:     %.loc9_24: type = ptr_type Class [template = constants.%.1]
+// CHECK:STDOUT:     %self.loc9_13.1: Class* = param self
+// CHECK:STDOUT:     %self.loc9_13.3: Class* = bind_name self, %self.loc9_13.1
+// CHECK:STDOUT:     %.loc9_8: Class* = addr_pattern %self.loc9_13.3
+// CHECK:STDOUT:     %return.var.loc9: ref i32 = var <return slot>
+// CHECK:STDOUT:   } [template]
 // CHECK:STDOUT:   %F.ref: <function> = name_ref F, %F [template = %F]
 // CHECK:STDOUT:   %F.ref: <function> = name_ref F, %F [template = %F]
 // CHECK:STDOUT:   %A: <function> = bind_alias A, %F [template = %F]
 // CHECK:STDOUT:   %A: <function> = bind_alias A, %F [template = %F]
 // CHECK:STDOUT:   %.loc13: <unbound element of class Class> = field_decl k, element0 [template]
 // CHECK:STDOUT:   %.loc13: <unbound element of class Class> = field_decl k, element0 [template]
@@ -103,7 +153,7 @@ fn CallGOnInitializingExpr() -> i32 {
 // CHECK:STDOUT:   return %.loc17_14.2
 // CHECK:STDOUT:   return %.loc17_14.2
 // CHECK:STDOUT: }
 // CHECK:STDOUT: }
 // CHECK:STDOUT:
 // CHECK:STDOUT:
-// CHECK:STDOUT: fn @G[addr %self: Class*]() -> i32;
+// CHECK:STDOUT: fn @G[addr @Class.%self.loc9_13.3: Class*]() -> i32;
 // CHECK:STDOUT:
 // CHECK:STDOUT:
 // CHECK:STDOUT: fn @Call(%c: Class) -> i32 {
 // CHECK:STDOUT: fn @Call(%c: Class) -> i32 {
 // CHECK:STDOUT: !entry:
 // CHECK:STDOUT: !entry:

+ 8 - 3
toolchain/check/testdata/class/nested.carbon

@@ -47,12 +47,17 @@ fn F(a: Outer*) {
 // CHECK:STDOUT:
 // CHECK:STDOUT:
 // CHECK:STDOUT: file {
 // CHECK:STDOUT: file {
 // CHECK:STDOUT:   package: <namespace> = namespace {.Outer = %Outer.decl, .F = %F} [template]
 // CHECK:STDOUT:   package: <namespace> = namespace {.Outer = %Outer.decl, .F = %F} [template]
-// CHECK:STDOUT:   %Outer.decl = class_decl @Outer, () [template = constants.%Outer]
-// CHECK:STDOUT:   %F: <function> = fn_decl @F [template]
+// CHECK:STDOUT:   %Outer.decl = class_decl @Outer {} [template = constants.%Outer]
+// CHECK:STDOUT:   %F: <function> = fn_decl @F {
+// CHECK:STDOUT:     %Outer.ref: type = name_ref Outer, %Outer.decl [template = constants.%Outer]
+// CHECK:STDOUT:     %.loc19: type = ptr_type Outer [template = constants.%.3]
+// CHECK:STDOUT:     %a.loc19_6.1: Outer* = param a
+// CHECK:STDOUT:     @F.%a: Outer* = bind_name a, %a.loc19_6.1
+// CHECK:STDOUT:   } [template]
 // CHECK:STDOUT: }
 // CHECK:STDOUT: }
 // CHECK:STDOUT:
 // CHECK:STDOUT:
 // CHECK:STDOUT: class @Outer {
 // CHECK:STDOUT: class @Outer {
-// CHECK:STDOUT:   %Inner.decl = class_decl @Inner, () [template = constants.%Inner]
+// CHECK:STDOUT:   %Inner.decl = class_decl @Inner {} [template = constants.%Inner]
 // CHECK:STDOUT:   %Self.ref: type = name_ref Self, constants.%Outer [template = constants.%Outer]
 // CHECK:STDOUT:   %Self.ref: type = name_ref Self, constants.%Outer [template = constants.%Outer]
 // CHECK:STDOUT:   %.loc14_15: type = ptr_type Outer [template = constants.%.3]
 // CHECK:STDOUT:   %.loc14_15: type = ptr_type Outer [template = constants.%.3]
 // CHECK:STDOUT:   %.loc14_9: <unbound element of class Outer> = field_decl po, element0 [template]
 // CHECK:STDOUT:   %.loc14_9: <unbound element of class Outer> = field_decl po, element0 [template]

+ 14 - 4
toolchain/check/testdata/class/nested_name.carbon

@@ -33,13 +33,23 @@ fn G(o: Outer) {
 // CHECK:STDOUT:
 // CHECK:STDOUT:
 // CHECK:STDOUT: file {
 // CHECK:STDOUT: file {
 // CHECK:STDOUT:   package: <namespace> = namespace {.Outer = %Outer.decl, .F = %F, .G = %G} [template]
 // CHECK:STDOUT:   package: <namespace> = namespace {.Outer = %Outer.decl, .F = %F, .G = %G} [template]
-// CHECK:STDOUT:   %Outer.decl = class_decl @Outer, () [template = constants.%Outer]
-// CHECK:STDOUT:   %F: <function> = fn_decl @F [template]
-// CHECK:STDOUT:   %G: <function> = fn_decl @G [template]
+// CHECK:STDOUT:   %Outer.decl = class_decl @Outer {} [template = constants.%Outer]
+// CHECK:STDOUT:   %F: <function> = fn_decl @F {
+// CHECK:STDOUT:     %Outer.ref.loc13: type = name_ref Outer, %Outer.decl [template = constants.%Outer]
+// CHECK:STDOUT:     %Inner.ref: type = name_ref Inner, @Outer.%Inner.decl [template = constants.%Inner]
+// CHECK:STDOUT:     %oi.loc13_6.1: Inner = param oi
+// CHECK:STDOUT:     @F.%oi: Inner = bind_name oi, %oi.loc13_6.1
+// CHECK:STDOUT:     %return.var: ref i32 = var <return slot>
+// CHECK:STDOUT:   } [template]
+// CHECK:STDOUT:   %G: <function> = fn_decl @G {
+// CHECK:STDOUT:     %Outer.ref.loc17: type = name_ref Outer, %Outer.decl [template = constants.%Outer]
+// CHECK:STDOUT:     %o.loc17_6.1: Outer = param o
+// CHECK:STDOUT:     @G.%o: Outer = bind_name o, %o.loc17_6.1
+// CHECK:STDOUT:   } [template]
 // CHECK:STDOUT: }
 // CHECK:STDOUT: }
 // CHECK:STDOUT:
 // CHECK:STDOUT:
 // CHECK:STDOUT: class @Outer {
 // CHECK:STDOUT: class @Outer {
-// CHECK:STDOUT:   %Inner.decl = class_decl @Inner, () [template = constants.%Inner]
+// CHECK:STDOUT:   %Inner.decl = class_decl @Inner {} [template = constants.%Inner]
 // CHECK:STDOUT:
 // CHECK:STDOUT:
 // CHECK:STDOUT: !members:
 // CHECK:STDOUT: !members:
 // CHECK:STDOUT:   .Inner = %Inner.decl
 // CHECK:STDOUT:   .Inner = %Inner.decl

+ 39 - 5
toolchain/check/testdata/class/raw_self.carbon

@@ -33,14 +33,48 @@ fn Class.G[self: Class](r#self: i32) -> (i32, i32) {
 // CHECK:STDOUT:
 // CHECK:STDOUT:
 // CHECK:STDOUT: file {
 // CHECK:STDOUT: file {
 // CHECK:STDOUT:   package: <namespace> = namespace {.Class = %Class.decl} [template]
 // CHECK:STDOUT:   package: <namespace> = namespace {.Class = %Class.decl} [template]
-// CHECK:STDOUT:   %Class.decl = class_decl @Class, () [template = constants.%Class]
-// CHECK:STDOUT:   %F: <function> = fn_decl @F [template]
-// CHECK:STDOUT:   %G: <function> = fn_decl @G [template]
+// CHECK:STDOUT:   %Class.decl = class_decl @Class {} [template = constants.%Class]
+// CHECK:STDOUT:   %F: <function> = fn_decl @F {
+// CHECK:STDOUT:     %Class.ref.loc13: type = name_ref Class, %Class.decl [template = constants.%Class]
+// CHECK:STDOUT:     %.loc13_28: type = ptr_type Class [template = constants.%.1]
+// CHECK:STDOUT:     %self.loc13_17.1: Class* = param self
+// CHECK:STDOUT:     @F.%self.loc13_17: Class* = bind_name self, %self.loc13_17.1
+// CHECK:STDOUT:     @F.%.loc13: Class* = addr_pattern @F.%self.loc13_17
+// CHECK:STDOUT:     %self.loc13_31.1: i32 = param r#self
+// CHECK:STDOUT:     @F.%self.loc13_31: i32 = bind_name r#self, %self.loc13_31.1
+// CHECK:STDOUT:   } [template]
+// CHECK:STDOUT:   %G: <function> = fn_decl @G {
+// CHECK:STDOUT:     %Class.ref.loc17: type = name_ref Class, %Class.decl [template = constants.%Class]
+// CHECK:STDOUT:     %self.loc17_12.1: Class = param self
+// CHECK:STDOUT:     @G.%self.loc17_12: Class = bind_name self, %self.loc17_12.1
+// CHECK:STDOUT:     %self.loc17_25.1: i32 = param r#self
+// CHECK:STDOUT:     @G.%self.loc17_25: i32 = bind_name r#self, %self.loc17_25.1
+// CHECK:STDOUT:     %.loc17_50.1: (type, type) = tuple_literal (i32, i32)
+// CHECK:STDOUT:     %.loc17_50.2: type = converted %.loc17_50.1, constants.%.3 [template = constants.%.3]
+// CHECK:STDOUT:     @G.%return: ref (i32, i32) = var <return slot>
+// CHECK:STDOUT:   } [template]
 // CHECK:STDOUT: }
 // CHECK:STDOUT: }
 // CHECK:STDOUT:
 // CHECK:STDOUT:
 // CHECK:STDOUT: class @Class {
 // CHECK:STDOUT: class @Class {
-// CHECK:STDOUT:   %F: <function> = fn_decl @F [template]
-// CHECK:STDOUT:   %G: <function> = fn_decl @G [template]
+// CHECK:STDOUT:   %F: <function> = fn_decl @F {
+// CHECK:STDOUT:     %Class.ref.loc8: type = name_ref Class, file.%Class.decl [template = constants.%Class]
+// CHECK:STDOUT:     %.loc8_24: type = ptr_type Class [template = constants.%.1]
+// CHECK:STDOUT:     %self.loc8_13.1: Class* = param self
+// CHECK:STDOUT:     %self.loc8_13.3: Class* = bind_name self, %self.loc8_13.1
+// CHECK:STDOUT:     %.loc8_8: Class* = addr_pattern %self.loc8_13.3
+// CHECK:STDOUT:     %self.loc8_27.1: i32 = param r#self
+// CHECK:STDOUT:     %self.loc8_27.2: i32 = bind_name r#self, %self.loc8_27.1
+// CHECK:STDOUT:   } [template]
+// CHECK:STDOUT:   %G: <function> = fn_decl @G {
+// CHECK:STDOUT:     %Class.ref.loc9: type = name_ref Class, file.%Class.decl [template = constants.%Class]
+// CHECK:STDOUT:     %self.loc9_8.1: Class = param self
+// CHECK:STDOUT:     %self.loc9_8.2: Class = bind_name self, %self.loc9_8.1
+// CHECK:STDOUT:     %self.loc9_21.1: i32 = param r#self
+// CHECK:STDOUT:     %self.loc9_21.2: i32 = bind_name r#self, %self.loc9_21.1
+// CHECK:STDOUT:     %.loc9_46.1: (type, type) = tuple_literal (i32, i32)
+// CHECK:STDOUT:     %.loc9_46.2: type = converted %.loc9_46.1, constants.%.3 [template = constants.%.3]
+// CHECK:STDOUT:     %return.var: ref (i32, i32) = var <return slot>
+// CHECK:STDOUT:   } [template]
 // CHECK:STDOUT:   %.loc10: <unbound element of class Class> = field_decl n, element0 [template]
 // CHECK:STDOUT:   %.loc10: <unbound element of class Class> = field_decl n, element0 [template]
 // CHECK:STDOUT:
 // CHECK:STDOUT:
 // CHECK:STDOUT: !members:
 // CHECK:STDOUT: !members:

+ 2 - 2
toolchain/check/testdata/class/raw_self_type.carbon

@@ -21,11 +21,11 @@ class Class {
 // CHECK:STDOUT:
 // CHECK:STDOUT:
 // CHECK:STDOUT: file {
 // CHECK:STDOUT: file {
 // CHECK:STDOUT:   package: <namespace> = namespace {.Class = %Class.decl} [template]
 // CHECK:STDOUT:   package: <namespace> = namespace {.Class = %Class.decl} [template]
-// CHECK:STDOUT:   %Class.decl = class_decl @Class, () [template = constants.%Class]
+// CHECK:STDOUT:   %Class.decl = class_decl @Class {} [template = constants.%Class]
 // CHECK:STDOUT: }
 // CHECK:STDOUT: }
 // CHECK:STDOUT:
 // CHECK:STDOUT:
 // CHECK:STDOUT: class @Class {
 // CHECK:STDOUT: class @Class {
-// CHECK:STDOUT:   %F: <function> = fn_decl @F [template]
+// CHECK:STDOUT:   %F: <function> = fn_decl @F {} [template]
 // CHECK:STDOUT:
 // CHECK:STDOUT:
 // CHECK:STDOUT: !members:
 // CHECK:STDOUT: !members:
 // CHECK:STDOUT:   .F = %F
 // CHECK:STDOUT:   .F = %F

+ 4 - 4
toolchain/check/testdata/class/redeclaration.carbon

@@ -21,13 +21,13 @@ fn Class.F() {}
 // CHECK:STDOUT:
 // CHECK:STDOUT:
 // CHECK:STDOUT: file {
 // CHECK:STDOUT: file {
 // CHECK:STDOUT:   package: <namespace> = namespace {.Class = %Class.decl.loc7} [template]
 // CHECK:STDOUT:   package: <namespace> = namespace {.Class = %Class.decl.loc7} [template]
-// CHECK:STDOUT:   %Class.decl.loc7 = class_decl @Class, () [template = constants.%Class]
-// CHECK:STDOUT:   %Class.decl.loc9 = class_decl @Class, () [template = constants.%Class]
-// CHECK:STDOUT:   %F: <function> = fn_decl @F [template]
+// CHECK:STDOUT:   %Class.decl.loc7 = class_decl @Class {} [template = constants.%Class]
+// CHECK:STDOUT:   %Class.decl.loc9 = class_decl @Class {} [template = constants.%Class]
+// CHECK:STDOUT:   %F: <function> = fn_decl @F {} [template]
 // CHECK:STDOUT: }
 // CHECK:STDOUT: }
 // CHECK:STDOUT:
 // CHECK:STDOUT:
 // CHECK:STDOUT: class @Class {
 // CHECK:STDOUT: class @Class {
-// CHECK:STDOUT:   %F: <function> = fn_decl @F [template]
+// CHECK:STDOUT:   %F: <function> = fn_decl @F {} [template]
 // CHECK:STDOUT:
 // CHECK:STDOUT:
 // CHECK:STDOUT: !members:
 // CHECK:STDOUT: !members:
 // CHECK:STDOUT:   .F = %F
 // CHECK:STDOUT:   .F = %F

+ 6 - 6
toolchain/check/testdata/class/redeclaration_introducer.carbon

@@ -23,12 +23,12 @@ abstract class C {}
 // CHECK:STDOUT:
 // CHECK:STDOUT:
 // CHECK:STDOUT: file {
 // CHECK:STDOUT: file {
 // CHECK:STDOUT:   package: <namespace> = namespace {.A = %A.decl.loc7, .B = %B.decl.loc8, .C = %C.decl.loc9} [template]
 // CHECK:STDOUT:   package: <namespace> = namespace {.A = %A.decl.loc7, .B = %B.decl.loc8, .C = %C.decl.loc9} [template]
-// CHECK:STDOUT:   %A.decl.loc7 = class_decl @A, () [template = constants.%A]
-// CHECK:STDOUT:   %B.decl.loc8 = class_decl @B, () [template = constants.%B]
-// CHECK:STDOUT:   %C.decl.loc9 = class_decl @C, () [template = constants.%C]
-// CHECK:STDOUT:   %A.decl.loc11 = class_decl @A, () [template = constants.%A]
-// CHECK:STDOUT:   %B.decl.loc12 = class_decl @B, () [template = constants.%B]
-// CHECK:STDOUT:   %C.decl.loc13 = class_decl @C, () [template = constants.%C]
+// CHECK:STDOUT:   %A.decl.loc7 = class_decl @A {} [template = constants.%A]
+// CHECK:STDOUT:   %B.decl.loc8 = class_decl @B {} [template = constants.%B]
+// CHECK:STDOUT:   %C.decl.loc9 = class_decl @C {} [template = constants.%C]
+// CHECK:STDOUT:   %A.decl.loc11 = class_decl @A {} [template = constants.%A]
+// CHECK:STDOUT:   %B.decl.loc12 = class_decl @B {} [template = constants.%B]
+// CHECK:STDOUT:   %C.decl.loc13 = class_decl @C {} [template = constants.%C]
 // CHECK:STDOUT: }
 // CHECK:STDOUT: }
 // CHECK:STDOUT:
 // CHECK:STDOUT:
 // CHECK:STDOUT: class @A {
 // CHECK:STDOUT: class @A {

+ 10 - 4
toolchain/check/testdata/class/reenter_scope.carbon

@@ -22,13 +22,19 @@ fn Class.F() -> i32 {
 // CHECK:STDOUT:
 // CHECK:STDOUT:
 // CHECK:STDOUT: file {
 // CHECK:STDOUT: file {
 // CHECK:STDOUT:   package: <namespace> = namespace {.Class = %Class.decl} [template]
 // CHECK:STDOUT:   package: <namespace> = namespace {.Class = %Class.decl} [template]
-// CHECK:STDOUT:   %Class.decl = class_decl @Class, () [template = constants.%Class]
-// CHECK:STDOUT:   %F: <function> = fn_decl @F [template]
+// CHECK:STDOUT:   %Class.decl = class_decl @Class {} [template = constants.%Class]
+// CHECK:STDOUT:   %F: <function> = fn_decl @F {
+// CHECK:STDOUT:     %return.var: ref i32 = var <return slot>
+// CHECK:STDOUT:   } [template]
 // CHECK:STDOUT: }
 // CHECK:STDOUT: }
 // CHECK:STDOUT:
 // CHECK:STDOUT:
 // CHECK:STDOUT: class @Class {
 // CHECK:STDOUT: class @Class {
-// CHECK:STDOUT:   %F: <function> = fn_decl @F [template]
-// CHECK:STDOUT:   %G: <function> = fn_decl @G [template]
+// CHECK:STDOUT:   %F: <function> = fn_decl @F {
+// CHECK:STDOUT:     %return.var.loc8: ref i32 = var <return slot>
+// CHECK:STDOUT:   } [template]
+// CHECK:STDOUT:   %G: <function> = fn_decl @G {
+// CHECK:STDOUT:     %return.var.loc9: ref i32 = var <return slot>
+// CHECK:STDOUT:   } [template]
 // CHECK:STDOUT:
 // CHECK:STDOUT:
 // CHECK:STDOUT: !members:
 // CHECK:STDOUT: !members:
 // CHECK:STDOUT:   .F = %F
 // CHECK:STDOUT:   .F = %F

+ 11 - 5
toolchain/check/testdata/class/scope.carbon

@@ -34,14 +34,20 @@ fn Run() {
 // CHECK:STDOUT:
 // CHECK:STDOUT:
 // CHECK:STDOUT: file {
 // CHECK:STDOUT: file {
 // CHECK:STDOUT:   package: <namespace> = namespace {.Class = %Class.decl, .F = %F, .Run = %Run} [template]
 // CHECK:STDOUT:   package: <namespace> = namespace {.Class = %Class.decl, .F = %F, .Run = %Run} [template]
-// CHECK:STDOUT:   %Class.decl = class_decl @Class, () [template = constants.%Class]
-// CHECK:STDOUT:   %F: <function> = fn_decl @F.2 [template]
-// CHECK:STDOUT:   %Run: <function> = fn_decl @Run [template]
+// CHECK:STDOUT:   %Class.decl = class_decl @Class {} [template = constants.%Class]
+// CHECK:STDOUT:   %F: <function> = fn_decl @F.2 {
+// CHECK:STDOUT:     %return.var: ref i32 = var <return slot>
+// CHECK:STDOUT:   } [template]
+// CHECK:STDOUT:   %Run: <function> = fn_decl @Run {} [template]
 // CHECK:STDOUT: }
 // CHECK:STDOUT: }
 // CHECK:STDOUT:
 // CHECK:STDOUT:
 // CHECK:STDOUT: class @Class {
 // CHECK:STDOUT: class @Class {
-// CHECK:STDOUT:   %F: <function> = fn_decl @F.1 [template]
-// CHECK:STDOUT:   %G: <function> = fn_decl @G [template]
+// CHECK:STDOUT:   %F: <function> = fn_decl @F.1 {
+// CHECK:STDOUT:     %return.var.loc8: ref i32 = var <return slot>
+// CHECK:STDOUT:   } [template]
+// CHECK:STDOUT:   %G: <function> = fn_decl @G {
+// CHECK:STDOUT:     %return.var.loc12: ref i32 = var <return slot>
+// CHECK:STDOUT:   } [template]
 // CHECK:STDOUT:
 // CHECK:STDOUT:
 // CHECK:STDOUT: !members:
 // CHECK:STDOUT: !members:
 // CHECK:STDOUT:   .F = %F
 // CHECK:STDOUT:   .F = %F

+ 29 - 5
toolchain/check/testdata/class/self.carbon

@@ -31,14 +31,38 @@ fn Class.G[addr self: Class*]() -> i32 {
 // CHECK:STDOUT:
 // CHECK:STDOUT:
 // CHECK:STDOUT: file {
 // CHECK:STDOUT: file {
 // CHECK:STDOUT:   package: <namespace> = namespace {.Class = %Class.decl} [template]
 // CHECK:STDOUT:   package: <namespace> = namespace {.Class = %Class.decl} [template]
-// CHECK:STDOUT:   %Class.decl = class_decl @Class, () [template = constants.%Class]
-// CHECK:STDOUT:   %F: <function> = fn_decl @F [template]
-// CHECK:STDOUT:   %G: <function> = fn_decl @G [template]
+// CHECK:STDOUT:   %Class.decl = class_decl @Class {} [template = constants.%Class]
+// CHECK:STDOUT:   %F: <function> = fn_decl @F {
+// CHECK:STDOUT:     %Class.ref.loc14: type = name_ref Class, %Class.decl [template = constants.%Class]
+// CHECK:STDOUT:     %self.loc14_12.1: Class = param self
+// CHECK:STDOUT:     @F.%self: Class = bind_name self, %self.loc14_12.1
+// CHECK:STDOUT:     %return.var.loc14: ref i32 = var <return slot>
+// CHECK:STDOUT:   } [template]
+// CHECK:STDOUT:   %G: <function> = fn_decl @G {
+// CHECK:STDOUT:     %Class.ref.loc18: type = name_ref Class, %Class.decl [template = constants.%Class]
+// CHECK:STDOUT:     %.loc18_28: type = ptr_type Class [template = constants.%.1]
+// CHECK:STDOUT:     %self.loc18_17.1: Class* = param self
+// CHECK:STDOUT:     @G.%self: Class* = bind_name self, %self.loc18_17.1
+// CHECK:STDOUT:     @G.%.loc18: Class* = addr_pattern @G.%self
+// CHECK:STDOUT:     %return.var.loc18: ref i32 = var <return slot>
+// CHECK:STDOUT:   } [template]
 // CHECK:STDOUT: }
 // CHECK:STDOUT: }
 // CHECK:STDOUT:
 // CHECK:STDOUT:
 // CHECK:STDOUT: class @Class {
 // CHECK:STDOUT: class @Class {
-// CHECK:STDOUT:   %F: <function> = fn_decl @F [template]
-// CHECK:STDOUT:   %G: <function> = fn_decl @G [template]
+// CHECK:STDOUT:   %F: <function> = fn_decl @F {
+// CHECK:STDOUT:     %Class.ref.loc8: type = name_ref Class, file.%Class.decl [template = constants.%Class]
+// CHECK:STDOUT:     %self.loc8_8.1: Class = param self
+// CHECK:STDOUT:     %self.loc8_8.2: Class = bind_name self, %self.loc8_8.1
+// CHECK:STDOUT:     %return.var.loc8: ref i32 = var <return slot>
+// CHECK:STDOUT:   } [template]
+// CHECK:STDOUT:   %G: <function> = fn_decl @G {
+// CHECK:STDOUT:     %Class.ref.loc9: type = name_ref Class, file.%Class.decl [template = constants.%Class]
+// CHECK:STDOUT:     %.loc9_24: type = ptr_type Class [template = constants.%.1]
+// CHECK:STDOUT:     %self.loc9_13.1: Class* = param self
+// CHECK:STDOUT:     %self.loc9_13.3: Class* = bind_name self, %self.loc9_13.1
+// CHECK:STDOUT:     %.loc9_8: Class* = addr_pattern %self.loc9_13.3
+// CHECK:STDOUT:     %return.var.loc9: ref i32 = var <return slot>
+// CHECK:STDOUT:   } [template]
 // CHECK:STDOUT:   %.loc11: <unbound element of class Class> = field_decl n, element0 [template]
 // CHECK:STDOUT:   %.loc11: <unbound element of class Class> = field_decl n, element0 [template]
 // CHECK:STDOUT:
 // CHECK:STDOUT:
 // CHECK:STDOUT: !members:
 // CHECK:STDOUT: !members:

+ 36 - 8
toolchain/check/testdata/class/self_conversion.carbon

@@ -48,11 +48,28 @@ fn Call(p: Derived*) -> i32 {
 // CHECK:STDOUT:
 // CHECK:STDOUT:
 // CHECK:STDOUT: file {
 // CHECK:STDOUT: file {
 // CHECK:STDOUT:   package: <namespace> = namespace {.Base = %Base.decl, .Derived = %Derived.decl, .Call = %Call} [template]
 // CHECK:STDOUT:   package: <namespace> = namespace {.Base = %Base.decl, .Derived = %Derived.decl, .Call = %Call} [template]
-// CHECK:STDOUT:   %Base.decl = class_decl @Base, () [template = constants.%Base]
-// CHECK:STDOUT:   %Derived.decl = class_decl @Derived, () [template = constants.%Derived]
-// CHECK:STDOUT:   %SelfBase: <function> = fn_decl @SelfBase [template]
-// CHECK:STDOUT:   %AddrSelfBase: <function> = fn_decl @AddrSelfBase [template]
-// CHECK:STDOUT:   %Call: <function> = fn_decl @Call [template]
+// CHECK:STDOUT:   %Base.decl = class_decl @Base {} [template = constants.%Base]
+// CHECK:STDOUT:   %Derived.decl = class_decl @Derived {} [template = constants.%Derived]
+// CHECK:STDOUT:   %SelfBase: <function> = fn_decl @SelfBase {
+// CHECK:STDOUT:     %Base.ref.loc18: type = name_ref Base, %Base.decl [template = constants.%Base]
+// CHECK:STDOUT:     %self.loc18_21.1: Base = param self
+// CHECK:STDOUT:     @SelfBase.%self: Base = bind_name self, %self.loc18_21.1
+// CHECK:STDOUT:     %return.var.loc18: ref i32 = var <return slot>
+// CHECK:STDOUT:   } [template]
+// CHECK:STDOUT:   %AddrSelfBase: <function> = fn_decl @AddrSelfBase {
+// CHECK:STDOUT:     %Base.ref.loc22: type = name_ref Base, %Base.decl [template = constants.%Base]
+// CHECK:STDOUT:     %.loc22_40: type = ptr_type Base [template = constants.%.5]
+// CHECK:STDOUT:     %self.loc22_30.1: Base* = param self
+// CHECK:STDOUT:     @AddrSelfBase.%self: Base* = bind_name self, %self.loc22_30.1
+// CHECK:STDOUT:     @AddrSelfBase.%.loc22: Base* = addr_pattern @AddrSelfBase.%self
+// CHECK:STDOUT:   } [template]
+// CHECK:STDOUT:   %Call: <function> = fn_decl @Call {
+// CHECK:STDOUT:     %Derived.ref: type = name_ref Derived, %Derived.decl [template = constants.%Derived]
+// CHECK:STDOUT:     %.loc26: type = ptr_type Derived [template = constants.%.8]
+// CHECK:STDOUT:     %p.loc26_9.1: Derived* = param p
+// CHECK:STDOUT:     @Call.%p: Derived* = bind_name p, %p.loc26_9.1
+// CHECK:STDOUT:     %return.var.loc26: ref i32 = var <return slot>
+// CHECK:STDOUT:   } [template]
 // CHECK:STDOUT: }
 // CHECK:STDOUT: }
 // CHECK:STDOUT:
 // CHECK:STDOUT:
 // CHECK:STDOUT: class @Base {
 // CHECK:STDOUT: class @Base {
@@ -63,10 +80,21 @@ fn Call(p: Derived*) -> i32 {
 // CHECK:STDOUT: }
 // CHECK:STDOUT: }
 // CHECK:STDOUT:
 // CHECK:STDOUT:
 // CHECK:STDOUT: class @Derived {
 // CHECK:STDOUT: class @Derived {
-// CHECK:STDOUT:   %Base.ref: type = name_ref Base, file.%Base.decl [template = constants.%Base]
+// CHECK:STDOUT:   %Base.ref.loc12: type = name_ref Base, file.%Base.decl [template = constants.%Base]
 // CHECK:STDOUT:   %.loc12: <unbound element of class Derived> = base_decl Base, element0 [template]
 // CHECK:STDOUT:   %.loc12: <unbound element of class Derived> = base_decl Base, element0 [template]
-// CHECK:STDOUT:   %SelfBase: <function> = fn_decl @SelfBase [template]
-// CHECK:STDOUT:   %AddrSelfBase: <function> = fn_decl @AddrSelfBase [template]
+// CHECK:STDOUT:   %SelfBase: <function> = fn_decl @SelfBase {
+// CHECK:STDOUT:     %Base.ref.loc14: type = name_ref Base, file.%Base.decl [template = constants.%Base]
+// CHECK:STDOUT:     %self.loc14_15.1: Base = param self
+// CHECK:STDOUT:     %self.loc14_15.2: Base = bind_name self, %self.loc14_15.1
+// CHECK:STDOUT:     %return.var: ref i32 = var <return slot>
+// CHECK:STDOUT:   } [template]
+// CHECK:STDOUT:   %AddrSelfBase: <function> = fn_decl @AddrSelfBase {
+// CHECK:STDOUT:     %Base.ref.loc15: type = name_ref Base, file.%Base.decl [template = constants.%Base]
+// CHECK:STDOUT:     %.loc15_34: type = ptr_type Base [template = constants.%.5]
+// CHECK:STDOUT:     %self.loc15_24.1: Base* = param self
+// CHECK:STDOUT:     %self.loc15_24.3: Base* = bind_name self, %self.loc15_24.1
+// CHECK:STDOUT:     %.loc15_19: Base* = addr_pattern %self.loc15_24.3
+// CHECK:STDOUT:   } [template]
 // CHECK:STDOUT:
 // CHECK:STDOUT:
 // CHECK:STDOUT: !members:
 // CHECK:STDOUT: !members:
 // CHECK:STDOUT:   .base = %.loc12
 // CHECK:STDOUT:   .base = %.loc12

+ 14 - 4
toolchain/check/testdata/class/self_type.carbon

@@ -28,13 +28,23 @@ fn Class.F[self: Class]() -> i32 {
 // CHECK:STDOUT:
 // CHECK:STDOUT:
 // CHECK:STDOUT: file {
 // CHECK:STDOUT: file {
 // CHECK:STDOUT:   package: <namespace> = namespace {.Class = %Class.decl} [template]
 // CHECK:STDOUT:   package: <namespace> = namespace {.Class = %Class.decl} [template]
-// CHECK:STDOUT:   %Class.decl = class_decl @Class, () [template = constants.%Class]
-// CHECK:STDOUT:   %F: <function> = fn_decl @F [template]
+// CHECK:STDOUT:   %Class.decl = class_decl @Class {} [template = constants.%Class]
+// CHECK:STDOUT:   %F: <function> = fn_decl @F {
+// CHECK:STDOUT:     %Class.ref: type = name_ref Class, %Class.decl [template = constants.%Class]
+// CHECK:STDOUT:     %self.loc15_12.1: Class = param self
+// CHECK:STDOUT:     @F.%self: Class = bind_name self, %self.loc15_12.1
+// CHECK:STDOUT:     %return.var: ref i32 = var <return slot>
+// CHECK:STDOUT:   } [template]
 // CHECK:STDOUT: }
 // CHECK:STDOUT: }
 // CHECK:STDOUT:
 // CHECK:STDOUT:
 // CHECK:STDOUT: class @Class {
 // CHECK:STDOUT: class @Class {
-// CHECK:STDOUT:   %F: <function> = fn_decl @F [template]
-// CHECK:STDOUT:   %Self.ref: type = name_ref Self, constants.%Class [template = constants.%Class]
+// CHECK:STDOUT:   %F: <function> = fn_decl @F {
+// CHECK:STDOUT:     %Self.ref.loc8: type = name_ref Self, constants.%Class [template = constants.%Class]
+// CHECK:STDOUT:     %self.loc8_8.1: Class = param self
+// CHECK:STDOUT:     %self.loc8_8.2: Class = bind_name self, %self.loc8_8.1
+// CHECK:STDOUT:     %return.var: ref i32 = var <return slot>
+// CHECK:STDOUT:   } [template]
+// CHECK:STDOUT:   %Self.ref.loc9: type = name_ref Self, constants.%Class [template = constants.%Class]
 // CHECK:STDOUT:   %.loc9_14: type = ptr_type Class [template = constants.%.1]
 // CHECK:STDOUT:   %.loc9_14: type = ptr_type Class [template = constants.%.1]
 // CHECK:STDOUT:   %.loc9_8: <unbound element of class Class> = field_decl p, element0 [template]
 // CHECK:STDOUT:   %.loc9_8: <unbound element of class Class> = field_decl p, element0 [template]
 // CHECK:STDOUT:
 // CHECK:STDOUT:

+ 7 - 3
toolchain/check/testdata/class/static_method.carbon

@@ -24,12 +24,16 @@ fn Run() -> i32 {
 // CHECK:STDOUT:
 // CHECK:STDOUT:
 // CHECK:STDOUT: file {
 // CHECK:STDOUT: file {
 // CHECK:STDOUT:   package: <namespace> = namespace {.Class = %Class.decl, .Run = %Run} [template]
 // CHECK:STDOUT:   package: <namespace> = namespace {.Class = %Class.decl, .Run = %Run} [template]
-// CHECK:STDOUT:   %Class.decl = class_decl @Class, () [template = constants.%Class]
-// CHECK:STDOUT:   %Run: <function> = fn_decl @Run [template]
+// CHECK:STDOUT:   %Class.decl = class_decl @Class {} [template = constants.%Class]
+// CHECK:STDOUT:   %Run: <function> = fn_decl @Run {
+// CHECK:STDOUT:     %return.var: ref i32 = var <return slot>
+// CHECK:STDOUT:   } [template]
 // CHECK:STDOUT: }
 // CHECK:STDOUT: }
 // CHECK:STDOUT:
 // CHECK:STDOUT:
 // CHECK:STDOUT: class @Class {
 // CHECK:STDOUT: class @Class {
-// CHECK:STDOUT:   %F: <function> = fn_decl @F [template]
+// CHECK:STDOUT:   %F: <function> = fn_decl @F {
+// CHECK:STDOUT:     %return.var: ref i32 = var <return slot>
+// CHECK:STDOUT:   } [template]
 // CHECK:STDOUT:
 // CHECK:STDOUT:
 // CHECK:STDOUT: !members:
 // CHECK:STDOUT: !members:
 // CHECK:STDOUT:   .F = %F
 // CHECK:STDOUT:   .F = %F

+ 20 - 2
toolchain/check/testdata/const/basic.carbon

@@ -24,8 +24,26 @@ fn B(p: const (i32*)) -> const (i32*) {
 // CHECK:STDOUT:
 // CHECK:STDOUT:
 // CHECK:STDOUT: file {
 // CHECK:STDOUT: file {
 // CHECK:STDOUT:   package: <namespace> = namespace {.A = %A, .B = %B} [template]
 // CHECK:STDOUT:   package: <namespace> = namespace {.A = %A, .B = %B} [template]
-// CHECK:STDOUT:   %A: <function> = fn_decl @A [template]
-// CHECK:STDOUT:   %B: <function> = fn_decl @B [template]
+// CHECK:STDOUT:   %A: <function> = fn_decl @A {
+// CHECK:STDOUT:     %.loc7_9: type = const_type i32 [template = constants.%.1]
+// CHECK:STDOUT:     %.loc7_18: type = ptr_type const i32 [template = constants.%.2]
+// CHECK:STDOUT:     %.loc7_19: type = ptr_type const i32* [template = constants.%.3]
+// CHECK:STDOUT:     %p.loc7_6.1: const i32** = param p
+// CHECK:STDOUT:     @A.%p: const i32** = bind_name p, %p.loc7_6.1
+// CHECK:STDOUT:     %.loc7_25: type = const_type i32 [template = constants.%.1]
+// CHECK:STDOUT:     %.loc7_34: type = ptr_type const i32 [template = constants.%.2]
+// CHECK:STDOUT:     %.loc7_35: type = ptr_type const i32* [template = constants.%.3]
+// CHECK:STDOUT:     %return.var.loc7: ref const i32** = var <return slot>
+// CHECK:STDOUT:   } [template]
+// CHECK:STDOUT:   %B: <function> = fn_decl @B {
+// CHECK:STDOUT:     %.loc11_19: type = ptr_type i32 [template = constants.%.4]
+// CHECK:STDOUT:     %.loc11_9: type = const_type i32* [template = constants.%.5]
+// CHECK:STDOUT:     %p.loc11_6.1: const (i32*) = param p
+// CHECK:STDOUT:     @B.%p: const (i32*) = bind_name p, %p.loc11_6.1
+// CHECK:STDOUT:     %.loc11_36: type = ptr_type i32 [template = constants.%.4]
+// CHECK:STDOUT:     %.loc11_26: type = const_type i32* [template = constants.%.5]
+// CHECK:STDOUT:     %return.var.loc11: ref const (i32*) = var <return slot>
+// CHECK:STDOUT:   } [template]
 // CHECK:STDOUT: }
 // CHECK:STDOUT: }
 // CHECK:STDOUT:
 // CHECK:STDOUT:
 // CHECK:STDOUT: fn @A(%p: const i32**) -> const i32** {
 // CHECK:STDOUT: fn @A(%p: const i32**) -> const i32** {

+ 12 - 1
toolchain/check/testdata/const/collapse.carbon

@@ -22,7 +22,18 @@ fn F(p: const i32**) -> const (const i32)** {
 // CHECK:STDOUT:
 // CHECK:STDOUT:
 // CHECK:STDOUT: file {
 // CHECK:STDOUT: file {
 // CHECK:STDOUT:   package: <namespace> = namespace {.F = %F} [template]
 // CHECK:STDOUT:   package: <namespace> = namespace {.F = %F} [template]
-// CHECK:STDOUT:   %F: <function> = fn_decl @F [template]
+// CHECK:STDOUT:   %F: <function> = fn_decl @F {
+// CHECK:STDOUT:     %.loc11_9: type = const_type i32 [template = constants.%.1]
+// CHECK:STDOUT:     %.loc11_18: type = ptr_type const i32 [template = constants.%.2]
+// CHECK:STDOUT:     %.loc11_19: type = ptr_type const i32* [template = constants.%.3]
+// CHECK:STDOUT:     %p.loc11_6.1: const i32** = param p
+// CHECK:STDOUT:     @F.%p: const i32** = bind_name p, %p.loc11_6.1
+// CHECK:STDOUT:     %.loc11_32: type = const_type i32 [template = constants.%.1]
+// CHECK:STDOUT:     %.loc11_25: type = const_type const i32 [template = constants.%.1]
+// CHECK:STDOUT:     %.loc11_42: type = ptr_type const i32 [template = constants.%.2]
+// CHECK:STDOUT:     %.loc11_43: type = ptr_type const i32* [template = constants.%.3]
+// CHECK:STDOUT:     %return.var: ref const i32** = var <return slot>
+// CHECK:STDOUT:   } [template]
 // CHECK:STDOUT: }
 // CHECK:STDOUT: }
 // CHECK:STDOUT:
 // CHECK:STDOUT:
 // CHECK:STDOUT: fn @F(%p: const i32**) -> const i32** {
 // CHECK:STDOUT: fn @F(%p: const i32**) -> const i32** {

+ 11 - 1
toolchain/check/testdata/const/fail_collapse.carbon

@@ -26,7 +26,17 @@ fn G(p: const (const i32)**) -> i32** {
 // CHECK:STDOUT:
 // CHECK:STDOUT:
 // CHECK:STDOUT: file {
 // CHECK:STDOUT: file {
 // CHECK:STDOUT:   package: <namespace> = namespace {.G = %G} [template]
 // CHECK:STDOUT:   package: <namespace> = namespace {.G = %G} [template]
-// CHECK:STDOUT:   %G: <function> = fn_decl @G [template]
+// CHECK:STDOUT:   %G: <function> = fn_decl @G {
+// CHECK:STDOUT:     %.loc10_16: type = const_type i32 [template = constants.%.1]
+// CHECK:STDOUT:     %.loc10_9: type = const_type const i32 [template = constants.%.1]
+// CHECK:STDOUT:     %.loc10_26: type = ptr_type const i32 [template = constants.%.2]
+// CHECK:STDOUT:     %.loc10_27: type = ptr_type const i32* [template = constants.%.3]
+// CHECK:STDOUT:     %p.loc10_6.1: const i32** = param p
+// CHECK:STDOUT:     @G.%p: const i32** = bind_name p, %p.loc10_6.1
+// CHECK:STDOUT:     %.loc10_36: type = ptr_type i32 [template = constants.%.4]
+// CHECK:STDOUT:     %.loc10_37: type = ptr_type i32* [template = constants.%.5]
+// CHECK:STDOUT:     %return.var: ref i32** = var <return slot>
+// CHECK:STDOUT:   } [template]
 // CHECK:STDOUT: }
 // CHECK:STDOUT: }
 // CHECK:STDOUT:
 // CHECK:STDOUT:
 // CHECK:STDOUT: fn @G(%p: const i32**) -> i32** {
 // CHECK:STDOUT: fn @G(%p: const i32**) -> i32** {

+ 4 - 1
toolchain/check/testdata/const/import.carbon

@@ -31,7 +31,10 @@ var a_ptr: const i32* = a_ptr_ref;
 // CHECK:STDOUT:
 // CHECK:STDOUT:
 // CHECK:STDOUT: file {
 // CHECK:STDOUT: file {
 // CHECK:STDOUT:   package: <namespace> = namespace {.F = %F, .a_ref = %a_ref, .a_ptr_ref = %a_ptr_ref} [template]
 // CHECK:STDOUT:   package: <namespace> = namespace {.F = %F, .a_ref = %a_ref, .a_ptr_ref = %a_ptr_ref} [template]
-// CHECK:STDOUT:   %F: <function> = fn_decl @F [template]
+// CHECK:STDOUT:   %F: <function> = fn_decl @F {
+// CHECK:STDOUT:     %.loc4: type = const_type i32 [template = constants.%.1]
+// CHECK:STDOUT:     %return.var: ref const i32 = var <return slot>
+// CHECK:STDOUT:   } [template]
 // CHECK:STDOUT:   %.loc6: type = const_type i32 [template = constants.%.1]
 // CHECK:STDOUT:   %.loc6: type = const_type i32 [template = constants.%.1]
 // CHECK:STDOUT:   %a_ref.var: ref const i32 = var a_ref
 // CHECK:STDOUT:   %a_ref.var: ref const i32 = var a_ref
 // CHECK:STDOUT:   %a_ref: ref const i32 = bind_name a_ref, %a_ref.var
 // CHECK:STDOUT:   %a_ref: ref const i32 = bind_name a_ref, %a_ref.var

+ 4 - 1
toolchain/check/testdata/eval/fail_symbolic.carbon

@@ -16,7 +16,10 @@ fn G(N:! i32) {
 // CHECK:STDOUT:
 // CHECK:STDOUT:
 // CHECK:STDOUT: file {
 // CHECK:STDOUT: file {
 // CHECK:STDOUT:   package: <namespace> = namespace {.G = %G} [template]
 // CHECK:STDOUT:   package: <namespace> = namespace {.G = %G} [template]
-// CHECK:STDOUT:   %G: <function> = fn_decl @G [template]
+// CHECK:STDOUT:   %G: <function> = fn_decl @G {
+// CHECK:STDOUT:     %N.loc8_6.1: i32 = param N
+// CHECK:STDOUT:     @G.%N: i32 = bind_symbolic_name N, %N.loc8_6.1 [symbolic]
+// CHECK:STDOUT:   } [template]
 // CHECK:STDOUT: }
 // CHECK:STDOUT: }
 // CHECK:STDOUT:
 // CHECK:STDOUT:
 // CHECK:STDOUT: fn @G(%N: i32) {
 // CHECK:STDOUT: fn @G(%N: i32) {

+ 4 - 1
toolchain/check/testdata/eval/symbolic.carbon

@@ -28,7 +28,10 @@ fn F(T:! type) {
 // CHECK:STDOUT:
 // CHECK:STDOUT:
 // CHECK:STDOUT: file {
 // CHECK:STDOUT: file {
 // CHECK:STDOUT:   package: <namespace> = namespace {.F = %F} [template]
 // CHECK:STDOUT:   package: <namespace> = namespace {.F = %F} [template]
-// CHECK:STDOUT:   %F: <function> = fn_decl @F [template]
+// CHECK:STDOUT:   %F: <function> = fn_decl @F {
+// CHECK:STDOUT:     %T.loc8_6.1: type = param T
+// CHECK:STDOUT:     @F.%T: type = bind_symbolic_name T, %T.loc8_6.1 [symbolic]
+// CHECK:STDOUT:   } [template]
 // CHECK:STDOUT: }
 // CHECK:STDOUT: }
 // CHECK:STDOUT:
 // CHECK:STDOUT:
 // CHECK:STDOUT: fn @F(%T: type) {
 // CHECK:STDOUT: fn @F(%T: type) {

+ 13 - 3
toolchain/check/testdata/expr_category/in_place_tuple_init.carbon

@@ -27,9 +27,19 @@ fn H() -> i32 {
 // CHECK:STDOUT:
 // CHECK:STDOUT:
 // CHECK:STDOUT: file {
 // CHECK:STDOUT: file {
 // CHECK:STDOUT:   package: <namespace> = namespace {.F = %F, .G = %G, .H = %H} [template]
 // CHECK:STDOUT:   package: <namespace> = namespace {.F = %F, .G = %G, .H = %H} [template]
-// CHECK:STDOUT:   %F: <function> = fn_decl @F [template]
-// CHECK:STDOUT:   %G: <function> = fn_decl @G [template]
-// CHECK:STDOUT:   %H: <function> = fn_decl @H [template]
+// CHECK:STDOUT:   %F: <function> = fn_decl @F {
+// CHECK:STDOUT:     %.loc7_20.1: (type, type) = tuple_literal (i32, i32)
+// CHECK:STDOUT:     %.loc7_20.2: type = converted %.loc7_20.1, constants.%.2 [template = constants.%.2]
+// CHECK:STDOUT:     @F.%return: ref (i32, i32) = var <return slot>
+// CHECK:STDOUT:   } [template]
+// CHECK:STDOUT:   %G: <function> = fn_decl @G {
+// CHECK:STDOUT:     %.loc9_20.1: (type, type) = tuple_literal (i32, i32)
+// CHECK:STDOUT:     %.loc9_20.2: type = converted %.loc9_20.1, constants.%.2 [template = constants.%.2]
+// CHECK:STDOUT:     @G.%return: ref (i32, i32) = var <return slot>
+// CHECK:STDOUT:   } [template]
+// CHECK:STDOUT:   %H: <function> = fn_decl @H {
+// CHECK:STDOUT:     %return.var.loc15: ref i32 = var <return slot>
+// CHECK:STDOUT:   } [template]
 // CHECK:STDOUT: }
 // CHECK:STDOUT: }
 // CHECK:STDOUT:
 // CHECK:STDOUT:
 // CHECK:STDOUT: fn @F() -> %return: (i32, i32);
 // CHECK:STDOUT: fn @F() -> %return: (i32, i32);

+ 4 - 2
toolchain/check/testdata/function/call/alias.carbon

@@ -20,10 +20,12 @@ fn Main() {
 // CHECK:STDOUT:
 // CHECK:STDOUT:
 // CHECK:STDOUT: file {
 // CHECK:STDOUT: file {
 // CHECK:STDOUT:   package: <namespace> = namespace {.A = %A, .B = %B, .Main = %Main} [template]
 // CHECK:STDOUT:   package: <namespace> = namespace {.A = %A, .B = %B, .Main = %Main} [template]
-// CHECK:STDOUT:   %A: <function> = fn_decl @A [template]
+// CHECK:STDOUT:   %A: <function> = fn_decl @A {
+// CHECK:STDOUT:     %return.var: ref i32 = var <return slot>
+// CHECK:STDOUT:   } [template]
 // CHECK:STDOUT:   %A.ref: <function> = name_ref A, %A [template = %A]
 // CHECK:STDOUT:   %A.ref: <function> = name_ref A, %A [template = %A]
 // CHECK:STDOUT:   %B: <function> = bind_alias B, %A [template = %A]
 // CHECK:STDOUT:   %B: <function> = bind_alias B, %A [template = %A]
-// CHECK:STDOUT:   %Main: <function> = fn_decl @Main [template]
+// CHECK:STDOUT:   %Main: <function> = fn_decl @Main {} [template]
 // CHECK:STDOUT: }
 // CHECK:STDOUT: }
 // CHECK:STDOUT:
 // CHECK:STDOUT:
 // CHECK:STDOUT: fn @A() -> i32 {
 // CHECK:STDOUT: fn @A() -> i32 {

+ 10 - 2
toolchain/check/testdata/function/call/empty_struct.carbon

@@ -22,8 +22,16 @@ fn Main() {
 // CHECK:STDOUT:
 // CHECK:STDOUT:
 // CHECK:STDOUT: file {
 // CHECK:STDOUT: file {
 // CHECK:STDOUT:   package: <namespace> = namespace {.Echo = %Echo, .Main = %Main} [template]
 // CHECK:STDOUT:   package: <namespace> = namespace {.Echo = %Echo, .Main = %Main} [template]
-// CHECK:STDOUT:   %Echo: <function> = fn_decl @Echo [template]
-// CHECK:STDOUT:   %Main: <function> = fn_decl @Main [template]
+// CHECK:STDOUT:   %Echo: <function> = fn_decl @Echo {
+// CHECK:STDOUT:     %.loc7_13.1: {} = struct_literal ()
+// CHECK:STDOUT:     %.loc7_13.2: type = converted %.loc7_13.1, constants.%.1 [template = constants.%.1]
+// CHECK:STDOUT:     %a.loc7_9.1: {} = param a
+// CHECK:STDOUT:     @Echo.%a: {} = bind_name a, %a.loc7_9.1
+// CHECK:STDOUT:     %.loc7_20.1: {} = struct_literal ()
+// CHECK:STDOUT:     %.loc7_20.2: type = converted %.loc7_20.1, constants.%.1 [template = constants.%.1]
+// CHECK:STDOUT:     %return.var: ref {} = var <return slot>
+// CHECK:STDOUT:   } [template]
+// CHECK:STDOUT:   %Main: <function> = fn_decl @Main {} [template]
 // CHECK:STDOUT: }
 // CHECK:STDOUT: }
 // CHECK:STDOUT:
 // CHECK:STDOUT:
 // CHECK:STDOUT: fn @Echo(%a: {}) -> {} {
 // CHECK:STDOUT: fn @Echo(%a: {}) -> {} {

Некоторые файлы не были показаны из-за большого количества измененных файлов