This patch improves the warning for C++ APIs returning
`SWIFT_SHARED_REFERENCE` types but not annotated with either
`SWIFT_RETURNS_RETAINED` or `SWIFT_RETURNS_UNRETAINED` in the following
ways:
1. The warning for missing `SWIFT_RETURNS_(UN)RETAINED` annotations is
now emitted on Swift use sites, rather than while importing the API
(func/method decls).
- This logic is now implemented as a Misl Diagnostic in function
`diagnoseCxxFunctionCalls` in file lib/Sema/MiscDiagnostics.cpp.
- The warning is now triggered only when the API is actually used, which
reduces noise in large C++ headers.
- These warnings are still gated behind experimental-feature-flag `WarnUnannotatedReturnOfCxxFrt`
rdar://150800115
Normally, Swift cannot import an incomplete type. However, when we are
importing a SWIFT_SHARED_REFERENCE type, we're always dealing with
pointers to the type, and there is no need for the underlying type to
be complete. This permits a common pattern in C libraries where the
actual underlying storage is opaque and all APIs traffic in the
pointer, e.g.,
typedef struct MyTypeImpl *MyType;
void MyTypeRetain(MyType ptr);
void MyTypeRelease(MyType ptr);
to use SWIFT_SHARED_REFERENCE to import such types as foreign
references, rather than as OpaquePointer.
Fixes rdar://155970441.
When importing custom availability domains with dynamic predicates from Clang
modules, synthesize predicate functions for `if #available` queries and call
them when generating SIL.
Resolves rdar://138441312.
When MemberImportVisibility is enabled we failed to find certain base
methods from the extensions when said base methods are imported from
C++.
rdar://154887575
While this made sense in the distant past where the scanning service provided backing storage for the dependency cache, it no longer does so and now makes for awkard layering where clients get at the service via the cache. Now the cache is a simple data structure while all the clients that need access to the scanning service will get it explicitly.
- 'SwiftModuleScanner' will now be owned directly by the 'ModuleDependencyScanningWorker' and will contain all the necessary custom logic, instead of being instantiated by the module interface loader for each query
- Moves ownership over module output path and sdk module output path directly into the scanning worker, instead of the cache
This patch makes sure we don't get warnings in strict memory safe mode
when using shared references. Those types are reference counted so we
are unlikely to run into lifetime errors.
rdar://151039766
On creation, 'ClangImporter' adds overlay modulemap files for non-modular platform libraries (e.g. glibc, libstdc++), which allows Swift code to import and use those libraries.
This change adds the same filesystem overlay to dependency scanning queries by applying them to the filesystem instantiated for each depndency scanning worker. Without these overlays EBM builds cannot discover and use non-modular system libraries on non-Darwin platforms.
Resolves rdar://151780437
After removing the CASFS implementation for clang modules, there is no
need to capture clang extra file that sets up the VFS for the clang
modules since all content imported by ClangImporter is dependency
scanned and available via include-tree. This saves more ClangImporter
instance when caching is enabled.
Update the test to check that clang content found via `-Xcc` VFS options
can currently work without capture the headermaps and vfs overlays.
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
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
It is possible for a C++ class template to inherit from a specialization
of itself. Normally, these are imported to Swift as separate (unrelated)
types, but when symbolic import is enabled, unspecialized templates are
imported in place of their specializations, leading to circularly
inheriting classes to seemingly inherit from themselves.
This patch adds a check to guard against the most common case of
circular inheritance, when a class template directly inherits from
itself. This pattern appears in a recent version of libc++,
necessitating this patch. However, the solution here is imperfect as it
does not handle more complex/contrived circular inheritance patterns.
This patch also adds a test case exercising this pattern. The
-index-store-path flag causes swift-frontend to index the C++ module
with symbolic import enabled, without the fix in this patch, that test
triggers an assertion failure due to the circular reference (and can
infinitely recurse in the StorageVisitor when assertions are disabled).
rdar://148026461
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
When loading a module with embedded bridging header, bind the bridging
header module in the context when bridging header auto chaining is used.
This is because all the bridging header contents are chained into a PCH
file so binary module with bridging header should reference the PCH file
for all declarations.
rdar://148538787
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
Currently, we only get warnings for using unsafe types in expressions
but not in the function signature. The tests did not use the std::string
object in the function body. As a result, we regressed and std::string
was considered unsafe.
The reason is that the annotation only mode for calculating escapability
of a type did not do what we intended. std::basic_string is
conditionally escapable if the template argument is escapable. We
considered 'char' to have unknown escapability in annotation only mode.
The annotation only mode was introduced to avoid suddenly importing
certain types as not escapable when they have pointer fields and break
backward compatibility.
The solution is to make annotation only mode to still consider char and
co as escapable types and only fall back to unknown when the inference
otherwise would have deduced non-escapable (for unannotated typed).
The Error enum synthesized declarations, e.g. the struct and its static accessors, should generally appear to be identical to the underlying Clang definitions. There are some specific use cases where the synthesized declarations are necessary though.
I've added an option for USR generation to override the Clang node and emit the USR of the synthesized Swift declaration. This is used by SwiftDocSupport so that the USRs of the synthesized declarations are emitted.
Fixes 79912
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
With '-sdk-module-cache-path', Swift textual interfaces found in the SDK will be built into a separate SDK-specific module cache.
Clang modules are not yet affected by this change, pending addition of the required API.
This is very brittle in this first iteration. For now we require the
declaration representing the availability domain be deserialized before it can
be looked up by name since Clang does not have a lookup table for availabilty
domains in its module representation. As a result, it only works for bridging
headers that are not precompiled.
Part of rdar://138441266.
It is possible for a module interface (e.g., ModuleA) to be generated
with C++ interop disabled, and then rebuilt with C++ interop enabled
(e.g., because ModuleB, which imports ModuleA, has C++ interop enabled).
This circumstance can lead to various issues when name lookup behaves
differently depending on whether C++ interop is enabled, e.g., when
a module name is shadowed by a namespace of the same name---this only
happens in C++ because namespaces do not exist in C. Unfortunately,
naming namespaces the same as a module is a common C++ convention,
leading to many textual interfaces whose fully-qualified identifiers
(e.g., c_module.c_member) cannot be correctly resolved when C++ interop
is enabled (because c_module is shadowed by a namespace of the same
name).
This patch does two things. First, it introduces a new frontend flag,
-formal-cxx-interoperability-mode, which records the C++ interop mode
a module interface was originally compiled with. Doing so allows
subsequent consumers of that interface to interpret it according to the
formal C++ interop mode. Note that the actual "versioning" used by this
flag is very crude: "off" means disabled, and "swift-6" means enabled.
This is done to be compatible with C++ interop compat versioning scheme,
which seems to produce some invalid (but unused) version numbers. The
versioning scheme for both the formal and actual C++ interop modes
should be clarified and fixed in a subsequent patch.
The second thing this patch does is fix the module/namespace collision
issue in module interface files. It uses the formal C++ interop mode to
determine whether it should resolve C++-only decls during name lookup.
For now, the fix is very minimal and conservative: it only filters out
C++ namespaces during unqualified name lookup in an interface that was
originally generated without C++ interop. Doing so should fix the issue
while minimizing the chance for collateral breakge. More cases other
than C++ namespaces should be added in subsequent patches, with
sufficient testing and careful consideration.
rdar://144566922
This patch is follow-up work from #78942 and imports non-public members,
which were previously not being imported. Those members can be accessed
in a Swift file blessed by the SWIFT_PRIVATE_FILEID annotation.
As a consequence of this patch, we are also now importing inherited members
that are inaccessible from the derived classes, because they were declared
private, or because they were inherited via nested private inheritance. We
import them anyway but mark them unavailable, for better diagnostics and to
(somewhat) simplify the import logic for inheritance.
Because non-public base class members are now imported too, this patch
inflames an existing issue where a 'using' declaration on an inherited member
with a synthesized name (e.g., operators) produces duplicate members, leading
to miscompilation (resulting in a runtime crash). This was not previously noticed
because a 'using' declaration on a public inherited member is not usually
necessary, but is a common way to expose otherwise non-public members.
This patch puts in a workaround to prevent this from affecting the behavior
of MSVC's std::optional implementation, which uses this pattern of 'using'
a private inherited member. That will be fixed in a follow-up patch.
Follow-up work is also needed to correctly diagnose ambiguous overloads
in cases of multiple inheritance, and to account for virtual inheritance.
rdar://137764620
This patch introduces an a C++ class annotation, SWIFT_PRIVATE_FILEID,
which will specify where Swift extensions of that class will be allowed
to access its non-public members, e.g.:
class SWIFT_PRIVATE_FILEID("MyModule/MyFile.swift") Foo { ... };
The goal of this feature is to help C++ developers incrementally migrate
the implementation of their C++ classes to Swift, without breaking
encapsulation and indiscriminately exposing those classes' private and
protected fields.
As an implementation detail of this feature, this patch introduces an
abstraction for file ID strings, FileIDStr, which represent a parsed pair
of module name/file name.
rdar://137764620
Interop is injecting escapability annotations for the STL and doing a
limited inference for aggregates. Let's reuse the same facilities in the
AST when we calculate the safety of the foreign types.
Add ability to automatically chaining the bridging headers discovered from all
dependencies module when doing swift caching build. This will eliminate all
implicit bridging header imports from the build and make the bridging header
importing behavior much more reliable, while keep the compatibility at maximum.
For example, if the current module A depends on module B and C, and both B and
C are binary modules that uses bridging header, when building module A,
dependency scanner will construct a new header that chains three bridging
headers together with the option to build a PCH from it. This will make all
importing errors more obvious while improving the performance.
This commit removes the guardrails in ImportDecl.cpp:SwiftDeclConverter
that prevent it from importing non-public C++ members. It also
accordingly adjusts all code that assumes generated Swift decls should
be public. This commit does not import non-public inherited members;
that needs its own follow-up patch.
Note that Swift enforces stricter invariants about access levels than C++.
For instance, public typealiases cannot be assigned private underlying types,
and public functions cannot take or return private types. Meanwhile,
both of these patterns are supported in C++, where exposing private types
from a class's public interface is considered feature. As far as I am aware,
Swift was already importing such private-containing public decls from C++
already, but I added a test suite, access inversion, that checks and
documents this scenario, to ensure that it doesn't trip any assertions.
Follow-up from #78132, which did not fix issues related to eagerly imported members like subscripts.
This patch restructures recursive ClangRecordMemberLookup requests to importBaseMemberDecl() in the recursive calls, rather than propagating base member decls up to the initial lookup request and doing the import. Doing so seems to fix lingering resolution issues (which I've added to the regression tests).
rdar://141069984
Nested calls to importBaseMemberDecl() subvert its cache and compromise its idempotence, causing the semantic checker to spuriously report ambiguous member lookups when multiple ClangRecordMemberLookup requests are made (e.g., because of an unrelated missing member lookup).
One such scenario is documented as a test case: test/Interop/Cxx/class/inheritance/inherited-lookup-typechecker.swift fails without this patch because of the expected error from the missing member. Meanwhile, test/Interop/Cxx/class/inheritance/inherited-lookup-executable.swift works because it does not attempt to access a missing member.
This patch fixes the issue by only calling importBaseMemberDecl() in the most derived class (where the ClangRecordMemberLookup originated, i.e., not in recursive requests).
As a consequence of my patch, synthesized member accessors in the derived class directly invoke the member from the base class where the member is inherited from, rather than incurring an indirection at each level of inheritance. As such, the synthesized symbol names are different (and shorter). I've taken this opportunity to update the relevant tests to // CHECK for more of the mangled symbol, rather than only the synthesized symbol prefix, for more precise testing and slightly better readability.
rdar://141069984
In rare scenarios, Swift was emitting diagnostics that looked like this:
```
warning: 'import_owned' swift attribute ignored on type 'basic_string': type is not copyable or destructible
```
This change makes sure the compiler does not emit these (incorrect) warnings. See the inline comment for more details.
This PR adds a variadic macro that builds a SwiftAttr string containing
the names of the template type parameters that need to be escapable for
the type to be considered escapable. It also adds logic to interpret
this annotation.
rdar://139065437