@@ -518,7 +518,7 @@ matchFactoryAsInitName(const clang::ObjCMethodDecl *method) {
518
518
// / Determine the kind of initializer the given factory method could be mapped
519
519
// / to, or produce \c None.
520
520
static Optional<CtorInitializerKind>
521
- determineCtorInitializerKind (const clang::ObjCMethodDecl *method) {
521
+ determineFactoryInitializerKind (const clang::ObjCMethodDecl *method) {
522
522
// Determine whether we have a suitable return type.
523
523
if (method->hasRelatedResultType ()) {
524
524
// When the factory method has an "instancetype" result type, we
@@ -708,7 +708,7 @@ findSwiftNameAttr(const clang::Decl *decl, ImportNameVersion version) {
708
708
}
709
709
710
710
// Special case: preventing a mapping to an initializer.
711
- if (matchFactoryAsInitName (method) && determineCtorInitializerKind (method))
711
+ if (matchFactoryAsInitName (method) && determineFactoryInitializerKind (method))
712
712
return attr;
713
713
714
714
return nullptr ;
@@ -733,32 +733,39 @@ getFactoryAsInit(const clang::ObjCInterfaceDecl *classDecl,
733
733
return FactoryAsInitKind::Infer;
734
734
}
735
735
736
+ Optional<CtorInitializerKind> determineCtorInitializerKind (
737
+ const clang::ObjCMethodDecl *method) {
738
+ const clang::ObjCInterfaceDecl *interface = method->getClassInterface ();
739
+
740
+ if (isInitMethod (method)) {
741
+ // If the owning Objective-C class has designated initializers and this
742
+ // is not one of them, treat it as a convenience initializer.
743
+ if (interface && interface->hasDesignatedInitializers () &&
744
+ !method->hasAttr <clang::ObjCDesignatedInitializerAttr>()) {
745
+ return CtorInitializerKind::Convenience;
746
+ }
747
+
748
+ return CtorInitializerKind::Designated;
749
+ }
750
+
751
+ if (method->isClassMethod ())
752
+ return determineFactoryInitializerKind (method);
753
+
754
+ return None;
755
+ }
756
+
736
757
// / Determine whether this Objective-C method should be imported as
737
758
// / an initializer.
738
759
// /
739
760
// / \param prefixLength Will be set to the length of the prefix that
740
761
// / should be stripped from the first selector piece, e.g., "init"
741
762
// / or the restated name of the class in a factory method.
742
- // /
743
- // / \param kind Will be set to the kind of initializer being imported.
744
763
static bool shouldImportAsInitializer (const clang::ObjCMethodDecl *method,
745
764
ImportNameVersion version,
746
- unsigned &prefixLength,
747
- CtorInitializerKind &kind) {
765
+ unsigned &prefixLength) {
748
766
// / Is this an initializer?
749
767
if (isInitMethod (method)) {
750
768
prefixLength = 4 ;
751
-
752
- // If the owning Objective-C class has designated initializers and this
753
- // is not one of them, treat it as a convenience initializer.
754
- const clang::ObjCInterfaceDecl *interface = method->getClassInterface ();
755
- if (interface && interface->hasDesignatedInitializers () &&
756
- !method->hasAttr <clang::ObjCDesignatedInitializerAttr>()) {
757
- kind = CtorInitializerKind::Convenience;
758
- } else {
759
- kind = CtorInitializerKind::Designated;
760
- }
761
-
762
769
return true ;
763
770
}
764
771
@@ -791,11 +798,8 @@ static bool shouldImportAsInitializer(const clang::ObjCMethodDecl *method,
791
798
return false ;
792
799
}
793
800
794
- // Determine what kind of initializer we're creating.
795
- if (auto initKind = determineCtorInitializerKind (method)) {
796
- kind = *initKind;
801
+ if (determineFactoryInitializerKind (method))
797
802
return true ;
798
- }
799
803
800
804
// Not imported as an initializer.
801
805
return false ;
@@ -1246,6 +1250,11 @@ ImportedName NameImporter::importNameImpl(const clang::NamedDecl *D,
1246
1250
if (overriddenNames.size () > 1 )
1247
1251
mergeOverriddenNames (swiftCtx, method, overriddenNames);
1248
1252
overriddenNames[0 ].second .effectiveContext = result.effectiveContext ;
1253
+
1254
+ // Compute the initializer kind from the derived method, though.
1255
+ if (auto kind = determineCtorInitializerKind (method))
1256
+ overriddenNames[0 ].second .info .initKind = *kind;
1257
+
1249
1258
return overriddenNames[0 ].second ;
1250
1259
}
1251
1260
} else if (auto property = dyn_cast<clang::ObjCPropertyDecl>(D)) {
@@ -1302,12 +1311,14 @@ ImportedName NameImporter::importNameImpl(const clang::NamedDecl *D,
1302
1311
if (method) {
1303
1312
unsigned initPrefixLength;
1304
1313
if (parsedName.BaseName == " init" && parsedName.IsFunctionName ) {
1305
- if (!shouldImportAsInitializer (method, version, initPrefixLength,
1306
- result.info .initKind )) {
1314
+ if (!shouldImportAsInitializer (method, version, initPrefixLength)) {
1307
1315
// We cannot import this as an initializer anyway.
1308
1316
return ImportedName ();
1309
1317
}
1310
1318
1319
+ if (auto kind = determineCtorInitializerKind (method))
1320
+ result.info .initKind = *kind;
1321
+
1311
1322
// If this swift_name attribute maps a factory method to an
1312
1323
// initializer and we were asked not to do so, ignore the
1313
1324
// custom name.
@@ -1479,14 +1490,18 @@ ImportedName NameImporter::importNameImpl(const clang::NamedDecl *D,
1479
1490
return ImportedName ();
1480
1491
1481
1492
isInitializer = shouldImportAsInitializer (objcMethod, version,
1482
- initializerPrefixLen,
1483
- result.info .initKind );
1484
-
1485
- // If we would import a factory method as an initializer but were
1486
- // asked not to, don't consider this as an initializer.
1487
- if (isInitializer && suppressFactoryMethodAsInit (objcMethod, version,
1488
- result.getInitKind ())) {
1489
- isInitializer = false ;
1493
+ initializerPrefixLen);
1494
+
1495
+ if (isInitializer) {
1496
+ if (auto kind = determineCtorInitializerKind (objcMethod))
1497
+ result.info .initKind = *kind;
1498
+
1499
+ // If we would import a factory method as an initializer but were
1500
+ // asked not to, don't consider this as an initializer.
1501
+ if (suppressFactoryMethodAsInit (objcMethod, version,
1502
+ result.getInitKind ())) {
1503
+ isInitializer = false ;
1504
+ }
1490
1505
}
1491
1506
1492
1507
if (isInitializer)
0 commit comments