Skip to content

Commit f358cbe

Browse files
authored
Merge pull request swiftlang#65578 from zoecarver/disable-rvalue-ref
[cxx-interop] Disable rvalue references. We don't support them correc…
2 parents 002eb34 + 50edc0b commit f358cbe

File tree

13 files changed

+114
-61
lines changed

13 files changed

+114
-61
lines changed

include/swift/AST/DiagnosticsClangImporter.def

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -156,6 +156,7 @@ NOTE(macro_not_imported, none, "macro '%0' unavailable (cannot import)", (String
156156

157157
NOTE(return_type_not_imported, none, "return type unavailable (cannot import)", ())
158158
NOTE(parameter_type_not_imported, none, "parameter %0 unavailable (cannot import)", (const clang::NamedDecl*))
159+
NOTE(rvalue_ref_params_not_imported, none, "C++ functions with rvalue reference parameters are unavailable in Swift", ())
159160
NOTE(incomplete_interface, none, "interface %0 is incomplete", (const clang::NamedDecl*))
160161
NOTE(incomplete_protocol, none, "protocol %0 is incomplete", (const clang::NamedDecl*))
161162
NOTE(incomplete_record, none, "record '%0' is not defined (incomplete)", (StringRef))

include/swift/ClangImporter/ClangImporter.h

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -588,6 +588,14 @@ namespace importer {
588588
/// Returns true if the given module has a 'cplusplus' requirement.
589589
bool requiresCPlusPlus(const clang::Module *module);
590590

591+
/// Returns the pointee type if the given type is a C++ `const`
592+
/// reference type, `None` otherwise.
593+
llvm::Optional<clang::QualType>
594+
getCxxReferencePointeeTypeOrNone(const clang::Type *type);
595+
596+
/// Returns true if the given type is a C++ `const` reference type.
597+
bool isCxxConstReferenceType(const clang::Type *type);
598+
591599
} // namespace importer
592600

593601
struct ClangInvocationFileMapping {

lib/ClangImporter/ClangImporter.cpp

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6834,3 +6834,15 @@ bool importer::requiresCPlusPlus(const clang::Module *module) {
68346834
return req.first == "cplusplus";
68356835
});
68366836
}
6837+
6838+
llvm::Optional<clang::QualType>
6839+
importer::getCxxReferencePointeeTypeOrNone(const clang::Type *type) {
6840+
if (type->isReferenceType())
6841+
return type->getPointeeType();
6842+
return {};
6843+
}
6844+
6845+
bool importer::isCxxConstReferenceType(const clang::Type *type) {
6846+
auto pointeeType = getCxxReferencePointeeTypeOrNone(type);
6847+
return pointeeType && pointeeType->isConstQualified();
6848+
}

lib/ClangImporter/ImportType.cpp

Lines changed: 25 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -2356,15 +2356,32 @@ ClangImporter::Implementation::importParameterType(
23562356
dyn_cast<clang::TemplateTypeParmType>(paramTy)) {
23572357
swiftParamTy = findGenericTypeInGenericDecls(
23582358
*this, templateParamType, genericParams, attrs, addImportDiagnosticFn);
2359-
} else if (auto refType = dyn_cast<clang::ReferenceType>(paramTy)) {
2360-
// We don't support reference type to a dependent type, just bail.
2361-
if (refType->getPointeeType()->isDependentType()) {
2362-
return None;
2363-
}
2359+
}
23642360

2365-
paramTy = refType->getPointeeType();
2366-
if (!paramTy.isConstQualified())
2367-
isInOut = true;
2361+
if (!swiftParamTy) {
2362+
// C++ reference types are brought in as direct
2363+
// types most commonly.
2364+
auto refPointeeType =
2365+
importer::getCxxReferencePointeeTypeOrNone(paramTy.getTypePtr());
2366+
if (refPointeeType) {
2367+
// We don't support reference type to a dependent type, just bail.
2368+
if ((*refPointeeType)->isDependentType()) {
2369+
return None;
2370+
}
2371+
2372+
// We don't support rvalue reference types, just bail.
2373+
if (paramTy->isRValueReferenceType()) {
2374+
addImportDiagnosticFn(Diagnostic(diag::rvalue_ref_params_not_imported));
2375+
return None;
2376+
}
2377+
2378+
// A C++ parameter of type `const <type> &` or `<type> &` becomes `<type>`
2379+
// or `inout <type>` in Swift. Note that SILGen will use the indirect
2380+
// parameter convention for such a type.
2381+
paramTy = *refPointeeType;
2382+
if (!paramTy.isConstQualified())
2383+
isInOut = true;
2384+
}
23682385
}
23692386

23702387
// Special case for NSDictionary's subscript.

lib/SIL/IR/SILFunctionType.cpp

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1420,8 +1420,7 @@ static bool isClangTypeMoreIndirectThanSubstType(TypeConverter &TC,
14201420
// Pass C++ const reference types indirectly. Right now there's no way to
14211421
// express immutable borrowed params, so we have to have this hack.
14221422
// Eventually, we should just express these correctly: rdar://89647503
1423-
if (clangTy->isReferenceType() &&
1424-
clangTy->getPointeeType().isConstQualified())
1423+
if (importer::isCxxConstReferenceType(clangTy))
14251424
return true;
14261425

14271426
return false;
@@ -3109,7 +3108,7 @@ static bool isCFTypedef(const TypeLowering &tl, clang::QualType type) {
31093108
static ParameterConvention getIndirectCParameterConvention(clang::QualType type) {
31103109
// Non-trivial C++ types would be Indirect_Inout (at least in Itanium).
31113110
// A trivial const * parameter in C should be considered @in.
3112-
if (type->isReferenceType() && type->getPointeeType().isConstQualified())
3111+
if (importer::isCxxConstReferenceType(type.getTypePtr()))
31133112
return ParameterConvention::Indirect_In_Guaranteed;
31143113
return ParameterConvention::Indirect_In;
31153114
}

test/Interop/Cxx/reference/Inputs/reference.cpp

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,3 +20,11 @@ auto getFuncRvalueRef() -> int (&&)() { return getStaticInt; }
2020
void takeConstRef(const int &value) {
2121
staticInt = value;
2222
}
23+
24+
void setConstStaticIntRefTypealias(ConstIntRefTypealias ref) {
25+
staticInt = ref;
26+
}
27+
28+
void setStaticIntRefTypealias(IntRefTypealias ref) {
29+
staticInt = ref;
30+
}

test/Interop/Cxx/reference/Inputs/reference.h

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,14 @@ void setConstStaticIntRvalueRef(const int &&);
1616
auto getFuncRef() -> int (&)();
1717
auto getFuncRvalueRef() -> int (&&)();
1818

19+
using ConstIntRefTypealias = const int &;
20+
21+
void setConstStaticIntRefTypealias(ConstIntRefTypealias ref);
22+
23+
using IntRefTypealias = int &;
24+
25+
void setStaticIntRefTypealias(IntRefTypealias ref);
26+
1927
template<class T>
2028
struct ClassTemplate {};
2129

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
// RUN: rm -rf %t
2+
// RUN: split-file %s %t
3+
// RUN: not %target-swift-frontend -typecheck -I %t/Inputs %t/test.swift -enable-experimental-cxx-interop 2>&1 | %FileCheck %s
4+
5+
//--- Inputs/module.modulemap
6+
module Test {
7+
header "test.h"
8+
requires cplusplus
9+
}
10+
11+
//--- Inputs/test.h
12+
13+
void acceptRValueRef(int &&);
14+
15+
//--- test.swift
16+
17+
import Test
18+
19+
public func test() {
20+
var x: CInt = 2
21+
acceptRValueRef(x)
22+
// CHECK: note: function 'acceptRValueRef' unavailable (cannot import)
23+
// CHECK: note: C++ functions with rvalue reference parameters are unavailable in Swift
24+
}

test/Interop/Cxx/reference/reference-irgen.swift

Lines changed: 0 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -45,19 +45,3 @@ public func setCxxConstRef() {
4545

4646
// CHECK: define {{(protected |dllexport )?}}swiftcc void @"$s4main14setCxxConstRefyyF"()
4747
// CHECK: call void @{{_Z20setConstStaticIntRefRKi|"\?setConstStaticIntRef@@YAXAEBH@Z"}}(i32* %{{.*}})
48-
49-
public func setCxxRvalueRef() {
50-
var val: CInt = 21
51-
setStaticIntRvalueRef(&val)
52-
}
53-
54-
// CHECK: define {{(protected |dllexport )?}}swiftcc void @"$s4main15setCxxRvalueRefyyF"()
55-
// CHECK: call void @{{_Z21setStaticIntRvalueRefOi|"\?setStaticIntRvalueRef@@YAX\$\$QEAH@Z"}}(i32* %{{.*}})
56-
57-
public func setCxxConstRvalueRef() {
58-
let val: CInt = 21
59-
setConstStaticIntRvalueRef(val)
60-
}
61-
62-
// CHECK: define {{(protected |dllexport )?}}swiftcc void @"$s4main20setCxxConstRvalueRefyyF"()
63-
// CHECK: call void @{{_Z26setConstStaticIntRvalueRefOKi|"\?setConstStaticIntRvalueRef@@YAX\$\$QEBH@Z"}}(i32* %{{.*}})

test/Interop/Cxx/reference/reference-module-interface.swift

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -7,14 +7,16 @@
77
// CHECK: func getConstStaticIntRvalueRef() -> UnsafePointer<Int32>
88
// CHECK: func setStaticInt(_: Int32)
99
// CHECK: func setStaticIntRef(_: inout Int32)
10-
// CHECK: func setStaticIntRvalueRef(_: inout Int32)
1110
// CHECK: func setConstStaticIntRef(_: Int32)
12-
// CHECK: func setConstStaticIntRvalueRef(_: Int32)
1311
// CHECK: func getFuncRef() -> @convention(c) () -> Int32
1412
// CHECK: func getFuncRvalueRef() -> @convention(c) () -> Int32
13+
// CHECK: func setConstStaticIntRefTypealias(_ ref: Int32)
14+
// CHECK: func setStaticIntRefTypealias(_ ref: inout Int32)
1515
// CHECK: func refToTemplate<T>(_ t: inout T) -> UnsafeMutablePointer<T>
1616
// CHECK: func constRefToTemplate<T>(_ t: T) -> UnsafePointer<T>
1717

1818
// CHECK-NOT: refToDependent
1919
// CHECK-NOT: refToDependentParam
2020
// CHECK-NOT: dontImportAtomicRef
21+
// CHECK-NOT: setStaticIntRvalueRef
22+
// CHECK-NOT: setConstStaticIntRvalueRef

test/Interop/Cxx/reference/reference-silgen.swift

Lines changed: 12 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -52,20 +52,20 @@ func setCxxConstRef() {
5252
// CHECK: [[REF:%.*]] = function_ref @{{_Z20setConstStaticIntRefRKi|\?setConstStaticIntRef@@YAXAEBH@Z}} : $@convention(c) (@in_guaranteed Int32) -> ()
5353
// CHECK: apply [[REF]](%{{[0-9]+}}) : $@convention(c) (@in_guaranteed Int32) -> ()
5454

55-
func setCxxRvalueRef() {
56-
var val: CInt = 21
57-
setStaticIntRvalueRef(&val)
55+
func setCxxConstRefTypealias() {
56+
let val: CInt = 21
57+
setConstStaticIntRefTypealias(val)
5858
}
5959

60-
// CHECK: sil hidden @$s4main15setCxxRvalueRefyyF : $@convention(thin) () -> ()
61-
// CHECK: [[REF:%.*]] = function_ref @{{_Z21setStaticIntRvalueRefOi|\?setStaticIntRvalueRef@@YAX\$\$QEAH@Z}} : $@convention(c) (@inout Int32) -> ()
62-
// CHECK: apply [[REF]](%{{[0-9]+}}) : $@convention(c) (@inout Int32) -> ()
60+
// CHECK: sil hidden @$s4main23setCxxConstRefTypealiasyyF : $@convention(thin) () -> ()
61+
// CHECK: [[REF:%.*]] = function_ref @{{_Z29setConstStaticIntRefTypealiasRKi|\?setConstStaticIntRefTypealias@@YAXAEBH@Z}} : $@convention(c) (@in_guaranteed Int32) -> ()
62+
// CHECK: apply [[REF]](%{{[0-9]+}}) : $@convention(c) (@in_guaranteed Int32) -> ()
6363

64-
func setCxxConstRvalueRef() {
65-
let val: CInt = 21
66-
setConstStaticIntRvalueRef(val)
64+
func setStaticIntRefTypealias() {
65+
var val: CInt = 21
66+
setStaticIntRefTypealias(&val)
6767
}
6868

69-
// CHECK: sil hidden @$s4main20setCxxConstRvalueRefyyF : $@convention(thin) () -> ()
70-
// CHECK: [[REF:%.*]] = function_ref @{{_Z26setConstStaticIntRvalueRefOKi|\?setConstStaticIntRvalueRef@@YAX\$\$QEBH@Z}} : $@convention(c) (@in_guaranteed Int32) -> ()
71-
// CHECK: apply [[REF]](%{{[0-9]+}}) : $@convention(c) (@in_guaranteed Int32) -> ()
69+
// CHECK: sil hidden @$s4main24setStaticIntRefTypealiasyyF : $@convention(thin) () -> ()
70+
// CHECK: [[REF:%.*]] = function_ref @{{_Z24setStaticIntRefTypealiasRi|\?setStaticIntRefTypealias@@YAXAEAH@Z}} : $@convention(c) (@inout Int32) -> ()
71+
// CHECK: apply [[REF]](%{{[0-9]+}}) : $@convention(c) (@inout Int32) -> ()

test/Interop/Cxx/reference/reference.swift

Lines changed: 5 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -42,27 +42,18 @@ ReferenceTestSuite.test("pass-lvalue-reference") {
4242
var val: CInt = 21
4343
setStaticIntRef(&val)
4444
expectEqual(21, getStaticInt())
45+
val = 111
46+
setStaticIntRefTypealias(&val)
47+
expectEqual(getStaticInt(), 111)
4548
}
4649

4750
ReferenceTestSuite.test("pass-const-lvalue-reference") {
4851
expectNotEqual(22, getStaticInt())
4952
let val: CInt = 22
5053
setConstStaticIntRef(val)
5154
expectEqual(22, getStaticInt())
52-
}
53-
54-
ReferenceTestSuite.test("pass-rvalue-reference") {
55-
expectNotEqual(52, getStaticInt())
56-
var val: CInt = 52
57-
setStaticIntRvalueRef(&val)
58-
expectEqual(52, getStaticInt())
59-
}
60-
61-
ReferenceTestSuite.test("pass-const-rvalue-reference") {
62-
expectNotEqual(53, getStaticInt())
63-
let val: CInt = 53
64-
setConstStaticIntRvalueRef(val)
65-
expectEqual(53, getStaticInt())
55+
setConstStaticIntRefTypealias(112)
56+
expectEqual(getStaticInt(), 112)
6657
}
6758

6859
ReferenceTestSuite.test("func-reference") {

test/Interop/Cxx/stdlib/use-std-vector.swift

Lines changed: 5 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -20,18 +20,17 @@ StdVectorTestSuite.test("init") {
2020

2121
StdVectorTestSuite.test("push back") {
2222
var v = Vector()
23-
var _42: CInt = 42
24-
v.push_back(&_42)
23+
let _42: CInt = 42
24+
v.push_back(_42)
2525
expectEqual(v.size(), 1)
2626
expectFalse(v.empty())
2727
expectEqual(v[0], 42)
2828
}
2929

3030
func fill(vector v: inout Vector) {
31-
var _1: CInt = 1, _2: CInt = 2, _3: CInt = 3
32-
v.push_back(&_1)
33-
v.push_back(&_2)
34-
v.push_back(&_3)
31+
v.push_back(1)
32+
v.push_back(2)
33+
v.push_back(CInt(3))
3534
}
3635

3736
StdVectorTestSuite.test("for loop") {

0 commit comments

Comments
 (0)