Преглед изворни кода

Track the location of the Cpp import for use in Clang diagnostics. (#5783)

When diagnosing a problem with C++ code imported from Carbon, include
the location of the specific `import Cpp` statement that imported the
C++ code as part of the backtrace, rather than providing a location in a
generated file that doesn't exist on disk.

Also fix handling in autoupdate of check lines that contain multiple
file name and line number pairs to use the matched file name for
remapping of locations rather than the first file name in the line.
Richard Smith пре 9 месеци
родитељ
комит
f987504614

+ 36 - 27
testing/file_test/autoupdate.cpp

@@ -43,6 +43,7 @@ FileTestAutoupdater::FileAndLineNumber::FileAndLineNumber(
       line_number(ParseLineNumber(line_number)) {}
 
 auto FileTestAutoupdater::CheckLine::RemapLineNumbers(
+    const llvm::DenseMap<llvm::StringRef, int>& file_to_number_map,
     const llvm::DenseMap<std::pair<int, int>, int>& output_line_remap,
     const llvm::SmallVector<int>& new_last_line_numbers) -> void {
   // Only need to do remappings when there's a line number replacement.
@@ -60,9 +61,10 @@ auto FileTestAutoupdater::CheckLine::RemapLineNumbers(
     line_cursor.remove_prefix(line_offset);
     // Look for a line number to replace. There may be multiple, so we
     // repeatedly check.
+    absl::string_view matched_filename;
     absl::string_view matched_line_number;
     if (replacement_->has_file) {
-      RE2::PartialMatch(line_cursor, *replacement_->re, nullptr,
+      RE2::PartialMatch(line_cursor, *replacement_->re, &matched_filename,
                         &matched_line_number);
     } else {
       RE2::PartialMatch(line_cursor, *replacement_->re, &matched_line_number);
@@ -71,25 +73,31 @@ auto FileTestAutoupdater::CheckLine::RemapLineNumbers(
       return;
     }
 
-    // Update the cursor offset from the match.
-    line_offset = matched_line_number.begin() - line_.c_str();
+    // Map the matched filename to its file number.
+    auto matched_file_number = file_number();
+    if (replacement_->has_file) {
+      auto it = file_to_number_map.find(matched_filename);
+      if (it != file_to_number_map.end()) {
+        matched_file_number = it->second;
+      }
+    }
 
     // Calculate the new line number (possibly with new CHECK lines added, or
     // some removed).
     int old_line_number = ParseLineNumber(matched_line_number);
     int new_line_number = -1;
     if (auto remapped =
-            output_line_remap.find({file_number(), old_line_number});
+            output_line_remap.find({matched_file_number, old_line_number});
         remapped != output_line_remap.end()) {
       // Map old non-check lines to their new line numbers.
       new_line_number = remapped->second;
     } else {
       // We assume unmapped references point to the end-of-file.
-      new_line_number = new_last_line_numbers[file_number()];
+      new_line_number = new_last_line_numbers[matched_file_number];
     }
 
     std::string replacement;
-    if (output_file_number_ == file_number()) {
+    if (matched_file_number == output_file_number_) {
       int offset = new_line_number - output_line_number_;
       // Update the line offset in the CHECK line.
       const char* offset_prefix = offset < 0 ? "" : "+";
@@ -103,8 +111,11 @@ auto FileTestAutoupdater::CheckLine::RemapLineNumbers(
       replacement =
           llvm::formatv(replacement_->line_formatv.c_str(), new_line_number);
     }
-    line_.replace(matched_line_number.data() - line_.data(),
-                  matched_line_number.size(), replacement);
+    auto line_number_offset = matched_line_number.data() - line_.data();
+    line_.replace(line_number_offset, matched_line_number.size(), replacement);
+
+    // Resume matching from the end of the replacement line number.
+    line_offset = line_number_offset + replacement.size();
   }
 }
 
@@ -144,12 +155,6 @@ auto FileTestAutoupdater::BuildCheckLines(llvm::StringRef output,
     return CheckLines({});
   }
 
-  // Prepare to look for filenames in lines.
-  llvm::DenseMap<llvm::StringRef, int> file_to_number_map;
-  for (auto [number, name] : llvm::enumerate(filenames_)) {
-    file_to_number_map.insert({name, number});
-  }
-
   // %t substitution means we may see the temporary directory's path in output.
   std::filesystem::path tmpdir_path = GetTempDirectory();
   llvm::StringRef tmpdir = tmpdir_path.native();
@@ -200,14 +205,14 @@ auto FileTestAutoupdater::BuildCheckLines(llvm::StringRef output,
     if (default_file_re_) {
       absl::string_view filename;
       if (RE2::PartialMatch(line, *default_file_re_, &filename)) {
-        auto it = file_to_number_map.find(filename);
-        CARBON_CHECK(it != file_to_number_map.end(),
+        auto it = file_to_number_map_.find(filename);
+        CARBON_CHECK(it != file_to_number_map_.end(),
                      "default_file_re had unexpected match in '{0}' (`{1}`)",
                      line, default_file_re_->pattern());
         default_file_number = it->second;
       }
     }
-    auto file_and_line = GetFileAndLineNumber(file_to_number_map,
+    auto file_and_line = GetFileAndLineNumber(file_to_number_map_,
                                               default_file_number, check_line);
     check_lines.push_back(CheckLine(file_and_line, check_line));
   }
@@ -241,7 +246,8 @@ auto FileTestAutoupdater::AddTips() -> void {
 
 auto FileTestAutoupdater::ShouldAddCheckLine(const CheckLines& check_lines,
                                              bool to_file_end) const -> bool {
-  return !autoupdate_split_ && check_lines.cursor != check_lines.lines.end() &&
+  return !autoupdate_split_file_ &&
+         check_lines.cursor != check_lines.lines.end() &&
          (check_lines.cursor->file_number() < output_file_number_ ||
           (check_lines.cursor->file_number() == output_file_number_ &&
            (to_file_end || check_lines.cursor->line_number() <=
@@ -318,7 +324,7 @@ auto FileTestAutoupdater::Run(bool dry_run) -> bool {
   // lines after AUTOUPDATE.
   AddRemappedNonCheckLine();
   AddTips();
-  if (!autoupdate_split_) {
+  if (!autoupdate_split_file_) {
     AddCheckLines(stderr_, /*to_file_end=*/false);
     if (any_attached_stdout_lines_) {
       AddCheckLines(stdout_, /*to_file_end=*/false);
@@ -331,8 +337,7 @@ auto FileTestAutoupdater::Run(bool dry_run) -> bool {
     if (output_file_number_ < non_check_line_->file_number()) {
       FinishFile(/*is_last_file=*/false);
       StartSplitFile();
-      if (autoupdate_split_ &&
-          output_file_number_ == static_cast<int>(filenames_.size())) {
+      if (output_file_number_ == autoupdate_split_file_) {
         break;
       }
       continue;
@@ -353,18 +358,22 @@ auto FileTestAutoupdater::Run(bool dry_run) -> bool {
     ++non_check_line_;
   }
 
-  // When autoupdate_split_ was true, this will result in all check lines (and
-  // only check lines) being added to the split by FinishFile. We don't use
-  // autoupdate_split_ past this point.
-  autoupdate_split_ = false;
+  // Clear out the autoupdate split, which would otherwise prevent check lines
+  // being written to the autoupdate file. When autoupdate_split_file_ was set,
+  // this will result in all check lines (and only check lines) being added to
+  // the split by FinishFile. We don't use autoupdate_split_file_ past this
+  // point.
+  autoupdate_split_file_ = std::nullopt;
 
   FinishFile(/*is_last_file=*/true);
 
   for (auto& check_line : stdout_.lines) {
-    check_line.RemapLineNumbers(output_line_remap_, new_last_line_numbers_);
+    check_line.RemapLineNumbers(file_to_number_map_, output_line_remap_,
+                                new_last_line_numbers_);
   }
   for (auto& check_line : stderr_.lines) {
-    check_line.RemapLineNumbers(output_line_remap_, new_last_line_numbers_);
+    check_line.RemapLineNumbers(file_to_number_map_, output_line_remap_,
+                                new_last_line_numbers_);
   }
 
   // Generate the autoupdated file.

+ 21 - 4
testing/file_test/autoupdate.h

@@ -47,13 +47,14 @@ class FileTestAutoupdater {
         test_command_(std::move(test_command)),
         dump_command_(std::move(dump_command)),
         input_content_(input_content),
-        filenames_(filenames),
         autoupdate_line_number_(autoupdate_line_number),
-        autoupdate_split_(autoupdate_split),
         non_check_lines_(non_check_lines),
         default_file_re_(default_file_re),
         line_number_replacements_(line_number_replacements),
         do_extra_check_replacements_(std::move(do_extra_check_replacements)),
+        autoupdate_split_file_(
+            autoupdate_split ? std::optional(filenames.size()) : std::nullopt),
+        file_to_number_map_(BuildFileToNumberMap(filenames)),
         // BuildCheckLines should only be called after other member
         // initialization.
         stdout_(BuildCheckLines(actual_stdout, "STDOUT")),
@@ -132,6 +133,7 @@ class FileTestAutoupdater {
     // When the location of all lines in a file are known, we can set the line
     // offset based on the target line.
     auto RemapLineNumbers(
+        const llvm::DenseMap<llvm::StringRef, int>& file_to_number_map,
         const llvm::DenseMap<std::pair<int, int>, int>& output_line_remap,
         const llvm::SmallVector<int>& new_last_line_numbers) -> void;
 
@@ -163,6 +165,16 @@ class FileTestAutoupdater {
       int default_file_number, const std::string& check_line)
       -> FileAndLineNumber;
 
+  // Builds a mapping from file name to file number.
+  auto BuildFileToNumberMap(const llvm::SmallVector<llvm::StringRef>& filenames)
+      -> llvm::DenseMap<llvm::StringRef, int> {
+    llvm::DenseMap<llvm::StringRef, int> file_to_number_map;
+    for (auto [number, name] : llvm::enumerate(filenames)) {
+      file_to_number_map.insert({name, number});
+    }
+    return file_to_number_map;
+  }
+
   // Builds CheckLine lists for autoupdate.
   auto BuildCheckLines(llvm::StringRef output, const char* label) -> CheckLines;
 
@@ -197,17 +209,22 @@ class FileTestAutoupdater {
   std::string test_command_;
   std::string dump_command_;
   llvm::StringRef input_content_;
-  const llvm::SmallVector<llvm::StringRef>& filenames_;
   int autoupdate_line_number_;
-  bool autoupdate_split_;
   const llvm::SmallVector<FileTestLine>& non_check_lines_;
   const std::optional<RE2>& default_file_re_;
   const llvm::SmallVector<LineNumberReplacement>& line_number_replacements_;
   std::function<auto(std::string&)->void> do_extra_check_replacements_;
 
+  // If we have an autoupdate split that still needs to be processed, the file
+  // number of the autoupdate split. Otherwise, this is nullopt.
+  std::optional<int> autoupdate_split_file_;
+
   // Generated TIP lines, from AddTips.
   llvm::SmallVector<TipLine> tips_;
 
+  // Mapping from file names to file numbers.
+  llvm::DenseMap<llvm::StringRef, int> file_to_number_map_;
+
   // The constructed CheckLine list and cursor.
   CheckLines stdout_;
   CheckLines stderr_;

+ 24 - 0
testing/file_test/testdata/multiple_file_refs_in_line.carbon

@@ -0,0 +1,24 @@
+// Part of the Carbon Language project, under the Apache License v2.0 with LLVM
+// Exceptions. See /LICENSE for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+
+// AUTOUPDATE
+// TIP: To test this file alone, run:
+// TIP:   bazel test //testing/file_test:file_test_base_test --test_arg=--file_tests=testing/file_test/testdata/multiple_file_refs_in_line.carbon
+// TIP: To dump output, run:
+// TIP:   bazel run //testing/file_test:file_test_base_test -- --dump_output --file_tests=testing/file_test/testdata/multiple_file_refs_in_line.carbon
+// CHECK:STDOUT: 3 args: `default_args`, `a.carbon`, `b.carbon`
+
+// --- a.carbon
+a.carbon:1: b.carbon:3: a.carbon:3: hello
+// CHECK:STDOUT: a.carbon:[[@LINE-1]]: a.carbon:[[@LINE-1]]: b.carbon:3: a.carbon:[[@LINE+1]]: hello
+
+// --- b.carbon
+
+
+a.carbon:1: b.carbon:3: a.carbon:3: hello
+// CHECK:STDOUT: b.carbon:[[@LINE-1]]: a.carbon:1: b.carbon:[[@LINE-1]]: a.carbon:3: hello
+a.carbon:1: b.carbon:5: a.carbon:3: hello
+// CHECK:STDOUT: b.carbon:[[@LINE-1]]: a.carbon:1: b.carbon:[[@LINE-1]]: a.carbon:3: hello
+a.carbon:1: b.carbon:7: a.carbon:3: hello
+// CHECK:STDOUT: b.carbon:[[@LINE-1]]: a.carbon:1: b.carbon:[[@LINE-1]]: a.carbon:3: hello

+ 11 - 2
toolchain/check/import_cpp.cpp

@@ -13,6 +13,7 @@
 #include "clang/Frontend/TextDiagnostic.h"
 #include "clang/Sema/Lookup.h"
 #include "clang/Tooling/Tooling.h"
+#include "common/ostream.h"
 #include "common/raw_string_ostream.h"
 #include "llvm/ADT/IntrusiveRefCntPtr.h"
 #include "llvm/ADT/StringRef.h"
@@ -44,6 +45,15 @@ static auto GenerateCppIncludesHeaderCode(
   std::string code;
   llvm::raw_string_ostream code_stream(code);
   for (const Parse::Tree::PackagingNames& import : imports) {
+    // Add a line marker directive pointing at the location of the `import Cpp`
+    // declaration in the Carbon source file. This will cause Clang's
+    // diagnostics machinery to track and report the location in Carbon code
+    // where the import was written.
+    auto token = context.parse_tree().node_token(import.node_id);
+    code_stream << "# " << context.tokens().GetLineNumber(token) << " \""
+                << FormatEscaped(context.tokens().source().filename())
+                << "\"\n";
+
     code_stream << "#include \""
                 << FormatEscaped(
                        context.string_literal_values().Get(import.library_id))
@@ -108,6 +118,7 @@ class CarbonClangDiagnosticConsumer : public clang::DiagnosticConsumer {
     // TODO: Consider allowing setting `DiagnosticOptions` or use
     // `ASTUnit::getDiagnostics().getLangOptions().getDiagnosticOptions()`.
     clang::DiagnosticOptions diagnostic_options;
+    diagnostic_options.ShowPresumedLoc = true;
     clang::TextDiagnostic text_diagnostic(diagnostics_stream, lang_options,
                                           diagnostic_options);
     text_diagnostic.emitDiagnostic(
@@ -139,8 +150,6 @@ class CarbonClangDiagnosticConsumer : public clang::DiagnosticConsumer {
         case clang::DiagnosticsEngine::Warning:
         case clang::DiagnosticsEngine::Error:
         case clang::DiagnosticsEngine::Fatal: {
-          // TODO: Parse the message to select the relevant C++ import and add
-          // that information to the location.
           CARBON_DIAGNOSTIC(CppInteropParseWarning, Warning, "{0}",
                             std::string);
           CARBON_DIAGNOSTIC(CppInteropParseError, Error, "{0}", std::string);

+ 2 - 2
toolchain/check/testdata/interop/cpp/bad_import.carbon

@@ -35,8 +35,8 @@ import Cpp library "";
 library "[[@TEST_NAME]]";
 
 // CHECK:STDERR: fail_import_cpp_library_file_with_quotes.carbon:[[@LINE+6]]:1: in import [InImport]
-// CHECK:STDERR: fail_import_cpp_library_file_with_quotes.carbon.generated.cpp_imports.h:1: error: fail_import_cpp_library_file_with_quotes.carbon.generated.cpp_imports.h:1:10: fatal error: '\"foo.h\"' file not found
-// CHECK:STDERR:     1 | #include "\"foo.h\""
+// CHECK:STDERR: fail_import_cpp_library_file_with_quotes.carbon:[[@LINE+5]]: error: fail_import_cpp_library_file_with_quotes.carbon:[[@LINE+5]]:10: fatal error: '\"foo.h\"' file not found
+// CHECK:STDERR:    10 | #include "\"foo.h\""
 // CHECK:STDERR:       |          ^~~~~~~~~~~
 // CHECK:STDERR:  [CppInteropParseError]
 // CHECK:STDERR:

+ 29 - 29
toolchain/check/testdata/interop/cpp/cpp_diagnostics.carbon

@@ -23,7 +23,7 @@
 library "[[@TEST_NAME]]";
 
 // CHECK:STDERR: fail_import_cpp_file_with_one_error.carbon:[[@LINE+7]]:1: in import [InImport]
-// CHECK:STDERR: ./one_error.h:2: error: In file included from fail_import_cpp_file_with_one_error.carbon.generated.cpp_imports.h:1:
+// CHECK:STDERR: ./one_error.h:2: error: In file included from fail_import_cpp_file_with_one_error.carbon:[[@LINE+6]]:
 // CHECK:STDERR: ./one_error.h:2:2: error: "error1"
 // CHECK:STDERR:     2 | #error "error1"
 // CHECK:STDERR:       |  ^
@@ -45,14 +45,14 @@ import Cpp library "one_error.h";
 library "[[@TEST_NAME]]";
 
 // CHECK:STDERR: fail_import_cpp_file_with_multiple_errors.carbon:[[@LINE+14]]:1: in import [InImport]
-// CHECK:STDERR: ./multiple_errors.h:2: error: In file included from fail_import_cpp_file_with_multiple_errors.carbon.generated.cpp_imports.h:1:
+// CHECK:STDERR: ./multiple_errors.h:2: error: In file included from fail_import_cpp_file_with_multiple_errors.carbon:[[@LINE+13]]:
 // CHECK:STDERR: ./multiple_errors.h:2:2: error: "error1"
 // CHECK:STDERR:     2 | #error "error1"
 // CHECK:STDERR:       |  ^
 // CHECK:STDERR:  [CppInteropParseError]
 // CHECK:STDERR:
 // CHECK:STDERR: fail_import_cpp_file_with_multiple_errors.carbon:[[@LINE+7]]:1: in import [InImport]
-// CHECK:STDERR: ./multiple_errors.h:3: error: In file included from fail_import_cpp_file_with_multiple_errors.carbon.generated.cpp_imports.h:1:
+// CHECK:STDERR: ./multiple_errors.h:3: error: In file included from fail_import_cpp_file_with_multiple_errors.carbon:[[@LINE+6]]:
 // CHECK:STDERR: ./multiple_errors.h:3:2: error: "error2"
 // CHECK:STDERR:     3 | #error "error2"
 // CHECK:STDERR:       |  ^
@@ -74,7 +74,7 @@ library "[[@TEST_NAME]]";
 
 //@dump-sem-ir-begin
 // CHECK:STDERR: import_cpp_file_with_one_warning.carbon:[[@LINE+7]]:1: in import [InImport]
-// CHECK:STDERR: ./one_warning.h:2: warning: In file included from import_cpp_file_with_one_warning.carbon.generated.cpp_imports.h:1:
+// CHECK:STDERR: ./one_warning.h:2: warning: In file included from import_cpp_file_with_one_warning.carbon:[[@LINE+6]]:
 // CHECK:STDERR: ./one_warning.h:2:2: warning: "warning1"
 // CHECK:STDERR:     2 | #warning "warning1"
 // CHECK:STDERR:       |  ^
@@ -99,21 +99,21 @@ library "[[@TEST_NAME]]";
 
 //@dump-sem-ir-begin
 // CHECK:STDERR: import_cpp_file_with_multiple_warnings.carbon:[[@LINE+21]]:1: in import [InImport]
-// CHECK:STDERR: ./multiple_warnings.h:2: warning: In file included from import_cpp_file_with_multiple_warnings.carbon.generated.cpp_imports.h:1:
+// CHECK:STDERR: ./multiple_warnings.h:2: warning: In file included from import_cpp_file_with_multiple_warnings.carbon:[[@LINE+20]]:
 // CHECK:STDERR: ./multiple_warnings.h:2:2: warning: "warning1"
 // CHECK:STDERR:     2 | #warning "warning1"
 // CHECK:STDERR:       |  ^
 // CHECK:STDERR:  [CppInteropParseWarning]
 // CHECK:STDERR:
 // CHECK:STDERR: import_cpp_file_with_multiple_warnings.carbon:[[@LINE+14]]:1: in import [InImport]
-// CHECK:STDERR: ./multiple_warnings.h:3: warning: In file included from import_cpp_file_with_multiple_warnings.carbon.generated.cpp_imports.h:1:
+// CHECK:STDERR: ./multiple_warnings.h:3: warning: In file included from import_cpp_file_with_multiple_warnings.carbon:[[@LINE+13]]:
 // CHECK:STDERR: ./multiple_warnings.h:3:2: warning: "warning2"
 // CHECK:STDERR:     3 | #warning "warning2"
 // CHECK:STDERR:       |  ^
 // CHECK:STDERR:  [CppInteropParseWarning]
 // CHECK:STDERR:
 // CHECK:STDERR: import_cpp_file_with_multiple_warnings.carbon:[[@LINE+7]]:1: in import [InImport]
-// CHECK:STDERR: ./multiple_warnings.h:4: warning: In file included from import_cpp_file_with_multiple_warnings.carbon.generated.cpp_imports.h:1:
+// CHECK:STDERR: ./multiple_warnings.h:4: warning: In file included from import_cpp_file_with_multiple_warnings.carbon:[[@LINE+6]]:
 // CHECK:STDERR: ./multiple_warnings.h:4:2: warning: "warning3"
 // CHECK:STDERR:     4 | #warning "warning3"
 // CHECK:STDERR:       |  ^
@@ -136,14 +136,14 @@ import Cpp library "multiple_warnings.h";
 library "[[@TEST_NAME]]";
 
 // CHECK:STDERR: fail_import_cpp_file_with_one_error_and_one_warning.carbon:[[@LINE+14]]:1: in import [InImport]
-// CHECK:STDERR: ./one_error_and_one_warning.h:2: error: In file included from fail_import_cpp_file_with_one_error_and_one_warning.carbon.generated.cpp_imports.h:1:
+// CHECK:STDERR: ./one_error_and_one_warning.h:2: error: In file included from fail_import_cpp_file_with_one_error_and_one_warning.carbon:[[@LINE+13]]:
 // CHECK:STDERR: ./one_error_and_one_warning.h:2:2: error: "error1"
 // CHECK:STDERR:     2 | #error "error1"
 // CHECK:STDERR:       |  ^
 // CHECK:STDERR:  [CppInteropParseError]
 // CHECK:STDERR:
 // CHECK:STDERR: fail_import_cpp_file_with_one_error_and_one_warning.carbon:[[@LINE+7]]:1: in import [InImport]
-// CHECK:STDERR: ./one_error_and_one_warning.h:3: warning: In file included from fail_import_cpp_file_with_one_error_and_one_warning.carbon.generated.cpp_imports.h:1:
+// CHECK:STDERR: ./one_error_and_one_warning.h:3: warning: In file included from fail_import_cpp_file_with_one_error_and_one_warning.carbon:[[@LINE+6]]:
 // CHECK:STDERR: ./one_error_and_one_warning.h:3:2: warning: "warning1"
 // CHECK:STDERR:     3 | #warning "warning1"
 // CHECK:STDERR:       |  ^
@@ -168,35 +168,35 @@ import Cpp library "one_error_and_one_warning.h";
 library "[[@TEST_NAME]]";
 
 // CHECK:STDERR: fail_import_cpp_file_with_multiple_errors_and_multiple_warnings.carbon:[[@LINE+35]]:1: in import [InImport]
-// CHECK:STDERR: ./multiple_errors_and_multiple_warnings.h:2: error: In file included from fail_import_cpp_file_with_multiple_errors_and_multiple_warnings.carbon.generated.cpp_imports.h:1:
+// CHECK:STDERR: ./multiple_errors_and_multiple_warnings.h:2: error: In file included from fail_import_cpp_file_with_multiple_errors_and_multiple_warnings.carbon:[[@LINE+34]]:
 // CHECK:STDERR: ./multiple_errors_and_multiple_warnings.h:2:2: error: "error1"
 // CHECK:STDERR:     2 | #error "error1"
 // CHECK:STDERR:       |  ^
 // CHECK:STDERR:  [CppInteropParseError]
 // CHECK:STDERR:
 // CHECK:STDERR: fail_import_cpp_file_with_multiple_errors_and_multiple_warnings.carbon:[[@LINE+28]]:1: in import [InImport]
-// CHECK:STDERR: ./multiple_errors_and_multiple_warnings.h:3: error: In file included from fail_import_cpp_file_with_multiple_errors_and_multiple_warnings.carbon.generated.cpp_imports.h:1:
+// CHECK:STDERR: ./multiple_errors_and_multiple_warnings.h:3: error: In file included from fail_import_cpp_file_with_multiple_errors_and_multiple_warnings.carbon:[[@LINE+27]]:
 // CHECK:STDERR: ./multiple_errors_and_multiple_warnings.h:3:2: error: "error2"
 // CHECK:STDERR:     3 | #error "error2"
 // CHECK:STDERR:       |  ^
 // CHECK:STDERR:  [CppInteropParseError]
 // CHECK:STDERR:
 // CHECK:STDERR: fail_import_cpp_file_with_multiple_errors_and_multiple_warnings.carbon:[[@LINE+21]]:1: in import [InImport]
-// CHECK:STDERR: ./multiple_errors_and_multiple_warnings.h:4: warning: In file included from fail_import_cpp_file_with_multiple_errors_and_multiple_warnings.carbon.generated.cpp_imports.h:1:
+// CHECK:STDERR: ./multiple_errors_and_multiple_warnings.h:4: warning: In file included from fail_import_cpp_file_with_multiple_errors_and_multiple_warnings.carbon:[[@LINE+20]]:
 // CHECK:STDERR: ./multiple_errors_and_multiple_warnings.h:4:2: warning: "warning1"
 // CHECK:STDERR:     4 | #warning "warning1"
 // CHECK:STDERR:       |  ^
 // CHECK:STDERR:  [CppInteropParseWarning]
 // CHECK:STDERR:
 // CHECK:STDERR: fail_import_cpp_file_with_multiple_errors_and_multiple_warnings.carbon:[[@LINE+14]]:1: in import [InImport]
-// CHECK:STDERR: ./multiple_errors_and_multiple_warnings.h:5: warning: In file included from fail_import_cpp_file_with_multiple_errors_and_multiple_warnings.carbon.generated.cpp_imports.h:1:
+// CHECK:STDERR: ./multiple_errors_and_multiple_warnings.h:5: warning: In file included from fail_import_cpp_file_with_multiple_errors_and_multiple_warnings.carbon:[[@LINE+13]]:
 // CHECK:STDERR: ./multiple_errors_and_multiple_warnings.h:5:2: warning: "warning2"
 // CHECK:STDERR:     5 | #warning "warning2"
 // CHECK:STDERR:       |  ^
 // CHECK:STDERR:  [CppInteropParseWarning]
 // CHECK:STDERR:
 // CHECK:STDERR: fail_import_cpp_file_with_multiple_errors_and_multiple_warnings.carbon:[[@LINE+7]]:1: in import [InImport]
-// CHECK:STDERR: ./multiple_errors_and_multiple_warnings.h:6: warning: In file included from fail_import_cpp_file_with_multiple_errors_and_multiple_warnings.carbon.generated.cpp_imports.h:1:
+// CHECK:STDERR: ./multiple_errors_and_multiple_warnings.h:6: warning: In file included from fail_import_cpp_file_with_multiple_errors_and_multiple_warnings.carbon:[[@LINE+6]]:
 // CHECK:STDERR: ./multiple_errors_and_multiple_warnings.h:6:2: warning: "warning3"
 // CHECK:STDERR:     6 | #warning "warning3"
 // CHECK:STDERR:       |  ^
@@ -214,28 +214,28 @@ library "[[@TEST_NAME]]";
 
 //@dump-sem-ir-begin
 // CHECK:STDERR: import_multiple_cpp_files_with_warnings.carbon:[[@LINE+28]]:1: in import [InImport]
-// CHECK:STDERR: ./one_warning.h:2: warning: In file included from import_multiple_cpp_files_with_warnings.carbon.generated.cpp_imports.h:1:
+// CHECK:STDERR: ./one_warning.h:2: warning: In file included from import_multiple_cpp_files_with_warnings.carbon:[[@LINE+27]]:
 // CHECK:STDERR: ./one_warning.h:2:2: warning: "warning1"
 // CHECK:STDERR:     2 | #warning "warning1"
 // CHECK:STDERR:       |  ^
 // CHECK:STDERR:  [CppInteropParseWarning]
 // CHECK:STDERR:
 // CHECK:STDERR: import_multiple_cpp_files_with_warnings.carbon:[[@LINE+21]]:1: in import [InImport]
-// CHECK:STDERR: ./multiple_warnings.h:2: warning: In file included from import_multiple_cpp_files_with_warnings.carbon.generated.cpp_imports.h:2:
+// CHECK:STDERR: ./multiple_warnings.h:2: warning: In file included from import_multiple_cpp_files_with_warnings.carbon:[[@LINE+21]]:
 // CHECK:STDERR: ./multiple_warnings.h:2:2: warning: "warning1"
 // CHECK:STDERR:     2 | #warning "warning1"
 // CHECK:STDERR:       |  ^
 // CHECK:STDERR:  [CppInteropParseWarning]
 // CHECK:STDERR:
 // CHECK:STDERR: import_multiple_cpp_files_with_warnings.carbon:[[@LINE+14]]:1: in import [InImport]
-// CHECK:STDERR: ./multiple_warnings.h:3: warning: In file included from import_multiple_cpp_files_with_warnings.carbon.generated.cpp_imports.h:2:
+// CHECK:STDERR: ./multiple_warnings.h:3: warning: In file included from import_multiple_cpp_files_with_warnings.carbon:[[@LINE+14]]:
 // CHECK:STDERR: ./multiple_warnings.h:3:2: warning: "warning2"
 // CHECK:STDERR:     3 | #warning "warning2"
 // CHECK:STDERR:       |  ^
 // CHECK:STDERR:  [CppInteropParseWarning]
 // CHECK:STDERR:
 // CHECK:STDERR: import_multiple_cpp_files_with_warnings.carbon:[[@LINE+7]]:1: in import [InImport]
-// CHECK:STDERR: ./multiple_warnings.h:4: warning: In file included from import_multiple_cpp_files_with_warnings.carbon.generated.cpp_imports.h:2:
+// CHECK:STDERR: ./multiple_warnings.h:4: warning: In file included from import_multiple_cpp_files_with_warnings.carbon:[[@LINE+7]]:
 // CHECK:STDERR: ./multiple_warnings.h:4:2: warning: "warning3"
 // CHECK:STDERR:     4 | #warning "warning3"
 // CHECK:STDERR:       |  ^
@@ -254,49 +254,49 @@ import Cpp library "multiple_warnings.h";
 library "[[@TEST_NAME]]";
 
 // CHECK:STDERR: fail_import_multiple_cpp_files_with_errors_and_warnings.carbon:[[@LINE+49]]:1: in import [InImport]
-// CHECK:STDERR: ./one_error_and_one_warning.h:2: error: In file included from fail_import_multiple_cpp_files_with_errors_and_warnings.carbon.generated.cpp_imports.h:1:
+// CHECK:STDERR: ./one_error_and_one_warning.h:2: error: In file included from fail_import_multiple_cpp_files_with_errors_and_warnings.carbon:[[@LINE+48]]:
 // CHECK:STDERR: ./one_error_and_one_warning.h:2:2: error: "error1"
 // CHECK:STDERR:     2 | #error "error1"
 // CHECK:STDERR:       |  ^
 // CHECK:STDERR:  [CppInteropParseError]
 // CHECK:STDERR:
 // CHECK:STDERR: fail_import_multiple_cpp_files_with_errors_and_warnings.carbon:[[@LINE+42]]:1: in import [InImport]
-// CHECK:STDERR: ./one_error_and_one_warning.h:3: warning: In file included from fail_import_multiple_cpp_files_with_errors_and_warnings.carbon.generated.cpp_imports.h:1:
+// CHECK:STDERR: ./one_error_and_one_warning.h:3: warning: In file included from fail_import_multiple_cpp_files_with_errors_and_warnings.carbon:[[@LINE+41]]:
 // CHECK:STDERR: ./one_error_and_one_warning.h:3:2: warning: "warning1"
 // CHECK:STDERR:     3 | #warning "warning1"
 // CHECK:STDERR:       |  ^
 // CHECK:STDERR:  [CppInteropParseWarning]
 // CHECK:STDERR:
 // CHECK:STDERR: fail_import_multiple_cpp_files_with_errors_and_warnings.carbon:[[@LINE+35]]:1: in import [InImport]
-// CHECK:STDERR: ./multiple_errors_and_multiple_warnings.h:2: error: In file included from fail_import_multiple_cpp_files_with_errors_and_warnings.carbon.generated.cpp_imports.h:2:
+// CHECK:STDERR: ./multiple_errors_and_multiple_warnings.h:2: error: In file included from fail_import_multiple_cpp_files_with_errors_and_warnings.carbon:[[@LINE+35]]:
 // CHECK:STDERR: ./multiple_errors_and_multiple_warnings.h:2:2: error: "error1"
 // CHECK:STDERR:     2 | #error "error1"
 // CHECK:STDERR:       |  ^
 // CHECK:STDERR:  [CppInteropParseError]
 // CHECK:STDERR:
 // CHECK:STDERR: fail_import_multiple_cpp_files_with_errors_and_warnings.carbon:[[@LINE+28]]:1: in import [InImport]
-// CHECK:STDERR: ./multiple_errors_and_multiple_warnings.h:3: error: In file included from fail_import_multiple_cpp_files_with_errors_and_warnings.carbon.generated.cpp_imports.h:2:
+// CHECK:STDERR: ./multiple_errors_and_multiple_warnings.h:3: error: In file included from fail_import_multiple_cpp_files_with_errors_and_warnings.carbon:[[@LINE+28]]:
 // CHECK:STDERR: ./multiple_errors_and_multiple_warnings.h:3:2: error: "error2"
 // CHECK:STDERR:     3 | #error "error2"
 // CHECK:STDERR:       |  ^
 // CHECK:STDERR:  [CppInteropParseError]
 // CHECK:STDERR:
 // CHECK:STDERR: fail_import_multiple_cpp_files_with_errors_and_warnings.carbon:[[@LINE+21]]:1: in import [InImport]
-// CHECK:STDERR: ./multiple_errors_and_multiple_warnings.h:4: warning: In file included from fail_import_multiple_cpp_files_with_errors_and_warnings.carbon.generated.cpp_imports.h:2:
+// CHECK:STDERR: ./multiple_errors_and_multiple_warnings.h:4: warning: In file included from fail_import_multiple_cpp_files_with_errors_and_warnings.carbon:[[@LINE+21]]:
 // CHECK:STDERR: ./multiple_errors_and_multiple_warnings.h:4:2: warning: "warning1"
 // CHECK:STDERR:     4 | #warning "warning1"
 // CHECK:STDERR:       |  ^
 // CHECK:STDERR:  [CppInteropParseWarning]
 // CHECK:STDERR:
 // CHECK:STDERR: fail_import_multiple_cpp_files_with_errors_and_warnings.carbon:[[@LINE+14]]:1: in import [InImport]
-// CHECK:STDERR: ./multiple_errors_and_multiple_warnings.h:5: warning: In file included from fail_import_multiple_cpp_files_with_errors_and_warnings.carbon.generated.cpp_imports.h:2:
+// CHECK:STDERR: ./multiple_errors_and_multiple_warnings.h:5: warning: In file included from fail_import_multiple_cpp_files_with_errors_and_warnings.carbon:[[@LINE+14]]:
 // CHECK:STDERR: ./multiple_errors_and_multiple_warnings.h:5:2: warning: "warning2"
 // CHECK:STDERR:     5 | #warning "warning2"
 // CHECK:STDERR:       |  ^
 // CHECK:STDERR:  [CppInteropParseWarning]
 // CHECK:STDERR:
 // CHECK:STDERR: fail_import_multiple_cpp_files_with_errors_and_warnings.carbon:[[@LINE+7]]:1: in import [InImport]
-// CHECK:STDERR: ./multiple_errors_and_multiple_warnings.h:6: warning: In file included from fail_import_multiple_cpp_files_with_errors_and_warnings.carbon.generated.cpp_imports.h:2:
+// CHECK:STDERR: ./multiple_errors_and_multiple_warnings.h:6: warning: In file included from fail_import_multiple_cpp_files_with_errors_and_warnings.carbon:[[@LINE+7]]:
 // CHECK:STDERR: ./multiple_errors_and_multiple_warnings.h:6:2: warning: "warning3"
 // CHECK:STDERR:     6 | #warning "warning3"
 // CHECK:STDERR:       |  ^
@@ -320,7 +320,7 @@ library "[[@TEST_NAME]]";
 // TODO: The `In file included from` line should not be prefixed. See
 // https://github.com/carbon-language/carbon-lang/pull/5614#pullrequestreview-2900939411
 // CHECK:STDERR: fail_todo_import_indirect_error.carbon:[[@LINE+8]]:1: in import [InImport]
-// CHECK:STDERR: ./one_error.h:2: error: In file included from fail_todo_import_indirect_error.carbon.generated.cpp_imports.h:1:
+// CHECK:STDERR: ./one_error.h:2: error: In file included from fail_todo_import_indirect_error.carbon:[[@LINE+7]]:
 // CHECK:STDERR: In file included from ./indirect_error.h:2:
 // CHECK:STDERR: ./one_error.h:2:2: error: "error1"
 // CHECK:STDERR:     2 | #error "error1"
@@ -345,7 +345,7 @@ library "[[@TEST_NAME]]";
 // https://github.com/carbon-language/carbon-lang/pull/5614#pullrequestreview-2900939411
 //@dump-sem-ir-begin
 // CHECK:STDERR: todo_import_indirect_warning.carbon:[[@LINE+8]]:1: in import [InImport]
-// CHECK:STDERR: ./one_warning.h:2: warning: In file included from todo_import_indirect_warning.carbon.generated.cpp_imports.h:1:
+// CHECK:STDERR: ./one_warning.h:2: warning: In file included from todo_import_indirect_warning.carbon:[[@LINE+7]]:
 // CHECK:STDERR: In file included from ./indirect_warning.h:2:
 // CHECK:STDERR: ./one_warning.h:2:2: warning: "warning1"
 // CHECK:STDERR:     2 | #warning "warning1"
@@ -365,7 +365,7 @@ library "[[@TEST_NAME]]";  // Trailing comment
 
 // TODO: Move this warning to be after the lexer trailing comment error.
 // CHECK:STDERR: fail_import_cpp_library_lexer_error.carbon:[[@LINE+11]]:1: in import [InImport]
-// CHECK:STDERR: ./one_warning.h:2: warning: In file included from fail_import_cpp_library_lexer_error.carbon.generated.cpp_imports.h:1:
+// CHECK:STDERR: ./one_warning.h:2: warning: In file included from fail_import_cpp_library_lexer_error.carbon:[[@LINE+10]]:
 // CHECK:STDERR: ./one_warning.h:2:2: warning: "warning1"
 // CHECK:STDERR:     2 | #warning "warning1"
 // CHECK:STDERR:       |  ^
@@ -390,7 +390,7 @@ double score = 0.1
 library "[[@TEST_NAME]]";
 
 // CHECK:STDERR: fail_import_fix_it_hints.carbon:[[@LINE+8]]:1: in import [InImport]
-// CHECK:STDERR: ./fix_it_hints.h:2: error: In file included from fail_import_fix_it_hints.carbon.generated.cpp_imports.h:1:
+// CHECK:STDERR: ./fix_it_hints.h:2: error: In file included from fail_import_fix_it_hints.carbon:[[@LINE+7]]:
 // CHECK:STDERR: ./fix_it_hints.h:2:19: error: expected ';' after top level declarator
 // CHECK:STDERR:     2 | double score = 0.1
 // CHECK:STDERR:       |                   ^

+ 2 - 2
toolchain/check/testdata/interop/cpp/file_not_found.carbon

@@ -15,8 +15,8 @@
 library "[[@TEST_NAME]]";
 
 // CHECK:STDERR: fail_cpp_file_not_found.carbon:[[@LINE+6]]:1: in import [InImport]
-// CHECK:STDERR: fail_cpp_file_not_found.carbon.generated.cpp_imports.h:1: error: fail_cpp_file_not_found.carbon.generated.cpp_imports.h:1:10: fatal error: 'not_found.h' file not found
-// CHECK:STDERR:     1 | #include "not_found.h"
+// CHECK:STDERR: fail_cpp_file_not_found.carbon:[[@LINE+5]]: error: fail_cpp_file_not_found.carbon:[[@LINE+5]]:10: fatal error: 'not_found.h' file not found
+// CHECK:STDERR:    10 | #include "not_found.h"
 // CHECK:STDERR:       |          ^~~~~~~~~~~~~
 // CHECK:STDERR:  [CppInteropParseError]
 // CHECK:STDERR: