From 0224b4e2fa58b09abf082491687944bf2ae4abc3 Mon Sep 17 00:00:00 2001 From: Jordan Rose Date: Thu, 24 Oct 2019 15:40:40 -0700 Subject: [PATCH] [ClangImporter] Compute initializer kinds up front 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. --- lib/ClangImporter/ClangAdapter.cpp | 23 ---------------- lib/ClangImporter/ClangAdapter.h | 9 ------ lib/ClangImporter/ImportDecl.cpp | 44 ++++++------------------------ lib/ClangImporter/ImportName.cpp | 16 ++++++++--- 4 files changed, 20 insertions(+), 72 deletions(-) diff --git a/lib/ClangImporter/ClangAdapter.cpp b/lib/ClangImporter/ClangAdapter.cpp index 6260ccdb911a8..582d244e865e2 100644 --- a/lib/ClangImporter/ClangAdapter.cpp +++ b/lib/ClangImporter/ClangAdapter.cpp @@ -601,29 +601,6 @@ OptionalTypeKind importer::translateNullability(clang::NullabilityKind kind) { llvm_unreachable("Invalid NullabilityKind."); } -bool importer::hasDesignatedInitializers( - const clang::ObjCInterfaceDecl *classDecl) { - if (classDecl->hasDesignatedInitializers()) - return true; - - return false; -} - -bool importer::isDesignatedInitializer( - const clang::ObjCInterfaceDecl *classDecl, - const clang::ObjCMethodDecl *method) { - // If the information is on the AST, use it. - if (classDecl->hasDesignatedInitializers()) { - auto *methodParent = method->getClassInterface(); - if (!methodParent || - methodParent->getCanonicalDecl() == classDecl->getCanonicalDecl()) { - return method->hasAttr(); - } - } - - return false; -} - bool importer::isRequiredInitializer(const clang::ObjCMethodDecl *method) { // FIXME: No way to express this in Objective-C. return false; diff --git a/lib/ClangImporter/ClangAdapter.h b/lib/ClangImporter/ClangAdapter.h index 84c35ad118961..47a20d202b89d 100644 --- a/lib/ClangImporter/ClangAdapter.h +++ b/lib/ClangImporter/ClangAdapter.h @@ -111,15 +111,6 @@ bool hasNativeSwiftDecl(const clang::Decl *decl); /// Translation API nullability from an API note into an optional kind. OptionalTypeKind translateNullability(clang::NullabilityKind kind); -/// Determine whether the given class has designated initializers, -/// consulting -bool hasDesignatedInitializers(const clang::ObjCInterfaceDecl *classDecl); - -/// Determine whether the given method is a designated initializer -/// of the given class. -bool isDesignatedInitializer(const clang::ObjCInterfaceDecl *classDecl, - const clang::ObjCMethodDecl *method); - /// Determine whether the given method is a required initializer /// of the given class. bool isRequiredInitializer(const clang::ObjCMethodDecl *method); diff --git a/lib/ClangImporter/ImportDecl.cpp b/lib/ClangImporter/ImportDecl.cpp index 524f7055b0a24..4791f3afec87c 100644 --- a/lib/ClangImporter/ImportDecl.cpp +++ b/lib/ClangImporter/ImportDecl.cpp @@ -4415,7 +4415,7 @@ namespace { ConstructorDecl *importConstructor(const clang::ObjCMethodDecl *objcMethod, DeclContext *dc, bool implicit, - Optional kindIn, + CtorInitializerKind kind, bool required, ObjCSelector selector, ImportedName importedName, @@ -6035,9 +6035,10 @@ ConstructorDecl *SwiftDeclConverter::importConstructor( } bool redundant; - auto result = - importConstructor(objcMethod, dc, implicit, kind, required, selector, - importedName, params, variadic, redundant); + auto result = importConstructor(objcMethod, dc, implicit, + kind.getValueOr(importedName.getInitKind()), + required, selector, importedName, params, + variadic, redundant); // If this is a compatibility stub, mark it as such. if (result && correctSwiftName) @@ -6147,7 +6148,7 @@ bool SwiftDeclConverter::existingConstructorIsWorse( /// constructor declaration appropriately. ConstructorDecl *SwiftDeclConverter::importConstructor( const clang::ObjCMethodDecl *objcMethod, DeclContext *dc, bool implicit, - Optional kindIn, bool required, ObjCSelector selector, + CtorInitializerKind kind, bool required, ObjCSelector selector, ImportedName importedName, ArrayRef args, bool variadic, bool &redundant) { redundant = false; @@ -6156,35 +6157,6 @@ ConstructorDecl *SwiftDeclConverter::importConstructor( auto ownerNominal = dc->getSelfNominalTypeDecl(); assert(ownerNominal && "Method in non-type context?"); - // Find the interface, if we can. - const clang::ObjCInterfaceDecl *interface = nullptr; - if (auto classDecl = dyn_cast(ownerNominal)) { - interface = - dyn_cast_or_null(classDecl->getClangDecl()); - } - - // If we weren't told what kind of initializer this should be, - // figure it out now. - CtorInitializerKind kind; - - if (kindIn) { - kind = *kindIn; - - // If we know this is a designated initializer, mark it as such. - if (interface && hasDesignatedInitializers(interface) && - isDesignatedInitializer(interface, objcMethod)) - kind = CtorInitializerKind::Designated; - } else { - // If the owning Objective-C class has designated initializers and this - // is not one of them, treat it as a convenience initializer. - if (interface && hasDesignatedInitializers(interface) && - !isDesignatedInitializer(interface, objcMethod)) { - kind = CtorInitializerKind::Convenience; - } else { - kind = CtorInitializerKind::Designated; - } - } - // Import the type that this method will have. Optional errorConvention; ParameterList *bodyParams; @@ -7228,9 +7200,9 @@ void SwiftDeclConverter::importInheritedConstructors( }; // The kind of initializer to import. If this class has designated - // initializers, everything it imports is a convenience initializer. + // initializers, everything it inherits is a convenience initializer. Optional kind; - if (hasDesignatedInitializers(curObjCClass)) + if (curObjCClass->hasDesignatedInitializers()) kind = CtorInitializerKind::Convenience; diff --git a/lib/ClangImporter/ImportName.cpp b/lib/ClangImporter/ImportName.cpp index dc1b4d9a9af74..c2494397d8a37 100644 --- a/lib/ClangImporter/ImportName.cpp +++ b/lib/ClangImporter/ImportName.cpp @@ -740,9 +740,7 @@ getFactoryAsInit(const clang::ObjCInterfaceDecl *classDecl, /// should be stripped from the first selector piece, e.g., "init" /// or the restated name of the class in a factory method. /// -/// \param kind Will be set to the kind of initializer being -/// imported. Note that this does not distinguish designated -/// vs. convenience; both will be classified as "designated". +/// \param kind Will be set to the kind of initializer being imported. static bool shouldImportAsInitializer(const clang::ObjCMethodDecl *method, ImportNameVersion version, unsigned &prefixLength, @@ -750,7 +748,17 @@ static bool shouldImportAsInitializer(const clang::ObjCMethodDecl *method, /// Is this an initializer? if (isInitMethod(method)) { prefixLength = 4; - kind = CtorInitializerKind::Designated; + + // If the owning Objective-C class has designated initializers and this + // is not one of them, treat it as a convenience initializer. + const clang::ObjCInterfaceDecl *interface = method->getClassInterface(); + if (interface && interface->hasDesignatedInitializers() && + !method->hasAttr()) { + kind = CtorInitializerKind::Convenience; + } else { + kind = CtorInitializerKind::Designated; + } + return true; }