diff --git a/toolchain/check/check_unit.cpp b/toolchain/check/check_unit.cpp index f0a761965a00..43e9cfa05283 100644 --- a/toolchain/check/check_unit.cpp +++ b/toolchain/check/check_unit.cpp @@ -34,7 +34,11 @@ static auto GetImportedIRCount(UnitAndImports* unit_and_imports) -> int { count += package_imports.imports.size(); } if (!unit_and_imports->api_for_impl) { - // Leave an empty slot for ImportIRId::ApiForImpl. + // Leave an empty slot for `ImportIRId::ApiForImpl`. + ++count; + } + if (!unit_and_imports->cpp_import_names.empty()) { + // Leave an empty slot for `ImportIRId::Cpp`. ++count; } return count; @@ -101,20 +105,20 @@ auto CheckUnit::InitPackageScopeAndImports() -> void { .import_id = SemIR::InstId::None}); CARBON_CHECK(package_inst_id == SemIR::Namespace::PackageInstId); - // If there is an implicit `api` import, set it first so that it uses the - // ImportIRId::ApiForImpl when processed for imports. + // Call `SetSpecialImportIRs()` to set `ImportIRId::ApiForImpl` and + // `ImportIRId::Cpp` first, as required. if (unit_and_imports_->api_for_impl) { const auto& names = context_.parse_tree().packaging_decl()->names; auto import_decl_id = AddInst( context_, names.node_id, {.package_id = SemIR::NameId::ForPackageName(names.package_id)}); - SetApiImportIR(context_, - {.decl_id = import_decl_id, - .is_export = false, - .sem_ir = unit_and_imports_->api_for_impl->unit->sem_ir}); + SetSpecialImportIRs( + context_, {.decl_id = import_decl_id, + .is_export = false, + .sem_ir = unit_and_imports_->api_for_impl->unit->sem_ir}); } else { - SetApiImportIR(context_, - {.decl_id = SemIR::InstId::None, .sem_ir = nullptr}); + SetSpecialImportIRs(context_, + {.decl_id = SemIR::InstId::None, .sem_ir = nullptr}); } // Add import instructions for everything directly imported. Implicit imports @@ -327,9 +331,9 @@ auto CheckUnit::ImportOtherPackages(SemIR::TypeId namespace_type_id) -> void { if (local_imports) { CARBON_CHECK(package_id == api_imports_entry.first); } else { - auto import_ir_inst_id = context_.import_ir_insts().Add( - {.ir_id = SemIR::ImportIRId::ApiForImpl, - .inst_id = api_imports->import_decl_id}); + auto import_ir_inst_id = + context_.import_ir_insts().Add(SemIR::ImportIRInst( + SemIR::ImportIRId::ApiForImpl, api_imports->import_decl_id)); import_decl_id = AddInst(context_, MakeImportedLocIdAndInst( context_, import_ir_inst_id, @@ -411,7 +415,7 @@ auto CheckUnit::CheckRequiredDeclarations() -> void { auto import_ir_id = context_.sem_ir() .import_ir_insts() .Get(function_loc_id.import_ir_inst_id()) - .ir_id; + .ir_id(); auto& import_ir = context_.import_irs().Get(import_ir_id); if (import_ir.sem_ir->package_id().has_value() != context_.sem_ir().package_id().has_value()) { diff --git a/toolchain/check/diagnostic_emitter.cpp b/toolchain/check/diagnostic_emitter.cpp index 38c66365e151..b3e223cba44e 100644 --- a/toolchain/check/diagnostic_emitter.cpp +++ b/toolchain/check/diagnostic_emitter.cpp @@ -5,6 +5,7 @@ #include "toolchain/check/diagnostic_emitter.h" #include +#include #include #include "common/raw_string_ostream.h" @@ -16,6 +17,14 @@ namespace Carbon::Check { auto DiagnosticEmitter::ConvertLoc(SemIR::LocId loc_id, ContextFnT context_fn) const -> Diagnostics::ConvertedLoc { + // TODO: Instead of special casing Clang location here, support it within + // `GetAbsoluteNodeId()`. See discussion in + // https://github.com/carbon-language/carbon-lang/pull/5262/files#r2040308805. + auto converted_clang_loc = TryConvertClangDiagnosticLoc(loc_id); + if (converted_clang_loc) { + return *converted_clang_loc; + } + auto converted = ConvertLocImpl(loc_id, context_fn); // Use the token when possible, but -1 is the default value. @@ -60,6 +69,33 @@ auto DiagnosticEmitter::ConvertLocImpl(SemIR::LocId loc_id, return ConvertLocInFile(final_node_id, token_only, context_fn); } +auto DiagnosticEmitter::TryConvertClangDiagnosticLoc(SemIR::LocId loc_id) const + -> std::optional { + if (loc_id.kind() != SemIR::LocId::Kind::ImportIRInstId) { + return std::nullopt; + } + + SemIR::ImportIRInst import_ir_inst = + sem_ir_->import_ir_insts().Get(loc_id.import_ir_inst_id()); + + if (import_ir_inst.ir_id() != SemIR::ImportIRId::Cpp) { + return std::nullopt; + } + + clang::SourceLocation clang_loc = + sem_ir_->clang_source_locs().Get(import_ir_inst.clang_source_loc_id()); + + CARBON_CHECK(sem_ir_->cpp_ast()); + clang::PresumedLoc presumed_loc = + sem_ir_->cpp_ast()->getSourceManager().getPresumedLoc(clang_loc); + + return Diagnostics::ConvertedLoc{ + .loc = {.filename = presumed_loc.getFilename(), + .line_number = static_cast(presumed_loc.getLine())}, + // TODO: Set `last_byte_offset` based on the `import Cpp` location. + .last_byte_offset = 0}; +} + auto DiagnosticEmitter::ConvertLocInFile(SemIR::AbsoluteNodeId absolute_node_id, bool token_only, ContextFnT /*context_fn*/) const diff --git a/toolchain/check/diagnostic_emitter.h b/toolchain/check/diagnostic_emitter.h index c796ed16b68a..fc0f27eb2bf3 100644 --- a/toolchain/check/diagnostic_emitter.h +++ b/toolchain/check/diagnostic_emitter.h @@ -51,6 +51,10 @@ class DiagnosticEmitter : public DiagnosticEmitterBase { auto ConvertLocImpl(SemIR::LocId loc_id, ContextFnT context_fn) const -> Diagnostics::ConvertedLoc; + // Returns `ConvertedLoc` if `loc` points to a `ClangDiagnostic` instruction. + auto TryConvertClangDiagnosticLoc(SemIR::LocId loc_id) const + -> std::optional; + // Converts a node_id corresponding to a specific sem_ir to a diagnostic // location. auto ConvertLocInFile(SemIR::AbsoluteNodeId absolute_node_id, bool token_only, diff --git a/toolchain/check/dump.cpp b/toolchain/check/dump.cpp index 6e79c53a6b3f..1ea0ba9b57d5 100644 --- a/toolchain/check/dump.cpp +++ b/toolchain/check/dump.cpp @@ -120,7 +120,7 @@ LLVM_DUMP_METHOD static auto Dump(const Context& context, SemIR::LocId loc_id) auto import_ir_id = context.sem_ir() .import_ir_insts() .Get(loc_id.import_ir_inst_id()) - .ir_id; + .ir_id(); const auto* import_file = context.sem_ir().import_irs().Get(import_ir_id).sem_ir; out << "LocId(import from \"" << FormatEscaped(import_file->filename()) diff --git a/toolchain/check/handle_class.cpp b/toolchain/check/handle_class.cpp index 0d9858e25085..9fc8e35663b7 100644 --- a/toolchain/check/handle_class.cpp +++ b/toolchain/check/handle_class.cpp @@ -132,8 +132,8 @@ static auto MergeOrAddName(Context& context, Parse::AnyClassDeclId node_id, // Verify the decl so that things like aliases are name conflicts. const auto* import_ir = - context.import_irs().Get(import_ir_inst.ir_id).sem_ir; - if (!import_ir->insts().Is(import_ir_inst.inst_id)) { + context.import_irs().Get(import_ir_inst.ir_id()).sem_ir; + if (!import_ir->insts().Is(import_ir_inst.inst_id())) { break; } @@ -142,12 +142,12 @@ static auto MergeOrAddName(Context& context, Parse::AnyClassDeclId node_id, context.constant_values().GetConstantInstId(prev_id)); if (auto class_type = decl_value.TryAs()) { prev_class_id = class_type->class_id; - prev_import_ir_id = import_ir_inst.ir_id; + prev_import_ir_id = import_ir_inst.ir_id(); } else if (auto generic_class_type = context.types().TryGetAs( decl_value.type_id())) { prev_class_id = generic_class_type->class_id; - prev_import_ir_id = import_ir_inst.ir_id; + prev_import_ir_id = import_ir_inst.ir_id(); } break; } diff --git a/toolchain/check/handle_function.cpp b/toolchain/check/handle_function.cpp index 94906e100ec2..18914e83483b 100644 --- a/toolchain/check/handle_function.cpp +++ b/toolchain/check/handle_function.cpp @@ -221,8 +221,9 @@ static auto TryMergeRedecl(Context& context, Parse::AnyFunctionDeclId node_id, // Verify the decl so that things like aliases are name conflicts. const auto* import_ir = - context.import_irs().Get(import_ir_inst.ir_id).sem_ir; - if (!import_ir->insts().Is(import_ir_inst.inst_id)) { + context.import_irs().Get(import_ir_inst.ir_id()).sem_ir; + if (!import_ir->insts().Is( + import_ir_inst.inst_id())) { break; } @@ -233,7 +234,7 @@ static auto TryMergeRedecl(Context& context, Parse::AnyFunctionDeclId node_id, struct_value->type_id)) { prev_function_id = function_type->function_id; prev_type_id = struct_value->type_id; - prev_import_ir_id = import_ir_inst.ir_id; + prev_import_ir_id = import_ir_inst.ir_id(); } } break; diff --git a/toolchain/check/impl_lookup.cpp b/toolchain/check/impl_lookup.cpp index f6deba75807e..94ac822ca6fc 100644 --- a/toolchain/check/impl_lookup.cpp +++ b/toolchain/check/impl_lookup.cpp @@ -42,7 +42,7 @@ static auto FindAssociatedImportIRs(Context& context, if (!decl_id.has_value()) { return; } - if (auto ir_id = GetCanonicalImportIRInst(context, decl_id).ir_id; + if (auto ir_id = GetCanonicalImportIRInst(context, decl_id).ir_id(); ir_id.has_value()) { result.push_back(ir_id); } diff --git a/toolchain/check/import.cpp b/toolchain/check/import.cpp index 6df3b06e480f..3e5c8c639ae0 100644 --- a/toolchain/check/import.cpp +++ b/toolchain/check/import.cpp @@ -226,7 +226,7 @@ static auto CopySingleNameScopeFromImportIR( auto entity_name_id = context.entity_names().Add( {.name_id = name_id, .parent_scope_id = parent_scope_id}); auto import_ir_inst_id = context.import_ir_insts().Add( - {.ir_id = ir_id, .inst_id = import_inst_id}); + SemIR::ImportIRInst(ir_id, import_inst_id)); auto inst_id = AddInstInNoBlock( context, MakeImportedLocIdAndInst( context, import_ir_inst_id, @@ -354,7 +354,7 @@ static auto AddImportRefOrMerge(Context& context, SemIR::ImportIRId ir_id, auto entity_name_id = context.entity_names().Add( {.name_id = name_id, .parent_scope_id = parent_scope_id}); auto import_ref = AddImportRef( - context, {.ir_id = ir_id, .inst_id = import_inst_id}, entity_name_id); + context, SemIR::ImportIRInst(ir_id, import_inst_id), entity_name_id); entry.result = SemIR::ScopeLookupResult::MakeFound( import_ref, SemIR::AccessKind::Public); @@ -444,8 +444,8 @@ static auto ImportScopeFromApiFile(Context& context, } else { // Add an ImportRef for other instructions. AddScopedImportRef(context, impl_scope_id, impl_scope, impl_name_id, - {.ir_id = SemIR::ImportIRId::ApiForImpl, - .inst_id = api_entry.result.target_inst_id()}, + SemIR::ImportIRInst(SemIR::ImportIRId::ApiForImpl, + api_entry.result.target_inst_id()), api_entry.result.access_kind()); } } @@ -668,7 +668,7 @@ auto ImportNameFromOtherPackage( } else { result_id = AddScopedImportRef( context, scope_id, context.name_scopes().Get(scope_id), name_id, - {.ir_id = import_ir_id, .inst_id = import_scope_inst_id}, + SemIR::ImportIRInst(import_ir_id, import_scope_inst_id), SemIR::AccessKind::Public); LoadImportRef(context, result_id); } diff --git a/toolchain/check/import_cpp.cpp b/toolchain/check/import_cpp.cpp index 1c827991c460..5f10085ae447 100644 --- a/toolchain/check/import_cpp.cpp +++ b/toolchain/check/import_cpp.cpp @@ -52,6 +52,17 @@ static auto GenerateCppIncludesHeaderCode( namespace { +// Adds the given source location and an `ImportIRInst` referring to it in +// `ImportIRId::Cpp`. +static auto AddImportIRInst(Context& context, + clang::SourceLocation clang_source_loc) + -> SemIR::ImportIRInstId { + SemIR::ClangSourceLocId clang_source_loc_id = + context.sem_ir().clang_source_locs().Add(clang_source_loc); + return context.import_ir_insts().Add( + SemIR::ImportIRInst(clang_source_loc_id)); +} + // Used to convert Clang diagnostics to Carbon diagnostics. class CarbonClangDiagnosticConsumer : public clang::DiagnosticConsumer { public: @@ -66,6 +77,9 @@ class CarbonClangDiagnosticConsumer : public clang::DiagnosticConsumer { const clang::Diagnostic& info) -> void override { DiagnosticConsumer::HandleDiagnostic(diag_level, info); + SemIR::ImportIRInstId clang_import_ir_inst_id = + AddImportIRInst(*context_, info.getLocation()); + llvm::SmallString<256> message; info.FormatDiagnostic(message); @@ -84,40 +98,48 @@ class CarbonClangDiagnosticConsumer : public clang::DiagnosticConsumer { std::string diagnostics_str = diagnostics_stream.TakeStr(); - switch (diag_level) { - case clang::DiagnosticsEngine::Ignored: - case clang::DiagnosticsEngine::Note: - case clang::DiagnosticsEngine::Remark: { - context_->TODO( - loc_id_, - llvm::formatv( - "Unsupported: C++ diagnostic level for diagnostic\n{0}", - diagnostics_str)); - return; - } - 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}", - 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"); + diagnostic_infos_.push_back({.level = diag_level, + .import_ir_inst_id = clang_import_ir_inst_id, + .message = diagnostics_str}); + } - // TODO: Use a more specific location. - context_->emitter() - .Build(SemIR::LocId::None, - diag_level == clang::DiagnosticsEngine::Warning - ? CppInteropParseWarning - : CppInteropParseError, - diagnostics_str) - .Note(loc_id_, InCppImport) - .Emit(); - return; + // Outputs Carbon diagnostics based on the collected Clang diagnostics. Must + // be called after the AST is set in the context. + auto EmitDiagnostics() -> void { + for (const ClangDiagnosticInfo& info : diagnostic_infos_) { + switch (info.level) { + case clang::DiagnosticsEngine::Ignored: + case clang::DiagnosticsEngine::Note: + case clang::DiagnosticsEngine::Remark: { + context_->TODO( + SemIR::LocId(info.import_ir_inst_id), + llvm::formatv( + "Unsupported: C++ diagnostic level for diagnostic\n{0}", + info.message)); + break; + } + 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}", + 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(); + break; + } } } } @@ -128,13 +150,32 @@ class CarbonClangDiagnosticConsumer : public clang::DiagnosticConsumer { // 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 { + // The Clang diagnostic level. + clang::DiagnosticsEngine::Level level; + + // The ID of the ImportIR instruction referring to the Clang source + // location. + SemIR::ImportIRInstId import_ir_inst_id; + + // The Clang diagnostic textual message. + std::string message; + }; + + // Collects the information for all Clang diagnostics to be converted to + // Carbon diagnostics after the context has been initialized with the Clang + // AST. + llvm::SmallVector diagnostic_infos_; }; } // namespace // Returns an AST for the C++ imports and a bool that represents whether // compilation errors where encountered or the generated AST is null due to an -// error. +// error. Sets the AST in the context's `sem_ir`. // TODO: Consider to always have a (non-null) AST. static auto GenerateAst(Context& context, llvm::StringRef importing_file_path, llvm::ArrayRef imports, @@ -157,6 +198,10 @@ static auto GenerateAst(Context& context, llvm::StringRef importing_file_path, // Remove link to the diagnostics consumer before its deletion. ast->getDiagnostics().setClient(nullptr); + // In order to emit diagnostics, we need the AST. + context.sem_ir().set_cpp_ast(ast.get()); + diagnostics_consumer.EmitDiagnostics(); + return {std::move(ast), !ast || diagnostics_consumer.getNumErrors() > 0}; } @@ -212,8 +257,6 @@ auto ImportCppFiles(Context& context, llvm::StringRef importing_file_path, name_scope.set_cpp_decl_context( generated_ast->getASTContext().getTranslationUnitDecl()); - context.sem_ir().set_cpp_ast(generated_ast.get()); - if (ast_has_error) { name_scope.set_has_error(); } diff --git a/toolchain/check/import_ref.cpp b/toolchain/check/import_ref.cpp index 7870db7b2a36..d4b825f64d20 100644 --- a/toolchain/check/import_ref.cpp +++ b/toolchain/check/import_ref.cpp @@ -37,7 +37,10 @@ static auto InternalAddImportIR(Context& context, SemIR::ImportIR import_ir) return context.import_irs().Add(import_ir); } -auto SetApiImportIR(Context& context, SemIR::ImportIR import_ir) -> void { +// Adds a special-cased IR and verifies it received the correct ID. +static auto SetSpecialImportIR(Context& context, SemIR::ImportIR import_ir, + SemIR::ImportIRId expected_import_ir_id) + -> void { auto ir_id = SemIR::ImportIRId::None; if (import_ir.sem_ir != nullptr) { ir_id = AddImportIR(context, import_ir); @@ -45,8 +48,16 @@ auto SetApiImportIR(Context& context, SemIR::ImportIR import_ir) -> void { // We don't have a check_ir_id, so add without touching check_ir_map. ir_id = InternalAddImportIR(context, import_ir); } - CARBON_CHECK(ir_id == SemIR::ImportIRId::ApiForImpl, - "ApiForImpl must be the first IR"); + CARBON_CHECK(ir_id == expected_import_ir_id, + "Actual ImportIRId ($0) != Expected ImportIRId ({1})", ir_id, + expected_import_ir_id); +} + +auto SetSpecialImportIRs(Context& context, SemIR::ImportIR import_ir) -> void { + SetSpecialImportIR(context, import_ir, SemIR::ImportIRId::ApiForImpl); + SetSpecialImportIR(context, + {.decl_id = SemIR::InstId::None, .is_export = false}, + SemIR::ImportIRId::Cpp); } auto AddImportIR(Context& context, SemIR::ImportIR import_ir) @@ -95,8 +106,8 @@ static auto AddLoadedImportRef(Context& context, SemIR::TypeId type_id, context.import_ref_ids().push_back(inst_id); context.constant_values().Set(inst_id, const_id); - context.import_ir_constant_values()[import_ir_inst.ir_id.index].Set( - import_ir_inst.inst_id, const_id); + context.import_ir_constant_values()[import_ir_inst.ir_id().index].Set( + import_ir_inst.inst_id(), const_id); return inst_id; } @@ -111,8 +122,8 @@ static auto GetCanonicalImportIRInst(Context& context, if (loc_id.kind() == SemIR::LocId::Kind::ImportIRInstId) { auto import_ir_inst = cursor_ir->import_ir_insts().Get(loc_id.import_ir_inst_id()); - cursor_ir = cursor_ir->import_irs().Get(import_ir_inst.ir_id).sem_ir; - cursor_inst_id = import_ir_inst.inst_id; + cursor_ir = cursor_ir->import_irs().Get(import_ir_inst.ir_id()).sem_ir; + cursor_inst_id = import_ir_inst.inst_id(); continue; } @@ -135,7 +146,7 @@ static auto GetCanonicalImportIRInst(Context& context, .is_export = false, .sem_ir = cursor_ir}); } - return {.ir_id = ir_id, .inst_id = cursor_inst_id}; + return SemIR::ImportIRInst(ir_id, cursor_inst_id); } auto GetCanonicalImportIRInst(Context& context, SemIR::InstId inst_id) @@ -155,7 +166,7 @@ auto VerifySameCanonicalImportIRInst(Context& context, SemIR::NameId name_id, return; } auto conflict_id = - AddImportRef(context, {.ir_id = new_ir_id, .inst_id = new_inst_id}); + AddImportRef(context, SemIR::ImportIRInst(new_ir_id, new_inst_id)); // TODO: Pass the imported name location instead of the conflict id. DiagnoseDuplicateName(context, name_id, conflict_id, prev_id); } @@ -609,7 +620,7 @@ class ImportRefResolver : public ImportContext { const auto* prev_ir = cursor_ir; auto prev_inst_id = cursor_inst_id; - cursor_ir = cursor_ir->import_irs().Get(ir_inst.ir_id).sem_ir; + cursor_ir = cursor_ir->import_irs().Get(ir_inst.ir_id()).sem_ir; cursor_ir_id = local_context().check_ir_map()[cursor_ir->check_ir_id().index]; if (!cursor_ir_id.has_value()) { @@ -619,7 +630,7 @@ class ImportRefResolver : public ImportContext { .is_export = false, .sem_ir = cursor_ir}); } - cursor_inst_id = ir_inst.inst_id; + cursor_inst_id = ir_inst.inst_id(); CARBON_CHECK(cursor_ir != prev_ir || cursor_inst_id != prev_inst_id, "{0}", cursor_ir->insts().Get(cursor_inst_id)); @@ -634,7 +645,7 @@ class ImportRefResolver : public ImportContext { return result; } else { result.indirect_insts.push_back( - {.ir_id = cursor_ir_id, .inst_id = cursor_inst_id}); + SemIR::ImportIRInst(cursor_ir_id, cursor_inst_id)); } } } @@ -646,8 +657,8 @@ class ImportRefResolver : public ImportContext { local_constant_values_for_import_insts().Set(inst_id, const_id); for (auto indirect_inst : indirect_insts) { local_context() - .import_ir_constant_values()[indirect_inst.ir_id.index] - .Set(indirect_inst.inst_id, const_id); + .import_ir_constant_values()[indirect_inst.ir_id().index] + .Set(indirect_inst.inst_id(), const_id); } } @@ -663,7 +674,7 @@ static auto AddImportRef(ImportContext& context, SemIR::InstId inst_id, SemIR::EntityNameId entity_name_id = SemIR::EntityNameId::None) -> SemIR::InstId { return AddImportRef(context.local_context(), - {.ir_id = context.import_ir_id(), .inst_id = inst_id}, + SemIR::ImportIRInst(context.import_ir_id(), inst_id), entity_name_id); } @@ -672,13 +683,13 @@ static auto AddLoadedImportRef(ImportContext& context, SemIR::TypeId type_id, SemIR::ConstantId const_id) -> SemIR::InstId { return AddLoadedImportRef( context.local_context(), type_id, - {.ir_id = context.import_ir_id(), .inst_id = inst_id}, const_id); + SemIR::ImportIRInst(context.import_ir_id(), inst_id), const_id); } static auto AddImportIRInst(ImportContext& context, SemIR::InstId inst_id) -> SemIR::ImportIRInstId { return context.local_import_ir_insts().Add( - {.ir_id = context.import_ir_id(), .inst_id = inst_id}); + SemIR::ImportIRInst(context.import_ir_id(), inst_id)); } // Computes, sets, and returns the constant value for an instruction. @@ -3267,10 +3278,11 @@ static auto GetInstForLoad(Context& context, // The first ImportIRInst is added directly because the IR doesn't need to be // localized. import_ir_insts.push_back(import_ir_inst); - const auto* cursor_ir = context.import_irs().Get(import_ir_inst.ir_id).sem_ir; + const auto* cursor_ir = + context.import_irs().Get(import_ir_inst.ir_id()).sem_ir; while (true) { - auto cursor_inst = cursor_ir->insts().Get(import_ir_inst.inst_id); + auto cursor_inst = cursor_ir->insts().Get(import_ir_inst.inst_id()); auto import_ref = cursor_inst.TryAs(); if (!import_ref) { @@ -3280,12 +3292,12 @@ static auto GetInstForLoad(Context& context, import_ir_inst = cursor_ir->import_ir_insts().Get(import_ref->import_ir_inst_id); - cursor_ir = cursor_ir->import_irs().Get(import_ir_inst.ir_id).sem_ir; - import_ir_insts.push_back( - {.ir_id = AddImportIR(context, {.decl_id = SemIR::InstId::None, - .is_export = false, - .sem_ir = cursor_ir}), - .inst_id = import_ir_inst.inst_id}); + cursor_ir = cursor_ir->import_irs().Get(import_ir_inst.ir_id()).sem_ir; + import_ir_insts.push_back(SemIR::ImportIRInst( + AddImportIR(context, {.decl_id = SemIR::InstId::None, + .is_export = false, + .sem_ir = cursor_ir}), + import_ir_inst.inst_id())); } } @@ -3302,9 +3314,9 @@ auto LoadImportRef(Context& context, SemIR::InstId inst_id) -> void { // The last indirect instruction is the one to resolve. Pop it here because // Resolve will assign the constant. auto load_ir_inst = indirect_insts.pop_back_val(); - ImportRefResolver resolver(&context, load_ir_inst.ir_id); + ImportRefResolver resolver(&context, load_ir_inst.ir_id()); auto type_id = resolver.ResolveType(load_type_id); - auto constant_id = resolver.Resolve(load_ir_inst.inst_id); + auto constant_id = resolver.Resolve(load_ir_inst.inst_id()); // Replace the ImportRefUnloaded instruction with ImportRefLoaded. This // doesn't use ReplacePlaceholderImportedInst because it would trigger @@ -3318,8 +3330,8 @@ auto LoadImportRef(Context& context, SemIR::InstId inst_id) -> void { // Store the constant for both the ImportRefLoaded and indirect instructions. context.constant_values().Set(inst_id, constant_id); for (const auto& import_ir_inst : indirect_insts) { - context.import_ir_constant_values()[import_ir_inst.ir_id.index].Set( - import_ir_inst.inst_id, constant_id); + context.import_ir_constant_values()[import_ir_inst.ir_id().index].Set( + import_ir_inst.inst_id(), constant_id); } } @@ -3370,8 +3382,9 @@ auto CheckCompatibleImportedNodeKind(Context& context, SemIR::ImportIRInstId imported_loc_id, SemIR::InstKind kind) -> void { auto& import_ir_inst = context.import_ir_insts().Get(imported_loc_id); - const auto* import_ir = context.import_irs().Get(import_ir_inst.ir_id).sem_ir; - auto imported_kind = import_ir->insts().Get(import_ir_inst.inst_id).kind(); + const auto* import_ir = + context.import_irs().Get(import_ir_inst.ir_id()).sem_ir; + auto imported_kind = import_ir->insts().Get(import_ir_inst.inst_id()).kind(); CARBON_CHECK( HasCompatibleImportedNodeKind(imported_kind, kind), "Node of kind {0} created with location of imported node of kind {1}", diff --git a/toolchain/check/import_ref.h b/toolchain/check/import_ref.h index b22872da49e1..32bbaac19089 100644 --- a/toolchain/check/import_ref.h +++ b/toolchain/check/import_ref.h @@ -11,9 +11,10 @@ namespace Carbon::Check { -// Sets the IR for ImportIRId::ApiForImpl. Should be called before AddImportIR -// in order to ensure the correct ID is assigned. -auto SetApiImportIR(Context& context, SemIR::ImportIR import_ir) -> void; +// Sets the IRs for `ImportIRId::ApiForImpl` from `import_ir`, and +// `ImportIRId::Cpp` from defaults. Should be called before `AddImportIR` in +// order to ensure the correct IDs are assigned. +auto SetSpecialImportIRs(Context& context, SemIR::ImportIR import_ir) -> void; // Adds an ImportIR, returning the ID. May use an existing ID if already added. auto AddImportIR(Context& context, SemIR::ImportIR import_ir) diff --git a/toolchain/check/testdata/basics/builtin_insts.carbon b/toolchain/check/testdata/basics/builtin_insts.carbon index 2872f7b1e06a..247c57ae056f 100644 --- a/toolchain/check/testdata/basics/builtin_insts.carbon +++ b/toolchain/check/testdata/basics/builtin_insts.carbon @@ -15,6 +15,7 @@ // CHECK:STDOUT: sem_ir: // CHECK:STDOUT: import_irs: // CHECK:STDOUT: ir0: {decl_id: inst, is_export: false} +// CHECK:STDOUT: ir1: {decl_id: inst, is_export: false} // CHECK:STDOUT: import_ir_insts: {} // CHECK:STDOUT: name_scopes: // CHECK:STDOUT: name_scope0: {inst: inst14, parent_scope: name_scope, has_error: false, extended_scopes: [], names: {}} diff --git a/toolchain/check/testdata/interop/cpp/no_prelude/bad_import.carbon b/toolchain/check/testdata/interop/cpp/no_prelude/bad_import.carbon index 237a50c7a7e6..bde31504fe55 100644 --- a/toolchain/check/testdata/interop/cpp/no_prelude/bad_import.carbon +++ b/toolchain/check/testdata/interop/cpp/no_prelude/bad_import.carbon @@ -22,18 +22,18 @@ import Cpp; library "[[@TEST_NAME]]"; -// CHECK:STDERR: fail_import_cpp_library_empty.carbon:[[@LINE+4]]:1: error: `Cpp` import missing library [CppInteropMissingLibrary] +// CHECK:STDERR: fail_import_cpp_library_empty.carbon:[[@LINE+9]]:1: error: `Cpp` import missing library [CppInteropMissingLibrary] // CHECK:STDERR: import Cpp library ""; // CHECK:STDERR: ^~~~~~~~~~~~~~~~~~~~~~ // CHECK:STDERR: -import Cpp library ""; - -// --- fail_import_cpp_library_file_with_quotes.carbon -// CHECK:STDERR: fail_import_cpp_library_file_with_quotes.carbon: error: C++: +// 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]]"; diff --git a/toolchain/check/testdata/interop/cpp/no_prelude/cpp_diagnostics.carbon b/toolchain/check/testdata/interop/cpp/no_prelude/cpp_diagnostics.carbon index e86f0573173c..491655321675 100644 --- a/toolchain/check/testdata/interop/cpp/no_prelude/cpp_diagnostics.carbon +++ b/toolchain/check/testdata/interop/cpp/no_prelude/cpp_diagnostics.carbon @@ -10,15 +10,15 @@ // --- 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 -// CHECK:STDERR: fail_import_cpp_file_with_one_error.carbon: 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:2:2: error: "error1" -// CHECK:STDERR: 2 | #error "error1" -// CHECK:STDERR: | ^ -// CHECK:STDERR: [CppInteropParseError] library "[[@TEST_NAME]]"; @@ -30,16 +30,16 @@ 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" // --- fail_import_cpp_file_with_multiple_errors.carbon -// CHECK:STDERR: fail_import_cpp_file_with_multiple_errors.carbon: 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:2:2: error: "error1" -// CHECK:STDERR: 2 | #error "error1" -// CHECK:STDERR: | ^ -// CHECK:STDERR: [CppInteropParseError] library "[[@TEST_NAME]]"; @@ -47,10 +47,10 @@ library "[[@TEST_NAME]]"; // CHECK:STDERR: import Cpp library "multiple_errors.h"; // CHECK:STDERR: ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // CHECK:STDERR: -// CHECK:STDERR: fail_import_cpp_file_with_multiple_errors.carbon: error: C++: +// 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:3:2: error: "error2" -// CHECK:STDERR: 3 | #error "error2" +// CHECK:STDERR: ./multiple_errors.h:9:2: error: "error2" +// CHECK:STDERR: 9 | #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] @@ -61,15 +61,15 @@ 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 -// CHECK:STDERR: import_cpp_file_with_one_warning.carbon: 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:2:2: warning: "warning1" -// CHECK:STDERR: 2 | #warning "warning1" -// CHECK:STDERR: | ^ -// CHECK:STDERR: [CppInteropParseWarning] library "[[@TEST_NAME]]"; @@ -81,17 +81,17 @@ 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" // --- import_cpp_file_with_multiple_warnings.carbon -// CHECK:STDERR: import_cpp_file_with_multiple_warnings.carbon: 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:2:2: warning: "warning1" -// CHECK:STDERR: 2 | #warning "warning1" -// CHECK:STDERR: | ^ -// CHECK:STDERR: [CppInteropParseWarning] library "[[@TEST_NAME]]"; @@ -99,20 +99,20 @@ library "[[@TEST_NAME]]"; // CHECK:STDERR: import Cpp library "multiple_warnings.h"; // CHECK:STDERR: ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // CHECK:STDERR: -// CHECK:STDERR: import_cpp_file_with_multiple_warnings.carbon: warning: C++: +// 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:3:2: warning: "warning2" -// CHECK:STDERR: 3 | #warning "warning2" +// CHECK:STDERR: ./multiple_warnings.h:9:2: warning: "warning2" +// CHECK:STDERR: 9 | #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: import_cpp_file_with_multiple_warnings.carbon: warning: C++: +// 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:4:2: warning: "warning3" -// CHECK:STDERR: 4 | #warning "warning3" +// CHECK:STDERR: ./multiple_warnings.h:10:2: warning: "warning3" +// CHECK:STDERR: 10 | #warning "warning3" // CHECK:STDERR: | ^ // CHECK:STDERR: [CppInteropParseWarning] // CHECK:STDERR: import_cpp_file_with_multiple_warnings.carbon:[[@LINE+4]]:1: note: in `Cpp` import [InCppImport] @@ -123,16 +123,16 @@ 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" // --- fail_import_cpp_file_with_one_error_and_one_warning.carbon -// CHECK:STDERR: fail_import_cpp_file_with_one_error_and_one_warning.carbon: 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:2:2: error: "error1" -// CHECK:STDERR: 2 | #error "error1" -// CHECK:STDERR: | ^ -// CHECK:STDERR: [CppInteropParseError] library "[[@TEST_NAME]]"; @@ -140,10 +140,10 @@ library "[[@TEST_NAME]]"; // CHECK:STDERR: import Cpp library "one_error_and_one_warning.h"; // CHECK:STDERR: ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // CHECK:STDERR: -// CHECK:STDERR: fail_import_cpp_file_with_one_error_and_one_warning.carbon: warning: C++: +// 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:3:2: warning: "warning1" -// CHECK:STDERR: 3 | #warning "warning1" +// CHECK:STDERR: ./one_error_and_one_warning.h:9:2: warning: "warning1" +// CHECK:STDERR: 9 | #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] @@ -154,6 +154,12 @@ 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" @@ -161,227 +167,242 @@ import Cpp library "one_error_and_one_warning.h"; #warning "warning3" // --- fail_import_cpp_file_with_multiple_errors_and_multiple_warnings.carbon -// CHECK:STDERR: fail_import_cpp_file_with_multiple_errors_and_multiple_warnings.carbon: 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:2:2: error: "error1" -// CHECK:STDERR: 2 | #error "error1" -// CHECK:STDERR: | ^ -// CHECK:STDERR: [CppInteropParseError] library "[[@TEST_NAME]]"; -// CHECK:STDERR: fail_import_cpp_file_with_multiple_errors_and_multiple_warnings.carbon:[[@LINE+44]]:1: note: in `Cpp` import [InCppImport] +// 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: fail_import_cpp_file_with_multiple_errors_and_multiple_warnings.carbon: error: C++: +// 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:3:2: error: "error2" -// CHECK:STDERR: 3 | #error "error2" +// CHECK:STDERR: ./multiple_errors_and_multiple_warnings.h:9:2: error: "error2" +// CHECK:STDERR: 9 | #error "error2" // CHECK:STDERR: | ^ // CHECK:STDERR: [CppInteropParseError] -// CHECK:STDERR: fail_import_cpp_file_with_multiple_errors_and_multiple_warnings.carbon:[[@LINE+34]]:1: note: in `Cpp` import [InCppImport] +// 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: fail_import_cpp_file_with_multiple_errors_and_multiple_warnings.carbon: warning: C++: +// 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:4:2: warning: "warning1" -// CHECK:STDERR: 4 | #warning "warning1" +// CHECK:STDERR: ./multiple_errors_and_multiple_warnings.h:10:2: warning: "warning1" +// CHECK:STDERR: 10 | #warning "warning1" // CHECK:STDERR: | ^ // CHECK:STDERR: [CppInteropParseWarning] -// CHECK:STDERR: fail_import_cpp_file_with_multiple_errors_and_multiple_warnings.carbon:[[@LINE+24]]:1: note: in `Cpp` import [InCppImport] +// 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: -// CHECK:STDERR: fail_import_cpp_file_with_multiple_errors_and_multiple_warnings.carbon: warning: C++: +// 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:5:2: warning: "warning2" -// CHECK:STDERR: 5 | #warning "warning2" +// CHECK:STDERR: ./multiple_errors_and_multiple_warnings.h:11:2: warning: "warning2" +// CHECK:STDERR: 11 | #warning "warning2" // CHECK:STDERR: | ^ // CHECK:STDERR: [CppInteropParseWarning] -// CHECK:STDERR: fail_import_cpp_file_with_multiple_errors_and_multiple_warnings.carbon:[[@LINE+14]]:1: note: in `Cpp` import [InCppImport] +// 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: fail_import_cpp_file_with_multiple_errors_and_multiple_warnings.carbon: warning: C++: +// 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:6:2: warning: "warning3" -// CHECK:STDERR: 6 | #warning "warning3" +// CHECK:STDERR: ./multiple_errors_and_multiple_warnings.h:12:2: warning: "warning3" +// CHECK:STDERR: 12 | #warning "warning3" // CHECK:STDERR: | ^ // CHECK:STDERR: [CppInteropParseWarning] -// CHECK:STDERR: fail_import_cpp_file_with_multiple_errors_and_multiple_warnings.carbon:[[@LINE+4]]:1: note: in `Cpp` import [InCppImport] +// 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: | ^ +// CHECK:STDERR: [CppInteropParseWarning] import Cpp library "multiple_errors_and_multiple_warnings.h"; // --- import_multiple_cpp_files_with_warnings.carbon -// CHECK:STDERR: import_multiple_cpp_files_with_warnings.carbon: 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:2:2: warning: "warning1" -// CHECK:STDERR: 2 | #warning "warning1" -// CHECK:STDERR: | ^ -// CHECK:STDERR: [CppInteropParseWarning] library "[[@TEST_NAME]]"; import Cpp library "one_warning.h"; -// CHECK:STDERR: import_multiple_cpp_files_with_warnings.carbon:[[@LINE+34]]:1: note: in `Cpp` import [InCppImport] +// 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: import_multiple_cpp_files_with_warnings.carbon: warning: C++: +// 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:2:2: warning: "warning1" -// CHECK:STDERR: 2 | #warning "warning1" +// CHECK:STDERR: ./multiple_warnings.h:8:2: warning: "warning1" +// CHECK:STDERR: 8 | #warning "warning1" // CHECK:STDERR: | ^ // CHECK:STDERR: [CppInteropParseWarning] -// CHECK:STDERR: import_multiple_cpp_files_with_warnings.carbon:[[@LINE+24]]:1: note: in `Cpp` import [InCppImport] +// 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: import_multiple_cpp_files_with_warnings.carbon: warning: C++: +// 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:3:2: warning: "warning2" -// CHECK:STDERR: 3 | #warning "warning2" +// CHECK:STDERR: ./multiple_warnings.h:9:2: warning: "warning2" +// CHECK:STDERR: 9 | #warning "warning2" // CHECK:STDERR: | ^ // CHECK:STDERR: [CppInteropParseWarning] -// CHECK:STDERR: import_multiple_cpp_files_with_warnings.carbon:[[@LINE+14]]:1: note: in `Cpp` import [InCppImport] +// 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: import_multiple_cpp_files_with_warnings.carbon: warning: C++: +// 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:4:2: warning: "warning3" -// CHECK:STDERR: 4 | #warning "warning3" +// CHECK:STDERR: ./multiple_warnings.h:10:2: warning: "warning3" +// CHECK:STDERR: 10 | #warning "warning3" // CHECK:STDERR: | ^ // CHECK:STDERR: [CppInteropParseWarning] -// CHECK:STDERR: import_multiple_cpp_files_with_warnings.carbon:[[@LINE+4]]:1: note: in `Cpp` import [InCppImport] +// 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_warnings_and_errors.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: | ^ +// CHECK:STDERR: [CppInteropParseError] import Cpp library "multiple_warnings.h"; // --- fail_import_multiple_cpp_files_with_warnings_and_errors.carbon -// CHECK:STDERR: fail_import_multiple_cpp_files_with_warnings_and_errors.carbon: error: C++: -// CHECK:STDERR: In file included from fail_import_multiple_cpp_files_with_warnings_and_errors.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] library "[[@TEST_NAME]]"; import Cpp library "one_error_and_one_warning.h"; -// CHECK:STDERR: fail_import_multiple_cpp_files_with_warnings_and_errors.carbon:[[@LINE+64]]:1: note: in `Cpp` import [InCppImport] +// CHECK:STDERR: fail_import_multiple_cpp_files_with_warnings_and_errors.carbon:[[@LINE+66]]:1: note: in `Cpp` import [InCppImport] // CHECK:STDERR: import Cpp library "multiple_errors_and_multiple_warnings.h"; // CHECK:STDERR: ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // CHECK:STDERR: -// CHECK:STDERR: fail_import_multiple_cpp_files_with_warnings_and_errors.carbon: warning: C++: +// CHECK:STDERR: ./one_error_and_one_warning.h:9: warning: C++: // CHECK:STDERR: In file included from fail_import_multiple_cpp_files_with_warnings_and_errors.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: ./one_error_and_one_warning.h:9:2: warning: "warning1" +// CHECK:STDERR: 9 | #warning "warning1" // CHECK:STDERR: | ^ // CHECK:STDERR: [CppInteropParseWarning] -// CHECK:STDERR: fail_import_multiple_cpp_files_with_warnings_and_errors.carbon:[[@LINE+54]]:1: note: in `Cpp` import [InCppImport] +// CHECK:STDERR: fail_import_multiple_cpp_files_with_warnings_and_errors.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: fail_import_multiple_cpp_files_with_warnings_and_errors.carbon: error: C++: +// CHECK:STDERR: ./multiple_errors_and_multiple_warnings.h:8: error: C++: // CHECK:STDERR: In file included from fail_import_multiple_cpp_files_with_warnings_and_errors.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: ./multiple_errors_and_multiple_warnings.h:8:2: error: "error1" +// CHECK:STDERR: 8 | #error "error1" // CHECK:STDERR: | ^ // CHECK:STDERR: [CppInteropParseError] -// CHECK:STDERR: fail_import_multiple_cpp_files_with_warnings_and_errors.carbon:[[@LINE+44]]:1: note: in `Cpp` import [InCppImport] +// CHECK:STDERR: fail_import_multiple_cpp_files_with_warnings_and_errors.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: fail_import_multiple_cpp_files_with_warnings_and_errors.carbon: error: C++: +// CHECK:STDERR: ./multiple_errors_and_multiple_warnings.h:9: error: C++: // CHECK:STDERR: In file included from fail_import_multiple_cpp_files_with_warnings_and_errors.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: ./multiple_errors_and_multiple_warnings.h:9:2: error: "error2" +// CHECK:STDERR: 9 | #error "error2" // CHECK:STDERR: | ^ // CHECK:STDERR: [CppInteropParseError] -// CHECK:STDERR: fail_import_multiple_cpp_files_with_warnings_and_errors.carbon:[[@LINE+34]]:1: note: in `Cpp` import [InCppImport] +// CHECK:STDERR: fail_import_multiple_cpp_files_with_warnings_and_errors.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: fail_import_multiple_cpp_files_with_warnings_and_errors.carbon: warning: C++: +// CHECK:STDERR: ./multiple_errors_and_multiple_warnings.h:10: warning: C++: // CHECK:STDERR: In file included from fail_import_multiple_cpp_files_with_warnings_and_errors.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: ./multiple_errors_and_multiple_warnings.h:10:2: warning: "warning1" +// CHECK:STDERR: 10 | #warning "warning1" // CHECK:STDERR: | ^ // CHECK:STDERR: [CppInteropParseWarning] -// CHECK:STDERR: fail_import_multiple_cpp_files_with_warnings_and_errors.carbon:[[@LINE+24]]:1: note: in `Cpp` import [InCppImport] +// CHECK:STDERR: fail_import_multiple_cpp_files_with_warnings_and_errors.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: fail_import_multiple_cpp_files_with_warnings_and_errors.carbon: warning: C++: +// CHECK:STDERR: ./multiple_errors_and_multiple_warnings.h:11: warning: C++: // CHECK:STDERR: In file included from fail_import_multiple_cpp_files_with_warnings_and_errors.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: ./multiple_errors_and_multiple_warnings.h:11:2: warning: "warning2" +// CHECK:STDERR: 11 | #warning "warning2" // CHECK:STDERR: | ^ // CHECK:STDERR: [CppInteropParseWarning] -// CHECK:STDERR: fail_import_multiple_cpp_files_with_warnings_and_errors.carbon:[[@LINE+14]]:1: note: in `Cpp` import [InCppImport] +// CHECK:STDERR: fail_import_multiple_cpp_files_with_warnings_and_errors.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: fail_import_multiple_cpp_files_with_warnings_and_errors.carbon: warning: C++: +// CHECK:STDERR: ./multiple_errors_and_multiple_warnings.h:12: warning: C++: // CHECK:STDERR: In file included from fail_import_multiple_cpp_files_with_warnings_and_errors.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: ./multiple_errors_and_multiple_warnings.h:12:2: warning: "warning3" +// CHECK:STDERR: 12 | #warning "warning3" // CHECK:STDERR: | ^ // CHECK:STDERR: [CppInteropParseWarning] -// CHECK:STDERR: fail_import_multiple_cpp_files_with_warnings_and_errors.carbon:[[@LINE+4]]:1: note: in `Cpp` import [InCppImport] +// CHECK:STDERR: fail_import_multiple_cpp_files_with_warnings_and_errors.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 "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 -// CHECK:STDERR: fail_import_indirect_error.carbon: error: C++: -// CHECK:STDERR: In file included from fail_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] library "[[@TEST_NAME]]"; -// CHECK:STDERR: fail_import_indirect_error.carbon:[[@LINE+4]]:1: note: in `Cpp` import [InCppImport] +// 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: ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // 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"; // --- 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 -// CHECK:STDERR: import_indirect_warning.carbon: warning: C++: -// CHECK:STDERR: In file included from 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] library "[[@TEST_NAME]]"; -// CHECK:STDERR: import_indirect_warning.carbon:[[@LINE+4]]:1: note: in `Cpp` import [InCppImport] +// 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" +// CHECK:STDERR: | ^ +// CHECK:STDERR: [CppInteropParseWarning] import Cpp library "indirect_warning.h"; +// --- fail_import_cpp_library_lexer_error.carbon + +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: +// CHECK:STDERR: fail_import_cpp_library_lexer_error.carbon:[[@LINE-7]]:44: error: trailing comments are not permitted [TrailingComment] +// CHECK:STDERR: library "import_cpp_library_lexer_error"; // Trailing comment +// CHECK:STDERR: ^ +// CHECK:STDERR: +import Cpp library "one_warning.h"; + // CHECK:STDOUT: --- fail_import_cpp_file_with_one_error.carbon // CHECK:STDOUT: // CHECK:STDOUT: imports { @@ -560,3 +581,20 @@ import Cpp library "indirect_warning.h"; // CHECK:STDOUT: } // CHECK:STDOUT: } // CHECK:STDOUT: +// CHECK:STDOUT: --- fail_import_cpp_library_lexer_error.carbon +// CHECK:STDOUT: +// CHECK:STDOUT: imports { +// CHECK:STDOUT: %Cpp: = namespace file.%Cpp.import_cpp, [concrete] { +// CHECK:STDOUT: import Cpp//... +// CHECK:STDOUT: } +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: file { +// CHECK:STDOUT: package: = namespace [concrete] { +// CHECK:STDOUT: .Cpp = imports.%Cpp +// CHECK:STDOUT: } +// CHECK:STDOUT: %Cpp.import_cpp = import_cpp { +// CHECK:STDOUT: import Cpp "one_warning.h" +// CHECK:STDOUT: } +// CHECK:STDOUT: } +// CHECK:STDOUT: diff --git a/toolchain/check/testdata/interop/cpp/no_prelude/file_not_found.carbon b/toolchain/check/testdata/interop/cpp/no_prelude/file_not_found.carbon index 40ea036cebbc..2b710ef1c78c 100644 --- a/toolchain/check/testdata/interop/cpp/no_prelude/file_not_found.carbon +++ b/toolchain/check/testdata/interop/cpp/no_prelude/file_not_found.carbon @@ -7,14 +7,14 @@ // TIP: bazel test //toolchain/testing:file_test --test_arg=--file_tests=toolchain/check/testdata/interop/cpp/no_prelude/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/no_prelude/file_not_found.carbon - -// --- fail_cpp_file_not_found.carbon -// CHECK:STDERR: fail_cpp_file_not_found.carbon: error: C++: +// 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] diff --git a/toolchain/driver/compile_subcommand.cpp b/toolchain/driver/compile_subcommand.cpp index a4eb7719f9f7..81e5446931bf 100644 --- a/toolchain/driver/compile_subcommand.cpp +++ b/toolchain/driver/compile_subcommand.cpp @@ -573,13 +573,13 @@ auto CompilationUnit::PostCheck() -> void { auto import_ir_inst = file->import_ir_insts().Get(loc_id.import_ir_inst_id()); const auto* import_file = - file->import_irs().Get(import_ir_inst.ir_id).sem_ir; + file->import_irs().Get(import_ir_inst.ir_id()).sem_ir; CARBON_CHECK(import_file); if (!IncludeInDumps(import_file->filename())) { return false; } file = import_file; - entity_inst_id = import_ir_inst.inst_id; + entity_inst_id = import_ir_inst.inst_id(); } }; diff --git a/toolchain/driver/testdata/compile/multifile_raw_and_textual_ir.carbon b/toolchain/driver/testdata/compile/multifile_raw_and_textual_ir.carbon index b7f9e2702f00..d763e252e6b1 100644 --- a/toolchain/driver/testdata/compile/multifile_raw_and_textual_ir.carbon +++ b/toolchain/driver/testdata/compile/multifile_raw_and_textual_ir.carbon @@ -31,6 +31,7 @@ fn B() { // CHECK:STDOUT: sem_ir: // CHECK:STDOUT: import_irs: // CHECK:STDOUT: ir0: {decl_id: inst, is_export: false} +// CHECK:STDOUT: ir1: {decl_id: inst, is_export: false} // CHECK:STDOUT: import_ir_insts: {} // CHECK:STDOUT: name_scopes: // CHECK:STDOUT: name_scope0: {inst: inst14, parent_scope: name_scope, has_error: false, extended_scopes: [], names: {name0: inst15}} @@ -105,10 +106,11 @@ fn B() { // CHECK:STDOUT: sem_ir: // CHECK:STDOUT: import_irs: // CHECK:STDOUT: ir0: {decl_id: inst, is_export: false} -// CHECK:STDOUT: ir1: {decl_id: inst15, is_export: false} +// CHECK:STDOUT: ir1: {decl_id: inst, is_export: false} +// CHECK:STDOUT: ir2: {decl_id: inst15, is_export: false} // CHECK:STDOUT: import_ir_insts: -// CHECK:STDOUT: import_ir_inst0: {ir_id: ir1, inst_id: inst15} -// CHECK:STDOUT: import_ir_inst1: {ir_id: ir1, inst_id: inst15} +// CHECK:STDOUT: import_ir_inst0: {ir_id: ir2, inst_id: inst15} +// CHECK:STDOUT: import_ir_inst1: {ir_id: ir2, inst_id: inst15} // CHECK:STDOUT: name_scopes: // CHECK:STDOUT: name_scope0: {inst: inst14, parent_scope: name_scope, has_error: false, extended_scopes: [], names: {name1: inst16, name0: inst17}} // CHECK:STDOUT: name_scope1: {inst: inst16, parent_scope: name_scope0, has_error: false, extended_scopes: [], names: {name1: inst22}} diff --git a/toolchain/driver/testdata/compile/multifile_raw_ir.carbon b/toolchain/driver/testdata/compile/multifile_raw_ir.carbon index 62aceb25f194..ae46624f4553 100644 --- a/toolchain/driver/testdata/compile/multifile_raw_ir.carbon +++ b/toolchain/driver/testdata/compile/multifile_raw_ir.carbon @@ -31,6 +31,7 @@ fn B() { // CHECK:STDOUT: sem_ir: // CHECK:STDOUT: import_irs: // CHECK:STDOUT: ir0: {decl_id: inst, is_export: false} +// CHECK:STDOUT: ir1: {decl_id: inst, is_export: false} // CHECK:STDOUT: import_ir_insts: {} // CHECK:STDOUT: name_scopes: // CHECK:STDOUT: name_scope0: {inst: inst14, parent_scope: name_scope, has_error: false, extended_scopes: [], names: {name0: inst15}} @@ -85,10 +86,11 @@ fn B() { // CHECK:STDOUT: sem_ir: // CHECK:STDOUT: import_irs: // CHECK:STDOUT: ir0: {decl_id: inst, is_export: false} -// CHECK:STDOUT: ir1: {decl_id: inst15, is_export: false} +// CHECK:STDOUT: ir1: {decl_id: inst, is_export: false} +// CHECK:STDOUT: ir2: {decl_id: inst15, is_export: false} // CHECK:STDOUT: import_ir_insts: -// CHECK:STDOUT: import_ir_inst0: {ir_id: ir1, inst_id: inst15} -// CHECK:STDOUT: import_ir_inst1: {ir_id: ir1, inst_id: inst15} +// CHECK:STDOUT: import_ir_inst0: {ir_id: ir2, inst_id: inst15} +// CHECK:STDOUT: import_ir_inst1: {ir_id: ir2, inst_id: inst15} // CHECK:STDOUT: name_scopes: // CHECK:STDOUT: name_scope0: {inst: inst14, parent_scope: name_scope, has_error: false, extended_scopes: [], names: {name1: inst16, name0: inst17}} // CHECK:STDOUT: name_scope1: {inst: inst16, parent_scope: name_scope0, has_error: false, extended_scopes: [], names: {name1: inst22}} diff --git a/toolchain/driver/testdata/compile/raw_and_textual_ir.carbon b/toolchain/driver/testdata/compile/raw_and_textual_ir.carbon index b620ff9f36f2..4b3568a474ec 100644 --- a/toolchain/driver/testdata/compile/raw_and_textual_ir.carbon +++ b/toolchain/driver/testdata/compile/raw_and_textual_ir.carbon @@ -21,6 +21,7 @@ fn Foo(n: ()) -> ((), ()) { // CHECK:STDOUT: sem_ir: // CHECK:STDOUT: import_irs: // CHECK:STDOUT: ir0: {decl_id: inst, is_export: false} +// CHECK:STDOUT: ir1: {decl_id: inst, is_export: false} // CHECK:STDOUT: import_ir_insts: {} // CHECK:STDOUT: name_scopes: // CHECK:STDOUT: name_scope0: {inst: inst14, parent_scope: name_scope, has_error: false, extended_scopes: [], names: {name0: inst34}} diff --git a/toolchain/driver/testdata/compile/raw_ir.carbon b/toolchain/driver/testdata/compile/raw_ir.carbon index c2d185e599bf..d58ea3bbf1e0 100644 --- a/toolchain/driver/testdata/compile/raw_ir.carbon +++ b/toolchain/driver/testdata/compile/raw_ir.carbon @@ -21,6 +21,7 @@ fn Foo[T:! type](n: T) -> (T, ()) { // CHECK:STDOUT: sem_ir: // CHECK:STDOUT: import_irs: // CHECK:STDOUT: ir0: {decl_id: inst, is_export: false} +// CHECK:STDOUT: ir1: {decl_id: inst, is_export: false} // CHECK:STDOUT: import_ir_insts: {} // CHECK:STDOUT: name_scopes: // CHECK:STDOUT: name_scope0: {inst: inst14, parent_scope: name_scope, has_error: false, extended_scopes: [], names: {name0: inst36}} diff --git a/toolchain/sem_ir/absolute_node_id.cpp b/toolchain/sem_ir/absolute_node_id.cpp index 564f11bcac49..c2439d03efd3 100644 --- a/toolchain/sem_ir/absolute_node_id.cpp +++ b/toolchain/sem_ir/absolute_node_id.cpp @@ -15,7 +15,8 @@ static auto FollowImportRef( const File*& cursor_ir, InstId& cursor_inst_id, ImportIRInstId import_ir_inst_id) -> void { auto import_ir_inst = cursor_ir->import_ir_insts().Get(import_ir_inst_id); - const auto& import_ir = cursor_ir->import_irs().Get(import_ir_inst.ir_id); + CARBON_CHECK(import_ir_inst.ir_id() != ImportIRId::Cpp); + const auto& import_ir = cursor_ir->import_irs().Get(import_ir_inst.ir_id()); CARBON_CHECK(import_ir.decl_id.has_value(), "If we get `None` locations here, we may need to more " "thoroughly track ImportDecls."); @@ -31,9 +32,9 @@ static auto FollowImportRef( auto implicit_import_ir_inst = cursor_ir->import_ir_insts().Get(import_loc_id.import_ir_inst_id()); const auto& implicit_ir = - cursor_ir->import_irs().Get(implicit_import_ir_inst.ir_id); - auto implicit_loc_id = - implicit_ir.sem_ir->insts().GetLocId(implicit_import_ir_inst.inst_id); + cursor_ir->import_irs().Get(implicit_import_ir_inst.ir_id()); + auto implicit_loc_id = implicit_ir.sem_ir->insts().GetLocId( + implicit_import_ir_inst.inst_id()); CARBON_CHECK(implicit_loc_id.kind() == SemIR::LocId::Kind::NodeId, "Should only be one layer of implicit imports"); absolute_node_ids.push_back( @@ -54,7 +55,7 @@ static auto FollowImportRef( } cursor_ir = import_ir.sem_ir; - cursor_inst_id = import_ir_inst.inst_id; + cursor_inst_id = import_ir_inst.inst_id(); } // Returns true if this is the final parse node location. If the location is is diff --git a/toolchain/sem_ir/expr_info.cpp b/toolchain/sem_ir/expr_info.cpp index 4c26eb1edda3..34e91f2ae57a 100644 --- a/toolchain/sem_ir/expr_info.cpp +++ b/toolchain/sem_ir/expr_info.cpp @@ -50,8 +50,8 @@ auto GetExprCategory(const File& file, InstId inst_id) -> ExprCategory { case ImportRefLoaded::Kind: { auto import_ir_inst = ir->import_ir_insts().Get( untyped_inst.As().import_ir_inst_id); - ir = ir->import_irs().Get(import_ir_inst.ir_id).sem_ir; - inst_id = import_ir_inst.inst_id; + ir = ir->import_irs().Get(import_ir_inst.ir_id()).sem_ir; + inst_id = import_ir_inst.inst_id(); continue; } diff --git a/toolchain/sem_ir/file.h b/toolchain/sem_ir/file.h index f3b18f288129..d3c153b614a9 100644 --- a/toolchain/sem_ir/file.h +++ b/toolchain/sem_ir/file.h @@ -198,6 +198,7 @@ class File : public Printable { return import_cpps_; } auto cpp_ast() -> clang::ASTUnit* { return cpp_ast_; } + auto cpp_ast() const -> const clang::ASTUnit* { return cpp_ast_; } // TODO: When the AST can be created before creating `File`, initialize the // pointer in the constructor and remove this function. This is part of // https://github.com/carbon-language/carbon-lang/issues/4666 @@ -231,6 +232,13 @@ class File : public Printable { return expr_regions_; } + auto clang_source_locs() -> ValueStore& { + return clang_source_locs_; + } + auto clang_source_locs() const -> const ValueStore& { + return clang_source_locs_; + } + auto top_inst_block_id() const -> InstBlockId { return top_inst_block_id_; } auto set_top_inst_block_id(InstBlockId block_id) -> void { top_inst_block_id_ = block_id; @@ -354,6 +362,9 @@ class File : public Printable { // Single-entry/single-exit regions that are referenced as units, e.g. because // they represent expressions. ValueStore expr_regions_; + + // C++ source locations for C++ interop. + ValueStore clang_source_locs_; }; } // namespace Carbon::SemIR diff --git a/toolchain/sem_ir/formatter.cpp b/toolchain/sem_ir/formatter.cpp index cee2facc8f2b..f85ab8a3dac8 100644 --- a/toolchain/sem_ir/formatter.cpp +++ b/toolchain/sem_ir/formatter.cpp @@ -566,7 +566,7 @@ class FormatterImpl { auto loc_id = sem_ir_->insts().GetLocId(first_owning_decl_id); if (loc_id.kind() == SemIR::LocId::Kind::ImportIRInstId) { auto import_ir_id = - sem_ir_->import_ir_insts().Get(loc_id.import_ir_inst_id()).ir_id; + sem_ir_->import_ir_insts().Get(loc_id.import_ir_inst_id()).ir_id(); const auto* import_file = sem_ir_->import_irs().Get(import_ir_id).sem_ir; pending_imported_from_ = import_file->filename(); @@ -1149,7 +1149,7 @@ class FormatterImpl { llvm::StringLiteral loaded_label) -> void { out_ << " "; auto import_ir_inst = sem_ir_->import_ir_insts().Get(import_ir_inst_id); - FormatArg(import_ir_inst.ir_id); + FormatArg(import_ir_inst.ir_id()); out_ << ", "; if (entity_name_id.has_value()) { // Prefer to show the entity name when possible. @@ -1157,17 +1157,18 @@ class FormatterImpl { } else { // Show a name based on the location when possible, or the numeric // instruction as a last resort. - const auto& import_ir = sem_ir_->import_irs().Get(import_ir_inst.ir_id); - auto loc_id = import_ir.sem_ir->insts().GetLocId(import_ir_inst.inst_id); + const auto& import_ir = sem_ir_->import_irs().Get(import_ir_inst.ir_id()); + auto loc_id = + import_ir.sem_ir->insts().GetLocId(import_ir_inst.inst_id()); switch (loc_id.kind()) { case SemIR::LocId::Kind::None: { - out_ << import_ir_inst.inst_id << " [no loc]"; + out_ << import_ir_inst.inst_id() << " [no loc]"; break; } case SemIR::LocId::Kind::ImportIRInstId: { // TODO: Probably don't want to format each indirection, but maybe // reuse GetCanonicalImportIRInst? - out_ << import_ir_inst.inst_id << " [indirect]"; + out_ << import_ir_inst.inst_id() << " [indirect]"; break; } case SemIR::LocId::Kind::NodeId: { diff --git a/toolchain/sem_ir/ids.h b/toolchain/sem_ir/ids.h index ff0c034b5a4d..0526cfea1f82 100644 --- a/toolchain/sem_ir/ids.h +++ b/toolchain/sem_ir/ids.h @@ -14,10 +14,19 @@ #include "toolchain/diagnostics/diagnostic_emitter.h" #include "toolchain/parse/node_ids.h" +// NOLINTNEXTLINE(readability-identifier-naming) +namespace clang { + +// Forward declare indexed types, for integration with ValueStore. +class SourceLocation; + +} // namespace clang + namespace Carbon::SemIR { // Forward declare indexed types, for integration with ValueStore. class File; +class ImportIRInst; class Inst; class NameScope; struct AssociatedConstant; @@ -32,7 +41,6 @@ struct Specific; struct SpecificInterface; struct ImportCpp; struct ImportIR; -struct ImportIRInst; struct Impl; struct Interface; struct StructTypeField; @@ -409,10 +417,15 @@ struct ImportIRId : public IdBase { // instructions. static const ImportIRId ApiForImpl; + // The `Cpp` import. A null entry is added if there is none, in which case + // this ID should not show up in instructions. + static const ImportIRId Cpp; + using IdBase::IdBase; }; constexpr ImportIRId ImportIRId::ApiForImpl = ImportIRId(0); +constexpr ImportIRId ImportIRId::Cpp = ImportIRId(ApiForImpl.index + 1); // A boolean value. struct BoolValue : public IdBase { @@ -757,6 +770,14 @@ struct TypeId : public IdBase { auto Print(llvm::raw_ostream& out) const -> void; }; +// The ID of a Clang Source Location. +struct ClangSourceLocId : public IdBase { + static constexpr llvm::StringLiteral Label = "clang_source_loc"; + using ValueType = clang::SourceLocation; + + using IdBase::IdBase; +}; + // An index for element access, for structs, tuples, and classes. struct ElementIndex : public IndexBase { static constexpr llvm::StringLiteral Label = "element"; diff --git a/toolchain/sem_ir/import_ir.h b/toolchain/sem_ir/import_ir.h index 4b9aef09d414..a47f8fbaf2b8 100644 --- a/toolchain/sem_ir/import_ir.h +++ b/toolchain/sem_ir/import_ir.h @@ -29,19 +29,57 @@ struct ImportIR : public Printable { static_assert(sizeof(ImportIR) == 8 + sizeof(uintptr_t), "Unexpected size"); // A reference to an instruction in an imported IR. Used for diagnostics with -// LocId. -struct ImportIRInst : public Printable { +// LocId. For a `Cpp` import, points to a Clang source location. +class ImportIRInst : public Printable { + public: + // Constructor for a non-`Cpp` import. + explicit ImportIRInst(ImportIRId ir_id, InstId inst_id) + : ir_id_(ir_id), inst_id_(inst_id) { + CARBON_CHECK(ir_id != ImportIRId::Cpp); + } + + // Constructor for a `Cpp` import. + explicit ImportIRInst(ClangSourceLocId clang_source_loc_id) + : ir_id_(SemIR::ImportIRId::Cpp), + clang_source_loc_id_(clang_source_loc_id) {} + auto Print(llvm::raw_ostream& out) const -> void { - out << "{ir_id: " << ir_id << ", inst_id: " << inst_id << "}"; + out << "{ir_id: " << ir_id() << ", "; + if (ir_id() == ImportIRId::Cpp) { + out << "clang_source_loc_id: " << clang_source_loc_id(); + } else { + out << "inst_id: " << inst_id(); + } + out << "}"; } friend auto operator==(const ImportIRInst& lhs, const ImportIRInst& rhs) -> bool { - return lhs.ir_id == rhs.ir_id && lhs.inst_id == rhs.inst_id; + return lhs.ir_id() == rhs.ir_id() && + (lhs.ir_id() == ImportIRId::Cpp + ? lhs.clang_source_loc_id() == rhs.clang_source_loc_id() + : lhs.inst_id() == rhs.inst_id()); } - ImportIRId ir_id; - InstId inst_id; + auto ir_id() const -> ImportIRId { return ir_id_; } + auto inst_id() const -> InstId { + CARBON_CHECK(ir_id() != ImportIRId::Cpp); + return inst_id_; + } + auto clang_source_loc_id() const -> ClangSourceLocId { + CARBON_CHECK(ir_id() == ImportIRId::Cpp); + return clang_source_loc_id_; + } + + private: + ImportIRId ir_id_; + union { + // Set iff `ir_id != ImportIRId::Cpp`. + InstId inst_id_; + + // Set iff `ir_id == ImportIRId::Cpp`. + ClangSourceLocId clang_source_loc_id_; + }; }; } // namespace Carbon::SemIR diff --git a/toolchain/sem_ir/inst_fingerprinter.cpp b/toolchain/sem_ir/inst_fingerprinter.cpp index 13bb9bacc2b0..817b8fa347fc 100644 --- a/toolchain/sem_ir/inst_fingerprinter.cpp +++ b/toolchain/sem_ir/inst_fingerprinter.cpp @@ -293,7 +293,8 @@ struct Worklist { auto Add(ImportIRInstId ir_inst_id) -> void { auto ir_inst = sem_ir->import_ir_insts().Get(ir_inst_id); - AddInFile(sem_ir->import_irs().Get(ir_inst.ir_id).sem_ir, ir_inst.inst_id); + AddInFile(sem_ir->import_irs().Get(ir_inst.ir_id()).sem_ir, + ir_inst.inst_id()); } template diff --git a/toolchain/sem_ir/inst_namer.cpp b/toolchain/sem_ir/inst_namer.cpp index 5d4dac58c12a..6f62d5f5a2bf 100644 --- a/toolchain/sem_ir/inst_namer.cpp +++ b/toolchain/sem_ir/inst_namer.cpp @@ -737,7 +737,7 @@ auto InstNamer::CollectNamesInBlock(ScopeId top_scope_id, auto import_ir_inst = sem_ir_->import_ir_insts().Get(inst.import_ir_inst_id); const auto& import_ir = - *sem_ir_->import_irs().Get(import_ir_inst.ir_id).sem_ir; + *sem_ir_->import_irs().Get(import_ir_inst.ir_id()).sem_ir; auto package_id = import_ir.package_id(); if (auto ident_id = package_id.AsIdentifierId(); ident_id.has_value()) { out << import_ir.identifiers().Get(ident_id); diff --git a/toolchain/sem_ir/yaml_test.cpp b/toolchain/sem_ir/yaml_test.cpp index ff8ae0bd6322..288e45aefcf9 100644 --- a/toolchain/sem_ir/yaml_test.cpp +++ b/toolchain/sem_ir/yaml_test.cpp @@ -56,7 +56,7 @@ TEST(SemIRTest, Yaml) { auto type_builtin = Pair(type_id, Yaml::Mapping(_)); auto file = Yaml::Mapping(ElementsAre( - Pair("import_irs", Yaml::Mapping(SizeIs(1))), + Pair("import_irs", Yaml::Mapping(SizeIs(2))), Pair("import_ir_insts", Yaml::Mapping(SizeIs(0))), Pair("name_scopes", Yaml::Mapping(SizeIs(1))), Pair("entity_names", Yaml::Mapping(SizeIs(1))),