@@ -745,6 +745,44 @@ static bool simplifyBlocksWithCallsToNoReturn(SILBasicBlock &BB,
745745 // function, the entire block is dead.
746746 NoReturnCall = getPrecedingCallToNoReturn (BB);
747747
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+
748786 // Does this block contain a call to a noreturn function?
749787 while (I != E) {
750788 auto *CurrentInst = &*I;
@@ -758,26 +796,8 @@ static bool simplifyBlocksWithCallsToNoReturn(SILBasicBlock &BB,
758796 // We will need to delete the instruction later on.
759797 ToBeDeleted.push_back (CurrentInst);
760798
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);
781801
782802 // We are going to bluntly remove these instructions. Change uses in
783803 // different basic blocks to undef. This is safe because all control flow
0 commit comments