浏览代码

Convert literals to `i32` when forming an `i32`-typed `int_literal` instruction. (#3814)

This is temporary: eventually per the design we should be forming
integer literals whose types reflect their values. But for now we should
ensure that values fit within their types.

This also fixes canonicalization of integer constants and hence of array
types, because we no longer have multiple different representations of
each `i32` value depending on the bit-width used for the literal.
Richard Smith 2 年之前
父节点
当前提交
3763d0130a
共有 27 个文件被更改,包括 463 次插入313 次删除
  1. 17 2
      toolchain/check/handle_literal.cpp
  2. 10 12
      toolchain/check/testdata/array/array_vs_tuple.carbon
  3. 1 2
      toolchain/check/testdata/array/assign_return_value.carbon
  4. 2 4
      toolchain/check/testdata/array/assign_var.carbon
  5. 32 34
      toolchain/check/testdata/array/base.carbon
  6. 74 0
      toolchain/check/testdata/array/canonicalize_index.carbon
  7. 30 0
      toolchain/check/testdata/array/fail_bound_negative.carbon
  8. 13 9
      toolchain/check/testdata/array/fail_bound_overflow.carbon
  9. 9 11
      toolchain/check/testdata/array/fail_out_of_bound_non_literal.carbon
  10. 9 10
      toolchain/check/testdata/array/fail_type_mismatch.carbon
  11. 5 7
      toolchain/check/testdata/array/function_param.carbon
  12. 9 11
      toolchain/check/testdata/array/index_not_literal.carbon
  13. 11 19
      toolchain/check/testdata/array/nine_elements.carbon
  14. 32 0
      toolchain/check/testdata/basics/fail_numeric_literal_overflow.carbon
  15. 82 78
      toolchain/check/testdata/basics/numeric_literals.carbon
  16. 2 2
      toolchain/check/testdata/basics/raw_and_textual_ir.carbon
  17. 2 2
      toolchain/check/testdata/basics/raw_ir.carbon
  18. 12 13
      toolchain/check/testdata/eval/aggregate.carbon
  19. 10 13
      toolchain/check/testdata/eval/fail_aggregate.carbon
  20. 20 23
      toolchain/check/testdata/function/builtin/call_from_operator.carbon
  21. 10 13
      toolchain/check/testdata/function/builtin/import.carbon
  22. 4 5
      toolchain/check/testdata/if_expr/basic.carbon
  23. 2 4
      toolchain/check/testdata/index/array_element_access.carbon
  24. 18 21
      toolchain/check/testdata/index/expr_category.carbon
  25. 25 10
      toolchain/check/testdata/index/fail_array_large_index.carbon
  26. 21 8
      toolchain/check/testdata/index/fail_tuple_large_index.carbon
  27. 1 0
      toolchain/diagnostics/diagnostic_kind.def

+ 17 - 2
toolchain/check/handle_literal.cpp

@@ -25,11 +25,26 @@ auto HandleBoolLiteralTrue(Context& context, Parse::BoolLiteralTrueId node_id)
 }
 
 auto HandleIntLiteral(Context& context, Parse::IntLiteralId node_id) -> bool {
+  // Convert the literal to i32.
+  // TODO: Form an integer literal value and a corresponding type here instead.
+  auto literal_int_id =
+      context.tokens().GetIntLiteral(context.parse_tree().node_token(node_id));
+  auto literal_val = context.ints().Get(literal_int_id);
+  if (literal_val.getActiveBits() > 31) {
+    CARBON_DIAGNOSTIC(IntLiteralTooLargeForI32, Error,
+                      "Integer literal with value {0} does not fit in i32.",
+                      llvm::APSInt);
+    context.emitter().Emit(node_id, IntLiteralTooLargeForI32,
+                           llvm::APSInt(literal_val, /*isUnsigned=*/true));
+    context.node_stack().Push(node_id, SemIR::InstId::BuiltinError);
+    return true;
+  }
+  // Literals are always represented as unsigned, so zero-extend if needed.
+  auto i32_val = literal_val.zextOrTrunc(32);
   context.AddInstAndPush(
       {node_id,
        SemIR::IntLiteral{context.GetBuiltinType(SemIR::BuiltinKind::IntType),
-                         context.tokens().GetIntLiteral(
-                             context.parse_tree().node_token(node_id))}});
+                         context.ints().Add(i32_val)}});
   return true;
 }
 

+ 10 - 12
toolchain/check/testdata/array/array_vs_tuple.carbon

@@ -20,12 +20,10 @@ fn G() {
 // CHECK:STDOUT:   %.5: i32 = int_literal 2 [template]
 // CHECK:STDOUT:   %.6: type = tuple_type (i32, i32, i32) [template]
 // CHECK:STDOUT:   %.7: i32 = int_literal 0 [template]
-// CHECK:STDOUT:   %.8: i32 = int_literal 1 [template]
-// CHECK:STDOUT:   %.9: i32 = int_literal 2 [template]
-// CHECK:STDOUT:   %.10: [i32; 3] = tuple_value (%.4, %.5, %.1) [template]
-// CHECK:STDOUT:   %.11: type = tuple_type (type, type, type) [template]
-// CHECK:STDOUT:   %.12: type = ptr_type (i32, i32, i32) [template]
-// CHECK:STDOUT:   %.13: (i32, i32, i32) = tuple_value (%.4, %.5, %.1) [template]
+// CHECK:STDOUT:   %.8: [i32; 3] = tuple_value (%.4, %.5, %.1) [template]
+// CHECK:STDOUT:   %.9: type = tuple_type (type, type, type) [template]
+// CHECK:STDOUT:   %.10: type = ptr_type (i32, i32, i32) [template]
+// CHECK:STDOUT:   %.11: (i32, i32, i32) = tuple_value (%.4, %.5, %.1) [template]
 // CHECK:STDOUT: }
 // CHECK:STDOUT:
 // CHECK:STDOUT: file {
@@ -48,14 +46,14 @@ fn G() {
 // CHECK:STDOUT:   %.loc9_29.2: i32 = int_literal 0 [template = constants.%.7]
 // CHECK:STDOUT:   %.loc9_29.3: ref i32 = array_index %a.var, %.loc9_29.2
 // CHECK:STDOUT:   %.loc9_29.4: init i32 = initialize_from %.loc9_22 to %.loc9_29.3 [template = constants.%.4]
-// CHECK:STDOUT:   %.loc9_29.5: i32 = int_literal 1 [template = constants.%.8]
+// CHECK:STDOUT:   %.loc9_29.5: i32 = int_literal 1 [template = constants.%.4]
 // CHECK:STDOUT:   %.loc9_29.6: ref i32 = array_index %a.var, %.loc9_29.5
 // CHECK:STDOUT:   %.loc9_29.7: init i32 = initialize_from %.loc9_25 to %.loc9_29.6 [template = constants.%.5]
-// CHECK:STDOUT:   %.loc9_29.8: i32 = int_literal 2 [template = constants.%.9]
+// CHECK:STDOUT:   %.loc9_29.8: i32 = int_literal 2 [template = constants.%.5]
 // CHECK:STDOUT:   %.loc9_29.9: ref i32 = array_index %a.var, %.loc9_29.8
 // CHECK:STDOUT:   %.loc9_29.10: init i32 = initialize_from %.loc9_28 to %.loc9_29.9 [template = constants.%.1]
-// CHECK:STDOUT:   %.loc9_29.11: init [i32; 3] = array_init (%.loc9_29.4, %.loc9_29.7, %.loc9_29.10) to %a.var [template = constants.%.10]
-// CHECK:STDOUT:   %.loc9_29.12: init [i32; 3] = converted %.loc9_29.1, %.loc9_29.11 [template = constants.%.10]
+// CHECK:STDOUT:   %.loc9_29.11: init [i32; 3] = array_init (%.loc9_29.4, %.loc9_29.7, %.loc9_29.10) to %a.var [template = constants.%.8]
+// CHECK:STDOUT:   %.loc9_29.12: init [i32; 3] = converted %.loc9_29.1, %.loc9_29.11 [template = constants.%.8]
 // CHECK:STDOUT:   assign %a.var, %.loc9_29.12
 // CHECK:STDOUT:   %.loc10_24.1: (type, type, type) = tuple_literal (i32, i32, i32)
 // CHECK:STDOUT:   %.loc10_24.2: type = converted %.loc10_24.1, constants.%.6 [template = constants.%.6]
@@ -71,8 +69,8 @@ fn G() {
 // CHECK:STDOUT:   %.loc10_36.5: init i32 = initialize_from %.loc10_32 to %.loc10_36.4 [template = constants.%.5]
 // CHECK:STDOUT:   %.loc10_36.6: ref i32 = tuple_access %b.var, element2
 // CHECK:STDOUT:   %.loc10_36.7: init i32 = initialize_from %.loc10_35 to %.loc10_36.6 [template = constants.%.1]
-// CHECK:STDOUT:   %.loc10_36.8: init (i32, i32, i32) = tuple_init (%.loc10_36.3, %.loc10_36.5, %.loc10_36.7) to %b.var [template = constants.%.13]
-// CHECK:STDOUT:   %.loc10_36.9: init (i32, i32, i32) = converted %.loc10_36.1, %.loc10_36.8 [template = constants.%.13]
+// CHECK:STDOUT:   %.loc10_36.8: init (i32, i32, i32) = tuple_init (%.loc10_36.3, %.loc10_36.5, %.loc10_36.7) to %b.var [template = constants.%.11]
+// CHECK:STDOUT:   %.loc10_36.9: init (i32, i32, i32) = converted %.loc10_36.1, %.loc10_36.8 [template = constants.%.11]
 // CHECK:STDOUT:   assign %b.var, %.loc10_36.9
 // CHECK:STDOUT:   return
 // CHECK:STDOUT: }

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

@@ -20,7 +20,6 @@ fn Run() {
 // CHECK:STDOUT:   %.5: i32 = int_literal 1 [template]
 // CHECK:STDOUT:   %.6: type = array_type %.5, i32 [template]
 // CHECK:STDOUT:   %.7: type = ptr_type [i32; 1] [template]
-// CHECK:STDOUT:   %.8: i32 = int_literal 0 [template]
 // CHECK:STDOUT: }
 // CHECK:STDOUT:
 // CHECK:STDOUT: file {
@@ -57,7 +56,7 @@ fn Run() {
 // CHECK:STDOUT:   %.loc10_22.3: ref (i32,) = temporary %.loc10_22.2, %.loc10_22.1
 // CHECK:STDOUT:   %.loc10_22.4: ref i32 = tuple_access %.loc10_22.3, element0
 // CHECK:STDOUT:   %.loc10_22.5: i32 = bind_value %.loc10_22.4
-// CHECK:STDOUT:   %.loc10_22.6: i32 = int_literal 0 [template = constants.%.8]
+// CHECK:STDOUT:   %.loc10_22.6: i32 = int_literal 0 [template = constants.%.3]
 // CHECK:STDOUT:   %.loc10_22.7: ref i32 = array_index %t.var, %.loc10_22.6
 // CHECK:STDOUT:   %.loc10_22.8: init i32 = initialize_from %.loc10_22.5 to %.loc10_22.7
 // CHECK:STDOUT:   %.loc10_22.9: init [i32; 1] = array_init (%.loc10_22.8) to %t.var

+ 2 - 4
toolchain/check/testdata/array/assign_var.carbon

@@ -20,8 +20,6 @@ var b: [i32; 3] = a;
 // CHECK:STDOUT:   %.8: type = array_type %.6, i32 [template]
 // CHECK:STDOUT:   %.9: type = ptr_type [i32; 3] [template]
 // CHECK:STDOUT:   %.10: i32 = int_literal 0 [template]
-// CHECK:STDOUT:   %.11: i32 = int_literal 1 [template]
-// CHECK:STDOUT:   %.12: i32 = int_literal 2 [template]
 // CHECK:STDOUT: }
 // CHECK:STDOUT:
 // CHECK:STDOUT: file {
@@ -62,12 +60,12 @@ var b: [i32; 3] = a;
 // CHECK:STDOUT:   %.loc8_19.5: init i32 = initialize_from %.loc8_19.2 to %.loc8_19.4
 // CHECK:STDOUT:   %.loc8_19.6: ref i32 = tuple_access %a.ref, element1
 // CHECK:STDOUT:   %.loc8_19.7: i32 = bind_value %.loc8_19.6
-// CHECK:STDOUT:   %.loc8_19.8: i32 = int_literal 1 [template = constants.%.11]
+// CHECK:STDOUT:   %.loc8_19.8: i32 = int_literal 1 [template = constants.%.4]
 // CHECK:STDOUT:   %.loc8_19.9: ref i32 = array_index file.%b.var, %.loc8_19.8
 // CHECK:STDOUT:   %.loc8_19.10: init i32 = initialize_from %.loc8_19.7 to %.loc8_19.9
 // CHECK:STDOUT:   %.loc8_19.11: ref i32 = tuple_access %a.ref, element2
 // CHECK:STDOUT:   %.loc8_19.12: i32 = bind_value %.loc8_19.11
-// CHECK:STDOUT:   %.loc8_19.13: i32 = int_literal 2 [template = constants.%.12]
+// CHECK:STDOUT:   %.loc8_19.13: i32 = int_literal 2 [template = constants.%.5]
 // CHECK:STDOUT:   %.loc8_19.14: ref i32 = array_index file.%b.var, %.loc8_19.13
 // CHECK:STDOUT:   %.loc8_19.15: init i32 = initialize_from %.loc8_19.12 to %.loc8_19.14
 // CHECK:STDOUT:   %.loc8_19.16: init [i32; 3] = array_init (%.loc8_19.5, %.loc8_19.10, %.loc8_19.15) to file.%b.var

+ 32 - 34
toolchain/check/testdata/array/base.carbon

@@ -23,18 +23,16 @@ var c: [(); 5] = ((), (), (), (), (),);
 // CHECK:STDOUT:   %.10: f64 = real_literal 111e-1 [template]
 // CHECK:STDOUT:   %.11: f64 = real_literal 22e-1 [template]
 // CHECK:STDOUT:   %.12: type = tuple_type (f64, f64) [template]
-// CHECK:STDOUT:   %.13: i32 = int_literal 1 [template]
-// CHECK:STDOUT:   %.14: [f64; 2] = tuple_value (%.10, %.11) [template]
-// CHECK:STDOUT:   %.15: type = tuple_type () [template]
-// CHECK:STDOUT:   %.16: i32 = int_literal 5 [template]
-// CHECK:STDOUT:   %.17: type = array_type %.16, () [template]
-// CHECK:STDOUT:   %.18: type = ptr_type [(); 5] [template]
-// CHECK:STDOUT:   %.19: type = tuple_type ((), (), (), (), ()) [template]
-// CHECK:STDOUT:   %.20: () = tuple_value () [template]
-// CHECK:STDOUT:   %.21: i32 = int_literal 2 [template]
-// CHECK:STDOUT:   %.22: i32 = int_literal 3 [template]
-// CHECK:STDOUT:   %.23: i32 = int_literal 4 [template]
-// CHECK:STDOUT:   %.24: [(); 5] = tuple_value (%.20, %.20, %.20, %.20, %.20) [template]
+// CHECK:STDOUT:   %.13: [f64; 2] = tuple_value (%.10, %.11) [template]
+// CHECK:STDOUT:   %.14: type = tuple_type () [template]
+// CHECK:STDOUT:   %.15: i32 = int_literal 5 [template]
+// CHECK:STDOUT:   %.16: type = array_type %.15, () [template]
+// CHECK:STDOUT:   %.17: type = ptr_type [(); 5] [template]
+// CHECK:STDOUT:   %.18: type = tuple_type ((), (), (), (), ()) [template]
+// CHECK:STDOUT:   %.19: () = tuple_value () [template]
+// CHECK:STDOUT:   %.20: i32 = int_literal 3 [template]
+// CHECK:STDOUT:   %.21: i32 = int_literal 4 [template]
+// CHECK:STDOUT:   %.22: [(); 5] = tuple_value (%.19, %.19, %.19, %.19, %.19) [template]
 // CHECK:STDOUT: }
 // CHECK:STDOUT:
 // CHECK:STDOUT: file {
@@ -52,9 +50,9 @@ var c: [(); 5] = ((), (), (), (), (),);
 // CHECK:STDOUT:   %b.var: ref [f64; 2] = var b
 // CHECK:STDOUT:   %b: ref [f64; 2] = bind_name b, %b.var
 // CHECK:STDOUT:   %.loc9_10.1: () = tuple_literal ()
-// CHECK:STDOUT:   %.loc9_13: i32 = int_literal 5 [template = constants.%.16]
-// CHECK:STDOUT:   %.loc9_10.2: type = converted %.loc9_10.1, constants.%.15 [template = constants.%.15]
-// CHECK:STDOUT:   %.loc9_14: type = array_type %.loc9_13, () [template = constants.%.17]
+// CHECK:STDOUT:   %.loc9_13: i32 = int_literal 5 [template = constants.%.15]
+// CHECK:STDOUT:   %.loc9_10.2: type = converted %.loc9_10.1, constants.%.14 [template = constants.%.14]
+// CHECK:STDOUT:   %.loc9_14: type = array_type %.loc9_13, () [template = constants.%.16]
 // CHECK:STDOUT:   %c.var: ref [(); 5] = var c
 // CHECK:STDOUT:   %c: ref [(); 5] = bind_name c, %c.var
 // CHECK:STDOUT: }
@@ -75,11 +73,11 @@ var c: [(); 5] = ((), (), (), (), (),);
 // CHECK:STDOUT:   %.loc8_30.2: i32 = int_literal 0 [template = constants.%.5]
 // CHECK:STDOUT:   %.loc8_30.3: ref f64 = array_index file.%b.var, %.loc8_30.2
 // CHECK:STDOUT:   %.loc8_30.4: init f64 = initialize_from %.loc8_20 to %.loc8_30.3 [template = constants.%.10]
-// CHECK:STDOUT:   %.loc8_30.5: i32 = int_literal 1 [template = constants.%.13]
+// CHECK:STDOUT:   %.loc8_30.5: i32 = int_literal 1 [template = constants.%.1]
 // CHECK:STDOUT:   %.loc8_30.6: ref f64 = array_index file.%b.var, %.loc8_30.5
 // CHECK:STDOUT:   %.loc8_30.7: init f64 = initialize_from %.loc8_26 to %.loc8_30.6 [template = constants.%.11]
-// CHECK:STDOUT:   %.loc8_30.8: init [f64; 2] = array_init (%.loc8_30.4, %.loc8_30.7) to file.%b.var [template = constants.%.14]
-// CHECK:STDOUT:   %.loc8_30.9: init [f64; 2] = converted %.loc8_30.1, %.loc8_30.8 [template = constants.%.14]
+// CHECK:STDOUT:   %.loc8_30.8: init [f64; 2] = array_init (%.loc8_30.4, %.loc8_30.7) to file.%b.var [template = constants.%.13]
+// CHECK:STDOUT:   %.loc8_30.9: init [f64; 2] = converted %.loc8_30.1, %.loc8_30.8 [template = constants.%.13]
 // CHECK:STDOUT:   assign file.%b.var, %.loc8_30.9
 // CHECK:STDOUT:   %.loc9_20.1: () = tuple_literal ()
 // CHECK:STDOUT:   %.loc9_24.1: () = tuple_literal ()
@@ -89,26 +87,26 @@ var c: [(); 5] = ((), (), (), (), (),);
 // CHECK:STDOUT:   %.loc9_38.1: ((), (), (), (), ()) = tuple_literal (%.loc9_20.1, %.loc9_24.1, %.loc9_28.1, %.loc9_32.1, %.loc9_36.1)
 // CHECK:STDOUT:   %.loc9_38.2: i32 = int_literal 0 [template = constants.%.5]
 // CHECK:STDOUT:   %.loc9_38.3: ref () = array_index file.%c.var, %.loc9_38.2
-// CHECK:STDOUT:   %.loc9_20.2: init () = tuple_init () to %.loc9_38.3 [template = constants.%.20]
-// CHECK:STDOUT:   %.loc9_20.3: init () = converted %.loc9_20.1, %.loc9_20.2 [template = constants.%.20]
-// CHECK:STDOUT:   %.loc9_38.4: i32 = int_literal 1 [template = constants.%.13]
+// CHECK:STDOUT:   %.loc9_20.2: init () = tuple_init () to %.loc9_38.3 [template = constants.%.19]
+// CHECK:STDOUT:   %.loc9_20.3: init () = converted %.loc9_20.1, %.loc9_20.2 [template = constants.%.19]
+// CHECK:STDOUT:   %.loc9_38.4: i32 = int_literal 1 [template = constants.%.1]
 // CHECK:STDOUT:   %.loc9_38.5: ref () = array_index file.%c.var, %.loc9_38.4
-// CHECK:STDOUT:   %.loc9_24.2: init () = tuple_init () to %.loc9_38.5 [template = constants.%.20]
-// CHECK:STDOUT:   %.loc9_24.3: init () = converted %.loc9_24.1, %.loc9_24.2 [template = constants.%.20]
-// CHECK:STDOUT:   %.loc9_38.6: i32 = int_literal 2 [template = constants.%.21]
+// CHECK:STDOUT:   %.loc9_24.2: init () = tuple_init () to %.loc9_38.5 [template = constants.%.19]
+// CHECK:STDOUT:   %.loc9_24.3: init () = converted %.loc9_24.1, %.loc9_24.2 [template = constants.%.19]
+// CHECK:STDOUT:   %.loc9_38.6: i32 = int_literal 2 [template = constants.%.7]
 // CHECK:STDOUT:   %.loc9_38.7: ref () = array_index file.%c.var, %.loc9_38.6
-// CHECK:STDOUT:   %.loc9_28.2: init () = tuple_init () to %.loc9_38.7 [template = constants.%.20]
-// CHECK:STDOUT:   %.loc9_28.3: init () = converted %.loc9_28.1, %.loc9_28.2 [template = constants.%.20]
-// CHECK:STDOUT:   %.loc9_38.8: i32 = int_literal 3 [template = constants.%.22]
+// CHECK:STDOUT:   %.loc9_28.2: init () = tuple_init () to %.loc9_38.7 [template = constants.%.19]
+// CHECK:STDOUT:   %.loc9_28.3: init () = converted %.loc9_28.1, %.loc9_28.2 [template = constants.%.19]
+// CHECK:STDOUT:   %.loc9_38.8: i32 = int_literal 3 [template = constants.%.20]
 // CHECK:STDOUT:   %.loc9_38.9: ref () = array_index file.%c.var, %.loc9_38.8
-// CHECK:STDOUT:   %.loc9_32.2: init () = tuple_init () to %.loc9_38.9 [template = constants.%.20]
-// CHECK:STDOUT:   %.loc9_32.3: init () = converted %.loc9_32.1, %.loc9_32.2 [template = constants.%.20]
-// CHECK:STDOUT:   %.loc9_38.10: i32 = int_literal 4 [template = constants.%.23]
+// CHECK:STDOUT:   %.loc9_32.2: init () = tuple_init () to %.loc9_38.9 [template = constants.%.19]
+// CHECK:STDOUT:   %.loc9_32.3: init () = converted %.loc9_32.1, %.loc9_32.2 [template = constants.%.19]
+// CHECK:STDOUT:   %.loc9_38.10: i32 = int_literal 4 [template = constants.%.21]
 // CHECK:STDOUT:   %.loc9_38.11: ref () = array_index file.%c.var, %.loc9_38.10
-// CHECK:STDOUT:   %.loc9_36.2: init () = tuple_init () to %.loc9_38.11 [template = constants.%.20]
-// CHECK:STDOUT:   %.loc9_36.3: init () = converted %.loc9_36.1, %.loc9_36.2 [template = constants.%.20]
-// CHECK:STDOUT:   %.loc9_38.12: init [(); 5] = array_init (%.loc9_20.3, %.loc9_24.3, %.loc9_28.3, %.loc9_32.3, %.loc9_36.3) to file.%c.var [template = constants.%.24]
-// CHECK:STDOUT:   %.loc9_38.13: init [(); 5] = converted %.loc9_38.1, %.loc9_38.12 [template = constants.%.24]
+// CHECK:STDOUT:   %.loc9_36.2: init () = tuple_init () to %.loc9_38.11 [template = constants.%.19]
+// CHECK:STDOUT:   %.loc9_36.3: init () = converted %.loc9_36.1, %.loc9_36.2 [template = constants.%.19]
+// CHECK:STDOUT:   %.loc9_38.12: init [(); 5] = array_init (%.loc9_20.3, %.loc9_24.3, %.loc9_28.3, %.loc9_32.3, %.loc9_36.3) to file.%c.var [template = constants.%.22]
+// CHECK:STDOUT:   %.loc9_38.13: init [(); 5] = converted %.loc9_38.1, %.loc9_38.12 [template = constants.%.22]
 // CHECK:STDOUT:   assign file.%c.var, %.loc9_38.13
 // CHECK:STDOUT:   return
 // CHECK:STDOUT: }

+ 74 - 0
toolchain/check/testdata/array/canonicalize_index.carbon

@@ -0,0 +1,74 @@
+// Part of the Carbon Language project, under the Apache License v2.0 with LLVM
+// Exceptions. See /LICENSE for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+// AUTOUPDATE
+
+fn Add(a: i32, b: i32) -> i32 = "int.add";
+
+var a: [i32; Add(1, 2)] = (1, 2, 3);
+let b: [i32; 3]* = &a;
+
+// CHECK:STDOUT: --- canonicalize_index.carbon
+// CHECK:STDOUT:
+// CHECK:STDOUT: constants {
+// CHECK:STDOUT:   %.1: i32 = int_literal 1 [template]
+// CHECK:STDOUT:   %.2: i32 = int_literal 2 [template]
+// CHECK:STDOUT:   %.3: i32 = int_literal 3 [template]
+// CHECK:STDOUT:   %.4: type = array_type %.3, i32 [template]
+// CHECK:STDOUT:   %.5: type = ptr_type [i32; 3] [template]
+// CHECK:STDOUT:   %.6: type = tuple_type (i32, i32, i32) [template]
+// CHECK:STDOUT:   %.7: i32 = int_literal 0 [template]
+// CHECK:STDOUT:   %.8: [i32; 3] = tuple_value (%.1, %.2, %.3) [template]
+// CHECK:STDOUT: }
+// CHECK:STDOUT:
+// CHECK:STDOUT: file {
+// CHECK:STDOUT:   package: <namespace> = namespace [template] {
+// CHECK:STDOUT:     .Add = %Add
+// CHECK:STDOUT:     .a = %a.loc9
+// CHECK:STDOUT:   }
+// CHECK:STDOUT:   %Add: <function> = fn_decl @Add [template] {
+// CHECK:STDOUT:     %a.loc7_8.1: i32 = param a
+// CHECK:STDOUT:     @Add.%a: i32 = bind_name a, %a.loc7_8.1
+// CHECK:STDOUT:     %b.loc7_16.1: i32 = param b
+// CHECK:STDOUT:     @Add.%b: i32 = bind_name b, %b.loc7_16.1
+// CHECK:STDOUT:     %return.var: ref i32 = var <return slot>
+// CHECK:STDOUT:   }
+// CHECK:STDOUT:   %Add.ref: <function> = name_ref Add, %Add [template = %Add]
+// CHECK:STDOUT:   %.loc9_18: i32 = int_literal 1 [template = constants.%.1]
+// CHECK:STDOUT:   %.loc9_21: i32 = int_literal 2 [template = constants.%.2]
+// CHECK:STDOUT:   %.loc9_17: init i32 = call %Add.ref(%.loc9_18, %.loc9_21) [template = constants.%.3]
+// CHECK:STDOUT:   %.loc9_23: type = array_type %.loc9_17, i32 [template = constants.%.4]
+// CHECK:STDOUT:   %a.var: ref [i32; 3] = var a
+// CHECK:STDOUT:   %a.loc9: ref [i32; 3] = bind_name a, %a.var
+// CHECK:STDOUT:   %.loc10_14: i32 = int_literal 3 [template = constants.%.3]
+// CHECK:STDOUT:   %.loc10_15: type = array_type %.loc10_14, i32 [template = constants.%.4]
+// CHECK:STDOUT:   %.loc10_16: type = ptr_type [i32; 3] [template = constants.%.5]
+// CHECK:STDOUT:   %a.ref: ref [i32; 3] = name_ref a, %a.loc9
+// CHECK:STDOUT:   %.loc10_20: [i32; 3]* = addr_of %a.ref
+// CHECK:STDOUT:   %b.loc10: [i32; 3]* = bind_name b, %.loc10_20
+// CHECK:STDOUT: }
+// CHECK:STDOUT:
+// CHECK:STDOUT: fn @Add(%a: i32, %b: i32) -> i32 = "int.add";
+// CHECK:STDOUT:
+// CHECK:STDOUT: fn @__global_init() {
+// CHECK:STDOUT: !entry:
+// CHECK:STDOUT:   %.loc9_28: i32 = int_literal 1 [template = constants.%.1]
+// CHECK:STDOUT:   %.loc9_31: i32 = int_literal 2 [template = constants.%.2]
+// CHECK:STDOUT:   %.loc9_34: i32 = int_literal 3 [template = constants.%.3]
+// CHECK:STDOUT:   %.loc9_35.1: (i32, i32, i32) = tuple_literal (%.loc9_28, %.loc9_31, %.loc9_34)
+// CHECK:STDOUT:   %.loc9_35.2: i32 = int_literal 0 [template = constants.%.7]
+// CHECK:STDOUT:   %.loc9_35.3: ref i32 = array_index file.%a.var, %.loc9_35.2
+// CHECK:STDOUT:   %.loc9_35.4: init i32 = initialize_from %.loc9_28 to %.loc9_35.3 [template = constants.%.1]
+// CHECK:STDOUT:   %.loc9_35.5: i32 = int_literal 1 [template = constants.%.1]
+// CHECK:STDOUT:   %.loc9_35.6: ref i32 = array_index file.%a.var, %.loc9_35.5
+// CHECK:STDOUT:   %.loc9_35.7: init i32 = initialize_from %.loc9_31 to %.loc9_35.6 [template = constants.%.2]
+// CHECK:STDOUT:   %.loc9_35.8: i32 = int_literal 2 [template = constants.%.2]
+// CHECK:STDOUT:   %.loc9_35.9: ref i32 = array_index file.%a.var, %.loc9_35.8
+// CHECK:STDOUT:   %.loc9_35.10: init i32 = initialize_from %.loc9_34 to %.loc9_35.9 [template = constants.%.3]
+// CHECK:STDOUT:   %.loc9_35.11: init [i32; 3] = array_init (%.loc9_35.4, %.loc9_35.7, %.loc9_35.10) to file.%a.var [template = constants.%.8]
+// CHECK:STDOUT:   %.loc9_35.12: init [i32; 3] = converted %.loc9_35.1, %.loc9_35.11 [template = constants.%.8]
+// CHECK:STDOUT:   assign file.%a.var, %.loc9_35.12
+// CHECK:STDOUT:   return
+// CHECK:STDOUT: }
+// CHECK:STDOUT:

+ 30 - 0
toolchain/check/testdata/array/fail_bound_negative.carbon

@@ -0,0 +1,30 @@
+// Part of the Carbon Language project, under the Apache License v2.0 with LLVM
+// Exceptions. See /LICENSE for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+// AUTOUPDATE
+
+// TODO: Once we supoprt negating integer literals, check that we reject a
+// negative array bound.
+
+// CHECK:STDERR: fail_bound_negative.carbon:[[@LINE+3]]:14: ERROR: Semantics TODO: `missing or invalid operator interface`.
+// CHECK:STDERR: var a: [i32; -1];
+// CHECK:STDERR:              ^~
+var a: [i32; -1];
+
+// CHECK:STDOUT: --- fail_bound_negative.carbon
+// CHECK:STDOUT:
+// CHECK:STDOUT: constants {
+// CHECK:STDOUT:   %.1: i32 = int_literal 1 [template]
+// CHECK:STDOUT: }
+// CHECK:STDOUT:
+// CHECK:STDOUT: file {
+// CHECK:STDOUT:   package: <namespace> = namespace [template] {
+// CHECK:STDOUT:     .a = %a
+// CHECK:STDOUT:   }
+// CHECK:STDOUT:   %.loc13_15: i32 = int_literal 1 [template = constants.%.1]
+// CHECK:STDOUT:   %.loc13_16: type = array_type <error>, i32 [template = <error>]
+// CHECK:STDOUT:   %a.var: ref <error> = var a
+// CHECK:STDOUT:   %a: ref <error> = bind_name a, %a.var
+// CHECK:STDOUT: }
+// CHECK:STDOUT:

+ 13 - 9
toolchain/check/testdata/array/fail_bound_overflow.carbon

@@ -4,22 +4,28 @@
 //
 // AUTOUPDATE
 
-// CHECK:STDERR: fail_bound_overflow.carbon:[[@LINE+4]]:14: ERROR: Array bound of 39999999999999999993 is too large.
+// TODO: Once we preserve the full value of integer literals in SemIR, check
+// that we reject the array bound being too large.
+
+// CHECK:STDERR: fail_bound_overflow.carbon:[[@LINE+4]]:14: ERROR: Integer literal with value 39999999999999999993 does not fit in i32.
 // CHECK:STDERR: var a: [i32; 39999999999999999993];
 // CHECK:STDERR:              ^~~~~~~~~~~~~~~~~~~~
 // CHECK:STDERR:
 var a: [i32; 39999999999999999993];
 
-// CHECK:STDERR: fail_bound_overflow.carbon:[[@LINE+3]]:9: ERROR: Cannot implicitly convert from `i32` to `type`.
+// CHECK:STDERR: fail_bound_overflow.carbon:[[@LINE+7]]:9: ERROR: Cannot implicitly convert from `i32` to `type`.
 // CHECK:STDERR: var b: [1; 39999999999999999993];
 // CHECK:STDERR:         ^
+// CHECK:STDERR:
+// CHECK:STDERR: fail_bound_overflow.carbon:[[@LINE+3]]:12: ERROR: Integer literal with value 39999999999999999993 does not fit in i32.
+// CHECK:STDERR: var b: [1; 39999999999999999993];
+// CHECK:STDERR:            ^~~~~~~~~~~~~~~~~~~~
 var b: [1; 39999999999999999993];
 
 // CHECK:STDOUT: --- fail_bound_overflow.carbon
 // CHECK:STDOUT:
 // CHECK:STDOUT: constants {
-// CHECK:STDOUT:   %.1: i32 = int_literal 39999999999999999993 [template]
-// CHECK:STDOUT:   %.2: i32 = int_literal 1 [template]
+// CHECK:STDOUT:   %.1: i32 = int_literal 1 [template]
 // CHECK:STDOUT: }
 // CHECK:STDOUT:
 // CHECK:STDOUT: file {
@@ -27,13 +33,11 @@ var b: [1; 39999999999999999993];
 // CHECK:STDOUT:     .a = %a
 // CHECK:STDOUT:     .b = %b
 // CHECK:STDOUT:   }
-// CHECK:STDOUT:   %.loc11_14: i32 = int_literal 39999999999999999993 [template = constants.%.1]
-// CHECK:STDOUT:   %.loc11_34: type = array_type %.loc11_14, i32 [template = <error>]
+// CHECK:STDOUT:   %.loc14: type = array_type <error>, i32 [template = <error>]
 // CHECK:STDOUT:   %a.var: ref <error> = var a
 // CHECK:STDOUT:   %a: ref <error> = bind_name a, %a.var
-// CHECK:STDOUT:   %.loc16_9: i32 = int_literal 1 [template = constants.%.2]
-// CHECK:STDOUT:   %.loc16_12: i32 = int_literal 39999999999999999993 [template = constants.%.1]
-// CHECK:STDOUT:   %.loc16_32: type = array_type %.loc16_12, <error> [template = <error>]
+// CHECK:STDOUT:   %.loc23_9: i32 = int_literal 1 [template = constants.%.1]
+// CHECK:STDOUT:   %.loc23_32: type = array_type <error>, <error> [template = <error>]
 // CHECK:STDOUT:   %b.var: ref <error> = var b
 // CHECK:STDOUT:   %b: ref <error> = bind_name b, %b.var
 // CHECK:STDOUT: }

+ 9 - 11
toolchain/check/testdata/array/fail_out_of_bound_non_literal.carbon

@@ -20,11 +20,9 @@ var b: i32 = a[{.index = 3}.index];
 // CHECK:STDOUT:   %.5: i32 = int_literal 2 [template]
 // CHECK:STDOUT:   %.6: type = tuple_type (i32, i32, i32) [template]
 // CHECK:STDOUT:   %.7: i32 = int_literal 0 [template]
-// CHECK:STDOUT:   %.8: i32 = int_literal 1 [template]
-// CHECK:STDOUT:   %.9: i32 = int_literal 2 [template]
-// CHECK:STDOUT:   %.10: [i32; 3] = tuple_value (%.4, %.5, %.1) [template]
-// CHECK:STDOUT:   %.11: type = struct_type {.index: i32} [template]
-// CHECK:STDOUT:   %.12: {.index: i32} = struct_value (%.1) [template]
+// CHECK:STDOUT:   %.8: [i32; 3] = tuple_value (%.4, %.5, %.1) [template]
+// CHECK:STDOUT:   %.9: type = struct_type {.index: i32} [template]
+// CHECK:STDOUT:   %.10: {.index: i32} = struct_value (%.1) [template]
 // CHECK:STDOUT: }
 // CHECK:STDOUT:
 // CHECK:STDOUT: file {
@@ -49,20 +47,20 @@ var b: i32 = a[{.index = 3}.index];
 // CHECK:STDOUT:   %.loc7_27.2: i32 = int_literal 0 [template = constants.%.7]
 // CHECK:STDOUT:   %.loc7_27.3: ref i32 = array_index file.%a.var, %.loc7_27.2
 // CHECK:STDOUT:   %.loc7_27.4: init i32 = initialize_from %.loc7_20 to %.loc7_27.3 [template = constants.%.4]
-// CHECK:STDOUT:   %.loc7_27.5: i32 = int_literal 1 [template = constants.%.8]
+// CHECK:STDOUT:   %.loc7_27.5: i32 = int_literal 1 [template = constants.%.4]
 // CHECK:STDOUT:   %.loc7_27.6: ref i32 = array_index file.%a.var, %.loc7_27.5
 // CHECK:STDOUT:   %.loc7_27.7: init i32 = initialize_from %.loc7_23 to %.loc7_27.6 [template = constants.%.5]
-// CHECK:STDOUT:   %.loc7_27.8: i32 = int_literal 2 [template = constants.%.9]
+// CHECK:STDOUT:   %.loc7_27.8: i32 = int_literal 2 [template = constants.%.5]
 // CHECK:STDOUT:   %.loc7_27.9: ref i32 = array_index file.%a.var, %.loc7_27.8
 // CHECK:STDOUT:   %.loc7_27.10: init i32 = initialize_from %.loc7_26 to %.loc7_27.9 [template = constants.%.1]
-// CHECK:STDOUT:   %.loc7_27.11: init [i32; 3] = array_init (%.loc7_27.4, %.loc7_27.7, %.loc7_27.10) to file.%a.var [template = constants.%.10]
-// CHECK:STDOUT:   %.loc7_27.12: init [i32; 3] = converted %.loc7_27.1, %.loc7_27.11 [template = constants.%.10]
+// CHECK:STDOUT:   %.loc7_27.11: init [i32; 3] = array_init (%.loc7_27.4, %.loc7_27.7, %.loc7_27.10) to file.%a.var [template = constants.%.8]
+// CHECK:STDOUT:   %.loc7_27.12: init [i32; 3] = converted %.loc7_27.1, %.loc7_27.11 [template = constants.%.8]
 // CHECK:STDOUT:   assign file.%a.var, %.loc7_27.12
 // CHECK:STDOUT:   %a.ref: ref [i32; 3] = name_ref a, file.%a
 // CHECK:STDOUT:   %.loc11_26: i32 = int_literal 3 [template = constants.%.1]
 // CHECK:STDOUT:   %.loc11_27.1: {.index: i32} = struct_literal (%.loc11_26)
-// CHECK:STDOUT:   %.loc11_27.2: {.index: i32} = struct_value (%.loc11_26) [template = constants.%.12]
-// CHECK:STDOUT:   %.loc11_27.3: {.index: i32} = converted %.loc11_27.1, %.loc11_27.2 [template = constants.%.12]
+// CHECK:STDOUT:   %.loc11_27.2: {.index: i32} = struct_value (%.loc11_26) [template = constants.%.10]
+// CHECK:STDOUT:   %.loc11_27.3: {.index: i32} = converted %.loc11_27.1, %.loc11_27.2 [template = constants.%.10]
 // CHECK:STDOUT:   %.loc11_28: i32 = struct_access %.loc11_27.3, element0 [template = constants.%.1]
 // CHECK:STDOUT:   %.loc11_34.1: ref i32 = array_index %a.ref, %.loc11_28 [template = <error>]
 // CHECK:STDOUT:   %.loc11_34.2: i32 = bind_value %.loc11_34.1

+ 9 - 10
toolchain/check/testdata/array/fail_type_mismatch.carbon

@@ -41,14 +41,13 @@ var d: [i32; 3] = t2;
 // CHECK:STDOUT:   %.7: String = string_literal "World" [template]
 // CHECK:STDOUT:   %.8: type = tuple_type (i32, String, String) [template]
 // CHECK:STDOUT:   %.9: i32 = int_literal 0 [template]
-// CHECK:STDOUT:   %.10: i32 = int_literal 1 [template]
-// CHECK:STDOUT:   %.11: type = tuple_type (type, type, type) [template]
-// CHECK:STDOUT:   %.12: type = tuple_type (i32, String*, String*) [template]
-// CHECK:STDOUT:   %.13: type = ptr_type (i32, String*, String*) [template]
-// CHECK:STDOUT:   %.14: i32 = int_literal 2 [template]
-// CHECK:STDOUT:   %.15: type = tuple_type (i32, i32) [template]
-// CHECK:STDOUT:   %.16: type = tuple_type (type, type) [template]
-// CHECK:STDOUT:   %.17: type = ptr_type (i32, i32) [template]
+// CHECK:STDOUT:   %.10: type = tuple_type (type, type, type) [template]
+// CHECK:STDOUT:   %.11: type = tuple_type (i32, String*, String*) [template]
+// CHECK:STDOUT:   %.12: type = ptr_type (i32, String*, String*) [template]
+// CHECK:STDOUT:   %.13: i32 = int_literal 2 [template]
+// CHECK:STDOUT:   %.14: type = tuple_type (i32, i32) [template]
+// CHECK:STDOUT:   %.15: type = tuple_type (type, type) [template]
+// CHECK:STDOUT:   %.16: type = ptr_type (i32, i32) [template]
 // CHECK:STDOUT: }
 // CHECK:STDOUT:
 // CHECK:STDOUT: file {
@@ -77,7 +76,7 @@ var d: [i32; 3] = t2;
 // CHECK:STDOUT:   %c.var: ref [i32; 3] = var c
 // CHECK:STDOUT:   %c: ref [i32; 3] = bind_name c, %c.var
 // CHECK:STDOUT:   %.loc26_18.1: (type, type) = tuple_literal (i32, i32)
-// CHECK:STDOUT:   %.loc26_18.2: type = converted %.loc26_18.1, constants.%.15 [template = constants.%.15]
+// CHECK:STDOUT:   %.loc26_18.2: type = converted %.loc26_18.1, constants.%.14 [template = constants.%.14]
 // CHECK:STDOUT:   %t2.var: ref (i32, i32) = var t2
 // CHECK:STDOUT:   %t2: ref (i32, i32) = bind_name t2, %t2.var
 // CHECK:STDOUT:   %.loc30_14: i32 = int_literal 3 [template = constants.%.1]
@@ -105,7 +104,7 @@ var d: [i32; 3] = t2;
 // CHECK:STDOUT:   %.loc18_19.6: ref String = tuple_access %t1.ref, element1
 // CHECK:STDOUT:   assign file.%b.var, <error>
 // CHECK:STDOUT:   %.loc24_20: i32 = int_literal 1 [template = constants.%.4]
-// CHECK:STDOUT:   %.loc24_23: i32 = int_literal 2 [template = constants.%.14]
+// CHECK:STDOUT:   %.loc24_23: i32 = int_literal 2 [template = constants.%.13]
 // CHECK:STDOUT:   %.loc24_24: (i32, i32) = tuple_literal (%.loc24_20, %.loc24_23)
 // CHECK:STDOUT:   assign file.%c.var, <error>
 // CHECK:STDOUT:   %t2.ref: ref (i32, i32) = name_ref t2, file.%t2

+ 5 - 7
toolchain/check/testdata/array/function_param.carbon

@@ -22,9 +22,7 @@ fn G() -> i32 {
 // CHECK:STDOUT:   %.5: i32 = int_literal 2 [template]
 // CHECK:STDOUT:   %.6: type = tuple_type (i32, i32, i32) [template]
 // CHECK:STDOUT:   %.7: i32 = int_literal 0 [template]
-// CHECK:STDOUT:   %.8: i32 = int_literal 1 [template]
-// CHECK:STDOUT:   %.9: i32 = int_literal 2 [template]
-// CHECK:STDOUT:   %.10: [i32; 3] = tuple_value (%.4, %.5, %.1) [template]
+// CHECK:STDOUT:   %.8: [i32; 3] = tuple_value (%.4, %.5, %.1) [template]
 // CHECK:STDOUT: }
 // CHECK:STDOUT:
 // CHECK:STDOUT: file {
@@ -68,14 +66,14 @@ fn G() -> i32 {
 // CHECK:STDOUT:   %.loc12_20.3: i32 = int_literal 0 [template = constants.%.7]
 // CHECK:STDOUT:   %.loc12_20.4: ref i32 = array_index %.loc12_20.2, %.loc12_20.3
 // CHECK:STDOUT:   %.loc12_20.5: init i32 = initialize_from %.loc12_13 to %.loc12_20.4 [template = constants.%.4]
-// CHECK:STDOUT:   %.loc12_20.6: i32 = int_literal 1 [template = constants.%.8]
+// CHECK:STDOUT:   %.loc12_20.6: i32 = int_literal 1 [template = constants.%.4]
 // CHECK:STDOUT:   %.loc12_20.7: ref i32 = array_index %.loc12_20.2, %.loc12_20.6
 // CHECK:STDOUT:   %.loc12_20.8: init i32 = initialize_from %.loc12_16 to %.loc12_20.7 [template = constants.%.5]
-// CHECK:STDOUT:   %.loc12_20.9: i32 = int_literal 2 [template = constants.%.9]
+// CHECK:STDOUT:   %.loc12_20.9: i32 = int_literal 2 [template = constants.%.5]
 // CHECK:STDOUT:   %.loc12_20.10: ref i32 = array_index %.loc12_20.2, %.loc12_20.9
 // CHECK:STDOUT:   %.loc12_20.11: init i32 = initialize_from %.loc12_19 to %.loc12_20.10 [template = constants.%.1]
-// CHECK:STDOUT:   %.loc12_20.12: init [i32; 3] = array_init (%.loc12_20.5, %.loc12_20.8, %.loc12_20.11) to %.loc12_20.2 [template = constants.%.10]
-// CHECK:STDOUT:   %.loc12_20.13: init [i32; 3] = converted %.loc12_20.1, %.loc12_20.12 [template = constants.%.10]
+// CHECK:STDOUT:   %.loc12_20.12: init [i32; 3] = array_init (%.loc12_20.5, %.loc12_20.8, %.loc12_20.11) to %.loc12_20.2 [template = constants.%.8]
+// CHECK:STDOUT:   %.loc12_20.13: init [i32; 3] = converted %.loc12_20.1, %.loc12_20.12 [template = constants.%.8]
 // CHECK:STDOUT:   %.loc12_20.14: ref [i32; 3] = temporary %.loc12_20.2, %.loc12_20.13
 // CHECK:STDOUT:   %.loc12_20.15: [i32; 3] = bind_value %.loc12_20.14
 // CHECK:STDOUT:   %.loc12_11.1: init i32 = call %F.ref(%.loc12_20.15, %.loc12_23)

+ 9 - 11
toolchain/check/testdata/array/index_not_literal.carbon

@@ -17,11 +17,9 @@ var b: i32 = a[{.index = 2}.index];
 // CHECK:STDOUT:   %.5: i32 = int_literal 2 [template]
 // CHECK:STDOUT:   %.6: type = tuple_type (i32, i32, i32) [template]
 // CHECK:STDOUT:   %.7: i32 = int_literal 0 [template]
-// CHECK:STDOUT:   %.8: i32 = int_literal 1 [template]
-// CHECK:STDOUT:   %.9: i32 = int_literal 2 [template]
-// CHECK:STDOUT:   %.10: [i32; 3] = tuple_value (%.4, %.5, %.1) [template]
-// CHECK:STDOUT:   %.11: type = struct_type {.index: i32} [template]
-// CHECK:STDOUT:   %.12: {.index: i32} = struct_value (%.5) [template]
+// CHECK:STDOUT:   %.8: [i32; 3] = tuple_value (%.4, %.5, %.1) [template]
+// CHECK:STDOUT:   %.9: type = struct_type {.index: i32} [template]
+// CHECK:STDOUT:   %.10: {.index: i32} = struct_value (%.5) [template]
 // CHECK:STDOUT: }
 // CHECK:STDOUT:
 // CHECK:STDOUT: file {
@@ -46,20 +44,20 @@ var b: i32 = a[{.index = 2}.index];
 // CHECK:STDOUT:   %.loc7_27.2: i32 = int_literal 0 [template = constants.%.7]
 // CHECK:STDOUT:   %.loc7_27.3: ref i32 = array_index file.%a.var, %.loc7_27.2
 // CHECK:STDOUT:   %.loc7_27.4: init i32 = initialize_from %.loc7_20 to %.loc7_27.3 [template = constants.%.4]
-// CHECK:STDOUT:   %.loc7_27.5: i32 = int_literal 1 [template = constants.%.8]
+// CHECK:STDOUT:   %.loc7_27.5: i32 = int_literal 1 [template = constants.%.4]
 // CHECK:STDOUT:   %.loc7_27.6: ref i32 = array_index file.%a.var, %.loc7_27.5
 // CHECK:STDOUT:   %.loc7_27.7: init i32 = initialize_from %.loc7_23 to %.loc7_27.6 [template = constants.%.5]
-// CHECK:STDOUT:   %.loc7_27.8: i32 = int_literal 2 [template = constants.%.9]
+// CHECK:STDOUT:   %.loc7_27.8: i32 = int_literal 2 [template = constants.%.5]
 // CHECK:STDOUT:   %.loc7_27.9: ref i32 = array_index file.%a.var, %.loc7_27.8
 // CHECK:STDOUT:   %.loc7_27.10: init i32 = initialize_from %.loc7_26 to %.loc7_27.9 [template = constants.%.1]
-// CHECK:STDOUT:   %.loc7_27.11: init [i32; 3] = array_init (%.loc7_27.4, %.loc7_27.7, %.loc7_27.10) to file.%a.var [template = constants.%.10]
-// CHECK:STDOUT:   %.loc7_27.12: init [i32; 3] = converted %.loc7_27.1, %.loc7_27.11 [template = constants.%.10]
+// CHECK:STDOUT:   %.loc7_27.11: init [i32; 3] = array_init (%.loc7_27.4, %.loc7_27.7, %.loc7_27.10) to file.%a.var [template = constants.%.8]
+// CHECK:STDOUT:   %.loc7_27.12: init [i32; 3] = converted %.loc7_27.1, %.loc7_27.11 [template = constants.%.8]
 // CHECK:STDOUT:   assign file.%a.var, %.loc7_27.12
 // CHECK:STDOUT:   %a.ref: ref [i32; 3] = name_ref a, file.%a
 // CHECK:STDOUT:   %.loc8_26: i32 = int_literal 2 [template = constants.%.5]
 // CHECK:STDOUT:   %.loc8_27.1: {.index: i32} = struct_literal (%.loc8_26)
-// CHECK:STDOUT:   %.loc8_27.2: {.index: i32} = struct_value (%.loc8_26) [template = constants.%.12]
-// CHECK:STDOUT:   %.loc8_27.3: {.index: i32} = converted %.loc8_27.1, %.loc8_27.2 [template = constants.%.12]
+// CHECK:STDOUT:   %.loc8_27.2: {.index: i32} = struct_value (%.loc8_26) [template = constants.%.10]
+// CHECK:STDOUT:   %.loc8_27.3: {.index: i32} = converted %.loc8_27.1, %.loc8_27.2 [template = constants.%.10]
 // CHECK:STDOUT:   %.loc8_28: i32 = struct_access %.loc8_27.3, element0 [template = constants.%.5]
 // CHECK:STDOUT:   %.loc8_34.1: ref i32 = array_index %a.ref, %.loc8_28
 // CHECK:STDOUT:   %.loc8_34.2: i32 = bind_value %.loc8_34.1

+ 11 - 19
toolchain/check/testdata/array/nine_elements.carbon

@@ -22,15 +22,7 @@ var a: [i32; 9] = (1, 2, 3, 4, 5, 6, 7, 8, 9);
 // CHECK:STDOUT:   %.11: i32 = int_literal 8 [template]
 // CHECK:STDOUT:   %.12: type = tuple_type (i32, i32, i32, i32, i32, i32, i32, i32, i32) [template]
 // CHECK:STDOUT:   %.13: i32 = int_literal 0 [template]
-// CHECK:STDOUT:   %.14: i32 = int_literal 1 [template]
-// CHECK:STDOUT:   %.15: i32 = int_literal 2 [template]
-// CHECK:STDOUT:   %.16: i32 = int_literal 3 [template]
-// CHECK:STDOUT:   %.17: i32 = int_literal 4 [template]
-// CHECK:STDOUT:   %.18: i32 = int_literal 5 [template]
-// CHECK:STDOUT:   %.19: i32 = int_literal 6 [template]
-// CHECK:STDOUT:   %.20: i32 = int_literal 7 [template]
-// CHECK:STDOUT:   %.21: i32 = int_literal 8 [template]
-// CHECK:STDOUT:   %.22: [i32; 9] = tuple_value (%.4, %.5, %.6, %.7, %.8, %.9, %.10, %.11, %.1) [template]
+// CHECK:STDOUT:   %.14: [i32; 9] = tuple_value (%.4, %.5, %.6, %.7, %.8, %.9, %.10, %.11, %.1) [template]
 // CHECK:STDOUT: }
 // CHECK:STDOUT:
 // CHECK:STDOUT: file {
@@ -58,32 +50,32 @@ var a: [i32; 9] = (1, 2, 3, 4, 5, 6, 7, 8, 9);
 // CHECK:STDOUT:   %.loc7_45.2: i32 = int_literal 0 [template = constants.%.13]
 // CHECK:STDOUT:   %.loc7_45.3: ref i32 = array_index file.%a.var, %.loc7_45.2
 // CHECK:STDOUT:   %.loc7_45.4: init i32 = initialize_from %.loc7_20 to %.loc7_45.3 [template = constants.%.4]
-// CHECK:STDOUT:   %.loc7_45.5: i32 = int_literal 1 [template = constants.%.14]
+// CHECK:STDOUT:   %.loc7_45.5: i32 = int_literal 1 [template = constants.%.4]
 // CHECK:STDOUT:   %.loc7_45.6: ref i32 = array_index file.%a.var, %.loc7_45.5
 // CHECK:STDOUT:   %.loc7_45.7: init i32 = initialize_from %.loc7_23 to %.loc7_45.6 [template = constants.%.5]
-// CHECK:STDOUT:   %.loc7_45.8: i32 = int_literal 2 [template = constants.%.15]
+// CHECK:STDOUT:   %.loc7_45.8: i32 = int_literal 2 [template = constants.%.5]
 // CHECK:STDOUT:   %.loc7_45.9: ref i32 = array_index file.%a.var, %.loc7_45.8
 // CHECK:STDOUT:   %.loc7_45.10: init i32 = initialize_from %.loc7_26 to %.loc7_45.9 [template = constants.%.6]
-// CHECK:STDOUT:   %.loc7_45.11: i32 = int_literal 3 [template = constants.%.16]
+// CHECK:STDOUT:   %.loc7_45.11: i32 = int_literal 3 [template = constants.%.6]
 // CHECK:STDOUT:   %.loc7_45.12: ref i32 = array_index file.%a.var, %.loc7_45.11
 // CHECK:STDOUT:   %.loc7_45.13: init i32 = initialize_from %.loc7_29 to %.loc7_45.12 [template = constants.%.7]
-// CHECK:STDOUT:   %.loc7_45.14: i32 = int_literal 4 [template = constants.%.17]
+// CHECK:STDOUT:   %.loc7_45.14: i32 = int_literal 4 [template = constants.%.7]
 // CHECK:STDOUT:   %.loc7_45.15: ref i32 = array_index file.%a.var, %.loc7_45.14
 // CHECK:STDOUT:   %.loc7_45.16: init i32 = initialize_from %.loc7_32 to %.loc7_45.15 [template = constants.%.8]
-// CHECK:STDOUT:   %.loc7_45.17: i32 = int_literal 5 [template = constants.%.18]
+// CHECK:STDOUT:   %.loc7_45.17: i32 = int_literal 5 [template = constants.%.8]
 // CHECK:STDOUT:   %.loc7_45.18: ref i32 = array_index file.%a.var, %.loc7_45.17
 // CHECK:STDOUT:   %.loc7_45.19: init i32 = initialize_from %.loc7_35 to %.loc7_45.18 [template = constants.%.9]
-// CHECK:STDOUT:   %.loc7_45.20: i32 = int_literal 6 [template = constants.%.19]
+// CHECK:STDOUT:   %.loc7_45.20: i32 = int_literal 6 [template = constants.%.9]
 // CHECK:STDOUT:   %.loc7_45.21: ref i32 = array_index file.%a.var, %.loc7_45.20
 // CHECK:STDOUT:   %.loc7_45.22: init i32 = initialize_from %.loc7_38 to %.loc7_45.21 [template = constants.%.10]
-// CHECK:STDOUT:   %.loc7_45.23: i32 = int_literal 7 [template = constants.%.20]
+// CHECK:STDOUT:   %.loc7_45.23: i32 = int_literal 7 [template = constants.%.10]
 // CHECK:STDOUT:   %.loc7_45.24: ref i32 = array_index file.%a.var, %.loc7_45.23
 // CHECK:STDOUT:   %.loc7_45.25: init i32 = initialize_from %.loc7_41 to %.loc7_45.24 [template = constants.%.11]
-// CHECK:STDOUT:   %.loc7_45.26: i32 = int_literal 8 [template = constants.%.21]
+// CHECK:STDOUT:   %.loc7_45.26: i32 = int_literal 8 [template = constants.%.11]
 // CHECK:STDOUT:   %.loc7_45.27: ref i32 = array_index file.%a.var, %.loc7_45.26
 // CHECK:STDOUT:   %.loc7_45.28: init i32 = initialize_from %.loc7_44 to %.loc7_45.27 [template = constants.%.1]
-// CHECK:STDOUT:   %.loc7_45.29: init [i32; 9] = array_init (%.loc7_45.4, %.loc7_45.7, %.loc7_45.10, %.loc7_45.13, %.loc7_45.16, %.loc7_45.19, %.loc7_45.22, %.loc7_45.25, %.loc7_45.28) to file.%a.var [template = constants.%.22]
-// CHECK:STDOUT:   %.loc7_45.30: init [i32; 9] = converted %.loc7_45.1, %.loc7_45.29 [template = constants.%.22]
+// CHECK:STDOUT:   %.loc7_45.29: init [i32; 9] = array_init (%.loc7_45.4, %.loc7_45.7, %.loc7_45.10, %.loc7_45.13, %.loc7_45.16, %.loc7_45.19, %.loc7_45.22, %.loc7_45.25, %.loc7_45.28) to file.%a.var [template = constants.%.14]
+// CHECK:STDOUT:   %.loc7_45.30: init [i32; 9] = converted %.loc7_45.1, %.loc7_45.29 [template = constants.%.14]
 // CHECK:STDOUT:   assign file.%a.var, %.loc7_45.30
 // CHECK:STDOUT:   return
 // CHECK:STDOUT: }

+ 32 - 0
toolchain/check/testdata/basics/fail_numeric_literal_overflow.carbon

@@ -0,0 +1,32 @@
+// Part of the Carbon Language project, under the Apache License v2.0 with LLVM
+// Exceptions. See /LICENSE for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+// AUTOUPDATE
+
+// CHECK:STDERR: fail_numeric_literal_overflow.carbon:[[@LINE+4]]:14: ERROR: Integer literal with value 39999999999999999993 does not fit in i32.
+// CHECK:STDERR: let a: i32 = 39999999999999999993;
+// CHECK:STDERR:              ^~~~~~~~~~~~~~~~~~~~
+// CHECK:STDERR:
+let a: i32 = 39999999999999999993;
+
+// CHECK:STDERR: fail_numeric_literal_overflow.carbon:[[@LINE+4]]:14: ERROR: Integer literal with value 2147483648 does not fit in i32.
+// CHECK:STDERR: let b: i32 = 2_147_483_648;
+// CHECK:STDERR:              ^~~~~~~~~~~~~
+// CHECK:STDERR:
+let b: i32 = 2_147_483_648;
+
+// CHECK:STDERR: fail_numeric_literal_overflow.carbon:[[@LINE+3]]:14: ERROR: Integer literal with value 2147483648 does not fit in i32.
+// CHECK:STDERR: let c: i32 = 0x8000_0000;
+// CHECK:STDERR:              ^~~~~~~~~~~
+let c: i32 = 0x8000_0000;
+
+// CHECK:STDOUT: --- fail_numeric_literal_overflow.carbon
+// CHECK:STDOUT:
+// CHECK:STDOUT: file {
+// CHECK:STDOUT:   package: <namespace> = namespace [template] {}
+// CHECK:STDOUT:   %a: i32 = bind_name a, <error>
+// CHECK:STDOUT:   %b: i32 = bind_name b, <error>
+// CHECK:STDOUT:   %c: i32 = bind_name c, <error>
+// CHECK:STDOUT: }
+// CHECK:STDOUT:

+ 82 - 78
toolchain/check/testdata/basics/numeric_literals.carbon

@@ -7,12 +7,13 @@
 fn F() {
   // 8 and 9 trigger special behavior in APInt when mishandling signed versus
   // unsigned, so we pay extra attention to those.
-  var ints: [i32; 5] = (
+  var ints: [i32; 6] = (
     8,
     9,
     0x8,
     0b1000,
-    39999999999999999993,
+    2147483647,
+    0x7FFFFFFF,
   );
   var floats: [f64; 7] = (
     0.9,
@@ -28,33 +29,32 @@ fn F() {
 // CHECK:STDOUT: --- numeric_literals.carbon
 // CHECK:STDOUT:
 // CHECK:STDOUT: constants {
-// CHECK:STDOUT:   %.1: i32 = int_literal 5 [template]
+// CHECK:STDOUT:   %.1: i32 = int_literal 6 [template]
 // CHECK:STDOUT:   %.2: type = array_type %.1, i32 [template]
-// CHECK:STDOUT:   %.3: type = ptr_type [i32; 5] [template]
+// CHECK:STDOUT:   %.3: type = ptr_type [i32; 6] [template]
 // CHECK:STDOUT:   %.4: i32 = int_literal 8 [template]
 // CHECK:STDOUT:   %.5: i32 = int_literal 9 [template]
-// CHECK:STDOUT:   %.6: i32 = int_literal 39999999999999999993 [template]
-// CHECK:STDOUT:   %.7: type = tuple_type (i32, i32, i32, i32, i32) [template]
+// CHECK:STDOUT:   %.6: i32 = int_literal 2147483647 [template]
+// CHECK:STDOUT:   %.7: type = tuple_type (i32, i32, i32, i32, i32, i32) [template]
 // CHECK:STDOUT:   %.8: i32 = int_literal 0 [template]
 // CHECK:STDOUT:   %.9: i32 = int_literal 1 [template]
 // CHECK:STDOUT:   %.10: i32 = int_literal 2 [template]
 // CHECK:STDOUT:   %.11: i32 = int_literal 3 [template]
 // CHECK:STDOUT:   %.12: i32 = int_literal 4 [template]
-// CHECK:STDOUT:   %.13: [i32; 5] = tuple_value (%.4, %.5, %.4, %.4, %.6) [template]
-// CHECK:STDOUT:   %.14: i32 = int_literal 7 [template]
-// CHECK:STDOUT:   %.15: type = array_type %.14, f64 [template]
-// CHECK:STDOUT:   %.16: type = ptr_type [f64; 7] [template]
-// CHECK:STDOUT:   %.17: f64 = real_literal 9e-1 [template]
-// CHECK:STDOUT:   %.18: f64 = real_literal 80e-1 [template]
-// CHECK:STDOUT:   %.19: f64 = real_literal 800e-1 [template]
-// CHECK:STDOUT:   %.20: f64 = real_literal 10e6 [template]
-// CHECK:STDOUT:   %.21: f64 = real_literal 10e7 [template]
-// CHECK:STDOUT:   %.22: f64 = real_literal 10e-9 [template]
-// CHECK:STDOUT:   %.23: f64 = real_literal 399999999999999999930e39999999999999999992 [template]
-// CHECK:STDOUT:   %.24: type = tuple_type (f64, f64, f64, f64, f64, f64, f64) [template]
-// CHECK:STDOUT:   %.25: i32 = int_literal 5 [template]
-// CHECK:STDOUT:   %.26: i32 = int_literal 6 [template]
-// CHECK:STDOUT:   %.27: [f64; 7] = tuple_value (%.17, %.18, %.19, %.20, %.21, %.22, %.23) [template]
+// CHECK:STDOUT:   %.13: i32 = int_literal 5 [template]
+// CHECK:STDOUT:   %.14: [i32; 6] = tuple_value (%.4, %.5, %.4, %.4, %.6, %.6) [template]
+// CHECK:STDOUT:   %.15: i32 = int_literal 7 [template]
+// CHECK:STDOUT:   %.16: type = array_type %.15, f64 [template]
+// CHECK:STDOUT:   %.17: type = ptr_type [f64; 7] [template]
+// CHECK:STDOUT:   %.18: f64 = real_literal 9e-1 [template]
+// CHECK:STDOUT:   %.19: f64 = real_literal 80e-1 [template]
+// CHECK:STDOUT:   %.20: f64 = real_literal 800e-1 [template]
+// CHECK:STDOUT:   %.21: f64 = real_literal 10e6 [template]
+// CHECK:STDOUT:   %.22: f64 = real_literal 10e7 [template]
+// CHECK:STDOUT:   %.23: f64 = real_literal 10e-9 [template]
+// CHECK:STDOUT:   %.24: f64 = real_literal 399999999999999999930e39999999999999999992 [template]
+// CHECK:STDOUT:   %.25: type = tuple_type (f64, f64, f64, f64, f64, f64, f64) [template]
+// CHECK:STDOUT:   %.26: [f64; 7] = tuple_value (%.18, %.19, %.20, %.21, %.22, %.23, %.24) [template]
 // CHECK:STDOUT: }
 // CHECK:STDOUT:
 // CHECK:STDOUT: file {
@@ -66,70 +66,74 @@ fn F() {
 // CHECK:STDOUT:
 // CHECK:STDOUT: fn @F() {
 // CHECK:STDOUT: !entry:
-// CHECK:STDOUT:   %.loc10_19: i32 = int_literal 5 [template = constants.%.1]
+// CHECK:STDOUT:   %.loc10_19: i32 = int_literal 6 [template = constants.%.1]
 // CHECK:STDOUT:   %.loc10_20: type = array_type %.loc10_19, i32 [template = constants.%.2]
-// CHECK:STDOUT:   %ints.var: ref [i32; 5] = var ints
-// CHECK:STDOUT:   %ints: ref [i32; 5] = bind_name ints, %ints.var
+// CHECK:STDOUT:   %ints.var: ref [i32; 6] = var ints
+// CHECK:STDOUT:   %ints: ref [i32; 6] = bind_name ints, %ints.var
 // CHECK:STDOUT:   %.loc11: i32 = int_literal 8 [template = constants.%.4]
 // CHECK:STDOUT:   %.loc12: i32 = int_literal 9 [template = constants.%.5]
 // CHECK:STDOUT:   %.loc13: i32 = int_literal 8 [template = constants.%.4]
 // CHECK:STDOUT:   %.loc14: i32 = int_literal 8 [template = constants.%.4]
-// CHECK:STDOUT:   %.loc15: i32 = int_literal 39999999999999999993 [template = constants.%.6]
-// CHECK:STDOUT:   %.loc16_3.1: (i32, i32, i32, i32, i32) = tuple_literal (%.loc11, %.loc12, %.loc13, %.loc14, %.loc15)
-// CHECK:STDOUT:   %.loc16_3.2: i32 = int_literal 0 [template = constants.%.8]
-// CHECK:STDOUT:   %.loc16_3.3: ref i32 = array_index %ints.var, %.loc16_3.2
-// CHECK:STDOUT:   %.loc16_3.4: init i32 = initialize_from %.loc11 to %.loc16_3.3 [template = constants.%.4]
-// CHECK:STDOUT:   %.loc16_3.5: i32 = int_literal 1 [template = constants.%.9]
-// CHECK:STDOUT:   %.loc16_3.6: ref i32 = array_index %ints.var, %.loc16_3.5
-// CHECK:STDOUT:   %.loc16_3.7: init i32 = initialize_from %.loc12 to %.loc16_3.6 [template = constants.%.5]
-// CHECK:STDOUT:   %.loc16_3.8: i32 = int_literal 2 [template = constants.%.10]
-// CHECK:STDOUT:   %.loc16_3.9: ref i32 = array_index %ints.var, %.loc16_3.8
-// CHECK:STDOUT:   %.loc16_3.10: init i32 = initialize_from %.loc13 to %.loc16_3.9 [template = constants.%.4]
-// CHECK:STDOUT:   %.loc16_3.11: i32 = int_literal 3 [template = constants.%.11]
-// CHECK:STDOUT:   %.loc16_3.12: ref i32 = array_index %ints.var, %.loc16_3.11
-// CHECK:STDOUT:   %.loc16_3.13: init i32 = initialize_from %.loc14 to %.loc16_3.12 [template = constants.%.4]
-// CHECK:STDOUT:   %.loc16_3.14: i32 = int_literal 4 [template = constants.%.12]
-// CHECK:STDOUT:   %.loc16_3.15: ref i32 = array_index %ints.var, %.loc16_3.14
-// CHECK:STDOUT:   %.loc16_3.16: init i32 = initialize_from %.loc15 to %.loc16_3.15 [template = constants.%.6]
-// CHECK:STDOUT:   %.loc16_3.17: init [i32; 5] = array_init (%.loc16_3.4, %.loc16_3.7, %.loc16_3.10, %.loc16_3.13, %.loc16_3.16) to %ints.var [template = constants.%.13]
-// CHECK:STDOUT:   %.loc16_3.18: init [i32; 5] = converted %.loc16_3.1, %.loc16_3.17 [template = constants.%.13]
-// CHECK:STDOUT:   assign %ints.var, %.loc16_3.18
-// CHECK:STDOUT:   %.loc17_21: i32 = int_literal 7 [template = constants.%.14]
-// CHECK:STDOUT:   %.loc17_22: type = array_type %.loc17_21, f64 [template = constants.%.15]
+// CHECK:STDOUT:   %.loc15: i32 = int_literal 2147483647 [template = constants.%.6]
+// CHECK:STDOUT:   %.loc16: i32 = int_literal 2147483647 [template = constants.%.6]
+// CHECK:STDOUT:   %.loc17_3.1: (i32, i32, i32, i32, i32, i32) = tuple_literal (%.loc11, %.loc12, %.loc13, %.loc14, %.loc15, %.loc16)
+// CHECK:STDOUT:   %.loc17_3.2: i32 = int_literal 0 [template = constants.%.8]
+// CHECK:STDOUT:   %.loc17_3.3: ref i32 = array_index %ints.var, %.loc17_3.2
+// CHECK:STDOUT:   %.loc17_3.4: init i32 = initialize_from %.loc11 to %.loc17_3.3 [template = constants.%.4]
+// CHECK:STDOUT:   %.loc17_3.5: i32 = int_literal 1 [template = constants.%.9]
+// CHECK:STDOUT:   %.loc17_3.6: ref i32 = array_index %ints.var, %.loc17_3.5
+// CHECK:STDOUT:   %.loc17_3.7: init i32 = initialize_from %.loc12 to %.loc17_3.6 [template = constants.%.5]
+// CHECK:STDOUT:   %.loc17_3.8: i32 = int_literal 2 [template = constants.%.10]
+// CHECK:STDOUT:   %.loc17_3.9: ref i32 = array_index %ints.var, %.loc17_3.8
+// CHECK:STDOUT:   %.loc17_3.10: init i32 = initialize_from %.loc13 to %.loc17_3.9 [template = constants.%.4]
+// CHECK:STDOUT:   %.loc17_3.11: i32 = int_literal 3 [template = constants.%.11]
+// CHECK:STDOUT:   %.loc17_3.12: ref i32 = array_index %ints.var, %.loc17_3.11
+// CHECK:STDOUT:   %.loc17_3.13: init i32 = initialize_from %.loc14 to %.loc17_3.12 [template = constants.%.4]
+// CHECK:STDOUT:   %.loc17_3.14: i32 = int_literal 4 [template = constants.%.12]
+// CHECK:STDOUT:   %.loc17_3.15: ref i32 = array_index %ints.var, %.loc17_3.14
+// CHECK:STDOUT:   %.loc17_3.16: init i32 = initialize_from %.loc15 to %.loc17_3.15 [template = constants.%.6]
+// CHECK:STDOUT:   %.loc17_3.17: i32 = int_literal 5 [template = constants.%.13]
+// CHECK:STDOUT:   %.loc17_3.18: ref i32 = array_index %ints.var, %.loc17_3.17
+// CHECK:STDOUT:   %.loc17_3.19: init i32 = initialize_from %.loc16 to %.loc17_3.18 [template = constants.%.6]
+// CHECK:STDOUT:   %.loc17_3.20: init [i32; 6] = array_init (%.loc17_3.4, %.loc17_3.7, %.loc17_3.10, %.loc17_3.13, %.loc17_3.16, %.loc17_3.19) to %ints.var [template = constants.%.14]
+// CHECK:STDOUT:   %.loc17_3.21: init [i32; 6] = converted %.loc17_3.1, %.loc17_3.20 [template = constants.%.14]
+// CHECK:STDOUT:   assign %ints.var, %.loc17_3.21
+// CHECK:STDOUT:   %.loc18_21: i32 = int_literal 7 [template = constants.%.15]
+// CHECK:STDOUT:   %.loc18_22: type = array_type %.loc18_21, f64 [template = constants.%.16]
 // CHECK:STDOUT:   %floats.var: ref [f64; 7] = var floats
 // CHECK:STDOUT:   %floats: ref [f64; 7] = bind_name floats, %floats.var
-// CHECK:STDOUT:   %.loc18: f64 = real_literal 9e-1 [template = constants.%.17]
-// CHECK:STDOUT:   %.loc19: f64 = real_literal 80e-1 [template = constants.%.18]
-// CHECK:STDOUT:   %.loc20: f64 = real_literal 800e-1 [template = constants.%.19]
-// CHECK:STDOUT:   %.loc21: f64 = real_literal 10e6 [template = constants.%.20]
-// CHECK:STDOUT:   %.loc22: f64 = real_literal 10e7 [template = constants.%.21]
-// CHECK:STDOUT:   %.loc23: f64 = real_literal 10e-9 [template = constants.%.22]
-// CHECK:STDOUT:   %.loc24: f64 = real_literal 399999999999999999930e39999999999999999992 [template = constants.%.23]
-// CHECK:STDOUT:   %.loc25_3.1: (f64, f64, f64, f64, f64, f64, f64) = tuple_literal (%.loc18, %.loc19, %.loc20, %.loc21, %.loc22, %.loc23, %.loc24)
-// CHECK:STDOUT:   %.loc25_3.2: i32 = int_literal 0 [template = constants.%.8]
-// CHECK:STDOUT:   %.loc25_3.3: ref f64 = array_index %floats.var, %.loc25_3.2
-// CHECK:STDOUT:   %.loc25_3.4: init f64 = initialize_from %.loc18 to %.loc25_3.3 [template = constants.%.17]
-// CHECK:STDOUT:   %.loc25_3.5: i32 = int_literal 1 [template = constants.%.9]
-// CHECK:STDOUT:   %.loc25_3.6: ref f64 = array_index %floats.var, %.loc25_3.5
-// CHECK:STDOUT:   %.loc25_3.7: init f64 = initialize_from %.loc19 to %.loc25_3.6 [template = constants.%.18]
-// CHECK:STDOUT:   %.loc25_3.8: i32 = int_literal 2 [template = constants.%.10]
-// CHECK:STDOUT:   %.loc25_3.9: ref f64 = array_index %floats.var, %.loc25_3.8
-// CHECK:STDOUT:   %.loc25_3.10: init f64 = initialize_from %.loc20 to %.loc25_3.9 [template = constants.%.19]
-// CHECK:STDOUT:   %.loc25_3.11: i32 = int_literal 3 [template = constants.%.11]
-// CHECK:STDOUT:   %.loc25_3.12: ref f64 = array_index %floats.var, %.loc25_3.11
-// CHECK:STDOUT:   %.loc25_3.13: init f64 = initialize_from %.loc21 to %.loc25_3.12 [template = constants.%.20]
-// CHECK:STDOUT:   %.loc25_3.14: i32 = int_literal 4 [template = constants.%.12]
-// CHECK:STDOUT:   %.loc25_3.15: ref f64 = array_index %floats.var, %.loc25_3.14
-// CHECK:STDOUT:   %.loc25_3.16: init f64 = initialize_from %.loc22 to %.loc25_3.15 [template = constants.%.21]
-// CHECK:STDOUT:   %.loc25_3.17: i32 = int_literal 5 [template = constants.%.25]
-// CHECK:STDOUT:   %.loc25_3.18: ref f64 = array_index %floats.var, %.loc25_3.17
-// CHECK:STDOUT:   %.loc25_3.19: init f64 = initialize_from %.loc23 to %.loc25_3.18 [template = constants.%.22]
-// CHECK:STDOUT:   %.loc25_3.20: i32 = int_literal 6 [template = constants.%.26]
-// CHECK:STDOUT:   %.loc25_3.21: ref f64 = array_index %floats.var, %.loc25_3.20
-// CHECK:STDOUT:   %.loc25_3.22: init f64 = initialize_from %.loc24 to %.loc25_3.21 [template = constants.%.23]
-// CHECK:STDOUT:   %.loc25_3.23: init [f64; 7] = array_init (%.loc25_3.4, %.loc25_3.7, %.loc25_3.10, %.loc25_3.13, %.loc25_3.16, %.loc25_3.19, %.loc25_3.22) to %floats.var [template = constants.%.27]
-// CHECK:STDOUT:   %.loc25_3.24: init [f64; 7] = converted %.loc25_3.1, %.loc25_3.23 [template = constants.%.27]
-// CHECK:STDOUT:   assign %floats.var, %.loc25_3.24
+// CHECK:STDOUT:   %.loc19: f64 = real_literal 9e-1 [template = constants.%.18]
+// CHECK:STDOUT:   %.loc20: f64 = real_literal 80e-1 [template = constants.%.19]
+// CHECK:STDOUT:   %.loc21: f64 = real_literal 800e-1 [template = constants.%.20]
+// CHECK:STDOUT:   %.loc22: f64 = real_literal 10e6 [template = constants.%.21]
+// CHECK:STDOUT:   %.loc23: f64 = real_literal 10e7 [template = constants.%.22]
+// CHECK:STDOUT:   %.loc24: f64 = real_literal 10e-9 [template = constants.%.23]
+// CHECK:STDOUT:   %.loc25: f64 = real_literal 399999999999999999930e39999999999999999992 [template = constants.%.24]
+// CHECK:STDOUT:   %.loc26_3.1: (f64, f64, f64, f64, f64, f64, f64) = tuple_literal (%.loc19, %.loc20, %.loc21, %.loc22, %.loc23, %.loc24, %.loc25)
+// CHECK:STDOUT:   %.loc26_3.2: i32 = int_literal 0 [template = constants.%.8]
+// CHECK:STDOUT:   %.loc26_3.3: ref f64 = array_index %floats.var, %.loc26_3.2
+// CHECK:STDOUT:   %.loc26_3.4: init f64 = initialize_from %.loc19 to %.loc26_3.3 [template = constants.%.18]
+// CHECK:STDOUT:   %.loc26_3.5: i32 = int_literal 1 [template = constants.%.9]
+// CHECK:STDOUT:   %.loc26_3.6: ref f64 = array_index %floats.var, %.loc26_3.5
+// CHECK:STDOUT:   %.loc26_3.7: init f64 = initialize_from %.loc20 to %.loc26_3.6 [template = constants.%.19]
+// CHECK:STDOUT:   %.loc26_3.8: i32 = int_literal 2 [template = constants.%.10]
+// CHECK:STDOUT:   %.loc26_3.9: ref f64 = array_index %floats.var, %.loc26_3.8
+// CHECK:STDOUT:   %.loc26_3.10: init f64 = initialize_from %.loc21 to %.loc26_3.9 [template = constants.%.20]
+// CHECK:STDOUT:   %.loc26_3.11: i32 = int_literal 3 [template = constants.%.11]
+// CHECK:STDOUT:   %.loc26_3.12: ref f64 = array_index %floats.var, %.loc26_3.11
+// CHECK:STDOUT:   %.loc26_3.13: init f64 = initialize_from %.loc22 to %.loc26_3.12 [template = constants.%.21]
+// CHECK:STDOUT:   %.loc26_3.14: i32 = int_literal 4 [template = constants.%.12]
+// CHECK:STDOUT:   %.loc26_3.15: ref f64 = array_index %floats.var, %.loc26_3.14
+// CHECK:STDOUT:   %.loc26_3.16: init f64 = initialize_from %.loc23 to %.loc26_3.15 [template = constants.%.22]
+// CHECK:STDOUT:   %.loc26_3.17: i32 = int_literal 5 [template = constants.%.13]
+// CHECK:STDOUT:   %.loc26_3.18: ref f64 = array_index %floats.var, %.loc26_3.17
+// CHECK:STDOUT:   %.loc26_3.19: init f64 = initialize_from %.loc24 to %.loc26_3.18 [template = constants.%.23]
+// CHECK:STDOUT:   %.loc26_3.20: i32 = int_literal 6 [template = constants.%.1]
+// CHECK:STDOUT:   %.loc26_3.21: ref f64 = array_index %floats.var, %.loc26_3.20
+// CHECK:STDOUT:   %.loc26_3.22: init f64 = initialize_from %.loc25 to %.loc26_3.21 [template = constants.%.24]
+// CHECK:STDOUT:   %.loc26_3.23: init [f64; 7] = array_init (%.loc26_3.4, %.loc26_3.7, %.loc26_3.10, %.loc26_3.13, %.loc26_3.16, %.loc26_3.19, %.loc26_3.22) to %floats.var [template = constants.%.26]
+// CHECK:STDOUT:   %.loc26_3.24: init [f64; 7] = converted %.loc26_3.1, %.loc26_3.23 [template = constants.%.26]
+// CHECK:STDOUT:   assign %floats.var, %.loc26_3.24
 // CHECK:STDOUT:   return
 // CHECK:STDOUT: }
 // CHECK:STDOUT:

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

@@ -56,8 +56,8 @@ fn Foo(n: i32) -> (i32, i32, f64) {
 // CHECK:STDOUT:     inst+8:          {kind: PointerType, arg0: type4, type: typeTypeType}
 // 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+11:         {kind: IntLiteral, arg0: int4, type: type1}
-// CHECK:STDOUT:     inst+12:         {kind: IntLiteral, arg0: int4, type: type1}
+// CHECK:STDOUT:     inst+11:         {kind: IntLiteral, arg0: int5, type: type1}
+// CHECK:STDOUT:     inst+12:         {kind: IntLiteral, arg0: int5, type: type1}
 // CHECK:STDOUT:     inst+13:         {kind: RealLiteral, arg0: real0, type: type3}
 // CHECK:STDOUT:     inst+14:         {kind: RealLiteral, arg0: real0, type: type3}
 // CHECK:STDOUT:     inst+15:         {kind: TupleLiteral, arg0: block7, type: type4}

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

@@ -56,8 +56,8 @@ fn Foo(n: i32) -> (i32, i32, f64) {
 // CHECK:STDOUT:     inst+8:          {kind: PointerType, arg0: type4, type: typeTypeType}
 // 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+11:         {kind: IntLiteral, arg0: int4, type: type1}
-// CHECK:STDOUT:     inst+12:         {kind: IntLiteral, arg0: int4, type: type1}
+// CHECK:STDOUT:     inst+11:         {kind: IntLiteral, arg0: int5, type: type1}
+// CHECK:STDOUT:     inst+12:         {kind: IntLiteral, arg0: int5, type: type1}
 // CHECK:STDOUT:     inst+13:         {kind: RealLiteral, arg0: real0, type: type3}
 // CHECK:STDOUT:     inst+14:         {kind: RealLiteral, arg0: real0, type: type3}
 // CHECK:STDOUT:     inst+15:         {kind: TupleLiteral, arg0: block7, type: type4}

+ 12 - 13
toolchain/check/testdata/eval/aggregate.carbon

@@ -39,11 +39,10 @@ var struct_access: [i32; 1] = (0,) as [i32; {.a = 3, .b = 1}.b];
 // CHECK:STDOUT:   %.22: type = tuple_type (i32, i32, i32, i32) [template]
 // CHECK:STDOUT:   %.23: type = ptr_type (i32, i32, i32, i32) [template]
 // CHECK:STDOUT:   %.24: (i32, i32, i32, i32) = tuple_value (%.19, %.20, %.4, %.21) [template]
-// CHECK:STDOUT:   %.25: i32 = int_literal 0 [template]
-// CHECK:STDOUT:   %.26: [i32; 1] = tuple_value (%.17) [template]
-// CHECK:STDOUT:   %.27: type = struct_type {.a: i32, .b: i32} [template]
-// CHECK:STDOUT:   %.28: type = ptr_type {.a: i32, .b: i32} [template]
-// CHECK:STDOUT:   %.29: {.a: i32, .b: i32} = struct_value (%.9, %.4) [template]
+// CHECK:STDOUT:   %.25: [i32; 1] = tuple_value (%.17) [template]
+// CHECK:STDOUT:   %.26: type = struct_type {.a: i32, .b: i32} [template]
+// CHECK:STDOUT:   %.27: type = ptr_type {.a: i32, .b: i32} [template]
+// CHECK:STDOUT:   %.28: {.a: i32, .b: i32} = struct_value (%.9, %.4) [template]
 // CHECK:STDOUT: }
 // CHECK:STDOUT:
 // CHECK:STDOUT: file {
@@ -116,27 +115,27 @@ var struct_access: [i32; 1] = (0,) as [i32; {.a = 3, .b = 1}.b];
 // CHECK:STDOUT:   %.loc11_57: i32 = tuple_index %.loc11_54.3, %.loc11_56 [template = constants.%.4]
 // CHECK:STDOUT:   %.loc11_58: type = array_type %.loc11_57, i32 [template = constants.%.15]
 // CHECK:STDOUT:   %.loc11_5: ref [i32; 1] = splice_block file.%tuple_index.var {}
-// CHECK:STDOUT:   %.loc11_32.2: i32 = int_literal 0 [template = constants.%.25]
+// CHECK:STDOUT:   %.loc11_32.2: i32 = int_literal 0 [template = constants.%.17]
 // CHECK:STDOUT:   %.loc11_32.3: ref i32 = array_index %.loc11_5, %.loc11_32.2
 // CHECK:STDOUT:   %.loc11_32.4: init i32 = initialize_from %.loc11_30 to %.loc11_32.3 [template = constants.%.17]
-// CHECK:STDOUT:   %.loc11_32.5: init [i32; 1] = array_init (%.loc11_32.4) to %.loc11_5 [template = constants.%.26]
-// CHECK:STDOUT:   %.loc11_32.6: init [i32; 1] = converted %.loc11_32.1, %.loc11_32.5 [template = constants.%.26]
+// CHECK:STDOUT:   %.loc11_32.5: init [i32; 1] = array_init (%.loc11_32.4) to %.loc11_5 [template = constants.%.25]
+// CHECK:STDOUT:   %.loc11_32.6: init [i32; 1] = converted %.loc11_32.1, %.loc11_32.5 [template = constants.%.25]
 // CHECK:STDOUT:   assign file.%tuple_index.var, %.loc11_32.6
 // CHECK:STDOUT:   %.loc13_32: i32 = int_literal 0 [template = constants.%.17]
 // CHECK:STDOUT:   %.loc13_34.1: (i32,) = tuple_literal (%.loc13_32)
 // CHECK:STDOUT:   %.loc13_51: i32 = int_literal 3 [template = constants.%.9]
 // CHECK:STDOUT:   %.loc13_59: i32 = int_literal 1 [template = constants.%.4]
 // CHECK:STDOUT:   %.loc13_60.1: {.a: i32, .b: i32} = struct_literal (%.loc13_51, %.loc13_59)
-// CHECK:STDOUT:   %.loc13_60.2: {.a: i32, .b: i32} = struct_value (%.loc13_51, %.loc13_59) [template = constants.%.29]
-// CHECK:STDOUT:   %.loc13_60.3: {.a: i32, .b: i32} = converted %.loc13_60.1, %.loc13_60.2 [template = constants.%.29]
+// CHECK:STDOUT:   %.loc13_60.2: {.a: i32, .b: i32} = struct_value (%.loc13_51, %.loc13_59) [template = constants.%.28]
+// CHECK:STDOUT:   %.loc13_60.3: {.a: i32, .b: i32} = converted %.loc13_60.1, %.loc13_60.2 [template = constants.%.28]
 // CHECK:STDOUT:   %.loc13_61: i32 = struct_access %.loc13_60.3, element1 [template = constants.%.4]
 // CHECK:STDOUT:   %.loc13_63: type = array_type %.loc13_61, i32 [template = constants.%.15]
 // CHECK:STDOUT:   %.loc13_5: ref [i32; 1] = splice_block file.%struct_access.var {}
-// CHECK:STDOUT:   %.loc13_34.2: i32 = int_literal 0 [template = constants.%.25]
+// CHECK:STDOUT:   %.loc13_34.2: i32 = int_literal 0 [template = constants.%.17]
 // CHECK:STDOUT:   %.loc13_34.3: ref i32 = array_index %.loc13_5, %.loc13_34.2
 // CHECK:STDOUT:   %.loc13_34.4: init i32 = initialize_from %.loc13_32 to %.loc13_34.3 [template = constants.%.17]
-// CHECK:STDOUT:   %.loc13_34.5: init [i32; 1] = array_init (%.loc13_34.4) to %.loc13_5 [template = constants.%.26]
-// CHECK:STDOUT:   %.loc13_34.6: init [i32; 1] = converted %.loc13_34.1, %.loc13_34.5 [template = constants.%.26]
+// CHECK:STDOUT:   %.loc13_34.5: init [i32; 1] = array_init (%.loc13_34.4) to %.loc13_5 [template = constants.%.25]
+// CHECK:STDOUT:   %.loc13_34.6: init [i32; 1] = converted %.loc13_34.1, %.loc13_34.5 [template = constants.%.25]
 // CHECK:STDOUT:   assign file.%struct_access.var, %.loc13_34.6
 // CHECK:STDOUT:   return
 // CHECK:STDOUT: }

+ 10 - 13
toolchain/check/testdata/eval/fail_aggregate.carbon

@@ -26,12 +26,9 @@ var array_index: [i32; 1] = (0,) as [i32; ((5, 7, 1, 9) as [i32; 4])[2]];
 // CHECK:STDOUT:   %.10: i32 = int_literal 4 [template]
 // CHECK:STDOUT:   %.11: type = array_type %.10, i32 [template]
 // CHECK:STDOUT:   %.12: type = ptr_type [i32; 4] [template]
-// CHECK:STDOUT:   %.13: i32 = int_literal 0 [template]
-// CHECK:STDOUT:   %.14: i32 = int_literal 1 [template]
-// CHECK:STDOUT:   %.15: i32 = int_literal 2 [template]
-// CHECK:STDOUT:   %.16: i32 = int_literal 3 [template]
-// CHECK:STDOUT:   %.17: [i32; 4] = tuple_value (%.6, %.7, %.1, %.8) [template]
-// CHECK:STDOUT:   %.18: i32 = int_literal 2 [template]
+// CHECK:STDOUT:   %.13: i32 = int_literal 2 [template]
+// CHECK:STDOUT:   %.14: i32 = int_literal 3 [template]
+// CHECK:STDOUT:   %.15: [i32; 4] = tuple_value (%.6, %.7, %.1, %.8) [template]
 // CHECK:STDOUT: }
 // CHECK:STDOUT:
 // CHECK:STDOUT: file {
@@ -56,21 +53,21 @@ var array_index: [i32; 1] = (0,) as [i32; ((5, 7, 1, 9) as [i32; 4])[2]];
 // CHECK:STDOUT:   %.loc12_66: i32 = int_literal 4 [template = constants.%.10]
 // CHECK:STDOUT:   %.loc12_67: type = array_type %.loc12_66, i32 [template = constants.%.11]
 // CHECK:STDOUT:   %.loc12_55.2: ref [i32; 4] = temporary_storage
-// CHECK:STDOUT:   %.loc12_55.3: i32 = int_literal 0 [template = constants.%.13]
+// CHECK:STDOUT:   %.loc12_55.3: i32 = int_literal 0 [template = constants.%.4]
 // CHECK:STDOUT:   %.loc12_55.4: ref i32 = array_index %.loc12_55.2, %.loc12_55.3
 // CHECK:STDOUT:   %.loc12_55.5: init i32 = initialize_from %.loc12_45 to %.loc12_55.4 [template = constants.%.6]
-// CHECK:STDOUT:   %.loc12_55.6: i32 = int_literal 1 [template = constants.%.14]
+// CHECK:STDOUT:   %.loc12_55.6: i32 = int_literal 1 [template = constants.%.1]
 // CHECK:STDOUT:   %.loc12_55.7: ref i32 = array_index %.loc12_55.2, %.loc12_55.6
 // CHECK:STDOUT:   %.loc12_55.8: init i32 = initialize_from %.loc12_48 to %.loc12_55.7 [template = constants.%.7]
-// CHECK:STDOUT:   %.loc12_55.9: i32 = int_literal 2 [template = constants.%.15]
+// CHECK:STDOUT:   %.loc12_55.9: i32 = int_literal 2 [template = constants.%.13]
 // CHECK:STDOUT:   %.loc12_55.10: ref i32 = array_index %.loc12_55.2, %.loc12_55.9
 // CHECK:STDOUT:   %.loc12_55.11: init i32 = initialize_from %.loc12_51 to %.loc12_55.10 [template = constants.%.1]
-// CHECK:STDOUT:   %.loc12_55.12: i32 = int_literal 3 [template = constants.%.16]
+// CHECK:STDOUT:   %.loc12_55.12: i32 = int_literal 3 [template = constants.%.14]
 // CHECK:STDOUT:   %.loc12_55.13: ref i32 = array_index %.loc12_55.2, %.loc12_55.12
 // CHECK:STDOUT:   %.loc12_55.14: init i32 = initialize_from %.loc12_54 to %.loc12_55.13 [template = constants.%.8]
-// CHECK:STDOUT:   %.loc12_55.15: init [i32; 4] = array_init (%.loc12_55.5, %.loc12_55.8, %.loc12_55.11, %.loc12_55.14) to %.loc12_55.2 [template = constants.%.17]
-// CHECK:STDOUT:   %.loc12_55.16: init [i32; 4] = converted %.loc12_55.1, %.loc12_55.15 [template = constants.%.17]
-// CHECK:STDOUT:   %.loc12_70: i32 = int_literal 2 [template = constants.%.18]
+// CHECK:STDOUT:   %.loc12_55.15: init [i32; 4] = array_init (%.loc12_55.5, %.loc12_55.8, %.loc12_55.11, %.loc12_55.14) to %.loc12_55.2 [template = constants.%.15]
+// CHECK:STDOUT:   %.loc12_55.16: init [i32; 4] = converted %.loc12_55.1, %.loc12_55.15 [template = constants.%.15]
+// CHECK:STDOUT:   %.loc12_70: i32 = int_literal 2 [template = constants.%.13]
 // CHECK:STDOUT:   %.loc12_55.17: ref [i32; 4] = temporary %.loc12_55.2, %.loc12_55.16
 // CHECK:STDOUT:   %.loc12_71.1: ref i32 = array_index %.loc12_55.17, %.loc12_70
 // CHECK:STDOUT:   %.loc12_71.2: i32 = bind_value %.loc12_71.1

+ 20 - 23
toolchain/check/testdata/function/builtin/call_from_operator.carbon

@@ -80,15 +80,12 @@ var arr: [i32; 1 + 2] = (3, 4, 3 + 4);
 // CHECK:STDOUT:   %.8: i32 = int_literal 3 [template]
 // CHECK:STDOUT:   %.9: type = array_type %.8, i32 [template]
 // CHECK:STDOUT:   %.10: type = ptr_type [i32; 3] [template]
-// CHECK:STDOUT:   %.11: i32 = int_literal 3 [template]
-// CHECK:STDOUT:   %.12: i32 = int_literal 4 [template]
-// CHECK:STDOUT:   %.13: <bound method> = bound_method %.11, @impl.%Op [template]
-// CHECK:STDOUT:   %.14: i32 = int_literal 7 [template]
-// CHECK:STDOUT:   %.15: type = tuple_type (i32, i32, i32) [template]
-// CHECK:STDOUT:   %.16: i32 = int_literal 0 [template]
-// CHECK:STDOUT:   %.17: i32 = int_literal 1 [template]
-// CHECK:STDOUT:   %.18: i32 = int_literal 2 [template]
-// CHECK:STDOUT:   %.19: [i32; 3] = tuple_value (%.11, %.12, %.14) [template]
+// CHECK:STDOUT:   %.11: i32 = int_literal 4 [template]
+// CHECK:STDOUT:   %.12: <bound method> = bound_method %.8, @impl.%Op [template]
+// CHECK:STDOUT:   %.13: i32 = int_literal 7 [template]
+// CHECK:STDOUT:   %.14: type = tuple_type (i32, i32, i32) [template]
+// CHECK:STDOUT:   %.15: i32 = int_literal 0 [template]
+// CHECK:STDOUT:   %.16: [i32; 3] = tuple_value (%.8, %.11, %.13) [template]
 // CHECK:STDOUT: }
 // CHECK:STDOUT:
 // CHECK:STDOUT: file {
@@ -147,25 +144,25 @@ var arr: [i32; 1 + 2] = (3, 4, 3 + 4);
 // CHECK:STDOUT:
 // CHECK:STDOUT: fn @__global_init() {
 // CHECK:STDOUT: !entry:
-// CHECK:STDOUT:   %.loc10_26: i32 = int_literal 3 [template = constants.%.11]
-// CHECK:STDOUT:   %.loc10_29: i32 = int_literal 4 [template = constants.%.12]
-// CHECK:STDOUT:   %.loc10_32: i32 = int_literal 3 [template = constants.%.11]
-// CHECK:STDOUT:   %.loc10_36: i32 = int_literal 4 [template = constants.%.12]
+// CHECK:STDOUT:   %.loc10_26: i32 = int_literal 3 [template = constants.%.8]
+// CHECK:STDOUT:   %.loc10_29: i32 = int_literal 4 [template = constants.%.11]
+// CHECK:STDOUT:   %.loc10_32: i32 = int_literal 3 [template = constants.%.8]
+// CHECK:STDOUT:   %.loc10_36: i32 = int_literal 4 [template = constants.%.11]
 // CHECK:STDOUT:   %.1: <function> = interface_witness_access @impl.%.1, element0 [template = @impl.%Op]
-// CHECK:STDOUT:   %.loc10_34.1: <bound method> = bound_method %.loc10_32, %.1 [template = constants.%.13]
-// CHECK:STDOUT:   %.loc10_34.2: init i32 = call %.loc10_34.1(%.loc10_32, %.loc10_36) [template = constants.%.14]
+// CHECK:STDOUT:   %.loc10_34.1: <bound method> = bound_method %.loc10_32, %.1 [template = constants.%.12]
+// CHECK:STDOUT:   %.loc10_34.2: init i32 = call %.loc10_34.1(%.loc10_32, %.loc10_36) [template = constants.%.13]
 // CHECK:STDOUT:   %.loc10_37.1: (i32, i32, i32) = tuple_literal (%.loc10_26, %.loc10_29, %.loc10_34.2)
-// CHECK:STDOUT:   %.loc10_37.2: i32 = int_literal 0 [template = constants.%.16]
+// CHECK:STDOUT:   %.loc10_37.2: i32 = int_literal 0 [template = constants.%.15]
 // CHECK:STDOUT:   %.loc10_37.3: ref i32 = array_index file.%arr.var, %.loc10_37.2
-// CHECK:STDOUT:   %.loc10_37.4: init i32 = initialize_from %.loc10_26 to %.loc10_37.3 [template = constants.%.11]
-// CHECK:STDOUT:   %.loc10_37.5: i32 = int_literal 1 [template = constants.%.17]
+// CHECK:STDOUT:   %.loc10_37.4: init i32 = initialize_from %.loc10_26 to %.loc10_37.3 [template = constants.%.8]
+// CHECK:STDOUT:   %.loc10_37.5: i32 = int_literal 1 [template = constants.%.3]
 // CHECK:STDOUT:   %.loc10_37.6: ref i32 = array_index file.%arr.var, %.loc10_37.5
-// CHECK:STDOUT:   %.loc10_37.7: init i32 = initialize_from %.loc10_29 to %.loc10_37.6 [template = constants.%.12]
-// CHECK:STDOUT:   %.loc10_37.8: i32 = int_literal 2 [template = constants.%.18]
+// CHECK:STDOUT:   %.loc10_37.7: init i32 = initialize_from %.loc10_29 to %.loc10_37.6 [template = constants.%.11]
+// CHECK:STDOUT:   %.loc10_37.8: i32 = int_literal 2 [template = constants.%.4]
 // CHECK:STDOUT:   %.loc10_37.9: ref i32 = array_index file.%arr.var, %.loc10_37.8
-// CHECK:STDOUT:   %.loc10_37.10: init i32 = initialize_from %.loc10_34.2 to %.loc10_37.9 [template = constants.%.14]
-// CHECK:STDOUT:   %.loc10_37.11: init [i32; 3] = array_init (%.loc10_37.4, %.loc10_37.7, %.loc10_37.10) to file.%arr.var [template = constants.%.19]
-// CHECK:STDOUT:   %.loc10_37.12: init [i32; 3] = converted %.loc10_37.1, %.loc10_37.11 [template = constants.%.19]
+// CHECK:STDOUT:   %.loc10_37.10: init i32 = initialize_from %.loc10_34.2 to %.loc10_37.9 [template = constants.%.13]
+// CHECK:STDOUT:   %.loc10_37.11: init [i32; 3] = array_init (%.loc10_37.4, %.loc10_37.7, %.loc10_37.10) to file.%arr.var [template = constants.%.16]
+// CHECK:STDOUT:   %.loc10_37.12: init [i32; 3] = converted %.loc10_37.1, %.loc10_37.11 [template = constants.%.16]
 // CHECK:STDOUT:   assign file.%arr.var, %.loc10_37.12
 // CHECK:STDOUT:   return
 // CHECK:STDOUT: }

+ 10 - 13
toolchain/check/testdata/function/builtin/import.carbon

@@ -41,12 +41,9 @@ var arr: [i32; Core.Add(1, 2)] = (1, 2, 3);
 // CHECK:STDOUT:   %.3: i32 = int_literal 3 [template]
 // CHECK:STDOUT:   %.4: type = array_type %.3, i32 [template]
 // CHECK:STDOUT:   %.5: type = ptr_type [i32; 3] [template]
-// CHECK:STDOUT:   %.6: i32 = int_literal 3 [template]
-// CHECK:STDOUT:   %.7: type = tuple_type (i32, i32, i32) [template]
-// CHECK:STDOUT:   %.8: i32 = int_literal 0 [template]
-// CHECK:STDOUT:   %.9: i32 = int_literal 1 [template]
-// CHECK:STDOUT:   %.10: i32 = int_literal 2 [template]
-// CHECK:STDOUT:   %.11: [i32; 3] = tuple_value (%.1, %.2, %.6) [template]
+// CHECK:STDOUT:   %.6: type = tuple_type (i32, i32, i32) [template]
+// CHECK:STDOUT:   %.7: i32 = int_literal 0 [template]
+// CHECK:STDOUT:   %.8: [i32; 3] = tuple_value (%.1, %.2, %.3) [template]
 // CHECK:STDOUT: }
 // CHECK:STDOUT:
 // CHECK:STDOUT: file {
@@ -72,19 +69,19 @@ var arr: [i32; Core.Add(1, 2)] = (1, 2, 3);
 // CHECK:STDOUT: !entry:
 // CHECK:STDOUT:   %.loc4_35: i32 = int_literal 1 [template = constants.%.1]
 // CHECK:STDOUT:   %.loc4_38: i32 = int_literal 2 [template = constants.%.2]
-// CHECK:STDOUT:   %.loc4_41: i32 = int_literal 3 [template = constants.%.6]
+// CHECK:STDOUT:   %.loc4_41: i32 = int_literal 3 [template = constants.%.3]
 // CHECK:STDOUT:   %.loc4_42.1: (i32, i32, i32) = tuple_literal (%.loc4_35, %.loc4_38, %.loc4_41)
-// CHECK:STDOUT:   %.loc4_42.2: i32 = int_literal 0 [template = constants.%.8]
+// CHECK:STDOUT:   %.loc4_42.2: i32 = int_literal 0 [template = constants.%.7]
 // CHECK:STDOUT:   %.loc4_42.3: ref i32 = array_index file.%arr.var, %.loc4_42.2
 // CHECK:STDOUT:   %.loc4_42.4: init i32 = initialize_from %.loc4_35 to %.loc4_42.3 [template = constants.%.1]
-// CHECK:STDOUT:   %.loc4_42.5: i32 = int_literal 1 [template = constants.%.9]
+// CHECK:STDOUT:   %.loc4_42.5: i32 = int_literal 1 [template = constants.%.1]
 // CHECK:STDOUT:   %.loc4_42.6: ref i32 = array_index file.%arr.var, %.loc4_42.5
 // CHECK:STDOUT:   %.loc4_42.7: init i32 = initialize_from %.loc4_38 to %.loc4_42.6 [template = constants.%.2]
-// CHECK:STDOUT:   %.loc4_42.8: i32 = int_literal 2 [template = constants.%.10]
+// CHECK:STDOUT:   %.loc4_42.8: i32 = int_literal 2 [template = constants.%.2]
 // CHECK:STDOUT:   %.loc4_42.9: ref i32 = array_index file.%arr.var, %.loc4_42.8
-// CHECK:STDOUT:   %.loc4_42.10: init i32 = initialize_from %.loc4_41 to %.loc4_42.9 [template = constants.%.6]
-// CHECK:STDOUT:   %.loc4_42.11: init [i32; 3] = array_init (%.loc4_42.4, %.loc4_42.7, %.loc4_42.10) to file.%arr.var [template = constants.%.11]
-// CHECK:STDOUT:   %.loc4_42.12: init [i32; 3] = converted %.loc4_42.1, %.loc4_42.11 [template = constants.%.11]
+// CHECK:STDOUT:   %.loc4_42.10: init i32 = initialize_from %.loc4_41 to %.loc4_42.9 [template = constants.%.3]
+// CHECK:STDOUT:   %.loc4_42.11: init [i32; 3] = array_init (%.loc4_42.4, %.loc4_42.7, %.loc4_42.10) to file.%arr.var [template = constants.%.8]
+// CHECK:STDOUT:   %.loc4_42.12: init [i32; 3] = converted %.loc4_42.1, %.loc4_42.11 [template = constants.%.8]
 // CHECK:STDOUT:   assign file.%arr.var, %.loc4_42.12
 // CHECK:STDOUT:   return
 // CHECK:STDOUT: }

+ 4 - 5
toolchain/check/testdata/if_expr/basic.carbon

@@ -17,8 +17,7 @@ fn F(b: bool, n: i32, m: i32) -> i32 {
 // CHECK:STDOUT:   %.3: type = ptr_type [i32; 1] [template]
 // CHECK:STDOUT:   %.4: i32 = int_literal 0 [template]
 // CHECK:STDOUT:   %.5: type = tuple_type (i32) [template]
-// CHECK:STDOUT:   %.6: i32 = int_literal 0 [template]
-// CHECK:STDOUT:   %.7: [i32; 1] = tuple_value (%.4) [template]
+// CHECK:STDOUT:   %.6: [i32; 1] = tuple_value (%.4) [template]
 // CHECK:STDOUT: }
 // CHECK:STDOUT:
 // CHECK:STDOUT: file {
@@ -44,11 +43,11 @@ fn F(b: bool, n: i32, m: i32) -> i32 {
 // CHECK:STDOUT:   %x: ref [i32; 1] = bind_name x, %x.var
 // CHECK:STDOUT:   %.loc8_22: i32 = int_literal 0 [template = constants.%.4]
 // CHECK:STDOUT:   %.loc8_24.1: (i32,) = tuple_literal (%.loc8_22)
-// CHECK:STDOUT:   %.loc8_24.2: i32 = int_literal 0 [template = constants.%.6]
+// CHECK:STDOUT:   %.loc8_24.2: i32 = int_literal 0 [template = constants.%.4]
 // CHECK:STDOUT:   %.loc8_24.3: ref i32 = array_index %x.var, %.loc8_24.2
 // CHECK:STDOUT:   %.loc8_24.4: init i32 = initialize_from %.loc8_22 to %.loc8_24.3 [template = constants.%.4]
-// CHECK:STDOUT:   %.loc8_24.5: init [i32; 1] = array_init (%.loc8_24.4) to %x.var [template = constants.%.7]
-// CHECK:STDOUT:   %.loc8_24.6: init [i32; 1] = converted %.loc8_24.1, %.loc8_24.5 [template = constants.%.7]
+// CHECK:STDOUT:   %.loc8_24.5: init [i32; 1] = array_init (%.loc8_24.4) to %x.var [template = constants.%.6]
+// CHECK:STDOUT:   %.loc8_24.6: init [i32; 1] = converted %.loc8_24.1, %.loc8_24.5 [template = constants.%.6]
 // CHECK:STDOUT:   assign %x.var, %.loc8_24.6
 // CHECK:STDOUT:   %b.ref: bool = name_ref b, %b
 // CHECK:STDOUT:   if %b.ref br !if.expr.then else br !if.expr.else

+ 2 - 4
toolchain/check/testdata/index/array_element_access.carbon

@@ -21,8 +21,6 @@ var d: i32 = a[b];
 // CHECK:STDOUT:   %.7: i32 = int_literal 0 [template]
 // CHECK:STDOUT:   %.8: i32 = int_literal 1 [template]
 // CHECK:STDOUT:   %.9: [i32; 2] = tuple_value (%.4, %.5) [template]
-// CHECK:STDOUT:   %.10: i32 = int_literal 1 [template]
-// CHECK:STDOUT:   %.11: i32 = int_literal 0 [template]
 // CHECK:STDOUT: }
 // CHECK:STDOUT:
 // CHECK:STDOUT: file {
@@ -58,10 +56,10 @@ var d: i32 = a[b];
 // CHECK:STDOUT:   %.loc7_26.8: init [i32; 2] = array_init (%.loc7_26.4, %.loc7_26.7) to file.%a.var [template = constants.%.9]
 // CHECK:STDOUT:   %.loc7_26.9: init [i32; 2] = converted %.loc7_26.1, %.loc7_26.8 [template = constants.%.9]
 // CHECK:STDOUT:   assign file.%a.var, %.loc7_26.9
-// CHECK:STDOUT:   %.loc8: i32 = int_literal 1 [template = constants.%.10]
+// CHECK:STDOUT:   %.loc8: i32 = int_literal 1 [template = constants.%.8]
 // CHECK:STDOUT:   assign file.%b.var, %.loc8
 // CHECK:STDOUT:   %a.ref.loc9: ref [i32; 2] = name_ref a, file.%a
-// CHECK:STDOUT:   %.loc9_16: i32 = int_literal 0 [template = constants.%.11]
+// CHECK:STDOUT:   %.loc9_16: i32 = int_literal 0 [template = constants.%.7]
 // CHECK:STDOUT:   %.loc9_17.1: ref i32 = array_index %a.ref.loc9, %.loc9_16
 // CHECK:STDOUT:   %.loc9_17.2: i32 = bind_value %.loc9_17.1
 // CHECK:STDOUT:   assign file.%c.var, %.loc9_17.2

+ 18 - 21
toolchain/check/testdata/index/expr_category.carbon

@@ -34,12 +34,9 @@ fn ValueBinding(b: [i32; 3]) {
 // CHECK:STDOUT:   %.5: i32 = int_literal 2 [template]
 // CHECK:STDOUT:   %.6: type = tuple_type (i32, i32, i32) [template]
 // CHECK:STDOUT:   %.7: i32 = int_literal 0 [template]
-// CHECK:STDOUT:   %.8: i32 = int_literal 1 [template]
-// CHECK:STDOUT:   %.9: i32 = int_literal 2 [template]
-// CHECK:STDOUT:   %.10: [i32; 3] = tuple_value (%.4, %.5, %.1) [template]
-// CHECK:STDOUT:   %.11: type = ptr_type i32 [template]
-// CHECK:STDOUT:   %.12: i32 = int_literal 0 [template]
-// CHECK:STDOUT:   %.13: i32 = int_literal 4 [template]
+// CHECK:STDOUT:   %.8: [i32; 3] = tuple_value (%.4, %.5, %.1) [template]
+// CHECK:STDOUT:   %.9: type = ptr_type i32 [template]
+// CHECK:STDOUT:   %.10: i32 = int_literal 4 [template]
 // CHECK:STDOUT: }
 // CHECK:STDOUT:
 // CHECK:STDOUT: file {
@@ -82,27 +79,27 @@ fn ValueBinding(b: [i32; 3]) {
 // CHECK:STDOUT:   %.loc10_29.2: i32 = int_literal 0 [template = constants.%.7]
 // CHECK:STDOUT:   %.loc10_29.3: ref i32 = array_index %a.var, %.loc10_29.2
 // CHECK:STDOUT:   %.loc10_29.4: init i32 = initialize_from %.loc10_22 to %.loc10_29.3 [template = constants.%.4]
-// CHECK:STDOUT:   %.loc10_29.5: i32 = int_literal 1 [template = constants.%.8]
+// CHECK:STDOUT:   %.loc10_29.5: i32 = int_literal 1 [template = constants.%.4]
 // CHECK:STDOUT:   %.loc10_29.6: ref i32 = array_index %a.var, %.loc10_29.5
 // CHECK:STDOUT:   %.loc10_29.7: init i32 = initialize_from %.loc10_25 to %.loc10_29.6 [template = constants.%.5]
-// CHECK:STDOUT:   %.loc10_29.8: i32 = int_literal 2 [template = constants.%.9]
+// CHECK:STDOUT:   %.loc10_29.8: i32 = int_literal 2 [template = constants.%.5]
 // CHECK:STDOUT:   %.loc10_29.9: ref i32 = array_index %a.var, %.loc10_29.8
 // CHECK:STDOUT:   %.loc10_29.10: init i32 = initialize_from %.loc10_28 to %.loc10_29.9 [template = constants.%.1]
-// CHECK:STDOUT:   %.loc10_29.11: init [i32; 3] = array_init (%.loc10_29.4, %.loc10_29.7, %.loc10_29.10) to %a.var [template = constants.%.10]
-// CHECK:STDOUT:   %.loc10_29.12: init [i32; 3] = converted %.loc10_29.1, %.loc10_29.11 [template = constants.%.10]
+// CHECK:STDOUT:   %.loc10_29.11: init [i32; 3] = array_init (%.loc10_29.4, %.loc10_29.7, %.loc10_29.10) to %a.var [template = constants.%.8]
+// CHECK:STDOUT:   %.loc10_29.12: init [i32; 3] = converted %.loc10_29.1, %.loc10_29.11 [template = constants.%.8]
 // CHECK:STDOUT:   assign %a.var, %.loc10_29.12
-// CHECK:STDOUT:   %.loc13_14: type = ptr_type i32 [template = constants.%.11]
+// CHECK:STDOUT:   %.loc13_14: type = ptr_type i32 [template = constants.%.9]
 // CHECK:STDOUT:   %pa.var: ref i32* = var pa
 // CHECK:STDOUT:   %pa: ref i32* = bind_name pa, %pa.var
 // CHECK:STDOUT:   %a.ref.loc13: ref [i32; 3] = name_ref a, %a
-// CHECK:STDOUT:   %.loc13_21: i32 = int_literal 0 [template = constants.%.12]
+// CHECK:STDOUT:   %.loc13_21: i32 = int_literal 0 [template = constants.%.7]
 // CHECK:STDOUT:   %.loc13_22: ref i32 = array_index %a.ref.loc13, %.loc13_21
 // CHECK:STDOUT:   %.loc13_18: i32* = addr_of %.loc13_22
 // CHECK:STDOUT:   assign %pa.var, %.loc13_18
 // CHECK:STDOUT:   %a.ref.loc14: ref [i32; 3] = name_ref a, %a
-// CHECK:STDOUT:   %.loc14_5: i32 = int_literal 0 [template = constants.%.12]
+// CHECK:STDOUT:   %.loc14_5: i32 = int_literal 0 [template = constants.%.7]
 // CHECK:STDOUT:   %.loc14_6: ref i32 = array_index %a.ref.loc14, %.loc14_5
-// CHECK:STDOUT:   %.loc14_10: i32 = int_literal 4 [template = constants.%.13]
+// CHECK:STDOUT:   %.loc14_10: i32 = int_literal 4 [template = constants.%.10]
 // CHECK:STDOUT:   assign %.loc14_6, %.loc14_10
 // CHECK:STDOUT:   return
 // CHECK:STDOUT: }
@@ -120,27 +117,27 @@ fn ValueBinding(b: [i32; 3]) {
 // CHECK:STDOUT:   %.loc18_29.2: i32 = int_literal 0 [template = constants.%.7]
 // CHECK:STDOUT:   %.loc18_29.3: ref i32 = array_index %a.var, %.loc18_29.2
 // CHECK:STDOUT:   %.loc18_29.4: init i32 = initialize_from %.loc18_22 to %.loc18_29.3 [template = constants.%.4]
-// CHECK:STDOUT:   %.loc18_29.5: i32 = int_literal 1 [template = constants.%.8]
+// CHECK:STDOUT:   %.loc18_29.5: i32 = int_literal 1 [template = constants.%.4]
 // CHECK:STDOUT:   %.loc18_29.6: ref i32 = array_index %a.var, %.loc18_29.5
 // CHECK:STDOUT:   %.loc18_29.7: init i32 = initialize_from %.loc18_25 to %.loc18_29.6 [template = constants.%.5]
-// CHECK:STDOUT:   %.loc18_29.8: i32 = int_literal 2 [template = constants.%.9]
+// CHECK:STDOUT:   %.loc18_29.8: i32 = int_literal 2 [template = constants.%.5]
 // CHECK:STDOUT:   %.loc18_29.9: ref i32 = array_index %a.var, %.loc18_29.8
 // CHECK:STDOUT:   %.loc18_29.10: init i32 = initialize_from %.loc18_28 to %.loc18_29.9 [template = constants.%.1]
-// CHECK:STDOUT:   %.loc18_29.11: init [i32; 3] = array_init (%.loc18_29.4, %.loc18_29.7, %.loc18_29.10) to %a.var [template = constants.%.10]
-// CHECK:STDOUT:   %.loc18_29.12: init [i32; 3] = converted %.loc18_29.1, %.loc18_29.11 [template = constants.%.10]
+// CHECK:STDOUT:   %.loc18_29.11: init [i32; 3] = array_init (%.loc18_29.4, %.loc18_29.7, %.loc18_29.10) to %a.var [template = constants.%.8]
+// CHECK:STDOUT:   %.loc18_29.12: init [i32; 3] = converted %.loc18_29.1, %.loc18_29.11 [template = constants.%.8]
 // CHECK:STDOUT:   assign %a.var, %.loc18_29.12
 // CHECK:STDOUT:   %a.ref: ref [i32; 3] = name_ref a, %a
-// CHECK:STDOUT:   %.loc22_5: i32 = int_literal 0 [template = constants.%.12]
+// CHECK:STDOUT:   %.loc22_5: i32 = int_literal 0 [template = constants.%.7]
 // CHECK:STDOUT:   %.loc22_6: ref i32 = array_index %a.ref, %.loc22_5
 // CHECK:STDOUT:   %b.ref: [i32; 3] = name_ref b, %b
-// CHECK:STDOUT:   %.loc23_5: i32 = int_literal 0 [template = constants.%.12]
+// CHECK:STDOUT:   %.loc23_5: i32 = int_literal 0 [template = constants.%.7]
 // CHECK:STDOUT:   %.loc23_6.1: ref [i32; 3] = value_as_ref %b.ref
 // CHECK:STDOUT:   %.loc23_6.2: ref i32 = array_index %.loc23_6.1, %.loc23_5
 // CHECK:STDOUT:   %.loc23_6.3: i32 = bind_value %.loc23_6.2
 // CHECK:STDOUT:   %F.ref: <function> = name_ref F, file.%F [template = file.%F]
 // CHECK:STDOUT:   %.loc24_4.1: ref [i32; 3] = temporary_storage
 // CHECK:STDOUT:   %.loc24_4.2: init [i32; 3] = call %F.ref() to %.loc24_4.1
-// CHECK:STDOUT:   %.loc24_7: i32 = int_literal 0 [template = constants.%.12]
+// CHECK:STDOUT:   %.loc24_7: i32 = int_literal 0 [template = constants.%.7]
 // CHECK:STDOUT:   %.loc24_4.3: ref [i32; 3] = temporary %.loc24_4.1, %.loc24_4.2
 // CHECK:STDOUT:   %.loc24_8.1: ref i32 = array_index %.loc24_4.3, %.loc24_7
 // CHECK:STDOUT:   %.loc24_8.2: i32 = bind_value %.loc24_8.1

+ 25 - 10
toolchain/check/testdata/index/fail_array_large_index.carbon

@@ -5,10 +5,17 @@
 // AUTOUPDATE
 
 var a: [i32; 1] = (12,);
-// CHECK:STDERR: fail_array_large_index.carbon:[[@LINE+3]]:16: ERROR: Array index `295147905179352825855` is past the end of type `[i32; 1]`.
-// CHECK:STDERR: var b: i32 = a[0xFFFFFFFFFFFFFFFFF];
-// CHECK:STDERR:                ^~~~~~~~~~~~~~~~~~~
-var b: i32 = a[0xFFFFFFFFFFFFFFFFF];
+
+// CHECK:STDERR: fail_array_large_index.carbon:[[@LINE+4]]:16: ERROR: Array index `1` is past the end of type `[i32; 1]`.
+// CHECK:STDERR: var b: i32 = a[1];
+// CHECK:STDERR:                ^
+// CHECK:STDERR:
+var b: i32 = a[1];
+
+// CHECK:STDERR: fail_array_large_index.carbon:[[@LINE+3]]:16: ERROR: Array index `2147483647` is past the end of type `[i32; 1]`.
+// CHECK:STDERR: var c: i32 = a[0x7FFF_FFFF];
+// CHECK:STDERR:                ^~~~~~~~~~~
+var c: i32 = a[0x7FFF_FFFF];
 
 // CHECK:STDOUT: --- fail_array_large_index.carbon
 // CHECK:STDOUT:
@@ -20,13 +27,14 @@ var b: i32 = a[0xFFFFFFFFFFFFFFFFF];
 // CHECK:STDOUT:   %.5: type = tuple_type (i32) [template]
 // CHECK:STDOUT:   %.6: i32 = int_literal 0 [template]
 // CHECK:STDOUT:   %.7: [i32; 1] = tuple_value (%.4) [template]
-// CHECK:STDOUT:   %.8: i32 = int_literal 295147905179352825855 [template]
+// CHECK:STDOUT:   %.8: i32 = int_literal 2147483647 [template]
 // CHECK:STDOUT: }
 // CHECK:STDOUT:
 // CHECK:STDOUT: file {
 // CHECK:STDOUT:   package: <namespace> = namespace [template] {
 // CHECK:STDOUT:     .a = %a
 // CHECK:STDOUT:     .b = %b
+// CHECK:STDOUT:     .c = %c
 // CHECK:STDOUT:   }
 // CHECK:STDOUT:   %.loc7_14: i32 = int_literal 1 [template = constants.%.1]
 // CHECK:STDOUT:   %.loc7_15: type = array_type %.loc7_14, i32 [template = constants.%.2]
@@ -34,6 +42,8 @@ var b: i32 = a[0xFFFFFFFFFFFFFFFFF];
 // CHECK:STDOUT:   %a: ref [i32; 1] = bind_name a, %a.var
 // CHECK:STDOUT:   %b.var: ref i32 = var b
 // CHECK:STDOUT:   %b: ref i32 = bind_name b, %b.var
+// CHECK:STDOUT:   %c.var: ref i32 = var c
+// CHECK:STDOUT:   %c: ref i32 = bind_name c, %c.var
 // CHECK:STDOUT: }
 // CHECK:STDOUT:
 // CHECK:STDOUT: fn @__global_init() {
@@ -46,11 +56,16 @@ var b: i32 = a[0xFFFFFFFFFFFFFFFFF];
 // CHECK:STDOUT:   %.loc7_23.5: init [i32; 1] = array_init (%.loc7_23.4) to file.%a.var [template = constants.%.7]
 // CHECK:STDOUT:   %.loc7_23.6: init [i32; 1] = converted %.loc7_23.1, %.loc7_23.5 [template = constants.%.7]
 // CHECK:STDOUT:   assign file.%a.var, %.loc7_23.6
-// CHECK:STDOUT:   %a.ref: ref [i32; 1] = name_ref a, file.%a
-// CHECK:STDOUT:   %.loc11_16: i32 = int_literal 295147905179352825855 [template = constants.%.8]
-// CHECK:STDOUT:   %.loc11_35.1: ref i32 = array_index %a.ref, %.loc11_16 [template = <error>]
-// CHECK:STDOUT:   %.loc11_35.2: i32 = bind_value %.loc11_35.1
-// CHECK:STDOUT:   assign file.%b.var, %.loc11_35.2
+// CHECK:STDOUT:   %a.ref.loc13: ref [i32; 1] = name_ref a, file.%a
+// CHECK:STDOUT:   %.loc13_16: i32 = int_literal 1 [template = constants.%.1]
+// CHECK:STDOUT:   %.loc13_17.1: ref i32 = array_index %a.ref.loc13, %.loc13_16 [template = <error>]
+// CHECK:STDOUT:   %.loc13_17.2: i32 = bind_value %.loc13_17.1
+// CHECK:STDOUT:   assign file.%b.var, %.loc13_17.2
+// CHECK:STDOUT:   %a.ref.loc18: ref [i32; 1] = name_ref a, file.%a
+// CHECK:STDOUT:   %.loc18_16: i32 = int_literal 2147483647 [template = constants.%.8]
+// CHECK:STDOUT:   %.loc18_27.1: ref i32 = array_index %a.ref.loc18, %.loc18_16 [template = <error>]
+// CHECK:STDOUT:   %.loc18_27.2: i32 = bind_value %.loc18_27.1
+// CHECK:STDOUT:   assign file.%c.var, %.loc18_27.2
 // CHECK:STDOUT:   return
 // CHECK:STDOUT: }
 // CHECK:STDOUT:

+ 21 - 8
toolchain/check/testdata/index/fail_tuple_large_index.carbon

@@ -6,10 +6,15 @@
 
 var a: (i32,) = (12,);
 var b: (i32,) = a;
-// CHECK:STDERR: fail_tuple_large_index.carbon:[[@LINE+3]]:14: ERROR: Tuple element index `295147905179352825855` is past the end of type `(i32,)`.
-// CHECK:STDERR: var c: i32 = b[0xFFFFFFFFFFFFFFFFF];
-// CHECK:STDERR:              ^~~~~~~~~~~~~~~~~~~~~~
-var c: i32 = b[0xFFFFFFFFFFFFFFFFF];
+// CHECK:STDERR: fail_tuple_large_index.carbon:[[@LINE+4]]:14: ERROR: Tuple element index `1` is past the end of type `(i32,)`.
+// CHECK:STDERR: var c: i32 = b[1];
+// CHECK:STDERR:              ^~~~
+// CHECK:STDERR:
+var c: i32 = b[1];
+// CHECK:STDERR: fail_tuple_large_index.carbon:[[@LINE+3]]:14: ERROR: Tuple element index `2147483647` is past the end of type `(i32,)`.
+// CHECK:STDERR: var d: i32 = b[0x7FFF_FFFF];
+// CHECK:STDERR:              ^~~~~~~~~~~~~~
+var d: i32 = b[0x7FFF_FFFF];
 
 // CHECK:STDOUT: --- fail_tuple_large_index.carbon
 // CHECK:STDOUT:
@@ -18,7 +23,8 @@ var c: i32 = b[0xFFFFFFFFFFFFFFFFF];
 // CHECK:STDOUT:   %.2: type = tuple_type (i32) [template]
 // CHECK:STDOUT:   %.3: i32 = int_literal 12 [template]
 // CHECK:STDOUT:   %.4: (i32,) = tuple_value (%.3) [template]
-// CHECK:STDOUT:   %.5: i32 = int_literal 295147905179352825855 [template]
+// CHECK:STDOUT:   %.5: i32 = int_literal 1 [template]
+// CHECK:STDOUT:   %.6: i32 = int_literal 2147483647 [template]
 // CHECK:STDOUT: }
 // CHECK:STDOUT:
 // CHECK:STDOUT: file {
@@ -26,6 +32,7 @@ var c: i32 = b[0xFFFFFFFFFFFFFFFFF];
 // CHECK:STDOUT:     .a = %a
 // CHECK:STDOUT:     .b = %b
 // CHECK:STDOUT:     .c = %c
+// CHECK:STDOUT:     .d = %d
 // CHECK:STDOUT:   }
 // CHECK:STDOUT:   %.loc7_13.1: (type,) = tuple_literal (i32)
 // CHECK:STDOUT:   %.loc7_13.2: type = converted %.loc7_13.1, constants.%.2 [template = constants.%.2]
@@ -37,6 +44,8 @@ var c: i32 = b[0xFFFFFFFFFFFFFFFFF];
 // CHECK:STDOUT:   %b: ref (i32,) = bind_name b, %b.var
 // CHECK:STDOUT:   %c.var: ref i32 = var c
 // CHECK:STDOUT:   %c: ref i32 = bind_name c, %c.var
+// CHECK:STDOUT:   %d.var: ref i32 = var d
+// CHECK:STDOUT:   %d: ref i32 = bind_name d, %d.var
 // CHECK:STDOUT: }
 // CHECK:STDOUT:
 // CHECK:STDOUT: fn @__global_init() {
@@ -52,10 +61,14 @@ var c: i32 = b[0xFFFFFFFFFFFFFFFFF];
 // CHECK:STDOUT:   %.loc8_17.3: init (i32,) = tuple_init (%.loc8_17.2) to file.%b.var
 // CHECK:STDOUT:   %.loc8_17.4: init (i32,) = converted %a.ref, %.loc8_17.3
 // CHECK:STDOUT:   assign file.%b.var, %.loc8_17.4
-// CHECK:STDOUT:   %b.ref: ref (i32,) = name_ref b, file.%b
-// CHECK:STDOUT:   %.loc12_16: i32 = int_literal 295147905179352825855 [template = constants.%.5]
-// CHECK:STDOUT:   %.loc12_35: ref <error> = tuple_index %b.ref, <error>
+// CHECK:STDOUT:   %b.ref.loc13: ref (i32,) = name_ref b, file.%b
+// CHECK:STDOUT:   %.loc13_16: i32 = int_literal 1 [template = constants.%.5]
+// CHECK:STDOUT:   %.loc13_17: ref <error> = tuple_index %b.ref.loc13, <error>
 // CHECK:STDOUT:   assign file.%c.var, <error>
+// CHECK:STDOUT:   %b.ref.loc17: ref (i32,) = name_ref b, file.%b
+// CHECK:STDOUT:   %.loc17_16: i32 = int_literal 2147483647 [template = constants.%.6]
+// CHECK:STDOUT:   %.loc17_27: ref <error> = tuple_index %b.ref.loc17, <error>
+// CHECK:STDOUT:   assign file.%d.var, <error>
 // CHECK:STDOUT:   return
 // CHECK:STDOUT: }
 // CHECK:STDOUT:

+ 1 - 0
toolchain/diagnostics/diagnostic_kind.def

@@ -255,6 +255,7 @@ CARBON_DIAGNOSTIC_KIND(IncompleteTypeInLetDecl)
 CARBON_DIAGNOSTIC_KIND(IncompleteTypeInMemberAccess)
 CARBON_DIAGNOSTIC_KIND(IncompleteTypeInValueConversion)
 CARBON_DIAGNOSTIC_KIND(IncompleteTypeInVarDecl)
+CARBON_DIAGNOSTIC_KIND(IntLiteralTooLargeForI32)
 CARBON_DIAGNOSTIC_KIND(InvalidArrayExpr)
 CARBON_DIAGNOSTIC_KIND(TypeNotIndexable)
 CARBON_DIAGNOSTIC_KIND(SelfOutsideImplicitParamList)