mirror of
https://github.com/apple/swift.git
synced 2025-12-21 12:14:44 +01:00
Start emitting stubs for unimplemented designated initializers of the superclass.
When a subclass does not implement a designated initializer of its superclass, introduce a stub initializer that simply traps. Such stubs cannot be invoked directly using Swift syntax, but can be invoked through the Objective-C runtime and from Objective-C code. Catch such errors rather than allowing them to violate the memory safety of the language. Note that we're currently using cond_fail to trap; this will be improved in the future, Swift SVN r14839
This commit is contained in:
@@ -279,8 +279,17 @@ class alignas(8) Decl {
|
||||
|
||||
/// Whether this is a complete object initializer.
|
||||
unsigned CompleteObjectInit : 1;
|
||||
|
||||
/// Whether this initializer is a stub placed into a subclass to
|
||||
/// catch invalid delegations to a subobject initializer not
|
||||
/// overridden by the subclass. A stub will always trap at runtime.
|
||||
///
|
||||
/// Initializer stubs can be invoked from Objective-C or through
|
||||
/// the Objective-C runtime; there is no way to directly express
|
||||
/// an object construction that will invoke a stub.
|
||||
unsigned HasStubImplementation : 1;
|
||||
};
|
||||
enum { NumConstructorDeclBits = NumAbstractFunctionDeclBits + 5 };
|
||||
enum { NumConstructorDeclBits = NumAbstractFunctionDeclBits + 6 };
|
||||
static_assert(NumConstructorDeclBits <= 32, "fits in an unsigned");
|
||||
|
||||
class TypeDeclBitfields {
|
||||
@@ -3742,6 +3751,17 @@ public:
|
||||
return !isCompleteObjectInit();
|
||||
}
|
||||
|
||||
/// Whether the implementation of this method is a stub that traps at runtime.
|
||||
bool hasStubImplementation() const {
|
||||
return ConstructorDeclBits.HasStubImplementation;
|
||||
}
|
||||
|
||||
/// Set whether the implementation of this method is a stub that
|
||||
/// traps at runtime.
|
||||
void setStubImplementation(bool stub) {
|
||||
ConstructorDeclBits.HasStubImplementation = stub;
|
||||
}
|
||||
|
||||
ConstructorDecl *getOverriddenDecl() const { return OverriddenDecl; }
|
||||
void setOverriddenDecl(ConstructorDecl *over) { OverriddenDecl = over; }
|
||||
|
||||
|
||||
@@ -464,6 +464,16 @@ public:
|
||||
/// \brief Retrieve the type without any default arguments.
|
||||
Type getWithoutDefaultArgs(const ASTContext &Context);
|
||||
|
||||
/// Replace the result type of the given function type with a new
|
||||
/// result type.
|
||||
///
|
||||
/// \param newResultType The new result type.
|
||||
///
|
||||
/// \param uncurryLevel The number of uncurry levels to apply before
|
||||
/// replacing the type. With uncurry level == 0, this simply
|
||||
/// replaces the current type with the new result type.
|
||||
Type replaceResultType(Type newResultType, unsigned uncurryLevel = 1);
|
||||
|
||||
/// getRValueType - For an @lvalue type, retrieves the underlying object type.
|
||||
/// Otherwise, returns the type itself.
|
||||
Type getRValueType();
|
||||
|
||||
@@ -1155,6 +1155,10 @@ bool ClassDecl::inheritsSuperclassInitializers(LazyResolver *resolver) {
|
||||
if (!ctor->hasType())
|
||||
resolver->resolveDeclSignature(ctor);
|
||||
|
||||
// Ignore any stub implementations.
|
||||
if (ctor->hasStubImplementation())
|
||||
continue;
|
||||
|
||||
if (auto overridden = ctor->getOverriddenDecl()) {
|
||||
if (overridden->isSubobjectInit())
|
||||
overriddenInits.insert(overridden);
|
||||
@@ -1983,6 +1987,7 @@ ConstructorDecl::ConstructorDecl(Identifier NameHack, SourceLoc ConstructorLoc,
|
||||
ConstructorDeclBits.ComputedBodyInitKind = 0;
|
||||
ConstructorDeclBits.Required = 0;
|
||||
ConstructorDeclBits.CompleteObjectInit = 0;
|
||||
ConstructorDeclBits.HasStubImplementation = 0;
|
||||
}
|
||||
|
||||
void ConstructorDecl::setArgParams(Pattern *selfPattern, Pattern *argParams) {
|
||||
|
||||
@@ -885,10 +885,9 @@ bool DeclContext::lookupQualified(Type type,
|
||||
// Allow filtering of the visible declarations based on
|
||||
bool onlyCompleteObjectInits = false;
|
||||
auto isAcceptableDecl = [&](NominalTypeDecl *current, Decl *decl) -> bool {
|
||||
// Filter out subobject initializers, if requestred.
|
||||
// Filter out subobject initializers, if requested.
|
||||
if (onlyCompleteObjectInits) {
|
||||
// Allow any initializer in an Objective-C class that neither declares nor
|
||||
// inherits designated initializers.
|
||||
// Allow any initializer in an Objective-C class.
|
||||
bool assumeCompleteObjectInit = false;
|
||||
if (current->hasClangNode()) {
|
||||
if (auto objcClass
|
||||
@@ -906,6 +905,12 @@ bool DeclContext::lookupQualified(Type type,
|
||||
}
|
||||
}
|
||||
|
||||
// Ignore stub implementations.
|
||||
if (auto ctor = dyn_cast<ConstructorDecl>(decl)) {
|
||||
if (ctor->hasStubImplementation())
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
};
|
||||
|
||||
|
||||
@@ -491,6 +491,32 @@ Type TypeBase::getWithoutDefaultArgs(const ASTContext &Context) {
|
||||
/*defaultArgs=*/true);
|
||||
}
|
||||
|
||||
Type TypeBase::replaceResultType(Type newResultType, unsigned uncurryLevel) {
|
||||
if (uncurryLevel == 0)
|
||||
return newResultType;
|
||||
|
||||
// Determine the input and result types of this function.
|
||||
auto fnType = this->castTo<AnyFunctionType>();
|
||||
Type inputType = fnType->getInput();
|
||||
Type resultType = fnType->getResult()->replaceResultType(newResultType,
|
||||
uncurryLevel - 1);
|
||||
|
||||
// Produce the resulting function type.
|
||||
if (auto genericFn = dyn_cast<GenericFunctionType>(fnType)) {
|
||||
return GenericFunctionType::get(genericFn->getGenericSignature(),
|
||||
inputType, resultType,
|
||||
fnType->getExtInfo());
|
||||
}
|
||||
|
||||
if (auto polyFn = dyn_cast<PolymorphicFunctionType>(fnType)) {
|
||||
return PolymorphicFunctionType::get(inputType, resultType,
|
||||
&polyFn->getGenericParams(),
|
||||
fnType->getExtInfo());
|
||||
}
|
||||
|
||||
return FunctionType::get(inputType, resultType, fnType->getExtInfo());
|
||||
}
|
||||
|
||||
/// Retrieve the object type for a 'self' parameter, digging into one-element
|
||||
/// tuples, lvalue types, and metatypes.
|
||||
Type TypeBase::getRValueInstanceType() {
|
||||
|
||||
@@ -2717,11 +2717,15 @@ void SILGenFunction::emitClassConstructorInitializer(ConstructorDecl *ctor) {
|
||||
// FIXME: Hack until all delegation is dispatched.
|
||||
IsCompleteObjectInit = ctor->isCompleteObjectInit();
|
||||
|
||||
assert(ctor->getBody() && "Class constructor without a body?");
|
||||
assert((ctor->getBody() || ctor->hasStubImplementation()) &&
|
||||
"Class constructor without a body?");
|
||||
|
||||
// True if this constructor delegates to a peer constructor with self.init().
|
||||
bool isDelegating = ctor->getDelegatingOrChainedInitKind(nullptr) ==
|
||||
bool isDelegating = false;
|
||||
if (!ctor->hasStubImplementation()) {
|
||||
isDelegating = ctor->getDelegatingOrChainedInitKind(nullptr) ==
|
||||
ConstructorDecl::BodyInitKind::Delegating;
|
||||
}
|
||||
|
||||
// FIXME: The (potentially partially initialized) value here would need to be
|
||||
// cleaned up on a constructor failure unwinding.
|
||||
@@ -2738,7 +2742,8 @@ void SILGenFunction::emitClassConstructorInitializer(ConstructorDecl *ctor) {
|
||||
auto selfTypeContext = ctor->getDeclContext()->getDeclaredTypeInContext();
|
||||
auto selfClassDecl =
|
||||
cast<ClassDecl>(selfTypeContext->getNominalOrBoundGenericNominal());
|
||||
bool NeedsBoxForSelf = isDelegating || selfClassDecl->hasSuperclass();
|
||||
bool NeedsBoxForSelf = isDelegating ||
|
||||
(selfClassDecl->hasSuperclass() && !ctor->hasStubImplementation());
|
||||
|
||||
if (NeedsBoxForSelf)
|
||||
emitLocalVariable(selfDecl);
|
||||
@@ -2754,16 +2759,18 @@ void SILGenFunction::emitClassConstructorInitializer(ConstructorDecl *ctor) {
|
||||
if (!NeedsBoxForSelf)
|
||||
B.createDebugValue(selfDecl, selfArg);
|
||||
|
||||
// If needed, mark 'self' as uninitialized so that DI knows to enforce its DI
|
||||
// properties on stored properties.
|
||||
bool usesObjCAllocator = Lowering::usesObjCAllocator(selfClassDecl);
|
||||
if (!ctor->hasStubImplementation()) {
|
||||
// If needed, mark 'self' as uninitialized so that DI knows to
|
||||
// enforce its DI properties on stored properties.
|
||||
MarkUninitializedInst::Kind MUKind;
|
||||
|
||||
bool usesObjCAllocator = Lowering::usesObjCAllocator(selfClassDecl);
|
||||
if (isDelegating)
|
||||
MUKind = MarkUninitializedInst::DelegatingSelf;
|
||||
else if (selfClassDecl->requiresStoredPropertyInits() && usesObjCAllocator) {
|
||||
// Stored properties will be initialized in a separate .cxx_construct method
|
||||
// called by the Objective-C runtime.
|
||||
else if (selfClassDecl->requiresStoredPropertyInits() &&
|
||||
usesObjCAllocator) {
|
||||
// Stored properties will be initialized in a separate
|
||||
// .cxx_construct method called by the Objective-C runtime.
|
||||
assert(selfClassDecl->hasSuperclass() &&
|
||||
"Cannot use ObjC allocation without a superclass");
|
||||
MUKind = MarkUninitializedInst::DerivedSelfOnly;
|
||||
@@ -2773,7 +2780,8 @@ void SILGenFunction::emitClassConstructorInitializer(ConstructorDecl *ctor) {
|
||||
MUKind = MarkUninitializedInst::RootSelf;
|
||||
|
||||
selfArg = B.createMarkUninitialized(selfDecl, selfArg, MUKind);
|
||||
assert(selfTy.hasReferenceSemantics() && "can't emit a value type ctor here");
|
||||
assert(selfTy.hasReferenceSemantics() &&
|
||||
"can't emit a value type ctor here");
|
||||
|
||||
if (NeedsBoxForSelf) {
|
||||
SILLocation prologueLoc = RegularLocation(ctor);
|
||||
@@ -2782,6 +2790,7 @@ void SILGenFunction::emitClassConstructorInitializer(ConstructorDecl *ctor) {
|
||||
} else {
|
||||
VarLocs[selfDecl] = VarLoc::getConstant(selfArg);
|
||||
}
|
||||
}
|
||||
|
||||
// Prepare the end of initializer location.
|
||||
SILLocation endOfInitLoc = RegularLocation(ctor);
|
||||
@@ -2795,7 +2804,10 @@ void SILGenFunction::emitClassConstructorInitializer(ConstructorDecl *ctor) {
|
||||
if (isDelegating) {
|
||||
// A delegating initializer does not initialize instance
|
||||
// variables.
|
||||
} else if (selfClassDecl->requiresStoredPropertyInits() && usesObjCAllocator) {
|
||||
} else if (ctor->hasStubImplementation()) {
|
||||
// Nor does a stub implementation.
|
||||
} else if (selfClassDecl->requiresStoredPropertyInits() &&
|
||||
usesObjCAllocator) {
|
||||
// When the class requires all stored properties to have initial
|
||||
// values and we're using Objective-C's allocation, stored
|
||||
// properties are initialized via the .cxx_construct method, which
|
||||
@@ -2808,7 +2820,14 @@ void SILGenFunction::emitClassConstructorInitializer(ConstructorDecl *ctor) {
|
||||
}
|
||||
|
||||
// Emit the constructor body.
|
||||
if (ctor->hasStubImplementation()) {
|
||||
auto int1Ty = SILType::getBuiltinIntegerType(1, getASTContext());
|
||||
auto *trueInst = B.createIntegerLiteral(endOfInitLoc, int1Ty, 1);
|
||||
auto *failInst = B.createCondFail(endOfInitLoc, trueInst);
|
||||
(void)failInst;
|
||||
} else {
|
||||
visit(ctor->getBody());
|
||||
}
|
||||
|
||||
// Return 'self' in the epilog.
|
||||
Optional<SILValue> maybeReturnValue;
|
||||
|
||||
@@ -1998,6 +1998,78 @@ public:
|
||||
}
|
||||
}
|
||||
|
||||
/// Create a new initializer that overrides the given subobject
|
||||
/// initializer.
|
||||
///
|
||||
/// \param classDecl The subclass in which the new initializer will
|
||||
/// be declared.
|
||||
///
|
||||
/// \param superclassCtor The superclass initializer for which this
|
||||
/// routine will create an override.
|
||||
///
|
||||
/// \returns the newly-created initializer that overrides \p
|
||||
/// superclassCtor.
|
||||
ConstructorDecl *
|
||||
createSubobjectInitOverride(ClassDecl *classDecl,
|
||||
ConstructorDecl *superclassCtor) {
|
||||
// Determine the initializer parameters.
|
||||
Type superInitType = superclassCtor->getInitializerInterfaceType();
|
||||
if (superInitType->is<GenericFunctionType>() ||
|
||||
classDecl->getGenericParamsOfContext()) {
|
||||
// FIXME: Handle generic initializers as well.
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
auto &ctx = TC.Context;
|
||||
|
||||
// Create the 'self' declaration and patterns.
|
||||
auto *selfDecl = new (ctx) VarDecl(/*static*/ false, /*IsLet*/ true,
|
||||
SourceLoc(), ctx.Id_self,
|
||||
Type(), classDecl);
|
||||
selfDecl->setImplicit();
|
||||
Pattern *selfArgPattern
|
||||
= new (ctx) NamedPattern(selfDecl, /*Implicit=*/true);
|
||||
selfArgPattern = new (ctx) TypedPattern(selfArgPattern, TypeLoc());
|
||||
Pattern *selfBodyPattern
|
||||
= new (ctx) NamedPattern(selfDecl, /*Implicit=*/true);
|
||||
selfBodyPattern = new (ctx) TypedPattern(selfBodyPattern, TypeLoc());
|
||||
|
||||
// Create the initializer parameter patterns.
|
||||
Pattern *argParamPatterns
|
||||
= superclassCtor->getArgParamPatterns()[1]->clone(ctx,/*Implicit=*/true);
|
||||
Pattern *bodyParamPatterns
|
||||
= superclassCtor->getBodyParamPatterns()[1]->clone(ctx,/*Implicit=*/true);
|
||||
|
||||
// Create the initializer declaration.
|
||||
auto ctor = new (ctx) ConstructorDecl(ctx.Id_init, SourceLoc(),
|
||||
selfArgPattern, argParamPatterns,
|
||||
selfBodyPattern, bodyParamPatterns,
|
||||
nullptr, classDecl);
|
||||
ctor->setImplicit();
|
||||
if (superclassCtor->hasSelectorStyleSignature())
|
||||
ctor->setHasSelectorStyleSignature();
|
||||
|
||||
// Configure 'self'.
|
||||
GenericParamList *outerGenericParams = nullptr;
|
||||
Type selfType = configureImplicitSelf(ctor, outerGenericParams);
|
||||
selfArgPattern->setType(selfType);
|
||||
selfBodyPattern->setType(selfType);
|
||||
cast<TypedPattern>(selfArgPattern)->getSubPattern()->setType(selfType);
|
||||
cast<TypedPattern>(selfBodyPattern)->getSubPattern()->setType(selfType);
|
||||
|
||||
// Set the type of the initializer.
|
||||
configureConstructorType(ctor, outerGenericParams, selfType,
|
||||
argParamPatterns->getType());
|
||||
if (superclassCtor->isObjC())
|
||||
ctor->setIsObjC(true);
|
||||
checkOverrides(ctor);
|
||||
|
||||
// Mark this as a stub implementation.
|
||||
ctor->setStubImplementation(true);
|
||||
|
||||
return ctor;
|
||||
}
|
||||
|
||||
void visitClassDecl(ClassDecl *CD) {
|
||||
if (!IsSecondPass) {
|
||||
TC.validateDecl(CD);
|
||||
@@ -2025,10 +2097,10 @@ public:
|
||||
TC.addImplicitConstructors(CD);
|
||||
TC.addImplicitDestructor(CD);
|
||||
|
||||
// Check whether the superclass has any abstract initializers and whether
|
||||
// they have been implemented.
|
||||
// Check for inconsistencies between the initializers of our
|
||||
// superclass and our own initializers.
|
||||
if (auto superclassTy = CD->getSuperclass()) {
|
||||
// Collect the set of constructors we override in the base class.
|
||||
// Collect the set of initializers we override in superclass.
|
||||
llvm::SmallPtrSet<ConstructorDecl *, 4> overriddenCtors;
|
||||
for (auto member : TC.lookupConstructors(CD->getDeclaredTypeInContext(),
|
||||
CD)) {
|
||||
@@ -2037,13 +2109,19 @@ public:
|
||||
overriddenCtors.insert(overridden);
|
||||
}
|
||||
|
||||
// Diagnose any abstract constructors from our superclass that have
|
||||
// not been overridden or inherited.
|
||||
// Look for any required constructors or subobject initializers in the
|
||||
// subclass that have not been overridden or otherwise provided.
|
||||
bool diagnosed = false;
|
||||
llvm::SmallVector<ConstructorDecl *, 2> synthesizedCtors;
|
||||
for (auto superclassMember : TC.lookupConstructors(superclassTy, CD)) {
|
||||
// We only care about abstract constructors.
|
||||
// We only care about required or subobject initializers.
|
||||
auto superclassCtor = cast<ConstructorDecl>(superclassMember);
|
||||
if (!superclassCtor->isRequired())
|
||||
if (!superclassCtor->isRequired() &&
|
||||
!superclassCtor->isSubobjectInit())
|
||||
continue;
|
||||
|
||||
// Skip invalid superclass initializers.
|
||||
if (superclassCtor->isInvalid())
|
||||
continue;
|
||||
|
||||
// If we have an override for this constructor, it's okay.
|
||||
@@ -2053,9 +2131,13 @@ public:
|
||||
// If the superclass constructor is a complete object initializer
|
||||
// that is inherited into the current class, it's okay.
|
||||
if (superclassCtor->isCompleteObjectInit() &&
|
||||
CD->inheritsSuperclassInitializers(&TC))
|
||||
CD->inheritsSuperclassInitializers(&TC)) {
|
||||
assert(superclassCtor->isRequired());
|
||||
continue;
|
||||
}
|
||||
|
||||
// Diagnose a missing override of a required initializer.
|
||||
if (superclassCtor->isRequired()) {
|
||||
// Complain that we don't have an overriding constructor.
|
||||
if (!diagnosed) {
|
||||
TC.diagnose(CD, diag::abstract_incomplete_implementation,
|
||||
@@ -2065,8 +2147,37 @@ public:
|
||||
|
||||
// FIXME: Using the type here is awful. We want to use the selector
|
||||
// name and provide a nice Fix-It with that declaration.
|
||||
TC.diagnose(superclassCtor, diag::abstract_initializer_not_overridden,
|
||||
TC.diagnose(superclassCtor,
|
||||
diag::abstract_initializer_not_overridden,
|
||||
superclassCtor->getArgumentType());
|
||||
continue;
|
||||
}
|
||||
|
||||
// A subobject initializer has not been overridden.
|
||||
|
||||
// Skip this subobject initializer if it's in an extension.
|
||||
// FIXME: We shouldn't allow this.
|
||||
if (isa<ExtensionDecl>(superclassCtor->getDeclContext()))
|
||||
continue;
|
||||
|
||||
// Create an override for it.
|
||||
if (auto ctor = createSubobjectInitOverride(CD, superclassCtor)) {
|
||||
assert(ctor->getOverriddenDecl() == superclassCtor &&
|
||||
"Not an override?");
|
||||
synthesizedCtors.push_back(ctor);
|
||||
}
|
||||
}
|
||||
|
||||
// If we synthesized any initializers, add them.
|
||||
if (!synthesizedCtors.empty()) {
|
||||
auto members = CD->getMembers();
|
||||
unsigned numMembers = members.size();
|
||||
MutableArrayRef<Decl *> newMembers
|
||||
= TC.Context.Allocate<Decl*>(numMembers + synthesizedCtors.size());
|
||||
std::copy(members.begin(), members.end(), newMembers.begin());
|
||||
std::copy(synthesizedCtors.begin(), synthesizedCtors.end(),
|
||||
newMembers.begin() + numMembers);
|
||||
CD->setMembers(newMembers, CD->getBraces());
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -2633,6 +2744,8 @@ public:
|
||||
return type;
|
||||
});
|
||||
}
|
||||
} else if (isa<ConstructorDecl>(decl)) {
|
||||
type = type->replaceResultType(subclass, /*uncurryLevel=*/2);
|
||||
}
|
||||
|
||||
return type;
|
||||
@@ -2796,7 +2909,7 @@ public:
|
||||
|
||||
// Check whether the types are identical.
|
||||
// FIXME: It's wrong to use the uncurried types here for methods.
|
||||
auto parentDeclTy = adjustSuperclassMemberDeclType(parentDecl,superclass);
|
||||
auto parentDeclTy = adjustSuperclassMemberDeclType(parentDecl,owningTy);
|
||||
auto uncurriedParentDeclTy = parentDeclTy;
|
||||
if (method) {
|
||||
uncurriedParentDeclTy = parentDeclTy->castTo<AnyFunctionType>()
|
||||
@@ -3171,6 +3284,37 @@ public:
|
||||
// their enclosing declaration.
|
||||
}
|
||||
|
||||
/// Compute the allocating and initializing constructor types for
|
||||
/// the given constructor.
|
||||
void configureConstructorType(ConstructorDecl *ctor,
|
||||
GenericParamList *outerGenericParams,
|
||||
Type selfType,
|
||||
Type argType) {
|
||||
Type fnType;
|
||||
Type allocFnType;
|
||||
Type initFnType;
|
||||
Type resultType = selfType->getInOutObjectType();
|
||||
|
||||
if (GenericParamList *innerGenericParams = ctor->getGenericParams()) {
|
||||
innerGenericParams->setOuterParameters(outerGenericParams);
|
||||
fnType = PolymorphicFunctionType::get(argType, resultType,
|
||||
innerGenericParams);
|
||||
} else
|
||||
fnType = FunctionType::get(argType, resultType);
|
||||
Type selfMetaType = MetatypeType::get(resultType, TC.Context);
|
||||
if (outerGenericParams) {
|
||||
allocFnType = PolymorphicFunctionType::get(selfMetaType, fnType,
|
||||
outerGenericParams);
|
||||
initFnType = PolymorphicFunctionType::get(selfType, fnType,
|
||||
outerGenericParams);
|
||||
} else {
|
||||
allocFnType = FunctionType::get(selfMetaType, fnType);
|
||||
initFnType = FunctionType::get(selfType, fnType);
|
||||
}
|
||||
ctor->setType(allocFnType);
|
||||
ctor->setInitializerType(initFnType);
|
||||
}
|
||||
|
||||
void visitConstructorDecl(ConstructorDecl *CD) {
|
||||
if (CD->isInvalid()) {
|
||||
CD->overwriteType(ErrorType::get(TC.Context));
|
||||
@@ -3260,30 +3404,8 @@ public:
|
||||
CD->overwriteType(ErrorType::get(TC.Context));
|
||||
CD->setInvalid();
|
||||
} else {
|
||||
Type FnTy;
|
||||
Type AllocFnTy;
|
||||
Type InitFnTy;
|
||||
Type ArgType = CD->getArgParamPatterns()[1]->getType();
|
||||
Type ResultTy = SelfTy->getInOutObjectType();
|
||||
|
||||
if (GenericParamList *innerGenericParams = CD->getGenericParams()) {
|
||||
innerGenericParams->setOuterParameters(outerGenericParams);
|
||||
FnTy = PolymorphicFunctionType::get(ArgType, ResultTy,
|
||||
innerGenericParams);
|
||||
} else
|
||||
FnTy = FunctionType::get(ArgType, ResultTy);
|
||||
Type SelfMetaTy = MetatypeType::get(ResultTy, TC.Context);
|
||||
if (outerGenericParams) {
|
||||
AllocFnTy = PolymorphicFunctionType::get(SelfMetaTy, FnTy,
|
||||
outerGenericParams);
|
||||
InitFnTy = PolymorphicFunctionType::get(SelfTy, FnTy,
|
||||
outerGenericParams);
|
||||
} else {
|
||||
AllocFnTy = FunctionType::get(SelfMetaTy, FnTy);
|
||||
InitFnTy = FunctionType::get(SelfTy, FnTy);
|
||||
}
|
||||
CD->setType(AllocFnTy);
|
||||
CD->setInitializerType(InitFnTy);
|
||||
configureConstructorType(CD, outerGenericParams, SelfTy,
|
||||
CD->getArgParamPatterns()[1]->getType());
|
||||
}
|
||||
|
||||
validateAttributes(TC, CD);
|
||||
|
||||
@@ -873,6 +873,12 @@ static bool shouldSerializeMember(Decl *D) {
|
||||
case DeclKind::EnumCase:
|
||||
return false;
|
||||
|
||||
case DeclKind::Constructor: {
|
||||
// Never serialize a constructor with a stub implementation.
|
||||
auto ctor = cast<ConstructorDecl>(D);
|
||||
return !ctor->hasStubImplementation();
|
||||
}
|
||||
|
||||
case DeclKind::EnumElement:
|
||||
case DeclKind::Protocol:
|
||||
case DeclKind::Destructor:
|
||||
@@ -886,7 +892,6 @@ static bool shouldSerializeMember(Decl *D) {
|
||||
case DeclKind::Class:
|
||||
case DeclKind::Var:
|
||||
case DeclKind::Func:
|
||||
case DeclKind::Constructor:
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -17,6 +17,7 @@ func onDestruct() { }
|
||||
|
||||
class SwiftGizmo : Gizmo {
|
||||
var x : X
|
||||
init()
|
||||
deinit
|
||||
}
|
||||
sil @_TFCSo10SwiftGizmoD : $@cc(method) @thin (SwiftGizmo) -> ()
|
||||
@@ -89,7 +90,7 @@ bb0(%0 : $SwiftGizmo):
|
||||
// CHECK-NEXT: [[OBJC_SUPER_RECEIVER:%[a-zA-Z0-9]+]] = getelementptr %objc_super* [[OBJC_SUPER]], i32 0, i32 0
|
||||
// CHECK-NEXT: store %objc_object* [[SUPER_OBJ]], %objc_object** [[OBJC_SUPER_RECEIVER]], align 8
|
||||
// CHECK-NEXT: [[OBJC_SUPER_CLASS:%[a-zA-Z0-9]+]] = getelementptr %objc_super* [[OBJC_SUPER]], i32 0, i32 1
|
||||
// CHECK-NEXT: store %objc_class* bitcast (%swift.type* getelementptr inbounds (%swift.full_heapmetadata* bitcast ({ void ([[SGIZMO]]*)*, i8**, i64, %objc_class*, %swift.opaque*, %swift.opaque*, i64, { i64, i8*, i64, i64, i8*, i64, i64 }*, i64, i64 }* @_TMdCSo10SwiftGizmo to %swift.full_heapmetadata*), i32 0, i32 2) to %objc_class*), %objc_class** [[OBJC_SUPER_CLASS]], align 8
|
||||
// CHECK-NEXT: store %objc_class* bitcast (%swift.type* getelementptr inbounds (%swift.full_heapmetadata* bitcast ({{.*}}* @_TMdCSo10SwiftGizmo to %swift.full_heapmetadata*), i32 0, i32 2) to %objc_class*), %objc_class** [[OBJC_SUPER_CLASS]], align 8
|
||||
// CHECK-NEXT: [[DEALLOC_SEL:%[a-zA-Z0-9]+]] = load i8** @"\01L_selector(dealloc)", align 8
|
||||
// CHECK-NEXT: call void bitcast (void ()* @objc_msgSendSuper2 to void (%objc_super*, i8*)*)(%objc_super* [[OBJC_SUPER]], i8* [[DEALLOC_SEL]])
|
||||
%5 = super_method %0 : $SwiftGizmo, #Gizmo.deinit!deallocator.foreign : $@cc(objc_method) @thin (Gizmo) -> () // user: %7
|
||||
@@ -107,3 +108,13 @@ bb0(%0 : $SwiftGizmo):
|
||||
%3 = tuple ()
|
||||
return %3 : $() // id: %4
|
||||
}
|
||||
|
||||
sil @_TToFCSo10SwiftGizmocfMS_FT_S_ : $@cc(objc_method) @thin (@owned SwiftGizmo) -> @owned SwiftGizmo {
|
||||
bb0(%0 : $SwiftGizmo):
|
||||
return %0 : $SwiftGizmo
|
||||
}
|
||||
|
||||
sil @_TToFCSo10SwiftGizmocfMS_FT11withBellsOnSi_S_ : $@cc(objc_method) @thin (Int, @owned SwiftGizmo) -> @owned SwiftGizmo {
|
||||
bb0(%0 : $Int, %1 : $SwiftGizmo):
|
||||
return %1 : $SwiftGizmo
|
||||
}
|
||||
|
||||
@@ -14,6 +14,7 @@
|
||||
#define NS_RETURNS_RETAINED __attribute__((ns_returns_retained))
|
||||
#define NS_CONSUMES_SELF __attribute__((ns_consumes_self))
|
||||
#define NS_CONSUMED __attribute__((ns_consumed))
|
||||
#define OBJC_DESIGNATED_INITIALIZER __attribute__((objc_designated_initializer))
|
||||
|
||||
struct Rect {
|
||||
float x;
|
||||
@@ -38,7 +39,9 @@ typedef long NSInteger;
|
||||
@interface Gizmo : NSObject
|
||||
- (Gizmo*) clone NS_RETURNS_RETAINED;
|
||||
- (Gizmo*) duplicate;
|
||||
- (Gizmo*) initWithBellsOn:(NSInteger)x;
|
||||
- (Gizmo*) init OBJC_DESIGNATED_INITIALIZER;
|
||||
- (Gizmo*) initWithBellsOn:(NSInteger)x OBJC_DESIGNATED_INITIALIZER;
|
||||
- (instancetype) initWithoutBells:(NSInteger)x;
|
||||
- (void) fork NS_CONSUMES_SELF;
|
||||
- (void) enumerateSubGizmos: (void (^)(Gizmo*))f;
|
||||
+ (void) consume: (NS_CONSUMED Gizmo*) gizmo;
|
||||
|
||||
Reference in New Issue
Block a user