Sfoglia il codice sorgente

Support `import Cpp;` to import `Cpp` namespace for using C++ builtins (#6320)

This allows writing
```
import Cpp;
```

Instead of writing
```
import Cpp inline "";
```

Part of #6330.
Boaz Brickner 6 mesi fa
parent
commit
b54f2dd592

+ 2 - 7
toolchain/check/check.cpp

@@ -79,12 +79,6 @@ static auto TrackImport(Map<ImportKey, UnitAndImports*>& 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<ImportKey, UnitAndImports*>& 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);

+ 1 - 1
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(

+ 56 - 10
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 "";

+ 3 - 3
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]

+ 2 - 2
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

+ 2 - 2
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

+ 1 - 1
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) {}

+ 37 - 0
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 {

+ 2 - 2
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 {}
 

+ 0 - 1
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)

+ 4 - 4
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";
   }