Skip to content

[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

Merged
merged 1 commit into from
Apr 6, 2025

Conversation

Xazax-hun
Copy link
Contributor

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

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
@Xazax-hun Xazax-hun added the c++ interop Feature: Interoperability with C++ label Apr 6, 2025
@Xazax-hun
Copy link
Contributor Author

@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())
Copy link
Contributor

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?

Copy link
Contributor Author

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") {
Copy link
Contributor

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?

Copy link
Contributor Author

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))
Copy link
Contributor

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?

Copy link
Contributor Author

@Xazax-hun Xazax-hun Apr 7, 2025

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.

@Xazax-hun Xazax-hun enabled auto-merge April 6, 2025 22:31
@Xazax-hun Xazax-hun merged commit 5ef33db into main Apr 6, 2025
3 checks passed
@Xazax-hun Xazax-hun deleted the gaborh/rvalue-ref-calling-conv branch April 6, 2025 22:40
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
c++ interop Feature: Interoperability with C++
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants