Explorar el Código

Underline the entire token when producing diagnostic messages. (#3413)

This is an incremental improvement on our diagnostic messages that
simply underlines an entire token if the token is larger than 1 char
(else it points to the single char with a caret like it used to).
Jacob Schneider hace 2 años
padre
commit
1d443a3617
Se han modificado 98 ficheros con 270 adiciones y 230 borrados
  1. 1 1
      toolchain/check/testdata/array/fail_incomplete_element.carbon
  2. 2 2
      toolchain/check/testdata/array/fail_type_mismatch.carbon
  3. 1 1
      toolchain/check/testdata/as/fail_no_conversion.carbon
  4. 1 1
      toolchain/check/testdata/basics/fail_bad_run.carbon
  5. 1 1
      toolchain/check/testdata/basics/fail_bad_run_2.carbon
  6. 2 2
      toolchain/check/testdata/class/fail_addr_not_self.carbon
  7. 3 3
      toolchain/check/testdata/class/fail_addr_self.carbon
  8. 19 19
      toolchain/check/testdata/class/fail_incomplete.carbon
  9. 2 2
      toolchain/check/testdata/class/fail_memaccess_category.carbon
  10. 2 2
      toolchain/check/testdata/class/fail_method.carbon
  11. 16 16
      toolchain/check/testdata/class/fail_redeclaration_introducer.carbon
  12. 1 1
      toolchain/check/testdata/class/fail_redefinition.carbon
  13. 2 2
      toolchain/check/testdata/class/fail_reorder.carbon
  14. 4 4
      toolchain/check/testdata/class/fail_self.carbon
  15. 1 1
      toolchain/check/testdata/class/fail_unbound_field.carbon
  16. 1 1
      toolchain/check/testdata/const/collapse.carbon
  17. 1 1
      toolchain/check/testdata/const/fail_collapse.carbon
  18. 6 6
      toolchain/check/testdata/function/call/fail_param_count.carbon
  19. 1 1
      toolchain/check/testdata/function/call/fail_param_type.carbon
  20. 7 7
      toolchain/check/testdata/if_expression/fail_not_in_function.carbon
  21. 1 1
      toolchain/check/testdata/index/fail_array_non_int_indexing.carbon
  22. 1 1
      toolchain/check/testdata/index/fail_tuple_index_error.carbon
  23. 1 1
      toolchain/check/testdata/namespace/fail_duplicate.carbon
  24. 1 1
      toolchain/check/testdata/namespace/fail_unresolved_scope.carbon
  25. 2 2
      toolchain/check/testdata/operators/fail_assignment_to_error.carbon
  26. 1 1
      toolchain/check/testdata/operators/fail_assignment_to_non_assignable.carbon
  27. 3 3
      toolchain/check/testdata/packages/fail_api_not_found.carbon
  28. 5 5
      toolchain/check/testdata/packages/fail_cycle.carbon
  29. 3 3
      toolchain/check/testdata/packages/fail_duplicate_api.carbon
  30. 8 8
      toolchain/check/testdata/packages/fail_extension.carbon
  31. 4 4
      toolchain/check/testdata/packages/fail_import_default.carbon
  32. 9 9
      toolchain/check/testdata/packages/fail_import_invalid.carbon
  33. 8 8
      toolchain/check/testdata/packages/fail_import_repeat.carbon
  34. 4 4
      toolchain/check/testdata/packages/fail_package_main.carbon
  35. 2 2
      toolchain/check/testdata/pointer/fail_address_of_error.carbon
  36. 1 1
      toolchain/check/testdata/pointer/fail_dereference_error.carbon
  37. 2 2
      toolchain/check/testdata/return/fail_returned_var_no_return_type.carbon
  38. 2 2
      toolchain/check/testdata/return/fail_returned_var_type.carbon
  39. 1 1
      toolchain/check/testdata/return/fail_value_disallowed.carbon
  40. 1 1
      toolchain/check/testdata/return/fail_value_missing.carbon
  41. 4 4
      toolchain/check/testdata/struct/fail_duplicate_name.carbon
  42. 1 1
      toolchain/check/testdata/struct/fail_nested_incomplete.carbon
  43. 1 1
      toolchain/check/testdata/tuples/fail_nested_incomplete.carbon
  44. 1 1
      toolchain/check/testdata/var/fail_not_copyable.carbon
  45. 4 4
      toolchain/check/testdata/while/fail_break_continue.carbon
  46. 5 0
      toolchain/diagnostics/BUILD
  47. 18 2
      toolchain/diagnostics/diagnostic_emitter.h
  48. 14 0
      toolchain/diagnostics/testdata/fail_multiline_token.carbon
  49. 3 3
      toolchain/driver/testdata/fail_flush_errors.carbon
  50. 6 2
      toolchain/lex/tokenized_buffer.cpp
  51. 2 2
      toolchain/parse/testdata/basics/fail_invalid_designators.carbon
  52. 1 1
      toolchain/parse/testdata/basics/fail_no_intro_with_semi.carbon
  53. 1 1
      toolchain/parse/testdata/basics/fail_no_intro_without_semi.carbon
  54. 3 3
      toolchain/parse/testdata/class/fail_introducer.carbon
  55. 1 1
      toolchain/parse/testdata/for/fail_returned_var.carbon
  56. 1 1
      toolchain/parse/testdata/function/declaration/fail_identifier_instead_of_sig.carbon
  57. 1 1
      toolchain/parse/testdata/function/declaration/fail_repeated_fn_and_semi.carbon
  58. 1 1
      toolchain/parse/testdata/function/declaration/fail_skip_without_semi_to_curly.carbon
  59. 1 1
      toolchain/parse/testdata/generics/interface/fail_missing_open_curly.carbon
  60. 2 2
      toolchain/parse/testdata/generics/interface/fail_self_param_syntax.carbon
  61. 1 1
      toolchain/parse/testdata/if/fail_else_unbraced.carbon
  62. 2 2
      toolchain/parse/testdata/if/fail_unbraced.carbon
  63. 3 3
      toolchain/parse/testdata/if_expression/fail_top_level_if.carbon
  64. 1 1
      toolchain/parse/testdata/namespace/fail_arrow.carbon
  65. 5 5
      toolchain/parse/testdata/namespace/fail_incomplete.carbon
  66. 2 2
      toolchain/parse/testdata/operators/fail_invalid_infix.carbon
  67. 2 2
      toolchain/parse/testdata/operators/fail_postincrement.carbon
  68. 1 1
      toolchain/parse/testdata/operators/fail_precedence_and_or.carbon
  69. 3 3
      toolchain/parse/testdata/operators/fail_precedence_as.carbon
  70. 4 4
      toolchain/parse/testdata/operators/fail_precedence_assign.carbon
  71. 1 1
      toolchain/parse/testdata/operators/fail_precedence_or_and.carbon
  72. 2 2
      toolchain/parse/testdata/operators/fail_variety.carbon
  73. 1 1
      toolchain/parse/testdata/operators/recover_prefix_repeat.carbon
  74. 2 2
      toolchain/parse/testdata/packages/import/fail_after_decl.carbon
  75. 6 6
      toolchain/parse/testdata/packages/import/fail_after_decl_repeated.carbon
  76. 1 1
      toolchain/parse/testdata/packages/import/fail_extra_string.carbon
  77. 1 1
      toolchain/parse/testdata/packages/import/fail_library_is_identifier.carbon
  78. 1 1
      toolchain/parse/testdata/packages/import/fail_name_is_keyword.carbon
  79. 1 1
      toolchain/parse/testdata/packages/import/fail_omit_library_keyword.carbon
  80. 1 1
      toolchain/parse/testdata/packages/import/fail_type.carbon
  81. 3 3
      toolchain/parse/testdata/packages/library/fail_invalid_name.carbon
  82. 2 2
      toolchain/parse/testdata/packages/library/fail_too_late.carbon
  83. 2 2
      toolchain/parse/testdata/packages/package/fail_after_decl.carbon
  84. 2 2
      toolchain/parse/testdata/packages/package/fail_after_import.carbon
  85. 2 2
      toolchain/parse/testdata/packages/package/fail_after_package.carbon
  86. 1 1
      toolchain/parse/testdata/packages/package/fail_extra_string.carbon
  87. 1 1
      toolchain/parse/testdata/packages/package/fail_library_is_identifier.carbon
  88. 1 1
      toolchain/parse/testdata/packages/package/fail_library_skips_name.carbon
  89. 1 1
      toolchain/parse/testdata/packages/package/fail_name_is_keyword.carbon
  90. 1 1
      toolchain/parse/testdata/packages/package/fail_omit_library_keyword.carbon
  91. 1 1
      toolchain/parse/testdata/return/fail_returned_no_var.carbon
  92. 1 1
      toolchain/parse/testdata/struct/fail_dot_string_colon.carbon
  93. 1 1
      toolchain/parse/testdata/struct/fail_dot_string_equals.carbon
  94. 1 1
      toolchain/parse/testdata/struct/fail_extra_token_in_type.carbon
  95. 1 1
      toolchain/parse/testdata/struct/fail_extra_token_in_value.carbon
  96. 1 1
      toolchain/parse/testdata/struct/fail_type_no_designator.carbon
  97. 1 1
      toolchain/parse/testdata/while/fail_unbraced.carbon
  98. 1 0
      toolchain/testing/BUILD

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

@@ -11,7 +11,7 @@ class Incomplete;
 // CHECK:STDERR:                      ^
 // CHECK:STDERR: fail_incomplete_element.carbon:[[@LINE-5]]:1: Class was forward declared here.
 // CHECK:STDERR: class Incomplete;
-// CHECK:STDERR: ^
+// CHECK:STDERR: ^~~~~
 var a: [Incomplete; 1];
 
 // CHECK:STDERR: fail_incomplete_element.carbon:[[@LINE+3]]:27: ERROR: Cannot implicitly convert from `<error>*` to `Incomplete*`.

+ 2 - 2
toolchain/check/testdata/array/fail_type_mismatch.carbon

@@ -12,7 +12,7 @@ var a: [i32; 3] = (1, "Hello", "World");
 var t1: (i32, String, String);
 // CHECK:STDERR: fail_type_mismatch.carbon:[[@LINE+3]]:19: ERROR: Cannot implicitly convert from `String` to `i32`.
 // CHECK:STDERR: var b: [i32; 3] = t1;
-// CHECK:STDERR:                   ^
+// CHECK:STDERR:                   ^~
 var b: [i32; 3] = t1;
 
 // CHECK:STDERR: fail_type_mismatch.carbon:[[@LINE+3]]:24: ERROR: Cannot initialize array of 3 element(s) from 2 initializer(s).
@@ -23,7 +23,7 @@ var c: [i32; 3] = (1, 2);
 var t2: (i32, i32);
 // CHECK:STDERR: fail_type_mismatch.carbon:[[@LINE+3]]:19: ERROR: Cannot initialize array of 3 element(s) from tuple with 2 element(s).
 // CHECK:STDERR: var d: [i32; 3] = t2;
-// CHECK:STDERR:                   ^
+// CHECK:STDERR:                   ^~
 var d: [i32; 3] = t2;
 
 // CHECK:STDOUT: constants {

+ 1 - 1
toolchain/check/testdata/as/fail_no_conversion.carbon

@@ -6,7 +6,7 @@
 
 // CHECK:STDERR: fail_no_conversion.carbon:[[@LINE+3]]:23: ERROR: Cannot convert from `i32` to `(i32, i32) as type` with `as`.
 // CHECK:STDERR: let n: (i32, i32) = 1 as (i32, i32);
-// CHECK:STDERR:                       ^
+// CHECK:STDERR:                       ^~
 let n: (i32, i32) = 1 as (i32, i32);
 
 // CHECK:STDOUT: constants {

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

@@ -6,7 +6,7 @@
 
 // CHECK:STDERR: fail_bad_run.carbon:[[@LINE+6]]:1: ERROR: Invalid signature for `Main.Run` function. Expected `fn ()` or `fn () -> i32`.
 // CHECK:STDERR: fn Run() -> String {}
-// CHECK:STDERR: ^
+// CHECK:STDERR: ^~
 // CHECK:STDERR: fail_bad_run.carbon:[[@LINE+3]]:21: ERROR: Missing `return` at end of function with declared return type.
 // CHECK:STDERR: fn Run() -> String {}
 // CHECK:STDERR:                     ^

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

@@ -6,7 +6,7 @@
 
 // CHECK:STDERR: fail_bad_run_2.carbon:[[@LINE+3]]:1: ERROR: Invalid signature for `Main.Run` function. Expected `fn ()` or `fn () -> i32`.
 // CHECK:STDERR: fn Run(n: i32) {}
-// CHECK:STDERR: ^
+// CHECK:STDERR: ^~
 fn Run(n: i32) {}
 
 // CHECK:STDOUT: file "fail_bad_run_2.carbon" {

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

@@ -7,12 +7,12 @@
 class Class {
   // CHECK:STDERR: fail_addr_not_self.carbon:[[@LINE+3]]:8: ERROR: `addr` can only be applied to a `self` parameter.
   // CHECK:STDERR:   fn F[addr a: Class*]();
-  // CHECK:STDERR:        ^
+  // CHECK:STDERR:        ^~~~
   fn F[addr a: Class*]();
 
   // CHECK:STDERR: fail_addr_not_self.carbon:[[@LINE+3]]:8: ERROR: `addr` can only be applied to a `self` parameter.
   // CHECK:STDERR:   fn G(addr b: Class*);
-  // CHECK:STDERR:        ^
+  // CHECK:STDERR:        ^~~~
   fn G(addr b: Class*);
 }
 

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

@@ -15,7 +15,7 @@ fn F(c: Class, p: Class*) {
   // CHECK:STDERR:      ^
   // CHECK:STDERR: fail_addr_self.carbon:[[@LINE-8]]:13: Initializing `addr self` parameter of method declared here.
   // CHECK:STDERR:   fn F[addr self: Class*]();
-  // CHECK:STDERR:             ^
+  // CHECK:STDERR:             ^~~~
   c.F();
 
   // CHECK:STDERR: fail_addr_self.carbon:[[@LINE+6]]:6: ERROR: `addr self` method cannot be invoked on a value.
@@ -23,7 +23,7 @@ fn F(c: Class, p: Class*) {
   // CHECK:STDERR:      ^
   // CHECK:STDERR: fail_addr_self.carbon:[[@LINE-15]]:13: Initializing `addr self` parameter of method declared here.
   // CHECK:STDERR:   fn G[addr self: Class]();
-  // CHECK:STDERR:             ^
+  // CHECK:STDERR:             ^~~~
   c.G();
 
   // This call is OK.
@@ -34,7 +34,7 @@ fn F(c: Class, p: Class*) {
   // CHECK:STDERR:         ^
   // CHECK:STDERR: fail_addr_self.carbon:[[@LINE-26]]:13: Initializing `addr self` parameter of method declared here.
   // CHECK:STDERR:   fn G[addr self: Class]();
-  // CHECK:STDERR:             ^
+  // CHECK:STDERR:             ^~~~
   (*p).G();
 }
 

+ 19 - 19
toolchain/check/testdata/class/fail_incomplete.carbon

@@ -8,36 +8,36 @@ class Class;
 
 // CHECK:STDERR: fail_incomplete.carbon:[[@LINE+6]]:4: ERROR: Cannot declare a member of incomplete class `Class`.
 // CHECK:STDERR: fn Class.Function() {}
-// CHECK:STDERR:    ^
+// CHECK:STDERR:    ^~~~~
 // CHECK:STDERR: fail_incomplete.carbon:[[@LINE-5]]:1: Class was forward declared here.
 // CHECK:STDERR: class Class;
-// CHECK:STDERR: ^
+// CHECK:STDERR: ^~~~~
 fn Class.Function() {}
 
 fn CallClassFunction() {
   // CHECK:STDERR: fail_incomplete.carbon:[[@LINE+6]]:3: ERROR: Member access into incomplete class `Class`.
   // CHECK:STDERR:   Class.Function();
-  // CHECK:STDERR:   ^
+  // CHECK:STDERR:   ^~~~~
   // CHECK:STDERR: fail_incomplete.carbon:[[@LINE-14]]:1: Class was forward declared here.
   // CHECK:STDERR: class Class;
-  // CHECK:STDERR: ^
+  // CHECK:STDERR: ^~~~~
   Class.Function();
 }
 
 // CHECK:STDERR: fail_incomplete.carbon:[[@LINE+6]]:17: ERROR: Variable has incomplete type `Class`.
 // CHECK:STDERR: var global_var: Class;
-// CHECK:STDERR:                 ^
+// CHECK:STDERR:                 ^~~~~
 // CHECK:STDERR: fail_incomplete.carbon:[[@LINE-23]]:1: Class was forward declared here.
 // CHECK:STDERR: class Class;
-// CHECK:STDERR: ^
+// CHECK:STDERR: ^~~~~
 var global_var: Class;
 
 // CHECK:STDERR: fail_incomplete.carbon:[[@LINE+6]]:24: ERROR: Function returns incomplete type `Class`.
 // CHECK:STDERR: fn ConvertFromStruct() -> Class { return {}; }
-// CHECK:STDERR:                        ^
+// CHECK:STDERR:                        ^~
 // CHECK:STDERR: fail_incomplete.carbon:[[@LINE-31]]:1: Class was forward declared here.
 // CHECK:STDERR: class Class;
-// CHECK:STDERR: ^
+// CHECK:STDERR: ^~~~~
 fn ConvertFromStruct() -> Class { return {}; }
 
 // TODO: Once the `->` operator is supported:
@@ -51,16 +51,16 @@ fn MemberAccess(p: Class*) -> i32 {
   // CHECK:STDERR:           ^
   // CHECK:STDERR: fail_incomplete.carbon:[[@LINE-45]]:1: Class was forward declared here.
   // CHECK:STDERR: class Class;
-  // CHECK:STDERR: ^
+  // CHECK:STDERR: ^~~~~
   return (*p).n;
 }
 
 // CHECK:STDERR: fail_incomplete.carbon:[[@LINE+6]]:20: ERROR: Function returns incomplete type `Class`.
 // CHECK:STDERR: fn Copy(p: Class*) -> Class {
-// CHECK:STDERR:                    ^
+// CHECK:STDERR:                    ^~
 // CHECK:STDERR: fail_incomplete.carbon:[[@LINE-54]]:1: Class was forward declared here.
 // CHECK:STDERR: class Class;
-// CHECK:STDERR: ^
+// CHECK:STDERR: ^~~~~
 fn Copy(p: Class*) -> Class {
   return *p;
 }
@@ -68,10 +68,10 @@ fn Copy(p: Class*) -> Class {
 fn Let(p: Class*) {
   // CHECK:STDERR: fail_incomplete.carbon:[[@LINE+6]]:10: ERROR: `let` binding has incomplete type `Class`.
   // CHECK:STDERR:   let c: Class = *p;
-  // CHECK:STDERR:          ^
+  // CHECK:STDERR:          ^~~~~
   // CHECK:STDERR: fail_incomplete.carbon:[[@LINE-65]]:1: Class was forward declared here.
   // CHECK:STDERR: class Class;
-  // CHECK:STDERR: ^
+  // CHECK:STDERR: ^~~~~
   let c: Class = *p;
 }
 
@@ -81,10 +81,10 @@ fn TakeIncomplete(c: Class);
 //
 // CHECK:STDERR: fail_incomplete.carbon:[[@LINE+6]]:23: ERROR: Function returns incomplete type `Class`.
 // CHECK:STDERR: fn ReturnIncomplete() -> Class;
-// CHECK:STDERR:                       ^
+// CHECK:STDERR:                       ^~
 // CHECK:STDERR: fail_incomplete.carbon:[[@LINE-78]]:1: Class was forward declared here.
 // CHECK:STDERR: class Class;
-// CHECK:STDERR: ^
+// CHECK:STDERR: ^~~~~
 fn ReturnIncomplete() -> Class;
 
 fn CallTakeIncomplete(p: Class*) {
@@ -93,10 +93,10 @@ fn CallTakeIncomplete(p: Class*) {
   // CHECK:STDERR:                 ^
   // CHECK:STDERR: fail_incomplete.carbon:[[@LINE-87]]:1: Class was forward declared here.
   // CHECK:STDERR: class Class;
-  // CHECK:STDERR: ^
+  // CHECK:STDERR: ^~~~~
   // CHECK:STDERR: fail_incomplete.carbon:[[@LINE-19]]:1: Initializing parameter 1 of function declared here.
   // CHECK:STDERR: fn TakeIncomplete(c: Class);
-  // CHECK:STDERR: ^
+  // CHECK:STDERR: ^~
   TakeIncomplete(*p);
 
   // CHECK:STDERR: fail_incomplete.carbon:[[@LINE+9]]:17: ERROR: Forming value of incomplete type `Class`.
@@ -104,10 +104,10 @@ fn CallTakeIncomplete(p: Class*) {
   // CHECK:STDERR:                 ^
   // CHECK:STDERR: fail_incomplete.carbon:[[@LINE-98]]:1: Class was forward declared here.
   // CHECK:STDERR: class Class;
-  // CHECK:STDERR: ^
+  // CHECK:STDERR: ^~~~~
   // CHECK:STDERR: fail_incomplete.carbon:[[@LINE-30]]:1: Initializing parameter 1 of function declared here.
   // CHECK:STDERR: fn TakeIncomplete(c: Class);
-  // CHECK:STDERR: ^
+  // CHECK:STDERR: ^~
   TakeIncomplete({});
 }
 

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

@@ -19,7 +19,7 @@ fn F(s: {.a: A}, b: B) {
   // CHECK:STDERR:        ^
   // CHECK:STDERR: fail_memaccess_category.carbon:[[@LINE-12]]:13: Initializing `addr self` parameter of method declared here.
   // CHECK:STDERR:   fn F[addr self: A*]();
-  // CHECK:STDERR:             ^
+  // CHECK:STDERR:             ^~~~
   s.a.F();
 
   // `b` has an object representation for `A`, but this is still invalid for
@@ -29,7 +29,7 @@ fn F(s: {.a: A}, b: B) {
   // CHECK:STDERR:        ^
   // CHECK:STDERR: fail_memaccess_category.carbon:[[@LINE-22]]:13: Initializing `addr self` parameter of method declared here.
   // CHECK:STDERR:   fn F[addr self: A*]();
-  // CHECK:STDERR:             ^
+  // CHECK:STDERR:             ^~~~
   b.a.F();
 }
 

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

@@ -19,14 +19,14 @@ fn F(c: Class) {
   // CHECK:STDERR:                 ^
   // CHECK:STDERR: fail_method.carbon:[[@LINE-11]]:3: Calling function declared here.
   // CHECK:STDERR:   fn WithSelf[self: Class]();
-  // CHECK:STDERR:   ^
+  // CHECK:STDERR:   ^~
   Class.WithSelf();
   // CHECK:STDERR: fail_method.carbon:[[@LINE+6]]:17: ERROR: 1 argument(s) passed to function expecting 0 argument(s).
   // CHECK:STDERR:   Class.WithSelf(c);
   // CHECK:STDERR:                 ^
   // CHECK:STDERR: fail_method.carbon:[[@LINE-18]]:3: Calling function declared here.
   // CHECK:STDERR:   fn WithSelf[self: Class]();
-  // CHECK:STDERR:   ^
+  // CHECK:STDERR:   ^~
   Class.WithSelf(c);
 }
 

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

@@ -7,71 +7,71 @@
 class A;
 // CHECK:STDERR: fail_redeclaration_introducer.carbon:[[@LINE+6]]:1: ERROR: Class redeclared with different inheritance kind.
 // CHECK:STDERR: base class A {}
-// CHECK:STDERR: ^
+// CHECK:STDERR: ^~~~
 // CHECK:STDERR: fail_redeclaration_introducer.carbon:[[@LINE-4]]:1: Previously declared here.
 // CHECK:STDERR: class A;
-// CHECK:STDERR: ^
+// CHECK:STDERR: ^~~~~
 base class A {}
 
 class B;
 // CHECK:STDERR: fail_redeclaration_introducer.carbon:[[@LINE+6]]:1: ERROR: Class redeclared with different inheritance kind.
 // CHECK:STDERR: abstract class B {}
-// CHECK:STDERR: ^
+// CHECK:STDERR: ^~~~~~~~
 // CHECK:STDERR: fail_redeclaration_introducer.carbon:[[@LINE-4]]:1: Previously declared here.
 // CHECK:STDERR: class B;
-// CHECK:STDERR: ^
+// CHECK:STDERR: ^~~~~
 abstract class B {}
 
 base class C;
 // CHECK:STDERR: fail_redeclaration_introducer.carbon:[[@LINE+6]]:1: ERROR: Class redeclared with different inheritance kind.
 // CHECK:STDERR: class C {}
-// CHECK:STDERR: ^
+// CHECK:STDERR: ^~~~~
 // CHECK:STDERR: fail_redeclaration_introducer.carbon:[[@LINE-4]]:1: Previously declared here.
 // CHECK:STDERR: base class C;
-// CHECK:STDERR: ^
+// CHECK:STDERR: ^~~~
 class C {}
 
 base class D;
 // CHECK:STDERR: fail_redeclaration_introducer.carbon:[[@LINE+6]]:1: ERROR: Class redeclared with different inheritance kind.
 // CHECK:STDERR: abstract class D {}
-// CHECK:STDERR: ^
+// CHECK:STDERR: ^~~~~~~~
 // CHECK:STDERR: fail_redeclaration_introducer.carbon:[[@LINE-4]]:1: Previously declared here.
 // CHECK:STDERR: base class D;
-// CHECK:STDERR: ^
+// CHECK:STDERR: ^~~~
 abstract class D {}
 
 abstract class E;
 // CHECK:STDERR: fail_redeclaration_introducer.carbon:[[@LINE+6]]:1: ERROR: Class redeclared with different inheritance kind.
 // CHECK:STDERR: class E {}
-// CHECK:STDERR: ^
+// CHECK:STDERR: ^~~~~
 // CHECK:STDERR: fail_redeclaration_introducer.carbon:[[@LINE-4]]:1: Previously declared here.
 // CHECK:STDERR: abstract class E;
-// CHECK:STDERR: ^
+// CHECK:STDERR: ^~~~~~~~
 class E {}
 
 abstract class F;
 // CHECK:STDERR: fail_redeclaration_introducer.carbon:[[@LINE+6]]:1: ERROR: Class redeclared with different inheritance kind.
 // CHECK:STDERR: base class F {}
-// CHECK:STDERR: ^
+// CHECK:STDERR: ^~~~
 // CHECK:STDERR: fail_redeclaration_introducer.carbon:[[@LINE-4]]:1: Previously declared here.
 // CHECK:STDERR: abstract class F;
-// CHECK:STDERR: ^
+// CHECK:STDERR: ^~~~~~~~
 base class F {}
 
 class G {}
 // CHECK:STDERR: fail_redeclaration_introducer.carbon:[[@LINE+6]]:1: ERROR: Class redeclared with different inheritance kind.
 // CHECK:STDERR: abstract class G;
-// CHECK:STDERR: ^
+// CHECK:STDERR: ^~~~~~~~
 // CHECK:STDERR: fail_redeclaration_introducer.carbon:[[@LINE-4]]:1: Previously declared here.
 // CHECK:STDERR: class G {}
-// CHECK:STDERR: ^
+// CHECK:STDERR: ^~~~~
 abstract class G;
 // CHECK:STDERR: fail_redeclaration_introducer.carbon:[[@LINE+6]]:1: ERROR: Class redeclared with different inheritance kind.
 // CHECK:STDERR: base class G;
-// CHECK:STDERR: ^
+// CHECK:STDERR: ^~~~
 // CHECK:STDERR: fail_redeclaration_introducer.carbon:[[@LINE-11]]:1: Previously declared here.
 // CHECK:STDERR: class G {}
-// CHECK:STDERR: ^
+// CHECK:STDERR: ^~~~~
 base class G;
 
 // CHECK:STDOUT: constants {

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

@@ -14,7 +14,7 @@ class Class {
 // CHECK:STDERR:             ^
 // CHECK:STDERR: fail_redefinition.carbon:[[@LINE-8]]:1: Previous definition was here.
 // CHECK:STDERR: class Class {
-// CHECK:STDERR: ^
+// CHECK:STDERR: ^~~~~
 class Class {
   fn G();
   fn H();

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

@@ -10,10 +10,10 @@ class Class {
     // later.
     // CHECK:STDERR: fail_reorder.carbon:[[@LINE+9]]:12: ERROR: Member access into incomplete class `Class`.
     // CHECK:STDERR:     return Class.F();
-    // CHECK:STDERR:            ^
+    // CHECK:STDERR:            ^~~~~
     // CHECK:STDERR: fail_reorder.carbon:[[@LINE-7]]:1: Class is incomplete within its definition.
     // CHECK:STDERR: class Class {
-    // CHECK:STDERR: ^
+    // CHECK:STDERR: ^~~~~
     // CHECK:STDERR: fail_reorder.carbon:[[@LINE+3]]:17: ERROR: Name `F` not found.
     // CHECK:STDERR:     return Class.F();
     // CHECK:STDERR:                 ^

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

@@ -12,10 +12,10 @@ class Class {
 
   // CHECK:STDERR: fail_self.carbon:[[@LINE+6]]:10: ERROR: Function returns incomplete type `Class`.
   // CHECK:STDERR:   fn G() -> Class;
-  // CHECK:STDERR:          ^
+  // CHECK:STDERR:          ^~
   // CHECK:STDERR: fail_self.carbon:[[@LINE-9]]:1: Class is incomplete within its definition.
   // CHECK:STDERR: class Class {
-  // CHECK:STDERR: ^
+  // CHECK:STDERR: ^~~~~
   fn G() -> Class;
 }
 
@@ -32,7 +32,7 @@ fn Class.G() -> Class {
   var self: Class;
   // CHECK:STDERR: fail_self.carbon:[[@LINE+3]]:10: ERROR: Name `self` not found.
   // CHECK:STDERR:   return self;
-  // CHECK:STDERR:          ^
+  // CHECK:STDERR:          ^~~~
   return self;
 }
 
@@ -46,7 +46,7 @@ fn CallWrongSelf(ws: WrongSelf) {
   // CHECK:STDERR:       ^
   // CHECK:STDERR: fail_self.carbon:[[@LINE-7]]:8: Initializing `self` parameter of method declared here.
   // CHECK:STDERR:   fn F[self: Class]();
-  // CHECK:STDERR:        ^
+  // CHECK:STDERR:        ^~~~
   ws.F();
 }
 

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

@@ -9,7 +9,7 @@ class Class {
   fn F() -> i32 {
     // CHECK:STDERR: fail_unbound_field.carbon:[[@LINE+3]]:12: ERROR: Expression cannot be used as a value.
     // CHECK:STDERR:     return field;
-    // CHECK:STDERR:            ^
+    // CHECK:STDERR:            ^~~~~
     return field;
   }
 }

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

@@ -7,7 +7,7 @@
 // OK, `const (const i32)` is the same type as `const i32`.
 // CHECK:STDERR: collapse.carbon:[[@LINE+3]]:25: `const` applied repeatedly to the same type has no additional effect.
 // CHECK:STDERR: fn F(p: const i32**) -> const (const i32)** {
-// CHECK:STDERR:                         ^
+// CHECK:STDERR:                         ^~~~~
 fn F(p: const i32**) -> const (const i32)** {
   return p;
 }

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

@@ -6,7 +6,7 @@
 
 // CHECK:STDERR: fail_collapse.carbon:[[@LINE+3]]:9: `const` applied repeatedly to the same type has no additional effect.
 // CHECK:STDERR: fn G(p: const (const i32)**) -> i32** {
-// CHECK:STDERR:         ^
+// CHECK:STDERR:         ^~~~~
 fn G(p: const (const i32)**) -> i32** {
   // CHECK:STDERR: fail_collapse.carbon:[[@LINE+3]]:11: ERROR: Cannot implicitly convert from `const i32**` to `i32**`.
   // CHECK:STDERR:   return p;

+ 6 - 6
toolchain/check/testdata/function/call/fail_param_count.carbon

@@ -14,14 +14,14 @@ fn Main() {
   // CHECK:STDERR:       ^
   // CHECK:STDERR: fail_param_count.carbon:[[@LINE-8]]:1: Calling function declared here.
   // CHECK:STDERR: fn Run0() {}
-  // CHECK:STDERR: ^
+  // CHECK:STDERR: ^~
   Run0(1);
   // CHECK:STDERR: fail_param_count.carbon:[[@LINE+6]]:7: ERROR: 2 argument(s) passed to function expecting 0 argument(s).
   // CHECK:STDERR:   Run0(0, 1);
   // CHECK:STDERR:       ^
   // CHECK:STDERR: fail_param_count.carbon:[[@LINE-15]]:1: Calling function declared here.
   // CHECK:STDERR: fn Run0() {}
-  // CHECK:STDERR: ^
+  // CHECK:STDERR: ^~
   Run0(0, 1);
 
   // CHECK:STDERR: fail_param_count.carbon:[[@LINE+6]]:7: ERROR: 0 argument(s) passed to function expecting 1 argument(s).
@@ -29,14 +29,14 @@ fn Main() {
   // CHECK:STDERR:       ^
   // CHECK:STDERR: fail_param_count.carbon:[[@LINE-22]]:1: Calling function declared here.
   // CHECK:STDERR: fn Run1(a: i32) {}
-  // CHECK:STDERR: ^
+  // CHECK:STDERR: ^~
   Run1();
   // CHECK:STDERR: fail_param_count.carbon:[[@LINE+6]]:7: ERROR: 2 argument(s) passed to function expecting 1 argument(s).
   // CHECK:STDERR:   Run1(0, 1);
   // CHECK:STDERR:       ^
   // CHECK:STDERR: fail_param_count.carbon:[[@LINE-29]]:1: Calling function declared here.
   // CHECK:STDERR: fn Run1(a: i32) {}
-  // CHECK:STDERR: ^
+  // CHECK:STDERR: ^~
   Run1(0, 1);
 
   // CHECK:STDERR: fail_param_count.carbon:[[@LINE+6]]:7: ERROR: 0 argument(s) passed to function expecting 2 argument(s).
@@ -44,14 +44,14 @@ fn Main() {
   // CHECK:STDERR:       ^
   // CHECK:STDERR: fail_param_count.carbon:[[@LINE-36]]:1: Calling function declared here.
   // CHECK:STDERR: fn Run2(a: i32, b: i32) {}
-  // CHECK:STDERR: ^
+  // CHECK:STDERR: ^~
   Run2();
   // CHECK:STDERR: fail_param_count.carbon:[[@LINE+6]]:7: ERROR: 1 argument(s) passed to function expecting 2 argument(s).
   // CHECK:STDERR:   Run2(0);
   // CHECK:STDERR:       ^
   // CHECK:STDERR: fail_param_count.carbon:[[@LINE-43]]:1: Calling function declared here.
   // CHECK:STDERR: fn Run2(a: i32, b: i32) {}
-  // CHECK:STDERR: ^
+  // CHECK:STDERR: ^~
   Run2(0);
 }
 

+ 1 - 1
toolchain/check/testdata/function/call/fail_param_type.carbon

@@ -12,7 +12,7 @@ fn F() {
   // CHECK:STDERR:    ^
   // CHECK:STDERR: fail_param_type.carbon:[[@LINE-6]]:1: Initializing parameter 1 of function declared here.
   // CHECK:STDERR: fn G(a: i32) {}
-  // CHECK:STDERR: ^
+  // CHECK:STDERR: ^~
   G(1.0);
 }
 

+ 7 - 7
toolchain/check/testdata/if_expression/fail_not_in_function.carbon

@@ -7,29 +7,29 @@
 // TODO: Should work with compile-time evaluation.
 // CHECK:STDERR: fail_not_in_function.carbon:[[@LINE+9]]:14: ERROR: Semantics TODO: `Control flow expressions are currently only supported inside functions.`.
 // CHECK:STDERR: let x: i32 = if true then 1 else 0;
-// CHECK:STDERR:              ^
+// CHECK:STDERR:              ^~
 // CHECK:STDERR: fail_not_in_function.carbon:[[@LINE+6]]:22: ERROR: Semantics TODO: `Control flow expressions are currently only supported inside functions.`.
 // CHECK:STDERR: let x: i32 = if true then 1 else 0;
-// CHECK:STDERR:                      ^
+// CHECK:STDERR:                      ^~~~
 // CHECK:STDERR: fail_not_in_function.carbon:[[@LINE+3]]:29: ERROR: Semantics TODO: `Control flow expressions are currently only supported inside functions.`.
 // CHECK:STDERR: let x: i32 = if true then 1 else 0;
-// CHECK:STDERR:                             ^
+// CHECK:STDERR:                             ^~~~
 let x: i32 = if true then 1 else 0;
 
 class C {
   // TODO: Should work with compile-time evaluation.
   // CHECK:STDERR: fail_not_in_function.carbon:[[@LINE+12]]:10: ERROR: Semantics TODO: `Control flow expressions are currently only supported inside functions.`.
   // CHECK:STDERR:   var n: if true then i32 else f64;
-  // CHECK:STDERR:          ^
+  // CHECK:STDERR:          ^~
   // CHECK:STDERR: fail_not_in_function.carbon:[[@LINE+9]]:18: ERROR: Semantics TODO: `Control flow expressions are currently only supported inside functions.`.
   // CHECK:STDERR:   var n: if true then i32 else f64;
-  // CHECK:STDERR:                  ^
+  // CHECK:STDERR:                  ^~~~
   // CHECK:STDERR: fail_not_in_function.carbon:[[@LINE+6]]:27: ERROR: Semantics TODO: `Control flow expressions are currently only supported inside functions.`.
   // CHECK:STDERR:   var n: if true then i32 else f64;
-  // CHECK:STDERR:                           ^
+  // CHECK:STDERR:                           ^~~~
   // CHECK:STDERR: fail_not_in_function.carbon:[[@LINE+3]]:27: ERROR: Cannot evaluate type expression.
   // CHECK:STDERR:   var n: if true then i32 else f64;
-  // CHECK:STDERR:                           ^
+  // CHECK:STDERR:                           ^~~~
   var n: if true then i32 else f64;
 }
 

+ 1 - 1
toolchain/check/testdata/index/fail_array_non_int_indexing.carbon

@@ -7,7 +7,7 @@
 var a: [i32; 1] = (12,);
 // CHECK:STDERR: fail_array_non_int_indexing.carbon:[[@LINE+3]]:16: ERROR: Cannot implicitly convert from `f64` to `i32`.
 // CHECK:STDERR: var b: i32 = a[2.6];
-// CHECK:STDERR:                ^
+// CHECK:STDERR:                ^~~
 var b: i32 = a[2.6];
 
 // CHECK:STDOUT: constants {

+ 1 - 1
toolchain/check/testdata/index/fail_tuple_index_error.carbon

@@ -7,7 +7,7 @@
 var a: (i32, i32) = (12, 6);
 // CHECK:STDERR: fail_tuple_index_error.carbon:[[@LINE+3]]:16: ERROR: Name `oops` not found.
 // CHECK:STDERR: var b: i32 = a[oops];
-// CHECK:STDERR:                ^
+// CHECK:STDERR:                ^~~~
 var b: i32 = a[oops];
 
 // CHECK:STDOUT: constants {

+ 1 - 1
toolchain/check/testdata/namespace/fail_duplicate.carbon

@@ -14,7 +14,7 @@ fn Foo.Baz() {
 // CHECK:STDERR:              ^
 // CHECK:STDERR: fail_duplicate.carbon:[[@LINE-6]]:1: Previous definition was here.
 // CHECK:STDERR: fn Foo.Baz() {
-// CHECK:STDERR: ^
+// CHECK:STDERR: ^~
 fn Foo.Baz() {
 }
 

+ 1 - 1
toolchain/check/testdata/namespace/fail_unresolved_scope.carbon

@@ -6,7 +6,7 @@
 
 // CHECK:STDERR: fail_unresolved_scope.carbon:[[@LINE+3]]:4: ERROR: Name `Foo` not found.
 // CHECK:STDERR: fn Foo.Baz() {
-// CHECK:STDERR:    ^
+// CHECK:STDERR:    ^~~
 fn Foo.Baz() {
 }
 

+ 2 - 2
toolchain/check/testdata/operators/fail_assignment_to_error.carbon

@@ -7,11 +7,11 @@
 fn Main() {
   // CHECK:STDERR: fail_assignment_to_error.carbon:[[@LINE+3]]:3: ERROR: Name `undeclared` not found.
   // CHECK:STDERR:   undeclared = 42;
-  // CHECK:STDERR:   ^
+  // CHECK:STDERR:   ^~~~~~~~~~
   undeclared = 42;
   // CHECK:STDERR: fail_assignment_to_error.carbon:[[@LINE+3]]:4: ERROR: Name `also_undeclared` not found.
   // CHECK:STDERR:   *also_undeclared = 42;
-  // CHECK:STDERR:    ^
+  // CHECK:STDERR:    ^~~~~~~~~~~~~~~
   *also_undeclared = 42;
 }
 

+ 1 - 1
toolchain/check/testdata/operators/fail_assignment_to_non_assignable.carbon

@@ -26,7 +26,7 @@ fn Main() {
   (n, n) = (1, 2);
   // CHECK:STDERR: fail_assignment_to_non_assignable.carbon:[[@LINE+3]]:3: ERROR: Expression is not assignable.
   // CHECK:STDERR:   i32 = i32*;
-  // CHECK:STDERR:   ^
+  // CHECK:STDERR:   ^~~
   i32 = i32*;
   // CHECK:STDERR: fail_assignment_to_non_assignable.carbon:[[@LINE+3]]:18: ERROR: Expression is not assignable.
   // CHECK:STDERR:   {.x = 1, .y = 2} = {.x = 3, .y = 4};

+ 3 - 3
toolchain/check/testdata/packages/fail_api_not_found.carbon

@@ -8,21 +8,21 @@
 
 // CHECK:STDERR: no_api.impl.carbon:[[@LINE+3]]:1: ERROR: Corresponding API not found.
 // CHECK:STDERR: package Foo impl;
-// CHECK:STDERR: ^
+// CHECK:STDERR: ^~~~~~~
 package Foo impl;
 
 // --- no_api_lib.impl.carbon
 
 // CHECK:STDERR: no_api_lib.impl.carbon:[[@LINE+3]]:1: ERROR: Corresponding API not found.
 // CHECK:STDERR: package Foo library "Bar" impl;
-// CHECK:STDERR: ^
+// CHECK:STDERR: ^~~~~~~
 package Foo library "Bar" impl;
 
 // --- no_api_main_lib.impl.carbon
 
 // CHECK:STDERR: no_api_main_lib.impl.carbon:[[@LINE+3]]:1: ERROR: Corresponding API not found.
 // CHECK:STDERR: library "Bar" impl;
-// CHECK:STDERR: ^
+// CHECK:STDERR: ^~~~~~~
 library "Bar" impl;
 
 // CHECK:STDOUT: file "no_api.impl.carbon" {

+ 5 - 5
toolchain/check/testdata/packages/fail_cycle.carbon

@@ -10,7 +10,7 @@ package A api;
 
 // CHECK:STDERR: a.carbon:[[@LINE+3]]:1: ERROR: Import cannot be used due to a cycle. Cycle must be fixed to import.
 // CHECK:STDERR: import B;
-// CHECK:STDERR: ^
+// CHECK:STDERR: ^~~~~~
 import B;
 
 // --- b.carbon
@@ -19,7 +19,7 @@ package B api;
 
 // CHECK:STDERR: b.carbon:[[@LINE+3]]:1: ERROR: Import cannot be used due to a cycle. Cycle must be fixed to import.
 // CHECK:STDERR: import C;
-// CHECK:STDERR: ^
+// CHECK:STDERR: ^~~~~~
 import C;
 
 // --- c.carbon
@@ -28,14 +28,14 @@ package C api;
 
 // CHECK:STDERR: c.carbon:[[@LINE+3]]:1: ERROR: Import cannot be used due to a cycle. Cycle must be fixed to import.
 // CHECK:STDERR: import A;
-// CHECK:STDERR: ^
+// CHECK:STDERR: ^~~~~~
 import A;
 
 // --- c.impl.carbon
 
 // CHECK:STDERR: c.impl.carbon:[[@LINE+3]]:1: ERROR: Import cannot be used due to a cycle. Cycle must be fixed to import.
 // CHECK:STDERR: package C impl;
-// CHECK:STDERR: ^
+// CHECK:STDERR: ^~~~~~~
 package C impl;
 
 // --- cycle_child.carbon
@@ -44,7 +44,7 @@ package CycleChild api;
 
 // CHECK:STDERR: cycle_child.carbon:[[@LINE+3]]:1: ERROR: Import cannot be used due to a cycle. Cycle must be fixed to import.
 // CHECK:STDERR: import B;
-// CHECK:STDERR: ^
+// CHECK:STDERR: ^~~~~~
 import B;
 
 // CHECK:STDOUT: file "a.carbon" {

+ 3 - 3
toolchain/check/testdata/packages/fail_duplicate_api.carbon

@@ -17,7 +17,7 @@ library "lib" api;
 
 // CHECK:STDERR: main_lib2.carbon:[[@LINE+3]]:1: ERROR: Library's API previously provided by `main_lib1.carbon`.
 // CHECK:STDERR: library "lib" api;
-// CHECK:STDERR: ^
+// CHECK:STDERR: ^~~~~~~
 library "lib" api;
 
 // --- package1.carbon
@@ -28,7 +28,7 @@ package Package api;
 
 // CHECK:STDERR: package2.carbon:[[@LINE+3]]:1: ERROR: Library's API previously provided by `package1.carbon`.
 // CHECK:STDERR: package Package api;
-// CHECK:STDERR: ^
+// CHECK:STDERR: ^~~~~~~
 package Package api;
 
 // --- package_lib1.carbon
@@ -39,7 +39,7 @@ package Package library "lib" api;
 
 // CHECK:STDERR: package_lib2.carbon:[[@LINE+3]]:1: ERROR: Library's API previously provided by `package_lib1.carbon`.
 // CHECK:STDERR: package Package library "lib" api;
-// CHECK:STDERR: ^
+// CHECK:STDERR: ^~~~~~~
 package Package library "lib" api;
 
 // CHECK:STDOUT: file "main1.carbon" {

+ 8 - 8
toolchain/check/testdata/packages/fail_extension.carbon

@@ -16,49 +16,49 @@
 
 // CHECK:STDERR: main_lib.incorrect:[[@LINE+3]]:1: ERROR: File extension of `.carbon` required for `api`.
 // CHECK:STDERR: library "lib" api;
-// CHECK:STDERR: ^
+// CHECK:STDERR: ^~~~~~~
 library "lib" api;
 
 // --- main_lib_impl.incorrect
 
 // CHECK:STDERR: main_lib_impl.incorrect:[[@LINE+3]]:1: ERROR: File extension of `.impl.carbon` required for `impl`.
 // CHECK:STDERR: library "lib" impl;
-// CHECK:STDERR: ^
+// CHECK:STDERR: ^~~~~~~
 library "lib" impl;
 
 // --- package.incorrect
 
 // CHECK:STDERR: package.incorrect:[[@LINE+3]]:1: ERROR: File extension of `.carbon` required for `api`.
 // CHECK:STDERR: package Package api;
-// CHECK:STDERR: ^
+// CHECK:STDERR: ^~~~~~~
 package Package api;
 
 // --- package_impl.incorrect
 
 // CHECK:STDERR: package_impl.incorrect:[[@LINE+3]]:1: ERROR: File extension of `.impl.carbon` required for `impl`.
 // CHECK:STDERR: package Package impl;
-// CHECK:STDERR: ^
+// CHECK:STDERR: ^~~~~~~
 package Package impl;
 
 // --- package_lib.incorrect
 
 // CHECK:STDERR: package_lib.incorrect:[[@LINE+3]]:1: ERROR: File extension of `.carbon` required for `api`.
 // CHECK:STDERR: package Package library "lib" api;
-// CHECK:STDERR: ^
+// CHECK:STDERR: ^~~~~~~
 package Package library "lib" api;
 
 // --- package_lib_impl.incorrect
 
 // CHECK:STDERR: package_lib_impl.incorrect:[[@LINE+3]]:1: ERROR: File extension of `.impl.carbon` required for `impl`.
 // CHECK:STDERR: package Package library "lib" impl;
-// CHECK:STDERR: ^
+// CHECK:STDERR: ^~~~~~~
 package Package library "lib" impl;
 
 // --- swapped_ext.impl.carbon
 
 // CHECK:STDERR: swapped_ext.impl.carbon:[[@LINE+4]]:1: ERROR: File extension of `.carbon` required for `api`.
 // CHECK:STDERR: package SwappedExt api;
-// CHECK:STDERR: ^
+// CHECK:STDERR: ^~~~~~~
 // CHECK:STDERR: swapped_ext.impl.carbon: File extension of `.impl.carbon` only allowed for `impl`.
 package SwappedExt api;
 
@@ -66,7 +66,7 @@ package SwappedExt api;
 
 // CHECK:STDERR: swapped_ext.carbon:[[@LINE+3]]:1: ERROR: File extension of `.impl.carbon` required for `impl`.
 // CHECK:STDERR: package SwappedExt impl;
-// CHECK:STDERR: ^
+// CHECK:STDERR: ^~~~~~~
 package SwappedExt impl;
 
 

+ 4 - 4
toolchain/check/testdata/packages/fail_import_default.carbon

@@ -10,7 +10,7 @@ package A api;
 
 // CHECK:STDERR: default_api.carbon:[[@LINE+3]]:1: ERROR: File cannot import itself.
 // CHECK:STDERR: import library default;
-// CHECK:STDERR: ^
+// CHECK:STDERR: ^~~~~~
 import library default;
 
 // --- default.impl.carbon
@@ -19,14 +19,14 @@ package A impl;
 
 // CHECK:STDERR: default.impl.carbon:[[@LINE+3]]:1: ERROR: Explicit import of `api` from `impl` file is redundant with implicit import.
 // CHECK:STDERR: import library default;
-// CHECK:STDERR: ^
+// CHECK:STDERR: ^~~~~~
 import library default;
 
 // --- main_import_default.carbon
 
 // CHECK:STDERR: main_import_default.carbon:[[@LINE+3]]:1: ERROR: Explicit import of `api` from `impl` file is redundant with implicit import.
 // CHECK:STDERR: import library default;
-// CHECK:STDERR: ^
+// CHECK:STDERR: ^~~~~~
 import library default;
 
 // --- main_lib_import_default.carbon
@@ -35,7 +35,7 @@ library "lib" api;
 
 // CHECK:STDERR: main_lib_import_default.carbon:[[@LINE+3]]:1: ERROR: Cannot import `Main//default`.
 // CHECK:STDERR: import library default;
-// CHECK:STDERR: ^
+// CHECK:STDERR: ^~~~~~
 import library default;
 
 // CHECK:STDOUT: file "default_api.carbon" {

+ 9 - 9
toolchain/check/testdata/packages/fail_import_invalid.carbon

@@ -8,12 +8,12 @@
 
 // CHECK:STDERR: main.carbon:[[@LINE+3]]:1: ERROR: Imports from the current package must omit the package name.
 // CHECK:STDERR: import Main;
-// CHECK:STDERR: ^
+// CHECK:STDERR: ^~~~~~
 import Main;
 
 // CHECK:STDERR: main.carbon:[[@LINE+3]]:1: ERROR: Imports from the current package must omit the package name.
 // CHECK:STDERR: import Main library "lib";
-// CHECK:STDERR: ^
+// CHECK:STDERR: ^~~~~~
 import Main library "lib";
 
 // --- not_main.carbon
@@ -22,12 +22,12 @@ package NotMain api;
 
 // CHECK:STDERR: not_main.carbon:[[@LINE+3]]:1: ERROR: Cannot import `Main` from other packages.
 // CHECK:STDERR: import Main;
-// CHECK:STDERR: ^
+// CHECK:STDERR: ^~~~~~
 import Main;
 
 // CHECK:STDERR: not_main.carbon:[[@LINE+3]]:1: ERROR: Cannot import `Main` from other packages.
 // CHECK:STDERR: import Main library "lib";
-// CHECK:STDERR: ^
+// CHECK:STDERR: ^~~~~~
 import Main library "lib";
 
 // --- this.carbon
@@ -36,7 +36,7 @@ package This api;
 
 // CHECK:STDERR: this.carbon:[[@LINE+3]]:1: ERROR: File cannot import itself.
 // CHECK:STDERR: import This;
-// CHECK:STDERR: ^
+// CHECK:STDERR: ^~~~~~
 import This;
 
 // --- this_lib.carbon
@@ -45,7 +45,7 @@ package This library "lib" api;
 
 // CHECK:STDERR: this_lib.carbon:[[@LINE+3]]:1: ERROR: File cannot import itself.
 // CHECK:STDERR: import library "lib";
-// CHECK:STDERR: ^
+// CHECK:STDERR: ^~~~~~
 import library "lib";
 
 // --- implicit_api.carbon
@@ -58,7 +58,7 @@ package Implicit impl;
 
 // CHECK:STDERR: implicit.impl.carbon:[[@LINE+3]]:1: ERROR: Explicit import of `api` from `impl` file is redundant with implicit import.
 // CHECK:STDERR: import Implicit;
-// CHECK:STDERR: ^
+// CHECK:STDERR: ^~~~~~
 import Implicit;
 
 // --- implicit_lib_api.carbon
@@ -71,7 +71,7 @@ package Implicit library "lib" impl;
 
 // CHECK:STDERR: implicit_lib.impl.carbon:[[@LINE+3]]:1: ERROR: Explicit import of `api` from `impl` file is redundant with implicit import.
 // CHECK:STDERR: import Implicit library "lib";
-// CHECK:STDERR: ^
+// CHECK:STDERR: ^~~~~~
 import Implicit library "lib";
 
 // --- not_found.carbon
@@ -79,7 +79,7 @@ package NotFound api;
 
 // CHECK:STDERR: not_found.carbon:[[@LINE+3]]:1: ERROR: Imported API not found.
 // CHECK:STDERR: import ImportNotFound;
-// CHECK:STDERR: ^
+// CHECK:STDERR: ^~~~~~
 import ImportNotFound;
 
 // CHECK:STDOUT: file "main.carbon" {

+ 8 - 8
toolchain/check/testdata/packages/fail_import_repeat.carbon

@@ -21,28 +21,28 @@ library "lib" api;
 import Api;
 // CHECK:STDERR: import.carbon:[[@LINE+6]]:1: ERROR: Library imported more than once.
 // CHECK:STDERR: import Api;
-// CHECK:STDERR: ^
+// CHECK:STDERR: ^~~~~~
 // CHECK:STDERR: import.carbon:[[@LINE-4]]:1: First import here.
 // CHECK:STDERR: import Api;
-// CHECK:STDERR: ^
+// CHECK:STDERR: ^~~~~~
 import Api;
 
 import Api library "lib";
 // CHECK:STDERR: import.carbon:[[@LINE+6]]:1: ERROR: Library imported more than once.
 // CHECK:STDERR: import Api library "lib";
-// CHECK:STDERR: ^
+// CHECK:STDERR: ^~~~~~
 // CHECK:STDERR: import.carbon:[[@LINE-4]]:1: First import here.
 // CHECK:STDERR: import Api library "lib";
-// CHECK:STDERR: ^
+// CHECK:STDERR: ^~~~~~
 import Api library "lib";
 
 import library "lib";
 // CHECK:STDERR: import.carbon:[[@LINE+6]]:1: ERROR: Library imported more than once.
 // CHECK:STDERR: import library "lib";
-// CHECK:STDERR: ^
+// CHECK:STDERR: ^~~~~~
 // CHECK:STDERR: import.carbon:[[@LINE-4]]:1: First import here.
 // CHECK:STDERR: import library "lib";
-// CHECK:STDERR: ^
+// CHECK:STDERR: ^~~~~~
 import library "lib";
 
 // --- default_import.carbon
@@ -52,10 +52,10 @@ package Api library "not_default" api;
 import library default;
 // CHECK:STDERR: default_import.carbon:[[@LINE+6]]:1: ERROR: Library imported more than once.
 // CHECK:STDERR: import library default;
-// CHECK:STDERR: ^
+// CHECK:STDERR: ^~~~~~
 // CHECK:STDERR: default_import.carbon:[[@LINE-4]]:1: First import here.
 // CHECK:STDERR: import library default;
-// CHECK:STDERR: ^
+// CHECK:STDERR: ^~~~~~
 import library default;
 
 // CHECK:STDOUT: file "api.carbon" {

+ 4 - 4
toolchain/check/testdata/packages/fail_package_main.carbon

@@ -8,14 +8,14 @@
 
 // CHECK:STDERR: main.carbon:[[@LINE+3]]:1: ERROR: `Main//default` must omit `package` directive.
 // CHECK:STDERR: package Main api;
-// CHECK:STDERR: ^
+// CHECK:STDERR: ^~~~~~~
 package Main api;
 
 // --- main_impl.carbon
 
 // CHECK:STDERR: main_impl.carbon:[[@LINE+3]]:1: ERROR: `Main//default` must omit `package` directive.
 // CHECK:STDERR: package Main impl;
-// CHECK:STDERR: ^
+// CHECK:STDERR: ^~~~~~~
 package Main impl;
 
 // --- raw_main.carbon
@@ -23,14 +23,14 @@ package Main impl;
 // `Main` isn't a keyword, so this fails the same way.
 // CHECK:STDERR: raw_main.carbon:[[@LINE+3]]:1: ERROR: `Main//default` must omit `package` directive.
 // CHECK:STDERR: package r#Main api;
-// CHECK:STDERR: ^
+// CHECK:STDERR: ^~~~~~~
 package r#Main api;
 
 // --- main_lib.carbon
 
 // CHECK:STDERR: main_lib.carbon:[[@LINE+3]]:1: ERROR: Use `library` directive in `Main` package libraries.
 // CHECK:STDERR: package Main library "lib" api;
-// CHECK:STDERR: ^
+// CHECK:STDERR: ^~~~~~~
 package Main library "lib" api;
 
 // CHECK:STDOUT: file "main.carbon" {

+ 2 - 2
toolchain/check/testdata/pointer/fail_address_of_error.carbon

@@ -7,14 +7,14 @@
 fn Test() {
   // CHECK:STDERR: fail_address_of_error.carbon:[[@LINE+3]]:4: ERROR: Name `undeclared` not found.
   // CHECK:STDERR:   &undeclared;
-  // CHECK:STDERR:    ^
+  // CHECK:STDERR:    ^~~~~~~~~~
   &undeclared;
   // CHECK:STDERR: fail_address_of_error.carbon:[[@LINE+6]]:3: ERROR: Cannot take the address of non-reference expression.
   // CHECK:STDERR:   &(&undeclared);
   // CHECK:STDERR:   ^
   // CHECK:STDERR: fail_address_of_error.carbon:[[@LINE+3]]:6: ERROR: Name `undeclared` not found.
   // CHECK:STDERR:   &(&undeclared);
-  // CHECK:STDERR:      ^
+  // CHECK:STDERR:      ^~~~~~~~~~
   &(&undeclared);
 }
 

+ 1 - 1
toolchain/check/testdata/pointer/fail_dereference_error.carbon

@@ -6,7 +6,7 @@
 
 // CHECK:STDERR: fail_dereference_error.carbon:[[@LINE+3]]:15: ERROR: Name `undeclared` not found.
 // CHECK:STDERR: let n: i32 = *undeclared;
-// CHECK:STDERR:               ^
+// CHECK:STDERR:               ^~~~~~~~~~
 let n: i32 = *undeclared;
 
 // CHECK:STDOUT: file "fail_dereference_error.carbon" {

+ 2 - 2
toolchain/check/testdata/return/fail_returned_var_no_return_type.carbon

@@ -7,10 +7,10 @@
 fn Procedure() {
   // CHECK:STDERR: fail_returned_var_no_return_type.carbon:[[@LINE+6]]:3: ERROR: Cannot declare a `returned var` in this function.
   // CHECK:STDERR:   returned var v: () = ();
-  // CHECK:STDERR:   ^
+  // CHECK:STDERR:   ^~~~~~~~
   // CHECK:STDERR: fail_returned_var_no_return_type.carbon:[[@LINE-4]]:1: There was no return type provided.
   // CHECK:STDERR: fn Procedure() {
-  // CHECK:STDERR: ^
+  // CHECK:STDERR: ^~
   returned var v: () = ();
   return;
 }

+ 2 - 2
toolchain/check/testdata/return/fail_returned_var_type.carbon

@@ -7,10 +7,10 @@
 fn Mismatch() -> i32 {
   // CHECK:STDERR: fail_returned_var_type.carbon:[[@LINE+6]]:19: ERROR: Type `f64` of `returned var` does not match return type of enclosing function.
   // CHECK:STDERR:   returned var v: f64 = 0.0;
-  // CHECK:STDERR:                   ^
+  // CHECK:STDERR:                   ^~~
   // CHECK:STDERR: fail_returned_var_type.carbon:[[@LINE-4]]:1: Return type of function is `i32`.
   // CHECK:STDERR: fn Mismatch() -> i32 {
-  // CHECK:STDERR: ^
+  // CHECK:STDERR: ^~
   returned var v: f64 = 0.0;
   return var;
 }

+ 1 - 1
toolchain/check/testdata/return/fail_value_disallowed.carbon

@@ -10,7 +10,7 @@ fn Main() {
   // CHECK:STDERR:           ^
   // CHECK:STDERR: fail_value_disallowed.carbon:[[@LINE-4]]:1: There was no return type provided.
   // CHECK:STDERR: fn Main() {
-  // CHECK:STDERR: ^
+  // CHECK:STDERR: ^~
   return 0;
 }
 

+ 1 - 1
toolchain/check/testdata/return/fail_value_missing.carbon

@@ -10,7 +10,7 @@ fn Main() -> i32 {
   // CHECK:STDERR:         ^
   // CHECK:STDERR: fail_value_missing.carbon:[[@LINE-4]]:1: Return type of function is `i32`.
   // CHECK:STDERR: fn Main() -> i32 {
-  // CHECK:STDERR: ^
+  // CHECK:STDERR: ^~
   return;
 }
 

+ 4 - 4
toolchain/check/testdata/struct/fail_duplicate_name.carbon

@@ -6,10 +6,10 @@
 
 // CHECK:STDERR: fail_duplicate_name.carbon:[[@LINE+6]]:42: ERROR: Duplicated field name `abc` in struct type literal.
 // CHECK:STDERR: fn F() -> {.d: i32, .abc: i32, .e: i32, .abc: i32, .f: i32};
-// CHECK:STDERR:                                          ^
+// CHECK:STDERR:                                          ^~~
 // CHECK:STDERR: fail_duplicate_name.carbon:[[@LINE+3]]:22: Field with the same name here.
 // CHECK:STDERR: fn F() -> {.d: i32, .abc: i32, .e: i32, .abc: i32, .f: i32};
-// CHECK:STDERR:                      ^
+// CHECK:STDERR:                      ^~~
 fn F() -> {.d: i32, .abc: i32, .e: i32, .abc: i32, .f: i32};
 
 // CHECK:STDERR: fail_duplicate_name.carbon:[[@LINE+6]]:19: ERROR: Duplicated field name `a` in struct type literal.
@@ -22,10 +22,10 @@ let v: {.a: i32, .a: i32} = {.a = 1};
 
 // CHECK:STDERR: fail_duplicate_name.carbon:[[@LINE+6]]:26: ERROR: Duplicated field name `def` in struct literal.
 // CHECK:STDERR: let w: i32 = {.def = 1, .def = 2}.def;
-// CHECK:STDERR:                          ^
+// CHECK:STDERR:                          ^~~
 // CHECK:STDERR: fail_duplicate_name.carbon:[[@LINE+3]]:16: Field with the same name here.
 // CHECK:STDERR: let w: i32 = {.def = 1, .def = 2}.def;
-// CHECK:STDERR:                ^
+// CHECK:STDERR:                ^~~
 let w: i32 = {.def = 1, .def = 2}.def;
 
 // CHECK:STDERR: fail_duplicate_name.carbon:[[@LINE+6]]:30: ERROR: Duplicated field name `a` in struct literal.

+ 1 - 1
toolchain/check/testdata/struct/fail_nested_incomplete.carbon

@@ -11,7 +11,7 @@ class Incomplete;
 // CHECK:STDERR:                       ^
 // CHECK:STDERR: fail_nested_incomplete.carbon:[[@LINE-5]]:1: Class was forward declared here.
 // CHECK:STDERR: class Incomplete;
-// CHECK:STDERR: ^
+// CHECK:STDERR: ^~~~~
 var s: {.a: Incomplete};
 
 // CHECK:STDERR: fail_nested_incomplete.carbon:[[@LINE+3]]:26: ERROR: Cannot implicitly convert from `<error>*` to `Incomplete*`.

+ 1 - 1
toolchain/check/testdata/tuples/fail_nested_incomplete.carbon

@@ -11,7 +11,7 @@ class Incomplete;
 // CHECK:STDERR:                        ^
 // CHECK:STDERR: fail_nested_incomplete.carbon:[[@LINE-5]]:1: Class was forward declared here.
 // CHECK:STDERR: class Incomplete;
-// CHECK:STDERR: ^
+// CHECK:STDERR: ^~~~~
 var t: (i32, Incomplete);
 
 // CHECK:STDERR: fail_nested_incomplete.carbon:[[@LINE+3]]:27: ERROR: Cannot implicitly convert from `<error>*` to `Incomplete*`.

+ 1 - 1
toolchain/check/testdata/var/fail_not_copyable.carbon

@@ -12,7 +12,7 @@ fn F(x: X) {
   // represent them.
   // CHECK:STDERR: fail_not_copyable.carbon:[[@LINE+3]]:19: ERROR: Cannot copy value of type `String`.
   // CHECK:STDERR:   var s: String = "hello";
-  // CHECK:STDERR:                   ^
+  // CHECK:STDERR:                   ^~~~~~~
   var s: String = "hello";
 
   // TODO: Decide on rules for when classes are copyable.

+ 4 - 4
toolchain/check/testdata/while/fail_break_continue.carbon

@@ -7,11 +7,11 @@
 fn While() {
   // CHECK:STDERR: fail_break_continue.carbon:[[@LINE+3]]:3: ERROR: `continue` can only be used in a loop.
   // CHECK:STDERR:   continue;
-  // CHECK:STDERR:   ^
+  // CHECK:STDERR:   ^~~~~~~~
   continue;
   // CHECK:STDERR: fail_break_continue.carbon:[[@LINE+3]]:3: ERROR: `break` can only be used in a loop.
   // CHECK:STDERR:   break;
-  // CHECK:STDERR:   ^
+  // CHECK:STDERR:   ^~~~~
   break;
   while (false) {
     continue;
@@ -19,11 +19,11 @@ fn While() {
   }
   // CHECK:STDERR: fail_break_continue.carbon:[[@LINE+3]]:3: ERROR: `continue` can only be used in a loop.
   // CHECK:STDERR:   continue;
-  // CHECK:STDERR:   ^
+  // CHECK:STDERR:   ^~~~~~~~
   continue;
   // CHECK:STDERR: fail_break_continue.carbon:[[@LINE+3]]:3: ERROR: `break` can only be used in a loop.
   // CHECK:STDERR:   break;
-  // CHECK:STDERR:   ^
+  // CHECK:STDERR:   ^~~~~
   break;
 }
 

+ 5 - 0
toolchain/diagnostics/BUILD

@@ -6,6 +6,11 @@ load("@rules_cc//cc:defs.bzl", "cc_library", "cc_test")
 
 package(default_visibility = ["//visibility:public"])
 
+filegroup(
+    name = "testdata",
+    data = glob(["testdata/**/*.carbon"]),
+)
+
 cc_library(
     name = "diagnostic_emitter",
     hdrs = ["diagnostic_emitter.h"],

+ 18 - 2
toolchain/diagnostics/diagnostic_emitter.h

@@ -5,6 +5,8 @@
 #ifndef CARBON_TOOLCHAIN_DIAGNOSTICS_DIAGNOSTIC_EMITTER_H_
 #define CARBON_TOOLCHAIN_DIAGNOSTICS_DIAGNOSTIC_EMITTER_H_
 
+#include <algorithm>
+#include <cstdint>
 #include <functional>
 #include <string>
 #include <type_traits>
@@ -58,6 +60,8 @@ struct DiagnosticLocation {
   int32_t line_number = -1;
   // 1-based column number.
   int32_t column_number = -1;
+  // A location can represent a range of text if set to >1 value.
+  int32_t length = 1;
 };
 
 // A message composing a diagnostic. This may be the main message, but can also
@@ -345,7 +349,7 @@ class StreamDiagnosticConsumer : public DiagnosticConsumer {
       : stream_(&stream) {}
 
   auto HandleDiagnostic(Diagnostic diagnostic) -> void override {
-    std::string prefix = "";
+    std::string prefix;
     if (diagnostic.level == DiagnosticLevel::Error) {
       prefix = "ERROR: ";
     }
@@ -367,7 +371,19 @@ class StreamDiagnosticConsumer : public DiagnosticConsumer {
     if (message.location.column_number > 0) {
       *stream_ << message.location.line << "\n";
       stream_->indent(message.location.column_number - 1);
-      *stream_ << "^\n";
+      *stream_ << "^";
+      int underline_length = std::max(0, message.location.length - 1);
+      // We want to ensure that we don't underline past the end of the line in
+      // case of a multiline token.
+      // TODO: revisit this once we can reference multiple ranges on multiple
+      // lines in a single diagnostic message.
+      underline_length = std::min(
+          underline_length, static_cast<int32_t>(message.location.line.size()) -
+                                message.location.column_number);
+      for (int i = 0; i < underline_length; ++i) {
+        *stream_ << "~";
+      }
+      *stream_ << "\n";
     }
   }
 

+ 14 - 0
toolchain/diagnostics/testdata/fail_multiline_token.carbon

@@ -0,0 +1,14 @@
+// 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
+//
+// ARGS: compile %s
+//
+// AUTOUPDATE
+
+// CHECK:STDERR: fail_multiline_token.carbon:[[@LINE+3]]:1: ERROR: Unrecognized declaration introducer.
+// CHECK:STDERR: '''
+// CHECK:STDERR: ^~~
+'''
+hello
+'''

+ 3 - 3
toolchain/driver/testdata/fail_flush_errors.carbon

@@ -11,7 +11,7 @@ fn F() {
   // of the string table.
   // CHECK:STDERR: fail_flush_errors.carbon:[[@LINE+3]]:3: ERROR: Name `undeclared1` not found.
   // CHECK:STDERR:   undeclared1;
-  // CHECK:STDERR:   ^
+  // CHECK:STDERR:   ^~~~~~~~~~~
   undeclared1;
 
   // Add the name into the string table from the tokenized buffer's string
@@ -20,13 +20,13 @@ fn F() {
   "undec\x6Cared2";
   // CHECK:STDERR: fail_flush_errors.carbon:[[@LINE+3]]:3: ERROR: Name `undeclared2` not found.
   // CHECK:STDERR:   undeclared2;
-  // CHECK:STDERR:   ^
+  // CHECK:STDERR:   ^~~~~~~~~~~
   undeclared2;
 
   // Add the name into the string table via a declaration rather than an expression.
   if (true) { var undeclared3: i32 = 0; }
   // CHECK:STDERR: fail_flush_errors.carbon:[[@LINE+3]]:3: ERROR: Name `undeclared3` not found.
   // CHECK:STDERR:   undeclared3;
-  // CHECK:STDERR:   ^
+  // CHECK:STDERR:   ^~~~~~~~~~~
   undeclared3;
 }

+ 6 - 2
toolchain/lex/tokenized_buffer.cpp

@@ -12,6 +12,7 @@
 #include "llvm/Support/Format.h"
 #include "llvm/Support/FormatVariadic.h"
 #include "toolchain/base/value_store.h"
+#include "toolchain/diagnostics/diagnostic_emitter.h"
 #include "toolchain/lex/character_set.h"
 #include "toolchain/lex/numeric_literal.h"
 #include "toolchain/lex/string_literal.h"
@@ -377,8 +378,11 @@ auto TokenLocationTranslator::GetLocation(Token token) -> DiagnosticLocation {
   // Find the corresponding file location.
   // TODO: Should we somehow indicate in the diagnostic location if this token
   // is a recovery token that doesn't correspond to the original source?
-  return TokenizedBuffer::SourceBufferLocationTranslator(buffer_).GetLocation(
-      token_start);
+  DiagnosticLocation loc =
+      TokenizedBuffer::SourceBufferLocationTranslator(buffer_).GetLocation(
+          token_start);
+  loc.length = buffer_->GetTokenText(token).size();
+  return loc;
 }
 
 }  // namespace Carbon::Lex

+ 2 - 2
toolchain/parse/testdata/basics/fail_invalid_designators.carbon

@@ -12,11 +12,11 @@ fn F() {
   a.;
   // CHECK:STDERR: fail_invalid_designators.carbon:[[@LINE+3]]:5: ERROR: Expected identifier after `.`.
   // CHECK:STDERR:   a.fn;
-  // CHECK:STDERR:     ^
+  // CHECK:STDERR:     ^~
   a.fn;
   // CHECK:STDERR: fail_invalid_designators.carbon:[[@LINE+3]]:5: ERROR: Expected identifier after `.`.
   // CHECK:STDERR:   a.42;
-  // CHECK:STDERR:     ^
+  // CHECK:STDERR:     ^~
   a.42;
 }
 

+ 1 - 1
toolchain/parse/testdata/basics/fail_no_intro_with_semi.carbon

@@ -6,7 +6,7 @@
 
 // CHECK:STDERR: fail_no_intro_with_semi.carbon:[[@LINE+3]]:1: ERROR: Unrecognized declaration introducer.
 // CHECK:STDERR: foo;
-// CHECK:STDERR: ^
+// CHECK:STDERR: ^~~
 foo;
 
 // CHECK:STDOUT: - filename: fail_no_intro_with_semi.carbon

+ 1 - 1
toolchain/parse/testdata/basics/fail_no_intro_without_semi.carbon

@@ -6,7 +6,7 @@
 
 // CHECK:STDERR: fail_no_intro_without_semi.carbon:[[@LINE+3]]:1: ERROR: Unrecognized declaration introducer.
 // CHECK:STDERR: foo bar baz
-// CHECK:STDERR: ^
+// CHECK:STDERR: ^~~
 foo bar baz
 
 // CHECK:STDOUT: - filename: fail_no_intro_without_semi.carbon

+ 3 - 3
toolchain/parse/testdata/class/fail_introducer.carbon

@@ -8,17 +8,17 @@
 // used on an `interface`.
 // CHECK:STDERR: fail_introducer.carbon:[[@LINE+3]]:1: ERROR: Unrecognized declaration introducer.
 // CHECK:STDERR: abstract interface I;
-// CHECK:STDERR: ^
+// CHECK:STDERR: ^~~~~~~~
 abstract interface I;
 
 // CHECK:STDERR: fail_introducer.carbon:[[@LINE+3]]:1: ERROR: Unrecognized declaration introducer.
 // CHECK:STDERR: base fn F();
-// CHECK:STDERR: ^
+// CHECK:STDERR: ^~~~
 base fn F();
 
 // CHECK:STDERR: fail_introducer.carbon:[[@LINE+3]]:1: ERROR: Unrecognized declaration introducer.
 // CHECK:STDERR: abstract base class C;
-// CHECK:STDERR: ^
+// CHECK:STDERR: ^~~~~~~~
 abstract base class C;
 
 // CHECK:STDOUT: - filename: fail_introducer.carbon

+ 1 - 1
toolchain/parse/testdata/for/fail_returned_var.carbon

@@ -8,7 +8,7 @@ fn foo() -> i32 {
   // TODO: Should we allow this?
   // CHECK:STDERR: fail_returned_var.carbon:[[@LINE+3]]:8: ERROR: Expected `var` declaration.
   // CHECK:STDERR:   for (returned var x: i32 in y) {
-  // CHECK:STDERR:        ^
+  // CHECK:STDERR:        ^~~~~~~~
   for (returned var x: i32 in y) {
     return var;
   }

+ 1 - 1
toolchain/parse/testdata/function/declaration/fail_identifier_instead_of_sig.carbon

@@ -6,7 +6,7 @@
 
 // CHECK:STDERR: fail_identifier_instead_of_sig.carbon:[[@LINE+3]]:8: ERROR: `fn` requires a `(` for parameters.
 // CHECK:STDERR: fn foo bar;
-// CHECK:STDERR:        ^
+// CHECK:STDERR:        ^~~
 fn foo bar;
 
 // CHECK:STDOUT: - filename: fail_identifier_instead_of_sig.carbon

+ 1 - 1
toolchain/parse/testdata/function/declaration/fail_repeated_fn_and_semi.carbon

@@ -6,7 +6,7 @@
 
 // CHECK:STDERR: fail_repeated_fn_and_semi.carbon:[[@LINE+3]]:4: ERROR: `fn` introducer should be followed by a name.
 // CHECK:STDERR: fn fn;
-// CHECK:STDERR:    ^
+// CHECK:STDERR:    ^~
 fn fn;
 
 // CHECK:STDOUT: - filename: fail_repeated_fn_and_semi.carbon

+ 1 - 1
toolchain/parse/testdata/function/declaration/fail_skip_without_semi_to_curly.carbon

@@ -6,7 +6,7 @@
 
 // CHECK:STDERR: fail_skip_without_semi_to_curly.carbon:[[@LINE+3]]:1: ERROR: Unrecognized declaration introducer.
 // CHECK:STDERR: struct X { fn () }
-// CHECK:STDERR: ^
+// CHECK:STDERR: ^~~~~~
 struct X { fn () }
 fn F();
 

+ 1 - 1
toolchain/parse/testdata/generics/interface/fail_missing_open_curly.carbon

@@ -6,7 +6,7 @@
 
 // CHECK:STDERR: fail_missing_open_curly.carbon:[[@LINE+3]]:15: ERROR: `interface` declarations must either end with a `;` or have a `{ ... }` block for a definition.
 // CHECK:STDERR: interface Bar Baz {}
-// CHECK:STDERR:               ^
+// CHECK:STDERR:               ^~~
 interface Bar Baz {}
 
 interface Foo

+ 2 - 2
toolchain/parse/testdata/generics/interface/fail_self_param_syntax.carbon

@@ -7,12 +7,12 @@
 interface Foo {
   // CHECK:STDERR: fail_self_param_syntax.carbon:[[@LINE+3]]:13: ERROR: Expected parameter declaration.
   // CHECK:STDERR:   fn Sub[me Self](b: Self) -> Self;
-  // CHECK:STDERR:             ^
+  // CHECK:STDERR:             ^~~~
   fn Sub[me Self](b: Self) -> Self;
 
   // CHECK:STDERR: fail_self_param_syntax.carbon:[[@LINE+3]]:10: ERROR: Expected parameter declaration.
   // CHECK:STDERR:   fn Mul[Self](b: Self) -> Self;
-  // CHECK:STDERR:          ^
+  // CHECK:STDERR:          ^~~~
   fn Mul[Self](b: Self) -> Self;
 }
 

+ 1 - 1
toolchain/parse/testdata/if/fail_else_unbraced.carbon

@@ -8,7 +8,7 @@ fn F() {
   if (a)
     // CHECK:STDERR: fail_else_unbraced.carbon:[[@LINE+3]]:5: ERROR: Expected braced code block.
     // CHECK:STDERR:     if (b)
-    // CHECK:STDERR:     ^
+    // CHECK:STDERR:     ^~
     if (b)
       // CHECK:STDERR: fail_else_unbraced.carbon:[[@LINE+3]]:7: ERROR: Expected braced code block.
       // CHECK:STDERR:       c;

+ 2 - 2
toolchain/parse/testdata/if/fail_unbraced.carbon

@@ -9,11 +9,11 @@ fn F() {
   if (a)
     // CHECK:STDERR: fail_unbraced.carbon:[[@LINE+3]]:5: ERROR: Expected braced code block.
     // CHECK:STDERR:     if (b)
-    // CHECK:STDERR:     ^
+    // CHECK:STDERR:     ^~
     if (b)
       // CHECK:STDERR: fail_unbraced.carbon:[[@LINE+3]]:7: ERROR: Expected braced code block.
       // CHECK:STDERR:       if (c)
-      // CHECK:STDERR:       ^
+      // CHECK:STDERR:       ^~
       if (c)
         // CHECK:STDERR: fail_unbraced.carbon:[[@LINE+3]]:9: ERROR: Expected braced code block.
         // CHECK:STDERR:         d;

+ 3 - 3
toolchain/parse/testdata/if_expression/fail_top_level_if.carbon

@@ -7,13 +7,13 @@
 fn F() {
   // CHECK:STDERR: fail_top_level_if.carbon:[[@LINE+9]]:6: ERROR: Expected `(` after `if`.
   // CHECK:STDERR:   if true then 1 else 2;
-  // CHECK:STDERR:      ^
+  // CHECK:STDERR:      ^~~~
   // CHECK:STDERR: fail_top_level_if.carbon:[[@LINE+6]]:11: ERROR: Expected braced code block.
   // CHECK:STDERR:   if true then 1 else 2;
-  // CHECK:STDERR:           ^
+  // CHECK:STDERR:           ^~~~
   // CHECK:STDERR: fail_top_level_if.carbon:[[@LINE+3]]:11: ERROR: Expected expression.
   // CHECK:STDERR:   if true then 1 else 2;
-  // CHECK:STDERR:           ^
+  // CHECK:STDERR:           ^~~~
   if true then 1 else 2;
 }
 

+ 1 - 1
toolchain/parse/testdata/namespace/fail_arrow.carbon

@@ -8,7 +8,7 @@ namespace Foo;
 
 // CHECK:STDERR: fail_arrow.carbon:[[@LINE+3]]:7: ERROR: `fn` requires a `(` for parameters.
 // CHECK:STDERR: fn Foo->Bar() {}
-// CHECK:STDERR:       ^
+// CHECK:STDERR:       ^~
 fn Foo->Bar() {}
 
 // CHECK:STDOUT: - filename: fail_arrow.carbon

+ 5 - 5
toolchain/parse/testdata/namespace/fail_incomplete.carbon

@@ -6,12 +6,12 @@
 
 // CHECK:STDERR: fail_incomplete.carbon:[[@LINE+3]]:11: ERROR: `namespace` introducer should be followed by a name.
 // CHECK:STDERR: namespace 123
-// CHECK:STDERR:           ^
+// CHECK:STDERR:           ^~~
 namespace 123
 
 // CHECK:STDERR: fail_incomplete.carbon:[[@LINE+3]]:11: ERROR: `namespace` introducer should be followed by a name.
 // CHECK:STDERR: namespace ""
-// CHECK:STDERR:           ^
+// CHECK:STDERR:           ^~
 namespace ""
 
 // CHECK:STDERR: fail_incomplete.carbon:[[@LINE+3]]:11: ERROR: `namespace` introducer should be followed by a name.
@@ -21,17 +21,17 @@ namespace +
 
 // CHECK:STDERR: fail_incomplete.carbon:[[@LINE+3]]:11: ERROR: `namespace` introducer should be followed by a name.
 // CHECK:STDERR: namespace bool
-// CHECK:STDERR:           ^
+// CHECK:STDERR:           ^~~~
 namespace bool
 
 // CHECK:STDERR: fail_incomplete.carbon:[[@LINE+3]]:11: ERROR: `namespace` introducer should be followed by a name.
 // CHECK:STDERR: namespace namespace namespace namespace namespace
-// CHECK:STDERR:           ^
+// CHECK:STDERR:           ^~~~~~~~~
 namespace namespace namespace namespace namespace
 
 // CHECK:STDERR: fail_incomplete.carbon:[[@LINE+3]]:1: ERROR: `namespace` introducer should be followed by a name.
 // CHECK:STDERR: namespace
-// CHECK:STDERR: ^
+// CHECK:STDERR: ^~~~~~~~~
 namespace
 
 // CHECK:STDOUT: - filename: fail_incomplete.carbon

+ 2 - 2
toolchain/parse/testdata/operators/fail_invalid_infix.carbon

@@ -10,11 +10,11 @@
 var a: i32 = n == ;
 // CHECK:STDERR: fail_invalid_infix.carbon:[[@LINE+3]]:14: ERROR: Expected expression.
 // CHECK:STDERR: var b: i32 = == n;
-// CHECK:STDERR:              ^
+// CHECK:STDERR:              ^~
 var b: i32 = == n;
 // CHECK:STDERR: fail_invalid_infix.carbon:[[@LINE+6]]:14: ERROR: Expected expression.
 // CHECK:STDERR: var c: i32 = == ;
-// CHECK:STDERR:              ^
+// CHECK:STDERR:              ^~
 // CHECK:STDERR: fail_invalid_infix.carbon:[[@LINE+3]]:17: ERROR: Expected expression.
 // CHECK:STDERR: var c: i32 = == ;
 // CHECK:STDERR:                 ^

+ 2 - 2
toolchain/parse/testdata/operators/fail_postincrement.carbon

@@ -9,11 +9,11 @@ fn F() {
   // TODO: It'd be nice to produce a custom diagnostic here.
   // CHECK:STDERR: fail_postincrement.carbon:[[@LINE+3]]:4: ERROR: Expected `;` after expression statement.
   // CHECK:STDERR:   n++;
-  // CHECK:STDERR:    ^
+  // CHECK:STDERR:    ^~
   n++;
   // CHECK:STDERR: fail_postincrement.carbon:[[@LINE+3]]:4: ERROR: Expected `;` after expression statement.
   // CHECK:STDERR:   n--;
-  // CHECK:STDERR:    ^
+  // CHECK:STDERR:    ^~
   n--;
 }
 

+ 1 - 1
toolchain/parse/testdata/operators/fail_precedence_and_or.carbon

@@ -7,7 +7,7 @@
 fn F() {
   // CHECK:STDERR: fail_precedence_and_or.carbon:[[@LINE+3]]:11: ERROR: Parentheses are required to disambiguate operator precedence.
   // CHECK:STDERR:   a and b or c;
-  // CHECK:STDERR:           ^
+  // CHECK:STDERR:           ^~
   a and b or c;
 }
 

+ 3 - 3
toolchain/parse/testdata/operators/fail_precedence_as.carbon

@@ -8,17 +8,17 @@ fn F(n: i32) {
   // No ordering between `not` and `as`.
   // CHECK:STDERR: fail_precedence_as.carbon:[[@LINE+3]]:12: ERROR: Parentheses are required to disambiguate operator precedence.
   // CHECK:STDERR:   not true as bool;
-  // CHECK:STDERR:            ^
+  // CHECK:STDERR:            ^~
   not true as bool;
 
   // No ordering between most binary operators and `as`.
   // CHECK:STDERR: fail_precedence_as.carbon:[[@LINE+3]]:9: ERROR: Parentheses are required to disambiguate operator precedence.
   // CHECK:STDERR:   1 + 1 as i32;
-  // CHECK:STDERR:         ^
+  // CHECK:STDERR:         ^~
   1 + 1 as i32;
   // CHECK:STDERR: fail_precedence_as.carbon:[[@LINE+3]]:9: ERROR: Parentheses are required to disambiguate operator precedence.
   // CHECK:STDERR:   5 % 2 as i32;
-  // CHECK:STDERR:         ^
+  // CHECK:STDERR:         ^~
   5 % 2 as i32;
 }
 

+ 4 - 4
toolchain/parse/testdata/operators/fail_precedence_assign.carbon

@@ -14,18 +14,18 @@ fn F() {
   1 + (a = 1);
   // CHECK:STDERR: fail_precedence_assign.carbon:[[@LINE+6]]:19: ERROR: Expected `else` after `if ... then ...`.
   // CHECK:STDERR:   (if true then a += 1 else a /= 2);
-  // CHECK:STDERR:                   ^
+  // CHECK:STDERR:                   ^~
   // CHECK:STDERR: fail_precedence_assign.carbon:[[@LINE+3]]:19: ERROR: Expected `,` or `)`.
   // CHECK:STDERR:   (if true then a += 1 else a /= 2);
-  // CHECK:STDERR:                   ^
+  // CHECK:STDERR:                   ^~
   (if true then a += 1 else a /= 2);
   // CHECK:STDERR: fail_precedence_assign.carbon:[[@LINE+3]]:7: ERROR: Operator `++` can only be used as a complete statement.
   // CHECK:STDERR:   a + ++a;
-  // CHECK:STDERR:       ^
+  // CHECK:STDERR:       ^~
   a + ++a;
   // CHECK:STDERR: fail_precedence_assign.carbon:[[@LINE+3]]:5: ERROR: Parentheses are required around this unary `if` operator.
   // CHECK:STDERR:   ++if c then a else b;
-  // CHECK:STDERR:     ^
+  // CHECK:STDERR:     ^~
   ++if c then a else b;
 }
 

+ 1 - 1
toolchain/parse/testdata/operators/fail_precedence_or_and.carbon

@@ -7,7 +7,7 @@
 fn F() {
   // CHECK:STDERR: fail_precedence_or_and.carbon:[[@LINE+3]]:10: ERROR: Parentheses are required to disambiguate operator precedence.
   // CHECK:STDERR:   a or b and c;
-  // CHECK:STDERR:          ^
+  // CHECK:STDERR:          ^~~
   a or b and c;
 }
 

+ 2 - 2
toolchain/parse/testdata/operators/fail_variety.carbon

@@ -10,7 +10,7 @@ fn F() {
   // CHECK:STDERR:                     ^
   // CHECK:STDERR: fail_variety.carbon:[[@LINE+12]]:29: ERROR: Parentheses are required to disambiguate operator precedence.
   // CHECK:STDERR:   n = a * b + c * d = d * d << e & f - not g;
-  // CHECK:STDERR:                             ^
+  // CHECK:STDERR:                             ^~
   // CHECK:STDERR: fail_variety.carbon:[[@LINE+9]]:34: ERROR: Parentheses are required to disambiguate operator precedence.
   // CHECK:STDERR:   n = a * b + c * d = d * d << e & f - not g;
   // CHECK:STDERR:                                  ^
@@ -19,7 +19,7 @@ fn F() {
   // CHECK:STDERR:                                      ^
   // CHECK:STDERR: fail_variety.carbon:[[@LINE+3]]:40: ERROR: Parentheses are required around this unary `not` operator.
   // CHECK:STDERR:   n = a * b + c * d = d * d << e & f - not g;
-  // CHECK:STDERR:                                        ^
+  // CHECK:STDERR:                                        ^~~
   n = a * b + c * d = d * d << e & f - not g;
 }
 

+ 1 - 1
toolchain/parse/testdata/operators/recover_prefix_repeat.carbon

@@ -6,7 +6,7 @@
 
 // CHECK:STDERR: recover_prefix_repeat.carbon:[[@LINE+3]]:17: ERROR: Parentheses are required around this unary `const` operator.
 // CHECK:STDERR: fn F() -> const const i32* {
-// CHECK:STDERR:                 ^
+// CHECK:STDERR:                 ^~~~~
 fn F() -> const const i32* {
 }
 

+ 2 - 2
toolchain/parse/testdata/packages/import/fail_after_decl.carbon

@@ -8,10 +8,10 @@ fn A();
 
 // CHECK:STDERR: fail_after_decl.carbon:[[@LINE+6]]:1: ERROR: `import` directives must come after the `package` directive (if present) and before any other entities in the file.
 // CHECK:STDERR: import B;
-// CHECK:STDERR: ^
+// CHECK:STDERR: ^~~~~~
 // CHECK:STDERR: fail_after_decl.carbon:[[@LINE-5]]:1: First declaration is here.
 // CHECK:STDERR: fn A();
-// CHECK:STDERR: ^
+// CHECK:STDERR: ^~
 import B;
 
 // CHECK:STDOUT: - filename: fail_after_decl.carbon

+ 6 - 6
toolchain/parse/testdata/packages/import/fail_after_decl_repeated.carbon

@@ -8,30 +8,30 @@ fn A();
 
 // CHECK:STDERR: fail_after_decl_repeated.carbon:[[@LINE+6]]:1: ERROR: `import` directives must come after the `package` directive (if present) and before any other entities in the file.
 // CHECK:STDERR: import B;
-// CHECK:STDERR: ^
+// CHECK:STDERR: ^~~~~~
 // CHECK:STDERR: fail_after_decl_repeated.carbon:[[@LINE-5]]:1: First declaration is here.
 // CHECK:STDERR: fn A();
-// CHECK:STDERR: ^
+// CHECK:STDERR: ^~
 import B;
 // Note this is still invalid, but doesn't warn because it's sequential.
 import C;
 
 // CHECK:STDERR: fail_after_decl_repeated.carbon:[[@LINE+6]]:1: ERROR: The `package` directive must be the first non-comment line.
 // CHECK:STDERR: package D;
-// CHECK:STDERR: ^
+// CHECK:STDERR: ^~~~~~~
 // CHECK:STDERR: fail_after_decl_repeated.carbon:[[@LINE-15]]:1: First non-comment line is here.
 // CHECK:STDERR: fn A();
-// CHECK:STDERR: ^
+// CHECK:STDERR: ^~
 package D;
 
 fn E();
 
 // CHECK:STDERR: fail_after_decl_repeated.carbon:[[@LINE+6]]:1: ERROR: `import` directives must come after the `package` directive (if present) and before any other entities in the file.
 // CHECK:STDERR: import F;
-// CHECK:STDERR: ^
+// CHECK:STDERR: ^~~~~~
 // CHECK:STDERR: fail_after_decl_repeated.carbon:[[@LINE-25]]:1: First declaration is here.
 // CHECK:STDERR: fn A();
-// CHECK:STDERR: ^
+// CHECK:STDERR: ^~
 import F;
 // Note this is still invalid, but doesn't warn because it's sequential.
 import G;

+ 1 - 1
toolchain/parse/testdata/packages/import/fail_extra_string.carbon

@@ -6,7 +6,7 @@
 
 // CHECK:STDERR: fail_extra_string.carbon:[[@LINE+3]]:26: ERROR: `import` declarations must end with a `;`.
 // CHECK:STDERR: import Foo library "bar" "baz";
-// CHECK:STDERR:                          ^
+// CHECK:STDERR:                          ^~~~~
 import Foo library "bar" "baz";
 
 // CHECK:STDOUT: - filename: fail_extra_string.carbon

+ 1 - 1
toolchain/parse/testdata/packages/import/fail_library_is_identifier.carbon

@@ -6,7 +6,7 @@
 
 // CHECK:STDERR: fail_library_is_identifier.carbon:[[@LINE+3]]:25: ERROR: Expected a string literal to specify the library name.
 // CHECK:STDERR: import Geometry library Shapes;
-// CHECK:STDERR:                         ^
+// CHECK:STDERR:                         ^~~~~~
 import Geometry library Shapes;
 
 // CHECK:STDOUT: - filename: fail_library_is_identifier.carbon

+ 1 - 1
toolchain/parse/testdata/packages/import/fail_name_is_keyword.carbon

@@ -6,7 +6,7 @@
 
 // CHECK:STDERR: fail_name_is_keyword.carbon:[[@LINE+3]]:8: ERROR: Expected identifier or `library` after `import`.
 // CHECK:STDERR: import fn;
-// CHECK:STDERR:        ^
+// CHECK:STDERR:        ^~
 import fn;
 
 // CHECK:STDOUT: - filename: fail_name_is_keyword.carbon

+ 1 - 1
toolchain/parse/testdata/packages/import/fail_omit_library_keyword.carbon

@@ -6,7 +6,7 @@
 
 // CHECK:STDERR: fail_omit_library_keyword.carbon:[[@LINE+3]]:17: ERROR: Missing `library` keyword.
 // CHECK:STDERR: import Geometry "Shapes";
-// CHECK:STDERR:                 ^
+// CHECK:STDERR:                 ^~~~~~~~
 import Geometry "Shapes";
 
 // CHECK:STDOUT: - filename: fail_omit_library_keyword.carbon

+ 1 - 1
toolchain/parse/testdata/packages/import/fail_type.carbon

@@ -6,7 +6,7 @@
 
 // CHECK:STDERR: fail_type.carbon:[[@LINE+3]]:17: ERROR: `import` declarations must end with a `;`.
 // CHECK:STDERR: import Geometry api;
-// CHECK:STDERR:                 ^
+// CHECK:STDERR:                 ^~~
 import Geometry api;
 
 // CHECK:STDOUT: - filename: fail_type.carbon

+ 3 - 3
toolchain/parse/testdata/packages/library/fail_invalid_name.carbon

@@ -8,14 +8,14 @@
 
 // CHECK:STDERR: identifier.carbon:[[@LINE+3]]:9: ERROR: Expected `default` or a string literal to specify the library name.
 // CHECK:STDERR: library Shapes api;
-// CHECK:STDERR:         ^
+// CHECK:STDERR:         ^~~~~~
 library Shapes api;
 
 // --- raw_identifier.carbon
 
 // CHECK:STDERR: raw_identifier.carbon:[[@LINE+3]]:9: ERROR: Expected `default` or a string literal to specify the library name.
 // CHECK:STDERR: library r#default api;
-// CHECK:STDERR:         ^
+// CHECK:STDERR:         ^~~~~~~
 library r#default api;
 
 // --- missing.carbon
@@ -29,7 +29,7 @@ library;
 
 // CHECK:STDERR: missing_with_api.carbon:[[@LINE+3]]:9: ERROR: Expected `default` or a string literal to specify the library name.
 // CHECK:STDERR: library api;
-// CHECK:STDERR:         ^
+// CHECK:STDERR:         ^~~
 library api;
 
 // --- no_semi.carbon

+ 2 - 2
toolchain/parse/testdata/packages/library/fail_too_late.carbon

@@ -8,10 +8,10 @@ import Geometry;
 
 // CHECK:STDERR: fail_too_late.carbon:[[@LINE+6]]:1: ERROR: The `library` directive must be the first non-comment line.
 // CHECK:STDERR: library "Shapes" api;
-// CHECK:STDERR: ^
+// CHECK:STDERR: ^~~~~~~
 // CHECK:STDERR: fail_too_late.carbon:[[@LINE-5]]:1: First non-comment line is here.
 // CHECK:STDERR: import Geometry;
-// CHECK:STDERR: ^
+// CHECK:STDERR: ^~~~~~
 library "Shapes" api;
 
 // CHECK:STDOUT: - filename: fail_too_late.carbon

+ 2 - 2
toolchain/parse/testdata/packages/package/fail_after_decl.carbon

@@ -8,10 +8,10 @@ fn A();
 
 // CHECK:STDERR: fail_after_decl.carbon:[[@LINE+6]]:1: ERROR: The `package` directive must be the first non-comment line.
 // CHECK:STDERR: package B api;
-// CHECK:STDERR: ^
+// CHECK:STDERR: ^~~~~~~
 // CHECK:STDERR: fail_after_decl.carbon:[[@LINE-5]]:1: First non-comment line is here.
 // CHECK:STDERR: fn A();
-// CHECK:STDERR: ^
+// CHECK:STDERR: ^~
 package B api;
 
 // CHECK:STDOUT: - filename: fail_after_decl.carbon

+ 2 - 2
toolchain/parse/testdata/packages/package/fail_after_import.carbon

@@ -8,10 +8,10 @@ import A;
 
 // CHECK:STDERR: fail_after_import.carbon:[[@LINE+6]]:1: ERROR: The `package` directive must be the first non-comment line.
 // CHECK:STDERR: package B api;
-// CHECK:STDERR: ^
+// CHECK:STDERR: ^~~~~~~
 // CHECK:STDERR: fail_after_import.carbon:[[@LINE-5]]:1: First non-comment line is here.
 // CHECK:STDERR: import A;
-// CHECK:STDERR: ^
+// CHECK:STDERR: ^~~~~~
 package B api;
 
 // CHECK:STDOUT: - filename: fail_after_import.carbon

+ 2 - 2
toolchain/parse/testdata/packages/package/fail_after_package.carbon

@@ -7,10 +7,10 @@
 package A api;
 // CHECK:STDERR: fail_after_package.carbon:[[@LINE+6]]:1: ERROR: The `package` directive must be the first non-comment line.
 // CHECK:STDERR: package B api;
-// CHECK:STDERR: ^
+// CHECK:STDERR: ^~~~~~~
 // CHECK:STDERR: fail_after_package.carbon:[[@LINE-4]]:1: First non-comment line is here.
 // CHECK:STDERR: package A api;
-// CHECK:STDERR: ^
+// CHECK:STDERR: ^~~~~~~
 package B api;
 
 // CHECK:STDOUT: - filename: fail_after_package.carbon

+ 1 - 1
toolchain/parse/testdata/packages/package/fail_extra_string.carbon

@@ -6,7 +6,7 @@
 
 // CHECK:STDERR: fail_extra_string.carbon:[[@LINE+3]]:27: ERROR: Expected `api` or `impl`.
 // CHECK:STDERR: package Foo library "bar" "baz";
-// CHECK:STDERR:                           ^
+// CHECK:STDERR:                           ^~~~~
 package Foo library "bar" "baz";
 
 // CHECK:STDOUT: - filename: fail_extra_string.carbon

+ 1 - 1
toolchain/parse/testdata/packages/package/fail_library_is_identifier.carbon

@@ -6,7 +6,7 @@
 
 // CHECK:STDERR: fail_library_is_identifier.carbon:[[@LINE+3]]:26: ERROR: Expected a string literal to specify the library name.
 // CHECK:STDERR: package Geometry library Shapes api;
-// CHECK:STDERR:                          ^
+// CHECK:STDERR:                          ^~~~~~
 package Geometry library Shapes api;
 
 // CHECK:STDOUT: - filename: fail_library_is_identifier.carbon

+ 1 - 1
toolchain/parse/testdata/packages/package/fail_library_skips_name.carbon

@@ -6,7 +6,7 @@
 
 // CHECK:STDERR: fail_library_skips_name.carbon:[[@LINE+3]]:9: ERROR: Expected identifier after `package`.
 // CHECK:STDERR: package library "Shapes" api;
-// CHECK:STDERR:         ^
+// CHECK:STDERR:         ^~~~~~~
 package library "Shapes" api;
 
 // CHECK:STDOUT: - filename: fail_library_skips_name.carbon

+ 1 - 1
toolchain/parse/testdata/packages/package/fail_name_is_keyword.carbon

@@ -6,7 +6,7 @@
 
 // CHECK:STDERR: fail_name_is_keyword.carbon:[[@LINE+3]]:9: ERROR: Expected identifier after `package`.
 // CHECK:STDERR: package fn;
-// CHECK:STDERR:         ^
+// CHECK:STDERR:         ^~
 package fn;
 
 // CHECK:STDOUT: - filename: fail_name_is_keyword.carbon

+ 1 - 1
toolchain/parse/testdata/packages/package/fail_omit_library_keyword.carbon

@@ -6,7 +6,7 @@
 
 // CHECK:STDERR: fail_omit_library_keyword.carbon:[[@LINE+3]]:18: ERROR: Missing `library` keyword.
 // CHECK:STDERR: package Geometry "Shapes" api;
-// CHECK:STDERR:                  ^
+// CHECK:STDERR:                  ^~~~~~~~
 package Geometry "Shapes" api;
 
 // CHECK:STDOUT: - filename: fail_omit_library_keyword.carbon

+ 1 - 1
toolchain/parse/testdata/return/fail_returned_no_var.carbon

@@ -7,7 +7,7 @@
 fn F() -> String {
   // CHECK:STDERR: fail_returned_no_var.carbon:[[@LINE+3]]:12: ERROR: Expected `var` after `returned`.
   // CHECK:STDERR:   returned fn G() -> i32;
-  // CHECK:STDERR:            ^
+  // CHECK:STDERR:            ^~
   returned fn G() -> i32;
 }
 

+ 1 - 1
toolchain/parse/testdata/struct/fail_dot_string_colon.carbon

@@ -6,7 +6,7 @@
 
 // CHECK:STDERR: fail_dot_string_colon.carbon:[[@LINE+3]]:10: ERROR: Expected identifier after `.`.
 // CHECK:STDERR: var x: {."hello": i32, .y: i32} = {};
-// CHECK:STDERR:          ^
+// CHECK:STDERR:          ^~~~~~~
 var x: {."hello": i32, .y: i32} = {};
 
 // CHECK:STDOUT: - filename: fail_dot_string_colon.carbon

+ 1 - 1
toolchain/parse/testdata/struct/fail_dot_string_equals.carbon

@@ -6,7 +6,7 @@
 
 // CHECK:STDERR: fail_dot_string_equals.carbon:[[@LINE+3]]:10: ERROR: Expected identifier after `.`.
 // CHECK:STDERR: var x: {."hello" = 0, .y = 4} = {};
-// CHECK:STDERR:          ^
+// CHECK:STDERR:          ^~~~~~~
 var x: {."hello" = 0, .y = 4} = {};
 
 // CHECK:STDOUT: - filename: fail_dot_string_equals.carbon

+ 1 - 1
toolchain/parse/testdata/struct/fail_extra_token_in_type.carbon

@@ -6,7 +6,7 @@
 
 // CHECK:STDERR: fail_extra_token_in_type.carbon:[[@LINE+3]]:17: ERROR: Expected `,` or `}`.
 // CHECK:STDERR: var x: {.a: i32 banana} = {.a = 0};
-// CHECK:STDERR:                 ^
+// CHECK:STDERR:                 ^~~~~~
 var x: {.a: i32 banana} = {.a = 0};
 
 // CHECK:STDOUT: - filename: fail_extra_token_in_type.carbon

+ 1 - 1
toolchain/parse/testdata/struct/fail_extra_token_in_value.carbon

@@ -6,7 +6,7 @@
 
 // CHECK:STDERR: fail_extra_token_in_value.carbon:[[@LINE+3]]:28: ERROR: Expected `,` or `}`.
 // CHECK:STDERR: var x: {.a: i32} = {.a = 0 banana};
-// CHECK:STDERR:                            ^
+// CHECK:STDERR:                            ^~~~~~
 var x: {.a: i32} = {.a = 0 banana};
 
 // CHECK:STDOUT: - filename: fail_extra_token_in_value.carbon

+ 1 - 1
toolchain/parse/testdata/struct/fail_type_no_designator.carbon

@@ -6,7 +6,7 @@
 
 // CHECK:STDERR: fail_type_no_designator.carbon:[[@LINE+3]]:9: ERROR: Expected `.field: field_type` or `.field = value`.
 // CHECK:STDERR: var x: {i32} = {};
-// CHECK:STDERR:         ^
+// CHECK:STDERR:         ^~~
 var x: {i32} = {};
 
 // CHECK:STDOUT: - filename: fail_type_no_designator.carbon

+ 1 - 1
toolchain/parse/testdata/while/fail_unbraced.carbon

@@ -9,7 +9,7 @@ fn F() {
   while (a)
     // CHECK:STDERR: fail_unbraced.carbon:[[@LINE+3]]:5: ERROR: Expected braced code block.
     // CHECK:STDERR:     break;
-    // CHECK:STDERR:     ^
+    // CHECK:STDERR:     ^~~~~
     break;
 }
 

+ 1 - 0
toolchain/testing/BUILD

@@ -14,6 +14,7 @@ file_test(
     tests = [
         "//toolchain/check:testdata",
         "//toolchain/codegen:testdata",
+        "//toolchain/diagnostics:testdata",
         "//toolchain/driver:testdata",
         "//toolchain/lex:testdata",
         "//toolchain/lower:testdata",