@@ -745,6 +745,44 @@ static bool simplifyBlocksWithCallsToNoReturn(SILBasicBlock &BB,
745
745
// function, the entire block is dead.
746
746
NoReturnCall = getPrecedingCallToNoReturn (BB);
747
747
748
+ // Diagnose the unreachable code within the same block as the call to
749
+ // noreturn.
750
+ auto diagnoseUnreachableCode = [&](SILInstruction *noReturnCall,
751
+ SILInstruction *currInst) {
752
+ if (DiagnosedUnreachableCode)
753
+ return false ;
754
+
755
+ // If current instruction belongs to the no-return call itself, skip it.
756
+ //
757
+ // It could happen when i.e. result has to be copied to be passed to
758
+ // some call.
759
+ if (currInst->getLoc ().hasSameSourceLocation (noReturnCall->getLoc ()))
760
+ return false ;
761
+
762
+ if (!isUserCode (currInst))
763
+ return false ;
764
+
765
+ // If we have an instruction that is an end_borrow, ignore it. This
766
+ // happens when passing a guaranteed argument through generic code paths
767
+ // to no return functions.
768
+ if (isa<EndBorrowInst>(currInst))
769
+ return false ;
770
+
771
+ // If no-return instruction is not something we can point in code or
772
+ // it's an explicit cast, skip it.
773
+ if (!noReturnCall->getLoc ().is <RegularLocation>() ||
774
+ noReturnCall->getLoc ().isASTNode <ExplicitCastExpr>())
775
+ return false ;
776
+
777
+ diagnose (BB.getModule ().getASTContext (), currInst->getLoc ().getSourceLoc (),
778
+ diag::unreachable_code);
779
+ diagnose (BB.getModule ().getASTContext (),
780
+ noReturnCall->getLoc ().getSourceLoc (),
781
+ diag::call_to_noreturn_note);
782
+
783
+ return true ;
784
+ };
785
+
748
786
// Does this block contain a call to a noreturn function?
749
787
while (I != E) {
750
788
auto *CurrentInst = &*I;
@@ -758,26 +796,8 @@ static bool simplifyBlocksWithCallsToNoReturn(SILBasicBlock &BB,
758
796
// We will need to delete the instruction later on.
759
797
ToBeDeleted.push_back (CurrentInst);
760
798
761
- // Diagnose the unreachable code within the same block as the call to
762
- // noreturn.
763
- if (isUserCode (CurrentInst) && !DiagnosedUnreachableCode) {
764
- // If we have an instruction that is an end_borrow, ignore it. This
765
- // happens when passing a guaranteed argument through generic code paths
766
- // to no return functions.
767
- if (!isa<EndBorrowInst>(CurrentInst)) {
768
- if (NoReturnCall->getLoc ().is <RegularLocation>()) {
769
- if (!NoReturnCall->getLoc ().isASTNode <ExplicitCastExpr>()) {
770
- diagnose (BB.getModule ().getASTContext (),
771
- CurrentInst->getLoc ().getSourceLoc (),
772
- diag::unreachable_code);
773
- diagnose (BB.getModule ().getASTContext (),
774
- NoReturnCall->getLoc ().getSourceLoc (),
775
- diag::call_to_noreturn_note);
776
- DiagnosedUnreachableCode = true ;
777
- }
778
- }
779
- }
780
- }
799
+ DiagnosedUnreachableCode |=
800
+ diagnoseUnreachableCode (NoReturnCall, CurrentInst);
781
801
782
802
// We are going to bluntly remove these instructions. Change uses in
783
803
// different basic blocks to undef. This is safe because all control flow
0 commit comments