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:
Doug Gregor
2014-03-09 07:16:30 +00:00
parent c92f159a8f
commit 00162dc243
10 changed files with 306 additions and 80 deletions

View File

@@ -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; }