Skip to content

Commit 42f72cb

Browse files
authored
[ClangImporter] Compute initializer kinds up front (#27870)
Previously we only did this for factory methods, but there's no reason why we can't do it for regular init methods too, and doing so simplifies the signature of SwiftDeclConverter::importConstructor. Also remove some indirection through helper functions in ClangAdapter. These were more useful back when Swift looked directly at API notes instead of relying on Clang turning them into attributes; now they're just an extra hop for no reason.
1 parent 220c477 commit 42f72cb

File tree

4 files changed

+20
-72
lines changed

4 files changed

+20
-72
lines changed

lib/ClangImporter/ClangAdapter.cpp

Lines changed: 0 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -601,29 +601,6 @@ OptionalTypeKind importer::translateNullability(clang::NullabilityKind kind) {
601601
llvm_unreachable("Invalid NullabilityKind.");
602602
}
603603

604-
bool importer::hasDesignatedInitializers(
605-
const clang::ObjCInterfaceDecl *classDecl) {
606-
if (classDecl->hasDesignatedInitializers())
607-
return true;
608-
609-
return false;
610-
}
611-
612-
bool importer::isDesignatedInitializer(
613-
const clang::ObjCInterfaceDecl *classDecl,
614-
const clang::ObjCMethodDecl *method) {
615-
// If the information is on the AST, use it.
616-
if (classDecl->hasDesignatedInitializers()) {
617-
auto *methodParent = method->getClassInterface();
618-
if (!methodParent ||
619-
methodParent->getCanonicalDecl() == classDecl->getCanonicalDecl()) {
620-
return method->hasAttr<clang::ObjCDesignatedInitializerAttr>();
621-
}
622-
}
623-
624-
return false;
625-
}
626-
627604
bool importer::isRequiredInitializer(const clang::ObjCMethodDecl *method) {
628605
// FIXME: No way to express this in Objective-C.
629606
return false;

lib/ClangImporter/ClangAdapter.h

Lines changed: 0 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -111,15 +111,6 @@ bool hasNativeSwiftDecl(const clang::Decl *decl);
111111
/// Translation API nullability from an API note into an optional kind.
112112
OptionalTypeKind translateNullability(clang::NullabilityKind kind);
113113

114-
/// Determine whether the given class has designated initializers,
115-
/// consulting
116-
bool hasDesignatedInitializers(const clang::ObjCInterfaceDecl *classDecl);
117-
118-
/// Determine whether the given method is a designated initializer
119-
/// of the given class.
120-
bool isDesignatedInitializer(const clang::ObjCInterfaceDecl *classDecl,
121-
const clang::ObjCMethodDecl *method);
122-
123114
/// Determine whether the given method is a required initializer
124115
/// of the given class.
125116
bool isRequiredInitializer(const clang::ObjCMethodDecl *method);

lib/ClangImporter/ImportDecl.cpp

Lines changed: 8 additions & 36 deletions
Original file line numberDiff line numberDiff line change
@@ -4415,7 +4415,7 @@ namespace {
44154415
ConstructorDecl *importConstructor(const clang::ObjCMethodDecl *objcMethod,
44164416
DeclContext *dc,
44174417
bool implicit,
4418-
Optional<CtorInitializerKind> kindIn,
4418+
CtorInitializerKind kind,
44194419
bool required,
44204420
ObjCSelector selector,
44214421
ImportedName importedName,
@@ -6081,9 +6081,10 @@ ConstructorDecl *SwiftDeclConverter::importConstructor(
60816081
}
60826082

60836083
bool redundant;
6084-
auto result =
6085-
importConstructor(objcMethod, dc, implicit, kind, required, selector,
6086-
importedName, params, variadic, redundant);
6084+
auto result = importConstructor(objcMethod, dc, implicit,
6085+
kind.getValueOr(importedName.getInitKind()),
6086+
required, selector, importedName, params,
6087+
variadic, redundant);
60876088

60886089
// If this is a compatibility stub, mark it as such.
60896090
if (result && correctSwiftName)
@@ -6193,7 +6194,7 @@ bool SwiftDeclConverter::existingConstructorIsWorse(
61936194
/// constructor declaration appropriately.
61946195
ConstructorDecl *SwiftDeclConverter::importConstructor(
61956196
const clang::ObjCMethodDecl *objcMethod, DeclContext *dc, bool implicit,
6196-
Optional<CtorInitializerKind> kindIn, bool required, ObjCSelector selector,
6197+
CtorInitializerKind kind, bool required, ObjCSelector selector,
61976198
ImportedName importedName, ArrayRef<const clang::ParmVarDecl *> args,
61986199
bool variadic, bool &redundant) {
61996200
redundant = false;
@@ -6202,35 +6203,6 @@ ConstructorDecl *SwiftDeclConverter::importConstructor(
62026203
auto ownerNominal = dc->getSelfNominalTypeDecl();
62036204
assert(ownerNominal && "Method in non-type context?");
62046205

6205-
// Find the interface, if we can.
6206-
const clang::ObjCInterfaceDecl *interface = nullptr;
6207-
if (auto classDecl = dyn_cast<ClassDecl>(ownerNominal)) {
6208-
interface =
6209-
dyn_cast_or_null<clang::ObjCInterfaceDecl>(classDecl->getClangDecl());
6210-
}
6211-
6212-
// If we weren't told what kind of initializer this should be,
6213-
// figure it out now.
6214-
CtorInitializerKind kind;
6215-
6216-
if (kindIn) {
6217-
kind = *kindIn;
6218-
6219-
// If we know this is a designated initializer, mark it as such.
6220-
if (interface && hasDesignatedInitializers(interface) &&
6221-
isDesignatedInitializer(interface, objcMethod))
6222-
kind = CtorInitializerKind::Designated;
6223-
} else {
6224-
// If the owning Objective-C class has designated initializers and this
6225-
// is not one of them, treat it as a convenience initializer.
6226-
if (interface && hasDesignatedInitializers(interface) &&
6227-
!isDesignatedInitializer(interface, objcMethod)) {
6228-
kind = CtorInitializerKind::Convenience;
6229-
} else {
6230-
kind = CtorInitializerKind::Designated;
6231-
}
6232-
}
6233-
62346206
// Import the type that this method will have.
62356207
Optional<ForeignErrorConvention> errorConvention;
62366208
ParameterList *bodyParams;
@@ -7274,9 +7246,9 @@ void SwiftDeclConverter::importInheritedConstructors(
72747246
};
72757247

72767248
// The kind of initializer to import. If this class has designated
7277-
// initializers, everything it imports is a convenience initializer.
7249+
// initializers, everything it inherits is a convenience initializer.
72787250
Optional<CtorInitializerKind> kind;
7279-
if (hasDesignatedInitializers(curObjCClass))
7251+
if (curObjCClass->hasDesignatedInitializers())
72807252
kind = CtorInitializerKind::Convenience;
72817253

72827254

lib/ClangImporter/ImportName.cpp

Lines changed: 12 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -740,17 +740,25 @@ getFactoryAsInit(const clang::ObjCInterfaceDecl *classDecl,
740740
/// should be stripped from the first selector piece, e.g., "init"
741741
/// or the restated name of the class in a factory method.
742742
///
743-
/// \param kind Will be set to the kind of initializer being
744-
/// imported. Note that this does not distinguish designated
745-
/// vs. convenience; both will be classified as "designated".
743+
/// \param kind Will be set to the kind of initializer being imported.
746744
static bool shouldImportAsInitializer(const clang::ObjCMethodDecl *method,
747745
ImportNameVersion version,
748746
unsigned &prefixLength,
749747
CtorInitializerKind &kind) {
750748
/// Is this an initializer?
751749
if (isInitMethod(method)) {
752750
prefixLength = 4;
753-
kind = CtorInitializerKind::Designated;
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+
754762
return true;
755763
}
756764

0 commit comments

Comments
 (0)