When we switched this path over to use lazy member loading, a
subsequent commit introduced a check that members were canonical. In
certain extremely twisty scenarios involving multiple modular frameworks
pulling in non-modular headers, this check can fail which results in us
silently dropping these members on the floor.
It's ultimately correct to only pull in the canonical members, but real-world
examples of "system" frameworks evading modularity diagnostics exist so this
is strictly a regression.
Drop the canonicity check for FieldDecls.
rdar://86740970
There are three major changes here:
1. The addition of "SILFunctionTypeRepresentation::CXXMethod".
2. C++ methods are imported with their members *last*. Then the arguments are switched when emitting the IR for an application of the function.
3. Clang decls are now marked as foreign witnesses.
These are all steps towards being able to have C++ protocol conformance.
This patch introduces new diagnostics to the ClangImporter to help
explain why certain C, Objective-C or C++ declarations fail to import
into Swift. This patch includes new diagnostics for the following entities:
- C functions
- C struct fields
- Macros
- Objective-C properties
- Objective-C methods
In particular, notes are attached to indicate when any of the above
entities fail to import as a result of refering an incomplete (only
forward declared) type.
The new diangostics are hidden behind two new flags, -enable-experimental-clang-importer-diagnostics
and -enable-experimental-eager-clang-module-diagnostics. The first flag emits diagnostics lazily,
while the second eagerly imports all declarations visible from loaded Clang modules. The first
flag is intended for day to day swiftc use, the second for module linting or debugging the importer.
Back when we were eagerly importing struct fields, we only attempted to import fields under the names they have in the current version; previous versions and the raw name were ignored. Now that we're importing them lazily, we're passing through code that attempts to import all versions. That's a nice idea in theory, but neither ImportDecl nor the rest of the compiler was prepared for this, and so ImportDecl has started adding redundant stored properties to clang structs. This trips an assertion in IRGen.
This commit returns to the old behavior of only importing struct fields under their current name by simply early-exiting from SwiftDeclConverter::VisitFieldDecl(). We can come up with a solution that imports the variants in the future.
Fixes rdar://86069786.
Unlike normal Objective-C functions, Swift does not directly call
Objective-C constructors because it creates a thunk to allocate the
object and call then constructor dynamically. This can be fixed, but for
now emit a compile-time error rather than a runtime error.
In C/ObjC interop mode a Clang AST with an ObjC Category resembles:
TranslationUnitDecl
`-ObjCCategoryDecl
However in C++-Interop mode the same Category could potentially have an
extern "C" linkage specifier (guarded with #ifdef __cplusplus) and
resembles:
TranslationUnitDecl
|-LinkageSpecDecl
`-ObjCCategoryDecl
In the latter case when the ClangImporter attempts to import the
category in swift::ClangImporter::Implementation::importDeclContextOr,
prior to this patch, would bail because it is expecting the DeclContext
above the ObjCCategoryDecl to be a TranslationUnitDecl and when it isn't
it returns nullptr.
Because of this, of course the category does not get imported as a swift
extension and therefore any fields or methods are also not imported.
In the case of UIKit, UIView has one of these categories that are
extern-"C"'ed due to UIKIT_EXTERN containing the linkage specifier in
-enable-cxx-interop mode. Since UIView is inherited by lots of other
UIKit types (UILabel etc), many of these types also have lots of missing fields
as well.
This patch checks to see if the decl about to be imported in
importDeclContextOr has a linkage specifier as it's context and makes
sure to materialize the TU from the parent of the declcontext instead of
just immediately bailing. Because of this, this patch enables
c++-interop mode to compile code that uses UIKit without hitting this
mis-compile.
Loading of the members of a C(++) struct/class can occur while doing a
direct lookup, so triggering a second direct lookup inside there can
introduce a request-evaluator cycle. Reimplement this operation to be
more like the way we lazily populate Objective-C classes and protocols,
walking through the record members in order and importing their
variants, then adding those. This eliminates a bunch of extraneous
lookup work, keeps the members in order (see the test case change),
and eliminates the potential for cycles.
The `@MainActor(unsafe)` attribute could be provided for C declarations
via the Clang `swift_attr` attribute. However, this facility was never
used outside of tests, and has been superceded by `@MainActor` with the
inferred `@_predatesConcurrency`.
An explicit swift_attr("@_nonSendable") will override it (except for ns_error_domain where the type is embedded in another type that's forced to be Sendable), but swift_attr("@_nonSendable(_assumed)") will not.
...by using `__attribute__((swift_attr("@Sendable")))`. `@_nonSendable` will "beat" `@Sendable`, while `@_nonSendable(_assumed)` will not.
This commit also checks if `SwiftAttr` supports `#pragma clang attribute` and, if it does, defines `__SWIFT_ATTR_SUPPORTS_SENDABLE_DECLS` in imported headers so they know they can apply these attributes in an auditing style.
This change applies SwiftAttr attributes as soon as possible after creating an instance of a Decl, rather than waiting until the declaration is "finished". That makes sure the attributes can influence the declaration very early in its lifecycle, and in particular, before its conformance table is initialized.
Mostly NFC in this commit (other than affecting the order that attributes are printed in), but necessary for future changes in this PR.
An explicit swift_attr("@_nonSendable") will override it (except for ns_error_domain where the type is embedded in another type that's forced to be Sendable), but swift_attr("@_nonSendable(_assumed)") will not.
...by using `__attribute__((swift_attr("@Sendable")))`. `@_nonSendable` will "beat" `@Sendable`, while `@_nonSendable(_assumed)` will not.
This commit also checks if `SwiftAttr` supports `#pragma clang attribute` and, if it does, defines `__SWIFT_ATTR_SUPPORTS_SENDABLE_DECLS` in imported headers so they know they can apply these attributes in an auditing style.
This change applies SwiftAttr attributes as soon as possible after creating an instance of a Decl, rather than waiting until the declaration is "finished". That makes sure the attributes can influence the declaration very early in its lifecycle, and in particular, before its conformance table is initialized.
Mostly NFC in this commit (other than affecting the order that attributes are printed in), but necessary for future changes in this PR.
If possible, add imported members to the StructDecl's LookupTable rather than adding them directly as members. This will fix the issues with ordering that #39436 poorly attempted to solve during IRGen.
This also allows us to break out most of the test changes from #39436.
A non functional change replacing auto with
Decl* for some declarations using ClangImporter::Implementation::importDecl.
Increases clarity and makes subsequent planned changes easier.