Przeglądaj źródła

Use `InImport` pointing to C++ imports in `ConvertLocInFile()` instead of adding a separate `InCppImport` when emitting (#5614)

I believe we will need to eventually add the specific C++ import
information in `LocId`.

This also seems to fix the `LanguageServerDiagnosticInWrongFile` issue
(#5604).

We're still not in the state we want to be according to
https://github.com/carbon-language/carbon-lang/pull/5246#issuecomment-2784301206.
Will look into removing the location part from the `"In file included
from ..."` line.

Part of #5245.
Boaz Brickner 10 miesięcy temu
rodzic
commit
ec97ec9664

+ 31 - 8
toolchain/check/diagnostic_emitter.cpp

@@ -11,6 +11,7 @@
 #include "common/raw_string_ostream.h"
 #include "toolchain/check/diagnostic_helpers.h"
 #include "toolchain/sem_ir/absolute_node_id.h"
+#include "toolchain/sem_ir/ids.h"
 #include "toolchain/sem_ir/stringify.h"
 
 namespace Carbon::Check {
@@ -55,8 +56,7 @@ auto DiagnosticEmitter::ConvertLocImpl(SemIR::LocId loc_id, bool is_token_only,
     // TODO: Include the name of the imported library in the diagnostic.
     auto diag_loc =
         ConvertLocInFile(absolute_node_id, is_token_only, context_fn);
-    CARBON_DIAGNOSTIC(InImport, LocationInfo, "in import");
-    context_fn(diag_loc.loc, InImport);
+    AddInImport(diag_loc.loc, context_fn);
   }
 
   return ConvertLocInFile(final_node_id, is_token_only, context_fn);
@@ -64,12 +64,21 @@ auto DiagnosticEmitter::ConvertLocImpl(SemIR::LocId loc_id, bool is_token_only,
 
 auto DiagnosticEmitter::ConvertLocInFile(SemIR::AbsoluteNodeId absolute_node_id,
                                          bool token_only,
-                                         ContextFnT /*context_fn*/) const
+                                         ContextFnT context_fn) const
     -> Diagnostics::ConvertedLoc {
   if (absolute_node_id.check_ir_id() == SemIR::CheckIRId::Cpp) {
     // Special handling of Clang source locations.
-    // TODO: Refactor to add an `InImport` pointing at the `Cpp` import, and
-    // eliminate `InCppImport`.
+    CARBON_CHECK(sem_ir_->import_cpps().size() > 0);
+    // TODO: Use information on the specific C++ import extract from Clang error
+    // message and propagated here instead of using first C++ import
+    // arbitrarily.
+    Parse::NodeId import_node_id =
+        sem_ir_->import_cpps().values().begin()->node_id;
+    AddInImport(ConvertLocInCarbonFile(sem_ir_->check_ir_id(), import_node_id,
+                                       /*token_only=*/false)
+                    .loc,
+                context_fn);
+
     clang::SourceLocation clang_loc = sem_ir_->clang_source_locs().Get(
         absolute_node_id.clang_source_loc_id());
 
@@ -84,10 +93,18 @@ auto DiagnosticEmitter::ConvertLocInFile(SemIR::AbsoluteNodeId absolute_node_id,
         .last_byte_offset = 0};
   }
 
+  return ConvertLocInCarbonFile(absolute_node_id.check_ir_id(),
+                                absolute_node_id.node_id(), token_only);
+}
+
+auto DiagnosticEmitter::ConvertLocInCarbonFile(SemIR::CheckIRId check_ir_id,
+                                               Parse::NodeId node_id,
+                                               bool token_only) const
+    -> Diagnostics::ConvertedLoc {
+  CARBON_CHECK(check_ir_id != SemIR::CheckIRId::Cpp);
   const auto& tree_and_subtrees =
-      tree_and_subtrees_getters_[absolute_node_id.check_ir_id().index]();
-  return tree_and_subtrees.NodeToDiagnosticLoc(absolute_node_id.node_id(),
-                                               token_only);
+      tree_and_subtrees_getters_[check_ir_id.index]();
+  return tree_and_subtrees.NodeToDiagnosticLoc(node_id, token_only);
 }
 
 auto DiagnosticEmitter::ConvertArg(llvm::Any arg) const -> llvm::Any {
@@ -161,4 +178,10 @@ auto DiagnosticEmitter::ConvertArg(llvm::Any arg) const -> llvm::Any {
   return DiagnosticEmitterBase::ConvertArg(arg);
 }
 
+auto DiagnosticEmitter::AddInImport(Diagnostics::Loc loc, ContextFnT context_fn)
+    -> void {
+  CARBON_DIAGNOSTIC(InImport, LocationInfo, "in import");
+  context_fn(loc, InImport);
+}
+
 }  // namespace Carbon::Check

+ 11 - 2
toolchain/check/diagnostic_emitter.h

@@ -51,12 +51,21 @@ class DiagnosticEmitter : public DiagnosticEmitterBase {
   auto ConvertLocImpl(SemIR::LocId loc_id, bool is_token_only,
                       ContextFnT context_fn) const -> Diagnostics::ConvertedLoc;
 
-  // Converts a node_id corresponding to a specific sem_ir to a diagnostic
-  // location.
+  // Converts an `absolute_node_id` in either a Carbon file or C++ import to a
+  // diagnostic location.
   auto ConvertLocInFile(SemIR::AbsoluteNodeId absolute_node_id, bool token_only,
                         ContextFnT context_fn) const
       -> Diagnostics::ConvertedLoc;
 
+  // Converts a `node_id` corresponding to a specific sem_ir to a diagnostic
+  // location.
+  auto ConvertLocInCarbonFile(SemIR::CheckIRId check_ir_id,
+                              Parse::NodeId node_id, bool token_only) const
+      -> Diagnostics::ConvertedLoc;
+
+  // Adds `in import` note.
+  static auto AddInImport(Diagnostics::Loc loc, ContextFnT context_fn) -> void;
+
   // Converters for each SemIR.
   llvm::ArrayRef<Parse::GetTreeAndSubtreesFn> tree_and_subtrees_getters_;
 

+ 17 - 29
toolchain/check/import_cpp.cpp

@@ -68,8 +68,8 @@ class CarbonClangDiagnosticConsumer : public clang::DiagnosticConsumer {
  public:
   // Creates an instance with the location that triggers calling Clang.
   // `context` must not be null.
-  explicit CarbonClangDiagnosticConsumer(Context* context, SemIR::LocId loc_id)
-      : context_(context), loc_id_(loc_id) {}
+  explicit CarbonClangDiagnosticConsumer(Context* context)
+      : context_(context) {}
 
   // Generates a Carbon warning for each Clang warning and a Carbon error for
   // each Clang error or fatal.
@@ -121,23 +121,17 @@ class CarbonClangDiagnosticConsumer : public clang::DiagnosticConsumer {
         case clang::DiagnosticsEngine::Warning:
         case clang::DiagnosticsEngine::Error:
         case clang::DiagnosticsEngine::Fatal: {
-          // TODO: Adjust diagnostics to drop the Carbon file here, and then
-          // remove the "C++:\n" prefix.
-          CARBON_DIAGNOSTIC(CppInteropParseWarning, Warning, "C++:\n{0}",
+          // 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, "C++:\n{0}",
-                            std::string);
-          // TODO: This should be part of the location, instead of added as a
-          // note here.
-          CARBON_DIAGNOSTIC(InCppImport, Note, "in `Cpp` import");
-          context_->emitter()
-              .Build(SemIR::LocId(info.import_ir_inst_id),
-                     info.level == clang::DiagnosticsEngine::Warning
-                         ? CppInteropParseWarning
-                         : CppInteropParseError,
-                     info.message)
-              .Note(loc_id_, InCppImport)
-              .Emit();
+          CARBON_DIAGNOSTIC(CppInteropParseError, Error, "{0}", std::string);
+          context_->emitter().Emit(
+              SemIR::LocId(info.import_ir_inst_id),
+              info.level == clang::DiagnosticsEngine::Warning
+                  ? CppInteropParseWarning
+                  : CppInteropParseError,
+              info.message);
           break;
         }
       }
@@ -148,9 +142,6 @@ class CarbonClangDiagnosticConsumer : public clang::DiagnosticConsumer {
   // The type-checking context in which we're running Clang.
   Context* context_;
 
-  // The location that triggered calling Clang.
-  SemIR::LocId loc_id_;
-
   // Information on a Clang diagnostic that can be converted to a Carbon
   // diagnostic.
   struct ClangDiagnosticInfo {
@@ -182,11 +173,7 @@ static auto GenerateAst(Context& context, llvm::StringRef importing_file_path,
                         llvm::IntrusiveRefCntPtr<llvm::vfs::FileSystem> fs,
                         llvm::StringRef target)
     -> std::pair<std::unique_ptr<clang::ASTUnit>, bool> {
-  // TODO: Use all import locations by referring each Clang diagnostic to the
-  // relevant import.
-  SemIR::LocId loc_id = imports.back().node_id;
-
-  CarbonClangDiagnosticConsumer diagnostics_consumer(&context, loc_id);
+  CarbonClangDiagnosticConsumer diagnostics_consumer(&context);
 
   // TODO: Share compilation flags with ClangRunner.
   auto ast = clang::tooling::buildASTFromCodeWithArgs(
@@ -253,15 +240,16 @@ auto ImportCppFiles(Context& context, llvm::StringRef importing_file_path,
 
   CARBON_CHECK(!context.sem_ir().cpp_ast());
 
-  auto [generated_ast, ast_has_error] =
-      GenerateAst(context, importing_file_path, imports, fs, target);
-
   PackageNameId package_id = imports.front().package_id;
   CARBON_CHECK(
       llvm::all_of(imports, [&](const Parse::Tree::PackagingNames& import) {
         return import.package_id == package_id;
       }));
   auto name_scope_id = AddNamespace(context, package_id, imports);
+
+  auto [generated_ast, ast_has_error] =
+      GenerateAst(context, importing_file_path, imports, fs, target);
+
   SemIR::NameScope& name_scope = context.name_scopes().Get(name_scope_id);
   name_scope.set_is_closed_import(true);
   name_scope.set_cpp_decl_context(

+ 6 - 9
toolchain/check/testdata/interop/cpp/bad_import.carbon

@@ -25,24 +25,21 @@ import Cpp;
 
 library "[[@TEST_NAME]]";
 
-// CHECK:STDERR: fail_import_cpp_library_empty.carbon:[[@LINE+9]]:1: error: `Cpp` import missing library [CppInteropMissingLibrary]
+// CHECK:STDERR: fail_import_cpp_library_empty.carbon:[[@LINE+4]]:1: error: `Cpp` import missing library [CppInteropMissingLibrary]
 // CHECK:STDERR: import Cpp library "";
 // CHECK:STDERR: ^~~~~~~~~~~~~~~~~~~~~~
 // CHECK:STDERR:
-// CHECK:STDERR: fail_import_cpp_library_file_with_quotes.carbon.generated.cpp_imports.h:1: error: C++:
-// CHECK:STDERR: 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:       |          ^~~~~~~~~~~
-// CHECK:STDERR:  [CppInteropParseError]
 import Cpp library "";
 
 // --- fail_import_cpp_library_file_with_quotes.carbon
 
 library "[[@TEST_NAME]]";
 
-// CHECK:STDERR: fail_import_cpp_library_file_with_quotes.carbon:[[@LINE+4]]:1: note: in `Cpp` import [InCppImport]
-// CHECK:STDERR: import Cpp library "\"foo.h\"";
-// CHECK:STDERR: ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+// 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:       |          ^~~~~~~~~~~
+// CHECK:STDERR:  [CppInteropParseError]
 // CHECK:STDERR:
 import Cpp library "\"foo.h\"";
 

+ 153 - 236
toolchain/check/testdata/interop/cpp/cpp_diagnostics.carbon

@@ -17,21 +17,18 @@
 
 // --- one_error.h
 
-// CHECK:STDERR: ./one_error.h:[[@LINE+6]]: error: C++:
-// CHECK:STDERR: In file included from fail_import_cpp_file_with_one_error.carbon.generated.cpp_imports.h:1:
-// CHECK:STDERR: ./one_error.h:[[@LINE+4]]:2: error: "error1"
-// CHECK:STDERR:     8 | #error "error1"
-// CHECK:STDERR:       |  ^
-// CHECK:STDERR:  [CppInteropParseError]
 #error "error1"
 
 // --- fail_import_cpp_file_with_one_error.carbon
 
 library "[[@TEST_NAME]]";
 
-// CHECK:STDERR: fail_import_cpp_file_with_one_error.carbon:[[@LINE+4]]:1: note: in `Cpp` import [InCppImport]
-// CHECK:STDERR: import Cpp library "one_error.h";
-// CHECK:STDERR: ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+// 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:2: error: "error1"
+// CHECK:STDERR:     2 | #error "error1"
+// CHECK:STDERR:       |  ^
+// CHECK:STDERR:  [CppInteropParseError]
 // CHECK:STDERR:
 import Cpp library "one_error.h";
 
@@ -41,12 +38,6 @@ import Cpp library "one_error.h";
 
 // --- multiple_errors.h
 
-// CHECK:STDERR: ./multiple_errors.h:[[@LINE+6]]: error: C++:
-// CHECK:STDERR: In file included from fail_import_cpp_file_with_multiple_errors.carbon.generated.cpp_imports.h:1:
-// CHECK:STDERR: ./multiple_errors.h:[[@LINE+4]]:2: error: "error1"
-// CHECK:STDERR:     8 | #error "error1"
-// CHECK:STDERR:       |  ^
-// CHECK:STDERR:  [CppInteropParseError]
 #error "error1"
 #error "error2"
 
@@ -54,19 +45,19 @@ import Cpp library "one_error.h";
 
 library "[[@TEST_NAME]]";
 
-// CHECK:STDERR: fail_import_cpp_file_with_multiple_errors.carbon:[[@LINE+14]]:1: note: in `Cpp` import [InCppImport]
-// CHECK:STDERR: import Cpp library "multiple_errors.h";
-// CHECK:STDERR: ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+// 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:2: error: "error1"
+// CHECK:STDERR:     2 | #error "error1"
+// CHECK:STDERR:       |  ^
+// CHECK:STDERR:  [CppInteropParseError]
 // CHECK:STDERR:
-// CHECK:STDERR: ./multiple_errors.h:9: error: C++:
-// CHECK:STDERR: In file included from fail_import_cpp_file_with_multiple_errors.carbon.generated.cpp_imports.h:1:
-// CHECK:STDERR: ./multiple_errors.h:9:2: error: "error2"
-// CHECK:STDERR:     9 | #error "error2"
+// 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:2: error: "error2"
+// CHECK:STDERR:     3 | #error "error2"
 // CHECK:STDERR:       |  ^
 // CHECK:STDERR:  [CppInteropParseError]
-// CHECK:STDERR: fail_import_cpp_file_with_multiple_errors.carbon:[[@LINE+4]]:1: note: in `Cpp` import [InCppImport]
-// CHECK:STDERR: import Cpp library "multiple_errors.h";
-// CHECK:STDERR: ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
 // CHECK:STDERR:
 import Cpp library "multiple_errors.h";
 
@@ -76,21 +67,18 @@ import Cpp library "multiple_errors.h";
 
 // --- one_warning.h
 
-// CHECK:STDERR: ./one_warning.h:[[@LINE+6]]: warning: C++:
-// CHECK:STDERR: In file included from import_cpp_file_with_one_warning.carbon.generated.cpp_imports.h:1:
-// CHECK:STDERR: ./one_warning.h:[[@LINE+4]]:2: warning: "warning1"
-// CHECK:STDERR:     8 | #warning "warning1"
-// CHECK:STDERR:       |  ^
-// CHECK:STDERR:  [CppInteropParseWarning]
 #warning "warning1"
 
 // --- import_cpp_file_with_one_warning.carbon
 
 library "[[@TEST_NAME]]";
 
-// CHECK:STDERR: import_cpp_file_with_one_warning.carbon:[[@LINE+4]]:1: note: in `Cpp` import [InCppImport]
-// CHECK:STDERR: import Cpp library "one_warning.h";
-// CHECK:STDERR: ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+// 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:2: warning: "warning1"
+// CHECK:STDERR:     2 | #warning "warning1"
+// CHECK:STDERR:       |  ^
+// CHECK:STDERR:  [CppInteropParseWarning]
 // CHECK:STDERR:
 import Cpp library "one_warning.h";
 
@@ -100,12 +88,6 @@ import Cpp library "one_warning.h";
 
 // --- multiple_warnings.h
 
-// CHECK:STDERR: ./multiple_warnings.h:[[@LINE+6]]: warning: C++:
-// CHECK:STDERR: In file included from import_cpp_file_with_multiple_warnings.carbon.generated.cpp_imports.h:1:
-// CHECK:STDERR: ./multiple_warnings.h:[[@LINE+4]]:2: warning: "warning1"
-// CHECK:STDERR:     8 | #warning "warning1"
-// CHECK:STDERR:       |  ^
-// CHECK:STDERR:  [CppInteropParseWarning]
 #warning "warning1"
 #warning "warning2"
 #warning "warning3"
@@ -114,29 +96,26 @@ import Cpp library "one_warning.h";
 
 library "[[@TEST_NAME]]";
 
-// CHECK:STDERR: import_cpp_file_with_multiple_warnings.carbon:[[@LINE+24]]:1: note: in `Cpp` import [InCppImport]
-// CHECK:STDERR: import Cpp library "multiple_warnings.h";
-// CHECK:STDERR: ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+// 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:2: warning: "warning1"
+// CHECK:STDERR:     2 | #warning "warning1"
+// CHECK:STDERR:       |  ^
+// CHECK:STDERR:  [CppInteropParseWarning]
 // CHECK:STDERR:
-// CHECK:STDERR: ./multiple_warnings.h:9: warning: C++:
-// CHECK:STDERR: In file included from import_cpp_file_with_multiple_warnings.carbon.generated.cpp_imports.h:1:
-// CHECK:STDERR: ./multiple_warnings.h:9:2: warning: "warning2"
-// CHECK:STDERR:     9 | #warning "warning2"
+// 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:2: warning: "warning2"
+// CHECK:STDERR:     3 | #warning "warning2"
 // CHECK:STDERR:       |  ^
 // CHECK:STDERR:  [CppInteropParseWarning]
-// CHECK:STDERR: import_cpp_file_with_multiple_warnings.carbon:[[@LINE+14]]:1: note: in `Cpp` import [InCppImport]
-// CHECK:STDERR: import Cpp library "multiple_warnings.h";
-// CHECK:STDERR: ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
 // CHECK:STDERR:
-// CHECK:STDERR: ./multiple_warnings.h:10: warning: C++:
-// CHECK:STDERR: In file included from import_cpp_file_with_multiple_warnings.carbon.generated.cpp_imports.h:1:
-// CHECK:STDERR: ./multiple_warnings.h:10:2: warning: "warning3"
-// CHECK:STDERR:    10 | #warning "warning3"
+// 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:2: warning: "warning3"
+// CHECK:STDERR:     4 | #warning "warning3"
 // CHECK:STDERR:       |  ^
 // CHECK:STDERR:  [CppInteropParseWarning]
-// CHECK:STDERR: import_cpp_file_with_multiple_warnings.carbon:[[@LINE+4]]:1: note: in `Cpp` import [InCppImport]
-// CHECK:STDERR: import Cpp library "multiple_warnings.h";
-// CHECK:STDERR: ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
 // CHECK:STDERR:
 import Cpp library "multiple_warnings.h";
 
@@ -146,12 +125,6 @@ import Cpp library "multiple_warnings.h";
 
 // --- one_error_and_one_warning.h
 
-// CHECK:STDERR: ./one_error_and_one_warning.h:[[@LINE+6]]: error: C++:
-// CHECK:STDERR: 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:[[@LINE+4]]:2: error: "error1"
-// CHECK:STDERR:     8 | #error "error1"
-// CHECK:STDERR:       |  ^
-// CHECK:STDERR:  [CppInteropParseError]
 #error "error1"
 #warning "warning1"
 
@@ -159,19 +132,19 @@ 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: note: in `Cpp` import [InCppImport]
-// CHECK:STDERR: import Cpp library "one_error_and_one_warning.h";
-// CHECK:STDERR: ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+// 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:2: error: "error1"
+// CHECK:STDERR:     2 | #error "error1"
+// CHECK:STDERR:       |  ^
+// CHECK:STDERR:  [CppInteropParseError]
 // CHECK:STDERR:
-// CHECK:STDERR: ./one_error_and_one_warning.h:9: warning: C++:
-// CHECK:STDERR: 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:9:2: warning: "warning1"
-// CHECK:STDERR:     9 | #warning "warning1"
+// 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:2: warning: "warning1"
+// CHECK:STDERR:     3 | #warning "warning1"
 // CHECK:STDERR:       |  ^
 // CHECK:STDERR:  [CppInteropParseWarning]
-// CHECK:STDERR: fail_import_cpp_file_with_one_error_and_one_warning.carbon:[[@LINE+4]]:1: note: in `Cpp` import [InCppImport]
-// CHECK:STDERR: import Cpp library "one_error_and_one_warning.h";
-// CHECK:STDERR: ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
 // CHECK:STDERR:
 import Cpp library "one_error_and_one_warning.h";
 
@@ -181,12 +154,6 @@ import Cpp library "one_error_and_one_warning.h";
 
 // --- multiple_errors_and_multiple_warnings.h
 
-// CHECK:STDERR: ./multiple_errors_and_multiple_warnings.h:[[@LINE+6]]: error: C++:
-// CHECK:STDERR: 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:[[@LINE+4]]:2: error: "error1"
-// CHECK:STDERR:     8 | #error "error1"
-// CHECK:STDERR:       |  ^
-// CHECK:STDERR:  [CppInteropParseError]
 #error "error1"
 #error "error2"
 #warning "warning1"
@@ -197,56 +164,41 @@ 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+50]]:1: note: in `Cpp` import [InCppImport]
-// CHECK:STDERR: import Cpp library "multiple_errors_and_multiple_warnings.h";
-// CHECK:STDERR: ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-// CHECK:STDERR:
-// CHECK:STDERR: ./multiple_errors_and_multiple_warnings.h:9: error: C++:
-// CHECK:STDERR: 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:9:2: error: "error2"
-// CHECK:STDERR:     9 | #error "error2"
+// 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:2: error: "error1"
+// CHECK:STDERR:     2 | #error "error1"
 // CHECK:STDERR:       |  ^
 // CHECK:STDERR:  [CppInteropParseError]
-// CHECK:STDERR: fail_import_cpp_file_with_multiple_errors_and_multiple_warnings.carbon:[[@LINE+40]]:1: note: in `Cpp` import [InCppImport]
-// CHECK:STDERR: import Cpp library "multiple_errors_and_multiple_warnings.h";
-// CHECK:STDERR: ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
 // CHECK:STDERR:
-// CHECK:STDERR: ./multiple_errors_and_multiple_warnings.h:10: warning: C++:
-// CHECK:STDERR: 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:10:2: warning: "warning1"
-// CHECK:STDERR:    10 | #warning "warning1"
+// 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:2: error: "error2"
+// CHECK:STDERR:     3 | #error "error2"
 // CHECK:STDERR:       |  ^
-// CHECK:STDERR:  [CppInteropParseWarning]
-// CHECK:STDERR: fail_import_cpp_file_with_multiple_errors_and_multiple_warnings.carbon:[[@LINE+30]]:1: note: in `Cpp` import [InCppImport]
-// CHECK:STDERR: import Cpp library "multiple_errors_and_multiple_warnings.h";
-// CHECK:STDERR: ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+// CHECK:STDERR:  [CppInteropParseError]
 // CHECK:STDERR:
-// CHECK:STDERR: ./multiple_errors_and_multiple_warnings.h:11: warning: C++:
-// CHECK:STDERR: 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:11:2: warning: "warning2"
-// CHECK:STDERR:    11 | #warning "warning2"
+// 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:2: warning: "warning1"
+// CHECK:STDERR:     4 | #warning "warning1"
 // CHECK:STDERR:       |  ^
 // CHECK:STDERR:  [CppInteropParseWarning]
-// CHECK:STDERR: fail_import_cpp_file_with_multiple_errors_and_multiple_warnings.carbon:[[@LINE+20]]:1: note: in `Cpp` import [InCppImport]
-// CHECK:STDERR: import Cpp library "multiple_errors_and_multiple_warnings.h";
-// CHECK:STDERR: ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
 // CHECK:STDERR:
-// CHECK:STDERR: ./multiple_errors_and_multiple_warnings.h:12: warning: C++:
-// CHECK:STDERR: 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:12:2: warning: "warning3"
-// CHECK:STDERR:    12 | #warning "warning3"
+// 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:2: warning: "warning2"
+// CHECK:STDERR:     5 | #warning "warning2"
 // CHECK:STDERR:       |  ^
 // CHECK:STDERR:  [CppInteropParseWarning]
-// CHECK:STDERR: fail_import_cpp_file_with_multiple_errors_and_multiple_warnings.carbon:[[@LINE+10]]:1: note: in `Cpp` import [InCppImport]
-// CHECK:STDERR: import Cpp library "multiple_errors_and_multiple_warnings.h";
-// CHECK:STDERR: ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
 // CHECK:STDERR:
-// CHECK:STDERR: ./one_warning.h:8: warning: C++:
-// CHECK:STDERR: In file included from import_multiple_cpp_files_with_warnings.carbon.generated.cpp_imports.h:1:
-// CHECK:STDERR: ./one_warning.h:8:2: warning: "warning1"
-// CHECK:STDERR:     8 | #warning "warning1"
+// 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:2: warning: "warning3"
+// CHECK:STDERR:     6 | #warning "warning3"
 // CHECK:STDERR:       |  ^
 // CHECK:STDERR:  [CppInteropParseWarning]
+// CHECK:STDERR:
 import Cpp library "multiple_errors_and_multiple_warnings.h";
 
 // ============================================================================
@@ -257,47 +209,35 @@ import Cpp library "multiple_errors_and_multiple_warnings.h";
 
 library "[[@TEST_NAME]]";
 
-import Cpp library "one_warning.h";
-// CHECK:STDERR: import_multiple_cpp_files_with_warnings.carbon:[[@LINE+40]]:1: note: in `Cpp` import [InCppImport]
-// CHECK:STDERR: import Cpp library "multiple_warnings.h";
-// CHECK:STDERR: ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-// CHECK:STDERR:
-// CHECK:STDERR: ./multiple_warnings.h:8: warning: C++:
-// CHECK:STDERR: In file included from import_multiple_cpp_files_with_warnings.carbon.generated.cpp_imports.h:2:
-// CHECK:STDERR: ./multiple_warnings.h:8:2: warning: "warning1"
-// CHECK:STDERR:     8 | #warning "warning1"
+// 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:2: warning: "warning1"
+// CHECK:STDERR:     2 | #warning "warning1"
 // CHECK:STDERR:       |  ^
 // CHECK:STDERR:  [CppInteropParseWarning]
-// CHECK:STDERR: import_multiple_cpp_files_with_warnings.carbon:[[@LINE+30]]:1: note: in `Cpp` import [InCppImport]
-// CHECK:STDERR: import Cpp library "multiple_warnings.h";
-// CHECK:STDERR: ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
 // CHECK:STDERR:
-// CHECK:STDERR: ./multiple_warnings.h:9: warning: C++:
-// CHECK:STDERR: In file included from import_multiple_cpp_files_with_warnings.carbon.generated.cpp_imports.h:2:
-// CHECK:STDERR: ./multiple_warnings.h:9:2: warning: "warning2"
-// CHECK:STDERR:     9 | #warning "warning2"
+// 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:2: warning: "warning1"
+// CHECK:STDERR:     2 | #warning "warning1"
 // CHECK:STDERR:       |  ^
 // CHECK:STDERR:  [CppInteropParseWarning]
-// CHECK:STDERR: import_multiple_cpp_files_with_warnings.carbon:[[@LINE+20]]:1: note: in `Cpp` import [InCppImport]
-// CHECK:STDERR: import Cpp library "multiple_warnings.h";
-// CHECK:STDERR: ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
 // CHECK:STDERR:
-// CHECK:STDERR: ./multiple_warnings.h:10: warning: C++:
-// CHECK:STDERR: In file included from import_multiple_cpp_files_with_warnings.carbon.generated.cpp_imports.h:2:
-// CHECK:STDERR: ./multiple_warnings.h:10:2: warning: "warning3"
-// CHECK:STDERR:    10 | #warning "warning3"
+// 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:2: warning: "warning2"
+// CHECK:STDERR:     3 | #warning "warning2"
 // CHECK:STDERR:       |  ^
 // CHECK:STDERR:  [CppInteropParseWarning]
-// CHECK:STDERR: import_multiple_cpp_files_with_warnings.carbon:[[@LINE+10]]:1: note: in `Cpp` import [InCppImport]
-// CHECK:STDERR: import Cpp library "multiple_warnings.h";
-// CHECK:STDERR: ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
 // CHECK:STDERR:
-// CHECK:STDERR: ./one_error_and_one_warning.h:8: error: C++:
-// CHECK:STDERR: 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:8:2: error: "error1"
-// CHECK:STDERR:     8 | #error "error1"
+// 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:2: warning: "warning3"
+// CHECK:STDERR:     4 | #warning "warning3"
 // CHECK:STDERR:       |  ^
-// CHECK:STDERR:  [CppInteropParseError]
+// CHECK:STDERR:  [CppInteropParseWarning]
+// CHECK:STDERR:
+import Cpp library "one_warning.h";
 import Cpp library "multiple_warnings.h";
 
 // ============================================================================
@@ -308,73 +248,56 @@ import Cpp library "multiple_warnings.h";
 
 library "[[@TEST_NAME]]";
 
-import Cpp library "one_error_and_one_warning.h";
-// CHECK:STDERR: fail_import_multiple_cpp_files_with_errors_and_warnings.carbon:[[@LINE+66]]:1: note: in `Cpp` import [InCppImport]
-// CHECK:STDERR: import Cpp library "multiple_errors_and_multiple_warnings.h";
-// CHECK:STDERR: ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+// 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:2: error: "error1"
+// CHECK:STDERR:     2 | #error "error1"
+// CHECK:STDERR:       |  ^
+// CHECK:STDERR:  [CppInteropParseError]
 // CHECK:STDERR:
-// CHECK:STDERR: ./one_error_and_one_warning.h:9: warning: C++:
-// CHECK:STDERR: 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:9:2: warning: "warning1"
-// CHECK:STDERR:     9 | #warning "warning1"
+// 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:2: warning: "warning1"
+// CHECK:STDERR:     3 | #warning "warning1"
 // CHECK:STDERR:       |  ^
 // CHECK:STDERR:  [CppInteropParseWarning]
-// CHECK:STDERR: fail_import_multiple_cpp_files_with_errors_and_warnings.carbon:[[@LINE+56]]:1: note: in `Cpp` import [InCppImport]
-// CHECK:STDERR: import Cpp library "multiple_errors_and_multiple_warnings.h";
-// CHECK:STDERR: ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
 // CHECK:STDERR:
-// CHECK:STDERR: ./multiple_errors_and_multiple_warnings.h:8: error: C++:
-// CHECK:STDERR: 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:8:2: error: "error1"
-// CHECK:STDERR:     8 | #error "error1"
+// 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:2: error: "error1"
+// CHECK:STDERR:     2 | #error "error1"
 // CHECK:STDERR:       |  ^
 // CHECK:STDERR:  [CppInteropParseError]
-// CHECK:STDERR: fail_import_multiple_cpp_files_with_errors_and_warnings.carbon:[[@LINE+46]]:1: note: in `Cpp` import [InCppImport]
-// CHECK:STDERR: import Cpp library "multiple_errors_and_multiple_warnings.h";
-// CHECK:STDERR: ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
 // CHECK:STDERR:
-// CHECK:STDERR: ./multiple_errors_and_multiple_warnings.h:9: error: C++:
-// CHECK:STDERR: 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:9:2: error: "error2"
-// CHECK:STDERR:     9 | #error "error2"
+// 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:2: error: "error2"
+// CHECK:STDERR:     3 | #error "error2"
 // CHECK:STDERR:       |  ^
 // CHECK:STDERR:  [CppInteropParseError]
-// CHECK:STDERR: fail_import_multiple_cpp_files_with_errors_and_warnings.carbon:[[@LINE+36]]:1: note: in `Cpp` import [InCppImport]
-// CHECK:STDERR: import Cpp library "multiple_errors_and_multiple_warnings.h";
-// CHECK:STDERR: ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
 // CHECK:STDERR:
-// CHECK:STDERR: ./multiple_errors_and_multiple_warnings.h:10: warning: C++:
-// CHECK:STDERR: 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:10:2: warning: "warning1"
-// CHECK:STDERR:    10 | #warning "warning1"
+// 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:2: warning: "warning1"
+// CHECK:STDERR:     4 | #warning "warning1"
 // CHECK:STDERR:       |  ^
 // CHECK:STDERR:  [CppInteropParseWarning]
-// CHECK:STDERR: fail_import_multiple_cpp_files_with_errors_and_warnings.carbon:[[@LINE+26]]:1: note: in `Cpp` import [InCppImport]
-// CHECK:STDERR: import Cpp library "multiple_errors_and_multiple_warnings.h";
-// CHECK:STDERR: ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
 // CHECK:STDERR:
-// CHECK:STDERR: ./multiple_errors_and_multiple_warnings.h:11: warning: C++:
-// CHECK:STDERR: 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:11:2: warning: "warning2"
-// CHECK:STDERR:    11 | #warning "warning2"
+// 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:2: warning: "warning2"
+// CHECK:STDERR:     5 | #warning "warning2"
 // CHECK:STDERR:       |  ^
 // CHECK:STDERR:  [CppInteropParseWarning]
-// CHECK:STDERR: fail_import_multiple_cpp_files_with_errors_and_warnings.carbon:[[@LINE+16]]:1: note: in `Cpp` import [InCppImport]
-// CHECK:STDERR: import Cpp library "multiple_errors_and_multiple_warnings.h";
-// CHECK:STDERR: ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
 // CHECK:STDERR:
-// CHECK:STDERR: ./multiple_errors_and_multiple_warnings.h:12: warning: C++:
-// CHECK:STDERR: 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:12:2: warning: "warning3"
-// CHECK:STDERR:    12 | #warning "warning3"
+// 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:2: warning: "warning3"
+// CHECK:STDERR:     6 | #warning "warning3"
 // CHECK:STDERR:       |  ^
 // CHECK:STDERR:  [CppInteropParseWarning]
-// CHECK:STDERR: fail_import_multiple_cpp_files_with_errors_and_warnings.carbon:[[@LINE+6]]:1: note: in `Cpp` import [InCppImport]
-// CHECK:STDERR: import Cpp library "multiple_errors_and_multiple_warnings.h";
-// CHECK:STDERR: ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
 // CHECK:STDERR:
-// CHECK:STDERR: ./one_error.h:8: error: C++:
-// CHECK:STDERR: In file included from fail_import_indirect_error.carbon.generated.cpp_imports.h:1:
+import Cpp library "one_error_and_one_warning.h";
 import Cpp library "multiple_errors_and_multiple_warnings.h";
 
 // ============================================================================
@@ -383,23 +306,22 @@ import Cpp library "multiple_errors_and_multiple_warnings.h";
 
 // --- indirect_error.h
 
-// CHECK:STDERR: In file included from ./indirect_error.h:[[@LINE+5]]:
-// CHECK:STDERR: ./one_error.h:8:2: error: "error1"
-// CHECK:STDERR:     8 | #error "error1"
-// CHECK:STDERR:       |  ^
-// CHECK:STDERR:  [CppInteropParseError]
 #include "one_error.h"
 
-// --- fail_import_indirect_error.carbon
+// --- fail_todo_import_indirect_error.carbon
 
 library "[[@TEST_NAME]]";
 
-// CHECK:STDERR: fail_import_indirect_error.carbon:[[@LINE+6]]:1: note: in `Cpp` import [InCppImport]
-// CHECK:STDERR: import Cpp library "indirect_error.h";
-// CHECK:STDERR: ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+// 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: In file included from ./indirect_error.h:2:
+// CHECK:STDERR: ./one_error.h:2:2: error: "error1"
+// CHECK:STDERR:     2 | #error "error1"
+// CHECK:STDERR:       |  ^
+// CHECK:STDERR:  [CppInteropParseError]
 // CHECK:STDERR:
-// CHECK:STDERR: ./one_warning.h:8: warning: C++:
-// CHECK:STDERR: In file included from import_indirect_warning.carbon.generated.cpp_imports.h:1:
 import Cpp library "indirect_error.h";
 
 // ============================================================================
@@ -408,27 +330,22 @@ import Cpp library "indirect_error.h";
 
 // --- indirect_warning.h
 
-// CHECK:STDERR: In file included from ./indirect_warning.h:[[@LINE+5]]:
-// CHECK:STDERR: ./one_warning.h:8:2: warning: "warning1"
-// CHECK:STDERR:     8 | #warning "warning1"
-// CHECK:STDERR:       |  ^
-// CHECK:STDERR:  [CppInteropParseWarning]
 #include "one_warning.h"
 
-// --- import_indirect_warning.carbon
+// --- todo_import_indirect_warning.carbon
 
 library "[[@TEST_NAME]]";
 
-// CHECK:STDERR: import_indirect_warning.carbon:[[@LINE+10]]:1: note: in `Cpp` import [InCppImport]
-// CHECK:STDERR: import Cpp library "indirect_warning.h";
-// CHECK:STDERR: ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-// CHECK:STDERR:
-// CHECK:STDERR: ./one_warning.h:8: warning: C++:
-// CHECK:STDERR: In file included from fail_import_cpp_library_lexer_error.carbon.generated.cpp_imports.h:1:
-// CHECK:STDERR: ./one_warning.h:8:2: warning: "warning1"
-// CHECK:STDERR:     8 | #warning "warning1"
+// 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: 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: In file included from ./indirect_warning.h:2:
+// CHECK:STDERR: ./one_warning.h:2:2: warning: "warning1"
+// CHECK:STDERR:     2 | #warning "warning1"
 // CHECK:STDERR:       |  ^
 // CHECK:STDERR:  [CppInteropParseWarning]
+// CHECK:STDERR:
 import Cpp library "indirect_warning.h";
 
 // ============================================================================
@@ -440,11 +357,14 @@ import Cpp library "indirect_warning.h";
 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+8]]:1: note: in `Cpp` import [InCppImport]
-// CHECK:STDERR: import Cpp library "one_warning.h";
-// CHECK:STDERR: ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+// 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:2: warning: "warning1"
+// CHECK:STDERR:     2 | #warning "warning1"
+// CHECK:STDERR:       |  ^
+// CHECK:STDERR:  [CppInteropParseWarning]
 // CHECK:STDERR:
-// CHECK:STDERR: fail_import_cpp_library_lexer_error.carbon:[[@LINE-7]]:44: error: trailing comments are not permitted [TrailingComment]
+// CHECK:STDERR: fail_import_cpp_library_lexer_error.carbon:[[@LINE-10]]:44: error: trailing comments are not permitted [TrailingComment]
 // CHECK:STDERR: library "import_cpp_library_lexer_error";  // Trailing comment
 // CHECK:STDERR:                                            ^
 // CHECK:STDERR:
@@ -456,22 +376,19 @@ import Cpp library "one_warning.h";
 
 // --- fix_it_hints.h
 
-// CHECK:STDERR: ./fix_it_hints.h:[[@LINE+7]]: error: C++:
-// CHECK:STDERR: In file included from fail_import_fix_it_hints.carbon.generated.cpp_imports.h:1:
-// CHECK:STDERR: ./fix_it_hints.h:[[@LINE+5]]:19: error: expected ';' after top level declarator
-// CHECK:STDERR:     9 | double score = 0.1
-// CHECK:STDERR:       |                   ^
-// CHECK:STDERR:       |                   ;
-// CHECK:STDERR:  [CppInteropParseError]
 double score = 0.1
 
 // --- fail_import_fix_it_hints.carbon
 
 library "[[@TEST_NAME]]";
 
-// CHECK:STDERR: fail_import_fix_it_hints.carbon:[[@LINE+4]]:1: note: in `Cpp` import [InCppImport]
-// CHECK:STDERR: import Cpp library "fix_it_hints.h";
-// CHECK:STDERR: ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+// 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:19: error: expected ';' after top level declarator
+// CHECK:STDERR:     2 | double score = 0.1
+// CHECK:STDERR:       |                   ^
+// CHECK:STDERR:       |                   ;
+// CHECK:STDERR:  [CppInteropParseError]
 // CHECK:STDERR:
 import Cpp library "fix_it_hints.h";
 
@@ -623,7 +540,7 @@ fn F() {
 // CHECK:STDOUT:   }
 // CHECK:STDOUT: }
 // CHECK:STDOUT:
-// CHECK:STDOUT: --- fail_import_indirect_error.carbon
+// CHECK:STDOUT: --- fail_todo_import_indirect_error.carbon
 // CHECK:STDOUT:
 // CHECK:STDOUT: imports {
 // CHECK:STDOUT:   %Cpp: <namespace> = namespace file.%Cpp.import_cpp, [concrete] {
@@ -641,7 +558,7 @@ fn F() {
 // CHECK:STDOUT:   }
 // CHECK:STDOUT: }
 // CHECK:STDOUT:
-// CHECK:STDOUT: --- import_indirect_warning.carbon
+// CHECK:STDOUT: --- todo_import_indirect_warning.carbon
 // CHECK:STDOUT:
 // CHECK:STDOUT: imports {
 // CHECK:STDOUT:   %Cpp: <namespace> = namespace file.%Cpp.import_cpp, [concrete] {

+ 5 - 8
toolchain/check/testdata/interop/cpp/file_not_found.carbon

@@ -10,19 +10,16 @@
 // TIP:   bazel test //toolchain/testing:file_test --test_arg=--file_tests=toolchain/check/testdata/interop/cpp/file_not_found.carbon
 // TIP: To dump output, run:
 // TIP:   bazel run //toolchain/testing:file_test -- --dump_output --file_tests=toolchain/check/testdata/interop/cpp/file_not_found.carbon
-// CHECK:STDERR: fail_cpp_file_not_found.carbon.generated.cpp_imports.h:1: error: C++:
-// CHECK:STDERR: 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:       |          ^~~~~~~~~~~~~
-// CHECK:STDERR:  [CppInteropParseError]
 
 // --- fail_cpp_file_not_found.carbon
 
 library "[[@TEST_NAME]]";
 
-// CHECK:STDERR: fail_cpp_file_not_found.carbon:[[@LINE+4]]:1: note: in `Cpp` import [InCppImport]
-// CHECK:STDERR: import Cpp library "not_found.h";
-// CHECK:STDERR: ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+// 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:       |          ^~~~~~~~~~~~~
+// CHECK:STDERR:  [CppInteropParseError]
 // CHECK:STDERR:
 import Cpp library "not_found.h";
 

+ 9 - 14
toolchain/diagnostics/coverage_test.cpp

@@ -19,20 +19,6 @@ constexpr Kind Kinds[] = {
 #include "toolchain/diagnostics/diagnostic_kind.def"
 };
 
-// TODO: LanguageServerDiagnosticInWrongFile currently has coverage, but
-// mainly due to incorrect behavior in C++ diagnostics. See
-// language_server/testdata/text_document/open_with_cpp_nonexistent.carbon.
-// Leaving this TODO here until it's more precisely tested, because the C++
-// diagnostics should be fixed (removing coverage); see below TODO.
-//
-// TODO: This can only fire if the first message in a diagnostic is rooted
-// in a file other than the file being compiled. The language server
-// currently only supports compiling one file at a time. Do one of:
-// - When imports are supported, find a diagnostic whose first message isn't
-//   in the current file.
-// - Require all diagnostics produced by compiling have their first location
-//   be in the file being compiled, never an import.
-// Kind::LanguageServerDiagnosticInWrongFile,
 constexpr Kind UntestedKinds[] = {
     // These exist only for unit tests.
     Kind::TestDiagnostic,
@@ -56,6 +42,15 @@ constexpr Kind UntestedKinds[] = {
 
     // This is a little long but is tested in lex/numeric_literal_test.cpp.
     Kind::TooManyDigits,
+
+    // TODO: This can only fire if the first message in a diagnostic is rooted
+    // in a file other than the file being compiled. The language server
+    // currently only supports compiling one file at a time. Do one of:
+    // - When imports are supported, find a diagnostic whose first message isn't
+    //   in the current file.
+    // - Require all diagnostics produced by compiling have their first location
+    //   be in the file being compiled, never an import.
+    Kind::LanguageServerDiagnosticInWrongFile,
 };
 
 // Looks for diagnostic kinds that aren't covered by a file_test.

+ 0 - 1
toolchain/diagnostics/diagnostic_kind.def

@@ -161,7 +161,6 @@ CARBON_DIAGNOSTIC_KIND(RequirementEqualAfterNonDesignator)
 CARBON_DIAGNOSTIC_KIND(SemanticsTodo)
 
 // Location context.
-CARBON_DIAGNOSTIC_KIND(InCppImport)
 CARBON_DIAGNOSTIC_KIND(InImport)
 CARBON_DIAGNOSTIC_KIND(ResolvingSpecificHere)
 

+ 18 - 18
toolchain/language_server/testdata/text_document/open_with_cpp_nonexistent.carbon

@@ -2,11 +2,6 @@
 // Exceptions. See /LICENSE for license information.
 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
 //
-// TODO: At present, this has a
-// "dropping diagnostic in /test.carbon.generated.cpp_imports.h". That should be
-// fixed to assign back to this file, but that may come from other fixes to C++
-// diagnostic output.
-//
 // AUTOUPDATE
 // TIP: To test this file alone, run:
 // TIP:   bazel test //toolchain/testing:file_test --test_arg=--file_tests=toolchain/language_server/testdata/text_document/open_with_cpp_nonexistent.carbon
@@ -27,17 +22,6 @@
 
 // --- AUTOUPDATE-SPLIT
 
-// CHECK:STDERR: /test.carbon: warning: dropping diagnostic in /test.carbon.generated.cpp_imports.h:
-// CHECK:STDERR: /test.carbon.generated.cpp_imports.h:1: error: C++:
-// CHECK:STDERR: /test.carbon.generated.cpp_imports.h:1:10: fatal error: 'nonexistent.h' file not found
-// CHECK:STDERR:     1 | #include "nonexistent.h"
-// CHECK:STDERR:       |          ^~~~~~~~~~~~~~~
-// CHECK:STDERR:
-// CHECK:STDERR: /test.carbon:1:1: note: in `Cpp` import
-// CHECK:STDERR: import Cpp library "nonexistent.h";
-// CHECK:STDERR: ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-// CHECK:STDERR:  [LanguageServerDiagnosticInWrongFile]
-// CHECK:STDERR:
 // CHECK:STDOUT: Content-Length: 146{{\r}}
 // CHECK:STDOUT: {{\r}}
 // CHECK:STDOUT: {
@@ -49,13 +33,29 @@
 // CHECK:STDOUT:       "textDocumentSync": 2
 // CHECK:STDOUT:     }
 // CHECK:STDOUT:   }
-// CHECK:STDOUT: }Content-Length: 144{{\r}}
+// CHECK:STDOUT: }Content-Length: 443{{\r}}
 // CHECK:STDOUT: {{\r}}
 // CHECK:STDOUT: {
 // CHECK:STDOUT:   "jsonrpc": "2.0",
 // CHECK:STDOUT:   "method": "textDocument/publishDiagnostics",
 // CHECK:STDOUT:   "params": {
-// CHECK:STDOUT:     "diagnostics": [],
+// CHECK:STDOUT:     "diagnostics": [
+// CHECK:STDOUT:       {
+// CHECK:STDOUT:         "message": "in import",
+// CHECK:STDOUT:         "range": {
+// CHECK:STDOUT:           "end": {
+// CHECK:STDOUT:             "character": 36,
+// CHECK:STDOUT:             "line": 1
+// CHECK:STDOUT:           },
+// CHECK:STDOUT:           "start": {
+// CHECK:STDOUT:             "character": 0,
+// CHECK:STDOUT:             "line": 0
+// CHECK:STDOUT:           }
+// CHECK:STDOUT:         },
+// CHECK:STDOUT:         "severity": 1,
+// CHECK:STDOUT:         "source": "carbon"
+// CHECK:STDOUT:       }
+// CHECK:STDOUT:     ],
 // CHECK:STDOUT:     "uri": "file:///test.carbon"
 // CHECK:STDOUT:   }
 // CHECK:STDOUT: }Content-Length: 144{{\r}}