Skip to content

Commit 0056129

Browse files
authored
[cxx-interop] std::string::push_back is broken (#41240)
* [cxx-interop] fix std::string::push_back by fixing mapping between clang/swift self/this type for cxx methods * cleanup * Fix unit test * XFail test: operators/member-inline on linux-android * add `C++` in expandExternalSignatureTypes comment * Fix rebase * Fix mapping issue in externalizeArguments * Improve cxx_interop_ir test regex
1 parent e3b2719 commit 0056129

File tree

4 files changed

+30
-16
lines changed

4 files changed

+30
-16
lines changed

lib/IRGen/GenCall.cpp

Lines changed: 19 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1278,7 +1278,7 @@ static bool doesClangExpansionMatchSchema(IRGenModule &IGM,
12781278
}
12791279

12801280
/// Expand the result and parameter types to the appropriate LLVM IR
1281-
/// types for C and Objective-C signatures.
1281+
/// types for C, C++ and Objective-C signatures.
12821282
void SignatureExpansion::expandExternalSignatureTypes() {
12831283
assert(FnType->getLanguage() == SILFunctionLanguage::C);
12841284

@@ -1319,7 +1319,15 @@ void SignatureExpansion::expandExternalSignatureTypes() {
13191319
paramTys.push_back(clangCtx.VoidPtrTy);
13201320
break;
13211321

1322-
case SILFunctionTypeRepresentation::CXXMethod:
1322+
case SILFunctionTypeRepresentation::CXXMethod: {
1323+
// Cxx methods take their 'self' argument first.
1324+
auto &self = params.back();
1325+
auto clangTy = IGM.getClangType(self, FnType);
1326+
paramTys.push_back(clangTy);
1327+
params = params.drop_back();
1328+
break;
1329+
}
1330+
13231331
case SILFunctionTypeRepresentation::CFunctionPointer:
13241332
// No implicit arguments.
13251333
break;
@@ -1437,9 +1445,14 @@ void SignatureExpansion::expandExternalSignatureTypes() {
14371445
case clang::CodeGen::ABIArgInfo::IndirectAliased:
14381446
llvm_unreachable("not implemented");
14391447
case clang::CodeGen::ABIArgInfo::Indirect: {
1440-
assert(i >= clangToSwiftParamOffset &&
1448+
// When `i` is 0, if the clang offset is 1, that means we mapped the last
1449+
// Swift parameter (self) to the first Clang parameter (this). In this
1450+
// case, the corresponding Swift param is the last function parameter.
1451+
assert((i >= clangToSwiftParamOffset || clangToSwiftParamOffset == 1) &&
14411452
"Unexpected index for indirect byval argument");
1442-
auto &param = params[i - clangToSwiftParamOffset];
1453+
auto &param = i < clangToSwiftParamOffset
1454+
? FnType->getParameters().back()
1455+
: params[i - clangToSwiftParamOffset];
14431456
auto paramTy = getSILFuncConventions().getSILType(
14441457
param, IGM.getMaximalTypeExpansionContext());
14451458
auto &paramTI = cast<FixedTypeInfo>(IGM.getTypeInfo(paramTy));
@@ -3544,7 +3557,8 @@ static void externalizeArguments(IRGenFunction &IGF, const Callee &callee,
35443557
} else if (callee.getRepresentation() ==
35453558
SILFunctionTypeRepresentation::CXXMethod) {
35463559
// Skip the "self" param.
3547-
paramEnd--;
3560+
firstParam += 1;
3561+
params = params.drop_back();
35483562
}
35493563

35503564
if (fnType->getNumResults() > 0 &&

test/ClangImporter/cxx_interop_ir.swift

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -36,7 +36,7 @@ func accessNSMember() {
3636
// CHECK-LABEL: define hidden swiftcc i32 @"$s6cxx_ir12basicMethods1as5Int32VSpySo0D0VG_tF"(i8* %0)
3737
// CHECK: [[THIS_PTR1:%.*]] = bitcast i8* %0 to %TSo7MethodsV*
3838
// CHECK: [[THIS_PTR2:%.*]] = bitcast %TSo7MethodsV* [[THIS_PTR1]] to %class.Methods*
39-
// CHECK: [[RESULT:%.*]] = call {{(signext )?}}i32 @{{_ZN7Methods12SimpleMethodEi|"\?SimpleMethod@Methods@@QEAAHH@Z"}}(%class.Methods* [[THIS_PTR2]], i32{{( signext)?}} 4)
39+
// CHECK: [[RESULT:%.*]] = call {{(signext )?}}i32 @{{_ZN7Methods12SimpleMethodEi|"\?SimpleMethod@Methods@@QEAAHH@Z"}}(%class.Methods* [[THIS_PTR2]], i32 {{%?[0-9]+}})
4040
// CHECK: ret i32 [[RESULT]]
4141
func basicMethods(a: UnsafeMutablePointer<Methods>) -> Int32 {
4242
return a.pointee.SimpleMethod(4)
@@ -46,7 +46,7 @@ func basicMethods(a: UnsafeMutablePointer<Methods>) -> Int32 {
4646
// CHECK: [[THIS_PTR1:%.*]] = alloca %TSo7MethodsV, align {{4|8}}
4747
// CHECK: [[THIS_PTR2:%.*]] = bitcast %TSo7MethodsV* [[THIS_PTR1]] to %class.Methods*
4848
// CHECK: [[THIS_PTR3:%.*]] = bitcast %TSo7MethodsV* [[THIS_PTR1]] to %class.Methods*
49-
// CHECK: [[RESULT:%.*]] = call {{(signext )?}}i32 @{{_ZNK7Methods17SimpleConstMethodEi|"\?SimpleConstMethod@Methods@@QEBAHH@Z"}}(%class.Methods* [[THIS_PTR3]], i32{{( signext)?}} 3)
49+
// CHECK: [[RESULT:%.*]] = call {{(signext )?}}i32 @{{_ZNK7Methods17SimpleConstMethodEi|"\?SimpleConstMethod@Methods@@QEBAHH@Z"}}(%class.Methods* [[THIS_PTR3]], i32 {{%?[0-9]+}})
5050
// CHECK: ret i32 [[RESULT]]
5151
func basicMethodsConst(a: UnsafeMutablePointer<Methods>) -> Int32 {
5252
return a.pointee.SimpleConstMethod(3)
@@ -62,7 +62,7 @@ func basicMethodsStatic() -> Int32 {
6262
// CHECK-LABEL: define hidden swiftcc i32 @"$s6cxx_ir12basicMethods1as5Int32VSpySo8Methods2VG_tF"(i8* %0)
6363
// CHECK: [[THIS_PTR1:%.*]] = bitcast i8* %0 to %TSo8Methods2V*
6464
// CHECK: [[THIS_PTR2:%.*]] = bitcast %TSo8Methods2V* [[THIS_PTR1]] to %class.Methods2*
65-
// CHECK: [[RESULT:%.*]] = call {{(signext )?}}i32 @{{_ZN8Methods212SimpleMethodEi|"\?SimpleMethod@Methods2@@QEAAHH@Z"}}(%class.Methods2* [[THIS_PTR2]], i32{{( signext)?}} 4)
65+
// CHECK: [[RESULT:%.*]] = call {{(signext )?}}i32 @{{_ZN8Methods212SimpleMethodEi|"\?SimpleMethod@Methods2@@QEAAHH@Z"}}(%class.Methods2* [[THIS_PTR2]], i32 {{%?[0-9]+}})
6666
// CHECK: ret i32 [[RESULT]]
6767
func basicMethods(a: UnsafeMutablePointer<Methods2>) -> Int32 {
6868
return a.pointee.SimpleMethod(4)

test/Interop/Cxx/operators/member-inline.swift

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
// RUN: %target-run-simple-swift(-I %S/Inputs -Xfrontend -enable-cxx-interop)
22

33
// REQUIRES: executable_test
4+
// XFAIL: OS=linux-android
45

56
import MemberInline
67
import StdlibUnittest

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

Lines changed: 7 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -17,13 +17,12 @@ StdStringTestSuite.test("init") {
1717
expectTrue(s.empty())
1818
}
1919

20-
// LLVM module verification fails for calls to std::string::push_back: rdar://88343327
21-
// StdStringTestSuite.test("push back") {
22-
// var s = CxxString()
23-
// s.push_back(42)
24-
// expectEqual(s.size(), 1)
25-
// expectFalse(s.empty())
26-
// expectEqual(s[0], 42)
27-
// }
20+
StdStringTestSuite.test("push back") {
21+
var s = CxxString()
22+
s.push_back(42)
23+
expectEqual(s.size(), 1)
24+
expectFalse(s.empty())
25+
expectEqual(s[0], 42)
26+
}
2827

2928
runAllTests()

0 commit comments

Comments
 (0)