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.
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.
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.
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.
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.
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.