mirror of
https://github.com/apple/swift.git
synced 2025-12-14 20:36:38 +01:00
[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.
This commit is contained in:
@@ -601,29 +601,6 @@ OptionalTypeKind importer::translateNullability(clang::NullabilityKind kind) {
|
|||||||
llvm_unreachable("Invalid NullabilityKind.");
|
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) {
|
bool importer::isRequiredInitializer(const clang::ObjCMethodDecl *method) {
|
||||||
// FIXME: No way to express this in Objective-C.
|
// FIXME: No way to express this in Objective-C.
|
||||||
return false;
|
return false;
|
||||||
|
|||||||
@@ -111,15 +111,6 @@ bool hasNativeSwiftDecl(const clang::Decl *decl);
|
|||||||
/// Translation API nullability from an API note into an optional kind.
|
/// Translation API nullability from an API note into an optional kind.
|
||||||
OptionalTypeKind translateNullability(clang::NullabilityKind 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
|
/// Determine whether the given method is a required initializer
|
||||||
/// of the given class.
|
/// of the given class.
|
||||||
bool isRequiredInitializer(const clang::ObjCMethodDecl *method);
|
bool isRequiredInitializer(const clang::ObjCMethodDecl *method);
|
||||||
|
|||||||
@@ -4415,7 +4415,7 @@ namespace {
|
|||||||
ConstructorDecl *importConstructor(const clang::ObjCMethodDecl *objcMethod,
|
ConstructorDecl *importConstructor(const clang::ObjCMethodDecl *objcMethod,
|
||||||
DeclContext *dc,
|
DeclContext *dc,
|
||||||
bool implicit,
|
bool implicit,
|
||||||
Optional<CtorInitializerKind> kindIn,
|
CtorInitializerKind kind,
|
||||||
bool required,
|
bool required,
|
||||||
ObjCSelector selector,
|
ObjCSelector selector,
|
||||||
ImportedName importedName,
|
ImportedName importedName,
|
||||||
@@ -6081,9 +6081,10 @@ ConstructorDecl *SwiftDeclConverter::importConstructor(
|
|||||||
}
|
}
|
||||||
|
|
||||||
bool redundant;
|
bool redundant;
|
||||||
auto result =
|
auto result = importConstructor(objcMethod, dc, implicit,
|
||||||
importConstructor(objcMethod, dc, implicit, kind, required, selector,
|
kind.getValueOr(importedName.getInitKind()),
|
||||||
importedName, params, variadic, redundant);
|
required, selector, importedName, params,
|
||||||
|
variadic, redundant);
|
||||||
|
|
||||||
// If this is a compatibility stub, mark it as such.
|
// If this is a compatibility stub, mark it as such.
|
||||||
if (result && correctSwiftName)
|
if (result && correctSwiftName)
|
||||||
@@ -6193,7 +6194,7 @@ bool SwiftDeclConverter::existingConstructorIsWorse(
|
|||||||
/// constructor declaration appropriately.
|
/// constructor declaration appropriately.
|
||||||
ConstructorDecl *SwiftDeclConverter::importConstructor(
|
ConstructorDecl *SwiftDeclConverter::importConstructor(
|
||||||
const clang::ObjCMethodDecl *objcMethod, DeclContext *dc, bool implicit,
|
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,
|
ImportedName importedName, ArrayRef<const clang::ParmVarDecl *> args,
|
||||||
bool variadic, bool &redundant) {
|
bool variadic, bool &redundant) {
|
||||||
redundant = false;
|
redundant = false;
|
||||||
@@ -6202,35 +6203,6 @@ ConstructorDecl *SwiftDeclConverter::importConstructor(
|
|||||||
auto ownerNominal = dc->getSelfNominalTypeDecl();
|
auto ownerNominal = dc->getSelfNominalTypeDecl();
|
||||||
assert(ownerNominal && "Method in non-type context?");
|
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.
|
// Import the type that this method will have.
|
||||||
Optional<ForeignErrorConvention> errorConvention;
|
Optional<ForeignErrorConvention> errorConvention;
|
||||||
ParameterList *bodyParams;
|
ParameterList *bodyParams;
|
||||||
@@ -7274,9 +7246,9 @@ void SwiftDeclConverter::importInheritedConstructors(
|
|||||||
};
|
};
|
||||||
|
|
||||||
// The kind of initializer to import. If this class has designated
|
// 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;
|
Optional<CtorInitializerKind> kind;
|
||||||
if (hasDesignatedInitializers(curObjCClass))
|
if (curObjCClass->hasDesignatedInitializers())
|
||||||
kind = CtorInitializerKind::Convenience;
|
kind = CtorInitializerKind::Convenience;
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -740,9 +740,7 @@ getFactoryAsInit(const clang::ObjCInterfaceDecl *classDecl,
|
|||||||
/// should be stripped from the first selector piece, e.g., "init"
|
/// should be stripped from the first selector piece, e.g., "init"
|
||||||
/// or the restated name of the class in a factory method.
|
/// or the restated name of the class in a factory method.
|
||||||
///
|
///
|
||||||
/// \param kind Will be set to the kind of initializer being
|
/// \param kind Will be set to the kind of initializer being imported.
|
||||||
/// imported. Note that this does not distinguish designated
|
|
||||||
/// vs. convenience; both will be classified as "designated".
|
|
||||||
static bool shouldImportAsInitializer(const clang::ObjCMethodDecl *method,
|
static bool shouldImportAsInitializer(const clang::ObjCMethodDecl *method,
|
||||||
ImportNameVersion version,
|
ImportNameVersion version,
|
||||||
unsigned &prefixLength,
|
unsigned &prefixLength,
|
||||||
@@ -750,7 +748,17 @@ static bool shouldImportAsInitializer(const clang::ObjCMethodDecl *method,
|
|||||||
/// Is this an initializer?
|
/// Is this an initializer?
|
||||||
if (isInitMethod(method)) {
|
if (isInitMethod(method)) {
|
||||||
prefixLength = 4;
|
prefixLength = 4;
|
||||||
|
|
||||||
|
// 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;
|
kind = CtorInitializerKind::Designated;
|
||||||
|
}
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user