@@ -546,25 +546,17 @@ static ControlFlowKind CheckFallThrough(AnalysisDeclContext &AC) {
546
546
namespace {
547
547
548
548
struct CheckFallThroughDiagnostics {
549
- unsigned diag_MaybeFallThrough_HasNoReturn;
550
- unsigned diag_MaybeFallThrough_ReturnsNonVoid;
551
- unsigned diag_AlwaysFallThrough_HasNoReturn;
552
- unsigned diag_AlwaysFallThrough_ReturnsNonVoid;
553
- unsigned diag_NeverFallThroughOrReturn;
554
- enum { Function, Block, Lambda, Coroutine } funMode;
549
+ unsigned diag_FallThrough_HasNoReturn = 0 ;
550
+ unsigned diag_FallThrough_ReturnsNonVoid = 0 ;
551
+ unsigned diag_NeverFallThroughOrReturn = 0 ;
552
+ unsigned FunKind; // TODO: use diag::FalloffFunctionKind
555
553
SourceLocation FuncLoc;
556
554
557
555
static CheckFallThroughDiagnostics MakeForFunction (const Decl *Func) {
558
556
CheckFallThroughDiagnostics D;
559
557
D.FuncLoc = Func->getLocation ();
560
- D.diag_MaybeFallThrough_HasNoReturn =
561
- diag::warn_falloff_noreturn_function;
562
- D.diag_MaybeFallThrough_ReturnsNonVoid =
563
- diag::warn_maybe_falloff_nonvoid_function;
564
- D.diag_AlwaysFallThrough_HasNoReturn =
565
- diag::warn_falloff_noreturn_function;
566
- D.diag_AlwaysFallThrough_ReturnsNonVoid =
567
- diag::warn_falloff_nonvoid_function;
558
+ D.diag_FallThrough_HasNoReturn = diag::warn_noreturn_has_return_expr;
559
+ D.diag_FallThrough_ReturnsNonVoid = diag::warn_falloff_nonvoid;
568
560
569
561
// Don't suggest that virtual functions be marked "noreturn", since they
570
562
// might be overridden by non-noreturn functions.
@@ -578,76 +570,49 @@ struct CheckFallThroughDiagnostics {
578
570
isTemplateInstantiation = Function->isTemplateInstantiation ();
579
571
580
572
if (!isVirtualMethod && !isTemplateInstantiation)
581
- D.diag_NeverFallThroughOrReturn =
582
- diag::warn_suggest_noreturn_function;
583
- else
584
- D.diag_NeverFallThroughOrReturn = 0 ;
573
+ D.diag_NeverFallThroughOrReturn = diag::warn_suggest_noreturn_function;
585
574
586
- D.funMode = Function;
575
+ D.FunKind = diag::FalloffFunctionKind:: Function;
587
576
return D;
588
577
}
589
578
590
579
static CheckFallThroughDiagnostics MakeForCoroutine (const Decl *Func) {
591
580
CheckFallThroughDiagnostics D;
592
581
D.FuncLoc = Func->getLocation ();
593
- D.diag_MaybeFallThrough_HasNoReturn = 0 ;
594
- D.diag_MaybeFallThrough_ReturnsNonVoid =
595
- diag::warn_maybe_falloff_nonvoid_coroutine;
596
- D.diag_AlwaysFallThrough_HasNoReturn = 0 ;
597
- D.diag_AlwaysFallThrough_ReturnsNonVoid =
598
- diag::warn_falloff_nonvoid_coroutine;
599
- D.diag_NeverFallThroughOrReturn = 0 ;
600
- D.funMode = Coroutine;
582
+ D.diag_FallThrough_ReturnsNonVoid = diag::warn_falloff_nonvoid;
583
+ D.FunKind = diag::FalloffFunctionKind::Coroutine;
601
584
return D;
602
585
}
603
586
604
587
static CheckFallThroughDiagnostics MakeForBlock () {
605
588
CheckFallThroughDiagnostics D;
606
- D.diag_MaybeFallThrough_HasNoReturn =
607
- diag::err_noreturn_block_has_return_expr;
608
- D.diag_MaybeFallThrough_ReturnsNonVoid =
609
- diag::err_maybe_falloff_nonvoid_block;
610
- D.diag_AlwaysFallThrough_HasNoReturn =
611
- diag::err_noreturn_block_has_return_expr;
612
- D.diag_AlwaysFallThrough_ReturnsNonVoid =
613
- diag::err_falloff_nonvoid_block;
614
- D.diag_NeverFallThroughOrReturn = 0 ;
615
- D.funMode = Block;
589
+ D.diag_FallThrough_HasNoReturn = diag::err_noreturn_has_return_expr;
590
+ D.diag_FallThrough_ReturnsNonVoid = diag::err_falloff_nonvoid;
591
+ D.FunKind = diag::FalloffFunctionKind::Block;
616
592
return D;
617
593
}
618
594
619
595
static CheckFallThroughDiagnostics MakeForLambda () {
620
596
CheckFallThroughDiagnostics D;
621
- D.diag_MaybeFallThrough_HasNoReturn =
622
- diag::err_noreturn_lambda_has_return_expr;
623
- D.diag_MaybeFallThrough_ReturnsNonVoid =
624
- diag::warn_maybe_falloff_nonvoid_lambda;
625
- D.diag_AlwaysFallThrough_HasNoReturn =
626
- diag::err_noreturn_lambda_has_return_expr;
627
- D.diag_AlwaysFallThrough_ReturnsNonVoid =
628
- diag::warn_falloff_nonvoid_lambda;
629
- D.diag_NeverFallThroughOrReturn = 0 ;
630
- D.funMode = Lambda;
597
+ D.diag_FallThrough_HasNoReturn = diag::err_noreturn_has_return_expr;
598
+ D.diag_FallThrough_ReturnsNonVoid = diag::warn_falloff_nonvoid;
599
+ D.FunKind = diag::FalloffFunctionKind::Lambda;
631
600
return D;
632
601
}
633
602
634
603
bool checkDiagnostics (DiagnosticsEngine &D, bool ReturnsVoid,
635
604
bool HasNoReturn) const {
636
- if (funMode == Function) {
605
+ if (FunKind == diag::FalloffFunctionKind:: Function) {
637
606
return (ReturnsVoid ||
638
- D.isIgnored (diag::warn_maybe_falloff_nonvoid_function,
639
- FuncLoc)) &&
607
+ D.isIgnored (diag::warn_falloff_nonvoid, FuncLoc)) &&
640
608
(!HasNoReturn ||
641
- D.isIgnored (diag::warn_noreturn_function_has_return_expr,
642
- FuncLoc)) &&
609
+ D.isIgnored (diag::warn_noreturn_has_return_expr, FuncLoc)) &&
643
610
(!ReturnsVoid ||
644
611
D.isIgnored (diag::warn_suggest_noreturn_block, FuncLoc));
645
612
}
646
- if (funMode == Coroutine) {
613
+ if (FunKind == diag::FalloffFunctionKind:: Coroutine) {
647
614
return (ReturnsVoid ||
648
- D.isIgnored (diag::warn_maybe_falloff_nonvoid_function, FuncLoc) ||
649
- D.isIgnored (diag::warn_maybe_falloff_nonvoid_coroutine,
650
- FuncLoc)) &&
615
+ D.isIgnored (diag::warn_falloff_nonvoid, FuncLoc)) &&
651
616
(!HasNoReturn);
652
617
}
653
618
// For blocks / lambdas.
@@ -664,12 +629,10 @@ struct CheckFallThroughDiagnostics {
664
629
static void CheckFallThroughForBody (Sema &S, const Decl *D, const Stmt *Body,
665
630
QualType BlockType,
666
631
const CheckFallThroughDiagnostics &CD,
667
- AnalysisDeclContext &AC,
668
- sema::FunctionScopeInfo *FSI) {
632
+ AnalysisDeclContext &AC) {
669
633
670
634
bool ReturnsVoid = false ;
671
635
bool HasNoReturn = false ;
672
- bool IsCoroutine = FSI->isCoroutine ();
673
636
674
637
if (const auto *FD = dyn_cast<FunctionDecl>(D)) {
675
638
if (const auto *CBody = dyn_cast<CoroutineBodyStmt>(Body))
@@ -698,49 +661,40 @@ static void CheckFallThroughForBody(Sema &S, const Decl *D, const Stmt *Body,
698
661
if (CD.checkDiagnostics (Diags, ReturnsVoid, HasNoReturn))
699
662
return ;
700
663
SourceLocation LBrace = Body->getBeginLoc (), RBrace = Body->getEndLoc ();
701
- auto EmitDiag = [&](SourceLocation Loc, unsigned DiagID) {
702
- if (IsCoroutine) {
703
- if (DiagID != 0 )
704
- S.Diag (Loc, DiagID) << FSI->CoroutinePromise ->getType ();
705
- } else {
706
- S.Diag (Loc, DiagID);
707
- }
708
- };
709
664
710
665
// cpu_dispatch functions permit empty function bodies for ICC compatibility.
711
666
if (D->getAsFunction () && D->getAsFunction ()->isCPUDispatchMultiVersion ())
712
667
return ;
713
668
714
669
// Either in a function body compound statement, or a function-try-block.
715
- switch (CheckFallThrough (AC)) {
716
- case UnknownFallThrough:
717
- break ;
670
+ switch (int FallThroughType = CheckFallThrough (AC)) {
671
+ case UnknownFallThrough:
672
+ break ;
718
673
719
- case MaybeFallThrough:
720
- if (HasNoReturn)
721
- EmitDiag (RBrace, CD.diag_MaybeFallThrough_HasNoReturn );
722
- else if (!ReturnsVoid)
723
- EmitDiag (RBrace, CD.diag_MaybeFallThrough_ReturnsNonVoid );
724
- break ;
725
- case AlwaysFallThrough:
726
- if (HasNoReturn)
727
- EmitDiag (RBrace, CD.diag_AlwaysFallThrough_HasNoReturn );
728
- else if (!ReturnsVoid)
729
- EmitDiag (RBrace, CD.diag_AlwaysFallThrough_ReturnsNonVoid );
730
- break ;
731
- case NeverFallThroughOrReturn:
732
- if (ReturnsVoid && !HasNoReturn && CD.diag_NeverFallThroughOrReturn ) {
733
- if (const FunctionDecl *FD = dyn_cast<FunctionDecl>(D)) {
734
- S.Diag (LBrace, CD.diag_NeverFallThroughOrReturn ) << 0 << FD;
735
- } else if (const ObjCMethodDecl *MD = dyn_cast<ObjCMethodDecl>(D)) {
736
- S.Diag (LBrace, CD.diag_NeverFallThroughOrReturn ) << 1 << MD;
737
- } else {
738
- S.Diag (LBrace, CD.diag_NeverFallThroughOrReturn );
739
- }
674
+ case MaybeFallThrough:
675
+ case AlwaysFallThrough:
676
+ if (HasNoReturn) {
677
+ if (CD.diag_FallThrough_HasNoReturn )
678
+ S.Diag (RBrace, CD.diag_FallThrough_HasNoReturn ) << CD.FunKind ;
679
+ } else if (!ReturnsVoid && CD.diag_FallThrough_ReturnsNonVoid ) {
680
+ bool NotInAllControlPaths = FallThroughType == MaybeFallThrough;
681
+ S.Diag (RBrace, CD.diag_FallThrough_ReturnsNonVoid )
682
+ << CD.FunKind << NotInAllControlPaths;
683
+ }
684
+ break ;
685
+ case NeverFallThroughOrReturn:
686
+ if (ReturnsVoid && !HasNoReturn && CD.diag_NeverFallThroughOrReturn ) {
687
+ if (const FunctionDecl *FD = dyn_cast<FunctionDecl>(D)) {
688
+ S.Diag (LBrace, CD.diag_NeverFallThroughOrReturn ) << 0 << FD;
689
+ } else if (const ObjCMethodDecl *MD = dyn_cast<ObjCMethodDecl>(D)) {
690
+ S.Diag (LBrace, CD.diag_NeverFallThroughOrReturn ) << 1 << MD;
691
+ } else {
692
+ S.Diag (LBrace, CD.diag_NeverFallThroughOrReturn );
740
693
}
741
- break ;
742
- case NeverFallThrough:
743
- break ;
694
+ }
695
+ break ;
696
+ case NeverFallThrough:
697
+ break ;
744
698
}
745
699
}
746
700
@@ -3381,7 +3335,7 @@ void clang::sema::AnalysisBasedWarnings::IssueWarnings(
3381
3335
: (fscope->isCoroutine ()
3382
3336
? CheckFallThroughDiagnostics::MakeForCoroutine (D)
3383
3337
: CheckFallThroughDiagnostics::MakeForFunction (D)));
3384
- CheckFallThroughForBody (S, D, Body, BlockType, CD, AC, fscope );
3338
+ CheckFallThroughForBody (S, D, Body, BlockType, CD, AC);
3385
3339
}
3386
3340
3387
3341
// Warning: check for unreachable code
0 commit comments