mirror of
https://github.com/carbon-language/carbon-lang.git
synced 2026-10-05 15:41:04 +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:
@@ -269,9 +269,9 @@ fn F() {
|
||||
|
||||
// --- short_pointer.h
|
||||
|
||||
auto foo(short* a) -> void;
|
||||
auto foo(short* _Nonnull a) -> void;
|
||||
|
||||
// --- fail_todo_import_short_pointer.carbon
|
||||
// --- import_short_pointer.carbon
|
||||
|
||||
library "[[@TEST_NAME]]";
|
||||
|
||||
@@ -280,13 +280,6 @@ import Cpp library "short_pointer.h";
|
||||
fn F() {
|
||||
var a: i16 = 1;
|
||||
//@dump-sem-ir-begin
|
||||
// CHECK:STDERR: fail_todo_import_short_pointer.carbon:[[@LINE+7]]:3: error: semantics TODO: `Unsupported: parameter type: short *` [SemanticsTodo]
|
||||
// CHECK:STDERR: Cpp.foo(&a);
|
||||
// CHECK:STDERR: ^~~~~~~
|
||||
// CHECK:STDERR: fail_todo_import_short_pointer.carbon:[[@LINE+4]]:3: note: in `Cpp` name lookup for `foo` [InCppNameLookup]
|
||||
// CHECK:STDERR: Cpp.foo(&a);
|
||||
// CHECK:STDERR: ^~~~~~~
|
||||
// CHECK:STDERR:
|
||||
Cpp.foo(&a);
|
||||
//@dump-sem-ir-end
|
||||
}
|
||||
@@ -297,9 +290,9 @@ fn F() {
|
||||
|
||||
// --- const_short_pointer.h
|
||||
|
||||
auto foo(const short* a) -> void;
|
||||
auto foo(const short* _Nonnull a) -> void;
|
||||
|
||||
// --- fail_todo_import_const_short_pointer.carbon
|
||||
// --- import_const_short_pointer.carbon
|
||||
|
||||
library "[[@TEST_NAME]]";
|
||||
|
||||
@@ -308,13 +301,6 @@ import Cpp library "const_short_pointer.h";
|
||||
fn F() {
|
||||
var a: i16 = 1;
|
||||
//@dump-sem-ir-begin
|
||||
// CHECK:STDERR: fail_todo_import_const_short_pointer.carbon:[[@LINE+7]]:3: error: semantics TODO: `Unsupported: parameter type: const short *` [SemanticsTodo]
|
||||
// CHECK:STDERR: Cpp.foo(&a);
|
||||
// CHECK:STDERR: ^~~~~~~
|
||||
// CHECK:STDERR: fail_todo_import_const_short_pointer.carbon:[[@LINE+4]]:3: note: in `Cpp` name lookup for `foo` [InCppNameLookup]
|
||||
// CHECK:STDERR: Cpp.foo(&a);
|
||||
// CHECK:STDERR: ^~~~~~~
|
||||
// CHECK:STDERR:
|
||||
Cpp.foo(&a);
|
||||
//@dump-sem-ir-end
|
||||
}
|
||||
@@ -834,53 +820,71 @@ fn F() {
|
||||
// CHECK:STDOUT: <elided>
|
||||
// CHECK:STDOUT: }
|
||||
// CHECK:STDOUT:
|
||||
// CHECK:STDOUT: --- fail_todo_import_short_pointer.carbon
|
||||
// CHECK:STDOUT: --- import_short_pointer.carbon
|
||||
// CHECK:STDOUT:
|
||||
// CHECK:STDOUT: constants {
|
||||
// CHECK:STDOUT: %empty_tuple.type: type = tuple_type () [concrete]
|
||||
// CHECK:STDOUT: %int_16: Core.IntLiteral = int_value 16 [concrete]
|
||||
// CHECK:STDOUT: %i16: type = class_type @Int, @Int(%int_16) [concrete]
|
||||
// CHECK:STDOUT: %ptr.251: type = ptr_type %i16 [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: import Cpp//...
|
||||
// CHECK:STDOUT: }
|
||||
// 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: <elided>
|
||||
// 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: %a.ref: ref %i16 = name_ref a, %a
|
||||
// CHECK:STDOUT: %addr.loc16: %ptr.251 = addr_of %a.ref
|
||||
// CHECK:STDOUT: %addr.loc9: %ptr.251 = addr_of %a.ref
|
||||
// CHECK:STDOUT: %foo.call: init %empty_tuple.type = call %foo.ref(%addr.loc9)
|
||||
// CHECK:STDOUT: <elided>
|
||||
// CHECK:STDOUT: }
|
||||
// CHECK:STDOUT:
|
||||
// CHECK:STDOUT: --- fail_todo_import_const_short_pointer.carbon
|
||||
// CHECK:STDOUT: --- import_const_short_pointer.carbon
|
||||
// CHECK:STDOUT:
|
||||
// CHECK:STDOUT: constants {
|
||||
// CHECK:STDOUT: %empty_tuple.type: type = tuple_type () [concrete]
|
||||
// CHECK:STDOUT: %int_16: Core.IntLiteral = int_value 16 [concrete]
|
||||
// CHECK:STDOUT: %i16: type = class_type @Int, @Int(%int_16) [concrete]
|
||||
// CHECK:STDOUT: %ptr.251: type = ptr_type %i16 [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: import Cpp//...
|
||||
// CHECK:STDOUT: }
|
||||
// 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: <elided>
|
||||
// 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: %a.ref: ref %i16 = name_ref a, %a
|
||||
// CHECK:STDOUT: %addr.loc16: %ptr.251 = addr_of %a.ref
|
||||
// CHECK:STDOUT: %addr.loc9: %ptr.251 = addr_of %a.ref
|
||||
// CHECK:STDOUT: %foo.call: init %empty_tuple.type = call %foo.ref(%addr.loc9)
|
||||
// CHECK:STDOUT: <elided>
|
||||
// CHECK:STDOUT: }
|
||||
// CHECK:STDOUT:
|
||||
|
||||
Reference in New Issue
Block a user