Skip to content

Commit e5c162d

Browse files
authored
Merge pull request #12445 from slavapestov/di-self-consumed-analysis-volume-1
DI: self-consumed analysis rework, volume 1
2 parents 0b8c949 + 083ab8b commit e5c162d

File tree

3 files changed

+83
-46
lines changed

3 files changed

+83
-46
lines changed

lib/SILOptimizer/Mandatory/DefiniteInitialization.cpp

Lines changed: 32 additions & 44 deletions
Original file line numberDiff line numberDiff line change
@@ -521,6 +521,8 @@ namespace {
521521

522522
private:
523523

524+
void emitSelfConsumedDiagnostic(SILInstruction *Inst);
525+
524526
LiveOutBlockState &getBlockInfo(SILBasicBlock *BB) {
525527
return PerBlockInfo.insert({BB,
526528
LiveOutBlockState(TheMemory.NumElements)}).first->second;
@@ -920,18 +922,23 @@ void LifetimeChecker::handleLoadUse(unsigned UseID) {
920922
}
921923
}
922924

925+
void LifetimeChecker::emitSelfConsumedDiagnostic(SILInstruction *Inst) {
926+
if (!shouldEmitError(Inst))
927+
return;
928+
929+
diagnose(Module, Inst->getLoc(),
930+
diag::self_inside_catch_superselfinit,
931+
(unsigned)TheMemory.isDelegatingInit());
932+
}
933+
923934
void LifetimeChecker::handleStoreUse(unsigned UseID) {
924935
DIMemoryUse &InstInfo = Uses[UseID];
925936

926-
if (getSelfConsumedAtInst(InstInfo.Inst) != DIKind::No) {
927-
// FIXME: more specific diagnostics here, handle this case gracefully below.
928-
if (!shouldEmitError(InstInfo.Inst))
937+
if (TheMemory.isAnyInitSelf()) {
938+
if (getSelfConsumedAtInst(InstInfo.Inst) != DIKind::No) {
939+
emitSelfConsumedDiagnostic(InstInfo.Inst);
929940
return;
930-
931-
diagnose(Module, InstInfo.Inst->getLoc(),
932-
diag::self_inside_catch_superselfinit,
933-
(unsigned)TheMemory.isDelegatingInit());
934-
return;
941+
}
935942
}
936943

937944
// Determine the liveness state of the element that we care about.
@@ -1025,13 +1032,7 @@ void LifetimeChecker::handleInOutUse(const DIMemoryUse &Use) {
10251032
// before the "address" is passed as an l-value.
10261033
if (!isInitializedAtUse(Use, &IsSuperInitDone, &FailedSelfUse)) {
10271034
if (FailedSelfUse) {
1028-
// FIXME: more specific diagnostics here, handle this case gracefully below.
1029-
if (!shouldEmitError(Use.Inst))
1030-
return;
1031-
1032-
diagnose(Module, Use.Inst->getLoc(),
1033-
diag::self_inside_catch_superselfinit,
1034-
(unsigned)TheMemory.isDelegatingInit());
1035+
emitSelfConsumedDiagnostic(Use.Inst);
10351036
return;
10361037
}
10371038

@@ -1133,13 +1134,7 @@ void LifetimeChecker::handleEscapeUse(const DIMemoryUse &Use) {
11331134
auto Inst = Use.Inst;
11341135

11351136
if (FailedSelfUse) {
1136-
// FIXME: more specific diagnostics here, handle this case gracefully below.
1137-
if (!shouldEmitError(Inst))
1138-
return;
1139-
1140-
diagnose(Module, Inst->getLoc(),
1141-
diag::self_inside_catch_superselfinit,
1142-
(unsigned)TheMemory.isDelegatingInit());
1137+
emitSelfConsumedDiagnostic(Inst);
11431138
return;
11441139
}
11451140

@@ -1500,13 +1495,7 @@ void LifetimeChecker::handleLoadUseFailure(const DIMemoryUse &Use,
15001495
SILInstruction *Inst = Use.Inst;
15011496

15021497
if (FailedSelfUse) {
1503-
// FIXME: more specific diagnostics here, handle this case gracefully below.
1504-
if (!shouldEmitError(Inst))
1505-
return;
1506-
1507-
diagnose(Module, Inst->getLoc(),
1508-
diag::self_inside_catch_superselfinit,
1509-
(unsigned)TheMemory.isDelegatingInit());
1498+
emitSelfConsumedDiagnostic(Inst);
15101499
return;
15111500
}
15121501

@@ -1664,16 +1653,11 @@ void LifetimeChecker::handleLoadUseFailure(const DIMemoryUse &Use,
16641653
void LifetimeChecker::handleSelfInitUse(DIMemoryUse &InstInfo) {
16651654
auto *Inst = InstInfo.Inst;
16661655

1656+
assert(TheMemory.isAnyInitSelf());
16671657
assert(TheMemory.getType()->hasReferenceSemantics());
16681658

16691659
if (getSelfConsumedAtInst(Inst) != DIKind::No) {
1670-
// FIXME: more specific diagnostics here, handle this case gracefully below.
1671-
if (!shouldEmitError(Inst))
1672-
return;
1673-
1674-
diagnose(Module, Inst->getLoc(),
1675-
diag::self_inside_catch_superselfinit,
1676-
(unsigned)TheMemory.isDelegatingInit());
1660+
emitSelfConsumedDiagnostic(Inst);
16771661
return;
16781662
}
16791663

@@ -1899,8 +1883,10 @@ void LifetimeChecker::processNonTrivialRelease(unsigned ReleaseID) {
18991883
isa<DestroyAddrInst>(Release));
19001884

19011885
auto Availability = getLivenessAtInst(Release, 0, TheMemory.NumElements);
1902-
DIKind SelfConsumed =
1903-
getSelfConsumedAtInst(Release);
1886+
DIKind SelfConsumed = DIKind::No;
1887+
1888+
if (TheMemory.isAnyInitSelf())
1889+
SelfConsumed = getSelfConsumedAtInst(Release);
19041890

19051891
if (SelfConsumed == DIKind::Yes) {
19061892
// We're in an error path after performing a self.init or super.init
@@ -2643,12 +2629,14 @@ bool LifetimeChecker::isInitializedAtUse(const DIMemoryUse &Use,
26432629
bool *FailedSelfUse) {
26442630
if (FailedSelfUse) *FailedSelfUse = false;
26452631
if (SuperInitDone) *SuperInitDone = true;
2646-
2647-
// If the self.init() or super.init() call threw an error and
2648-
// we caught it, self is no longer available.
2649-
if (getSelfConsumedAtInst(Use.Inst) != DIKind::No) {
2650-
if (FailedSelfUse) *FailedSelfUse = true;
2651-
return false;
2632+
2633+
if (TheMemory.isAnyInitSelf()) {
2634+
// If the self.init() or super.init() call threw an error and
2635+
// we caught it, self is no longer available.
2636+
if (getSelfConsumedAtInst(Use.Inst) != DIKind::No) {
2637+
if (FailedSelfUse) *FailedSelfUse = true;
2638+
return false;
2639+
}
26522640
}
26532641

26542642
// Determine the liveness states of the elements that we care about.

test/SILOptimizer/definite_init_failable_initializers_diagnostics.swift

Lines changed: 49 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -51,12 +51,61 @@ class ErrantClass : ErrantBaseClass {
5151
} catch {}
5252
} // expected-error {{'self' used inside 'catch' block reachable from super.init call}}
5353

54+
init(invalidEscapeDesignated2: ()) throws {
55+
x = 10
56+
y = 10
57+
do {
58+
try super.init()
59+
} catch {
60+
try super.init() // expected-error {{'self' used inside 'catch' block reachable from super.init call}}
61+
}
62+
} // expected-error {{'self' used inside 'catch' block reachable from super.init call}}
63+
64+
init(invalidEscapeDesignated3: ()) {
65+
x = 10
66+
y = 10
67+
do {
68+
try super.init()
69+
} catch {
70+
print(self.x) // expected-error {{'self' used inside 'catch' block reachable from super.init call}}
71+
self.y = 20 // expected-error {{'self' used inside 'catch' block reachable from super.init call}}
72+
}
73+
} // expected-error {{'self' used inside 'catch' block reachable from super.init call}}
74+
75+
init(invalidEscapeDesignated4: ()) throws {
76+
x = 10
77+
y = 10
78+
do {
79+
try super.init()
80+
} catch let e {
81+
print(self.x) // expected-error {{'self' used inside 'catch' block reachable from super.init call}}
82+
throw e
83+
}
84+
}
85+
5486
convenience init(invalidEscapeConvenience: ()) {
5587
do {
5688
try self.init()
5789
} catch {}
5890
} // expected-error {{'self' used inside 'catch' block reachable from self.init call}}
5991

92+
convenience init(invalidEscapeConvenience2: ()) throws {
93+
do {
94+
try self.init()
95+
} catch {
96+
try self.init() // expected-error {{'self' used inside 'catch' block reachable from self.init call}}
97+
}
98+
} // expected-error {{'self' used inside 'catch' block reachable from self.init call}}
99+
100+
convenience init(invalidEscapeConvenience3: ()) throws {
101+
do {
102+
try self.init()
103+
} catch let e {
104+
print(self) // expected-error {{'self' used inside 'catch' block reachable from self.init call}}
105+
throw e
106+
}
107+
}
108+
60109
init(noEscapeDesignated: ()) throws {
61110
x = 10
62111
y = 10

test/SILOptimizer/definite_init_markuninitialized_derivedself.sil

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -121,7 +121,7 @@ bb0(%0 : @owned $DerivedClassWithIVars):
121121
%14 = function_ref @superinit : $@convention(method) (@owned RootClassWithIVars) -> @owned RootClassWithIVars
122122
%15 = apply %14(%13) : $@convention(method) (@owned RootClassWithIVars) -> @owned RootClassWithIVars // expected-error {{property 'self.a' not initialized at super.init call}}
123123
%16 = unchecked_ref_cast %15 : $RootClassWithIVars to $DerivedClassWithIVars
124-
assign %16 to %3 : $*DerivedClassWithIVars
124+
store %16 to [init] %3 : $*DerivedClassWithIVars
125125

126126
%18 = load [copy] %3 : $*DerivedClassWithIVars
127127
destroy_value %1 : $<τ_0_0> { var τ_0_0 } <DerivedClassWithIVars>
@@ -272,7 +272,7 @@ bb0(%0 : @owned $DerivedClassWithIVars, %i : @trivial $Int):
272272
// Call super.init.
273273
%15 = apply %14(%13) : $@convention(method) (@owned RootClassWithIVars) -> @owned RootClassWithIVars
274274
%16 = unchecked_ref_cast %15 : $RootClassWithIVars to $DerivedClassWithIVars
275-
assign %16 to %3 : $*DerivedClassWithIVars
275+
store %16 to [init] %3 : $*DerivedClassWithIVars
276276
%18 = load [copy] %3 : $*DerivedClassWithIVars
277277
destroy_value %1 : $<τ_0_0> { var τ_0_0 } <DerivedClassWithIVars>
278278
return %18 : $DerivedClassWithIVars

0 commit comments

Comments
 (0)