Skip to content

Commit 66a7ebe

Browse files
authored
Merge pull request #67036 from plotfi/ns-options-type-import-inside-objc-interface
[cxx-interop] Import ObjCPropertyDecl of type NS_OPTIONS fields as struct type
2 parents 422fdaa + 7cef628 commit 66a7ebe

File tree

4 files changed

+48
-17
lines changed

4 files changed

+48
-17
lines changed

lib/ClangImporter/ImportDecl.cpp

+31-17
Original file line numberDiff line numberDiff line change
@@ -816,6 +816,31 @@ static bool isPrintLikeMethod(DeclName name, const DeclContext *dc) {
816816
using MirroredMethodEntry =
817817
std::tuple<const clang::ObjCMethodDecl*, ProtocolDecl*, bool /*isAsync*/>;
818818

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

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

36843694
if (!importedType)
36853695
importedType =
@@ -5201,7 +5211,11 @@ namespace {
52015211
}
52025212
}
52035213

5204-
auto importedType = Impl.importPropertyType(decl, isInSystemModule(dc));
5214+
auto fieldType = decl->getType();
5215+
ImportedType importedType = tryImportOptionsTypeForField(fieldType, Impl);
5216+
5217+
if (!importedType)
5218+
importedType = Impl.importPropertyType(decl, isInSystemModule(dc));
52055219
if (!importedType) {
52065220
Impl.addImportDiagnostic(
52075221
decl, Diagnostic(diag::objc_property_not_imported, decl),

lib/ClangImporter/ImportType.cpp

+7
Original file line numberDiff line numberDiff line change
@@ -3224,6 +3224,9 @@ ImportedType ClangImporter::Implementation::importMethodParamsAndReturnType(
32243224
importedType.isImplicitlyUnwrapped()};
32253225
}
32263226

3227+
ImportedType tryImportOptionsTypeForField(const clang::QualType type,
3228+
ClangImporter::Implementation &Impl);
3229+
32273230
ImportedType ClangImporter::Implementation::importAccessorParamsAndReturnType(
32283231
const DeclContext *dc, const clang::ObjCPropertyDecl *property,
32293232
const clang::ObjCMethodDecl *clangDecl, bool isFromSystemModule,
@@ -3247,9 +3250,13 @@ ImportedType ClangImporter::Implementation::importAccessorParamsAndReturnType(
32473250
DeclContext *origDC = importDeclContextOf(property,
32483251
property->getDeclContext());
32493252
assert(origDC);
3253+
auto fieldType = isGetter ? clangDecl->getReturnType() : clangDecl->getParamDecl(0)->getType();
3254+
ImportedType importedNSOptionsType = tryImportOptionsTypeForField(fieldType, *this);
32503255

32513256
// Import the property type, independent of what kind of accessor this is.
32523257
auto importedType = importPropertyType(property, isFromSystemModule);
3258+
if (importedNSOptionsType)
3259+
importedType = importedNSOptionsType;
32533260
if (!importedType)
32543261
return {Type(), false};
32553262

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

+4
Original file line numberDiff line numberDiff line change
@@ -82,6 +82,10 @@ struct HasNSOptionField {
8282
Bar bar;
8383
};
8484

85+
@interface HasNSOptionFieldObjC
86+
@property Bar bar;
87+
@end
88+
8589
Baz CFunctionReturningNSOption();
8690
void CFunctionTakingNSOption(Baz);
8791

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

+6
Original file line numberDiff line numberDiff line change
@@ -25,3 +25,9 @@ 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: }

0 commit comments

Comments
 (0)