@@ -61,16 +61,36 @@ static auto RenderImportKey(ImportKey import_key) -> std::string {
6161static auto TrackImport (Map<ImportKey, UnitAndImports*>& api_map,
6262 Map<ImportKey, Parse::NodeId>* explicit_import_map,
6363 UnitAndImports& unit_info,
64- Parse::Tree::PackagingNames import ) -> void {
64+ Parse::Tree::PackagingNames import , bool fuzzing)
65+ -> void {
6566 const auto & packaging = unit_info.parse_tree ().packaging_decl ();
6667
6768 IdentifierId file_package_id =
6869 packaging ? packaging->names .package_id : IdentifierId::Invalid;
69- auto import_key = GetImportKey (unit_info, file_package_id, import );
70+ const auto import_key = GetImportKey (unit_info, file_package_id, import );
71+ const auto & [import_package_name, import_library_name] = import_key;
72+
73+ if (import_package_name == CppPackageName) {
74+ if (import_library_name.empty ()) {
75+ CARBON_DIAGNOSTIC (CppInteropMissingLibrary, Error,
76+ " `Cpp` import missing library" );
77+ unit_info.emitter .Emit (import .node_id , CppInteropMissingLibrary);
78+ return ;
79+ }
80+ if (fuzzing) {
81+ // Clang is not crash-resilient.
82+ CARBON_DIAGNOSTIC (CppInteropFuzzing, Error,
83+ " `Cpp` import found during fuzzing" );
84+ unit_info.emitter .Emit (import .node_id , CppInteropFuzzing);
85+ return ;
86+ }
87+ unit_info.cpp_imports .push_back (import );
88+ return ;
89+ }
7090
7191 // True if the import has `Main` as the package name, even if it comes from
7292 // the file's packaging (diagnostics may differentiate).
73- bool is_explicit_main = import_key. first == MainPackageName;
93+ bool is_explicit_main = import_package_name == MainPackageName;
7494
7595 // Explicit imports need more validation than implicit ones. We try to do
7696 // these in an order of imports that should be removed, followed by imports
@@ -185,7 +205,7 @@ static auto TrackImport(Map<ImportKey, UnitAndImports*>& api_map,
185205 } else {
186206 // The imported api is missing.
187207 package_imports.has_load_error = true ;
188- if (!explicit_import_map && import_key. first == CppPackageName) {
208+ if (!explicit_import_map && import_package_name == CppPackageName) {
189209 // Don't diagnose the implicit import in `impl package Cpp`, because we'll
190210 // have diagnosed the use of `Cpp` in the declaration.
191211 return ;
@@ -295,7 +315,8 @@ static auto BuildApiMapAndDiagnosePackaging(
295315}
296316
297317auto CheckParseTrees (llvm::MutableArrayRef<Unit> units, bool prelude_import,
298- llvm::raw_ostream* vlog_stream) -> void {
318+ llvm::IntrusiveRefCntPtr<llvm::vfs::FileSystem> fs,
319+ llvm::raw_ostream* vlog_stream, bool fuzzing) -> void {
299320 // UnitAndImports is big due to its SmallVectors, so we default to 0 on the
300321 // stack.
301322 llvm::SmallVector<UnitAndImports, 0 > unit_infos;
@@ -316,7 +337,7 @@ auto CheckParseTrees(llvm::MutableArrayRef<Unit> units, bool prelude_import,
316337 // An `impl` has an implicit import of its `api`.
317338 auto implicit_names = packaging->names ;
318339 implicit_names.package_id = IdentifierId::Invalid;
319- TrackImport (api_map, nullptr , unit_info, implicit_names);
340+ TrackImport (api_map, nullptr , unit_info, implicit_names, fuzzing );
320341 }
321342
322343 Map<ImportKey, Parse::NodeId> explicit_import_map;
@@ -332,11 +353,12 @@ auto CheckParseTrees(llvm::MutableArrayRef<Unit> units, bool prelude_import,
332353 TrackImport (api_map, &explicit_import_map, unit_info,
333354 {.node_id = Parse::InvalidNodeId (),
334355 .package_id = core_ident_id,
335- .library_id = prelude_id});
356+ .library_id = prelude_id},
357+ fuzzing);
336358 }
337359
338360 for (const auto & import : unit_info.parse_tree ().imports ()) {
339- TrackImport (api_map, &explicit_import_map, unit_info, import );
361+ TrackImport (api_map, &explicit_import_map, unit_info, import , fuzzing );
340362 }
341363
342364 // If there were no imports, mark the file as ready to check for below.
@@ -350,7 +372,7 @@ auto CheckParseTrees(llvm::MutableArrayRef<Unit> units, bool prelude_import,
350372 for (int check_index = 0 ;
351373 check_index < static_cast <int >(ready_to_check.size ()); ++check_index) {
352374 auto * unit_info = ready_to_check[check_index];
353- CheckUnit (unit_info, units.size (), vlog_stream).Run ();
375+ CheckUnit (unit_info, units.size (), fs, vlog_stream).Run ();
354376 for (auto * incoming_import : unit_info->incoming_imports ) {
355377 --incoming_import->imports_remaining ;
356378 if (incoming_import->imports_remaining == 0 ) {
@@ -397,7 +419,7 @@ auto CheckParseTrees(llvm::MutableArrayRef<Unit> units, bool prelude_import,
397419 // incomplete imports.
398420 for (auto & unit_info : unit_infos) {
399421 if (unit_info.imports_remaining > 0 ) {
400- CheckUnit (&unit_info, units.size (), vlog_stream).Run ();
422+ CheckUnit (&unit_info, units.size (), fs, vlog_stream).Run ();
401423 }
402424 }
403425 }
0 commit comments