C++ Interop: Support reference types in fields and globals (#6187)

Implemented by generalizing the reference type support for parameters
and return values to other use cases.
The changes to the `method.carbon` test are due to to supporting the
reference types but not supporting the necessary conversions.

C++ Interop Demo:

```c++
// global.h

struct C {
  int member = 0;
  int& member_ref = member;
};

extern C& global;
```

```c++
// global.cpp

#include "global.h"

static C static_c;

C& global= static_c;
```

```carbon
// main.carbon

library "Main";

import Core library "io";

import Cpp library "global.h";

fn Run() -> i32 {
  Core.Print(Cpp.global->member);
  ++(*Cpp.global->member_ref);
  Core.Print(Cpp.global->member);
  ++(*Cpp.global->member_ref);
  Core.Print(Cpp.global->member);
  return 0;
}
```

```shell
$ clang++ -stdlib=libc++ -c global.cpp
$ bazel build toolchain:carbon && bazel-bin/toolchain/carbon compile main.carbon
$ bazel-bin/toolchain/carbon link global.o main.o --output=demo
$ ./demo
0
1
2
```

**Without this change**:
```shell
main.carbon:10:14: error: semantics TODO: `Unsupported: var type: C &`
  Core.Print(Cpp.global->member);
             ^~~~~~~~~~
main.carbon:10:14: note: in `Cpp` name lookup for `global`
  Core.Print(Cpp.global->member);
             ^~~~~~~~~~
```

Part of #6006 and #6186.
This commit is contained in:
Boaz Brickner
2025-10-10 23:15:31 +00:00
committed by GitHub
parent 0365467872
commit 1ac1d11063
4 changed files with 133 additions and 66 deletions
+44 -20
View File
@@ -47,42 +47,66 @@ fn F(v: Cpp.HasQualifiers, p: Cpp.HasQualifiers*) {
library "[[@TEST_NAME]]";
// CHECK:STDERR: fail_bad_object_param_qualifiers_by_value.carbon:[[@LINE+8]]:10: in file included here [InCppInclude]
// CHECK:STDERR: ./object_param_qualifiers.h:10:8: error: 'this' argument to member function 'ref_ref_this' is an lvalue, but function has rvalue ref-qualifier [CppInteropParseError]
// CHECK:STDERR: 10 | void ref_ref_this() &&;
// CHECK:STDERR: | ^
// CHECK:STDERR: fail_bad_object_param_qualifiers_by_value.carbon:[[@LINE+4]]:10: in file included here [InCppInclude]
// CHECK:STDERR: ./object_param_qualifiers.h:10:8: note: 'ref_ref_this' declared here [CppInteropParseNote]
// CHECK:STDERR: 10 | void ref_ref_this() &&;
// CHECK:STDERR: | ^
import Cpp library "object_param_qualifiers.h";
fn Value(v: Cpp.HasQualifiers) {
// CHECK:STDERR: fail_bad_object_param_qualifiers_by_value.carbon:[[@LINE+5]]:3: error: `addr self` method cannot be invoked on a value [AddrSelfIsNonRef]
v.plain();
// TODO: This should remain invalid once we support `volatile`.
v.volatile_this();
v.ref_this();
// CHECK:STDERR: fail_bad_object_param_qualifiers_by_value.carbon:[[@LINE+12]]:3: note: in thunk for C++ function used here [InCppThunk]
// CHECK:STDERR: v.ref_ref_this();
// CHECK:STDERR: ^~~~~~~~~~~~~~~~
// CHECK:STDERR:
// CHECK:STDERR: fail_bad_object_param_qualifiers_by_value.carbon:[[@LINE-14]]:10: in file included here [InCppInclude]
// CHECK:STDERR: ./object_param_qualifiers.h:11:8: error: 'this' argument to member function 'const_ref_ref_this' is an lvalue, but function has rvalue ref-qualifier [CppInteropParseError]
// CHECK:STDERR: 11 | void const_ref_ref_this() const&&;
// CHECK:STDERR: | ^
// CHECK:STDERR: fail_bad_object_param_qualifiers_by_value.carbon:[[@LINE-18]]:10: in file included here [InCppInclude]
// CHECK:STDERR: ./object_param_qualifiers.h:11:8: note: 'const_ref_ref_this' declared here [CppInteropParseNote]
// CHECK:STDERR: 11 | void const_ref_ref_this() const&&;
// CHECK:STDERR: | ^
v.ref_ref_this();
// CHECK:STDERR: fail_bad_object_param_qualifiers_by_value.carbon:[[@LINE+29]]:3: note: in thunk for C++ function used here [InCppThunk]
// CHECK:STDERR: v.const_ref_ref_this();
// CHECK:STDERR: ^~~~~~~~~~~~~~~~~~~~~~
// CHECK:STDERR:
// CHECK:STDERR: fail_bad_object_param_qualifiers_by_value.carbon:[[@LINE-25]]:3: error: `addr self` method cannot be invoked on a value [AddrSelfIsNonRef]
// CHECK:STDERR: v.plain();
// CHECK:STDERR: ^
// CHECK:STDERR: fail_bad_object_param_qualifiers_by_value.carbon: note: initializing function parameter [InCallToFunctionParam]
// CHECK:STDERR:
v.plain();
// TODO: This should remain invalid once we support `volatile`.
// CHECK:STDERR: fail_bad_object_param_qualifiers_by_value.carbon:[[@LINE+4]]:3: error: semantics TODO: `Unsupported: object parameter type: volatile struct HasQualifiers` [SemanticsTodo]
// CHECK:STDERR: fail_bad_object_param_qualifiers_by_value.carbon:[[@LINE-27]]:3: error: semantics TODO: `Unsupported: object parameter type: volatile struct HasQualifiers` [SemanticsTodo]
// CHECK:STDERR: v.volatile_this();
// CHECK:STDERR: ^~~~~~~~~~~~~~~~~
// CHECK:STDERR:
v.volatile_this();
// CHECK:STDERR: fail_bad_object_param_qualifiers_by_value.carbon:[[@LINE+8]]:14: error: no matching function for call to 'ref_this' [CppInteropParseError]
// CHECK:STDERR: 29 | v.ref_this();
// CHECK:STDERR: fail_bad_object_param_qualifiers_by_value.carbon:[[@LINE-29]]:14: error: no matching function for call to 'ref_this' [CppInteropParseError]
// CHECK:STDERR: 20 | v.ref_this();
// CHECK:STDERR: | ^
// CHECK:STDERR: fail_bad_object_param_qualifiers_by_value.carbon:[[@LINE-20]]:10: in file included here [InCppInclude]
// CHECK:STDERR: fail_bad_object_param_qualifiers_by_value.carbon:[[@LINE-40]]:10: in file included here [InCppInclude]
// CHECK:STDERR: ./object_param_qualifiers.h:7:8: note: candidate function not viable: expects an lvalue for object argument [CppInteropParseNote]
// CHECK:STDERR: 7 | void ref_this() &;
// CHECK:STDERR: | ^
// CHECK:STDERR:
v.ref_this();
// CHECK:STDERR: fail_bad_object_param_qualifiers_by_value.carbon:[[@LINE+4]]:3: error: semantics TODO: `Unsupported: object parameter type: struct HasQualifiers &&` [SemanticsTodo]
// CHECK:STDERR: v.ref_ref_this();
// CHECK:STDERR: ^~~~~~~~~~~~~~~~
// CHECK:STDERR:
v.ref_ref_this();
// CHECK:STDERR: fail_bad_object_param_qualifiers_by_value.carbon:[[@LINE+4]]:3: error: semantics TODO: `Unsupported: object parameter type: const struct HasQualifiers &&` [SemanticsTodo]
// CHECK:STDERR: fail_bad_object_param_qualifiers_by_value.carbon:[[@LINE+8]]:3: error: cannot implicitly convert expression of type `Cpp.HasQualifiers` to `const Cpp.HasQualifiers` [ConversionFailure]
// CHECK:STDERR: v.const_ref_ref_this();
// CHECK:STDERR: ^~~~~~~~~~~~~~~~~~~~~~
// CHECK:STDERR: ^
// CHECK:STDERR: fail_bad_object_param_qualifiers_by_value.carbon:[[@LINE+5]]:3: note: type `Cpp.HasQualifiers` does not implement interface `Core.ImplicitAs(const Cpp.HasQualifiers)` [MissingImplInMemberAccessNote]
// CHECK:STDERR: v.const_ref_ref_this();
// CHECK:STDERR: ^
// CHECK:STDERR: fail_bad_object_param_qualifiers_by_value.carbon: note: initializing function parameter [InCallToFunctionParam]
// CHECK:STDERR:
v.const_ref_ref_this();
}