Commit Graph

2523 Commits

Author SHA1 Message Date
Henrik G. Olsson
262a53f599 [Swiftify] Update availability for CxxSpan<->Span, fix lifetimebound on parameters with reference type (#81634)
Update availability for CxxSpan<->Span, fix lifetimebound on parameters
with reference type

Because swift-ide-test doesn't care about typechecking,
std-span-interface.swift passed despite containing 2 separate errors.
This updates the test file to properly exercise the entire compilation
pipeline for the macro expansions, by running swift-frontend
-emit-module and calling each macro expansion.

The first issue was that CxxSpan initializers taking [Mutable]Span still
had their availability set to Swift 6.2+, even after back-deploying
caused [Mutable]Span to have availability back to Swift 5.0. Since
_SwiftifyImport expansions copy the availbility of Span, this resulted
in the macro expansions calling unavailable initializers. Interestingly
enough, this manifested itself in the form of a tripped assert in SIL
verification, because although we do now typecheck the expansions from
_SwiftifyImport, the compilation can still keep going after
`shouldEmitFunctionBody` returns false: the macro expansion declaration
is still there, but is now missing its definition, despite not being
external.

The second issue was when parameters with C++ reference types were
annotated with `[[clang::lifetimebound]]`. For parameters with a type
that is `Escapable`, this is normally done using `@lifetime(borrow
foo)`. However C++ reference parameters are imported as `inout`, which
requires the `@lifetime(&foo)` syntax.

rdar://151493400
rdar://151678415
2025-05-22 15:36:19 -07:00
John Hui
828876f4ec Merge pull request #81625 from j-hui/fix-unavailable-enum 2025-05-22 00:01:30 -07:00
Henrik G. Olsson
6534b9b14f [Swiftify] Copy doc comment from clang node (#81584)
Swift nodes imported from clang don't have doc comments carried over,
but IDEs are clever enough to fetch the comments from the associated
clang node. The swift node in the macro expansion from _SwiftifyImport
doesn't have a clang node directly associated with it however.

This patch adds the same comment from the clang node to the
_SwiftifyImport macro invocation node. Since the macro has access to
this node, it can easily copy over its leading trivia.

For now the comment is not altered at all, meaning @param still remains
even if the parmeter is removed.

rdar://151346977
2025-05-20 08:06:20 -07:00
John Hui
5aa5bcfea2 [NFC] [cxx-interop] Flatten findOptionSetEnum() and move it to ImportEnumInfo.cpp
It's at home there alongside other ObjC enum-specific logic, rather than
in the middle of ImportDecl.cpp (since it isn't directly or exclusively
related to importing decls).
2025-05-19 14:21:49 -07:00
John Hui
c7070e73fe [NFC] [cxx-interop] Consolidate uses of findOptionSetType() helper function
Also renames it to findOptionSetEnum() to make it a bit clearer at face
value that the returned ImportedType will contain a Swift enum.

Also refactors some nearby instances of

  if (auto e = dyn_cast<ElaboratedType>(t))
      t = e->desugar();

into a helper function, desugarIfElaborated().
2025-05-19 14:10:49 -07:00
Hamish Knight
edca7c85ad Adopt ABORT throughout the compiler
Convert a bunch of places where we're dumping to stderr and calling
`abort` over to using `ABORT` such that the message gets printed to
the pretty stack trace. This ensures it gets picked up by
CrashReporter.
2025-05-19 20:55:01 +01:00
Henrik G. Olsson
e1eb960e7f [Swiftify] Don't create safe wrapper for autoreleasing pointers (#81568)
_SwiftifyImport doesn't know how to handle
AutoreleasingUnsafeMutablePointer, so we should not attach any
.countedBy information for pointers that are imported as this type.

This also adds defensive checks against adding .countedBy to any pointer
type that _SwiftifyImport doesn't know how to transform.

rdar://151479521
2025-05-17 20:33:00 -07:00
Kuba Mracek
1ecdb17fcc [ClangImporter] Fix enum conversion type when importing global values (unwrap if needed) 2025-05-13 16:02:15 -07:00
fahadnayyar
49aea31e41 [cxx-interop] Disabling should be annotated with SWIFT_RETURNS_(UN)RETAINED warning (#81411)
In Swift 6.1, we introduced warnings for C++ APIs returning
SWIFT_SHARED_REFERENCE types that lack the SWIFT_RETURNS_(UN)RETAINED
annotations. These warnings serve as a reminder to annotate APIs, as the
absence of these annotations can lead to arbitrary assumptions about the
ownership of returned SWIFT_SHARED_REFERENCE values. This could result
in both use-after-free (memory safety) bugs and memory leaks.

We have received feedback from a few adopters indicating potential false
positive cases where these warnings are triggered. Consequently, we have
decided to disable these warnings in Swift 6.2 and re-qualify the
warnings on larger projects to ensure their effectiveness and eliminate
false positives. Our intention is to re-enable the warnings in later
beta releases of Swift 6.2 once we have stronger evidence of their
effectiveness on large codebases and proof that there are no false
positives.

rdar://150937617
rdar://150800115
2025-05-09 17:36:00 -07:00
John Hui
203acbbb47 [NFC] Tidy up formatting for CountedByExpressionValidator
(Renamed from CATExprValidator)
2025-05-09 00:25:20 -07:00
John Hui
e5b1f4a251 [Swiftify] Do not swiftify non-Swift-like counted_by exprs
__counted_by (and __sized_by) expressions can have arbitrary C syntax
in them, such as:

    void foo(int * __counted_by(*len) p, int *len);

When @_SwififyImport tries to generate Swift code for this, the
expression `*len` leads to a syntax error, since it isn't valid Swift.

This patch adds a check to ensure we only attach the Swiftify macro to
__counted_by expressions that are also syntactically valid in Swift.

rdar://150956352
2025-05-08 21:13:20 -07:00
Henrik G. Olsson
59d7d3160f [Swiftify] Emit @availability when expansions contain Span (#81320)
This prevents errors when compiling for older targets using a newer
compiler.

rdar://150740330
2025-05-08 16:13:24 -07:00
fahadnayyar
b311c63ea9 [cxx-interop] Remove SWIFT_RETURNED_AS_RETAINED_BY_DEFAULT annotation (#81329)
This patch removes the `SWIFT_RETURNED_AS_RETAINED_BY_DEFAULT`
annotation while maintaining the support for
`SWIFT_RETURNED_AS_UNRETAINED_BY_DEFAULT`. These type-level annotations
were initially introduced in
[PR-81093](https://github.com/swiftlang/swift/pull/81093) to reduce the
annotation burden in large C++ codebases where many C++ APIs returning
`SWIFT_SHARED_REFERENCE` types are exposed to Swift.

### Motivation
The original goal was to make C++ interop more ergonomic by allowing
type-level defaults for ownership conventions
for`SWIFT_SHARED_REFERENCE` types . However, defaulting to retained
return values (+1) seems to be problematic and poses memory safety
risks.

### Why we’re removing `SWIFT_RETURNED_AS_RETAINED_BY_DEFAULT`

- **Memory safety risks:** Defaulting to retained can potentially lead
to use-after-free bugs when the API implementation actually returns
`unowned` (`+0`). These errors are subtle and can be hard to debug or
discover, particularly in the absence of explicit API-level
`SWIFT_RETURNS_(UN)RETAINED` annotations.
- **Risky transitive behavior:** If a `SWIFT_SHARED_REFERENCE` type is
annotated with `SWIFT_RETURNED_AS_RETAINED_BY_DEFAULT`, any new C++ API
returning this type will inherit the retained behavior by default—even
if the API's actual return behavior is unretained. Unless explicitly
overridden with `SWIFT_RETURNS_UNRETAINED`, this can introduce a silent
mismatch in ownership expectations and lead to use-after-free bugs. This
is especially risky in large or evolving codebases where such defaults
may be overlooked.
- **Simpler multiple inheritance semantics:** With only one type-level
default (`SWIFT_RETURNED_AS_UNRETAINED_BY_DEFAULT`), we avoid
complications that can arise when multiple base classes specify
conflicting ownership defaults. This simplifies reasoning about behavior
in class hierarchies and avoids ambiguity when Swift determines the
ownership convention for inherited APIs.

### Why we’re keeping `SWIFT_RETURNED_AS_UNRETAINED_BY_DEFAULT`
- It still enables projects to suppress warnings for unannotated C++
APIs returning `SWIFT_SHARED_REFERENCE` types, helping to reduce noise
while maintaining clarity.
- It encourages explicitness for retained behavior. Developers must
annotate retained return values with `SWIFT_RETURNS_RETAINED`, making
ownership intent clearer and safer.
- The worst-case outcome of assuming unretained when the return is
actually retained is a memory leak, which is more tolerable and easier
to debug than a use-after-free.
- Having a single default mechanism improves clarity for documentation,
diagnostics, and long-term maintenance of Swift/C++ interop code.
2025-05-07 13:25:25 -07:00
Egor Zhdan
294e4cf21b Merge pull request #81257 from swiftlang/egorzhdan/remove-symbolic-mode
[cxx-interop] Remove symbolic import mode
2025-05-05 18:36:32 +01:00
fahadnayyar
e7bbd4b762 [cxx-interop] Introduce type-level annotations to specify default ownership convention for C++ foreign reference return values (#81093)
In Swift 6.1, we introduced `SWIFT_RETURNS_RETAINED` and
`SWIFT_RETURNS_UNRETAINED` annotations for C++ APIs to explicitly
specify the ownership convention of `SWIFT_SHARED_REFERENCE` type return
values.

Currently the Swift compiler emits warnings for unannotated C++ APIs
returning `SWIFT_SHARED_REFERENCE` types. We've received some feedback
that people are finding these warnings useful to get a reminder to
annotate their APIs. While this improves correctness , it also imposes a
high annotation burden on adopters — especially in large C++ codebases.

This patch addresses that burden by introducing two new type-level
annotations:
- `SWIFT_RETURNED_AS_RETAINED_BY_DEFAULT`
- `SWIFT_RETURNED_AS_UNRETAINED_BY_DEFAULT`

These annotations allow developers to specify a default ownership
convention for all C++ APIs returning a given
`SWIFT_SHARED_REFERENCE`-annotated type, unless explicitly overridden at
the API by using `SWIFT_RETURNS_RETAINED` or `SWIFT_RETURNS_UNRETAINED`.
If a C++ class inherits from a base class annotated with
`SWIFT_RETURNED_AS_RETAINED_BY_DEFAULT` or
`SWIFT_RETURNED_AS_UNRETAINED_BY_DEFAULT`, the derived class
automatically inherits the default ownership convention unless it is
explicitly overridden. This strikes a balance between safety/correctness
and usability:

- It avoids the need to annotate every API individually.
- It retains the ability to opt out of the default at the API level when
needed.
- To verify correctness, the user can just remove the
`SWIFT_RETURNED_AS_(UN)RETAINED_BY_DEFAULT` annotation from that type
and they will start seeing the warnings on all the unannotated C++ APIs
returning that `SWIFT_SHARED_REFERENCE` type. They can add
`SWIFT_RETURNS_(UN)RETAINED` annotation at each API in which they want a
different behaviour than the default. Then they can reintroduce the
`SWIFT_RETURNED_AS_(UN)RETAINED_BY_DEFAULT` at the type level to
suppress the warnings on remaining unannotated APIs.

A global default ownership convention (like always return
`unretained`/`unowned`) was considered but it would weaken the
diagnostic signal and remove valuable guardrails that help detect
use-after-free bugs and memory leaks in absence of
`SWIFT_RETURNS_(UN)RETAINED` annotations. In the absence of these
annotations when Swift emits the unannotated API warning, the current
fallback behavior (e.g. relying on heuristics based on API name such as
`"create"`, `"copy"`, `"get"`) is derived from Objective-C interop but
is ill-suited for C++, which has no consistent naming patterns for
ownership semantics.

Several codebases are expected to have project-specific conventions,
such as defaulting to unretained except for factory methods and
constructors. A type-level default seems like the most precise and
scalable mechanism to support such patterns. It integrates cleanly with
existing `SWIFT_SHARED_REFERENCE` usage and provides a per-type opt-in
mechanism without global silencing of ownership diagnostics.

This addition improves ergonomics while preserving the safety benefits
of explicit annotations and diagnostics.

rdar://145453509
2025-05-02 16:26:07 -07:00
Egor Zhdan
b51cfa5c76 [cxx-interop] Remove symbolic import mode
Importing C++ class templates in symbolic mode has proven to be problematic in interaction with other compiler features, and it isn't used widely. This change removes the feature.

rdar://150528798
2025-05-02 18:43:09 +01:00
John Hui
34be8f988e Merge pull request #81228 from j-hui/fix-ast-layout-dependent-types 2025-05-01 08:40:32 -07:00
John Hui
1fdb239cea [cxx-interop] Avoid querying layout of dependent types during symbolic import
In #80786, we started importing certain padded fields as opaque blobs.
Part of this logic involved querying those fields' ASTRecordLayout.
However, dependent types (which are imported symbolically) do not have
an ASTRecordLayout, so calling Clang's getASTRecordLayout() would lead
to an assertion error for class templates where a no_unique_address
field is some kind of dependent C++ record type.

This patch avoids the field padding check during symbolic import mode
because that check is only relevant for codegen anyway.

rdar://150067288
2025-04-30 18:36:29 -07:00
Yeoul Na
2d7b7a73f8 [Swiftify] SafeInteropWrapper crashes with 'cgImage.width' (#80948)
* [Swiftify] Fix crash calling cgImage.width

cgImage.width calls the C function, CGImageGetWidth(CGImageRef).
Swift representation and Clang representation of this function
seem to have a parameter number mismatch, causing swiftify function
to crash.

rdar://149691207

* [NFC] Fix test/Interop/ObjC/swiftify-import/getter.swift
2025-04-30 08:53:22 -07:00
Gabor Horvath
939ee49dcb [cxx-interop] Fix a crash with [[no_unique_address]]
Swift does not support storing fields in the padding of the previous
fields just yet, so let's not import fields like that from C++.
Represent them as opaque blobs instead.

Fixes #80764

rdar://149072458
2025-04-25 12:46:31 +01:00
Gábor Horváth
c2f560e329 Merge pull request #81030 from swiftlang/gaborh/span-ctor-crash 2025-04-23 12:46:21 -07:00
Gabor Horvath
5238c3fc9b [cxx-interop] Work around crash in codegen when initializing C++ span
When initializing span with an UnsafePointer<Element>? we call into the
generic initializer that we imported from the C++ templated constructor
instead of the concrete initializer we have in the overlay that takes an
UnsafePointer<Element> (non-optional). We cannot properly codegen for
this generic initializer at the moment, so let's stop importing them
since the user probably wanted to call the initializer from the overlay.

We should come back later and fix the root cause.

rdar://148961349
2025-04-23 16:12:58 +01:00
Gabor Horvath
4dd35404b7 [cxx-interop] Properly import annotations from functions in namespace scope
C++ namespaces are imported as Swift enums. This confused the logic that
skips importing namespaces for free functions that are imported as
member functions via the SWIFT_NAME attribute.

rdar://149756644
2025-04-22 13:03:33 +01:00
Kuba Mracek
d70498957a [ClangImporter] Handle nullptr from importTypeIgnoreIUO() in constant values importing logic 2025-04-18 17:19:31 -07:00
Kuba Mracek
26cc36b8b0 [ClangImporter] Handle swift_wrapper annotated typedefs, skip CGFloats when importing const values 2025-04-14 15:03:18 -07:00
Kuba Mracek
8e6071ecbc [ClangImporter] Skip value importing on partial/dependent C++ decls, adjust C++ lit tests 2025-04-14 13:20:51 -07:00
Kuba Mracek
936e91130a [ClangImporter] Fix importing values for constant globals of enum types 2025-04-14 10:01:23 -07:00
Kuba Mracek
a39f60b9ad [ClangImporter] Import constant values for 'const' globals 2025-04-14 10:01:23 -07:00
Pavel Yaskevich
3906980f58 [AST] NFC: Add a convenient way to create implicit NonisolatedAttrs 2025-04-11 15:59:25 -07:00
fahadnayyar
0ae0528434 [cxx-interop] convert CXXForeignReferenceTypeInitializers into SuppressCXXForeignReferenceTypeInitializers to be an opt-out flag
Turning the feature "ctor of C++ foreign reference types is callable as Swift Initializers" on by default.

rdar://148285972
2025-04-10 00:37:50 -07:00
Gabor Horvath
e0a431ec98 [cxx-interop] Diagnose Escapable C++ types with non-escapable fields
rdar://148899224
2025-04-09 13:01:31 +01:00
fahadnayyar
56746e3456 [cxx-interop] Relax error when using SWIFT_RETURNS_(UN)RETAINED on templated return types resolving to non-frts (#78968)
We should not complain about usage of SWIFT_RETURNS_(UN)RETAINED for templated C++ APIs when instantiated with a non SWIFT_SHARED_REFERENCE types

rdar://143732201
2025-04-08 10:39:38 -07:00
fahadnayyar
5d1ce01eb9 [cxx-interop] Import parameterized public ctors of C++ foreign ref types as Swift Initializer (#80449)
Extends PR #79986 by adding support for calling parameterized C++ initializers from Swift. This patch synthesizes static factory methods corresponding to C++ parameterized constructors, allowing Swift to call them as Swift initializers (e.g., init(_:), init(_:_:), etc.). This patch also aded tests and logic to make sure that we emit no additional diagnostics when a C++ foreign ref type is just referred from Swift and its initializer is not explicitly called.

rdar://148285251
2025-04-08 08:58:11 -07:00
Becca Royal-Gordon
274c4d9d22 Merge pull request #80557 from beccadax/the-case-of-the-missing-member
[ClangImporter] Fix import of aliased enum cases
2025-04-07 16:25:53 -07:00
Gábor Horváth
fe98abb10b Merge pull request #80598 from swiftlang/gaborh/nested-foreign-type-metadata
[cxx-interop] Fix a rare compilation error in reverse interop header
2025-04-08 00:02:04 +01:00
Gabor Horvath
b3b20310f5 [cxx-interop] Fix a rare compilation error in reverse interop header
To trigger this error one needs to import a nested type from C++, use it
in a generic context in Swift, and export it back to C++. We were
inconsisent in what namespace did we declare the functions to get the
type metadata for types. It was in the swift namespace for foreign types
and in the module namespace for Swift types. This PR standardizes on how
the metadata function is declared and called to fix the issue.

Fixes #80538.

rdar://148597079
2025-04-07 17:50:19 +01:00
Crazy凡
c05d1fc135 [c++ interop] Swift should allow multiple SWIFT_CONFORMS_TO_PROTOCOL attributes on a C++ class. 2025-04-06 22:24:14 +08:00
Anthony Latsis
cdb2aaccfd AST: Cut down on DescriptiveDeclKind usage in DiagnosticsClangImporter.def 2025-04-05 12:31:20 +01:00
Becca Royal-Gordon
86704e35e1 [ClangImporter] Fix import of aliased enum cases
When a C enum has multiple constants with the same value, ClangImporter selects one of them to import as an `EnumElementDecl` and imports the others as `VarDecl` “aliases” of that one. This helps preserve the invariant that each case of an enum has a unique raw value and is distinct for exhaustiveness checking.

However, a bug in that logic could sometimes cause the canonical case to be imported *twice*—once as an `EnumElementDecl` and again as a `VarDecl` alias. In this situation, the `EnumElementDecl` was not added to the enum’s member list, resulting in a malformed AST. This bug has apparently been present since early 2017 (!), but it seems to have been harmless until recently, when the `ComputeSideEffects` SIL pass recently became sensitive to it (probably because of either #79872 or #80263).

Correct this problem by modifying the memoization logic to retrieve the canonical case’s clang-side constant so the subsequent check will succeed. Additionally change a variable name and add comments to help clarify this code for future maintainers.

In lieu of adding new unit tests, this commit adds a (slightly expensive) conditional assertion to catch this kind of AST malformation. There are actually about twenty tests that will fail with just the assertion and not the fix, but I’ve updated one of them to enable the assertion even in release mode.

Fixes rdar://148213237. Followup to #80487, which added related assertions to the SIL layer.
2025-04-04 18:54:36 -07:00
Gábor Horváth
20f73556f2 Merge pull request #80500 from swiftlang/gaborh/not-imported-return-type
[cxx-interop] Fix not importing return type for certain functions
2025-04-04 10:35:15 +01:00
Gabor Horvath
d254e83376 [cxx-interop] Fix not importing return type for certain functions
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.
2025-04-03 18:12:36 +01:00
Doug Gregor
c522138987 [Strict memory safety] Union member accessors are always unsafe
Union member accessors have no way to know what the "active field" is,
so consider them to always be unsafe.
2025-04-02 16:59:17 -07:00
John Hui
e8bcc52356 [cxx-interop] Fix access check for nested private C++ enums (#80366)
This patch fixes the access check for nested private C++ enums to look for the SWIFT_PRIVATE_FILEID of the enclosing C++ class, if any. Previously, the check was looking at for SWIFT_PRIVATE_FILEID on the enum decl itself (which is meaningless); that prevented nested private enum members from being accessible in Swift.

This patch also specializes the type signature of getPrivateFileIDAttrs to clarify the fact that SWIFT_PRIVATE_FILEID is not a meaningful annotation on anything other than CXXRecordDecl, because that is the only kind of decl that can assign access specifiers to its members.

rdar://148081340
2025-03-31 22:23:22 -07:00
fahadnayyar
9694cc8d70 [cxx-interop] Import default public ctor of C++ foreign ref types as Swift Initializer (#79986)
Building on top of PR #79288, this update synthesizes a static factory method using the default new operator, with a call to the default constructor expression for C++ foreign reference types, and imports them as Swift initializers.

rdar://147529406
2025-03-31 20:33:53 -07:00
John Hui
3b18849dcc [NFC] Remove stale FIXME about importing enum variants (#80358)
This comment is from 940a65a994, but is now stale.
2025-03-31 16:05:48 -07:00
John Hui
bbf92fd6e1 [cxx-interop] Import non-public members of SWIFT_PRIVATE_FILEID-annotated classes (#80320) 2025-03-26 22:41:38 -07:00
Egor Zhdan
7c494800a7 [cxx-interop] Avoid diagnosing missing lifetime operations in symbolic mode
When importing C++ decls in symbolic mode, class templates are not instantiated, which means they might not have a destructor or a move constructor. Make sure we are not trying to diagnose those missing lifetime operations in symbolic mode.

This fixes incorrect diagnostics that were emitted during indexing at the end of compilation:
```
warning: 'import_owned' Swift attribute ignored on type 'basic_string': type is not copyable or destructible
```

As a nice side effect, this moves the logic that emits these diagnostics from the request body, which might be invoked many times, to the importer itself, which is only invoked once per C++ class.

rdar://147421710
2025-03-21 18:07:22 +00:00
Gábor Horváth
ddd36a7cfc Merge pull request #79662 from swiftlang/gaborh/dynamic-self-frt
[cxx-interop] Interpret Self as a static shorthand for FRTs
2025-03-20 17:54:35 +00:00
Andrew Trick
d41c4d4cc9 ClangImporter: fix C++ memberwise inits to use @lifetime(immortal)
_unsafeNonEscapableResult no longer dsiables diagnostics at the call site. We
need to use a proper lifetime annotation for that.
2025-03-19 11:59:05 -07:00
Gabor Horvath
7bdd496f61 Address review comments. 2025-03-19 12:56:56 +00:00