@@ -397,9 +397,11 @@ namespace {
397
397
398
398
void handleStoreUse (unsigned UseID);
399
399
void handleInOutUse (const DIMemoryUse &Use);
400
+ void handleEscapeUse (const DIMemoryUse &Use);
400
401
401
402
void handleLoadUseFailure (const DIMemoryUse &InstInfo,
402
403
bool IsSuperInitComplete);
404
+
403
405
void handleSuperInitUse (const DIMemoryUse &InstInfo);
404
406
void handleSelfInitUse (DIMemoryUse &InstInfo);
405
407
void updateInstructionForInitState (DIMemoryUse &InstInfo);
@@ -519,6 +521,13 @@ void LifetimeChecker::noteUninitializedMembers(const DIMemoryUse &Use) {
519
521
assert (TheMemory.isAnyInitSelf () && !TheMemory.isDelegatingInit () &&
520
522
" Not an designated initializer" );
521
523
524
+ // Root protocol initializers (ones that reassign to self, not delegating to
525
+ // self.init) have no members to initialize and self itself has already been
526
+ // reported to be uninit in the primary diagnostic.
527
+ if (TheMemory.isProtocolInitSelf ())
528
+ return ;
529
+
530
+
522
531
// Determine which members, specifically are uninitialized.
523
532
AvailabilitySet Liveness =
524
533
getLivenessAtInst (Use.Inst , Use.FirstElement , Use.NumElements );
@@ -666,47 +675,8 @@ void LifetimeChecker::doIt() {
666
675
case DIUseKind::InOutUse:
667
676
handleInOutUse (Use);
668
677
break ;
669
-
670
678
case DIUseKind::Escape:
671
- if (!isInitializedAtUse (Use)) {
672
- Diag<StringRef> DiagMessage;
673
-
674
- // This is a use of an uninitialized value. Emit a diagnostic.
675
- if (TheMemory.isDelegatingInit ()) {
676
- DiagMessage = diag::self_use_before_init_in_delegatinginit;
677
-
678
- // If this is a load with a single user that is a return, then this is
679
- // a return before self.init. Emit a specific diagnostic.
680
- if (auto *LI = dyn_cast<LoadInst>(Inst))
681
- if (LI->hasOneUse () &&
682
- isa<ReturnInst>((*LI->use_begin ())->getUser ())) {
683
- if (shouldEmitError (Inst))
684
- diagnose (Module, Inst->getLoc (),
685
- diag::return_from_init_without_self_init);
686
- break ;
687
- }
688
- if (isa<ReturnInst>(Inst)) {
689
- if (shouldEmitError (Inst))
690
- diagnose (Module, Inst->getLoc (),
691
- diag::return_from_init_without_self_init);
692
- break ;
693
- }
694
- } else if (isa<ApplyInst>(Inst) && TheMemory.isStructInitSelf ()) {
695
- if (shouldEmitError (Inst)) {
696
- diagnose (Module, Inst->getLoc (),
697
- diag::use_of_self_before_fully_init);
698
- noteUninitializedMembers (Use);
699
- }
700
- break ;
701
- } else if (isa<MarkFunctionEscapeInst>(Inst))
702
- DiagMessage = diag::global_variable_function_use_uninit;
703
- else if (isa<AddressToPointerInst>(Inst))
704
- DiagMessage = diag::variable_addrtaken_before_initialized;
705
- else
706
- DiagMessage = diag::variable_escape_before_initialized;
707
-
708
- diagnoseInitError (Use, DiagMessage);
709
- }
679
+ handleEscapeUse (Use);
710
680
break ;
711
681
case DIUseKind::SuperInit:
712
682
handleSuperInitUse (Use);
@@ -739,6 +709,7 @@ void LifetimeChecker::doIt() {
739
709
handleConditionalDestroys (ControlVariable);
740
710
}
741
711
712
+
742
713
void LifetimeChecker::handleStoreUse (unsigned UseID) {
743
714
DIMemoryUse &InstInfo = Uses[UseID];
744
715
@@ -912,6 +883,60 @@ void LifetimeChecker::handleInOutUse(const DIMemoryUse &Use) {
912
883
}
913
884
}
914
885
886
+ void LifetimeChecker::handleEscapeUse (const DIMemoryUse &Use) {
887
+ // The value must be fully initialized at all escape points. If not, diagnose
888
+ // the error.
889
+ if (isInitializedAtUse (Use))
890
+ return ;
891
+
892
+ auto Inst = Use.Inst ;
893
+
894
+ // This is a use of an uninitialized value. Emit a diagnostic.
895
+ if (TheMemory.isDelegatingInit ()) {
896
+ // If this is a load with a single user that is a return, then this is
897
+ // a return before self.init. Emit a specific diagnostic.
898
+ if (auto *LI = dyn_cast<LoadInst>(Inst))
899
+ if (LI->hasOneUse () &&
900
+ isa<ReturnInst>((*LI->use_begin ())->getUser ())) {
901
+ if (!shouldEmitError (Inst)) return ;
902
+ diagnose (Module, Inst->getLoc (),
903
+ diag::return_from_init_without_self_init);
904
+ return ;
905
+ }
906
+ if (isa<ReturnInst>(Inst)) {
907
+ if (!shouldEmitError (Inst)) return ;
908
+ diagnose (Module, Inst->getLoc (),
909
+ diag::return_from_init_without_self_init);
910
+ return ;
911
+ }
912
+
913
+ return diagnoseInitError (Use, diag::self_use_before_init_in_delegatinginit);
914
+ }
915
+
916
+ if (isa<ApplyInst>(Inst) && TheMemory.isAnyInitSelf () &&
917
+ !TheMemory.isClassInitSelf ()) {
918
+ if (!shouldEmitError (Inst)) return ;
919
+
920
+ auto diagID = diag::use_of_self_before_fully_init;
921
+ if (TheMemory.isProtocolInitSelf ())
922
+ diagID = diag::use_of_self_before_fully_init_protocol;
923
+
924
+ diagnose (Module, Inst->getLoc (), diagID);
925
+ noteUninitializedMembers (Use);
926
+ return ;
927
+ }
928
+
929
+ Diag<StringRef> DiagMessage;
930
+ if (isa<MarkFunctionEscapeInst>(Inst))
931
+ DiagMessage = diag::global_variable_function_use_uninit;
932
+ else if (isa<AddressToPointerInst>(Inst))
933
+ DiagMessage = diag::variable_addrtaken_before_initialized;
934
+ else
935
+ DiagMessage = diag::variable_escape_before_initialized;
936
+
937
+ diagnoseInitError (Use, DiagMessage);
938
+ }
939
+
915
940
916
941
// / Failable enum initializer produce a CFG for the return that looks like this,
917
942
// / where the load is the use of 'self'. Detect this pattern so we can consider
@@ -1170,12 +1195,16 @@ void LifetimeChecker::handleLoadUseFailure(const DIMemoryUse &Use,
1170
1195
return ;
1171
1196
}
1172
1197
1173
- // If this is a load of self in a struct/enum initializer, then it must be a
1174
- // use of 'self' before all the stored properties are set up.
1198
+ // If this is a load of self in a struct/enum/protocol initializer, then it
1199
+ // must be a use of 'self' before all the stored properties are set up.
1175
1200
if (isa<LoadInst>(Inst) && TheMemory.isAnyInitSelf () &&
1176
1201
!TheMemory.isClassInitSelf ()) {
1177
1202
if (!shouldEmitError (Inst)) return ;
1178
- diagnose (Module, Inst->getLoc (), diag::use_of_self_before_fully_init);
1203
+
1204
+ auto diagID = diag::use_of_self_before_fully_init;
1205
+ if (TheMemory.isProtocolInitSelf ())
1206
+ diagID = diag::use_of_self_before_fully_init_protocol;
1207
+ diagnose (Module, Inst->getLoc (), diagID);
1179
1208
noteUninitializedMembers (Use);
1180
1209
return ;
1181
1210
}
0 commit comments