From 323c74565c2c9330b5a5fbcd931537ed854f8f2b Mon Sep 17 00:00:00 2001 From: "Igor S. Gerasimov" Date: Wed, 19 Feb 2025 19:48:57 +0100 Subject: [PATCH 1/4] Introduce n3483 (return expected in all control paths) --- clang/lib/Sema/AnalysisBasedWarnings.cpp | 19 +++++++++++-------- 1 file changed, 11 insertions(+), 8 deletions(-) diff --git a/clang/lib/Sema/AnalysisBasedWarnings.cpp b/clang/lib/Sema/AnalysisBasedWarnings.cpp index f21e571e6e0ce..03fa4dab7db76 100644 --- a/clang/lib/Sema/AnalysisBasedWarnings.cpp +++ b/clang/lib/Sema/AnalysisBasedWarnings.cpp @@ -550,11 +550,14 @@ struct CheckFallThroughDiagnostics { unsigned FunKind; // TODO: use diag::FalloffFunctionKind SourceLocation FuncLoc; - static CheckFallThroughDiagnostics MakeForFunction(const Decl *Func) { + static CheckFallThroughDiagnostics MakeForFunction(const Sema &S, const Decl *Func) { CheckFallThroughDiagnostics D; D.FuncLoc = Func->getLocation(); D.diag_FallThrough_HasNoReturn = diag::warn_noreturn_has_return_expr; D.diag_FallThrough_ReturnsNonVoid = diag::warn_falloff_nonvoid; + if (S.getLangOpts().C2y) { + D.diag_FallThrough_ReturnsNonVoid = diag::err_falloff_nonvoid; + } // Don't suggest that virtual functions be marked "noreturn", since they // might be overridden by non-noreturn functions. @@ -598,11 +601,13 @@ struct CheckFallThroughDiagnostics { return D; } - bool checkDiagnostics(DiagnosticsEngine &D, bool ReturnsVoid, + bool checkDiagnostics(const Sema &S, bool ReturnsVoid, bool HasNoReturn) const { + const DiagnosticsEngine &D = S.getDiagnostics(); if (FunKind == diag::FalloffFunctionKind::Function) { - return (ReturnsVoid || + return ((ReturnsVoid || D.isIgnored(diag::warn_falloff_nonvoid, FuncLoc)) && + !S.getLangOpts().C2y) && (!HasNoReturn || D.isIgnored(diag::warn_noreturn_has_return_expr, FuncLoc)) && (!ReturnsVoid || @@ -653,10 +658,8 @@ static void CheckFallThroughForBody(Sema &S, const Decl *D, const Stmt *Body, } } - DiagnosticsEngine &Diags = S.getDiagnostics(); - // Short circuit for compilation speed. - if (CD.checkDiagnostics(Diags, ReturnsVoid, HasNoReturn)) + if (CD.checkDiagnostics(S, ReturnsVoid, HasNoReturn)) return; SourceLocation LBrace = Body->getBeginLoc(), RBrace = Body->getEndLoc(); @@ -2708,7 +2711,7 @@ void clang::sema::AnalysisBasedWarnings::IssueWarnings( } // Warning: check missing 'return' - if (P.enableCheckFallThrough) { + if (P.enableCheckFallThrough || S.getLangOpts().C2y) { const CheckFallThroughDiagnostics &CD = (isa(D) ? CheckFallThroughDiagnostics::MakeForBlock() @@ -2718,7 +2721,7 @@ void clang::sema::AnalysisBasedWarnings::IssueWarnings( ? CheckFallThroughDiagnostics::MakeForLambda() : (fscope->isCoroutine() ? CheckFallThroughDiagnostics::MakeForCoroutine(D) - : CheckFallThroughDiagnostics::MakeForFunction(D))); + : CheckFallThroughDiagnostics::MakeForFunction(S, D))); CheckFallThroughForBody(S, D, Body, BlockType, CD, AC); } From 4b839741916d2e7d697b2096e969ecd0d45da998 Mon Sep 17 00:00:00 2001 From: "Igor S. Gerasimov" Date: Wed, 19 Feb 2025 19:54:27 +0100 Subject: [PATCH 2/4] Format code --- clang/lib/Sema/AnalysisBasedWarnings.cpp | 24 ++++++++++++------------ 1 file changed, 12 insertions(+), 12 deletions(-) diff --git a/clang/lib/Sema/AnalysisBasedWarnings.cpp b/clang/lib/Sema/AnalysisBasedWarnings.cpp index 03fa4dab7db76..134952689453a 100644 --- a/clang/lib/Sema/AnalysisBasedWarnings.cpp +++ b/clang/lib/Sema/AnalysisBasedWarnings.cpp @@ -550,7 +550,8 @@ struct CheckFallThroughDiagnostics { unsigned FunKind; // TODO: use diag::FalloffFunctionKind SourceLocation FuncLoc; - static CheckFallThroughDiagnostics MakeForFunction(const Sema &S, const Decl *Func) { + static CheckFallThroughDiagnostics MakeForFunction(const Sema &S, + const Decl *Func) { CheckFallThroughDiagnostics D; D.FuncLoc = Func->getLocation(); D.diag_FallThrough_HasNoReturn = diag::warn_noreturn_has_return_expr; @@ -606,7 +607,7 @@ struct CheckFallThroughDiagnostics { const DiagnosticsEngine &D = S.getDiagnostics(); if (FunKind == diag::FalloffFunctionKind::Function) { return ((ReturnsVoid || - D.isIgnored(diag::warn_falloff_nonvoid, FuncLoc)) && + D.isIgnored(diag::warn_falloff_nonvoid, FuncLoc)) && !S.getLangOpts().C2y) && (!HasNoReturn || D.isIgnored(diag::warn_noreturn_has_return_expr, FuncLoc)) && @@ -660,7 +661,7 @@ static void CheckFallThroughForBody(Sema &S, const Decl *D, const Stmt *Body, // Short circuit for compilation speed. if (CD.checkDiagnostics(S, ReturnsVoid, HasNoReturn)) - return; + return; SourceLocation LBrace = Body->getBeginLoc(), RBrace = Body->getEndLoc(); // cpu_dispatch functions permit empty function bodies for ICC compatibility. @@ -2713,15 +2714,14 @@ void clang::sema::AnalysisBasedWarnings::IssueWarnings( // Warning: check missing 'return' if (P.enableCheckFallThrough || S.getLangOpts().C2y) { const CheckFallThroughDiagnostics &CD = - (isa(D) - ? CheckFallThroughDiagnostics::MakeForBlock() - : (isa(D) && - cast(D)->getOverloadedOperator() == OO_Call && - cast(D)->getParent()->isLambda()) - ? CheckFallThroughDiagnostics::MakeForLambda() - : (fscope->isCoroutine() - ? CheckFallThroughDiagnostics::MakeForCoroutine(D) - : CheckFallThroughDiagnostics::MakeForFunction(S, D))); + (isa(D) ? CheckFallThroughDiagnostics::MakeForBlock() + : (isa(D) && + cast(D)->getOverloadedOperator() == OO_Call && + cast(D)->getParent()->isLambda()) + ? CheckFallThroughDiagnostics::MakeForLambda() + : (fscope->isCoroutine() + ? CheckFallThroughDiagnostics::MakeForCoroutine(D) + : CheckFallThroughDiagnostics::MakeForFunction(S, D))); CheckFallThroughForBody(S, D, Body, BlockType, CD, AC); } From 1a44f712103041d4abaca9be99acafacc9c281d3 Mon Sep 17 00:00:00 2001 From: "Igor S. Gerasimov" Date: Tue, 18 Feb 2025 11:40:03 +0100 Subject: [PATCH 3/4] Missed return statements are not allowed anymore --- clang/test/C/C2y/n3262.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/clang/test/C/C2y/n3262.c b/clang/test/C/C2y/n3262.c index 3ff2062d88dde..611458599c5d9 100644 --- a/clang/test/C/C2y/n3262.c +++ b/clang/test/C/C2y/n3262.c @@ -17,4 +17,4 @@ * copy is made and diagnosing on copy (or on use of the copied va_list). */ -int main() {} +int main() { return 0; } From 916e6767506117a87143609927945fe9b5a72d57 Mon Sep 17 00:00:00 2001 From: "Igor S. Gerasimov" Date: Tue, 18 Feb 2025 11:46:16 +0100 Subject: [PATCH 4/4] Fix unit tests --- clang/include/clang/Testing/TestClangConfig.h | 2 ++ clang/unittests/ASTMatchers/ASTMatchersNarrowingTest.cpp | 4 +++- clang/unittests/Tooling/Syntax/BuildTreeTest.cpp | 3 +++ 3 files changed, 8 insertions(+), 1 deletion(-) diff --git a/clang/include/clang/Testing/TestClangConfig.h b/clang/include/clang/Testing/TestClangConfig.h index e52aa37482dc1..b0687fe84655d 100644 --- a/clang/include/clang/Testing/TestClangConfig.h +++ b/clang/include/clang/Testing/TestClangConfig.h @@ -61,6 +61,8 @@ struct TestClangConfig { bool isC99OrLater() const { return isCOrLater(99); } + bool isC26OrLater() const { return isCOrLater(26); } + bool isCOrEarlier(int MaximumStdVersion) const { return isC() && (isC(MaximumStdVersion) || !isCOrLater(MaximumStdVersion)); } diff --git a/clang/unittests/ASTMatchers/ASTMatchersNarrowingTest.cpp b/clang/unittests/ASTMatchers/ASTMatchersNarrowingTest.cpp index 5e1c12ba26d87..8f4a43a9c7b05 100644 --- a/clang/unittests/ASTMatchers/ASTMatchersNarrowingTest.cpp +++ b/clang/unittests/ASTMatchers/ASTMatchersNarrowingTest.cpp @@ -4327,7 +4327,9 @@ TEST_P(ASTMatchersTest, hasOperator) { } TEST_P(ASTMatchersTest, IsMain) { - EXPECT_TRUE(matches("int main() {}", functionDecl(isMain()))); + EXPECT_TRUE(matches("void main() { }", functionDecl(isMain()))); + + EXPECT_TRUE(matches("int main() { return 0; }", functionDecl(isMain()))); EXPECT_TRUE(notMatches("int main2() { return 0; }", functionDecl(isMain()))); } diff --git a/clang/unittests/Tooling/Syntax/BuildTreeTest.cpp b/clang/unittests/Tooling/Syntax/BuildTreeTest.cpp index d58e190923a1f..166ccc21f4a8d 100644 --- a/clang/unittests/Tooling/Syntax/BuildTreeTest.cpp +++ b/clang/unittests/Tooling/Syntax/BuildTreeTest.cpp @@ -96,6 +96,9 @@ INSTANTIATE_TEST_SUITE_P( }); TEST_P(BuildSyntaxTreeTest, Simple) { + if (GetParam().isC26OrLater()) { + return; + } EXPECT_TRUE(treeDumpEqual( R"cpp( int main() {}