Skip to content

Commit 8b182fb

Browse files
authored
Merge pull request #67130 from plotfi/ns-options-type-import-inside-objc-interface-5.9
Implement correct NS_OPTIONS type import inside objc interface (5.9)
2 parents 8f032ec + 09a56a8 commit 8b182fb

File tree

4 files changed

+58
-18
lines changed

4 files changed

+58
-18
lines changed

lib/ClangImporter/ImportDecl.cpp

Lines changed: 31 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -818,6 +818,31 @@ static bool isPrintLikeMethod(DeclName name, const DeclContext *dc) {
818818
using MirroredMethodEntry =
819819
std::tuple<const clang::ObjCMethodDecl*, ProtocolDecl*, bool /*isAsync*/>;
820820

821+
ImportedType findOptionSetType(clang::QualType type,
822+
ClangImporter::Implementation &Impl) {
823+
ImportedType importedType;
824+
auto fieldType = type;
825+
if (auto elaborated = dyn_cast<clang::ElaboratedType>(fieldType))
826+
fieldType = elaborated->desugar();
827+
if (auto typedefType = dyn_cast<clang::TypedefType>(fieldType)) {
828+
if (Impl.isUnavailableInSwift(typedefType->getDecl())) {
829+
if (auto clangEnum =
830+
findAnonymousEnumForTypedef(Impl.SwiftContext, typedefType)) {
831+
// If this fails, it means that we need a stronger predicate for
832+
// determining the relationship between an enum and typedef.
833+
assert(
834+
clangEnum.value()->getIntegerType()->getCanonicalTypeInternal() ==
835+
typedefType->getCanonicalTypeInternal());
836+
if (auto swiftEnum = Impl.importDecl(*clangEnum, Impl.CurrentVersion)) {
837+
importedType = {cast<TypeDecl>(swiftEnum)->getDeclaredInterfaceType(),
838+
false};
839+
}
840+
}
841+
}
842+
}
843+
return importedType;
844+
}
845+
821846
namespace {
822847
/// Customized llvm::DenseMapInfo for storing borrowed APSInts.
823848
struct APSIntRefDenseMapInfo {
@@ -3658,23 +3683,8 @@ namespace {
36583683
return nullptr;
36593684
}
36603685

3661-
ImportedType importedType;
36623686
auto fieldType = decl->getType();
3663-
if (auto elaborated = dyn_cast<clang::ElaboratedType>(fieldType))
3664-
fieldType = elaborated->desugar();
3665-
if (auto typedefType = dyn_cast<clang::TypedefType>(fieldType)) {
3666-
if (Impl.isUnavailableInSwift(typedefType->getDecl())) {
3667-
if (auto clangEnum = findAnonymousEnumForTypedef(Impl.SwiftContext, typedefType)) {
3668-
// If this fails, it means that we need a stronger predicate for
3669-
// determining the relationship between an enum and typedef.
3670-
assert(clangEnum.value()->getIntegerType()->getCanonicalTypeInternal() ==
3671-
typedefType->getCanonicalTypeInternal());
3672-
if (auto swiftEnum = Impl.importDecl(*clangEnum, Impl.CurrentVersion)) {
3673-
importedType = {cast<TypeDecl>(swiftEnum)->getDeclaredInterfaceType(), false};
3674-
}
3675-
}
3676-
}
3677-
}
3687+
ImportedType importedType = findOptionSetType(fieldType, Impl);
36783688

36793689
if (!importedType)
36803690
importedType =
@@ -5199,7 +5209,11 @@ namespace {
51995209
}
52005210
}
52015211

5202-
auto importedType = Impl.importPropertyType(decl, isInSystemModule(dc));
5212+
auto fieldType = decl->getType();
5213+
ImportedType importedType = findOptionSetType(fieldType, Impl);
5214+
5215+
if (!importedType)
5216+
importedType = Impl.importPropertyType(decl, isInSystemModule(dc));
52035217
if (!importedType) {
52045218
Impl.addImportDiagnostic(
52055219
decl, Diagnostic(diag::objc_property_not_imported, decl),

lib/ClangImporter/ImportType.cpp

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3212,6 +3212,9 @@ ImportedType ClangImporter::Implementation::importMethodParamsAndReturnType(
32123212
importedType.isImplicitlyUnwrapped()};
32133213
}
32143214

3215+
ImportedType findOptionSetType(clang::QualType type,
3216+
ClangImporter::Implementation &Impl);
3217+
32153218
ImportedType ClangImporter::Implementation::importAccessorParamsAndReturnType(
32163219
const DeclContext *dc, const clang::ObjCPropertyDecl *property,
32173220
const clang::ObjCMethodDecl *clangDecl, bool isFromSystemModule,
@@ -3235,9 +3238,13 @@ ImportedType ClangImporter::Implementation::importAccessorParamsAndReturnType(
32353238
DeclContext *origDC = importDeclContextOf(property,
32363239
property->getDeclContext());
32373240
assert(origDC);
3241+
auto fieldType = isGetter ? clangDecl->getReturnType()
3242+
: clangDecl->getParamDecl(0)->getType();
32383243

32393244
// Import the property type, independent of what kind of accessor this is.
3240-
auto importedType = importPropertyType(property, isFromSystemModule);
3245+
ImportedType importedType = findOptionSetType(fieldType, *this);
3246+
if (!importedType)
3247+
importedType = importPropertyType(property, isFromSystemModule);
32413248
if (!importedType)
32423249
return {Type(), false};
32433250

test/Interop/Cxx/enum/Inputs/c-enums-NS_OPTIONS.h

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -82,6 +82,14 @@ struct HasNSOptionField {
8282
Bar bar;
8383
};
8484

85+
@interface HasNSOptionFieldObjC
86+
@property Bar bar;
87+
@end
88+
89+
@interface HasNSOptionFieldObjC2
90+
- (void)setBar:(Bar)bar;
91+
@end
92+
8593
Baz CFunctionReturningNSOption();
8694
void CFunctionTakingNSOption(Baz);
8795

test/Interop/Cxx/enum/c-enums-NS_OPTIONS.swift

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -25,3 +25,14 @@ import CenumsNSOptions
2525
// CHECK: struct HasNSOptionField {
2626
// CHECK: var bar: Bar
2727
// CHECK: }
28+
29+
// CHECK: class HasNSOptionFieldObjC {
30+
// CHECK-NEXT: var bar: Bar
31+
// CHECK-NEXT: class func bar() -> Bar
32+
// CHECK-NEXT: class func setBar(_ bar: Bar)
33+
// CHECK-NEXT: }
34+
35+
// CHECK: class HasNSOptionFieldObjC2 {
36+
// CHECK-NEXT: class func setBar(_ bar: Bar)
37+
// CHECK-NEXT: func setBar(_ bar: Bar)
38+
// CHECK-NEXT: }

0 commit comments

Comments
 (0)