diff --git a/toolchain/check/check.cpp b/toolchain/check/check.cpp index a22299660ae5..8d1320772fba 100644 --- a/toolchain/check/check.cpp +++ b/toolchain/check/check.cpp @@ -79,12 +79,6 @@ static auto TrackImport(Map& api_map, // have diagnosed the use of `Cpp` in the declaration. return; } - if (!import.library_id.has_value() && !import.inline_body_id.has_value()) { - CARBON_DIAGNOSTIC(CppInteropMissingLibrary, Error, - "`Cpp` import without `library` or `inline`"); - unit_info.emitter.Emit(import.node_id, CppInteropMissingLibrary); - return; - } if (fuzzing) { // Clang is not crash-resilient. CARBON_DIAGNOSTIC(CppInteropFuzzing, Error, @@ -94,7 +88,8 @@ static auto TrackImport(Map& api_map, } unit_info.cpp_imports.push_back(import); return; - } else if (import.inline_body_id.has_value()) { + } + if (import.inline_body_id.has_value()) { CARBON_DIAGNOSTIC(InlineImportNotCpp, Error, "`inline` import not in package `Cpp`"); unit_info.emitter.Emit(import.node_id, InlineImportNotCpp); diff --git a/toolchain/check/cpp/import.cpp b/toolchain/check/cpp/import.cpp index a4b3f1d6dcfa..cef23fdb3ad1 100644 --- a/toolchain/check/cpp/import.cpp +++ b/toolchain/check/cpp/import.cpp @@ -102,7 +102,7 @@ static auto GenerateCppIncludesHeaderCode( << "\n"; // TODO: Inject a clang pragma here to produce an error if there are // unclosed scopes at the end of this inline C++ fragment. - } else { + } else if (import.library_id.has_value()) { // Translate `import Cpp library "foo.h";` into `#include "foo.h"`. GenerateLineMarker(context, code_stream, context.tokens().GetLineNumber( diff --git a/toolchain/check/testdata/interop/cpp/bad_import.carbon b/toolchain/check/testdata/interop/cpp/bad_import.carbon index deae0a010589..7219feea84ba 100644 --- a/toolchain/check/testdata/interop/cpp/bad_import.carbon +++ b/toolchain/check/testdata/interop/cpp/bad_import.carbon @@ -10,16 +10,6 @@ // TIP: To dump output, run: // TIP: bazel run //toolchain/testing:file_test -- --dump_output --file_tests=toolchain/check/testdata/interop/cpp/bad_import.carbon -// --- fail_import_cpp.carbon - -library "[[@TEST_NAME]]"; - -// CHECK:STDERR: fail_import_cpp.carbon:[[@LINE+4]]:1: error: `Cpp` import without `library` or `inline` [CppInteropMissingLibrary] -// CHECK:STDERR: import Cpp; -// CHECK:STDERR: ^~~~~~~~~~~ -// CHECK:STDERR: -import Cpp; - // --- fail_import_cpp_library_empty.carbon library "[[@TEST_NAME]]"; @@ -52,3 +42,59 @@ void f() { import Cpp inline '''c++ } '''; + +// --- fail_import_cpp_library_without_name_and_inline_without_content.carbon + +library "[[@TEST_NAME]]"; + +// CHECK:STDERR: fail_import_cpp_library_without_name_and_inline_without_content.carbon:[[@LINE+8]]:20: error: expected a string literal to specify the library name [ExpectedLibraryName] +// CHECK:STDERR: import Cpp library inline; +// CHECK:STDERR: ^~~~~~ +// CHECK:STDERR: +// CHECK:STDERR: fail_import_cpp_library_without_name_and_inline_without_content.carbon:[[@LINE+4]]:20: error: semantics TODO: `handle invalid parse trees in `check`` [SemanticsTodo] +// CHECK:STDERR: import Cpp library inline; +// CHECK:STDERR: ^~~~~~ +// CHECK:STDERR: +import Cpp library inline; + +// --- fail_import_cpp_library_with_name_and_inline_without_content.carbon + +library "[[@TEST_NAME]]"; + +// CHECK:STDERR: fail_import_cpp_library_with_name_and_inline_without_content.carbon:[[@LINE+8]]:28: error: `import` declarations must end with a `;` [ExpectedDeclSemi] +// CHECK:STDERR: import Cpp library "foo.h" inline; +// CHECK:STDERR: ^~~~~~ +// CHECK:STDERR: +// CHECK:STDERR: fail_import_cpp_library_with_name_and_inline_without_content.carbon:[[@LINE+4]]:1: error: semantics TODO: `handle invalid parse trees in `check`` [SemanticsTodo] +// CHECK:STDERR: import Cpp library "foo.h" inline; +// CHECK:STDERR: ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// CHECK:STDERR: +import Cpp library "foo.h" inline; + +// --- fail_import_cpp_library_without_name_and_inline_with_content.carbon + +library "[[@TEST_NAME]]"; + +// CHECK:STDERR: fail_import_cpp_library_without_name_and_inline_with_content.carbon:[[@LINE+8]]:20: error: expected a string literal to specify the library name [ExpectedLibraryName] +// CHECK:STDERR: import Cpp library inline ""; +// CHECK:STDERR: ^~~~~~ +// CHECK:STDERR: +// CHECK:STDERR: fail_import_cpp_library_without_name_and_inline_with_content.carbon:[[@LINE+4]]:20: error: semantics TODO: `handle invalid parse trees in `check`` [SemanticsTodo] +// CHECK:STDERR: import Cpp library inline ""; +// CHECK:STDERR: ^~~~~~ +// CHECK:STDERR: +import Cpp library inline ""; + +// --- fail_import_cpp_library_with_name_and_inline_with_content.carbon + +library "[[@TEST_NAME]]"; + +// CHECK:STDERR: fail_import_cpp_library_with_name_and_inline_with_content.carbon:[[@LINE+8]]:28: error: `import` declarations must end with a `;` [ExpectedDeclSemi] +// CHECK:STDERR: import Cpp library "foo.h" inline ""; +// CHECK:STDERR: ^~~~~~ +// CHECK:STDERR: +// CHECK:STDERR: fail_import_cpp_library_with_name_and_inline_with_content.carbon:[[@LINE+4]]:1: error: semantics TODO: `handle invalid parse trees in `check`` [SemanticsTodo] +// CHECK:STDERR: import Cpp library "foo.h" inline ""; +// CHECK:STDERR: ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// CHECK:STDERR: +import Cpp library "foo.h" inline ""; diff --git a/toolchain/check/testdata/interop/cpp/builtins.carbon b/toolchain/check/testdata/interop/cpp/builtins.carbon index 5ec3f98a0fbe..c7d1c011cb82 100644 --- a/toolchain/check/testdata/interop/cpp/builtins.carbon +++ b/toolchain/check/testdata/interop/cpp/builtins.carbon @@ -14,7 +14,7 @@ library "[[@TEST_NAME]]"; -import Cpp inline ""; +import Cpp; fn F() { //@dump-sem-ir-begin @@ -48,7 +48,7 @@ fn F() { library "[[@TEST_NAME]]"; -import Cpp inline ""; +import Cpp; fn F() { //@dump-sem-ir-begin @@ -68,7 +68,7 @@ fn F() { library "[[@TEST_NAME]]"; -import Cpp inline ""; +import Cpp; fn F() { // CHECK:STDERR: fail_not_builtin.carbon:[[@LINE+4]]:21: error: member name `not_builtin` not found in `Cpp` [MemberNameNotFoundInInstScope] diff --git a/toolchain/check/testdata/interop/cpp/builtins.llp64.carbon b/toolchain/check/testdata/interop/cpp/builtins.llp64.carbon index c0af6588644b..90ee965782b9 100644 --- a/toolchain/check/testdata/interop/cpp/builtins.llp64.carbon +++ b/toolchain/check/testdata/interop/cpp/builtins.llp64.carbon @@ -15,7 +15,7 @@ library "[[@TEST_NAME]]"; -import Cpp inline ""; +import Cpp; fn F() { //@dump-sem-ir-begin @@ -31,7 +31,7 @@ fn F() { library "[[@TEST_NAME]]"; -import Cpp inline ""; +import Cpp; fn F() { //@dump-sem-ir-begin diff --git a/toolchain/check/testdata/interop/cpp/builtins.lp64.carbon b/toolchain/check/testdata/interop/cpp/builtins.lp64.carbon index 54a47fb1a5bb..2fc414dc0b62 100644 --- a/toolchain/check/testdata/interop/cpp/builtins.lp64.carbon +++ b/toolchain/check/testdata/interop/cpp/builtins.lp64.carbon @@ -15,7 +15,7 @@ library "[[@TEST_NAME]]"; -import Cpp inline ""; +import Cpp; fn F() { //@dump-sem-ir-begin @@ -31,7 +31,7 @@ fn F() { library "[[@TEST_NAME]]"; -import Cpp inline ""; +import Cpp; fn F() { //@dump-sem-ir-begin diff --git a/toolchain/check/testdata/interop/cpp/function/void_pointer.carbon b/toolchain/check/testdata/interop/cpp/function/void_pointer.carbon index 40b2391b9c9e..f81bc953dc43 100644 --- a/toolchain/check/testdata/interop/cpp/function/void_pointer.carbon +++ b/toolchain/check/testdata/interop/cpp/function/void_pointer.carbon @@ -88,7 +88,7 @@ fn F() { library "[[@TEST_NAME]]"; -import Cpp inline ""; +import Cpp; // CHECK:STDERR: fail_void.carbon:[[@LINE+5]]:6: error: parameter has incomplete type `Cpp.void` in function definition [IncompleteTypeInFunctionParam] // CHECK:STDERR: fn F(x: Cpp.void) {} diff --git a/toolchain/check/testdata/interop/cpp/import.carbon b/toolchain/check/testdata/interop/cpp/import.carbon index 827c2321289a..e13feba1ef88 100644 --- a/toolchain/check/testdata/interop/cpp/import.carbon +++ b/toolchain/check/testdata/interop/cpp/import.carbon @@ -115,6 +115,43 @@ fn F() { //@dump-sem-ir-end } +// ============================================================================ +// Import Cpp without a header +// ============================================================================ + +// --- no_header.carbon + +library "[[@TEST_NAME]]"; + +import Cpp; + +fn F(input: Cpp.int) { + let output: i32 = input; +} + +// ============================================================================ +// Import Cpp without a header, with a header and inline +// ============================================================================ + +// --- header_function.h + +auto MyHeaderFunction(int) -> void; + +// --- no_header_with_header_inline.carbon + +library "[[@TEST_NAME]]"; + +import Cpp; +import Cpp library "header_function.h"; +import Cpp inline ''' +auto MyInlineFunction(short) -> void; +'''; + +fn F() { + Cpp.MyHeaderFunction(8 as Cpp.int); + Cpp.MyInlineFunction(9 as Cpp.short); +} + // CHECK:STDOUT: --- fail_todo_import_struct_api.carbon // CHECK:STDOUT: // CHECK:STDOUT: constants { diff --git a/toolchain/check/testdata/interop/cpp/void_pointer.carbon b/toolchain/check/testdata/interop/cpp/void_pointer.carbon index ec06f42325c6..85bcdf970581 100644 --- a/toolchain/check/testdata/interop/cpp/void_pointer.carbon +++ b/toolchain/check/testdata/interop/cpp/void_pointer.carbon @@ -35,7 +35,7 @@ fn F(input: Cpp.S*) { library "[[@TEST_NAME]]"; -import Cpp inline ""; +import Cpp; class C {} @@ -77,7 +77,7 @@ fn F(input: Cpp.void*) { library "[[@TEST_NAME]]"; -import Cpp inline ""; +import Cpp; class C {} diff --git a/toolchain/diagnostics/diagnostic_kind.def b/toolchain/diagnostics/diagnostic_kind.def index bcac19f85eea..297a96a9cc3a 100644 --- a/toolchain/diagnostics/diagnostic_kind.def +++ b/toolchain/diagnostics/diagnostic_kind.def @@ -190,7 +190,6 @@ CARBON_DIAGNOSTIC_KIND(InCppTypeCompletion) // Package/import checking diagnostics. CARBON_DIAGNOSTIC_KIND(CppInteropFuzzing) -CARBON_DIAGNOSTIC_KIND(CppInteropMissingLibrary) CARBON_DIAGNOSTIC_KIND(CppInteropDriverError) CARBON_DIAGNOSTIC_KIND(CppInteropDriverWarning) CARBON_DIAGNOSTIC_KIND(CppInteropParseError) diff --git a/toolchain/sem_ir/formatter.cpp b/toolchain/sem_ir/formatter.cpp index 7ab977ed9cab..056bdf47a414 100644 --- a/toolchain/sem_ir/formatter.cpp +++ b/toolchain/sem_ir/formatter.cpp @@ -1260,14 +1260,14 @@ auto Formatter::FormatImportCppDeclRhs() -> void { } Indent(); - out_ << "import Cpp "; + out_ << "import Cpp"; if (import.library_id.has_value()) { - out_ << "\"" + out_ << " \"" << FormatEscaped( sem_ir_->string_literal_values().Get(import.library_id)) << "\""; - } else { - out_ << "inline"; + } else if (import.inline_body_id.has_value()) { + out_ << " inline"; } out_ << "\n"; }