Skip to content

Commit 991600e

Browse files
author
git apple-llvm automerger
committed
Merge commit '9ebb618d03cb' from llvm.org/main into next
2 parents 835bebb + 9ebb618 commit 991600e

File tree

3 files changed

+66
-125
lines changed

3 files changed

+66
-125
lines changed

clang/include/clang/Basic/DiagnosticSemaKinds.td

Lines changed: 13 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -713,30 +713,21 @@ def err_thread_non_global : Error<
713713
def err_thread_unsupported : Error<
714714
"thread-local storage is not supported for the current target">;
715715

716-
// FIXME: Combine fallout warnings to just one warning.
717-
def warn_maybe_falloff_nonvoid_function : Warning<
718-
"non-void function does not return a value in all control paths">,
719-
InGroup<ReturnType>;
720-
def warn_falloff_nonvoid_function : Warning<
721-
"non-void function does not return a value">,
716+
def warn_falloff_nonvoid : Warning<
717+
"non-void "
718+
"%enum_select<FalloffFunctionKind>{%Function{function}|%Block{block}|%Lambda{lambda}|%Coroutine{coroutine}}0"
719+
" does not return a value%select{| in all control paths}1">,
722720
InGroup<ReturnType>;
721+
def err_falloff_nonvoid : Error<
722+
"non-void %select{function|block|lambda|coroutine}0 "
723+
"does not return a value%select{| in all control paths}1">;
723724
def warn_const_attr_with_pure_attr : Warning<
724725
"'const' attribute imposes more restrictions; 'pure' attribute ignored">,
725726
InGroup<IgnoredAttributes>;
726727
def warn_pure_function_returns_void : Warning<
727728
"'%select{pure|const}0' attribute on function returning 'void'; attribute ignored">,
728729
InGroup<IgnoredAttributes>;
729730

730-
def err_maybe_falloff_nonvoid_block : Error<
731-
"non-void block does not return a value in all control paths">;
732-
def err_falloff_nonvoid_block : Error<
733-
"non-void block does not return a value">;
734-
def warn_maybe_falloff_nonvoid_coroutine : Warning<
735-
"non-void coroutine does not return a value in all control paths">,
736-
InGroup<ReturnType>;
737-
def warn_falloff_nonvoid_coroutine : Warning<
738-
"non-void coroutine does not return a value">,
739-
InGroup<ReturnType>;
740731
def warn_suggest_noreturn_function : Warning<
741732
"%select{function|method}0 %1 could be declared with attribute 'noreturn'">,
742733
InGroup<MissingNoreturn>, DefaultIgnore;
@@ -8460,14 +8451,6 @@ let CategoryName = "Lambda Issue" in {
84608451
"lambda expression in default argument cannot capture any entity">;
84618452
def err_lambda_incomplete_result : Error<
84628453
"incomplete result type %0 in lambda expression">;
8463-
def err_noreturn_lambda_has_return_expr : Error<
8464-
"lambda declared 'noreturn' should not return">;
8465-
def warn_maybe_falloff_nonvoid_lambda : Warning<
8466-
"non-void lambda does not return a value in all control paths">,
8467-
InGroup<ReturnType>;
8468-
def warn_falloff_nonvoid_lambda : Warning<
8469-
"non-void lambda does not return a value">,
8470-
InGroup<ReturnType>;
84718454
def err_access_lambda_capture : Error<
84728455
// The ERRORs represent other special members that aren't constructors, in
84738456
// hopes that someone will bother noticing and reporting if they appear
@@ -10673,14 +10656,16 @@ def err_ctor_dtor_returns_void : Error<
1067310656
def warn_noreturn_function_has_return_expr : Warning<
1067410657
"function %0 declared 'noreturn' should not return">,
1067510658
InGroup<InvalidNoreturn>;
10676-
def warn_falloff_noreturn_function : Warning<
10677-
"function declared 'noreturn' should not return">,
10659+
def warn_noreturn_has_return_expr : Warning<
10660+
"%select{function|block|lambda|coroutine}0 "
10661+
"declared 'noreturn' should not return">,
1067810662
InGroup<InvalidNoreturn>;
10663+
def err_noreturn_has_return_expr : Error<
10664+
"%select{function|block|lambda|coroutine}0 "
10665+
"declared 'noreturn' should not return">;
1067910666
def warn_noreturn_coroutine : Warning<
1068010667
"coroutine %0 cannot be declared 'noreturn' as it always returns a coroutine handle">,
1068110668
InGroup<InvalidNoreturn>;
10682-
def err_noreturn_block_has_return_expr : Error<
10683-
"block declared 'noreturn' should not return">;
1068410669
def err_carries_dependency_missing_on_first_decl : Error<
1068510670
"%select{function|parameter}0 declared '[[carries_dependency]]' "
1068610671
"after its first declaration">;

clang/lib/Sema/AnalysisBasedWarnings.cpp

Lines changed: 49 additions & 95 deletions
Original file line numberDiff line numberDiff line change
@@ -546,25 +546,17 @@ static ControlFlowKind CheckFallThrough(AnalysisDeclContext &AC) {
546546
namespace {
547547

548548
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
555553
SourceLocation FuncLoc;
556554

557555
static CheckFallThroughDiagnostics MakeForFunction(const Decl *Func) {
558556
CheckFallThroughDiagnostics D;
559557
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;
568560

569561
// Don't suggest that virtual functions be marked "noreturn", since they
570562
// might be overridden by non-noreturn functions.
@@ -578,76 +570,49 @@ struct CheckFallThroughDiagnostics {
578570
isTemplateInstantiation = Function->isTemplateInstantiation();
579571

580572
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;
585574

586-
D.funMode = Function;
575+
D.FunKind = diag::FalloffFunctionKind::Function;
587576
return D;
588577
}
589578

590579
static CheckFallThroughDiagnostics MakeForCoroutine(const Decl *Func) {
591580
CheckFallThroughDiagnostics D;
592581
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;
601584
return D;
602585
}
603586

604587
static CheckFallThroughDiagnostics MakeForBlock() {
605588
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;
616592
return D;
617593
}
618594

619595
static CheckFallThroughDiagnostics MakeForLambda() {
620596
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;
631600
return D;
632601
}
633602

634603
bool checkDiagnostics(DiagnosticsEngine &D, bool ReturnsVoid,
635604
bool HasNoReturn) const {
636-
if (funMode == Function) {
605+
if (FunKind == diag::FalloffFunctionKind::Function) {
637606
return (ReturnsVoid ||
638-
D.isIgnored(diag::warn_maybe_falloff_nonvoid_function,
639-
FuncLoc)) &&
607+
D.isIgnored(diag::warn_falloff_nonvoid, FuncLoc)) &&
640608
(!HasNoReturn ||
641-
D.isIgnored(diag::warn_noreturn_function_has_return_expr,
642-
FuncLoc)) &&
609+
D.isIgnored(diag::warn_noreturn_has_return_expr, FuncLoc)) &&
643610
(!ReturnsVoid ||
644611
D.isIgnored(diag::warn_suggest_noreturn_block, FuncLoc));
645612
}
646-
if (funMode == Coroutine) {
613+
if (FunKind == diag::FalloffFunctionKind::Coroutine) {
647614
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)) &&
651616
(!HasNoReturn);
652617
}
653618
// For blocks / lambdas.
@@ -664,12 +629,10 @@ struct CheckFallThroughDiagnostics {
664629
static void CheckFallThroughForBody(Sema &S, const Decl *D, const Stmt *Body,
665630
QualType BlockType,
666631
const CheckFallThroughDiagnostics &CD,
667-
AnalysisDeclContext &AC,
668-
sema::FunctionScopeInfo *FSI) {
632+
AnalysisDeclContext &AC) {
669633

670634
bool ReturnsVoid = false;
671635
bool HasNoReturn = false;
672-
bool IsCoroutine = FSI->isCoroutine();
673636

674637
if (const auto *FD = dyn_cast<FunctionDecl>(D)) {
675638
if (const auto *CBody = dyn_cast<CoroutineBodyStmt>(Body))
@@ -698,49 +661,40 @@ static void CheckFallThroughForBody(Sema &S, const Decl *D, const Stmt *Body,
698661
if (CD.checkDiagnostics(Diags, ReturnsVoid, HasNoReturn))
699662
return;
700663
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-
};
709664

710665
// cpu_dispatch functions permit empty function bodies for ICC compatibility.
711666
if (D->getAsFunction() && D->getAsFunction()->isCPUDispatchMultiVersion())
712667
return;
713668

714669
// 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;
718673

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);
740693
}
741-
break;
742-
case NeverFallThrough:
743-
break;
694+
}
695+
break;
696+
case NeverFallThrough:
697+
break;
744698
}
745699
}
746700

@@ -3381,7 +3335,7 @@ void clang::sema::AnalysisBasedWarnings::IssueWarnings(
33813335
: (fscope->isCoroutine()
33823336
? CheckFallThroughDiagnostics::MakeForCoroutine(D)
33833337
: CheckFallThroughDiagnostics::MakeForFunction(D)));
3384-
CheckFallThroughForBody(S, D, Body, BlockType, CD, AC, fscope);
3338+
CheckFallThroughForBody(S, D, Body, BlockType, CD, AC);
33853339
}
33863340

33873341
// Warning: check for unreachable code

clang/lib/Sema/SemaStmt.cpp

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3598,7 +3598,8 @@ StmtResult Sema::ActOnCapScopeReturnStmt(SourceLocation ReturnLoc,
35983598

35993599
if (auto *CurBlock = dyn_cast<BlockScopeInfo>(CurCap)) {
36003600
if (CurBlock->FunctionType->castAs<FunctionType>()->getNoReturnAttr()) {
3601-
Diag(ReturnLoc, diag::err_noreturn_block_has_return_expr);
3601+
Diag(ReturnLoc, diag::err_noreturn_has_return_expr)
3602+
<< diag::FalloffFunctionKind::Block;
36023603
return StmtError();
36033604
}
36043605
} else if (auto *CurRegion = dyn_cast<CapturedRegionScopeInfo>(CurCap)) {
@@ -3609,7 +3610,8 @@ StmtResult Sema::ActOnCapScopeReturnStmt(SourceLocation ReturnLoc,
36093610
if (CurLambda->CallOperator->getType()
36103611
->castAs<FunctionType>()
36113612
->getNoReturnAttr()) {
3612-
Diag(ReturnLoc, diag::err_noreturn_lambda_has_return_expr);
3613+
Diag(ReturnLoc, diag::err_noreturn_has_return_expr)
3614+
<< diag::FalloffFunctionKind::Lambda;
36133615
return StmtError();
36143616
}
36153617
}

0 commit comments

Comments
 (0)