@@ -544,25 +544,17 @@ static ControlFlowKind CheckFallThrough(AnalysisDeclContext &AC) {
544
544
namespace {
545
545
546
546
struct 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
553
551
SourceLocation FuncLoc;
554
552
555
553
static CheckFallThroughDiagnostics MakeForFunction (const Decl *Func) {
556
554
CheckFallThroughDiagnostics D;
557
555
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;
566
558
567
559
// Don't suggest that virtual functions be marked "noreturn", since they
568
560
// might be overridden by non-noreturn functions.
@@ -576,76 +568,49 @@ struct CheckFallThroughDiagnostics {
576
568
isTemplateInstantiation = Function->isTemplateInstantiation ();
577
569
578
570
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;
583
572
584
- D.funMode = Function;
573
+ D.FunKind = diag::FalloffFunctionKind:: Function;
585
574
return D;
586
575
}
587
576
588
577
static CheckFallThroughDiagnostics MakeForCoroutine (const Decl *Func) {
589
578
CheckFallThroughDiagnostics D;
590
579
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;
599
582
return D;
600
583
}
601
584
602
585
static CheckFallThroughDiagnostics MakeForBlock () {
603
586
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;
614
590
return D;
615
591
}
616
592
617
593
static CheckFallThroughDiagnostics MakeForLambda () {
618
594
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;
629
598
return D;
630
599
}
631
600
632
601
bool checkDiagnostics (DiagnosticsEngine &D, bool ReturnsVoid,
633
602
bool HasNoReturn) const {
634
- if (funMode == Function) {
603
+ if (FunKind == diag::FalloffFunctionKind:: Function) {
635
604
return (ReturnsVoid ||
636
- D.isIgnored (diag::warn_maybe_falloff_nonvoid_function,
637
- FuncLoc)) &&
605
+ D.isIgnored (diag::warn_falloff_nonvoid, FuncLoc)) &&
638
606
(!HasNoReturn ||
639
- D.isIgnored (diag::warn_noreturn_function_has_return_expr,
640
- FuncLoc)) &&
607
+ D.isIgnored (diag::warn_noreturn_has_return_expr, FuncLoc)) &&
641
608
(!ReturnsVoid ||
642
609
D.isIgnored (diag::warn_suggest_noreturn_block, FuncLoc));
643
610
}
644
- if (funMode == Coroutine) {
611
+ if (FunKind == diag::FalloffFunctionKind:: Coroutine) {
645
612
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)) &&
649
614
(!HasNoReturn);
650
615
}
651
616
// For blocks / lambdas.
@@ -662,12 +627,10 @@ struct CheckFallThroughDiagnostics {
662
627
static void CheckFallThroughForBody (Sema &S, const Decl *D, const Stmt *Body,
663
628
QualType BlockType,
664
629
const CheckFallThroughDiagnostics &CD,
665
- AnalysisDeclContext &AC,
666
- sema::FunctionScopeInfo *FSI) {
630
+ AnalysisDeclContext &AC) {
667
631
668
632
bool ReturnsVoid = false ;
669
633
bool HasNoReturn = false ;
670
- bool IsCoroutine = FSI->isCoroutine ();
671
634
672
635
if (const auto *FD = dyn_cast<FunctionDecl>(D)) {
673
636
if (const auto *CBody = dyn_cast<CoroutineBodyStmt>(Body))
@@ -696,49 +659,40 @@ static void CheckFallThroughForBody(Sema &S, const Decl *D, const Stmt *Body,
696
659
if (CD.checkDiagnostics (Diags, ReturnsVoid, HasNoReturn))
697
660
return ;
698
661
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
- };
707
662
708
663
// cpu_dispatch functions permit empty function bodies for ICC compatibility.
709
664
if (D->getAsFunction () && D->getAsFunction ()->isCPUDispatchMultiVersion ())
710
665
return ;
711
666
712
667
// 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 ;
716
671
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 );
738
691
}
739
- break ;
740
- case NeverFallThrough:
741
- break ;
692
+ }
693
+ break ;
694
+ case NeverFallThrough:
695
+ break ;
742
696
}
743
697
}
744
698
@@ -2765,7 +2719,7 @@ void clang::sema::AnalysisBasedWarnings::IssueWarnings(
2765
2719
: (fscope->isCoroutine ()
2766
2720
? CheckFallThroughDiagnostics::MakeForCoroutine (D)
2767
2721
: CheckFallThroughDiagnostics::MakeForFunction (D)));
2768
- CheckFallThroughForBody (S, D, Body, BlockType, CD, AC, fscope );
2722
+ CheckFallThroughForBody (S, D, Body, BlockType, CD, AC);
2769
2723
}
2770
2724
2771
2725
// Warning: check for unreachable code
0 commit comments