-
Notifications
You must be signed in to change notification settings - Fork 10.5k
[cxx-interop] Fix calling rvalue ref of a trivial type #80568
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Conversation
The Swift compiler used to generate a direct call to functions taking rvalue references to trivial types even though they expected an indirect calling conventions. This PR changes the calling convention on the Swift side to match C++. rdar://148585343
@swift-ci please smoke test |
@@ -103,4 +103,9 @@ ReferenceTestSuite.test("const reference to template") { | |||
expectEqual(53, ref.pointee) | |||
} | |||
|
|||
ReferenceTestSuite.test("rvalue reference of trivial type") { | |||
setStaticIntRvalueRef(consuming: 2) | |||
expectEqual(2, getStaticInt()) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Just curious, how would this test have failed prior to your change?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It crashed with bad memory access. We passed 2 directly as if it was the address of the value.
@@ -103,4 +103,9 @@ ReferenceTestSuite.test("const reference to template") { | |||
expectEqual(53, ref.pointee) | |||
} | |||
|
|||
ReferenceTestSuite.test("rvalue reference of trivial type") { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I was seeing similar crashing in case C++ value types taking rvalue ref inside ctors in these 3 patterns:
// C++
struct cxxValTy {
public:
int val;
cxxValTy() {};
cxxValTy(int x) { val = x; }
};
struct RValRefCtor {
public:
cxxValTy val;
RValRefCtor(cxxValTy &&x) {
val = std::move(x); // <-- 1.) This crashing at runtime
// val = x; // <-- 2.) This is also crashing at runtime
}
// RValRefCtor(cxxValTy &&x) : val(std::move(x)) {} // <-- 3.) This is also crashing at runtime
};
// Swift
let x11 = cxxValTy(5);
let y11 = RValRefCtor(consuming:x11)
expectEqual(y11.val.val, 5)
Should we add test cases for these as well in thie PR to verify that the problem is fixed in these patterns?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I ended up merging this to make sure this is fixed as soon as possible. I think it is always valuable to have more test cases. Since you already have very similar tests in your PR, I think your PR will cover this as well. Or in case you end up not adding a similar test to your foreign reference constructor work let me know and I can open a follow-up.
@@ -1543,6 +1543,9 @@ static bool isClangTypeMoreIndirectThanSubstType(TypeConverter &TC, | |||
if (importer::isCxxConstReferenceType(clangTy)) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I was reading rdar://89647503, I was wondering should we plan working on importing const ref param in C++ APIs as :borrowing . Does Swift now support immutable borrowed params?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think we have everything in place to always import const references as borrowing. But this could potentially be a big change so we should make this switch when we have the bandwidth to thoroughly test it to make sure it does not break existing code. Making the change itself should be relatively straightforward.
The Swift compiler used to generate a direct call to functions taking rvalue references to trivial types even though they expected an indirect calling conventions. This PR changes the calling convention on the Swift side to match C++.
rdar://148585343