-
Notifications
You must be signed in to change notification settings - Fork 10.5k
[cxx-interop] Ban ObjCBool from being substituted into C++ templates #74790
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 test |
This fixes a compiler crash when calling a templated C++ function with a parameter of type `ObjCBool` from Swift. The compiler now emits an error for this. Previously the following would happen: 1. Swift starts to emit SILGen for a call expression `takeTAsConstRef(ObjCBool(true))`. 2. `takeTAsConstRef` is a templated C++ function, so Swift asks Clang to instantiate a `takeTAsConstRef` with a built-in Obj-C boolean type. 3. Swift gets an instantiated function template back that looks like this: `void takeTAsConstRef(_Bool t) { ... }`. 4. Swift's ClangImporter begins to import that instantiated function. 5. Since the parameter type is not spelled as `BOOL`, the parameter is not imported as `ObjCBool`. Instead, it's imported as regular Swift `Bool`. 6. Swift realizes that the types don't match (`ObjCBool` vs `Bool`), tries to apply any of the known implicit conversions, fails to do so, crashes. rdar://130424969
ae872f8
to
fe5b009
Compare
@swift-ci please test |
// Verify that ObjCBool type is banned from C++ template parameters. | ||
|
||
takesValue(ObjCBool(true)) | ||
// CHECK: error: could not generate C++ types from the generic Swift types provided; the following Swift type(s) provided to 'takesValue' could not be converted: ObjCBool |
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 there a way to customize this error message for this case? Can we emit a fix-it that says use .boolValue
to convert to a Swift boolean?
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.
Emitting a fix-it seems like a bit like an overkill for this case, I think. We would also need to handle possible explicit generic parameters (e.g. myCxxMethod<T1, ObjCBool, T2>
).
This bit of logic also doesn't have access to source locations. We could certainly pipe them through, but I'm not sure if it's worth the effort.
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.
Question. I notice this line in ClangTypeConverter::visitStructType()
(ClangTypeConverter.cpp:265 or so):
CHECK_NAMED_TYPE("ObjCBool", ctx.ObjCBuiltinBoolTy);
If you change ctx.ObjCBuiltinBoolTy
to ctx.getBOOLType()
, do these templates start importing correctly? I think that might help explain why ObjCBool
isn't round-tripping.
If that doesn't help, this PR looks like a good band-aid to prevent the crash, but it seems like a better fix ought to be possible in the future.
That's a good question. I initially tried that, and found out that |
This fixes a compiler crash when calling a templated C++ function with a parameter of type
ObjCBool
from Swift. The compiler now emits an error for this.Previously the following would happen:
takeTAsConstRef(ObjCBool(true))
.takeTAsConstRef
is a templated C++ function, so Swift asks Clang to instantiate atakeTAsConstRef
with a built-in Obj-C boolean type.void takeTAsConstRef(_Bool t) { ... }
.BOOL
, the parameter is not imported asObjCBool
. Instead, it's imported as regular SwiftBool
.ObjCBool
vsBool
), tries to apply any of the known implicit conversions, fails to do so, crashes.rdar://130424969