Commit Graph

159 Commits

Author SHA1 Message Date
John Hui 0597c897b8 Merge pull request #87871 from j-hui/lazy-subscriptz 2026-05-12 07:53:36 -07:00
John Hui f1f17b8c75 [cxx-interop] Synthesize subscript on-demand
The implementation for this behavior was added in a previous patch;
this patch integrates and removes unused call sites.

This patch also adds some tests exercising the overloading behavior.

Annoyingly, imported members that point to the same source location
aren't sorted correctly in the module interface, so this changes the
order in a bunch of module interface tests.

rdar://170857428

Also, un-comment broken test case of using Base::operator[], which is
fixed by this commit.

rdar://145345345
2026-05-11 23:23:39 -07:00
Gabor Horvath e799354459 [cxx-interop] Deduplicate some code into shared helpers
This reduces the code size and also standardizes code. In some cases we
fixed a bug at one version of the "inlined helper" but not at the other.
Hopefully, the deduplicated code makes it less likely that we run into
similar situations.
2026-04-30 18:57:46 +01:00
John Hui 4317981951 Merge pull request #88426 from j-hui/unreachable-frts 2026-04-14 14:08:15 -07:00
John Hui d588fb2c78 [cxx-interop] Ensure FRT base has reachable definition
It is possible to get into situations where we have a derived FRT whose
definition is not reachable (in the modules sense). This is problematic
when we need to synthesize reference counting operations for derived
those FRTs via clang::Sema, because those operations require knowledge
about the layout of those classes, i.e.,

    Base::ref((Base *)derived) // otherwise-implicit cast added for emphasis

As such, clang::Sema would be unable to generate valid call expressions,
leading to assertion failures in the decl synthesizer logic which
assumed everything is hunky dory.

This patch adds logic to accommodate this scenario, throwing a compiler
error when reachability is an problem, so that the user can look into
possible modulemap/module layout issues.

rdar://172291423
2026-04-12 11:25:22 -07:00
John Hui 3e567e4d78 [cxx-interop] Make static factory synthesis more robust to failures
We'll still see error messages from Clang if the results are invalid for
any reason, but at least the compiler won't assertions-fail or generate
garbo ASTs.

rdar://172291423
2026-04-11 00:45:02 -07:00
John Hui a57bd276bd [cxx-interop] Do not synthesize factories for unreachable FRTs 2026-04-11 00:44:24 -07:00
John Hui 204cff39d5 [cxx-interop] Handle inherited ref count operations
cast<clang::FunctionDecl>(releaseResult.operation->getClangDecl()) would
crash when getClangDecl() returns a nulptr, which happens when the
operation is a synthesized inherited function.

rdar://172291423
2026-04-11 00:38:45 -07:00
susmonteiro 61c6038d45 [cxx-interop] Re-apply support for subscripts of non-copyable types 2026-04-08 17:14:06 +01:00
John Hui 0df1783907 [cxx-interop] [NFC] Push addAlternateDecl() into makeSubscript() 2026-03-31 17:37:23 -07:00
Egor Zhdan a2b7b8fb2f [cxx-interop] Honor default arguments of constructors
Previously Swift imported default argument expressions in C++ methods and global functions, but not constructors.

rdar://118987713 / resolves https://github.com/apple/swift/issues/70124
2026-03-30 17:51:43 +01:00
Gabor Horvath 0da3b379db [cxx-interop] Fix some clang tidy warnings
* Make some methods const or static
* Other minor cleanups
2026-03-26 14:48:24 +00:00
John Hui c62949c51c [cxx-interop] [NFC] Remove unused ClangImporter::Implementation pointer
This was previously used to control whether a CxxRecordSemantics or
CxxRecordAsSwiftType request would trigger diagnostics when determining
a type is a foreign reference type. That interface led to obscure
control flow and was removed recently. This patch removes the vestigial
pointer field those requests used.

(Actually, that pointer was *never* used by CxxRecordAsSwiftType
requests; its call sites just happened to pick it up because it shares
the same input descriptor type as CxxRecordSemantics).

rdar://170858418
2026-03-05 14:22:57 -08:00
John Hui 346bfe476b [cxx-interop] [NFCi] Clean up reference type analysis logic
Previously, the getRefParentOrDiag() function was used both to determine
the reference typedness of an imported record, and to diagnose cases
where that determination was invalid (e.g., due to complications that
arise from inheritance). However, it exposed a rather brutish interface
for controlling whether diagnostics are emitted: when it is given
a non-null ClangImporter::Implementation pointer, it emits diagnostics,
and when given a null pointer it doesn't. A lack of consideration for
where we actually needed these diagnostics led to that pointer being
unnecessarily threaded through a couple of requests and a half dozen
call sites, leading to unnecessarily obscure control flow.

This patch gets rid of getRefParentOrDiag() and replaces it with two
well-defined entry points: a request that does not emit diagnostics, and
a function that does. The nullable ClangImporter::Implementation pointer
is hidden from the interface of those entry points, and their side
effects are well-documented.

The code is migrated from ClangImporter.cpp to ClangAnalysis.cpp, which
I've introduced as the new home for various subroutines that analyze and
extract information from clang decls.

The reference type inference logic of getRefParentOrDiag() (and its
associated helpers) is also rewritten to replace the clang-provided
clang::CXXRecordDecl::forAllBases() with an explicit graph traversal
through the class hierarchy that is easier to debug and adjust (with
imminent behavior changes in mind). It also avoids an unnecessary
class hierarchy traversal whose only purpose was to look for reference
types that participates in diamond inheritance.

No behavior change is intended: we (should) still make perform the same
reference typedness analysis, and emit the exact same diagnostics.

rdar://170858418
2026-03-05 14:22:57 -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
Gabor Horvath 76e1f71674 [cxx-interop] Various code cleanups, no functional change intended
* Simplify conditionals
* Simplify loops
* Use llvm:: algorithms
* Simplify use of isa
* Deduplicate some code
* Other minor simplifications
2026-02-28 10:57:25 +00:00
Artem Chikin 1e5ba5fca8 [Literal Expressions] Add support for literal expressions in enum raw values
Modify relevant portions of the type-checker and parser to allow, when the 'LiteralExpressions' experimental feature is enabled, for arbitrary integer-typed expressions in enum raw value specifiers. These expressions will be type-checked and constant-folded into an integer literal expression, keeping the current interface of 'EnumElementDecl' consistent for clients.

Previously, 'EnumRawValuesRequest' had two different "modes" which were discerned based on typechecking stage (structural | interface), where the former had the request compute all raw values, both user-specified literal expressions and computing increment-derived values as well; the latter would also type-check the user-specified expressions and compute their types.
- With the need to have enum case raw values support arbitrary integer expressions, the request ('EnumRawValuesRequest') has been refactored and simplified to *always* both compute all case raw values and perform type-checking of user-specified raw value expressions. This is done in order to allow the AST-based constant-folding infrastructure ('ConstantFoldExpression' request) to run on the expressions. Constant folding is invoked during the evaluation of 'EnumRawValuesRequest' on all user-specified raw value expressions, in order to be able to compute subsequent increment values and ensure the expressions are foldable. If they are not, i.e. if constant folding fails, a relevant diagnostic will be emitted.
- 'EnumElementDecl' continues to store the raw value expression, which is no longer a 'LiteralExpr' but rather an 'Expr'; however, the getter ('getRawValueExpr') continues to return a 'LiteralExpr' by invoking the constant-folding request on the stored value, which is guaranteed to return a cached result from a prior invocation in 'EnumRawValuesRequest', assuming it succeeded.
- Furthermore, the 'structural' request kind was previously not cached, whereas now because the request must always do the complete type-checking work, it is always cached.

Resolves rdar://168005520
2026-02-10 09:43:07 +00:00
susmonteiro 1d4b29a2d6 Revert "[cxx-interop] Add support for subscripts of non-copyable types"
This reverts commit 341ef5b0e0.
2026-02-09 12:01:53 +00:00
John Hui 5dbc8c25f9 [cxx-interop] Support ownership annotations on FRT constructors
We were previously marking synthesized FRT initializers as
"returns_retained" unconditionally (for non-immortal types), which can
cause memory errors and also suppresses diagnostics about the lack of
such annotations.

This patch fixes that behavior, and also adjusts the source locations of
the synthesized C++ factory method to point to the actual constructor
decl when its location is available, so that the diagnostics make sense
when warning about the lack of annotations.

rdar://163127315
2026-01-21 16:23:53 -08:00
John Hui 3546e8753c Merge pull request #86360 from j-hui/inherited-subscript 2026-01-08 11:32:35 -08:00
Egor Zhdan b0fe5a159c Merge pull request #86122 from egorzhdan/egorzhdan/metatype-param-duplicates
[cxx-interop] Avoid miscompiling calls to function templates with added metatype parameters
2026-01-08 16:05:07 +00:00
John Hui 9de4cf8e11 [cxx-interop] Synthesize subscript without requiring ClangNode
This scenario happens when a derived class inherits operator[] from
a base class. The derived class's operator[] is a synthesized shim,
which (currently) does not have a ClangNode associated with it.

This prevents an assertion failure in SubscriptDecl::createImported().

rdar://167701851
2026-01-07 15:59:56 -08:00
Egor Zhdan 576e27788f [cxx-interop] Avoid miscompiling calls to function templates with added metatype parameters
C++ allows function templates that do not use all of their template parameters in the signature, such as:
```
template <typename T>
bool foo();
```

This is not compatible with Swift's generic model, so to let clients call such functions from Swift, ClangImporter generates an extra metatype parameter:
```
func foo<T>(T: T.Type) -> Bool

// Usage:
foo(Int.self)
foo(Bool.self)
```

That logic had a flaw that surfaced when the C++ function's behavior differs depending on the templated parameter. Instead of instantiating the function template with all of the required template parameters, and using the corresponding instantiation for each call, Swift was (correctly) instantiating the template for the necessary types, but then silently dropping all of the instantiations except for one, and using the remaining one for all callsites. This happened because all of the instantiations were getting the same name in Swift, and therefore had the exact same mangled name, which caused SILGen to pick one and discard the others.

This makes sure that if the extra metatype parameter was added to a function template, all of the function instantiations get unique mangled names.

rdar://166184513
2026-01-05 18:30:59 +00:00
susmonteiro 341ef5b0e0 [cxx-interop] Add support for subscripts of non-copyable types 2026-01-02 10:57:01 +00:00
Gabor Horvath 3a9725c4ac [cxx-interop] Fix missing implicit cast in synthesized code
Follow up for #86124. I forgot to update on of the branches to use Sema
to build the call expression, so the implicit casts responsible for the
offset adjustments did not get inserted. Updated the tests to make sure
both branches are covered.
2025-12-22 13:00:12 +00:00
Gabor Horvath 35bcc99f99 [cxx-interop] Fix miscompilation for inferred shared references
When a base class is annotated as shared reference we can occasionally
infer that the derived types also need to be shared references.
Unfortunately, we did not generate the correct code for some of those
scenarios. When the reference counted base is not at the offset zero we
need to do offset adjustments before we pass the pointer to the
reference counting functions. We did not do those offset calculations.

I looked into implementing the codegen for the offset calculation
directly in Swift but it needed significantly more work than I
anticipated. We need to invoke the frontend to get the path to the base
class and we also need to deal with virtual inheritance, alignment and
some other considerations.

This PR ends up generating a Clang shim instead and the derived to base
conversion happens in this shim. As a result, we piggy-back on Clang
making all the correct offset calculations. This patch also had to
change how certain aspects of shared references are implemented to be
compatible with this approach:
* Instead of always looking at the base classes to querry the
  retain/release operations we now propagate the corresponding
  annotations once per types. This also has the beneficial effects that
  we traverse the inheritance hierarchy less often.
* To generate the correct diagnostics, I reuse the result of the
  refcount operation query.
* We do not want these generated functions to be inherited, so added a
  set to exempt them from cloning.
* Tweaked the lookup logic for retain/release a bit as these generated
  clang methods are not found by lookup. We rely on looking up the
  imported methods instead.

rdar://166227787
rdar://165635002
2025-12-18 18:02:38 +00:00
Egor Zhdan 39d13c4093 [cxx-interop] Fix compile error
This fixes a compiler error introduced by ad56e061. The signature of `isMemberwiseInitializer()` changed after the CI ran on the PR.
2025-12-10 13:43:21 +00:00
Egor Zhdan ad56e061af Merge pull request #85066 from egorzhdan/egorzhdan/std-function-context
[cxx-interop] Allow initializing `std::function` from Swift capturing closures
2025-12-10 13:35:34 +00:00
John Hui f1e2b7a07f Merge pull request #85723 from an0/my-branch
[ClangImporter] Fix NS_CLOSED_ENUM to validate raw values
2025-12-09 13:35:30 -08:00
Gabor Horvath 77187a04ab [cxx-interop] Introduce SWIFT_REFCOUNTED_PTR
This attribute introduces some conversions between the annotated smart
pointer type and the native swift reference type. In the future we plan
to introduce bridging so the smart pointer type can be hidden in the
signature and we can automatically convert it to the native Swift
reference type on the ABI boundaries.

This PR is using a new way to use swift_attr attributes. Instead of
doing the parsing in the clang importer it falls back to Swift's
attribute parsing and makes sure that the annotation has valid Swift
attribute syntax.

rdar://156521316
2025-12-05 18:19:10 +00:00
Egor Zhdan 7fc815e383 [cxx-interop] Allow initializing std::function from Swift capturing closures
This introduces support for converting a Swift closure that captures variables from its surrounding context into an instance of `std::function`, which is useful for working with C++ APIs that use callbacks.

Each instantiation of `std::function` gets a synthesized Swift constructor that takes a Swift closure. Unlike the previous implementation, the closure is _not_ marked as `@convention(c)`. The body of the constructor is created lazily.

Under the hood, the closure is bitcast to a pair of a function pointer and a context pointer, which are then wrapped in a C++ object, `__SwiftFunctionWrapper`, that manages the lifetime of the context object via calls to `swift_retain`/`swift_release` from the copy constructor and the destructor. The `__SwiftFunctionWrapper` class is templated, and is instantiated by ClangImporter.

rdar://133777029
2025-12-05 15:41:59 +00:00
Ling Wang 7f7e41b282 [ClangImporter] Fix NS_CLOSED_ENUM to validate raw values
Generate switch-based validation for @frozen enum init?(rawValue:)
instead of using unchecked reinterpretCast. This ensures only declared
enum cases are accepted, returning nil for invalid raw values.

For non-frozen enums (NS_ENUM), preserve existing reinterpretCast
behavior for C compatibility.

Fixes #85701
2025-12-05 08:54:11 -06:00
Gábor Horváth 981ad6647f Merge pull request #85711 from Xazax-hun/virtual-move-only-types
[cxx-interop] Fix crash when virtual methods take move-only types
2025-12-01 21:09:47 +00:00
Susana Monteiro 92cbcb6864 Merge pull request #85485 from susmonteiro/susmonteiro/remove-request-cycles
[cxx-interop] Refactor ClangTypeEscapability and CxxValueSemantics requests
2025-12-01 21:09:03 +00:00
Gabor Horvath c473c55ce3 [cxx-interop] Fix crash when virtual methods take move-only types
We build forwarding methods to call the virtual methods. The forwarding
methods tried to copy move-only types which resulted in a compiler
crash. Now we try to detect this scenario and insert the required cast
to make sure we get a move instead.

rdar://162195228
2025-11-26 15:41:57 +00:00
Hamish Knight 7bca421d51 [ClangImporter] Add check for Bool in importNumericLiteral
I somehow missed this in my original patch, make sure we also handle
the bool case here.

rdar://164916048
2025-11-24 12:02:31 +00:00
susmonteiro 791194b0ff Simplify CxxValueSemanticsKind 2025-11-20 18:43:04 +00:00
Xi Ge d144524209 CustomAvailability: synthesized dynamic availability checking function should be private
When compiling a Swift module in incremental mode, each Swift source file is compiled into an object file
and we use linker to link them together. Because the predicate function for checking dynamic feature
availability is eagerly synthesized per compilation unit, the linker will complain about duplicated
symbols for them. Setting their visibility as private ensures that linker doesn't see them, thus addressing
the linker errors.

One workaround for this problem is to enable WMO.

rdar://164971313
2025-11-18 09:19:26 -08:00
Slava Pestov 819738c83e AST: Rename mapTypeIntoContext() => mapTypeIntoEnvironment(), mapTypeOutOfContext() => mapTypeOutOfEnvironment() 2025-11-12 14:48:19 -05:00
Xi Ge e31c1cc7f8 CustomAvailability: avoid exposing the synthesized function for dynamic availability checking as an API entry
For dynamic features defined from a header, we synthesize a pure Clang function to check whether the feature should
be enabled at runtime. Swift modules don't have capability to deserialize this clang predicate function, leading to
crasher as a result. This change fixes the crasher by hiding the synthesized function to be a module internal one.

rdar://164410957
2025-11-10 09:26:28 -08:00
Doug Gregor 020b69d4b6 [SE-0497] Implement @export attribute syntax
Implement the @export(implementation) and @export(interface) attributes
to replace @_alwaysEmitIntoClient and @_neverEmitIntoClient. Provide a
warning + Fix-It to start staging out the very-new
@_neverEmitIntoClient. We'll hold off on pushing folks toward
@_alwaysEmitIntoClient for a little longer.
2025-11-07 22:00:40 -08:00
Doug Gregor 34e47290f1 [C++ interop] Fix manual mangling of C++ base method thunks
When creating a C++ method that thunks from a particular C++ derived
class to call a method on one of its base classes, we do some manual
name mangling. This name mangling did not properly capture all of the
aspects of the thunk, so it was prone to collisions.

In moving to SIL asmname, we got a different set of collisions from
the ones that existed previously. Expanding the mangling to account
for small differences (const or not) as well as the base class type
eliminates these collisions. Most of the test changes account for the
new mangling, but the member-inheritance test indicates that this
change fixes an existing miscompile as well.
2025-10-29 19:35:57 -07:00
Hamish Knight 169096c233 [AST] Rename mangleDeclAsUSR -> mangleDeclWithPrefix
This is used by other things that don't necessarily want an IDE
USR.
2025-10-23 09:11:17 +01:00
Hamish Knight 73710e3eef [AST] Introduce Decl::addAttribute
Introduce a convenience entrypoint that also calls `attachToDecl` on
the attribute, and migrate all existing uses of `getAttrs().add` onto
it.
2025-10-16 11:21:54 +01:00
Egor Zhdan f157e71ff5 [cxx-interop] Honor default expressions for unnamed arguments
We stumbled upon an old workaround that disabled the synthesis of Swift default expressions for C++ function parameters that don't have a name.

This change removes the workaround.

rdar://162310543
2025-10-10 16:06:55 +01:00
Henrik G. Olsson 5519be8b7c Move span to conditional header in libstdc++ module map
`span` is not available in all versions of libstd++, so make it a
conditional header. Also adds other missing c++20 headers.

Fixing this triggered an assert when importing a constant initialized
`wchar_t` variable, so that is also fixed. The reason is that `wchar_t`
is mapped to `Unicode.Scalar`, which cannot be directly initialized by
integer literals in Swift, triggering an assert when looking up the
protocol conformance for `_ExpressibleByBuiltinIntegerLiteral`.

rdar://162074714
2025-10-06 16:02:35 -07:00
swift-ci 2b9632fde3 Merge remote-tracking branch 'origin/main' into rebranch 2025-09-30 07:55:22 -07:00
susmonteiro 7e14a8ea40 [cxx-interop] SWIFT_NONCOPYABLE overlooked in some cases 2025-09-30 09:28:58 +01:00
swift-ci ef534479d5 Merge remote-tracking branch 'origin/main' into rebranch 2025-09-22 18:21:46 -07:00
Egor Zhdan 6b4c7fcd80 Merge pull request #84343 from egorzhdan/egorzhdan/retain-release-methods
[cxx-interop] Allow retain/release operations to be methods
2025-09-22 21:53:28 +01:00