mirror of
https://github.com/carbon-language/carbon-lang.git
synced 2026-10-04 19:11:11 +01:00
Support importing C++ _Nonnull pointers as function parameters or return values (#5773)
We avoid using canonical type before knowing it's not a pointer because
we need the nullability attribute.
No support for pointers to pointers, yet.
C++ Interop Demo:
```c++
// hello_world.h
auto hello_world_param(int* _Nonnull i) -> void;
auto hello_world_return() -> int* _Nonnull;
```
```c++
// hello_world.cpp
#include "hello_world.h"
#include <cstdio>
auto hello_world_param(int* _Nonnull i) -> void {
printf("hello_world: %d\n", *i);
}
static int x = 5;
auto hello_world_return() -> int* _Nonnull { return &x; }
```
```carbon
// main.carbon
library "Main";
import Core library "io";
import Cpp library "hello_world.h";
fn Run() -> i32 {
var i: i32 = 10;
Cpp.hello_world_param(&i);
let p: i32* = Cpp.hello_world_return();
Core.Print(*p);
return 0;
}
```
```shell
$ clang -c hello_world.cpp
$ ./bazel-bin/toolchain/install/prefix_root/bin/carbon compile main.carbon
$ ./bazel-bin/toolchain/install/prefix_root/bin/carbon link hello_world.o main.o --output=demo
$ ./demo
hello_world: 10
5
```
Part of #5772.
This commit is contained in:
+49
-34
@@ -34,7 +34,7 @@ fn F() {
|
||||
// CHECK:STDERR: Cpp.foo({});
|
||||
// CHECK:STDERR: ^~~~~~~
|
||||
// CHECK:STDERR:
|
||||
// CHECK:STDERR: fail_todo_import_decl_value_param_type.carbon:[[@LINE+7]]:3: error: semantics TODO: `Unsupported: parameter type: class C` [SemanticsTodo]
|
||||
// CHECK:STDERR: fail_todo_import_decl_value_param_type.carbon:[[@LINE+7]]:3: error: semantics TODO: `Unsupported: parameter type: C` [SemanticsTodo]
|
||||
// CHECK:STDERR: Cpp.foo({});
|
||||
// CHECK:STDERR: ^~~~~~~
|
||||
// CHECK:STDERR: fail_todo_import_decl_value_param_type.carbon:[[@LINE+4]]:3: note: in `Cpp` name lookup for `foo` [InCppNameLookup]
|
||||
@@ -63,7 +63,7 @@ fn F() {
|
||||
// CHECK:STDERR: ^
|
||||
// CHECK:STDERR:
|
||||
let c: Cpp.C;
|
||||
// CHECK:STDERR: fail_todo_import_decl_value_param_type_previously_imported.carbon:[[@LINE+7]]:3: error: semantics TODO: `Unsupported: parameter type: class C` [SemanticsTodo]
|
||||
// CHECK:STDERR: fail_todo_import_decl_value_param_type_previously_imported.carbon:[[@LINE+7]]:3: error: semantics TODO: `Unsupported: parameter type: C` [SemanticsTodo]
|
||||
// CHECK:STDERR: Cpp.foo(c);
|
||||
// CHECK:STDERR: ^~~~~~~
|
||||
// CHECK:STDERR: fail_todo_import_decl_value_param_type_previously_imported.carbon:[[@LINE+4]]:3: note: in `Cpp` name lookup for `foo` [InCppNameLookup]
|
||||
@@ -98,7 +98,7 @@ fn F() {
|
||||
// CHECK:STDERR: Cpp.foo1({});
|
||||
// CHECK:STDERR: ^~~~~~~~
|
||||
// CHECK:STDERR:
|
||||
// CHECK:STDERR: fail_todo_import_double_decl_value_param_type.carbon:[[@LINE+7]]:3: error: semantics TODO: `Unsupported: parameter type: class C` [SemanticsTodo]
|
||||
// CHECK:STDERR: fail_todo_import_double_decl_value_param_type.carbon:[[@LINE+7]]:3: error: semantics TODO: `Unsupported: parameter type: C` [SemanticsTodo]
|
||||
// CHECK:STDERR: Cpp.foo1({});
|
||||
// CHECK:STDERR: ^~~~~~~~
|
||||
// CHECK:STDERR: fail_todo_import_double_decl_value_param_type.carbon:[[@LINE+4]]:3: note: in `Cpp` name lookup for `foo1` [InCppNameLookup]
|
||||
@@ -106,7 +106,7 @@ fn F() {
|
||||
// CHECK:STDERR: ^~~~~~~~
|
||||
// CHECK:STDERR:
|
||||
Cpp.foo1({});
|
||||
// CHECK:STDERR: fail_todo_import_double_decl_value_param_type.carbon:[[@LINE+7]]:3: error: semantics TODO: `Unsupported: parameter type: class C` [SemanticsTodo]
|
||||
// CHECK:STDERR: fail_todo_import_double_decl_value_param_type.carbon:[[@LINE+7]]:3: error: semantics TODO: `Unsupported: parameter type: C` [SemanticsTodo]
|
||||
// CHECK:STDERR: Cpp.foo2({});
|
||||
// CHECK:STDERR: ^~~~~~~~
|
||||
// CHECK:STDERR: fail_todo_import_double_decl_value_param_type.carbon:[[@LINE+4]]:3: note: in `Cpp` name lookup for `foo2` [InCppNameLookup]
|
||||
@@ -283,7 +283,7 @@ fn F() {
|
||||
|
||||
class C;
|
||||
|
||||
auto foo(C*) -> void;
|
||||
auto foo(C* _Nonnull) -> void;
|
||||
|
||||
// --- fail_todo_import_decl_pointer_param_type.carbon
|
||||
|
||||
@@ -300,7 +300,7 @@ import Cpp library "decl_pointer_param_type.h";
|
||||
// CHECK:STDERR:
|
||||
fn F(c: Cpp.C*) {
|
||||
//@dump-sem-ir-begin
|
||||
// CHECK:STDERR: fail_todo_import_decl_pointer_param_type.carbon:[[@LINE+7]]:3: error: semantics TODO: `Unsupported: parameter type: class C *` [SemanticsTodo]
|
||||
// CHECK:STDERR: fail_todo_import_decl_pointer_param_type.carbon:[[@LINE+7]]:3: error: semantics TODO: `Unsupported: parameter type: C * _Nonnull` [SemanticsTodo]
|
||||
// CHECK:STDERR: Cpp.foo(c);
|
||||
// CHECK:STDERR: ^~~~~~~
|
||||
// CHECK:STDERR: fail_todo_import_decl_pointer_param_type.carbon:[[@LINE+4]]:3: note: in `Cpp` name lookup for `foo` [InCppNameLookup]
|
||||
@@ -319,9 +319,9 @@ fn F(c: Cpp.C*) {
|
||||
|
||||
class C {};
|
||||
|
||||
auto foo(C*) -> void;
|
||||
auto foo(C* _Nonnull) -> void;
|
||||
|
||||
// --- fail_todo_import_definition_pointer_param_type.carbon
|
||||
// --- import_definition_pointer_param_type.carbon
|
||||
|
||||
library "[[@TEST_NAME]]";
|
||||
|
||||
@@ -329,13 +329,6 @@ import Cpp library "definition_pointer_param_type.h";
|
||||
|
||||
fn F(c: Cpp.C*) {
|
||||
//@dump-sem-ir-begin
|
||||
// CHECK:STDERR: fail_todo_import_definition_pointer_param_type.carbon:[[@LINE+7]]:3: error: semantics TODO: `Unsupported: parameter type: class C *` [SemanticsTodo]
|
||||
// CHECK:STDERR: Cpp.foo(c);
|
||||
// CHECK:STDERR: ^~~~~~~
|
||||
// CHECK:STDERR: fail_todo_import_definition_pointer_param_type.carbon:[[@LINE+4]]:3: note: in `Cpp` name lookup for `foo` [InCppNameLookup]
|
||||
// CHECK:STDERR: Cpp.foo(c);
|
||||
// CHECK:STDERR: ^~~~~~~
|
||||
// CHECK:STDERR:
|
||||
Cpp.foo(c);
|
||||
//@dump-sem-ir-end
|
||||
}
|
||||
@@ -364,7 +357,7 @@ fn F() {
|
||||
// CHECK:STDERR: Cpp.foo();
|
||||
// CHECK:STDERR: ^~~~~~~
|
||||
// CHECK:STDERR:
|
||||
// CHECK:STDERR: fail_todo_import_decl_value_return_type.carbon:[[@LINE+7]]:3: error: semantics TODO: `Unsupported: return type: class C` [SemanticsTodo]
|
||||
// CHECK:STDERR: fail_todo_import_decl_value_return_type.carbon:[[@LINE+7]]:3: error: semantics TODO: `Unsupported: return type: C` [SemanticsTodo]
|
||||
// CHECK:STDERR: Cpp.foo();
|
||||
// CHECK:STDERR: ^~~~~~~
|
||||
// CHECK:STDERR: fail_todo_import_decl_value_return_type.carbon:[[@LINE+4]]:3: note: in `Cpp` name lookup for `foo` [InCppNameLookup]
|
||||
@@ -404,7 +397,7 @@ fn F() {
|
||||
|
||||
class C;
|
||||
|
||||
auto foo() -> C*;
|
||||
auto foo() -> C* _Nonnull;
|
||||
|
||||
// --- fail_todo_import_decl_pointer_return_type.carbon
|
||||
|
||||
@@ -414,7 +407,14 @@ import Cpp library "decl_pointer_return_type.h";
|
||||
|
||||
fn F() {
|
||||
//@dump-sem-ir-begin
|
||||
// CHECK:STDERR: fail_todo_import_decl_pointer_return_type.carbon:[[@LINE+7]]:3: error: semantics TODO: `Unsupported: return type: class C *` [SemanticsTodo]
|
||||
// CHECK:STDERR: fail_todo_import_decl_pointer_return_type.carbon:[[@LINE+14]]:3: error: semantics TODO: `Unsupported: Record declarations without a definition` [SemanticsTodo]
|
||||
// CHECK:STDERR: Cpp.foo();
|
||||
// CHECK:STDERR: ^~~~~~~
|
||||
// CHECK:STDERR: fail_todo_import_decl_pointer_return_type.carbon:[[@LINE+11]]:3: note: in `Cpp` name lookup for `foo` [InCppNameLookup]
|
||||
// CHECK:STDERR: Cpp.foo();
|
||||
// CHECK:STDERR: ^~~~~~~
|
||||
// CHECK:STDERR:
|
||||
// CHECK:STDERR: fail_todo_import_decl_pointer_return_type.carbon:[[@LINE+7]]:3: error: semantics TODO: `Unsupported: return type: C * _Nonnull` [SemanticsTodo]
|
||||
// CHECK:STDERR: Cpp.foo();
|
||||
// CHECK:STDERR: ^~~~~~~
|
||||
// CHECK:STDERR: fail_todo_import_decl_pointer_return_type.carbon:[[@LINE+4]]:3: note: in `Cpp` name lookup for `foo` [InCppNameLookup]
|
||||
@@ -433,9 +433,9 @@ fn F() {
|
||||
|
||||
class C {};
|
||||
|
||||
auto foo() -> C*;
|
||||
auto foo() -> C* _Nonnull;
|
||||
|
||||
// --- fail_todo_import_definition_pointer_return_type.carbon
|
||||
// --- import_definition_pointer_return_type.carbon
|
||||
|
||||
library "[[@TEST_NAME]]";
|
||||
|
||||
@@ -443,13 +443,6 @@ import Cpp library "definition_pointer_return_type.h";
|
||||
|
||||
fn F() {
|
||||
//@dump-sem-ir-begin
|
||||
// CHECK:STDERR: fail_todo_import_definition_pointer_return_type.carbon:[[@LINE+7]]:3: error: semantics TODO: `Unsupported: return type: class C *` [SemanticsTodo]
|
||||
// CHECK:STDERR: Cpp.foo();
|
||||
// CHECK:STDERR: ^~~~~~~
|
||||
// CHECK:STDERR: fail_todo_import_definition_pointer_return_type.carbon:[[@LINE+4]]:3: note: in `Cpp` name lookup for `foo` [InCppNameLookup]
|
||||
// CHECK:STDERR: Cpp.foo();
|
||||
// CHECK:STDERR: ^~~~~~~
|
||||
// CHECK:STDERR:
|
||||
Cpp.foo();
|
||||
//@dump-sem-ir-end
|
||||
}
|
||||
@@ -904,27 +897,36 @@ fn F() {
|
||||
// CHECK:STDOUT: <elided>
|
||||
// CHECK:STDOUT: }
|
||||
// CHECK:STDOUT:
|
||||
// CHECK:STDOUT: --- fail_todo_import_definition_pointer_param_type.carbon
|
||||
// CHECK:STDOUT: --- import_definition_pointer_param_type.carbon
|
||||
// CHECK:STDOUT:
|
||||
// CHECK:STDOUT: constants {
|
||||
// CHECK:STDOUT: %C: type = class_type @C [concrete]
|
||||
// CHECK:STDOUT: %ptr: type = ptr_type %C [concrete]
|
||||
// CHECK:STDOUT: %empty_tuple.type: type = tuple_type () [concrete]
|
||||
// CHECK:STDOUT: %foo.type: type = fn_type @foo [concrete]
|
||||
// CHECK:STDOUT: %foo: %foo.type = struct_value () [concrete]
|
||||
// CHECK:STDOUT: }
|
||||
// CHECK:STDOUT:
|
||||
// CHECK:STDOUT: imports {
|
||||
// CHECK:STDOUT: %Cpp: <namespace> = namespace file.%Cpp.import_cpp, [concrete] {
|
||||
// CHECK:STDOUT: .C = %C.decl
|
||||
// CHECK:STDOUT: .foo = <error>
|
||||
// CHECK:STDOUT: .foo = %foo.decl
|
||||
// CHECK:STDOUT: import Cpp//...
|
||||
// CHECK:STDOUT: }
|
||||
// CHECK:STDOUT: %C.decl: type = class_decl @C [concrete = constants.%C] {} {}
|
||||
// CHECK:STDOUT: %foo.decl: %foo.type = fn_decl @foo [concrete = constants.%foo] {
|
||||
// CHECK:STDOUT: <elided>
|
||||
// CHECK:STDOUT: } {
|
||||
// CHECK:STDOUT: <elided>
|
||||
// CHECK:STDOUT: }
|
||||
// CHECK:STDOUT: }
|
||||
// CHECK:STDOUT:
|
||||
// CHECK:STDOUT: fn @F(%c.param: %ptr) {
|
||||
// CHECK:STDOUT: !entry:
|
||||
// CHECK:STDOUT: %Cpp.ref.loc15: <namespace> = name_ref Cpp, imports.%Cpp [concrete = imports.%Cpp]
|
||||
// CHECK:STDOUT: %foo.ref: <error> = name_ref foo, <error> [concrete = <error>]
|
||||
// CHECK:STDOUT: %Cpp.ref.loc8: <namespace> = name_ref Cpp, imports.%Cpp [concrete = imports.%Cpp]
|
||||
// CHECK:STDOUT: %foo.ref: %foo.type = name_ref foo, imports.%foo.decl [concrete = constants.%foo]
|
||||
// CHECK:STDOUT: %c.ref: %ptr = name_ref c, %c
|
||||
// CHECK:STDOUT: %foo.call: init %empty_tuple.type = call %foo.ref(%c.ref)
|
||||
// CHECK:STDOUT: <elided>
|
||||
// CHECK:STDOUT: }
|
||||
// CHECK:STDOUT:
|
||||
@@ -989,6 +991,7 @@ fn F() {
|
||||
// CHECK:STDOUT: imports {
|
||||
// CHECK:STDOUT: %Cpp: <namespace> = namespace file.%Cpp.import_cpp, [concrete] {
|
||||
// CHECK:STDOUT: .foo = <error>
|
||||
// CHECK:STDOUT: .C = <error>
|
||||
// CHECK:STDOUT: import Cpp//...
|
||||
// CHECK:STDOUT: }
|
||||
// CHECK:STDOUT: }
|
||||
@@ -1000,22 +1003,34 @@ fn F() {
|
||||
// CHECK:STDOUT: <elided>
|
||||
// CHECK:STDOUT: }
|
||||
// CHECK:STDOUT:
|
||||
// CHECK:STDOUT: --- fail_todo_import_definition_pointer_return_type.carbon
|
||||
// CHECK:STDOUT: --- import_definition_pointer_return_type.carbon
|
||||
// CHECK:STDOUT:
|
||||
// CHECK:STDOUT: constants {
|
||||
// CHECK:STDOUT: %C: type = class_type @C [concrete]
|
||||
// CHECK:STDOUT: %ptr: type = ptr_type %C [concrete]
|
||||
// CHECK:STDOUT: %foo.type: type = fn_type @foo [concrete]
|
||||
// CHECK:STDOUT: %foo: %foo.type = struct_value () [concrete]
|
||||
// CHECK:STDOUT: }
|
||||
// CHECK:STDOUT:
|
||||
// CHECK:STDOUT: imports {
|
||||
// CHECK:STDOUT: %Cpp: <namespace> = namespace file.%Cpp.import_cpp, [concrete] {
|
||||
// CHECK:STDOUT: .foo = <error>
|
||||
// CHECK:STDOUT: .foo = %foo.decl
|
||||
// CHECK:STDOUT: .C = %C.decl
|
||||
// CHECK:STDOUT: import Cpp//...
|
||||
// CHECK:STDOUT: }
|
||||
// CHECK:STDOUT: %C.decl: type = class_decl @C [concrete = constants.%C] {} {}
|
||||
// CHECK:STDOUT: %foo.decl: %foo.type = fn_decl @foo [concrete = constants.%foo] {
|
||||
// CHECK:STDOUT: <elided>
|
||||
// CHECK:STDOUT: } {
|
||||
// CHECK:STDOUT: <elided>
|
||||
// CHECK:STDOUT: }
|
||||
// CHECK:STDOUT: }
|
||||
// CHECK:STDOUT:
|
||||
// CHECK:STDOUT: fn @F() {
|
||||
// CHECK:STDOUT: !entry:
|
||||
// CHECK:STDOUT: %Cpp.ref: <namespace> = name_ref Cpp, imports.%Cpp [concrete = imports.%Cpp]
|
||||
// CHECK:STDOUT: %foo.ref: <error> = name_ref foo, <error> [concrete = <error>]
|
||||
// CHECK:STDOUT: %foo.ref: %foo.type = name_ref foo, imports.%foo.decl [concrete = constants.%foo]
|
||||
// CHECK:STDOUT: %foo.call: init %ptr = call %foo.ref()
|
||||
// CHECK:STDOUT: <elided>
|
||||
// CHECK:STDOUT: }
|
||||
// CHECK:STDOUT:
|
||||
|
||||
Reference in New Issue
Block a user