-
Notifications
You must be signed in to change notification settings - Fork 10.5k
[cxx-interop] Fix not importing return type for certain functions #80500
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
C++ namespaces are imported as enums. The importer triggered different code path for functions in C++ namespaces and functions in the global scope. As a result, we occasionally did not import the return type of certain C++ functions in namespace scope.
a74a18f
to
d254e83
Compare
@swift-ci please smoke test |
@swift-ci please smoke test macOS |
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 patch looks good at face value but I'm not familiar enough with the implementation of importFunctionDecl()
to understand why the change fixes things. I left a question there.
@@ -23,7 +23,9 @@ InheritanceTestSuite.test("Templated cast to base") { | |||
let sc: BaseT = cast(s) | |||
expectFalse(sc.isBase) | |||
let sx: BaseT = cxxCast(s) // should instantiate I to SubT and O to BaseT | |||
expectFalse(sc.isBase) |
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.
Was this a typo from a previous patch?
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.
Yeah, I believe this was a typo previously, sx
was unused.
@@ -3862,7 +3869,8 @@ namespace { | |||
|
|||
bool importFuncWithoutSignature = | |||
isa<clang::CXXMethodDecl>(decl) && Impl.importSymbolicCXXDecls; | |||
if (!dc->isModuleScopeContext() && !isa<clang::CXXMethodDecl>(decl)) { | |||
if (!dc->isModuleScopeContext() && !isClangNamespace(dc) && | |||
!isa<clang::CXXMethodDecl>(decl)) { |
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.
Can you explain what this if
statement is guarding, and why we need to make sure dc
is not a namespace here?
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.
Sure! In general, global C++ functions and C++ methods did not take this branch. This branch does not handle certain C++ constructs like template parameters. I believe this is the code path that was originally used for many scenarios in Obj-C interop. For example, importing a free function as a method (where the self is usually the first argument of the function). So the original condition checked if we are importing something as a member function (!dc->isModuleScopeContext()
) but it is not a C++ method. Since C++ namespaces are represented as enum
s in Swift, a C++ free function that is not a method ended up inadvertently taking this code path changing the import behavior depending on whether the function is in a namespace or in global context. To make sure we trigger the same code path regardless of if the function is in a namespace scope or global scope I added this condition to check if the enum
was created from a C++ namespace.
C++ namespaces are imported as enums. The importer triggered different code path for functions in C++ namespaces and functions in the global scope. As a result, we occasionally did not import the return type of certain C++ functions in namespace scope.