mirror of
https://github.com/apple/swift.git
synced 2025-12-21 12:14:44 +01:00
Fix <rdar://problem/20193929> Can't "return nil" in a convenience initializer
This falls out of the rework I did of 'self' in initializers. We now correctly dealloc_ref the allocated object on the failure path of a convenience init. Swift SVN r27752
This commit is contained in:
@@ -1340,8 +1340,8 @@ void LifetimeChecker::processNonTrivialRelease(unsigned ReleaseID) {
|
||||
|
||||
// Right now we don't fully support cleaning up a partially initialized object
|
||||
// after a failure. Handle this by only allowing an early 'return nil' in an
|
||||
// initializer after all properties are initialized.
|
||||
if (TheMemory.isClassInitSelf()) {
|
||||
// initializer after all properties are initialized or in a convenience init.
|
||||
if (TheMemory.isClassInitSelf() && !TheMemory.isDelegatingInit()) {
|
||||
SILLocation loc = Release->getLoc();
|
||||
|
||||
// The release is generally a cleanup in a failure block, and is usually the
|
||||
@@ -1358,25 +1358,19 @@ void LifetimeChecker::processNonTrivialRelease(unsigned ReleaseID) {
|
||||
}
|
||||
}
|
||||
|
||||
// If this is a convenience initializer, report that self.init() must be
|
||||
// called.
|
||||
if (TheMemory.isDelegatingInit()) {
|
||||
diagnose(Module, loc, diag::self_init_must_be_called_before_failure);
|
||||
} else {
|
||||
// Otherwise all members must be initialized (including the base class, if
|
||||
// present).
|
||||
diagnose(Module, loc, diag::object_not_fully_initialized_before_failure);
|
||||
|
||||
// Note each of the members that isn't initialized.
|
||||
DIMemoryUse Use(Release, DIUseKind::Load, 0, TheMemory.NumElements);
|
||||
noteUninitializedMembers(Use);
|
||||
|
||||
// If we're tracking the state of super.init (i.e., in a derived class)
|
||||
// then report on failure to call super.init as well.
|
||||
if (TheMemory.isAnyDerivedClassSelf() &&
|
||||
Availability.get(Availability.size()-1) != DIKind::Yes)
|
||||
diagnose(Module, loc, diag::must_call_super_init_failable_init);
|
||||
}
|
||||
// All members must be initialized (including the base class, if
|
||||
// present).
|
||||
diagnose(Module, loc, diag::object_not_fully_initialized_before_failure);
|
||||
|
||||
// Note each of the members that isn't initialized.
|
||||
DIMemoryUse Use(Release, DIUseKind::Load, 0, TheMemory.NumElements);
|
||||
noteUninitializedMembers(Use);
|
||||
|
||||
// If we're tracking the state of super.init (i.e., in a derived class)
|
||||
// then report on failure to call super.init as well.
|
||||
if (TheMemory.isAnyDerivedClassSelf() &&
|
||||
Availability.get(Availability.size()-1) != DIKind::Yes)
|
||||
diagnose(Module, loc, diag::must_call_super_init_failable_init);
|
||||
}
|
||||
|
||||
// If it is all 'no' then we can handle is specially without conditional code.
|
||||
|
||||
Reference in New Issue
Block a user