@@ -544,25 +544,17 @@ static ControlFlowKind CheckFallThrough(AnalysisDeclContext &AC) {
544544namespace {
545545
546546struct CheckFallThroughDiagnostics {
547- unsigned diag_MaybeFallThrough_HasNoReturn;
548- unsigned diag_MaybeFallThrough_ReturnsNonVoid;
549- unsigned diag_AlwaysFallThrough_HasNoReturn;
550- unsigned diag_AlwaysFallThrough_ReturnsNonVoid;
551- unsigned diag_NeverFallThroughOrReturn;
552- enum { Function, Block, Lambda, Coroutine } funMode;
547+ unsigned diag_FallThrough_HasNoReturn = 0 ;
548+ unsigned diag_FallThrough_ReturnsNonVoid = 0 ;
549+ unsigned diag_NeverFallThroughOrReturn = 0 ;
550+ unsigned FunKind; // TODO: use diag::FalloffFunctionKind
553551 SourceLocation FuncLoc;
554552
555553 static CheckFallThroughDiagnostics MakeForFunction (const Decl *Func) {
556554 CheckFallThroughDiagnostics D;
557555 D.FuncLoc = Func->getLocation ();
558- D.diag_MaybeFallThrough_HasNoReturn =
559- diag::warn_falloff_noreturn_function;
560- D.diag_MaybeFallThrough_ReturnsNonVoid =
561- diag::warn_maybe_falloff_nonvoid_function;
562- D.diag_AlwaysFallThrough_HasNoReturn =
563- diag::warn_falloff_noreturn_function;
564- D.diag_AlwaysFallThrough_ReturnsNonVoid =
565- diag::warn_falloff_nonvoid_function;
556+ D.diag_FallThrough_HasNoReturn = diag::warn_noreturn_has_return_expr;
557+ D.diag_FallThrough_ReturnsNonVoid = diag::warn_falloff_nonvoid;
566558
567559 // Don't suggest that virtual functions be marked "noreturn", since they
568560 // might be overridden by non-noreturn functions.
@@ -576,76 +568,49 @@ struct CheckFallThroughDiagnostics {
576568 isTemplateInstantiation = Function->isTemplateInstantiation ();
577569
578570 if (!isVirtualMethod && !isTemplateInstantiation)
579- D.diag_NeverFallThroughOrReturn =
580- diag::warn_suggest_noreturn_function;
581- else
582- D.diag_NeverFallThroughOrReturn = 0 ;
571+ D.diag_NeverFallThroughOrReturn = diag::warn_suggest_noreturn_function;
583572
584- D.funMode = Function;
573+ D.FunKind = diag::FalloffFunctionKind:: Function;
585574 return D;
586575 }
587576
588577 static CheckFallThroughDiagnostics MakeForCoroutine (const Decl *Func) {
589578 CheckFallThroughDiagnostics D;
590579 D.FuncLoc = Func->getLocation ();
591- D.diag_MaybeFallThrough_HasNoReturn = 0 ;
592- D.diag_MaybeFallThrough_ReturnsNonVoid =
593- diag::warn_maybe_falloff_nonvoid_coroutine;
594- D.diag_AlwaysFallThrough_HasNoReturn = 0 ;
595- D.diag_AlwaysFallThrough_ReturnsNonVoid =
596- diag::warn_falloff_nonvoid_coroutine;
597- D.diag_NeverFallThroughOrReturn = 0 ;
598- D.funMode = Coroutine;
580+ D.diag_FallThrough_ReturnsNonVoid = diag::warn_falloff_nonvoid;
581+ D.FunKind = diag::FalloffFunctionKind::Coroutine;
599582 return D;
600583 }
601584
602585 static CheckFallThroughDiagnostics MakeForBlock () {
603586 CheckFallThroughDiagnostics D;
604- D.diag_MaybeFallThrough_HasNoReturn =
605- diag::err_noreturn_block_has_return_expr;
606- D.diag_MaybeFallThrough_ReturnsNonVoid =
607- diag::err_maybe_falloff_nonvoid_block;
608- D.diag_AlwaysFallThrough_HasNoReturn =
609- diag::err_noreturn_block_has_return_expr;
610- D.diag_AlwaysFallThrough_ReturnsNonVoid =
611- diag::err_falloff_nonvoid_block;
612- D.diag_NeverFallThroughOrReturn = 0 ;
613- D.funMode = Block;
587+ D.diag_FallThrough_HasNoReturn = diag::err_noreturn_has_return_expr;
588+ D.diag_FallThrough_ReturnsNonVoid = diag::err_falloff_nonvoid;
589+ D.FunKind = diag::FalloffFunctionKind::Block;
614590 return D;
615591 }
616592
617593 static CheckFallThroughDiagnostics MakeForLambda () {
618594 CheckFallThroughDiagnostics D;
619- D.diag_MaybeFallThrough_HasNoReturn =
620- diag::err_noreturn_lambda_has_return_expr;
621- D.diag_MaybeFallThrough_ReturnsNonVoid =
622- diag::warn_maybe_falloff_nonvoid_lambda;
623- D.diag_AlwaysFallThrough_HasNoReturn =
624- diag::err_noreturn_lambda_has_return_expr;
625- D.diag_AlwaysFallThrough_ReturnsNonVoid =
626- diag::warn_falloff_nonvoid_lambda;
627- D.diag_NeverFallThroughOrReturn = 0 ;
628- D.funMode = Lambda;
595+ D.diag_FallThrough_HasNoReturn = diag::err_noreturn_has_return_expr;
596+ D.diag_FallThrough_ReturnsNonVoid = diag::warn_falloff_nonvoid;
597+ D.FunKind = diag::FalloffFunctionKind::Lambda;
629598 return D;
630599 }
631600
632601 bool checkDiagnostics (DiagnosticsEngine &D, bool ReturnsVoid,
633602 bool HasNoReturn) const {
634- if (funMode == Function) {
603+ if (FunKind == diag::FalloffFunctionKind:: Function) {
635604 return (ReturnsVoid ||
636- D.isIgnored (diag::warn_maybe_falloff_nonvoid_function,
637- FuncLoc)) &&
605+ D.isIgnored (diag::warn_falloff_nonvoid, FuncLoc)) &&
638606 (!HasNoReturn ||
639- D.isIgnored (diag::warn_noreturn_function_has_return_expr,
640- FuncLoc)) &&
607+ D.isIgnored (diag::warn_noreturn_has_return_expr, FuncLoc)) &&
641608 (!ReturnsVoid ||
642609 D.isIgnored (diag::warn_suggest_noreturn_block, FuncLoc));
643610 }
644- if (funMode == Coroutine) {
611+ if (FunKind == diag::FalloffFunctionKind:: Coroutine) {
645612 return (ReturnsVoid ||
646- D.isIgnored (diag::warn_maybe_falloff_nonvoid_function, FuncLoc) ||
647- D.isIgnored (diag::warn_maybe_falloff_nonvoid_coroutine,
648- FuncLoc)) &&
613+ D.isIgnored (diag::warn_falloff_nonvoid, FuncLoc)) &&
649614 (!HasNoReturn);
650615 }
651616 // For blocks / lambdas.
@@ -662,12 +627,10 @@ struct CheckFallThroughDiagnostics {
662627static void CheckFallThroughForBody (Sema &S, const Decl *D, const Stmt *Body,
663628 QualType BlockType,
664629 const CheckFallThroughDiagnostics &CD,
665- AnalysisDeclContext &AC,
666- sema::FunctionScopeInfo *FSI) {
630+ AnalysisDeclContext &AC) {
667631
668632 bool ReturnsVoid = false ;
669633 bool HasNoReturn = false ;
670- bool IsCoroutine = FSI->isCoroutine ();
671634
672635 if (const auto *FD = dyn_cast<FunctionDecl>(D)) {
673636 if (const auto *CBody = dyn_cast<CoroutineBodyStmt>(Body))
@@ -696,49 +659,40 @@ static void CheckFallThroughForBody(Sema &S, const Decl *D, const Stmt *Body,
696659 if (CD.checkDiagnostics (Diags, ReturnsVoid, HasNoReturn))
697660 return ;
698661 SourceLocation LBrace = Body->getBeginLoc (), RBrace = Body->getEndLoc ();
699- auto EmitDiag = [&](SourceLocation Loc, unsigned DiagID) {
700- if (IsCoroutine) {
701- if (DiagID != 0 )
702- S.Diag (Loc, DiagID) << FSI->CoroutinePromise ->getType ();
703- } else {
704- S.Diag (Loc, DiagID);
705- }
706- };
707662
708663 // cpu_dispatch functions permit empty function bodies for ICC compatibility.
709664 if (D->getAsFunction () && D->getAsFunction ()->isCPUDispatchMultiVersion ())
710665 return ;
711666
712667 // Either in a function body compound statement, or a function-try-block.
713- switch (CheckFallThrough (AC)) {
714- case UnknownFallThrough:
715- break ;
668+ switch (int FallThroughType = CheckFallThrough (AC)) {
669+ case UnknownFallThrough:
670+ break ;
716671
717- case MaybeFallThrough:
718- if (HasNoReturn)
719- EmitDiag (RBrace, CD.diag_MaybeFallThrough_HasNoReturn );
720- else if (!ReturnsVoid)
721- EmitDiag (RBrace, CD.diag_MaybeFallThrough_ReturnsNonVoid );
722- break ;
723- case AlwaysFallThrough:
724- if (HasNoReturn)
725- EmitDiag (RBrace, CD.diag_AlwaysFallThrough_HasNoReturn );
726- else if (!ReturnsVoid)
727- EmitDiag (RBrace, CD.diag_AlwaysFallThrough_ReturnsNonVoid );
728- break ;
729- case NeverFallThroughOrReturn:
730- if (ReturnsVoid && !HasNoReturn && CD.diag_NeverFallThroughOrReturn ) {
731- if (const FunctionDecl *FD = dyn_cast<FunctionDecl>(D)) {
732- S.Diag (LBrace, CD.diag_NeverFallThroughOrReturn ) << 0 << FD;
733- } else if (const ObjCMethodDecl *MD = dyn_cast<ObjCMethodDecl>(D)) {
734- S.Diag (LBrace, CD.diag_NeverFallThroughOrReturn ) << 1 << MD;
735- } else {
736- S.Diag (LBrace, CD.diag_NeverFallThroughOrReturn );
737- }
672+ case MaybeFallThrough:
673+ case AlwaysFallThrough:
674+ if (HasNoReturn) {
675+ if (CD.diag_FallThrough_HasNoReturn )
676+ S.Diag (RBrace, CD.diag_FallThrough_HasNoReturn ) << CD.FunKind ;
677+ } else if (!ReturnsVoid && CD.diag_FallThrough_ReturnsNonVoid ) {
678+ bool NotInAllControlPaths = FallThroughType == MaybeFallThrough;
679+ S.Diag (RBrace, CD.diag_FallThrough_ReturnsNonVoid )
680+ << CD.FunKind << NotInAllControlPaths;
681+ }
682+ break ;
683+ case NeverFallThroughOrReturn:
684+ if (ReturnsVoid && !HasNoReturn && CD.diag_NeverFallThroughOrReturn ) {
685+ if (const FunctionDecl *FD = dyn_cast<FunctionDecl>(D)) {
686+ S.Diag (LBrace, CD.diag_NeverFallThroughOrReturn ) << 0 << FD;
687+ } else if (const ObjCMethodDecl *MD = dyn_cast<ObjCMethodDecl>(D)) {
688+ S.Diag (LBrace, CD.diag_NeverFallThroughOrReturn ) << 1 << MD;
689+ } else {
690+ S.Diag (LBrace, CD.diag_NeverFallThroughOrReturn );
738691 }
739- break ;
740- case NeverFallThrough:
741- break ;
692+ }
693+ break ;
694+ case NeverFallThrough:
695+ break ;
742696 }
743697}
744698
@@ -2765,7 +2719,7 @@ void clang::sema::AnalysisBasedWarnings::IssueWarnings(
27652719 : (fscope->isCoroutine ()
27662720 ? CheckFallThroughDiagnostics::MakeForCoroutine (D)
27672721 : CheckFallThroughDiagnostics::MakeForFunction (D)));
2768- CheckFallThroughForBody (S, D, Body, BlockType, CD, AC, fscope );
2722+ CheckFallThroughForBody (S, D, Body, BlockType, CD, AC);
27692723 }
27702724
27712725 // Warning: check for unreachable code
0 commit comments