Skip to content

[ClangImporter] Compute initializer kinds up front #27870

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
23 changes: 0 additions & 23 deletions lib/ClangImporter/ClangAdapter.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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<clang::ObjCDesignatedInitializerAttr>();
}
}

return false;
}

bool importer::isRequiredInitializer(const clang::ObjCMethodDecl *method) {
// FIXME: No way to express this in Objective-C.
return false;
Expand Down
9 changes: 0 additions & 9 deletions lib/ClangImporter/ClangAdapter.h
Original file line number Diff line number Diff line change
Expand Up @@ -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);
Expand Down
44 changes: 8 additions & 36 deletions lib/ClangImporter/ImportDecl.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -4415,7 +4415,7 @@ namespace {
ConstructorDecl *importConstructor(const clang::ObjCMethodDecl *objcMethod,
DeclContext *dc,
bool implicit,
Optional<CtorInitializerKind> kindIn,
CtorInitializerKind kind,
bool required,
ObjCSelector selector,
ImportedName importedName,
Expand Down Expand Up @@ -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)
Expand Down Expand Up @@ -6147,7 +6148,7 @@ bool SwiftDeclConverter::existingConstructorIsWorse(
/// constructor declaration appropriately.
ConstructorDecl *SwiftDeclConverter::importConstructor(
const clang::ObjCMethodDecl *objcMethod, DeclContext *dc, bool implicit,
Optional<CtorInitializerKind> kindIn, bool required, ObjCSelector selector,
CtorInitializerKind kind, bool required, ObjCSelector selector,
ImportedName importedName, ArrayRef<const clang::ParmVarDecl *> args,
bool variadic, bool &redundant) {
redundant = false;
Expand All @@ -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<ClassDecl>(ownerNominal)) {
interface =
dyn_cast_or_null<clang::ObjCInterfaceDecl>(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<ForeignErrorConvention> errorConvention;
ParameterList *bodyParams;
Expand Down Expand Up @@ -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<CtorInitializerKind> kind;
if (hasDesignatedInitializers(curObjCClass))
if (curObjCClass->hasDesignatedInitializers())
kind = CtorInitializerKind::Convenience;


Expand Down
16 changes: 12 additions & 4 deletions lib/ClangImporter/ImportName.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -740,17 +740,25 @@ 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,
CtorInitializerKind &kind) {
/// 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<clang::ObjCDesignatedInitializerAttr>()) {
kind = CtorInitializerKind::Convenience;
} else {
kind = CtorInitializerKind::Designated;
}

return true;
}

Expand Down