@@ -112,7 +112,8 @@ class ObjCPrinter : private DeclVisitor<ObjCPrinter>,
112
112
friend ASTVisitor;
113
113
friend TypeVisitor;
114
114
115
- llvm::DenseMap<std::pair<Identifier, Identifier>, std::pair<StringRef, bool >>
115
+ using NameAndOptional = std::pair<StringRef, bool >;
116
+ llvm::DenseMap<std::pair<Identifier, Identifier>, NameAndOptional>
116
117
specialNames;
117
118
Identifier ID_CFTypeRef;
118
119
@@ -628,7 +629,9 @@ class ObjCPrinter : private DeclVisitor<ObjCPrinter>,
628
629
if (nominal == ctx.getArrayDecl () ||
629
630
nominal == ctx.getDictionaryDecl () ||
630
631
nominal == ctx.getSetDecl () ||
631
- nominal == ctx.getStringDecl ()) {
632
+ nominal == ctx.getStringDecl () ||
633
+ (!getKnownTypeInfo (nominal) && getObjCBridgedClass (nominal))) {
634
+ // We fast-path the most common cases in the condition above.
632
635
os << " , copy" ;
633
636
} else if (nominal == ctx.getUnmanagedDecl ()) {
634
637
os << " , unsafe_unretained" ;
@@ -798,25 +801,25 @@ class ObjCPrinter : private DeclVisitor<ObjCPrinter>,
798
801
return true ;
799
802
}
800
803
801
- // / If the nominal type is bridged to Objective-C (via a conformance
802
- // / to _ObjectiveCBridgeable), print the bridged type .
803
- bool printIfObjCBridgeable ( const NominalTypeDecl *nominal,
804
- ArrayRef<Type> typeArgs,
805
- Optional<OptionalTypeKind> optionalKind ) {
804
+ // / If \p nominal is bridged to an Objective-C class (via a conformance to
805
+ // / _ObjectiveCBridgeable), return that class .
806
+ // /
807
+ // / Otherwise returns null.
808
+ const ClassDecl * getObjCBridgedClass ( const NominalTypeDecl *nominal ) {
806
809
// Print imported bridgeable decls as their unbridged type.
807
810
if (nominal->hasClangNode ())
808
- return false ;
811
+ return nullptr ;
809
812
810
813
auto &ctx = nominal->getASTContext ();
811
814
812
815
// Dig out the ObjectiveCBridgeable protocol.
813
816
auto proto = ctx.getProtocol (KnownProtocolKind::ObjectiveCBridgeable);
814
- if (!proto) return false ;
817
+ if (!proto) return nullptr ;
815
818
816
819
// Determine whether this nominal type is _ObjectiveCBridgeable.
817
820
SmallVector<ProtocolConformance *, 2 > conformances;
818
821
if (!nominal->lookupConformance (&M, proto, conformances))
819
- return false ;
822
+ return nullptr ;
820
823
821
824
// Dig out the Objective-C type.
822
825
auto conformance = conformances.front ();
@@ -825,15 +828,20 @@ class ObjCPrinter : private DeclVisitor<ObjCPrinter>,
825
828
conformance,
826
829
ctx.Id_ObjectiveCType ,
827
830
nullptr );
828
- if (!objcType) return false ;
831
+ if (!objcType) return nullptr ;
829
832
830
833
// Dig out the Objective-C class.
831
- auto classDecl = objcType->getClassOrBoundGenericClass ();
832
- if (!classDecl) return false ;
834
+ return objcType->getClassOrBoundGenericClass ();
835
+ }
833
836
834
- // Determine the Objective-C name of the class.
835
- SmallString<32 > objcNameScratch;
836
- StringRef objcName = classDecl->getObjCRuntimeName (objcNameScratch);
837
+ // / If the nominal type is bridged to Objective-C (via a conformance
838
+ // / to _ObjectiveCBridgeable), print the bridged type.
839
+ void printObjCBridgeableType (const NominalTypeDecl *swiftNominal,
840
+ const ClassDecl *objcClass,
841
+ ArrayRef<Type> typeArgs,
842
+ Optional<OptionalTypeKind> optionalKind) {
843
+ auto &ctx = swiftNominal->getASTContext ();
844
+ assert (objcClass);
837
845
838
846
// Detect when the type arguments correspond to the unspecialized
839
847
// type, and clear them out. There is some type-specific hackery
@@ -843,15 +851,17 @@ class ObjCPrinter : private DeclVisitor<ObjCPrinter>,
843
851
// NSDictionary<NSObject *, id> --> NSDictionary
844
852
// NSSet<id> --> NSSet
845
853
if (!typeArgs.empty () &&
846
- (!hasGenericObjCType (classDecl ) ||
847
- (objcName == " NSArray " && typeArgs[0 ]->isAnyObject ()) ||
848
- (objcName == " NSDictionary " && isNSObject ( ctx, typeArgs[ 0 ] ) &&
849
- typeArgs[1 ]->isAnyObject ()) ||
850
- (objcName == " NSSet " && isNSObject (ctx, typeArgs[0 ]))))
854
+ (!hasGenericObjCType (objcClass ) ||
855
+ (swiftNominal == ctx. getArrayDecl () && typeArgs[0 ]->isAnyObject ()) ||
856
+ (swiftNominal == ctx. getDictionaryDecl ( ) &&
857
+ isNSObject (ctx, typeArgs[ 0 ]) && typeArgs[1 ]->isAnyObject ()) ||
858
+ (swiftNominal == ctx. getSetDecl () && isNSObject (ctx, typeArgs[0 ])))) {
851
859
typeArgs = {};
860
+ }
852
861
853
862
// Print the class type.
854
- os << objcName;
863
+ SmallString<32 > objcNameScratch;
864
+ os << objcClass->getObjCRuntimeName (objcNameScratch);
855
865
856
866
// Print the type arguments, if present.
857
867
if (!typeArgs.empty ()) {
@@ -866,17 +876,29 @@ class ObjCPrinter : private DeclVisitor<ObjCPrinter>,
866
876
867
877
os << " *" ;
868
878
printNullability (optionalKind);
869
- return true ;
870
879
}
871
880
872
- // / If "name" is one of the standard library types used to map in Clang
873
- // / primitives and basic types , print out the appropriate spelling and
874
- // / return true .
881
+ // / If the nominal type is bridged to Objective-C (via a conformance to
882
+ // / _ObjectiveCBridgeable) , print the bridged type. Otherwise, nothing is
883
+ // / printed .
875
884
// /
876
- // / This handles typealiases and structs provided by the standard library
877
- // / for interfacing with C and Objective-C.
878
- bool printIfKnownTypeName (Identifier moduleName, Identifier name,
879
- Optional<OptionalTypeKind> optionalKind) {
885
+ // / \returns true iff printed something.
886
+ bool printIfObjCBridgeable (const NominalTypeDecl *nominal,
887
+ ArrayRef<Type> typeArgs,
888
+ Optional<OptionalTypeKind> optionalKind) {
889
+ if (const ClassDecl *objcClass = getObjCBridgedClass (nominal)) {
890
+ printObjCBridgeableType (nominal, objcClass, typeArgs, optionalKind);
891
+ return true ;
892
+ }
893
+ return false ;
894
+ }
895
+
896
+ // / If \p typeDecl is one of the standard library types used to map in Clang
897
+ // / primitives and basic types, return the address of the info in
898
+ // / \c specialNames containing the Clang name and whether it can be optional.
899
+ // /
900
+ // / Returns null if the name is not one of these known types.
901
+ const NameAndOptional *getKnownTypeInfo (const TypeDecl *typeDecl) {
880
902
if (specialNames.empty ()) {
881
903
ASTContext &ctx = M.getASTContext ();
882
904
#define MAP (SWIFT_NAME, CLANG_REPR, NEEDS_NULLABILITY ) \
@@ -956,12 +978,27 @@ class ObjCPrinter : private DeclVisitor<ObjCPrinter>,
956
978
" SIMD elements is changed" );
957
979
}
958
980
981
+ Identifier moduleName = typeDecl->getModuleContext ()->getName ();
982
+ Identifier name = typeDecl->getName ();
959
983
auto iter = specialNames.find ({moduleName, name});
960
984
if (iter == specialNames.end ())
961
- return false ;
985
+ return nullptr ;
986
+ return &iter->second ;
987
+ }
962
988
963
- os << iter->second .first ;
964
- if (iter->second .second )
989
+ // / If \p typeDecl is one of the standard library types used to map in Clang
990
+ // / primitives and basic types, print out the appropriate spelling and
991
+ // / return true.
992
+ // /
993
+ // / This handles typealiases and structs provided by the standard library
994
+ // / for interfacing with C and Objective-C.
995
+ bool printIfKnownSimpleType (const TypeDecl *typeDecl,
996
+ Optional<OptionalTypeKind> optionalKind) {
997
+ auto *knownTypeInfo = getKnownTypeInfo (typeDecl);
998
+ if (!knownTypeInfo)
999
+ return false ;
1000
+ os << knownTypeInfo->first ;
1001
+ if (knownTypeInfo->second )
965
1002
printNullability (optionalKind);
966
1003
return true ;
967
1004
}
@@ -984,9 +1021,7 @@ class ObjCPrinter : private DeclVisitor<ObjCPrinter>,
984
1021
void visitNameAliasType (NameAliasType *aliasTy,
985
1022
Optional<OptionalTypeKind> optionalKind) {
986
1023
const TypeAliasDecl *alias = aliasTy->getDecl ();
987
- if (printIfKnownTypeName (alias->getModuleContext ()->getName (),
988
- alias->getName (),
989
- optionalKind))
1024
+ if (printIfKnownSimpleType (alias, optionalKind))
990
1025
return ;
991
1026
992
1027
if (alias->hasClangNode ()) {
@@ -1032,8 +1067,7 @@ class ObjCPrinter : private DeclVisitor<ObjCPrinter>,
1032
1067
const StructDecl *SD = ST->getStructOrBoundGenericStruct ();
1033
1068
1034
1069
// Handle known type names.
1035
- if (printIfKnownTypeName (SD->getModuleContext ()->getName (), SD->getName (),
1036
- optionalKind))
1070
+ if (printIfKnownSimpleType (SD, optionalKind))
1037
1071
return ;
1038
1072
1039
1073
// Handle bridged types.
0 commit comments