-
Notifications
You must be signed in to change notification settings - Fork 10.5k
[cxx-interop] Prevent Swift from importing fields marked with [[no_unique_address]] #80497
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
@swift-ci please smoke test |
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.
Thanks! I think the main thing missing here is a few more tests.
@@ -490,4 +490,11 @@ StdStringTestSuite.test("pass as a default argument") { | |||
} | |||
#endif | |||
|
|||
StdStringTestSuite.test("print std::string") { | |||
let cxxString: std.string = "Hello" | |||
print(cxxString) |
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.
This ensures that we don't crash, but I wonder if we can also verify that the right string got printed. One way to do that would be creating a new test file, containing the same code snippet, building and running it, then checking the output.
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.
Done
let swiftString = String(cxxString) | ||
print(swiftString) | ||
} | ||
|
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.
Could you please also add a test that ensures that the error message is emitted when someone tries to access a no_unique_address
field from Swift?
test/Interop/Cxx/class
would probably be the best place for such test
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.
Also done. Thanks for the suggestions!
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.
Might be interesting to sync up with John McCall on this. When he reviewed my PR to fix a crash in codegen (#79076) I had the impression that he would prefer to keep this information in the compiler instead of skipping this.
Swift already supports 0-sized types, empty struct
s are zero sized. So in case the root cause of the problem is that we might want to look into mimicking what happens for zero sized Swift types.
All this being said I am not against not importing them.
@@ -4383,6 +4383,15 @@ namespace { | |||
std::optional<ImportedName> correctSwiftName; | |||
ImportedName importedName; | |||
|
|||
if (decl->hasAttr<clang::NoUniqueAddressAttr>()) { |
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.
Is NoUniqueAddressAttr
the source of the problem or is it something else e.g., the field having 0
as its size? In case it is the latter we might want to make this workaround more targeted.
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 the problem is that we are incorrectly handling fields with the no_unique_address
attribute, and consequently the swift runtime tries to access fields of std::string
that were not imported, resulting in a runtime crash. We eventually want to correctly handle this attribute, but the impact of the bug required a quicker fix.
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.
Ah, let me elaborate a bit. According to CppReference:
Makes this member subobject potentially-overlapping, i.e., allows this member to be overlapped with other non-static data members or base class subobjects of its class. This means that if the member has an empty class type (e.g. stateless allocator), the compiler may optimize it to occupy no space, just like if it were an empty base. If the member is not empty, any tail padding in it may be also reused to store other data members.
So this attribute can have two effects:
- Empty sized fields can get optimized away
- Non-empty types' tail padding can be reused
If we know exactly which one of this is problematic, we could make this check more targeted. E.g., if we only have trouble with empty fields we can check for the size instead of the presence of the attribute, so we end up rejecting less code.
That being said, I am OK with landing this as is and doing the rest of the investigation as a follow-up.
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.
This makes sense to me. I can for sure investigate this further and, if possible, refine this workaround. However, if you agree, I would merge this patch and open a new one when we have a better fix.
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.
Sounds good!
279584d
to
7418b25
Compare
c3eb234
to
4be78c2
Compare
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.
LGTM, thanks! Just one minor comment.
|
||
import MemberVariables | ||
import CxxStdlib |
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.
Do we actually need this import?
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.
No, we don't. Thanks
4be78c2
to
f4435ee
Compare
@swift-ci please smoke test |
f4435ee
to
56be6f8
Compare
@swift-ci please smoke test |
56be6f8
to
fbd4e66
Compare
@swift-ci please smoke test |
From libc++ 20,
std::string
has 3 fields marked with[[no_unique_address]]
. This attribute is not supported in Swift and was causing a runtime crash when printing astd::string
in Swift. In this patch, we prevent Swift from importing such fields.rdar://147263490