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

Add line output to diagnostics to help identify error locations. (#3010)

This also makes the filename a reference to the buffer since the line
seems better to have as a reference (versus copying a string per error).
Most tests now have different line deltas due to the extra output, but
the actual errors should overall stay the same.

Some of the error locations look like they could be improved, but this
change is only making it clear where they were before.
Jon Ross-Perkins 2 лет назад
Родитель
Сommit
65a4e006a2
100 измененных файлов с 470 добавлено и 162 удалено
  1. 10 5
      toolchain/diagnostics/diagnostic_emitter.h
  2. 6 6
      toolchain/diagnostics/sorting_diagnostic_consumer_test.cpp
  3. 4 5
      toolchain/driver/driver.cpp
  4. 6 2
      toolchain/driver/testdata/errors_sorted_test.carbon
  5. 6 2
      toolchain/driver/testdata/errors_streamed_test.carbon
  6. 17 3
      toolchain/lexer/tokenized_buffer.cpp
  7. 4 0
      toolchain/lexer/tokenized_buffer.h
  8. 3 1
      toolchain/lowering/testdata/basics/fail_before_lowering.carbon
  9. 9 3
      toolchain/parser/testdata/basics/fail_invalid_designators.carbon
  10. 3 1
      toolchain/parser/testdata/basics/fail_no_intro_with_semi.carbon
  11. 3 1
      toolchain/parser/testdata/basics/fail_no_intro_without_semi.carbon
  12. 9 3
      toolchain/parser/testdata/basics/fail_paren_match_regression.carbon
  13. 3 1
      toolchain/parser/testdata/for/fail_colon_instead_of_in.carbon
  14. 3 1
      toolchain/parser/testdata/for/fail_missing_in.carbon
  15. 3 1
      toolchain/parser/testdata/for/fail_missing_var.carbon
  16. 3 1
      toolchain/parser/testdata/function/declaration/fail_identifier_instead_of_sig.carbon
  17. 9 3
      toolchain/parser/testdata/function/declaration/fail_missing_deduced_close.carbon
  18. 3 1
      toolchain/parser/testdata/function/declaration/fail_missing_name.carbon
  19. 3 1
      toolchain/parser/testdata/function/declaration/fail_no_sig_or_semi.carbon
  20. 3 1
      toolchain/parser/testdata/function/declaration/fail_only_fn_and_semi.carbon
  21. 3 1
      toolchain/parser/testdata/function/declaration/fail_repeated_fn_and_semi.carbon
  22. 3 1
      toolchain/parser/testdata/function/declaration/fail_skip_indented_newline_until_outdent.carbon
  23. 3 1
      toolchain/parser/testdata/function/declaration/fail_skip_indented_newline_with_semi.carbon
  24. 3 1
      toolchain/parser/testdata/function/declaration/fail_skip_indented_newline_without_semi.carbon
  25. 3 1
      toolchain/parser/testdata/function/declaration/fail_skip_to_newline_without_semi.carbon
  26. 3 1
      toolchain/parser/testdata/function/declaration/fail_skip_without_semi_to_curly.carbon
  27. 3 1
      toolchain/parser/testdata/function/declaration/fail_with_identifier_as_param.carbon
  28. 3 1
      toolchain/parser/testdata/function/declaration/fail_without_name_and_many_tokens_in_params.carbon
  29. 3 1
      toolchain/parser/testdata/function/definition/fail_identifier_in_statements.carbon
  30. 12 4
      toolchain/parser/testdata/generics/deduced_params/fail_no_parens.carbon
  31. 3 1
      toolchain/parser/testdata/generics/interface/fail_missing_name.carbon
  32. 6 2
      toolchain/parser/testdata/generics/interface/fail_missing_open_curly.carbon
  33. 3 1
      toolchain/parser/testdata/generics/interface/fail_no_impl_allowed.carbon
  34. 6 2
      toolchain/parser/testdata/generics/interface/fail_self_param_syntax.carbon
  35. 3 1
      toolchain/parser/testdata/generics/named_constraint/fail_no_impl_allowed.carbon
  36. 12 4
      toolchain/parser/testdata/if/fail_else_unbraced.carbon
  37. 15 5
      toolchain/parser/testdata/if/fail_errors.carbon
  38. 9 3
      toolchain/parser/testdata/if/fail_unbraced.carbon
  39. 3 1
      toolchain/parser/testdata/if_expression/fail_condition_missing.carbon
  40. 3 1
      toolchain/parser/testdata/if_expression/fail_else_expr_missing.carbon
  41. 3 1
      toolchain/parser/testdata/if_expression/fail_else_missing.carbon
  42. 3 1
      toolchain/parser/testdata/if_expression/fail_then_expr_missing.carbon
  43. 3 1
      toolchain/parser/testdata/if_expression/fail_then_missing.carbon
  44. 9 3
      toolchain/parser/testdata/if_expression/fail_top_level_if.carbon
  45. 3 1
      toolchain/parser/testdata/namespace/fail_args.carbon
  46. 3 1
      toolchain/parser/testdata/namespace/fail_incomplete_name.carbon
  47. 3 1
      toolchain/parser/testdata/namespace/fail_no_name.carbon
  48. 3 1
      toolchain/parser/testdata/operators/fail_infix_uneven_space_after.carbon
  49. 12 4
      toolchain/parser/testdata/operators/fail_invalid_infix.carbon
  50. 3 1
      toolchain/parser/testdata/operators/fail_precedence_and_or.carbon
  51. 3 1
      toolchain/parser/testdata/operators/fail_precedence_or_and.carbon
  52. 3 1
      toolchain/parser/testdata/operators/fail_precedence_star_minus.carbon
  53. 3 1
      toolchain/parser/testdata/operators/fail_precedence_star_star.carbon
  54. 3 1
      toolchain/parser/testdata/operators/fail_star_star_no_space.carbon
  55. 12 4
      toolchain/parser/testdata/operators/fail_variety.carbon
  56. 3 1
      toolchain/parser/testdata/operators/recover_infix_uneven_space_before.carbon
  57. 3 1
      toolchain/parser/testdata/operators/recover_postfix_space.carbon
  58. 3 1
      toolchain/parser/testdata/operators/recover_postfix_space_before_comma.carbon
  59. 3 1
      toolchain/parser/testdata/operators/recover_postfix_space_in_call.carbon
  60. 3 1
      toolchain/parser/testdata/operators/recover_postfix_space_surrounding.carbon
  61. 3 1
      toolchain/parser/testdata/operators/recover_prefix_space.carbon
  62. 3 1
      toolchain/parser/testdata/operators/recover_prefix_uneven_space_with_assign.carbon
  63. 3 1
      toolchain/parser/testdata/package/fail_extra_string.carbon
  64. 3 1
      toolchain/parser/testdata/package/fail_library_is_identifier.carbon
  65. 3 1
      toolchain/parser/testdata/package/fail_library_skips_name.carbon
  66. 3 1
      toolchain/parser/testdata/package/fail_name_is_keyword.carbon
  67. 3 1
      toolchain/parser/testdata/package/fail_no_name.carbon
  68. 3 1
      toolchain/parser/testdata/package/fail_no_semi.carbon
  69. 3 1
      toolchain/parser/testdata/package/fail_no_type.carbon
  70. 3 1
      toolchain/parser/testdata/package/fail_omit_library_keyword.carbon
  71. 3 1
      toolchain/parser/testdata/return/fail_expr_no_semi.carbon
  72. 6 2
      toolchain/parser/testdata/return/fail_no_semi.carbon
  73. 3 1
      toolchain/parser/testdata/struct/fail_comma_only.carbon
  74. 3 1
      toolchain/parser/testdata/struct/fail_comma_repeat_in_type.carbon
  75. 3 1
      toolchain/parser/testdata/struct/fail_comma_repeat_in_value.carbon
  76. 3 1
      toolchain/parser/testdata/struct/fail_dot_only.carbon
  77. 3 1
      toolchain/parser/testdata/struct/fail_dot_string_colon.carbon
  78. 3 1
      toolchain/parser/testdata/struct/fail_dot_string_equals.carbon
  79. 3 1
      toolchain/parser/testdata/struct/fail_extra_token_in_type.carbon
  80. 3 1
      toolchain/parser/testdata/struct/fail_extra_token_in_value.carbon
  81. 3 1
      toolchain/parser/testdata/struct/fail_identifier_colon.carbon
  82. 3 1
      toolchain/parser/testdata/struct/fail_identifier_equals.carbon
  83. 3 1
      toolchain/parser/testdata/struct/fail_identifier_only.carbon
  84. 3 1
      toolchain/parser/testdata/struct/fail_missing_type.carbon
  85. 3 1
      toolchain/parser/testdata/struct/fail_missing_value.carbon
  86. 3 1
      toolchain/parser/testdata/struct/fail_mix_type_and_value.carbon
  87. 3 1
      toolchain/parser/testdata/struct/fail_mix_value_and_type.carbon
  88. 12 4
      toolchain/parser/testdata/struct/fail_mix_with_unknown.carbon
  89. 3 1
      toolchain/parser/testdata/struct/fail_no_colon_or_equals.carbon
  90. 3 1
      toolchain/parser/testdata/struct/fail_type_no_designator.carbon
  91. 3 1
      toolchain/parser/testdata/var/fail_bad_name.carbon
  92. 3 1
      toolchain/parser/testdata/var/fail_empty.carbon
  93. 6 2
      toolchain/parser/testdata/while/fail_no_semi.carbon
  94. 3 1
      toolchain/parser/testdata/while/fail_unbraced.carbon
  95. 3 1
      toolchain/semantics/testdata/basics/fail_name_lookup.carbon
  96. 3 1
      toolchain/semantics/testdata/basics/fail_qualifier_unsupported.carbon
  97. 36 12
      toolchain/semantics/testdata/function/call/fail_param_count.carbon
  98. 6 2
      toolchain/semantics/testdata/function/call/fail_param_type.carbon
  99. 3 1
      toolchain/semantics/testdata/function/call/fail_return_type_mismatch.carbon
  100. 6 2
      toolchain/semantics/testdata/function/definition/fail_param_name_conflict.carbon

+ 10 - 5
toolchain/diagnostics/diagnostic_emitter.h

@@ -45,12 +45,14 @@ enum class DiagnosticLevel : int8_t {
           ::Carbon::DiagnosticKind::DiagnosticName,           \
           ::Carbon::DiagnosticLevel::Level, Format)
 
+// A location for a diagnostic in a file. The lifetime of a DiagnosticLocation
+// is required to be less than SourceBuffer that it refers to due to the
+// contained file_name and line references.
 struct DiagnosticLocation {
   // Name of the file or buffer that this diagnostic refers to.
-  // TODO: Move this out of DiagnosticLocation, as part of an expectation that
-  // files will be compiled separately, so storing the file's path
-  // per-diagnostic is wasteful.
-  std::string file_name;
+  llvm::StringRef file_name;
+  // A reference to the line of the error.
+  llvm::StringRef line;
   // 1-based line number.
   int32_t line_number;
   // 1-based column number.
@@ -311,7 +313,10 @@ class StreamDiagnosticConsumer : public DiagnosticConsumer {
     *stream_ << message.location.file_name << ":"
              << message.location.line_number << ":"
              << message.location.column_number << ": "
-             << message.format_fn(message) << "\n";
+             << message.format_fn(message) << "\n"
+             << message.location.line << "\n";
+    stream_->indent(message.location.column_number - 1);
+    *stream_ << "^\n";
   }
 
  private:

+ 6 - 6
toolchain/diagnostics/sorting_diagnostic_consumer_test.cpp

@@ -32,12 +32,12 @@ TEST(SortedDiagnosticEmitterTest, SortErrors) {
   SortingDiagnosticConsumer sorting_consumer(consumer);
   DiagnosticEmitter<DiagnosticLocation> emitter(translator, sorting_consumer);
 
-  emitter.Emit({"f", 2, 1}, TestDiagnostic, "M1");
-  emitter.Emit({"f", 1, 1}, TestDiagnostic, "M2");
-  emitter.Emit({"f", 1, 3}, TestDiagnostic, "M3");
-  emitter.Emit({"f", 3, 4}, TestDiagnostic, "M4");
-  emitter.Emit({"f", 3, 2}, TestDiagnostic, "M5");
-  emitter.Emit({"f", 3, 2}, TestDiagnostic, "M6");
+  emitter.Emit({"f", "line", 2, 1}, TestDiagnostic, "M1");
+  emitter.Emit({"f", "line", 1, 1}, TestDiagnostic, "M2");
+  emitter.Emit({"f", "line", 1, 3}, TestDiagnostic, "M3");
+  emitter.Emit({"f", "line", 3, 4}, TestDiagnostic, "M4");
+  emitter.Emit({"f", "line", 3, 2}, TestDiagnostic, "M5");
+  emitter.Emit({"f", "line", 3, 2}, TestDiagnostic, "M6");
 
   InSequence s;
   EXPECT_CALL(consumer, HandleDiagnostic(

+ 4 - 5
toolchain/driver/driver.cpp

@@ -6,6 +6,7 @@
 
 #include "common/vlog.h"
 #include "llvm/ADT/ArrayRef.h"
+#include "llvm/ADT/ScopeExit.h"
 #include "llvm/ADT/StringExtras.h"
 #include "llvm/ADT/StringRef.h"
 #include "llvm/ADT/StringSwitch.h"
@@ -200,6 +201,9 @@ auto Driver::RunDumpSubcommand(DiagnosticConsumer& consumer,
   CARBON_VLOG() << "*** SourceBuffer::CreateFromFile ***\n";
   auto source = SourceBuffer::CreateFromFile(fs_, input_file_name);
   CARBON_VLOG() << "*** SourceBuffer::CreateFromFile done ***\n";
+  // Require flushing the consumer before the source buffer is destroyed,
+  // because diagnostics may reference the buffer.
+  auto flush = llvm::make_scope_exit([&]() { consumer.Flush(); });
   if (!source.ok()) {
     error_stream_ << "ERROR: Unable to open input source file: "
                   << source.error();
@@ -214,7 +218,6 @@ auto Driver::RunDumpSubcommand(DiagnosticConsumer& consumer,
   CARBON_VLOG() << "*** TokenizedBuffer::Lex done ***\n";
   if (dump_mode == DumpMode::TokenizedBuffer) {
     CARBON_VLOG() << "Finishing output.";
-    consumer.Flush();
     output_stream_ << tokenized_source;
     return !has_errors;
   }
@@ -225,7 +228,6 @@ auto Driver::RunDumpSubcommand(DiagnosticConsumer& consumer,
   has_errors |= parse_tree.has_errors();
   CARBON_VLOG() << "*** ParseTree::Parse done ***\n";
   if (dump_mode == DumpMode::ParseTree) {
-    consumer.Flush();
     parse_tree.Print(output_stream_, parse_tree_preorder);
     return !has_errors;
   }
@@ -238,7 +240,6 @@ auto Driver::RunDumpSubcommand(DiagnosticConsumer& consumer,
   has_errors |= semantics_ir.has_errors();
   CARBON_VLOG() << "*** SemanticsIR::MakeFromParseTree done ***\n";
   if (dump_mode == DumpMode::SemanticsIR) {
-    consumer.Flush();
     semantics_ir.Print(output_stream_, semantics_ir_include_builtins);
     return !has_errors;
   }
@@ -256,7 +257,6 @@ auto Driver::RunDumpSubcommand(DiagnosticConsumer& consumer,
       LowerToLLVM(llvm_context, input_file_name, semantics_ir, vlog_stream_);
   CARBON_VLOG() << "*** LowerToLLVM done ***\n";
   if (dump_mode == DumpMode::LLVMIR) {
-    consumer.Flush();
     module->print(output_stream_, /*AAW=*/nullptr,
                   /*ShouldPreserveUseListOrder=*/true);
     return !has_errors;
@@ -269,7 +269,6 @@ auto Driver::RunDumpSubcommand(DiagnosticConsumer& consumer,
   }
 
   if (dump_mode == DumpMode::Assembly) {
-    consumer.Flush();
     CodeGen codegen(*module, target_triple, error_stream_, output_stream_);
     has_errors |= !codegen.PrintAssembly();
     return !has_errors;

+ 6 - 2
toolchain/driver/testdata/errors_sorted_test.carbon

@@ -7,9 +7,13 @@
 // CHECK-COUNT-17:STDOUT: {{.*}}
 // CHECK:STDOUT: ]
 
-// CHECK:STDERR: {{.*}}/errors_sorted_test.carbon:[[@LINE+1]]:24: Closing symbol does not match most recent opening symbol.
+// CHECK:STDERR: {{.*}}/errors_sorted_test.carbon:[[@LINE+3]]:24: Closing symbol does not match most recent opening symbol.
+// CHECK:STDERR: fn run(String program) {
+// CHECK:STDERR:                        ^
 fn run(String program) {
   return True;
 
-// CHECK:STDERR: {{.*}}/errors_sorted_test.carbon:[[@LINE+1]]:10: Invalid digit 'a' in decimal numeric literal.
+// CHECK:STDERR: {{.*}}/errors_sorted_test.carbon:[[@LINE+3]]:10: Invalid digit 'a' in decimal numeric literal.
+// CHECK:STDERR: var x = 3a;
+// CHECK:STDERR:          ^
 var x = 3a;

+ 6 - 2
toolchain/driver/testdata/errors_streamed_test.carbon

@@ -13,5 +13,9 @@ fn run(String program) {
 
 var x = 3a;
 
-// CHECK:STDERR:{{.*}}/errors_streamed_test.carbon:[[@LINE-2]]:10: Invalid digit 'a' in decimal numeric literal.
-// CHECK:STDERR:{{.*}}/errors_streamed_test.carbon:[[@LINE-6]]:24: Closing symbol does not match most recent opening symbol.
+// CHECK:STDERR: {{.*}}/errors_streamed_test.carbon:[[@LINE-2]]:10: Invalid digit 'a' in decimal numeric literal.
+// CHECK:STDERR: var x = 3a;
+// CHECK:STDERR:          ^
+// CHECK:STDERR: {{.*}}/errors_streamed_test.carbon:[[@LINE-8]]:24: Closing symbol does not match most recent opening symbol.
+// CHECK:STDERR: fn run(String program) {
+// CHECK:STDERR:                        ^

+ 17 - 3
toolchain/lexer/tokenized_buffer.cpp

@@ -88,7 +88,7 @@ class TokenizedBuffer::Lexer {
         emitter_(translator_, consumer),
         token_translator_(&buffer, &current_column_),
         token_emitter_(token_translator_, consumer),
-        current_line_(buffer.AddLine({0, 0, 0})),
+        current_line_(buffer.AddLine(LineInfo(0))),
         current_line_info_(&buffer.GetLineInfo(current_line_)) {}
 
   // Perform the necessary bookkeeping to step past a newline at the current
@@ -97,7 +97,7 @@ class TokenizedBuffer::Lexer {
     current_line_info_->length = current_column_;
 
     current_line_ = buffer_->AddLine(
-        {current_line_info_->start + current_column_ + 1, 0, 0});
+        LineInfo(current_line_info_->start + current_column_ + 1));
     current_line_info_ = &buffer_->GetLineInfo(current_line_);
     current_column_ = 0;
     set_indent_ = false;
@@ -907,23 +907,37 @@ auto TokenizedBuffer::SourceBufferLocationTranslator::GetLocation(
   int line_number = line_it - buffer_->line_infos_.begin();
   int column_number = offset - line_it->start;
 
+  llvm::StringRef line;
+
   // We might still be lexing the last line. If so, check to see if there are
   // any newline characters between the position we've finished lexing up to
   // and the given location.
   if (incomplete_line_info && column_number > *last_line_lexed_to_column_) {
     column_number = *last_line_lexed_to_column_;
+    int64_t start = line_it->start;
     for (int64_t i = line_it->start + *last_line_lexed_to_column_; i != offset;
          ++i) {
       if (buffer_->source_->text()[i] == '\n') {
+        start = i;
         ++line_number;
         column_number = 0;
       } else {
         ++column_number;
       }
     }
+    line = buffer_->source_->text().substr(start).take_until(
+        [](char c) { return c == '\n'; });
+  } else if (line_it->length < 0) {
+    line =
+        buffer_->source_->text().substr(line_it->start).take_until([](char c) {
+          return c == '\n';
+        });
+  } else {
+    line = buffer_->source_->text().substr(line_it->start, line_it->length);
   }
 
-  return {.file_name = buffer_->source_->filename().str(),
+  return {.file_name = buffer_->source_->filename(),
+          .line = line,
           .line_number = line_number + 1,
           .column_number = column_number + 1};
 }

+ 4 - 0
toolchain/lexer/tokenized_buffer.h

@@ -358,6 +358,10 @@ class TokenizedBuffer {
   };
 
   struct LineInfo {
+    // The length will always be assigned later. Indent may be assigned if
+    // non-zero.
+    explicit LineInfo(int64_t start) : start(start), length(-1), indent(0) {}
+
     // Zero-based byte offset of the start of the line within the source buffer
     // provided.
     int64_t start;

+ 3 - 1
toolchain/lowering/testdata/basics/fail_before_lowering.carbon

@@ -5,5 +5,7 @@
 // This validates that earlier errors prevent lowering, without crashing.
 // AUTOUPDATE
 
-// CHECK:STDERR: fail_before_lowering.carbon:[[@LINE+1]]:1: Unrecognized declaration introducer.
+// CHECK:STDERR: fail_before_lowering.carbon:[[@LINE+3]]:1: Unrecognized declaration introducer.
+// CHECK:STDERR: a;
+// CHECK:STDERR: ^
 a;

+ 9 - 3
toolchain/parser/testdata/basics/fail_invalid_designators.carbon

@@ -27,10 +27,16 @@
 
 // NOTE: Move to its own directory when more tests are added.
 fn F() {
-  // CHECK:STDERR: fail_invalid_designators.carbon:[[@LINE+1]]:5: Expected identifier after `.`.
+  // CHECK:STDERR: fail_invalid_designators.carbon:[[@LINE+3]]:5: Expected identifier after `.`.
+  // CHECK:STDERR:   a.;
+  // CHECK:STDERR:     ^
   a.;
-  // CHECK:STDERR: fail_invalid_designators.carbon:[[@LINE+1]]:5: Expected identifier after `.`.
+  // CHECK:STDERR: fail_invalid_designators.carbon:[[@LINE+3]]:5: Expected identifier after `.`.
+  // CHECK:STDERR:   a.fn;
+  // CHECK:STDERR:     ^
   a.fn;
-  // CHECK:STDERR: fail_invalid_designators.carbon:[[@LINE+1]]:5: Expected identifier after `.`.
+  // CHECK:STDERR: fail_invalid_designators.carbon:[[@LINE+3]]:5: Expected identifier after `.`.
+  // CHECK:STDERR:   a.42;
+  // CHECK:STDERR:     ^
   a.42;
 }

+ 3 - 1
toolchain/parser/testdata/basics/fail_no_intro_with_semi.carbon

@@ -8,5 +8,7 @@
 // CHECK:STDOUT: {kind: 'FileEnd', text: ''},
 // CHECK:STDOUT: ]
 
-// CHECK:STDERR: fail_no_intro_with_semi.carbon:[[@LINE+1]]:1: Unrecognized declaration introducer.
+// CHECK:STDERR: fail_no_intro_with_semi.carbon:[[@LINE+3]]:1: Unrecognized declaration introducer.
+// CHECK:STDERR: foo;
+// CHECK:STDERR: ^
 foo;

+ 3 - 1
toolchain/parser/testdata/basics/fail_no_intro_without_semi.carbon

@@ -8,5 +8,7 @@
 // CHECK:STDOUT: {kind: 'FileEnd', text: ''},
 // CHECK:STDOUT: ]
 
-// CHECK:STDERR: fail_no_intro_without_semi.carbon:[[@LINE+1]]:1: Unrecognized declaration introducer.
+// CHECK:STDERR: fail_no_intro_without_semi.carbon:[[@LINE+3]]:1: Unrecognized declaration introducer.
+// CHECK:STDERR: foo bar baz
+// CHECK:STDERR: ^
 foo bar baz

+ 9 - 3
toolchain/parser/testdata/basics/fail_paren_match_regression.carbon

@@ -16,7 +16,13 @@
 // CHECK:STDOUT: {kind: 'FileEnd', text: ''},
 // CHECK:STDOUT: ]
 
-// CHECK:STDERR: fail_paren_match_regression.carbon:[[@LINE+3]]:5: Expected pattern in `var` declaration.
-// CHECK:STDERR: fail_paren_match_regression.carbon:[[@LINE+2]]:12: Expected `,` or `)`.
-// CHECK:STDERR: fail_paren_match_regression.carbon:[[@LINE+1]]:15: `var` declarations must end with a `;`.
+// CHECK:STDERR: fail_paren_match_regression.carbon:[[@LINE+9]]:5: Expected pattern in `var` declaration.
+// CHECK:STDERR: var = (foo {})
+// CHECK:STDERR:     ^
+// CHECK:STDERR: fail_paren_match_regression.carbon:[[@LINE+6]]:12: Expected `,` or `)`.
+// CHECK:STDERR: var = (foo {})
+// CHECK:STDERR:            ^
+// CHECK:STDERR: fail_paren_match_regression.carbon:[[@LINE+3]]:15: `var` declarations must end with a `;`.
+// CHECK:STDERR: var = (foo {})
+// CHECK:STDERR:               ^
 var = (foo {})

+ 3 - 1
toolchain/parser/testdata/for/fail_colon_instead_of_in.carbon

@@ -30,7 +30,9 @@
 // CHECK:STDOUT: ]
 
 fn foo() {
-  // CHECK:STDERR: fail_colon_instead_of_in.carbon:[[@LINE+1]]:19: `:` should be replaced by `in`.
+  // CHECK:STDERR: fail_colon_instead_of_in.carbon:[[@LINE+3]]:19: `:` should be replaced by `in`.
+  // CHECK:STDERR:   for (var x: i32 : y) {
+  // CHECK:STDERR:                   ^
   for (var x: i32 : y) {
     Print(x);
   }

+ 3 - 1
toolchain/parser/testdata/for/fail_missing_in.carbon

@@ -30,7 +30,9 @@
 // CHECK:STDOUT: ]
 
 fn foo() {
-  // CHECK:STDERR: fail_missing_in.carbon:[[@LINE+1]]:19: Expected `in` after loop `var` declaration.
+  // CHECK:STDERR: fail_missing_in.carbon:[[@LINE+3]]:19: Expected `in` after loop `var` declaration.
+  // CHECK:STDERR:   for (var x: i32 y) {
+  // CHECK:STDERR:                   ^
   for (var x: i32 y) {
     Print(x);
   }

+ 3 - 1
toolchain/parser/testdata/for/fail_missing_var.carbon

@@ -25,7 +25,9 @@
 // CHECK:STDOUT: ]
 
 fn foo() {
-  // CHECK:STDERR: fail_missing_var.carbon:[[@LINE+1]]:8: Expected `var` declaration.
+  // CHECK:STDERR: fail_missing_var.carbon:[[@LINE+3]]:8: Expected `var` declaration.
+  // CHECK:STDERR:   for (x: i32 in y) {
+  // CHECK:STDERR:        ^
   for (x: i32 in y) {
     Print(x);
   }

+ 3 - 1
toolchain/parser/testdata/function/declaration/fail_identifier_instead_of_sig.carbon

@@ -10,5 +10,7 @@
 // CHECK:STDOUT: {kind: 'FileEnd', text: ''},
 // CHECK:STDOUT: ]
 
-// CHECK:STDERR: fail_identifier_instead_of_sig.carbon:[[@LINE+1]]:8: `fn` requires a `(` for parameters.
+// CHECK:STDERR: fail_identifier_instead_of_sig.carbon:[[@LINE+3]]:8: `fn` requires a `(` for parameters.
+// CHECK:STDERR: fn foo bar;
+// CHECK:STDERR:        ^
 fn foo bar;

+ 9 - 3
toolchain/parser/testdata/function/declaration/fail_missing_deduced_close.carbon

@@ -16,7 +16,13 @@
 // CHECK:STDOUT: ]
 
 // Fix and uncomment this to test error handling.
-// CHECK:STDERR: fail_missing_deduced_close.carbon:[[@LINE+2]]:7: Closing symbol does not match most recent opening symbol.
-// CHECK:STDERR: fail_missing_deduced_close.carbon:[[@LINE+1]]:8: Expected parameter declaration.
+// CHECK:STDERR: fail_missing_deduced_close.carbon:[[@LINE+9]]:7: Closing symbol does not match most recent opening symbol.
+// CHECK:STDERR: fn Div[();
+// CHECK:STDERR:       ^
+// CHECK:STDERR: fail_missing_deduced_close.carbon:[[@LINE+6]]:8: Expected parameter declaration.
+// CHECK:STDERR: fn Div[();
+// CHECK:STDERR:        ^
+// CHECK:STDERR: fail_missing_deduced_close.carbon:[[@LINE+3]]:11: A `(` for parameters is required after deduced parameters.
+// CHECK:STDERR: fn Div[();
+// CHECK:STDERR:           ^
 fn Div[();
-// CHECK:STDERR: fail_missing_deduced_close.carbon:[[@LINE+0]]:127: A `(` for parameters is required after deduced parameters.

+ 3 - 1
toolchain/parser/testdata/function/declaration/fail_missing_name.carbon

@@ -10,5 +10,7 @@
 // CHECK:STDOUT: {kind: 'FileEnd', text: ''},
 // CHECK:STDOUT: ]
 
-// CHECK:STDERR: fail_missing_name.carbon:[[@LINE+1]]:4: `fn` introducer should be followed by a name.
+// CHECK:STDERR: fail_missing_name.carbon:[[@LINE+3]]:4: `fn` introducer should be followed by a name.
+// CHECK:STDERR: fn ();
+// CHECK:STDERR:    ^
 fn ();

+ 3 - 1
toolchain/parser/testdata/function/declaration/fail_no_sig_or_semi.carbon

@@ -10,5 +10,7 @@
 // CHECK:STDOUT: {kind: 'FileEnd', text: ''},
 // CHECK:STDOUT: ]
 
-// CHECK:STDERR: fail_no_sig_or_semi.carbon:[[@LINE+1]]:7: `fn` requires a `(` for parameters.
+// CHECK:STDERR: fail_no_sig_or_semi.carbon:[[@LINE+3]]:7: `fn` requires a `(` for parameters.
+// CHECK:STDERR: fn foo
+// CHECK:STDERR:       ^
 fn foo

+ 3 - 1
toolchain/parser/testdata/function/declaration/fail_only_fn_and_semi.carbon

@@ -10,5 +10,7 @@
 // CHECK:STDOUT: {kind: 'FileEnd', text: ''},
 // CHECK:STDOUT: ]
 
-// CHECK:STDERR: fail_only_fn_and_semi.carbon:[[@LINE+1]]:3: `fn` introducer should be followed by a name.
+// CHECK:STDERR: fail_only_fn_and_semi.carbon:[[@LINE+3]]:3: `fn` introducer should be followed by a name.
+// CHECK:STDERR: fn;
+// CHECK:STDERR:   ^
 fn;

+ 3 - 1
toolchain/parser/testdata/function/declaration/fail_repeated_fn_and_semi.carbon

@@ -10,5 +10,7 @@
 // CHECK:STDOUT: {kind: 'FileEnd', text: ''},
 // CHECK:STDOUT: ]
 
-// CHECK:STDERR: fail_repeated_fn_and_semi.carbon:[[@LINE+1]]:4: `fn` introducer should be followed by a name.
+// CHECK:STDERR: fail_repeated_fn_and_semi.carbon:[[@LINE+3]]:4: `fn` introducer should be followed by a name.
+// CHECK:STDERR: fn fn;
+// CHECK:STDERR:    ^
 fn fn;

+ 3 - 1
toolchain/parser/testdata/function/declaration/fail_skip_indented_newline_until_outdent.carbon

@@ -15,7 +15,9 @@
 // CHECK:STDOUT: {kind: 'FileEnd', text: ''},
 // CHECK:STDOUT: ]
 
-  // CHECK:STDERR: fail_skip_indented_newline_until_outdent.carbon:[[@LINE+1]]:6: `fn` introducer should be followed by a name.
+  // CHECK:STDERR: fail_skip_indented_newline_until_outdent.carbon:[[@LINE+3]]:6: `fn` introducer should be followed by a name.
+  // CHECK:STDERR:   fn (x,
+  // CHECK:STDERR:      ^
   fn (x,
       y,
       z)

+ 3 - 1
toolchain/parser/testdata/function/declaration/fail_skip_indented_newline_with_semi.carbon

@@ -15,7 +15,9 @@
 // CHECK:STDOUT: {kind: 'FileEnd', text: ''},
 // CHECK:STDOUT: ]
 
-// CHECK:STDERR: fail_skip_indented_newline_with_semi.carbon:[[@LINE+1]]:4: `fn` introducer should be followed by a name.
+// CHECK:STDERR: fail_skip_indented_newline_with_semi.carbon:[[@LINE+3]]:4: `fn` introducer should be followed by a name.
+// CHECK:STDERR: fn (x,
+// CHECK:STDERR:    ^
 fn (x,
     y,
     z);

+ 3 - 1
toolchain/parser/testdata/function/declaration/fail_skip_indented_newline_without_semi.carbon

@@ -15,7 +15,9 @@
 // CHECK:STDOUT: {kind: 'FileEnd', text: ''},
 // CHECK:STDOUT: ]
 
-// CHECK:STDERR: fail_skip_indented_newline_without_semi.carbon:[[@LINE+1]]:4: `fn` introducer should be followed by a name.
+// CHECK:STDERR: fail_skip_indented_newline_without_semi.carbon:[[@LINE+3]]:4: `fn` introducer should be followed by a name.
+// CHECK:STDERR: fn (x,
+// CHECK:STDERR:    ^
 fn (x,
     y,
     z)

+ 3 - 1
toolchain/parser/testdata/function/declaration/fail_skip_to_newline_without_semi.carbon

@@ -15,6 +15,8 @@
 // CHECK:STDOUT: {kind: 'FileEnd', text: ''},
 // CHECK:STDOUT: ]
 
-// CHECK:STDERR: fail_skip_to_newline_without_semi.carbon:[[@LINE+1]]:4: `fn` introducer should be followed by a name.
+// CHECK:STDERR: fail_skip_to_newline_without_semi.carbon:[[@LINE+3]]:4: `fn` introducer should be followed by a name.
+// CHECK:STDERR: fn ()
+// CHECK:STDERR:    ^
 fn ()
 fn F();

+ 3 - 1
toolchain/parser/testdata/function/declaration/fail_skip_without_semi_to_curly.carbon

@@ -13,6 +13,8 @@
 // CHECK:STDOUT: {kind: 'FileEnd', text: ''},
 // CHECK:STDOUT: ]
 
-// CHECK:STDERR: fail_skip_without_semi_to_curly.carbon:[[@LINE+1]]:1: Unrecognized declaration introducer.
+// CHECK:STDERR: fail_skip_without_semi_to_curly.carbon:[[@LINE+3]]:1: Unrecognized declaration introducer.
+// CHECK:STDERR: struct X { fn () }
+// CHECK:STDERR: ^
 struct X { fn () }
 fn F();

+ 3 - 1
toolchain/parser/testdata/function/declaration/fail_with_identifier_as_param.carbon

@@ -15,5 +15,7 @@
 // CHECK:STDOUT: {kind: 'FileEnd', text: ''},
 // CHECK:STDOUT: ]
 
-// CHECK:STDERR: fail_with_identifier_as_param.carbon:[[@LINE+1]]:11: Expected parameter declaration.
+// CHECK:STDERR: fail_with_identifier_as_param.carbon:[[@LINE+3]]:11: Expected parameter declaration.
+// CHECK:STDERR: fn foo(bar);
+// CHECK:STDERR:           ^
 fn foo(bar);

+ 3 - 1
toolchain/parser/testdata/function/declaration/fail_without_name_and_many_tokens_in_params.carbon

@@ -10,5 +10,7 @@
 // CHECK:STDOUT: {kind: 'FileEnd', text: ''},
 // CHECK:STDOUT: ]
 
-// CHECK:STDERR: fail_without_name_and_many_tokens_in_params.carbon:[[@LINE+1]]:4: `fn` introducer should be followed by a name.
+// CHECK:STDERR: fail_without_name_and_many_tokens_in_params.carbon:[[@LINE+3]]:4: `fn` introducer should be followed by a name.
+// CHECK:STDERR: fn (a tokens c d e f g h i j k l m n o p q r s t u v w x y z);
+// CHECK:STDERR:    ^
 fn (a tokens c d e f g h i j k l m n o p q r s t u v w x y z);

+ 3 - 1
toolchain/parser/testdata/function/definition/fail_identifier_in_statements.carbon

@@ -18,5 +18,7 @@ fn F() {
   // Note: this might become valid depending on the expression syntax. This test
   // shouldn't be taken as a sign it should remain invalid.
   bar
-// CHECK:STDERR: fail_identifier_in_statements.carbon:[[@LINE+1]]:1: Expected `;` after expression statement.
+// CHECK:STDERR: fail_identifier_in_statements.carbon:[[@LINE+3]]:1: Expected `;` after expression statement.
+// CHECK:STDERR: }
+// CHECK:STDERR: ^
 }

+ 12 - 4
toolchain/parser/testdata/generics/deduced_params/fail_no_parens.carbon

@@ -33,14 +33,22 @@
 // CHECK:STDOUT: {kind: 'FileEnd', text: ''},
 // CHECK:STDOUT: ]
 
-// CHECK:STDERR: fail_no_parens.carbon:[[@LINE+1]]:12: A `(` for parameters is required after deduced parameters.
+// CHECK:STDERR: fail_no_parens.carbon:[[@LINE+3]]:12: A `(` for parameters is required after deduced parameters.
+// CHECK:STDERR: class Foo[];
+// CHECK:STDERR:            ^
 class Foo[];
 
-// CHECK:STDERR: fail_no_parens.carbon:[[@LINE+1]]:18: A `(` for parameters is required after deduced parameters.
+// CHECK:STDERR: fail_no_parens.carbon:[[@LINE+3]]:18: A `(` for parameters is required after deduced parameters.
+// CHECK:STDERR: class Foo[a: i32];
+// CHECK:STDERR:                  ^
 class Foo[a: i32];
 
-// CHECK:STDERR: fail_no_parens.carbon:[[@LINE+1]]:17: A `(` for parameters is required after deduced parameters.
+// CHECK:STDERR: fail_no_parens.carbon:[[@LINE+3]]:17: A `(` for parameters is required after deduced parameters.
+// CHECK:STDERR: interface Bar[] {}
+// CHECK:STDERR:                 ^
 interface Bar[] {}
 
-// CHECK:STDERR: fail_no_parens.carbon:[[@LINE+1]]:23: A `(` for parameters is required after deduced parameters.
+// CHECK:STDERR: fail_no_parens.carbon:[[@LINE+3]]:23: A `(` for parameters is required after deduced parameters.
+// CHECK:STDERR: interface Bar[a: i32] {}
+// CHECK:STDERR:                       ^
 interface Bar[a: i32] {}

+ 3 - 1
toolchain/parser/testdata/generics/interface/fail_missing_name.carbon

@@ -10,6 +10,8 @@
 // CHECK:STDOUT: {kind: 'FileEnd', text: ''},
 // CHECK:STDOUT: ]
 
-// CHECK:STDERR: fail_missing_name.carbon:[[@LINE+1]]:11: `interface` introducer should be followed by a name.
+// CHECK:STDERR: fail_missing_name.carbon:[[@LINE+3]]:11: `interface` introducer should be followed by a name.
+// CHECK:STDERR: interface {
+// CHECK:STDERR:           ^
 interface {
 }

+ 6 - 2
toolchain/parser/testdata/generics/interface/fail_missing_open_curly.carbon

@@ -13,8 +13,12 @@
 // CHECK:STDOUT: {kind: 'FileEnd', text: ''},
 // CHECK:STDOUT: ]
 
-// CHECK:STDERR: fail_missing_open_curly.carbon:[[@LINE+1]]:15: `interface` declarations must either end with a `;` or have a `{ ... }` block for a definition.
+// CHECK:STDERR: fail_missing_open_curly.carbon:[[@LINE+3]]:15: `interface` declarations must either end with a `;` or have a `{ ... }` block for a definition.
+// CHECK:STDERR: interface Bar Baz {}
+// CHECK:STDERR:               ^
 interface Bar Baz {}
 
-// CHECK:STDERR: fail_missing_open_curly.carbon:[[@LINE+1]]:14: `interface` declarations must either end with a `;` or have a `{ ... }` block for a definition.
+// CHECK:STDERR: fail_missing_open_curly.carbon:[[@LINE+3]]:14: `interface` declarations must either end with a `;` or have a `{ ... }` block for a definition.
+// CHECK:STDERR: interface Foo
+// CHECK:STDERR:              ^
 interface Foo

+ 3 - 1
toolchain/parser/testdata/generics/interface/fail_no_impl_allowed.carbon

@@ -27,7 +27,9 @@
 // CHECK:STDOUT: ]
 
 interface Foo {
-  // CHECK:STDERR: fail_no_impl_allowed.carbon:[[@LINE+1]]:39: Method implementations are not allowed in interfaces.
+  // CHECK:STDERR: fail_no_impl_allowed.carbon:[[@LINE+3]]:39: Method implementations are not allowed in interfaces.
+  // CHECK:STDERR:   fn Add[self: Self](b: Self) -> Self {
+  // CHECK:STDERR:                                       ^
   fn Add[self: Self](b: Self) -> Self {
     print("You can't do that.");
   }

+ 6 - 2
toolchain/parser/testdata/generics/interface/fail_self_param_syntax.carbon

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

+ 3 - 1
toolchain/parser/testdata/generics/named_constraint/fail_no_impl_allowed.carbon

@@ -27,6 +27,8 @@
 // CHECK:STDOUT: ]
 
 constraint Foo {
-  // CHECK:STDERR: fail_no_impl_allowed.carbon:[[@LINE+1]]:39: Method implementations are not allowed in interfaces.
+  // CHECK:STDERR: fail_no_impl_allowed.carbon:[[@LINE+3]]:39: Method implementations are not allowed in interfaces.
+  // CHECK:STDERR:   fn Add[self: Self](b: Self) -> Self {}
+  // CHECK:STDERR:                                       ^
   fn Add[self: Self](b: Self) -> Self {}
 }

+ 12 - 4
toolchain/parser/testdata/if/fail_else_unbraced.carbon

@@ -61,15 +61,23 @@
 
 fn F() {
   if (a)
-    // CHECK:STDERR: fail_else_unbraced.carbon:[[@LINE+1]]:5: Expected braced code block.
+    // CHECK:STDERR: fail_else_unbraced.carbon:[[@LINE+3]]:5: Expected braced code block.
+    // CHECK:STDERR:     if (b)
+    // CHECK:STDERR:     ^
     if (b)
-      // CHECK:STDERR: fail_else_unbraced.carbon:[[@LINE+1]]:7: Expected braced code block.
+      // CHECK:STDERR: fail_else_unbraced.carbon:[[@LINE+3]]:7: Expected braced code block.
+      // CHECK:STDERR:       c;
+      // CHECK:STDERR:       ^
       c;
     else
-      // CHECK:STDERR: fail_else_unbraced.carbon:[[@LINE+1]]:7: Expected braced code block.
+      // CHECK:STDERR: fail_else_unbraced.carbon:[[@LINE+3]]:7: Expected braced code block.
+      // CHECK:STDERR:       d;
+      // CHECK:STDERR:       ^
       d;
   else
-    // CHECK:STDERR: fail_else_unbraced.carbon:[[@LINE+1]]:5: Expected braced code block.
+    // CHECK:STDERR: fail_else_unbraced.carbon:[[@LINE+3]]:5: Expected braced code block.
+    // CHECK:STDERR:     e;
+    // CHECK:STDERR:     ^
     e;
   if (x) { f; }
   else if (x) { g; }

+ 15 - 5
toolchain/parser/testdata/if/fail_errors.carbon

@@ -39,13 +39,23 @@
 // CHECK:STDOUT: ]
 
 fn F() {
-  // CHECK:STDERR: fail_errors.carbon:[[@LINE+1]]:6: Expected `(` after `if`.
+  // CHECK:STDERR: fail_errors.carbon:[[@LINE+3]]:6: Expected `(` after `if`.
+  // CHECK:STDERR:   if a {}
+  // CHECK:STDERR:      ^
   if a {}
-  // CHECK:STDERR: fail_errors.carbon:[[@LINE+1]]:7: Expected expression.
+  // CHECK:STDERR: fail_errors.carbon:[[@LINE+3]]:7: Expected expression.
+  // CHECK:STDERR:   if () {}
+  // CHECK:STDERR:       ^
   if () {}
-  // CHECK:STDERR: fail_errors.carbon:[[@LINE+1]]:9: Unexpected tokens before `)`.
+  // CHECK:STDERR: fail_errors.carbon:[[@LINE+3]]:9: Unexpected tokens before `)`.
+  // CHECK:STDERR:   if (b c) {}
+  // CHECK:STDERR:         ^
   if (b c) {}
   if (d)
-// CHECK:STDERR: fail_errors.carbon:[[@LINE+2]]:1: Expected braced code block.
-// CHECK:STDERR: fail_errors.carbon:[[@LINE+1]]:1: Expected expression.
+// CHECK:STDERR: fail_errors.carbon:[[@LINE+6]]:1: Expected braced code block.
+// CHECK:STDERR: }
+// CHECK:STDERR: ^
+// CHECK:STDERR: fail_errors.carbon:[[@LINE+3]]:1: Expected expression.
+// CHECK:STDERR: }
+// CHECK:STDERR: ^
 }

+ 9 - 3
toolchain/parser/testdata/if/fail_unbraced.carbon

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

+ 3 - 1
toolchain/parser/testdata/if_expression/fail_condition_missing.carbon

@@ -25,6 +25,8 @@
 // CHECK:STDOUT: ]
 
 fn F() {
-  // CHECK:STDERR: fail_condition_missing.carbon:[[@LINE+1]]:18: Expected expression.
+  // CHECK:STDERR: fail_condition_missing.carbon:[[@LINE+3]]:18: Expected expression.
+  // CHECK:STDERR:   var n: i32 = if;
+  // CHECK:STDERR:                  ^
   var n: i32 = if;
 }

+ 3 - 1
toolchain/parser/testdata/if_expression/fail_else_expr_missing.carbon

@@ -26,6 +26,8 @@
 // CHECK:STDOUT: ]
 
 fn F() {
-  // CHECK:STDERR: fail_else_expr_missing.carbon:[[@LINE+1]]:35: Expected expression.
+  // CHECK:STDERR: fail_else_expr_missing.carbon:[[@LINE+3]]:35: Expected expression.
+  // CHECK:STDERR:   var n: i32 = if true then 1 else;
+  // CHECK:STDERR:                                   ^
   var n: i32 = if true then 1 else;
 }

+ 3 - 1
toolchain/parser/testdata/if_expression/fail_else_missing.carbon

@@ -26,6 +26,8 @@
 // CHECK:STDOUT: ]
 
 fn F() {
-  // CHECK:STDERR: fail_else_missing.carbon:[[@LINE+1]]:30: Expected `else` after `if ... then ...`.
+  // CHECK:STDERR: fail_else_missing.carbon:[[@LINE+3]]:30: Expected `else` after `if ... then ...`.
+  // CHECK:STDERR:   var n: i32 = if true then 1;
+  // CHECK:STDERR:                              ^
   var n: i32 = if true then 1;
 }

+ 3 - 1
toolchain/parser/testdata/if_expression/fail_then_expr_missing.carbon

@@ -26,6 +26,8 @@
 // CHECK:STDOUT: ]
 
 fn F() {
-  // CHECK:STDERR: fail_then_expr_missing.carbon:[[@LINE+1]]:28: Expected expression.
+  // CHECK:STDERR: fail_then_expr_missing.carbon:[[@LINE+3]]:28: Expected expression.
+  // CHECK:STDERR:   var n: i32 = if true then;
+  // CHECK:STDERR:                            ^
   var n: i32 = if true then;
 }

+ 3 - 1
toolchain/parser/testdata/if_expression/fail_then_missing.carbon

@@ -25,6 +25,8 @@
 // CHECK:STDOUT: ]
 
 fn F() {
-  // CHECK:STDERR: fail_then_missing.carbon:[[@LINE+1]]:23: Expected `then` after `if` condition.
+  // CHECK:STDERR: fail_then_missing.carbon:[[@LINE+3]]:23: Expected `then` after `if` condition.
+  // CHECK:STDERR:   var n: i32 = if true;
+  // CHECK:STDERR:                       ^
   var n: i32 = if true;
 }

+ 9 - 3
toolchain/parser/testdata/if_expression/fail_top_level_if.carbon

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

+ 3 - 1
toolchain/parser/testdata/namespace/fail_args.carbon

@@ -10,5 +10,7 @@
 // CHECK:STDOUT: {kind: 'FileEnd', text: ''},
 // CHECK:STDOUT: ]
 
-// CHECK:STDERR: fail_args.carbon:[[@LINE+1]]:14: `namespace` declarations must end with a `;`.
+// CHECK:STDERR: fail_args.carbon:[[@LINE+3]]:14: `namespace` declarations must end with a `;`.
+// CHECK:STDERR: namespace Foo();
+// CHECK:STDERR:              ^
 namespace Foo();

+ 3 - 1
toolchain/parser/testdata/namespace/fail_incomplete_name.carbon

@@ -12,5 +12,7 @@
 // CHECK:STDOUT: {kind: 'FileEnd', text: ''},
 // CHECK:STDOUT: ]
 
-// CHECK:STDERR: fail_incomplete_name.carbon:[[@LINE+1]]:15: Expected identifier after `.`.
+// CHECK:STDERR: fail_incomplete_name.carbon:[[@LINE+3]]:15: Expected identifier after `.`.
+// CHECK:STDERR: namespace Foo.;
+// CHECK:STDERR:               ^
 namespace Foo.;

+ 3 - 1
toolchain/parser/testdata/namespace/fail_no_name.carbon

@@ -10,5 +10,7 @@
 // CHECK:STDOUT: {kind: 'FileEnd', text: ''},
 // CHECK:STDOUT: ]
 
-// CHECK:STDERR: fail_no_name.carbon:[[@LINE+1]]:10: `namespace` introducer should be followed by a name.
+// CHECK:STDERR: fail_no_name.carbon:[[@LINE+3]]:10: `namespace` introducer should be followed by a name.
+// CHECK:STDERR: namespace;
+// CHECK:STDERR:          ^
 namespace;

+ 3 - 1
toolchain/parser/testdata/operators/fail_infix_uneven_space_after.carbon

@@ -17,5 +17,7 @@
 
 // TODO: We could figure out that this first Failed example is infix
 // with one-token lookahead.
-// CHECK:STDERR: fail_infix_uneven_space_after.carbon:[[@LINE+1]]:16: `var` declarations must end with a `;`.
+// CHECK:STDERR: fail_infix_uneven_space_after.carbon:[[@LINE+3]]:16: `var` declarations must end with a `;`.
+// CHECK:STDERR: var n: i8 = n* n;
+// CHECK:STDERR:                ^
 var n: i8 = n* n;

+ 12 - 4
toolchain/parser/testdata/operators/fail_invalid_infix.carbon

@@ -34,10 +34,18 @@
 // CHECK:STDOUT: {kind: 'FileEnd', text: ''},
 // CHECK:STDOUT: ]
 
-// CHECK:STDERR: fail_invalid_infix.carbon:[[@LINE+1]]:19: Expected expression.
+// CHECK:STDERR: fail_invalid_infix.carbon:[[@LINE+3]]:19: Expected expression.
+// CHECK:STDERR: var a: i32 = n == ;
+// CHECK:STDERR:                   ^
 var a: i32 = n == ;
-// CHECK:STDERR: fail_invalid_infix.carbon:[[@LINE+1]]:14: Expected expression.
+// CHECK:STDERR: fail_invalid_infix.carbon:[[@LINE+3]]:14: Expected expression.
+// CHECK:STDERR: var b: i32 = == n;
+// CHECK:STDERR:              ^
 var b: i32 = == n;
-// CHECK:STDERR: fail_invalid_infix.carbon:[[@LINE+2]]:14: Expected expression.
-// CHECK:STDERR: fail_invalid_infix.carbon:[[@LINE+1]]:17: Expected expression.
+// CHECK:STDERR: fail_invalid_infix.carbon:[[@LINE+6]]:14: Expected expression.
+// CHECK:STDERR: var c: i32 = == ;
+// CHECK:STDERR:              ^
+// CHECK:STDERR: fail_invalid_infix.carbon:[[@LINE+3]]:17: Expected expression.
+// CHECK:STDERR: var c: i32 = == ;
+// CHECK:STDERR:                 ^
 var c: i32 = == ;

+ 3 - 1
toolchain/parser/testdata/operators/fail_precedence_and_or.carbon

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

+ 3 - 1
toolchain/parser/testdata/operators/fail_precedence_or_and.carbon

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

+ 3 - 1
toolchain/parser/testdata/operators/fail_precedence_star_minus.carbon

@@ -17,5 +17,7 @@
 // CHECK:STDOUT: {kind: 'FileEnd', text: ''},
 // CHECK:STDOUT: ]
 
-// CHECK:STDERR: fail_precedence_star_minus.carbon:[[@LINE+1]]:16: Parentheses are required to disambiguate operator precedence.
+// CHECK:STDERR: fail_precedence_star_minus.carbon:[[@LINE+3]]:16: Parentheses are required to disambiguate operator precedence.
+// CHECK:STDERR: var n: i8 = n* -n;
+// CHECK:STDERR:                ^
 var n: i8 = n* -n;

+ 3 - 1
toolchain/parser/testdata/operators/fail_precedence_star_star.carbon

@@ -17,5 +17,7 @@
 // CHECK:STDOUT: {kind: 'FileEnd', text: ''},
 // CHECK:STDOUT: ]
 
-// CHECK:STDERR: fail_precedence_star_star.carbon:[[@LINE+1]]:16: Parentheses are required to disambiguate operator precedence.
+// CHECK:STDERR: fail_precedence_star_star.carbon:[[@LINE+3]]:16: Parentheses are required to disambiguate operator precedence.
+// CHECK:STDERR: var n: i8 = n* *p;
+// CHECK:STDERR:                ^
 var n: i8 = n* *p;

+ 3 - 1
toolchain/parser/testdata/operators/fail_star_star_no_space.carbon

@@ -20,5 +20,7 @@
 // before we notice the missing whitespace around the second `*`.
 // It'd be better to (somehow) form n*(*p) and reject due to the missing
 // whitespace around the first `*`.
-// CHECK:STDERR: fail_star_star_no_space.carbon:[[@LINE+1]]:16: `var` declarations must end with a `;`.
+// CHECK:STDERR: fail_star_star_no_space.carbon:[[@LINE+3]]:16: `var` declarations must end with a `;`.
+// CHECK:STDERR: var n: i8 = n**p;
+// CHECK:STDERR:                ^
 var n: i8 = n**p;

+ 12 - 4
toolchain/parser/testdata/operators/fail_variety.carbon

@@ -35,9 +35,17 @@
 // CHECK:STDOUT: ]
 
 fn F() {
-  // CHECK:STDERR: fail_variety.carbon:[[@LINE+4]]:29: Parentheses are required to disambiguate operator precedence.
-  // CHECK:STDERR: fail_variety.carbon:[[@LINE+3]]:34: Parentheses are required to disambiguate operator precedence.
-  // CHECK:STDERR: fail_variety.carbon:[[@LINE+2]]:38: Parentheses are required to disambiguate operator precedence.
-  // CHECK:STDERR: fail_variety.carbon:[[@LINE+1]]:40: Parentheses are required to disambiguate operator precedence.
+  // CHECK:STDERR: fail_variety.carbon:[[@LINE+12]]:29: Parentheses are required to disambiguate operator precedence.
+  // CHECK:STDERR:   n = a * b + c * d = d * d << e & f - not g;
+  // CHECK:STDERR:                             ^
+  // CHECK:STDERR: fail_variety.carbon:[[@LINE+9]]:34: Parentheses are required to disambiguate operator precedence.
+  // CHECK:STDERR:   n = a * b + c * d = d * d << e & f - not g;
+  // CHECK:STDERR:                                  ^
+  // CHECK:STDERR: fail_variety.carbon:[[@LINE+6]]:38: Parentheses are required to disambiguate operator precedence.
+  // CHECK:STDERR:   n = a * b + c * d = d * d << e & f - not g;
+  // CHECK:STDERR:                                      ^
+  // CHECK:STDERR: fail_variety.carbon:[[@LINE+3]]:40: Parentheses are required to disambiguate operator precedence.
+  // CHECK:STDERR:   n = a * b + c * d = d * d << e & f - not g;
+  // CHECK:STDERR:                                        ^
   n = a * b + c * d = d * d << e & f - not g;
 }

+ 3 - 1
toolchain/parser/testdata/operators/recover_infix_uneven_space_before.carbon

@@ -16,5 +16,7 @@
 // CHECK:STDOUT: {kind: 'FileEnd', text: ''},
 // CHECK:STDOUT: ]
 
-// CHECK:STDERR: recover_infix_uneven_space_before.carbon:[[@LINE+1]]:15: Whitespace missing after binary operator.
+// CHECK:STDERR: recover_infix_uneven_space_before.carbon:[[@LINE+3]]:15: Whitespace missing after binary operator.
+// CHECK:STDERR: var n: i8 = n *n;
+// CHECK:STDERR:               ^
 var n: i8 = n *n;

+ 3 - 1
toolchain/parser/testdata/operators/recover_postfix_space.carbon

@@ -15,5 +15,7 @@
 // CHECK:STDOUT: {kind: 'FileEnd', text: ''},
 // CHECK:STDOUT: ]
 
-// CHECK:STDERR: recover_postfix_space.carbon:[[@LINE+1]]:18: Whitespace is not allowed before this unary operator.
+// CHECK:STDERR: recover_postfix_space.carbon:[[@LINE+3]]:18: Whitespace is not allowed before this unary operator.
+// CHECK:STDERR: var v: type = i8 *;
+// CHECK:STDERR:                  ^
 var v: type = i8 *;

+ 3 - 1
toolchain/parser/testdata/operators/recover_postfix_space_before_comma.carbon

@@ -20,5 +20,7 @@
 // CHECK:STDOUT: {kind: 'FileEnd', text: ''},
 // CHECK:STDOUT: ]
 
-// CHECK:STDERR: recover_postfix_space_before_comma.carbon:[[@LINE+1]]:18: Whitespace is not allowed before this unary operator.
+// CHECK:STDERR: recover_postfix_space_before_comma.carbon:[[@LINE+3]]:18: Whitespace is not allowed before this unary operator.
+// CHECK:STDERR: var n: i8 = F(i8 *, 0);
+// CHECK:STDERR:                  ^
 var n: i8 = F(i8 *, 0);

+ 3 - 1
toolchain/parser/testdata/operators/recover_postfix_space_in_call.carbon

@@ -18,5 +18,7 @@
 // CHECK:STDOUT: {kind: 'FileEnd', text: ''},
 // CHECK:STDOUT: ]
 
-// CHECK:STDERR: recover_postfix_space_in_call.carbon:[[@LINE+1]]:18: Whitespace is not allowed before this unary operator.
+// CHECK:STDERR: recover_postfix_space_in_call.carbon:[[@LINE+3]]:18: Whitespace is not allowed before this unary operator.
+// CHECK:STDERR: var n: i8 = F(i8 *);
+// CHECK:STDERR:                  ^
 var n: i8 = F(i8 *);

+ 3 - 1
toolchain/parser/testdata/operators/recover_postfix_space_surrounding.carbon

@@ -15,5 +15,7 @@
 // CHECK:STDOUT: {kind: 'FileEnd', text: ''},
 // CHECK:STDOUT: ]
 
-// CHECK:STDERR: recover_postfix_space_surrounding.carbon:[[@LINE+1]]:18: Whitespace is not allowed before this unary operator.
+// CHECK:STDERR: recover_postfix_space_surrounding.carbon:[[@LINE+3]]:18: Whitespace is not allowed before this unary operator.
+// CHECK:STDERR: var v: type = i8 * ;
+// CHECK:STDERR:                  ^
 var v: type = i8 * ;

+ 3 - 1
toolchain/parser/testdata/operators/recover_prefix_space.carbon

@@ -15,5 +15,7 @@
 // CHECK:STDOUT: {kind: 'FileEnd', text: ''},
 // CHECK:STDOUT: ]
 
-// CHECK:STDERR: recover_prefix_space.carbon:[[@LINE+1]]:13: Whitespace is not allowed after this unary operator.
+// CHECK:STDERR: recover_prefix_space.carbon:[[@LINE+3]]:13: Whitespace is not allowed after this unary operator.
+// CHECK:STDERR: var n: i8 = - n;
+// CHECK:STDERR:             ^
 var n: i8 = - n;

+ 3 - 1
toolchain/parser/testdata/operators/recover_prefix_uneven_space_with_assign.carbon

@@ -15,5 +15,7 @@
 // CHECK:STDOUT: {kind: 'FileEnd', text: ''},
 // CHECK:STDOUT: ]
 
-// CHECK:STDERR: recover_prefix_uneven_space_with_assign.carbon:[[@LINE+1]]:12: Whitespace is not allowed after this unary operator.
+// CHECK:STDERR: recover_prefix_uneven_space_with_assign.carbon:[[@LINE+3]]:12: Whitespace is not allowed after this unary operator.
+// CHECK:STDERR: var n: i8 =- n;
+// CHECK:STDERR:            ^
 var n: i8 =- n;

+ 3 - 1
toolchain/parser/testdata/package/fail_extra_string.carbon

@@ -12,5 +12,7 @@
 // CHECK:STDOUT: {kind: 'FileEnd', text: ''},
 // CHECK:STDOUT: ]
 
-// CHECK:STDERR: fail_extra_string.carbon:[[@LINE+1]]:27: Expected a `api` or `impl`.
+// CHECK:STDERR: fail_extra_string.carbon:[[@LINE+3]]:27: Expected a `api` or `impl`.
+// CHECK:STDERR: package Foo library "bar" "baz";
+// CHECK:STDERR:                           ^
 package Foo library "bar" "baz";

+ 3 - 1
toolchain/parser/testdata/package/fail_library_is_identifier.carbon

@@ -10,5 +10,7 @@
 // CHECK:STDOUT: {kind: 'FileEnd', text: ''},
 // CHECK:STDOUT: ]
 
-// CHECK:STDERR: fail_library_is_identifier.carbon:[[@LINE+1]]:26: Expected a string literal to specify the library name.
+// CHECK:STDERR: fail_library_is_identifier.carbon:[[@LINE+3]]:26: Expected a string literal to specify the library name.
+// CHECK:STDERR: package Geometry library Shapes api;
+// CHECK:STDERR:                          ^
 package Geometry library Shapes api;

+ 3 - 1
toolchain/parser/testdata/package/fail_library_skips_name.carbon

@@ -9,5 +9,7 @@
 // CHECK:STDOUT: {kind: 'FileEnd', text: ''},
 // CHECK:STDOUT: ]
 
-// CHECK:STDERR: fail_library_skips_name.carbon:[[@LINE+1]]:9: Expected identifier after `package`.
+// CHECK:STDERR: fail_library_skips_name.carbon:[[@LINE+3]]:9: Expected identifier after `package`.
+// CHECK:STDERR: package library "Shapes" api;
+// CHECK:STDERR:         ^
 package library "Shapes" api;

+ 3 - 1
toolchain/parser/testdata/package/fail_name_is_keyword.carbon

@@ -9,5 +9,7 @@
 // CHECK:STDOUT: {kind: 'FileEnd', text: ''},
 // CHECK:STDOUT: ]
 
-// CHECK:STDERR: fail_name_is_keyword.carbon:[[@LINE+1]]:9: Expected identifier after `package`.
+// CHECK:STDERR: fail_name_is_keyword.carbon:[[@LINE+3]]:9: Expected identifier after `package`.
+// CHECK:STDERR: package fn;
+// CHECK:STDERR:         ^
 package fn;

+ 3 - 1
toolchain/parser/testdata/package/fail_no_name.carbon

@@ -9,5 +9,7 @@
 // CHECK:STDOUT: {kind: 'FileEnd', text: ''},
 // CHECK:STDOUT: ]
 
-// CHECK:STDERR: fail_no_name.carbon:[[@LINE+1]]:8: Expected identifier after `package`.
+// CHECK:STDERR: fail_no_name.carbon:[[@LINE+3]]:8: Expected identifier after `package`.
+// CHECK:STDERR: package;
+// CHECK:STDERR:        ^
 package;

+ 3 - 1
toolchain/parser/testdata/package/fail_no_semi.carbon

@@ -11,5 +11,7 @@
 // CHECK:STDOUT: {kind: 'FileEnd', text: ''},
 // CHECK:STDOUT: ]
 
-// CHECK:STDERR: fail_no_semi.carbon:[[@LINE+1]]:21: `package` declarations must end with a `;`.
+// CHECK:STDERR: fail_no_semi.carbon:[[@LINE+3]]:21: `package` declarations must end with a `;`.
+// CHECK:STDERR: package Geometry api
+// CHECK:STDERR:                     ^
 package Geometry api

+ 3 - 1
toolchain/parser/testdata/package/fail_no_type.carbon

@@ -10,5 +10,7 @@
 // CHECK:STDOUT: {kind: 'FileEnd', text: ''},
 // CHECK:STDOUT: ]
 
-// CHECK:STDERR: fail_no_type.carbon:[[@LINE+1]]:17: Expected a `api` or `impl`.
+// CHECK:STDERR: fail_no_type.carbon:[[@LINE+3]]:17: Expected a `api` or `impl`.
+// CHECK:STDERR: package Geometry;
+// CHECK:STDERR:                 ^
 package Geometry;

+ 3 - 1
toolchain/parser/testdata/package/fail_omit_library_keyword.carbon

@@ -10,5 +10,7 @@
 // CHECK:STDOUT: {kind: 'FileEnd', text: ''},
 // CHECK:STDOUT: ]
 
-// CHECK:STDERR: fail_omit_library_keyword.carbon:[[@LINE+1]]:18: Missing `library` keyword.
+// CHECK:STDERR: fail_omit_library_keyword.carbon:[[@LINE+3]]:18: Missing `library` keyword.
+// CHECK:STDERR: package Geometry "Shapes" api;
+// CHECK:STDERR:                  ^
 package Geometry "Shapes" api;

+ 3 - 1
toolchain/parser/testdata/return/fail_expr_no_semi.carbon

@@ -18,5 +18,7 @@
 
 fn F() {
   return x
-// CHECK:STDERR: fail_expr_no_semi.carbon:[[@LINE+1]]:1: `return` statements must end with a `;`.
+// CHECK:STDERR: fail_expr_no_semi.carbon:[[@LINE+3]]:1: `return` statements must end with a `;`.
+// CHECK:STDERR: }
+// CHECK:STDERR: ^
 }

+ 6 - 2
toolchain/parser/testdata/return/fail_no_semi.carbon

@@ -18,6 +18,10 @@
 
 fn F() {
   return
-// CHECK:STDERR: fail_no_semi.carbon:[[@LINE+2]]:1: Expected expression.
-// CHECK:STDERR: fail_no_semi.carbon:[[@LINE+1]]:1: `return` statements must end with a `;`.
+// CHECK:STDERR: fail_no_semi.carbon:[[@LINE+6]]:1: Expected expression.
+// CHECK:STDERR: }
+// CHECK:STDERR: ^
+// CHECK:STDERR: fail_no_semi.carbon:[[@LINE+3]]:1: `return` statements must end with a `;`.
+// CHECK:STDERR: }
+// CHECK:STDERR: ^
 }

+ 3 - 1
toolchain/parser/testdata/struct/fail_comma_only.carbon

@@ -18,5 +18,7 @@
 // CHECK:STDOUT: {kind: 'FileEnd', text: ''},
 // CHECK:STDOUT: ]
 
-// CHECK:STDERR: fail_comma_only.carbon:[[@LINE+1]]:9: Expected `.field: field_type` or `.field = value`.
+// CHECK:STDERR: fail_comma_only.carbon:[[@LINE+3]]:9: Expected `.field: field_type` or `.field = value`.
+// CHECK:STDERR: var x: {,} = {};
+// CHECK:STDERR:         ^
 var x: {,} = {};

+ 3 - 1
toolchain/parser/testdata/struct/fail_comma_repeat_in_type.carbon

@@ -23,5 +23,7 @@
 // CHECK:STDOUT: {kind: 'FileEnd', text: ''},
 // CHECK:STDOUT: ]
 
-// CHECK:STDERR: fail_comma_repeat_in_type.carbon:[[@LINE+1]]:17: Expected `.field: field_type`.
+// CHECK:STDERR: fail_comma_repeat_in_type.carbon:[[@LINE+3]]:17: Expected `.field: field_type`.
+// CHECK:STDERR: var x: {.a: i32,,} = {};
+// CHECK:STDERR:                 ^
 var x: {.a: i32,,} = {};

+ 3 - 1
toolchain/parser/testdata/struct/fail_comma_repeat_in_value.carbon

@@ -23,5 +23,7 @@
 // CHECK:STDOUT: {kind: 'FileEnd', text: ''},
 // CHECK:STDOUT: ]
 
-// CHECK:STDERR: fail_comma_repeat_in_value.carbon:[[@LINE+1]]:16: Expected `.field = value`.
+// CHECK:STDERR: fail_comma_repeat_in_value.carbon:[[@LINE+3]]:16: Expected `.field = value`.
+// CHECK:STDERR: var x: {.a = 0,,} = {};
+// CHECK:STDERR:                ^
 var x: {.a = 0,,} = {};

+ 3 - 1
toolchain/parser/testdata/struct/fail_dot_only.carbon

@@ -19,5 +19,7 @@
 // CHECK:STDOUT: {kind: 'FileEnd', text: ''},
 // CHECK:STDOUT: ]
 
-// CHECK:STDERR: fail_dot_only.carbon:[[@LINE+1]]:10: Expected identifier after `.`.
+// CHECK:STDERR: fail_dot_only.carbon:[[@LINE+3]]:10: Expected identifier after `.`.
+// CHECK:STDERR: var x: {.} = {};
+// CHECK:STDERR:          ^
 var x: {.} = {};

+ 3 - 1
toolchain/parser/testdata/struct/fail_dot_string_colon.carbon

@@ -25,5 +25,7 @@
 // CHECK:STDOUT: {kind: 'FileEnd', text: ''},
 // CHECK:STDOUT: ]
 
-// CHECK:STDERR: fail_dot_string_colon.carbon:[[@LINE+1]]:10: Expected identifier after `.`.
+// CHECK:STDERR: fail_dot_string_colon.carbon:[[@LINE+3]]:10: Expected identifier after `.`.
+// CHECK:STDERR: var x: {."hello": i32, .y: i32} = {};
+// CHECK:STDERR:          ^
 var x: {."hello": i32, .y: i32} = {};

+ 3 - 1
toolchain/parser/testdata/struct/fail_dot_string_equals.carbon

@@ -25,5 +25,7 @@
 // CHECK:STDOUT: {kind: 'FileEnd', text: ''},
 // CHECK:STDOUT: ]
 
-// CHECK:STDERR: fail_dot_string_equals.carbon:[[@LINE+1]]:10: Expected identifier after `.`.
+// CHECK:STDERR: fail_dot_string_equals.carbon:[[@LINE+3]]:10: Expected identifier after `.`.
+// CHECK:STDERR: var x: {."hello" = 0, .y = 4} = {};
+// CHECK:STDERR:          ^
 var x: {."hello" = 0, .y = 4} = {};

+ 3 - 1
toolchain/parser/testdata/struct/fail_extra_token_in_type.carbon

@@ -24,5 +24,7 @@
 // CHECK:STDOUT: {kind: 'FileEnd', text: ''},
 // CHECK:STDOUT: ]
 
-// CHECK:STDERR: fail_extra_token_in_type.carbon:[[@LINE+1]]:17: Expected `,` or `}`.
+// CHECK:STDERR: fail_extra_token_in_type.carbon:[[@LINE+3]]:17: Expected `,` or `}`.
+// CHECK:STDERR: var x: {.a: i32 banana} = {.a = 0};
+// CHECK:STDERR:                 ^
 var x: {.a: i32 banana} = {.a = 0};

+ 3 - 1
toolchain/parser/testdata/struct/fail_extra_token_in_value.carbon

@@ -24,5 +24,7 @@
 // CHECK:STDOUT: {kind: 'FileEnd', text: ''},
 // CHECK:STDOUT: ]
 
-// CHECK:STDERR: fail_extra_token_in_value.carbon:[[@LINE+1]]:28: Expected `,` or `}`.
+// CHECK:STDERR: fail_extra_token_in_value.carbon:[[@LINE+3]]:28: Expected `,` or `}`.
+// CHECK:STDERR: var x: {.a: i32} = {.a = 0 banana};
+// CHECK:STDERR:                            ^
 var x: {.a: i32} = {.a = 0 banana};

+ 3 - 1
toolchain/parser/testdata/struct/fail_identifier_colon.carbon

@@ -17,5 +17,7 @@
 // CHECK:STDOUT: {kind: 'FileEnd', text: ''},
 // CHECK:STDOUT: ]
 
-// CHECK:STDERR: fail_identifier_colon.carbon:[[@LINE+1]]:9: Expected `.field: field_type` or `.field = value`.
+// CHECK:STDERR: fail_identifier_colon.carbon:[[@LINE+3]]:9: Expected `.field: field_type` or `.field = value`.
+// CHECK:STDERR: var x: {a:} = {};
+// CHECK:STDERR:         ^
 var x: {a:} = {};

+ 3 - 1
toolchain/parser/testdata/struct/fail_identifier_equals.carbon

@@ -17,5 +17,7 @@
 // CHECK:STDOUT: {kind: 'FileEnd', text: ''},
 // CHECK:STDOUT: ]
 
-// CHECK:STDERR: fail_identifier_equals.carbon:[[@LINE+1]]:9: Expected `.field: field_type` or `.field = value`.
+// CHECK:STDERR: fail_identifier_equals.carbon:[[@LINE+3]]:9: Expected `.field: field_type` or `.field = value`.
+// CHECK:STDERR: var x: {a=} = {};
+// CHECK:STDERR:         ^
 var x: {a=} = {};

+ 3 - 1
toolchain/parser/testdata/struct/fail_identifier_only.carbon

@@ -17,5 +17,7 @@
 // CHECK:STDOUT: {kind: 'FileEnd', text: ''},
 // CHECK:STDOUT: ]
 
-// CHECK:STDERR: fail_identifier_only.carbon:[[@LINE+1]]:9: Expected `.field: field_type` or `.field = value`.
+// CHECK:STDERR: fail_identifier_only.carbon:[[@LINE+3]]:9: Expected `.field: field_type` or `.field = value`.
+// CHECK:STDERR: var x: {a} = {};
+// CHECK:STDERR:         ^
 var x: {a} = {};

+ 3 - 1
toolchain/parser/testdata/struct/fail_missing_type.carbon

@@ -20,5 +20,7 @@
 // CHECK:STDOUT: {kind: 'FileEnd', text: ''},
 // CHECK:STDOUT: ]
 
-// CHECK:STDERR: fail_missing_type.carbon:[[@LINE+1]]:12: Expected expression.
+// CHECK:STDERR: fail_missing_type.carbon:[[@LINE+3]]:12: Expected expression.
+// CHECK:STDERR: var x: {.a:} = {};
+// CHECK:STDERR:            ^
 var x: {.a:} = {};

+ 3 - 1
toolchain/parser/testdata/struct/fail_missing_value.carbon

@@ -20,5 +20,7 @@
 // CHECK:STDOUT: {kind: 'FileEnd', text: ''},
 // CHECK:STDOUT: ]
 
-// CHECK:STDERR: fail_missing_value.carbon:[[@LINE+1]]:12: Expected expression.
+// CHECK:STDERR: fail_missing_value.carbon:[[@LINE+3]]:12: Expected expression.
+// CHECK:STDERR: var x: {.a=} = {};
+// CHECK:STDERR:            ^
 var x: {.a=} = {};

+ 3 - 1
toolchain/parser/testdata/struct/fail_mix_type_and_value.carbon

@@ -24,5 +24,7 @@
 // CHECK:STDOUT: {kind: 'FileEnd', text: ''},
 // CHECK:STDOUT: ]
 
-// CHECK:STDERR: fail_mix_type_and_value.carbon:[[@LINE+1]]:21: Expected `.field: field_type`.
+// CHECK:STDERR: fail_mix_type_and_value.carbon:[[@LINE+3]]:21: Expected `.field: field_type`.
+// CHECK:STDERR: var x: {.a: i32, .b = 0} = {};
+// CHECK:STDERR:                     ^
 var x: {.a: i32, .b = 0} = {};

+ 3 - 1
toolchain/parser/testdata/struct/fail_mix_value_and_type.carbon

@@ -22,5 +22,7 @@
 // CHECK:STDOUT: {kind: 'FileEnd', text: ''},
 // CHECK:STDOUT: ]
 
-// CHECK:STDERR: fail_mix_value_and_type.carbon:[[@LINE+1]]:17: Expected `.field = value`.
+// CHECK:STDERR: fail_mix_value_and_type.carbon:[[@LINE+3]]:17: Expected `.field = value`.
+// CHECK:STDERR: var x: {.a = 0, b: i32} = {};
+// CHECK:STDERR:                 ^
 var x: {.a = 0, b: i32} = {};

+ 12 - 4
toolchain/parser/testdata/struct/fail_mix_with_unknown.carbon

@@ -47,10 +47,18 @@
 // CHECK:STDOUT: {kind: 'FileEnd', text: ''},
 // CHECK:STDOUT: ]
 
-// CHECK:STDERR: fail_mix_with_unknown.carbon:[[@LINE+2]]:25: Expected `.field = value`.
-// CHECK:STDERR: fail_mix_with_unknown.carbon:[[@LINE+1]]:29: Expected `.field = value`.
+// CHECK:STDERR: fail_mix_with_unknown.carbon:[[@LINE+6]]:25: Expected `.field = value`.
+// CHECK:STDERR: var x: i32 = {.a = 1, .b, .c: i32};
+// CHECK:STDERR:                         ^
+// CHECK:STDERR: fail_mix_with_unknown.carbon:[[@LINE+3]]:29: Expected `.field = value`.
+// CHECK:STDERR: var x: i32 = {.a = 1, .b, .c: i32};
+// CHECK:STDERR:                             ^
 var x: i32 = {.a = 1, .b, .c: i32};
 
-// CHECK:STDERR: fail_mix_with_unknown.carbon:[[@LINE+2]]:26: Expected `.field: field_type`.
-// CHECK:STDERR: fail_mix_with_unknown.carbon:[[@LINE+1]]:31: Expected `.field: field_type`.
+// CHECK:STDERR: fail_mix_with_unknown.carbon:[[@LINE+6]]:26: Expected `.field: field_type`.
+// CHECK:STDERR: var x: i32 = {.a: i32, .b, .c = 1};
+// CHECK:STDERR:                          ^
+// CHECK:STDERR: fail_mix_with_unknown.carbon:[[@LINE+3]]:31: Expected `.field: field_type`.
+// CHECK:STDERR: var x: i32 = {.a: i32, .b, .c = 1};
+// CHECK:STDERR:                               ^
 var x: i32 = {.a: i32, .b, .c = 1};

+ 3 - 1
toolchain/parser/testdata/struct/fail_no_colon_or_equals.carbon

@@ -19,5 +19,7 @@
 // CHECK:STDOUT: {kind: 'FileEnd', text: ''},
 // CHECK:STDOUT: ]
 
-// CHECK:STDERR: fail_no_colon_or_equals.carbon:[[@LINE+1]]:11: Expected `.field: field_type` or `.field = value`.
+// CHECK:STDERR: fail_no_colon_or_equals.carbon:[[@LINE+3]]:11: Expected `.field: field_type` or `.field = value`.
+// CHECK:STDERR: var x: {.a} = {};
+// CHECK:STDERR:           ^
 var x: {.a} = {};

+ 3 - 1
toolchain/parser/testdata/struct/fail_type_no_designator.carbon

@@ -17,5 +17,7 @@
 // CHECK:STDOUT: {kind: 'FileEnd', text: ''},
 // CHECK:STDOUT: ]
 
-// CHECK:STDERR: fail_type_no_designator.carbon:[[@LINE+1]]:9: Expected `.field: field_type` or `.field = value`.
+// CHECK:STDERR: fail_type_no_designator.carbon:[[@LINE+3]]:9: Expected `.field: field_type` or `.field = value`.
+// CHECK:STDERR: var x: {i32} = {};
+// CHECK:STDERR:         ^
 var x: {i32} = {};

+ 3 - 1
toolchain/parser/testdata/var/fail_bad_name.carbon

@@ -12,5 +12,7 @@
 // CHECK:STDOUT: {kind: 'FileEnd', text: ''},
 // CHECK:STDOUT: ]
 
-// CHECK:STDERR: fail_bad_name.carbon:[[@LINE+1]]:5: Expected pattern in `var` declaration.
+// CHECK:STDERR: fail_bad_name.carbon:[[@LINE+3]]:5: Expected pattern in `var` declaration.
+// CHECK:STDERR: var *;
+// CHECK:STDERR:     ^
 var *;

+ 3 - 1
toolchain/parser/testdata/var/fail_empty.carbon

@@ -12,5 +12,7 @@
 // CHECK:STDOUT: {kind: 'FileEnd', text: ''},
 // CHECK:STDOUT: ]
 
-// CHECK:STDERR: fail_empty.carbon:[[@LINE+1]]:4: Expected pattern in `var` declaration.
+// CHECK:STDERR: fail_empty.carbon:[[@LINE+3]]:4: Expected pattern in `var` declaration.
+// CHECK:STDERR: var;
+// CHECK:STDERR:    ^
 var;

+ 6 - 2
toolchain/parser/testdata/while/fail_no_semi.carbon

@@ -39,11 +39,15 @@ fn F() {
   while (a) {
     if (b) {
       break
-    // CHECK:STDERR: fail_no_semi.carbon:[[@LINE+1]]:5: `break` statements must end with a `;`.
+    // CHECK:STDERR: fail_no_semi.carbon:[[@LINE+3]]:5: `break` statements must end with a `;`.
+    // CHECK:STDERR:     }
+    // CHECK:STDERR:     ^
     }
     if (c) {
       continue
-    // CHECK:STDERR: fail_no_semi.carbon:[[@LINE+1]]:5: `continue` statements must end with a `;`.
+    // CHECK:STDERR: fail_no_semi.carbon:[[@LINE+3]]:5: `continue` statements must end with a `;`.
+    // CHECK:STDERR:     }
+    // CHECK:STDERR:     ^
     }
   }
 }

+ 3 - 1
toolchain/parser/testdata/while/fail_unbraced.carbon

@@ -24,6 +24,8 @@
 
 fn F() {
   while (a)
-    // CHECK:STDERR: fail_unbraced.carbon:[[@LINE+1]]:5: Expected braced code block.
+    // CHECK:STDERR: fail_unbraced.carbon:[[@LINE+3]]:5: Expected braced code block.
+    // CHECK:STDERR:     break;
+    // CHECK:STDERR:     ^
     break;
 }

+ 3 - 1
toolchain/semantics/testdata/basics/fail_name_lookup.carbon

@@ -36,6 +36,8 @@
 // CHECK:STDOUT: ]
 
 fn Main() {
-  // CHECK:STDERR: fail_name_lookup.carbon:[[@LINE+1]]:3: Name x not found
+  // CHECK:STDERR: fail_name_lookup.carbon:[[@LINE+3]]:3: Name x not found
+  // CHECK:STDERR:   x;
+  // CHECK:STDERR:   ^
   x;
 }

+ 3 - 1
toolchain/semantics/testdata/basics/fail_qualifier_unsupported.carbon

@@ -40,5 +40,7 @@
 // CHECK:STDOUT: ]
 
 var x: i32;
-// CHECK:STDERR: fail_qualifier_unsupported.carbon:[[@LINE+1]]:15: Type `i32` does not support qualified expressions.
+// CHECK:STDERR: fail_qualifier_unsupported.carbon:[[@LINE+3]]:15: Type `i32` does not support qualified expressions.
+// CHECK:STDERR: var y: i32 = x.b;
+// CHECK:STDERR:               ^
 var y: i32 = x.b;

+ 36 - 12
toolchain/semantics/testdata/function/call/fail_param_count.carbon

@@ -133,24 +133,48 @@ fn Run1(a: i32) {}
 fn Run2(a: i32, b: i32) {}
 
 fn Main() {
-  // CHECK:STDERR: fail_param_count.carbon:[[@LINE+2]]:7: No matching callable was found.
-  // CHECK:STDERR: fail_param_count.carbon:[[@LINE-6]]:1: Function cannot be used: Received 1 argument(s), but require 0 argument(s).
+  // CHECK:STDERR: fail_param_count.carbon:[[@LINE+6]]:7: No matching callable was found.
+  // CHECK:STDERR:   Run0(1);
+  // CHECK:STDERR:       ^
+  // CHECK:STDERR: fail_param_count.carbon:[[@LINE-8]]:1: Function cannot be used: Received 1 argument(s), but require 0 argument(s).
+  // CHECK:STDERR: fn Run0() {}
+  // CHECK:STDERR: ^
   Run0(1);
-  // CHECK:STDERR: fail_param_count.carbon:[[@LINE+2]]:7: No matching callable was found.
-  // CHECK:STDERR: fail_param_count.carbon:[[@LINE-9]]:1: Function cannot be used: Received 2 argument(s), but require 0 argument(s).
+  // CHECK:STDERR: fail_param_count.carbon:[[@LINE+6]]:7: No matching callable was found.
+  // CHECK:STDERR:   Run0(0, 1);
+  // CHECK:STDERR:       ^
+  // CHECK:STDERR: fail_param_count.carbon:[[@LINE-15]]:1: Function cannot be used: Received 2 argument(s), but require 0 argument(s).
+  // CHECK:STDERR: fn Run0() {}
+  // CHECK:STDERR: ^
   Run0(0, 1);
 
-  // CHECK:STDERR: fail_param_count.carbon:[[@LINE+2]]:7: No matching callable was found.
-  // CHECK:STDERR: fail_param_count.carbon:[[@LINE-12]]:1: Function cannot be used: Received 0 argument(s), but require 1 argument(s).
+  // CHECK:STDERR: fail_param_count.carbon:[[@LINE+6]]:7: No matching callable was found.
+  // CHECK:STDERR:   Run1();
+  // CHECK:STDERR:       ^
+  // CHECK:STDERR: fail_param_count.carbon:[[@LINE-22]]:1: Function cannot be used: Received 0 argument(s), but require 1 argument(s).
+  // CHECK:STDERR: fn Run1(a: i32) {}
+  // CHECK:STDERR: ^
   Run1();
-  // CHECK:STDERR: fail_param_count.carbon:[[@LINE+2]]:7: No matching callable was found.
-  // CHECK:STDERR: fail_param_count.carbon:[[@LINE-15]]:1: Function cannot be used: Received 2 argument(s), but require 1 argument(s).
+  // CHECK:STDERR: fail_param_count.carbon:[[@LINE+6]]:7: No matching callable was found.
+  // CHECK:STDERR:   Run1(0, 1);
+  // CHECK:STDERR:       ^
+  // CHECK:STDERR: fail_param_count.carbon:[[@LINE-29]]:1: Function cannot be used: Received 2 argument(s), but require 1 argument(s).
+  // CHECK:STDERR: fn Run1(a: i32) {}
+  // CHECK:STDERR: ^
   Run1(0, 1);
 
-  // CHECK:STDERR: fail_param_count.carbon:[[@LINE+2]]:7: No matching callable was found.
-  // CHECK:STDERR: fail_param_count.carbon:[[@LINE-18]]:1: Function cannot be used: Received 0 argument(s), but require 2 argument(s).
+  // CHECK:STDERR: fail_param_count.carbon:[[@LINE+6]]:7: No matching callable was found.
+  // CHECK:STDERR:   Run2();
+  // CHECK:STDERR:       ^
+  // CHECK:STDERR: fail_param_count.carbon:[[@LINE-36]]:1: Function cannot be used: Received 0 argument(s), but require 2 argument(s).
+  // CHECK:STDERR: fn Run2(a: i32, b: i32) {}
+  // CHECK:STDERR: ^
   Run2();
-  // CHECK:STDERR: fail_param_count.carbon:[[@LINE+2]]:7: No matching callable was found.
-  // CHECK:STDERR: fail_param_count.carbon:[[@LINE-21]]:1: Function cannot be used: Received 1 argument(s), but require 2 argument(s).
+  // CHECK:STDERR: fail_param_count.carbon:[[@LINE+6]]:7: No matching callable was found.
+  // CHECK:STDERR:   Run2(0);
+  // CHECK:STDERR:       ^
+  // CHECK:STDERR: fail_param_count.carbon:[[@LINE-43]]:1: Function cannot be used: Received 1 argument(s), but require 2 argument(s).
+  // CHECK:STDERR: fn Run2(a: i32, b: i32) {}
+  // CHECK:STDERR: ^
   Run2(0);
 }

+ 6 - 2
toolchain/semantics/testdata/function/call/fail_param_type.carbon

@@ -65,7 +65,11 @@
 fn Run(a: i32) {}
 
 fn Main() {
-  // CHECK:STDERR: fail_param_type.carbon:[[@LINE+2]]:6: No matching callable was found.
-  // CHECK:STDERR: fail_param_type.carbon:[[@LINE-4]]:1: Function cannot be used: Cannot implicityly convert argument 0 from `f64` to `i32`.
+  // CHECK:STDERR: fail_param_type.carbon:[[@LINE+6]]:6: No matching callable was found.
+  // CHECK:STDERR:   Run(1.0);
+  // CHECK:STDERR:      ^
+  // CHECK:STDERR: fail_param_type.carbon:[[@LINE-6]]:1: Function cannot be used: Cannot implicityly convert argument 0 from `f64` to `i32`.
+  // CHECK:STDERR: fn Run(a: i32) {}
+  // CHECK:STDERR: ^
   Run(1.0);
 }

+ 3 - 1
toolchain/semantics/testdata/function/call/fail_return_type_mismatch.carbon

@@ -59,6 +59,8 @@
 fn Foo() -> f64 { return 1.0; }
 
 fn Run() {
-  // CHECK:STDERR: fail_return_type_mismatch.carbon:[[@LINE+1]]:21: Cannot implicitly convert from `f64` to `i32`.
+  // CHECK:STDERR: fail_return_type_mismatch.carbon:[[@LINE+3]]:21: Cannot implicitly convert from `f64` to `i32`.
+  // CHECK:STDERR:   var x: i32 = Foo();
+  // CHECK:STDERR:                     ^
   var x: i32 = Foo();
 }

+ 6 - 2
toolchain/semantics/testdata/function/definition/fail_param_name_conflict.carbon

@@ -50,6 +50,10 @@
 // CHECK:STDOUT:   ],
 // CHECK:STDOUT: ]
 
-// CHECK:STDERR: fail_param_name_conflict.carbon:[[@LINE+2]]:16: Duplicate name being declared in the same scope.
-// CHECK:STDERR: fail_param_name_conflict.carbon:[[@LINE+1]]:8: Name is previously declared here.
+// CHECK:STDERR: fail_param_name_conflict.carbon:[[@LINE+6]]:16: Duplicate name being declared in the same scope.
+// CHECK:STDERR: fn Bar(a: i32, a: i32) {}
+// CHECK:STDERR:                ^
+// CHECK:STDERR: fail_param_name_conflict.carbon:[[@LINE+3]]:8: Name is previously declared here.
+// CHECK:STDERR: fn Bar(a: i32, a: i32) {}
+// CHECK:STDERR:        ^
 fn Bar(a: i32, a: i32) {}

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