Commit Graph

42 Commits

Author SHA1 Message Date
John Hui
89f8855ad6 [cxx-interop] Check for NS_OPTIONS macro in findOptionSetEnum()
importer::findOptionSetEnum() uses some fragile heuristics to determine
whether a typedef is involved in the construction of a CF_OPTIONS or
NS_OPTIONS type. This patch adds an explicit check that the typedef is
expanded from either of those macros, to prevent, e.g., an unavailable
NS_ENUM, from being mistakenly recognized as an NS_OPTIONS.

Note that doing this is still kind of fragile, and prevents users from
building {NS,CF}_OPTIONS with their own macros. The right thing to do is
probably specifically look for the flag_enum attribute, but that is not
currently what we're doing for reasons whose discovery is left as
an exercise to the future git archaeologist.

This patch also removes (part of) a test case that builds
a CF_OPTIONS-like type with the "SOME_OPTIONS" macro, which is no longer
supported as of this patch.

rdar://150399978
2025-05-21 15:01:09 -07:00
Susana Monteiro
7f1792a12f Merge pull request #79791 from swiftlang/susmonteiro/enums-same-gen-name
[cxx-interop] Use qualified name in import info of clang declarations
2025-03-11 20:34:45 +00:00
Egor Zhdan
5b7c595b2e [cxx-interop] Remove workarounds for CF_OPTIONS default arguments
ClangImporter has logic that infers default arguments of certain C/C++ types, such as the types declared via `CF_OPTIONS`/`NS_OPTIONS` macros.

There were some workarounds in place which triggered for C++ interop mode specifically. The workarounds were applying a heuristic based on the name of the type, which tried to match the behavior to non-C++ interop mode for certain types from the OS SDK. That was not working well for user-defined types, causing source compatibility breakages when enabling C++ interop.

This change replaces the name-based heuristic with a more robust criteria.

See also 3791ccb6.

rdar://142961112
2025-03-11 12:47:21 +00:00
susmonteiro
18ee0ee6f1 [cxx-interop] Use qualified name in import info of clang declarations 2025-03-10 12:39:32 +00:00
Egor Zhdan
3791ccb6e6 [cxx-interop] Allow AppKit & UIKit to be rebuilt with C++ interop enabled
This removes a workaround from the module interface loader, which was forcing AppKit and UIKit to be rebuilt from their textual interfaces with C++ interop disabled, even if the current compilation explicitly enables it.

The workaround was previously put in place because of a compiler error:
```
error: type 'AttributeScopes.AppKitAttributes.StrikethroughStyleAttribute' does not conform to protocol 'AttributedStringKey'
note: possibly intended match 'AttributeScopes.AppKitAttributes.StrikethroughStyleAttribute.Value' (aka 'NSUnderlineStyle') does not conform to 'Hashable'
```

`NSUnderlineStyle` is a C/C++ type from AppKit that is declared using `NS_OPTIONS` macro. `NS_OPTIONS`/`CF_OPTIONS` macros have different expansions in C vs C++ language modes. The C++ expansions weren't handled correctly by ClangImporter, resulting in two distinct Swift types being created: a `typealias NSUnderlineStyle` which was marked as unavailable in Swift, and `enum NSUnderlineStyle`. This mostly worked fine, since the lookup logic was picking the enum during regular name lookup. However, this silently broke down when rebuilding the explicit conformance from `AppKit.swiftinterface`:
```
extension AppKit.NSUnderlineStyle : Swift.Hashable {}
```
Swift was picking the (unavailable) typealias when rebuilding this extension, which means the (available) enum wasn't getting the conformance.

This is verified by an existing test (`test/Interop/Cxx/objc-correctness/appkit-uikit.swift`).

rdar://142961112
2025-03-07 13:27:11 +00:00
Erik Eckstein
7cceaff5f3 SIL: don't print operand types in textual SIL
Type annotations for instruction operands are omitted, e.g.

```
  %3 = struct $S(%1, %2)
```

Operand types are redundant anyway and were only used for sanity checking in the SIL parser.

But: operand types _are_ printed if the definition of the operand value was not printed yet.
This happens:

* if the block with the definition appears after the block where the operand's instruction is located

* if a block or instruction is printed in isolation, e.g. in a debugger

The old behavior can be restored with `-Xllvm -sil-print-types`.
This option is added to many existing test files which check for operand types in their check-lines.
2024-11-21 18:49:52 +01:00
John Hui
493d37e776 [cxx-interop] Fix hashable-enums test (#77053)
The hash of enum values are different from that of their underlying
rawValue due to the implementation details of Int on 64-bit platform
which are not true on 32-bit platforms. This commit removes the tests
that rely on this behavior.

rdar://138032645
2024-10-16 13:52:38 -07:00
John Hui
b58a908082 [cxx-interop] Add Hashable conformance to imported enums (#76940)
* [cxx-interop] Add Hashable conformance to imported enums

Previously, imported enums only conformed to RawRepresentable and Equatable,
so they could not be used as members of a Set or keys of a Dictionary.
This patch adds Hashable conformance to give them that ability,
as well as some test cases to clarify the expected behavior.
Existing test cases are updated to reflect this new conformance.

rdar://129713687
2024-10-15 20:24:35 -07:00
Alex Lorenz
1f6373ee8b Revert "Revert "Revert "[cxx-interop] Use up-to-date definition of CF_OPTIONS in tests"""
This reverts commit 6a3defdfb0.
2023-09-28 18:47:26 -07:00
Egor Zhdan
6a3defdfb0 Revert "Revert "[cxx-interop] Use up-to-date definition of CF_OPTIONS in tests""
This reverts commit e1a9be2203.
2023-09-15 13:57:25 +01:00
zoecarver
e1a9be2203 Revert "[cxx-interop] Use up-to-date definition of CF_OPTIONS in tests"
This reverts commit f20617be0c.
2023-09-11 15:38:42 -07:00
Egor Zhdan
f20617be0c [cxx-interop] Use up-to-date definition of CF_OPTIONS in tests 2023-08-18 16:23:41 +01:00
Alex Lorenz
0eed1a944c [cxx-interop] correctly add and lookup enumerators added to enums that correspond to namespaces
Fixes https://github.com/apple/swift/issues/67604
2023-07-31 18:57:50 -07:00
Puyan Lotfi
936990864d [cxx-interop] Add-on commits to previous NS_OPTIONS fix PR
Add-on to address comments from #67036

Addresses some nits, test addons, and some code cleanups/improvement.
2023-07-03 15:41:50 -04:00
Puyan Lotfi
7cef628f94 [cxx-interop] Import ObjCPropertyDecl of type NS_OPTIONS fields a struct type
Try importing ObjCPropertyDecl field types the C++-Interop-NS_OPTIONS
way. This will fix cases such as:

```
import UIKit

func f(gesture: UISwipeGestureRecognizer,
       direction: UISwipeGestureRecognizer.Direction) {
  gesture.direction = direction // error
}
```

because it will make sure the field inside class UIGestureRecognizer is
of the enum-struct type and not the typedef-rawValue type when importing
an ObjC class.
2023-06-30 17:51:37 -04:00
zoecarver
f374fa08e7 [nfc][cxx-interop] Remove NS(U)Integer typedefs from a test. 2023-06-14 14:17:10 -07:00
zoecarver
3f45c172cc [cxx-interop] Correctly import fields with type NS_Option. 2023-06-08 13:12:38 -07:00
Nuri Amari
709321b69f Fix ASTMangler mangling NS_OPTION differently in C++ mode
CF_OPTIONS is defined differently in the SDK based on
a __cplusplus preprocessor branch. As a result, declarations
referencing CF_OPTIONS are mangled differently depending
on if C++ interop is enabled.

This meant a module compiled with cxx interop on could
not be linked with a module compiled without and vice versa.
This patch modifies the mangler such that the mangled names
are consistent. This is achieved by feeding the mangler a modified
AST node that looks like the Objective-C definition of CF_OPTIONS,
even when we have cxx interop enabled.
2023-03-09 09:30:05 -08:00
Nuri Amari
a4d9082fa8 Fix NS_OPTION parameter label transformation for multi-word suffixes
When Objective-c methods are imported into Swift, the labels are
transforms to remove suffixes based on the type of the parameter. Due
to the structure of NS_OPTION when importing in C++ mode, there is
some special handling for this case introduced in PR #59421.

This patch fixes some of this hanlding for when a multi-word suffix
needs removing, specifically 'ControlEvents' and 'ScrollPosition'.
2023-02-16 14:04:54 -08:00
Nuri Amari
fb14414bc9 Fix assertion failure importing NS_OPTION with differing Swift name across versions
At the call sites of `findAnonymousEnumForTypedef` we often wish to
import the returned enum declaration and return the type the declaration
creates.

Prior to this patch, we assumed that the enum declaration would be
imported as a `NominalTypeDecl`. This is not always the case. For
whatever reason, sometimes in typechecking we import a declaration
for various different naming versions. If the Swift name for an imported
enum differs between the canonical name version, and currently
requested name version, we import the enum as a `TypeAliasDecl` instead.

Prior to this patch, this meant we would hit asserts importing some
components of UIKit.

This patch relaxes the assumption that the import is a `NominalTypeDecl`
to just a `TypeDecl`, which as of yet, seems to be true.
2023-02-16 08:44:44 -08:00
Nuri Amari
3a555bd2f7 Fix effective context construction for NS_OPTIONS in linkage spec
When the ClangImporter imports a name, it associates it with a
an EffectiveClangContext. An EffectiveClangContext can be thought of
as the Clang scope the declaration will reside in, as far as importing
into Swift is concerned. This helps API notes and NS_SWIFT_NAME
to manipulate the SDK interface presented to Swift users.

When a entry is added to the Swift lookup table, it is associated
with a context. This context is a type and a name, used to effectively
namespace entries in the table. This context is derived from the
EffectiveClangContext associated with the name. This translation is
handled by SwiftLookupTable::translateContextDecl among other machinery.
This method in particular, understands only how to translate a set of
Clang nodes, and fails to create a context in other cases.

Prior to this patch, the EffectiveClangContext of declarations annotated
with UIKIT_EXTERN, with cxx-interop turned on, was a LinkageSpecDecl.
This results in context translation failure, and warnings produced in
SwiftLookupTable::finalizeLookupTable. This patch corrects name import
behavior to skip over the LinkageSpecDecl, and use the enclosing
TranslationUnit instead. This is appropriate and performed by
`determineEffectiveContext` as a LinkageSpecDecl is a so called
"transparent" context. That is its members are semantically declared and
accessible outside the context without additional qualification.

This patch tests using API notes, as that is the method UIKit uses. The
issue could just as easily be surface with a NS_SWIFT_NAME annotation.
Even without any annotation at all, the we would still fail to
translate, though there would likely be no corresponding warnings.
2022-12-03 14:05:19 -08:00
Nuri Amari
5f5bebfe3e Correct effective context translation for NS_OPTIONS anon C++ enums
Prior to this patch, SwiftLookupTable::translateDeclToContext relied
on the `TypedefNameDeclOrQualifier` field of an anonymous tag decl to
create a name for entry representing an anonymous tag in the lookup
table. This field is not always populated by Clang, it is often
populated only for the purposes of generating a linkage name when the
type is introduced via typedef as follows:

```
typedef enum { option1, option2} MyAnonEnum;
```

The field is not populated for anonymous enums introduced by NS_OPTIONS
with cxx interop enabled. This patch adds a fallback check in
`translateDeclToContext` that if the field is empty, check if the enum
is backed by a typedef that is unavailable in Swift. If that is the
case, use that name for the lookup table entry.
2022-11-18 11:12:05 -08:00
Alex Lorenz
9348d440b0 Merge pull request #61639 from mikepinkerton/enum-test
[cxx-interop] Test typed and untyped enums cannot be assigned to each other
2022-10-19 23:13:52 -07:00
Mike Pinkerton
441ebd324a Initial cut. 2022-10-19 13:07:11 -05:00
Nuri Amari
bca7330fda Respect NS_REFINED_FOR_SWIFT importing anon enums
When an anonymous enum is imported, its imported name is under some
circumstances derived from the type that it is backed by.
NS_REFINED_FOR_SWIFT is a macro that produces a __attribute__((swift_private))
that when attached to a declaration, the imported name of this
declaration should have two underscores prepended. When the name
anonymous enum is derived from another declaration, and said declaration
does not have the same swift private attribute, the __ is dropped. This
patch fixes this.
2022-10-07 21:38:32 -07:00
zoecarver
aaec49e0a5 [cxx-interop] Fix anonymous enum issue for swift-named computed properties. 2022-08-14 15:45:39 -07:00
zoecarver
1adb6116e7 [cxx-interop] Add anonymous enum logic to importFunctionReturnType(). 2022-07-29 14:52:41 -07:00
Puyan Lotfi
28375ae7df [c++-interop] Providing information about enum types from inferDefaultArgument
When ClangImporter::Implementation::inferDefaultArgument processes
func/method arguments as part of omitNeedlessWordsInFunctionName it
processes information about how the typenames for the parameters related
to the parameter names to form a parameter names list. The parameter
names list is used to determine if the argument label for a function
should be clipped based on the typename. So for example a type like
NSOrderedCollectionDifferenceCalculationOptions would cause a label
ending with "Options" to get clipped so that for instance "withOptions"
becomes simply "with".

Unfortunately in the context of C++-Interop, the typename for the
parameter often resolves to what the type backing the typedef or enum is
and not the actual name of the typedef
(so `typedef NSUInteger NSOrderedCollectionDifferenceCalculationOptions`
 resolves to a name of NSUInteger rather than
 NSOrderedCollectionDifferenceCalculationOptions).

This patch seeks to collect a bit more information when processing
NS_OPTIONS typedefs and providing that to the calling
omitNeedlessWordsInFunctionName to handle more inteligently.

In practice this fixes anywhere in Foundatio where

`withOptions: NSOrderedCollectionDifferenceCalculationOptions` is used.
2022-06-16 19:41:04 -07:00
Puyan Lotfi
dd4cdfb653 [C++-Interop] Fix EffectiveClangContext for NS_OPTIONS EnumDecl lookup.
This patch fixes an issue with C++-Interop that has been making it so
that enums under interop were not getting properly looked up and
therefore not getting imported. The reason for this was that the proper
DeclContext was not getting applied when grabbing the decls use by
VisitDecls later in the ClangImporter.

The lookup code at SwiftLookupTable::lookup is given a clang TU which is
what implcitly gets turned into an EffectiveClangContext. The
EffectiveClangContext is the piece that decides which DeclContext to
use. In the case of an extern "C" (ie LinkageSpecDecl), the
EffectiveClangContext was not traversing inside the lexical scope of the
extern "C" as the context for searching the EnumDecl (the NS_OPTIONS
Enum).

This patch adds new behavior when EffectiveClangContext is given a
LinkageSpecDecl. It sets the DeclContext to the lexical decl context.

With this fix in place in the presence of C++-Interop we not only import
the NS_OPTIONS typedef properly, but we also import the enum (and
therefore the EnumConstants) correctly (which are used for getting to
the flags for populating the NS_OPTIONS bitfields.
2022-05-23 20:10:36 -07:00
zoecarver
06761a89e9 [cxx-interop] Use typedef's swift_name attr to rename anonymous enums. 2022-04-22 12:47:36 -07:00
Zoe Carver
5be506ed8f Merge pull request #42452 from zoecarver/method-param-types-use-enum-not-typedef
[cxx-interop] Apply typedef -> enum patch to method param types as well.
2022-04-19 22:49:43 -07:00
zoecarver
2c983d968e [cxx-interop] Apply typedef -> enum patch to method param types as well.
Basically just applying https://github.com/apple/swift/pull/42431 to ObjC method param tyeps.
2022-04-19 12:03:12 -07:00
Zoe Carver
56e024ddf0 Merge pull request #42412 from plotfi/c-enums-withOptions-omit
[C++-Interop] Teach omitNeedlessWords to handle raw integer C-enums in C++
2022-04-19 11:33:26 -07:00
Puyan Lotfi
a0985a0567 [C++-Interop] Teach omitNeedlessWords to handle raw integer C-enums in C++
As I understand it, enums in C++ do not allow for bitwise operations
that can also be assigned or returned as the same enum type. As a result
there are macros in (Core)Foundation like NS/CF_OPTIONS that produce
enums differently depending on #if __cplusplus or not.

Because of this, code in omitNeedlessWordsInFunctionName and
subsequently inferDefaultArgument in the ClangImporter that is in charge
of replacing "needless words" from method and enum names does not
trigger in the case of C++ because it is looking for EnumDecls that do
not exists because they are actually typedefs on wrap integers or
NSIntegers.

This change attempts to do the renaming off of the typedef alone when
such code exists.

Special thanks to @bulbazord (Alex Langford) for taking the time to
investigate this issue.
2022-04-19 00:00:52 -07:00
zoecarver
e6af2d9b49 [cxx-interop] Import enum, not typedef for parameter types.
Lookup the "anonymous" enum when importing parameter types rather than using the typedef's underlying type.
2022-04-18 19:20:19 -07:00
zoecarver
965c7ca443 [cxx-interop] Allow anonymous enums to use the name of their base.
If an anonymous enum inherits from a typedef, it will have the typedef's name.
2022-04-18 11:05:58 -07:00
zoecarver
839839f924 [cxx-interop] Rename enable-cxx-interop -> enable-experimental-cxx-interop.
Also removes the driver flag, this will now also always be guarded on `-Xfrontend`.
2022-04-07 19:15:25 -07:00
zoecarver
eeeb27d66e [cxx-interop] Add members to the LookupTable where possible.
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.
2021-10-13 11:53:58 -07:00
Saleem Abdulrasool
df9d1e815f Interop/Cxx: explicitly require C++ for modules
The C++ interop modules require C++ support.  Explicitly require C++ as
a feature when building these modules.  This has no impact on the
changes as all the tests enable C++ already.
2021-01-06 16:59:42 -08:00
zoecarver
3c5f2c9d52 [cxx-interop] Support scoped enums (enum classes).
Simply treat scoped enums as (pre-existing) "non frozen enums". C++
scoped enums are actually imported as Swift enums (unlike other enums)
and no global variables need be created (given their "scoped" nature).
2020-12-16 13:47:55 -08:00
Marcel Hlopko
bde9c3b683 [cxx-interop] Fix header guards in test/Interop (#35039) 2020-12-15 09:20:19 +01:00
zoecarver
05faa07c48 [cxx-interop] Support bool-based enums.
This is a small fix to prevent a crash. This change simply adds another
condition for the "bool" branch that checks if "type" is associated with
a "clang::EnumDecl" with an underlying type of "bool", and if so, treats
"type" as a "Bool".
2020-10-24 23:08:59 -07:00