Commit Graph

44 Commits

Author SHA1 Message Date
Henrik G. Olsson 8e7036f78b Merge pull request #88621 from hnrklssn/swiftify-span-typedefless
[Swiftify] enable safe wrappers for std::span without typedef
2026-05-07 09:56:47 -07:00
Gábor Horváth 43cae24ed4 Merge pull request #88228 from Xazax-hun/dedup-attr-logic
[cxx-interop] Deduplicate some logic to search for attributes
2026-05-06 12:22:50 +01:00
Henrik G. Olsson f2ccc6cbbd [Swiftify] delay importing return type
This moves processing of the Swift return type in `swiftify` as late as
possible, so that we only trigger importing of the return type if we
really need it (because we are about to attach the macro and need to
verify that it's safe to do so). This fixes an exponential type import
in Interop/Cxx/templates/large-class-templates-module-interface.swift
that was introduced when the early check for template instantiations in
the signature was removed, causing `swiftify` to reach the return type
import stage for a function with a really expensive template type in its
return type. Note that the test would still pass with the experimental
ImportCxxMembersLazily feature enabled. But regardless, we should strive
to be as lazy as possible in our importing even in `swiftify`.
2026-04-29 12:30:46 -07:00
Henrik G. Olsson db1815a66b [Swiftify] check std::span element type for templates
Even if the std::span template itself might be stripped from the safe
wrapper signature, we still need to check for templates in the element
type.
2026-04-29 12:30:46 -07:00
Henrik G. Olsson 7bbaeebba1 [Swiftify] enable safe wrappers for std::span without typedef
We previously prevented generating safe wrappers on functions with
template instantiations in the signature, unless those instantiations
were hidden behind a typedef. This is because those template
instantiations cannot be expressed in Swift syntax, so the macro
would expand to a function with invalid syntax.

For the std::span parameter itself however, that type is replaced with a
Swift Span in the safe wrapper, so it's not an issue in the type
signature. We would previously use the std::span type name from the
original signature to cast from Span to std::span, which does not work
with the raw std::span type. This uses `.init` instead when this is the
case, which avoids spelling out the type. When possible, we still use
the concrete type name, for clarity and by providing information we have
accessible the typechecker needs to do less work.

Resolves #86339

rdar://167712240
2026-04-29 12:30:44 -07:00
Gabor Horvath 970253b14a [cxx-interop] Deduplicate some logic to search for attributes
We wrote the same code multiple times, this PR replaces some of that
code with function calls. It is not entirely NFC as the called function
has some special case for parameters. That being said, having uniform
logic for looking up attributes is probably beneficial. If it does not
work out, we can always introduce a compile-time parameter to opt in/out
of the special case.
2026-04-27 16:52:25 +01:00
Henrik G. Olsson 58e424e7fb [Swiftify] limit lifetimebound on implicit "this" to experimental mode
When safe interop was stabilized, lifetimebound deliberately not
stabilized. The check for lifetimebound on the implicit "this" parameter
was accidentally not gated behind the experimental feature check,
however. Now lifetimebound on implicit "this" is no longer in the stable
feature set.

rdar://175396896
2026-04-22 22:23:06 -07:00
Henrik G. Olsson 7e3408fb2a [Swiftify][Embedded] don't print empty availability
Since 60d5ce8f19 stdlib availability is
substituted with an empty availability when targeting Embedded Swift,
since availability is irrelevant when statically linked. This resulted
in the _SwiftifyImport macro expansion containing an `@available(, *)`
annotation, which is syntactically invalid. Avoid this by simply not
including an availability parameter.

rdar://174341000
2026-04-11 21:43:13 -07:00
Henrik G. Olsson ce6a9fc8de Merge pull request #87585 from hnrklssn/swiftify-refactor-impl
[Swiftify] remove SwiftifyProtocolInfoPrinter (NFC)
2026-03-02 12:23:19 -08:00
Gabor Horvath 75dc9b0283 [cxx-interop] More cleaups, no functional change intended
* Simplify some patterns (isa + cast)
* Add some consts
* Get rid of some temporary objects by constructing more objects in
  place
* Remove some duplicated lookups
* Other minor cleanups
2026-02-28 23:43:22 +00:00
Henrik G. Olsson 66ae0df963 remove unused function (NFC)
This function is unused for now, triggering a warning. Remove until ObjC
method support is re-added.
2026-02-28 11:44:14 -08:00
Henrik G. Olsson d535860d78 [Swiftify] remove SwiftifyProtocolInfoPrinter (NFC)
This class is unused since safe interop wrapper support for ObjC methods
was backed out. When we reintroduce this, it will be implemented
differently, and this class won't be necessary - at least in its current
reincarnation. Move as much as possible into swiftifyImpl, making
swiftify a thin wrapper around it. This thin wrapper will be relevant
when we reimplement support for ObjC methods.
2026-02-28 11:42:53 -08:00
Henrik G. Olsson 664fe6d6a3 bracing
Co-authored-by: John Hui <updog@j-hui.com>
2026-02-27 13:06:39 -08:00
Henrik G. Olsson 5f3c313d69 remove include of Attrs.inc 2026-02-27 11:16:46 -08:00
Henrik G. Olsson b0f5646611 [Swiftify] add SWIFT_NO_SAFE_WRAPPER annotation
This adds SWIFT_NO_SAFE_WRAPPER, which can be used to signal that a
function should not get a safe interop wrapper. This can serve as a
fallback if a safe wrapper blocks compilation, while waiting for a fix
to ship.

rdar://169146789
2026-02-26 20:58:19 -08:00
Henrik G. Olsson 2d023ddfe3 update assert
This adds another case where parameter counts can mismatch, found in
test/IDE/Inputs/custom-modules/ImportAsMember.h:

```
extern struct IAMStruct1 IAMStruct1CreateSpecialLabel(void)
    __attribute__((swift_name("Struct1.init(specialLabel:)")));
```

This takes a function with no parameters and imports it as a constructor
with a single parameter taking the Void type.
2026-02-11 09:32:05 -08:00
Henrik G. Olsson d480ea3eee [Swiftify] replace StabilizedSafeInteropWrappers with -disable-safe-interop-wrappers
swift-synthesize-interface needs to match the safe interop wrappers
setting of the compiler invocation that built the Swift module, but
doesn't have -enable/disable-experimental-feature options. Instead of
introducing them for a single feature, which isn't even experimental,
this introduces the -disable-safe-interop-wrappers instead.
2026-02-11 09:32:03 -08:00
Henrik G. Olsson ce2bd15c44 [Swiftify] remove assertion
A FRT is not imported as a pointer type in the first place, so it can
have a concrete Swift type without an available Clang definition.
2026-02-10 22:06:29 -08:00
Henrik G. Olsson 87a70f60d0 [Swiftify] add safe wrappers flag that ignores lifetimebound
lifetimebound does not imply that the parameter does not escape. For
stabilising safe wrappers we don’t want to use that assumption, so we
need a new feature flag.

rdar://170090534
2026-02-10 16:51:35 -08:00
Henrik G. Olsson 006e3ac7e7 rename and clarify logic (NFC) 2026-02-09 22:17:38 -08:00
Henrik G. Olsson a4366f63e1 [Swiftify] handle ~Escapable return values
This adds support for safe wrappers on imported functions returning a
~Escapable value. This is only done if there is lifetime information for
the return value, as the wrapper will always have a lifetime error
otherwise. __lifetimebound is also ignored *unless* the return value is
~Escapable (or will be transformed to a Span), since lifetime info for
an Escapable return value is an error. To enable testing this it also
adds merging of lifetime annotations from the underlying funciton and
the extra info added by the macro.

rdar://157884394
2026-02-06 23:07:08 -08:00
Henrik G. Olsson 239bda9a3f Merge pull request #87058 from hnrklssn/swiftify-fix-escapability-check
[Swiftify] check clang type for escapability instead of Swift type
2026-02-06 23:02:51 -08:00
Henrik G. Olsson 1ff89bec41 [Swiftify] check clang type for escapability instead of Swift type
Checking the escapability of types at this point during compilation can
return the wrong result and prevent the correct result from being
calculated later due to caching.

rdar://169839008
2026-02-06 16:23:41 -08:00
Henrik G. Olsson 7680725396 [Swiftify] properly support initializers
This linearizes the macro expansions by leaking the internal buffer
pointer in [Mutable][Raw]Span parameters. This avoids the closure-based
nesting, simplifying the function body, but more importantly avoids an
error when the function is an intializer: Swift does not allow calls to
delegated initializers inside other expressions or closures.

Initializers for CoreFoundation-style references are not allowed at all
(other than the ones imported from C), so safe wrappers on those are
avoided entirely.

rdar://169661706
2026-02-04 19:06:46 -08:00
Henrik G. Olsson c0b30892a6 [Swiftify] don't attach macro if plugin unavailable
At the moment plugin paths do not get passed along when consuming a
textual interface of an imported module. Normally this is not an issue,
because all macros have already been expanded at this point, but this is
not the case for _SwiftifyImport which belongs to a clang module but is
expanded while gompiling a dependent Swift module. This would cause an
error when trying to expand the macro. Since most textual interfaces
don't call any safe wrappers at the moment, this unblocks the
compilation by checking whether the macro plugin can be loaded before
attaching the macro, and emitting a warning if not. Long term we'll want
to pass along the plugin path to swift-api-digester, but this will do
for now.

rdar://168967555
2026-01-29 10:34:11 -08:00
Henrik G. Olsson 66a3bea341 [Swiftify] disable safe interop for ObjC protocols
This removes the swiftifyProtocol function, because it fundamentally
incompatible with our layering. By iterating over the protocol members
of the node we are currently importing, we immediately force all members
to be imported. This can lead to cycles and various hard-to-debug import
failures. Instead we need to attach the extension macro when importing
each invidvidual method. This will take some plumbing however, because
that may happen after the protocol's macros have already been expanded,
preventing later macros from being expanded.

rdar://168500103
2026-01-28 20:28:02 -08:00
Henrik G. Olsson 398f09bb2e [Swiftify] get module from canonical decl
This aligns the logic in SwiftifyDecl.cpp for fetching the owning module
with that of the rest of the compiler. Previously we would fetch the
owning module from the clang decl directly associated with the Swift
decl, whereas the rest of the compiler looks at the canoncial (first)
decl to determine ownership. This mismatch resulted in a state where
swiftifyImpl did not think the decl originated in a bridging header
(because it was not imported into the __ObjC module), but it also didn't
find an owning module on the clang decl. This occured when a bridging
header would import a header from a module, and then redeclare a
function from that module.

rdar://168703691
2026-01-23 18:45:18 -08:00
Henrik G. Olsson 607c7af3d3 [Swiftify] fix ForwardDeclaredConcreteTypeVisitor
This fixes two bugs:
 1) The outermost pointee type is not necessarily a nominal type. There
can e.g. be a pointer to an array (tuple) type. This would result in a
null pointer dereference. Instead of assuming direct pointee nominal
types, we now check for nominal types anywhere in the type hierarchy.

2) Enum types can also be forward declared. Instead of checking for
clang::RecordDecl, we now check for clang::TagDecl (which is a base
class of clang::RecordDecl and clang::EnumDecl).

rdar://165864358
2026-01-15 16:01:46 -08:00
Slava Pestov f53014312e ClangImporter: Fix bogus deprecation warning 2026-01-12 22:20:36 -05:00
Henrik G. Olsson e62f6fe78b Merge pull request #86084 from swiftlang/opaque-non-opaque
[Swiftify] don't add macro when required type is unavailable
2026-01-08 16:32:25 -08:00
Henrik G. Olsson 75a110cdc6 [Swiftify] don't attach macro when module does not import stdlib
This prevents stuff like memcmp from SwiftShims from being imported with
@_SwiftifyImport, which would then result in name lookup errors as it
does not import the Swift standard library module. This makes the
previous approach to disable safe interop when compiling with
-parse-stdlib redundant.

irdar://165856959
2025-12-18 21:14:58 -08:00
Henrik G. Olsson ca3b77f6fc allow functions in modules to depend on decls with no owning module
Since decls with no module are imported to __ObjC this is not an issue,
because __ObjC is always implicitly imported. Added test case that would
previously assert.
2025-12-18 17:24:08 -08:00
Henrik G. Olsson db7c13c3dd traverse imported Swift type rather than clang type
This fixes an assert when signatures contain
`struct forward_declared_t **`, and makes sure that
`struct foo { struct forward_declared_t *bar; }` does *not* block
swiftification, since `@_SwiftifyImport` does not need to access the
struct field.
2025-12-17 22:09:59 -08:00
Henrik G. Olsson cd5d8e13d9 handle bridging header decls in ForwardDeclaredConcreteTypeVisitor 2025-12-17 16:26:19 -08:00
Henrik G. Olsson 96d3deb03c [Swiftify] fix missing owning module
Implicit decls don't have an owning module, since multiple modules could
instantiate them on demand. Since no implicit functions currently have
any need for safe wrappers we can simply detect this and early exit. For
templated functions, we need to fetch the owning module from the
instantiation.
2025-12-17 16:26:19 -08:00
Henrik G. Olsson 270f1d8619 [Swiftify] don't add macro when required type is unavailable
A Swift module only imports a type definition once. This means that some
clang modules may have function signatures imported with
`UnsafePointer<qux>` even if `qux` is only forward declared in that
module (which would normally be imported as `OpaquePointer`), because
some Swift file in the module imported the clang module with the
definition, so ClangImporter sees the definition. The macro expansion
only imports the imports of the clang module it belongs to however, so
namelookup for `qux` fails. This patch detects when this will result in
an error and avoids attaching the macro in those cases.

rdar://165864358
2025-12-17 16:26:16 -08:00
Henrik G. Olsson 38827c837e [Swiftify] don't swiftify functions with sugared parameter lists
These cases would trigger an assert in both release and debug builds.
With this change they are ignored in release mode, and cases that are
both unhandled and unknown trigger an assert in debug mode.

rdar://166074719
2025-12-15 14:37:07 -08:00
Henrik G. Olsson eb0d894986 [ClangImporter] improve structure of swiftify debug logs
This adds automatic scope management and indentation to the logs to make
them more structured. Also adds some additional logging.
Here's an example of what it can look like now:
```
[swiftify:593] Checking 'CountedByProtocol' protocol for methods with bounds and lifetime info
[swiftify:350] | Checking 'simple::' for bounds and lifetime info
[swiftify:411] | | Checking parameter 'len' with type 'int'
[swiftify:411] | | Checking parameter 'p' with type 'int * __counted_by(len)'
[swiftify:435] | | | Found bounds info 'int * __counted_by(len)'
[swiftify:350] | Checking 'shared:::' for bounds and lifetime info
[swiftify:411] | | Checking parameter 'len' with type 'int'
[swiftify:411] | | Checking parameter 'p1' with type 'int * __counted_by(len)'
[swiftify:435] | | | Found bounds info 'int * __counted_by(len)'
[swiftify:411] | | Checking parameter 'p2' with type 'int * __counted_by(len)'
[swiftify:435] | | | Found bounds info 'int * __counted_by(len)'
[swiftify:350] | Checking 'complexExpr:::' for bounds and lifetime info
[swiftify:411] | | Checking parameter 'len' with type 'int'
[swiftify:411] | | Checking parameter 'offset' with type 'int'
[swiftify:411] | | Checking parameter 'p' with type 'int * __counted_by(len - offset)'
[swiftify:435] | | | Found bounds info 'int * __counted_by(len - offset)'
[swiftify:350] | Checking 'nullUnspecified::' for bounds and lifetime info
[swiftify:411] | | Checking parameter 'len' with type 'int'
[swiftify:411] | | Checking parameter 'p' with type 'int * __counted_by(len) _Null_unspecified'
[swiftify:435] | | | Found bounds info 'int * __counted_by(len) _Null_unspecified'
[swiftify:350] | Checking 'nonnull::' for bounds and lifetime info
[swiftify:411] | | Checking parameter 'len' with type 'int'
[swiftify:411] | | Checking parameter 'p' with type 'int * __counted_by(len) _Nonnull'
[swiftify:435] | | | Found bounds info 'int * __counted_by(len) _Nonnull'
[swiftify:350] | Checking 'nullable::' for bounds and lifetime info
[swiftify:411] | | Checking parameter 'len' with type 'int'
[swiftify:411] | | Checking parameter 'p' with type 'int * __counted_by(len) _Nullable'
[swiftify:435] | | | Found bounds info 'int * __counted_by(len) _Nullable'
[swiftify:350] | Checking 'returnPointer:' for bounds and lifetime info
[swiftify:379] | | Found bounds info 'int * __counted_by(len)' on return value
[swiftify:411] | | Checking parameter 'len' with type 'int'
[swiftify:350] | Checking 'staticMethod::' for bounds and lifetime info
[swiftify:411] | | Checking parameter 'len' with type 'int'
[swiftify:411] | | Checking parameter 'p' with type 'int * __counted_by(len)'
[swiftify:435] | | | Found bounds info 'int * __counted_by(len)'
```
2025-11-13 19:06:49 -08:00
Henrik G. Olsson 14c79d292c [ClangImporter] don't emit empty .method()
This updates SwiftifyImportProtocolPrinter such that it no longer emits
anything for methods without bounds or lifetime info. Previously we
would not attach the macro if no methods in the protocol contained
bounds or lifetime info. However if one of the methods did, we would
still emit `.method(signature: "func foo()", paramInfo: [])` for the
methods without bounds of lifetime info. This would result in overloads
being generated, like so:
```
@_alwaysEmitIntoClient @_disfavoredOverload public
func foo() {
  return unsafe foo()
}
```

As part of this change, SwiftifyImportPrinter is now an abstract parent
type for SwiftifyImportProtocolPrinter, and the new
SwiftifyImportFunctionPrinter. Instead of SwiftifyImportProtocolPrinter
inheriting the function printing, `printMethod` instead creates a new
SwiftifyImportFunctionPrinter each time, with a new output string. If it
output anything interesting the result is forwarded, otherwise it is
discarded.
2025-10-24 18:56:45 -07:00
Henrik G. Olsson 72439d35a7 assert -> ASSERT 2025-10-24 13:28:04 -07:00
Henrik G. Olsson af819b9428 [ClangImporter] Attach _SwiftifyImportProtocol to imported protocols
...with bounds attributes

This creates safe overloads for any methods in the protocol annotated
with bounds information. Updates _SwiftifyImportProtocol to make the
added overloads in the protocol public.

rdar://144335990
2025-10-24 13:28:02 -07:00
Henrik G. Olsson 722afefff8 replace SIW_DBG with DLOG (NFC)
Now that swiftify related functions have their own file there's no need
to use DEBUG_WITH_TYPE explicitly anymore.
2025-10-23 23:59:26 -07:00
Henrik G. Olsson a2384b32c6 merge anonymous namespaces (NFC) 2025-10-23 20:37:26 -07:00
Henrik G. Olsson 6d8d09ee03 [ClangImporter] move swiftify to SwiftifyDecl.cpp (NFC)
This code doesn't interact that much with the rest of ClangImporter, and
will continue to grow. Keeping it in a separate file makes it easier to
navigate.
2025-10-23 20:37:24 -07:00