https://github.com/dutkalex updated https://github.com/llvm/llvm-project/pull/219589
>From 5a9cd36333b015ec66842d72e184318b7c42bdda Mon Sep 17 00:00:00 2001 From: Alex Dutka <[email protected]> Date: Fri, 28 Aug 2026 16:08:46 +0200 Subject: [PATCH 01/11] add if-block-size check --- .../clang-tidy/readability/CMakeLists.txt | 1 + .../readability/IfBlockSizeCheck.cpp | 32 ++++++++++++++++++ .../clang-tidy/readability/IfBlockSizeCheck.h | 33 +++++++++++++++++++ .../readability/ReadabilityTidyModule.cpp | 3 ++ .../checkers/readability/if-block-size.cpp | 14 ++++++++ 5 files changed, 83 insertions(+) create mode 100644 clang-tools-extra/clang-tidy/readability/IfBlockSizeCheck.cpp create mode 100644 clang-tools-extra/clang-tidy/readability/IfBlockSizeCheck.h create mode 100644 clang-tools-extra/test/clang-tidy/checkers/readability/if-block-size.cpp diff --git a/clang-tools-extra/clang-tidy/readability/CMakeLists.txt b/clang-tools-extra/clang-tidy/readability/CMakeLists.txt index 11cadf9f39879..e7d38f6427a49 100644 --- a/clang-tools-extra/clang-tidy/readability/CMakeLists.txt +++ b/clang-tools-extra/clang-tidy/readability/CMakeLists.txt @@ -23,6 +23,7 @@ add_clang_library(clangTidyReadabilityModule STATIC FunctionSizeCheck.cpp IdentifierLengthCheck.cpp IdentifierNamingCheck.cpp + IfBlockSizeCheck.cpp ImplicitBoolConversionCheck.cpp InconsistentIfElseBracesCheck.cpp RedundantInlineSpecifierCheck.cpp diff --git a/clang-tools-extra/clang-tidy/readability/IfBlockSizeCheck.cpp b/clang-tools-extra/clang-tidy/readability/IfBlockSizeCheck.cpp new file mode 100644 index 0000000000000..7623838512f87 --- /dev/null +++ b/clang-tools-extra/clang-tidy/readability/IfBlockSizeCheck.cpp @@ -0,0 +1,32 @@ +//===----------------------------------------------------------------------===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#include "IfBlockSizeCheck.h" +#include "clang/ASTMatchers/ASTMatchFinder.h" + +using namespace clang::ast_matchers; + +namespace clang::tidy::readability { + +void IfBlockSizeCheck::registerMatchers(MatchFinder *Finder) { + // FIXME: Add matchers. + Finder->addMatcher(functionDecl().bind("x"), this); +} + +void IfBlockSizeCheck::check(const MatchFinder::MatchResult &Result) { + // FIXME: Add callback implementation. + const auto *MatchedDecl = Result.Nodes.getNodeAs<FunctionDecl>("x"); + if (!MatchedDecl->getIdentifier() || MatchedDecl->getName().starts_with("awesome_")) + return; + diag(MatchedDecl->getLocation(), "function %0 is insufficiently awesome") + << MatchedDecl + << FixItHint::CreateInsertion(MatchedDecl->getLocation(), "awesome_"); + diag(MatchedDecl->getLocation(), "insert 'awesome'", DiagnosticIDs::Note); +} + +} // namespace clang::tidy::readability diff --git a/clang-tools-extra/clang-tidy/readability/IfBlockSizeCheck.h b/clang-tools-extra/clang-tidy/readability/IfBlockSizeCheck.h new file mode 100644 index 0000000000000..1a8bfb5efb7ee --- /dev/null +++ b/clang-tools-extra/clang-tidy/readability/IfBlockSizeCheck.h @@ -0,0 +1,33 @@ +//===----------------------------------------------------------------------===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_READABILITY_IFBLOCKSIZECHECK_H +#define LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_READABILITY_IFBLOCKSIZECHECK_H + +#include "../ClangTidyCheck.h" + +namespace clang::tidy::readability { + +/// FIXME: Write a short description. +/// +/// For the user-facing documentation see: +/// https://clang.llvm.org/extra/clang-tidy/checks/readability/if-block-size.html +class IfBlockSizeCheck : public ClangTidyCheck { +public: + IfBlockSizeCheck(StringRef Name, ClangTidyContext *Context) + : ClangTidyCheck(Name, Context) {} + void registerMatchers(ast_matchers::MatchFinder *Finder) override; + void check(const ast_matchers::MatchFinder::MatchResult &Result) override; + bool isLanguageVersionSupported(const LangOptions &LangOpts) const override { + return LangOpts.CPlusPlus; + } +}; + +} // namespace clang::tidy::readability + +#endif // LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_READABILITY_IFBLOCKSIZECHECK_H diff --git a/clang-tools-extra/clang-tidy/readability/ReadabilityTidyModule.cpp b/clang-tools-extra/clang-tidy/readability/ReadabilityTidyModule.cpp index 0592ae5f1bf60..67091551a4706 100644 --- a/clang-tools-extra/clang-tidy/readability/ReadabilityTidyModule.cpp +++ b/clang-tools-extra/clang-tidy/readability/ReadabilityTidyModule.cpp @@ -27,6 +27,7 @@ #include "FunctionSizeCheck.h" #include "IdentifierLengthCheck.h" #include "IdentifierNamingCheck.h" +#include "IfBlockSizeCheck.h" #include "ImplicitBoolConversionCheck.h" #include "InconsistentDeclarationParameterNameCheck.h" #include "InconsistentIfElseBracesCheck.h" @@ -117,6 +118,8 @@ class ReadabilityModule : public ClangTidyModule { "readability-identifier-length"); CheckFactories.registerCheck<IdentifierNamingCheck>( "readability-identifier-naming"); + CheckFactories.registerCheck<IfBlockSizeCheck>( + "readability-if-block-size"); CheckFactories.registerCheck<ImplicitBoolConversionCheck>( "readability-implicit-bool-conversion"); CheckFactories.registerCheck<InconsistentIfElseBracesCheck>( diff --git a/clang-tools-extra/test/clang-tidy/checkers/readability/if-block-size.cpp b/clang-tools-extra/test/clang-tidy/checkers/readability/if-block-size.cpp new file mode 100644 index 0000000000000..17a4fd5c62159 --- /dev/null +++ b/clang-tools-extra/test/clang-tidy/checkers/readability/if-block-size.cpp @@ -0,0 +1,14 @@ +// RUN: %check_clang_tidy %s readability-if-block-size %t + +// FIXME: Add something that triggers the check here. +void f(); +// CHECK-MESSAGES: :[[@LINE-1]]:6: warning: function 'f' is insufficiently awesome [readability-if-block-size] + +// FIXME: Verify the applied fix. +// * Make the CHECK patterns specific enough and try to make verified lines +// unique to avoid incorrect matches. +// * Use {{}} for regular expressions. +// CHECK-FIXES: {{^}}void awesome_f();{{$}} + +// FIXME: Add something that doesn't trigger the check here. +void awesome_f2(); >From 88d286eead3bf24e18aba8b2ccdd12f9590a00f5 Mon Sep 17 00:00:00 2001 From: Alex Dutka <[email protected]> Date: Fri, 28 Aug 2026 18:59:31 +0200 Subject: [PATCH 02/11] basic implementation working --- .../readability/IfBlockSizeCheck.cpp | 28 ++++--- .../clang-tidy/readability/IfBlockSizeCheck.h | 5 +- .../checkers/readability/if-block-size.cpp | 79 ++++++++++++++++--- 3 files changed, 92 insertions(+), 20 deletions(-) diff --git a/clang-tools-extra/clang-tidy/readability/IfBlockSizeCheck.cpp b/clang-tools-extra/clang-tidy/readability/IfBlockSizeCheck.cpp index 7623838512f87..847b588305e57 100644 --- a/clang-tools-extra/clang-tidy/readability/IfBlockSizeCheck.cpp +++ b/clang-tools-extra/clang-tidy/readability/IfBlockSizeCheck.cpp @@ -7,26 +7,36 @@ //===----------------------------------------------------------------------===// #include "IfBlockSizeCheck.h" +#include "clang/AST/Stmt.h" #include "clang/ASTMatchers/ASTMatchFinder.h" +#include "clang/ASTMatchers/ASTMatchers.h" using namespace clang::ast_matchers; namespace clang::tidy::readability { void IfBlockSizeCheck::registerMatchers(MatchFinder *Finder) { - // FIXME: Add matchers. - Finder->addMatcher(functionDecl().bind("x"), this); + Finder->addMatcher(ifStmt().bind("if"), this); } void IfBlockSizeCheck::check(const MatchFinder::MatchResult &Result) { - // FIXME: Add callback implementation. - const auto *MatchedDecl = Result.Nodes.getNodeAs<FunctionDecl>("x"); - if (!MatchedDecl->getIdentifier() || MatchedDecl->getName().starts_with("awesome_")) + const auto& SrcMgr = Result.SourceManager; + + const auto *IfBlk = Result.Nodes.getNodeAs<IfStmt>("if"); + const unsigned FirstLine = SrcMgr->getSpellingLineNumber(IfBlk->getBeginLoc()); + const unsigned LastLine = [&](){ + if (const auto *ElseBlk = IfBlk->getElse()) + return SrcMgr->getSpellingLineNumber(ElseBlk->getBeginLoc()); + return SrcMgr->getSpellingLineNumber(IfBlk->getEndLoc()); + }(); + const unsigned LineCount = LastLine - FirstLine + 1; + + if (LineCount <= LineCountThreshold) return; - diag(MatchedDecl->getLocation(), "function %0 is insufficiently awesome") - << MatchedDecl - << FixItHint::CreateInsertion(MatchedDecl->getLocation(), "awesome_"); - diag(MatchedDecl->getLocation(), "insert 'awesome'", DiagnosticIDs::Note); + + diag(IfBlk->getBeginLoc(), "if block spans %0 lines of code, which exceeds the threshold of %1 lines") + << LineCount + << LineCountThreshold; } } // namespace clang::tidy::readability diff --git a/clang-tools-extra/clang-tidy/readability/IfBlockSizeCheck.h b/clang-tools-extra/clang-tidy/readability/IfBlockSizeCheck.h index 1a8bfb5efb7ee..3197fe558bfd6 100644 --- a/clang-tools-extra/clang-tidy/readability/IfBlockSizeCheck.h +++ b/clang-tools-extra/clang-tidy/readability/IfBlockSizeCheck.h @@ -13,7 +13,7 @@ namespace clang::tidy::readability { -/// FIXME: Write a short description. +/// Warns about large if blocks /// /// For the user-facing documentation see: /// https://clang.llvm.org/extra/clang-tidy/checks/readability/if-block-size.html @@ -26,6 +26,9 @@ class IfBlockSizeCheck : public ClangTidyCheck { bool isLanguageVersionSupported(const LangOptions &LangOpts) const override { return LangOpts.CPlusPlus; } + +private: + const unsigned LineCountThreshold = 20; }; } // namespace clang::tidy::readability diff --git a/clang-tools-extra/test/clang-tidy/checkers/readability/if-block-size.cpp b/clang-tools-extra/test/clang-tidy/checkers/readability/if-block-size.cpp index 17a4fd5c62159..5005d6da85011 100644 --- a/clang-tools-extra/test/clang-tidy/checkers/readability/if-block-size.cpp +++ b/clang-tools-extra/test/clang-tidy/checkers/readability/if-block-size.cpp @@ -1,14 +1,73 @@ // RUN: %check_clang_tidy %s readability-if-block-size %t -// FIXME: Add something that triggers the check here. -void f(); -// CHECK-MESSAGES: :[[@LINE-1]]:6: warning: function 'f' is insufficiently awesome [readability-if-block-size] +void should_warn(){ + if (true){ // 1 +// CHECK-MESSAGES: :[[@LINE-1]]:5: warning: if block spans 21 lines of code, which exceeds the threshold of 20 lines [readability-if-block-size] + int sum = 3 + + 4 + + 5 + + 6 + + 7 + + 8 + + 9 + + 10 + + 11 + + 12 + + 13 + + 14 + + 15 + + 16 + + 17 + + 18 + + 19 + + 20; + } // 21 +} -// FIXME: Verify the applied fix. -// * Make the CHECK patterns specific enough and try to make verified lines -// unique to avoid incorrect matches. -// * Use {{}} for regular expressions. -// CHECK-FIXES: {{^}}void awesome_f();{{$}} +void should_not_warn(){ + if (true){ // 1 + int sum = 2 + + 3 + + 4 + + 5 + + 6 + + 7 + + 8 + + 9 + + 10 + + 11 + + 12 + + 13 + + 14 + + 15 + + 16 + + 17 + + 18 + + 19; + } // 20 -// FIXME: Add something that doesn't trigger the check here. -void awesome_f2(); + bool a = true; + bool b = false; + if (a && b){ + int sum = 2 + + 3 + + 4 + + 5 + + 6; + } else if (a || b) { + int sum = 8 + + 9 + + 10 + + 11 + + 12 + + 13 + + 14 + + 15; + } else { + int sum = 17 + + 18 + + 19 + + 20 + + 21; + } +} >From 4a637df8dbbbdcb95fffcfa4a57d8d918627d0f0 Mon Sep 17 00:00:00 2001 From: Alex Dutka <[email protected]> Date: Fri, 28 Aug 2026 21:30:56 +0200 Subject: [PATCH 03/11] add else block logic --- .../readability/IfBlockSizeCheck.cpp | 37 +++++++++++++------ clang-tools-extra/docs/ReleaseNotes.md | 5 +++ .../docs/clang-tidy/checks/list.md | 1 + .../checks/readability/if-block-size.md | 6 +++ .../checkers/readability/if-block-size.cpp | 25 +++++++++++++ 5 files changed, 62 insertions(+), 12 deletions(-) create mode 100644 clang-tools-extra/docs/clang-tidy/checks/readability/if-block-size.md diff --git a/clang-tools-extra/clang-tidy/readability/IfBlockSizeCheck.cpp b/clang-tools-extra/clang-tidy/readability/IfBlockSizeCheck.cpp index 847b588305e57..0c31cc3f7c532 100644 --- a/clang-tools-extra/clang-tidy/readability/IfBlockSizeCheck.cpp +++ b/clang-tools-extra/clang-tidy/readability/IfBlockSizeCheck.cpp @@ -20,23 +20,36 @@ void IfBlockSizeCheck::registerMatchers(MatchFinder *Finder) { } void IfBlockSizeCheck::check(const MatchFinder::MatchResult &Result) { - const auto& SrcMgr = Result.SourceManager; + const auto &SrcMgr = Result.SourceManager; const auto *IfBlk = Result.Nodes.getNodeAs<IfStmt>("if"); - const unsigned FirstLine = SrcMgr->getSpellingLineNumber(IfBlk->getBeginLoc()); - const unsigned LastLine = [&](){ - if (const auto *ElseBlk = IfBlk->getElse()) + const auto *ElseBlk = IfBlk->getElse(); + + const unsigned FirstLine = + SrcMgr->getSpellingLineNumber(IfBlk->getBeginLoc()); + const unsigned LastLine = [&]() { + if (ElseBlk != nullptr) return SrcMgr->getSpellingLineNumber(ElseBlk->getBeginLoc()); return SrcMgr->getSpellingLineNumber(IfBlk->getEndLoc()); }(); - const unsigned LineCount = LastLine - FirstLine + 1; - - if (LineCount <= LineCountThreshold) - return; - - diag(IfBlk->getBeginLoc(), "if block spans %0 lines of code, which exceeds the threshold of %1 lines") - << LineCount - << LineCountThreshold; + const unsigned LineCount = LastLine - FirstLine + 1; + + if (LineCount > LineCountThreshold) + diag(IfBlk->getBeginLoc(), "if block spans %0 lines of code, which exceeds " + "the threshold of %1 lines") + << LineCount << LineCountThreshold; + + if (ElseBlk != nullptr && isa<CompoundStmt>(ElseBlk)) { // i.e. is not an else if + const unsigned ElseLastLine = + SrcMgr->getSpellingLineNumber(IfBlk->getEndLoc()); + const unsigned ElseLineCount = ElseLastLine - LastLine + 1; + + if (ElseLineCount > LineCountThreshold) + diag(ElseBlk->getBeginLoc(), + "else block spans %0 lines of code, which exceeds " + "the threshold of %1 lines") + << ElseLineCount << LineCountThreshold; + } } } // namespace clang::tidy::readability diff --git a/clang-tools-extra/docs/ReleaseNotes.md b/clang-tools-extra/docs/ReleaseNotes.md index 420b7ddce20e6..134660e3fd7db 100644 --- a/clang-tools-extra/docs/ReleaseNotes.md +++ b/clang-tools-extra/docs/ReleaseNotes.md @@ -119,6 +119,11 @@ infrastructure are described first, followed by tool-specific sections. Finds uses of `#pragma comment` and, for `lib` or `linker` comments, suggests using the build system for improved portability. +- New {doc}`readability-if-block-size + <clang-tidy/checks/readability/if-block-size>` check. + + FIXME: Write a short description. + - New {doc}`readability-redundant-zero-initializer <clang-tidy/checks/readability/redundant-zero-initializer>` check. diff --git a/clang-tools-extra/docs/clang-tidy/checks/list.md b/clang-tools-extra/docs/clang-tidy/checks/list.md index 5a220b13eb599..7d824b1b5392b 100644 --- a/clang-tools-extra/docs/clang-tidy/checks/list.md +++ b/clang-tools-extra/docs/clang-tidy/checks/list.md @@ -399,6 +399,7 @@ readability/* | {doc}`readability-function-size <readability/function-size>` | | | {doc}`readability-identifier-length <readability/identifier-length>` | | | {doc}`readability-identifier-naming <readability/identifier-naming>` | Yes | +| {doc}`readability-if-block-size <readability/if-block-size>` | Yes | | {doc}`readability-implicit-bool-conversion <readability/implicit-bool-conversion>` | Yes | | {doc}`readability-inconsistent-declaration-parameter-name <readability/inconsistent-declaration-parameter-name>` | Yes | | {doc}`readability-inconsistent-ifelse-braces <readability/inconsistent-ifelse-braces>` | Yes | diff --git a/clang-tools-extra/docs/clang-tidy/checks/readability/if-block-size.md b/clang-tools-extra/docs/clang-tidy/checks/readability/if-block-size.md new file mode 100644 index 0000000000000..0289f5c11ce76 --- /dev/null +++ b/clang-tools-extra/docs/clang-tidy/checks/readability/if-block-size.md @@ -0,0 +1,6 @@ +```{title} clang-tidy - readability-if-block-size +``` + +# readability-if-block-size + +FIXME: Describe what patterns does the check detect and why. Give examples. diff --git a/clang-tools-extra/test/clang-tidy/checkers/readability/if-block-size.cpp b/clang-tools-extra/test/clang-tidy/checkers/readability/if-block-size.cpp index 5005d6da85011..679f601846390 100644 --- a/clang-tools-extra/test/clang-tidy/checkers/readability/if-block-size.cpp +++ b/clang-tools-extra/test/clang-tidy/checkers/readability/if-block-size.cpp @@ -22,6 +22,31 @@ void should_warn(){ + 19 + 20; } // 21 + + + if (true){ // 1 + int sum = 2; + } else { // 3 1 +// CHECK-MESSAGES: :[[@LINE-1]]:12: warning: else block spans 21 lines of code, which exceeds the threshold of 20 lines [readability-if-block-size] + int sum = 5 // 3 + + 6 // 4 + + 7 // 5 + + 8 // 6 + + 9 // 7 + + 10 // 8 + + 11 // 9 + + 12 // 10 + + 13 // 11 + + 14 // 12 + + 15 // 13 + + 16 // 14 + + 17 // 15 + + 18 // 16 + + 19 // 17 + + 20 // 18 + + 21 // 19 + + 22; // 20 + } // 23 21 } void should_not_warn(){ >From 41f9b89fbcf3354d9ae300a87bc6149a1b8f0776 Mon Sep 17 00:00:00 2001 From: Alex Dutka <[email protected]> Date: Fri, 28 Aug 2026 21:37:35 +0200 Subject: [PATCH 04/11] add else if test --- .../checkers/readability/if-block-size.cpp | 27 +++++++++++++++++++ 1 file changed, 27 insertions(+) diff --git a/clang-tools-extra/test/clang-tidy/checkers/readability/if-block-size.cpp b/clang-tools-extra/test/clang-tidy/checkers/readability/if-block-size.cpp index 679f601846390..f3f49acf9288e 100644 --- a/clang-tools-extra/test/clang-tidy/checkers/readability/if-block-size.cpp +++ b/clang-tools-extra/test/clang-tidy/checkers/readability/if-block-size.cpp @@ -47,6 +47,33 @@ void should_warn(){ + 21 // 19 + 22; // 20 } // 23 21 + + + if (true){ // 1 + int sum = 2; + } else if (true){ // 1 +// CHECK-MESSAGES: :[[@LINE-1]]:12: warning: if block spans 21 lines of code, which exceeds the threshold of 20 lines [readability-if-block-size] + int sum = 5 // 3 + + 6 // 4 + + 7 // 5 + + 8 // 6 + + 9 // 7 + + 10 // 8 + + 11 // 9 + + 12 // 10 + + 13 // 11 + + 14 // 12 + + 15 // 13 + + 16 // 14 + + 17 // 15 + + 18 // 16 + + 19 // 17 + + 20 // 18 + + 21 // 19 + + 22; // 20 + } else { // 23 21 + int sum = 24; + } // 25 } void should_not_warn(){ >From d1d134a2c1e7815f96c421240b5b4ffbdedde3a0 Mon Sep 17 00:00:00 2001 From: Alex Dutka <[email protected]> Date: Fri, 28 Aug 2026 22:00:23 +0200 Subject: [PATCH 05/11] extend scope to for and while loops --- .../readability/IfBlockSizeCheck.cpp | 91 +++++++++++++------ .../checkers/readability/if-block-size.cpp | 88 ++++++++++++++++++ 2 files changed, 153 insertions(+), 26 deletions(-) diff --git a/clang-tools-extra/clang-tidy/readability/IfBlockSizeCheck.cpp b/clang-tools-extra/clang-tidy/readability/IfBlockSizeCheck.cpp index 0c31cc3f7c532..2c83433d589c8 100644 --- a/clang-tools-extra/clang-tidy/readability/IfBlockSizeCheck.cpp +++ b/clang-tools-extra/clang-tidy/readability/IfBlockSizeCheck.cpp @@ -17,38 +17,77 @@ namespace clang::tidy::readability { void IfBlockSizeCheck::registerMatchers(MatchFinder *Finder) { Finder->addMatcher(ifStmt().bind("if"), this); + Finder->addMatcher(forStmt().bind("for"), this); + Finder->addMatcher(whileStmt().bind("while"), this); } void IfBlockSizeCheck::check(const MatchFinder::MatchResult &Result) { const auto &SrcMgr = Result.SourceManager; - const auto *IfBlk = Result.Nodes.getNodeAs<IfStmt>("if"); - const auto *ElseBlk = IfBlk->getElse(); - - const unsigned FirstLine = - SrcMgr->getSpellingLineNumber(IfBlk->getBeginLoc()); - const unsigned LastLine = [&]() { - if (ElseBlk != nullptr) - return SrcMgr->getSpellingLineNumber(ElseBlk->getBeginLoc()); - return SrcMgr->getSpellingLineNumber(IfBlk->getEndLoc()); - }(); - const unsigned LineCount = LastLine - FirstLine + 1; - - if (LineCount > LineCountThreshold) - diag(IfBlk->getBeginLoc(), "if block spans %0 lines of code, which exceeds " - "the threshold of %1 lines") - << LineCount << LineCountThreshold; - - if (ElseBlk != nullptr && isa<CompoundStmt>(ElseBlk)) { // i.e. is not an else if - const unsigned ElseLastLine = - SrcMgr->getSpellingLineNumber(IfBlk->getEndLoc()); - const unsigned ElseLineCount = ElseLastLine - LastLine + 1; - - if (ElseLineCount > LineCountThreshold) - diag(ElseBlk->getBeginLoc(), - "else block spans %0 lines of code, which exceeds " + if (const auto *IfBlk = Result.Nodes.getNodeAs<IfStmt>("if")) { + const auto *ElseBlk = IfBlk->getElse(); + + const unsigned FirstLine = + SrcMgr->getSpellingLineNumber(IfBlk->getBeginLoc()); + const unsigned LastLine = [&]() { + if (ElseBlk != nullptr) + return SrcMgr->getSpellingLineNumber(ElseBlk->getBeginLoc()); + return SrcMgr->getSpellingLineNumber(IfBlk->getEndLoc()); + }(); + const unsigned LineCount = LastLine - FirstLine + 1; + + if (LineCount > LineCountThreshold) + diag(IfBlk->getBeginLoc(), + "if block spans %0 lines of code, which exceeds " "the threshold of %1 lines") - << ElseLineCount << LineCountThreshold; + << LineCount << LineCountThreshold; + + if (ElseBlk != nullptr && + isa<CompoundStmt>(ElseBlk)) { // i.e. is not an else if + const unsigned ElseLastLine = + SrcMgr->getSpellingLineNumber(IfBlk->getEndLoc()); + const unsigned ElseLineCount = ElseLastLine - LastLine + 1; + + if (ElseLineCount > LineCountThreshold) + diag(ElseBlk->getBeginLoc(), + "else block spans %0 lines of code, which exceeds " + "the threshold of %1 lines") + << ElseLineCount << LineCountThreshold; + } + + return; + } + + if (const auto *ForLoop = Result.Nodes.getNodeAs<ForStmt>("for")) { + const unsigned FirstLine = + SrcMgr->getSpellingLineNumber(ForLoop->getBeginLoc()); + const unsigned LastLine = + SrcMgr->getSpellingLineNumber(ForLoop->getEndLoc()); + const unsigned LineCount = LastLine - FirstLine + 1; + + if (LineCount > LineCountThreshold) { + diag(ForLoop->getBeginLoc(), "for loop spans %0 lines of code, which " + "exceeds the threshold of %1 lines") + << LineCount << LineCountThreshold; + } + + return; + } + + if (const auto *WhileLoop = Result.Nodes.getNodeAs<WhileStmt>("while")) { + const unsigned FirstLine = + SrcMgr->getSpellingLineNumber(WhileLoop->getBeginLoc()); + const unsigned LastLine = + SrcMgr->getSpellingLineNumber(WhileLoop->getEndLoc()); + const unsigned LineCount = LastLine - FirstLine + 1; + + if (LineCount > LineCountThreshold) { + diag(WhileLoop->getBeginLoc(), "while loop spans %0 lines of code, which " + "exceeds the threshold of %1 lines") + << LineCount << LineCountThreshold; + } + + return; } } diff --git a/clang-tools-extra/test/clang-tidy/checkers/readability/if-block-size.cpp b/clang-tools-extra/test/clang-tidy/checkers/readability/if-block-size.cpp index f3f49acf9288e..232b9dc021643 100644 --- a/clang-tools-extra/test/clang-tidy/checkers/readability/if-block-size.cpp +++ b/clang-tools-extra/test/clang-tidy/checkers/readability/if-block-size.cpp @@ -74,6 +74,51 @@ void should_warn(){ } else { // 23 21 int sum = 24; } // 25 + + + for (int i = 0; i < 10; ++i) { +// CHECK-MESSAGES: :[[@LINE-1]]:5: warning: for loop spans 21 lines of code, which exceeds the threshold of 20 lines [readability-if-block-size] + int sum = 3 + + 4 + + 5 + + 6 + + 7 + + 8 + + 9 + + 10 + + 11 + + 12 + + 13 + + 14 + + 15 + + 16 + + 17 + + 18 + + 19 + + 20; + } + + while (true) { +// CHECK-MESSAGES: :[[@LINE-1]]:5: warning: while loop spans 21 lines of code, which exceeds the threshold of 20 lines [readability-if-block-size] + int sum = 3 + + 4 + + 5 + + 6 + + 7 + + 8 + + 9 + + 10 + + 11 + + 12 + + 13 + + 14 + + 15 + + 16 + + 17 + + 18 + + 19 + + 20; + } } void should_not_warn(){ @@ -122,4 +167,47 @@ void should_not_warn(){ + 20 + 21; } + + + for (int i = 0; i < 10; ++i) { + int sum = 2 + + 3 + + 4 + + 5 + + 6 + + 7 + + 8 + + 9 + + 10 + + 11 + + 12 + + 13 + + 14 + + 15 + + 16 + + 17 + + 18 + + 19; + } + + while (true) { + int sum = 2 + + 3 + + 4 + + 5 + + 6 + + 7 + + 8 + + 9 + + 10 + + 11 + + 12 + + 13 + + 14 + + 15 + + 16 + + 17 + + 18 + + 19; + } } >From e478064072ff2b5caf5e7f9f0d0032d1876191dd Mon Sep 17 00:00:00 2001 From: Alex Dutka <[email protected]> Date: Fri, 28 Aug 2026 22:12:37 +0200 Subject: [PATCH 06/11] rename check to readability-block-size --- .../{IfBlockSizeCheck.cpp => BlockSizeCheck.cpp} | 6 +++--- .../{IfBlockSizeCheck.h => BlockSizeCheck.h} | 12 ++++++------ .../clang-tidy/readability/CMakeLists.txt | 2 +- .../clang-tidy/readability/ReadabilityTidyModule.cpp | 6 +++--- clang-tools-extra/docs/ReleaseNotes.md | 4 ++-- clang-tools-extra/docs/clang-tidy/checks/list.md | 2 +- .../readability/{if-block-size.md => block-size.md} | 4 ++-- .../{if-block-size.cpp => block-size.cpp} | 12 ++++++------ 8 files changed, 24 insertions(+), 24 deletions(-) rename clang-tools-extra/clang-tidy/readability/{IfBlockSizeCheck.cpp => BlockSizeCheck.cpp} (95%) rename clang-tools-extra/clang-tidy/readability/{IfBlockSizeCheck.h => BlockSizeCheck.h} (69%) rename clang-tools-extra/docs/clang-tidy/checks/readability/{if-block-size.md => block-size.md} (51%) rename clang-tools-extra/test/clang-tidy/checkers/readability/{if-block-size.cpp => block-size.cpp} (97%) diff --git a/clang-tools-extra/clang-tidy/readability/IfBlockSizeCheck.cpp b/clang-tools-extra/clang-tidy/readability/BlockSizeCheck.cpp similarity index 95% rename from clang-tools-extra/clang-tidy/readability/IfBlockSizeCheck.cpp rename to clang-tools-extra/clang-tidy/readability/BlockSizeCheck.cpp index 2c83433d589c8..5335c8c30b55d 100644 --- a/clang-tools-extra/clang-tidy/readability/IfBlockSizeCheck.cpp +++ b/clang-tools-extra/clang-tidy/readability/BlockSizeCheck.cpp @@ -6,7 +6,7 @@ // //===----------------------------------------------------------------------===// -#include "IfBlockSizeCheck.h" +#include "BlockSizeCheck.h" #include "clang/AST/Stmt.h" #include "clang/ASTMatchers/ASTMatchFinder.h" #include "clang/ASTMatchers/ASTMatchers.h" @@ -15,13 +15,13 @@ using namespace clang::ast_matchers; namespace clang::tidy::readability { -void IfBlockSizeCheck::registerMatchers(MatchFinder *Finder) { +void BlockSizeCheck::registerMatchers(MatchFinder *Finder) { Finder->addMatcher(ifStmt().bind("if"), this); Finder->addMatcher(forStmt().bind("for"), this); Finder->addMatcher(whileStmt().bind("while"), this); } -void IfBlockSizeCheck::check(const MatchFinder::MatchResult &Result) { +void BlockSizeCheck::check(const MatchFinder::MatchResult &Result) { const auto &SrcMgr = Result.SourceManager; if (const auto *IfBlk = Result.Nodes.getNodeAs<IfStmt>("if")) { diff --git a/clang-tools-extra/clang-tidy/readability/IfBlockSizeCheck.h b/clang-tools-extra/clang-tidy/readability/BlockSizeCheck.h similarity index 69% rename from clang-tools-extra/clang-tidy/readability/IfBlockSizeCheck.h rename to clang-tools-extra/clang-tidy/readability/BlockSizeCheck.h index 3197fe558bfd6..acf4ffe7f8692 100644 --- a/clang-tools-extra/clang-tidy/readability/IfBlockSizeCheck.h +++ b/clang-tools-extra/clang-tidy/readability/BlockSizeCheck.h @@ -6,8 +6,8 @@ // //===----------------------------------------------------------------------===// -#ifndef LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_READABILITY_IFBLOCKSIZECHECK_H -#define LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_READABILITY_IFBLOCKSIZECHECK_H +#ifndef LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_READABILITY_BLOCKSIZECHECK_H +#define LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_READABILITY_BLOCKSIZECHECK_H #include "../ClangTidyCheck.h" @@ -16,10 +16,10 @@ namespace clang::tidy::readability { /// Warns about large if blocks /// /// For the user-facing documentation see: -/// https://clang.llvm.org/extra/clang-tidy/checks/readability/if-block-size.html -class IfBlockSizeCheck : public ClangTidyCheck { +/// https://clang.llvm.org/extra/clang-tidy/checks/readability/block-size.html +class BlockSizeCheck : public ClangTidyCheck { public: - IfBlockSizeCheck(StringRef Name, ClangTidyContext *Context) + BlockSizeCheck(StringRef Name, ClangTidyContext *Context) : ClangTidyCheck(Name, Context) {} void registerMatchers(ast_matchers::MatchFinder *Finder) override; void check(const ast_matchers::MatchFinder::MatchResult &Result) override; @@ -33,4 +33,4 @@ class IfBlockSizeCheck : public ClangTidyCheck { } // namespace clang::tidy::readability -#endif // LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_READABILITY_IFBLOCKSIZECHECK_H +#endif // LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_READABILITY_BLOCKSIZECHECK_H diff --git a/clang-tools-extra/clang-tidy/readability/CMakeLists.txt b/clang-tools-extra/clang-tidy/readability/CMakeLists.txt index e7d38f6427a49..b326c733f4588 100644 --- a/clang-tools-extra/clang-tidy/readability/CMakeLists.txt +++ b/clang-tools-extra/clang-tidy/readability/CMakeLists.txt @@ -23,7 +23,7 @@ add_clang_library(clangTidyReadabilityModule STATIC FunctionSizeCheck.cpp IdentifierLengthCheck.cpp IdentifierNamingCheck.cpp - IfBlockSizeCheck.cpp + BlockSizeCheck.cpp ImplicitBoolConversionCheck.cpp InconsistentIfElseBracesCheck.cpp RedundantInlineSpecifierCheck.cpp diff --git a/clang-tools-extra/clang-tidy/readability/ReadabilityTidyModule.cpp b/clang-tools-extra/clang-tidy/readability/ReadabilityTidyModule.cpp index 67091551a4706..c1a06f1601dcc 100644 --- a/clang-tools-extra/clang-tidy/readability/ReadabilityTidyModule.cpp +++ b/clang-tools-extra/clang-tidy/readability/ReadabilityTidyModule.cpp @@ -27,7 +27,7 @@ #include "FunctionSizeCheck.h" #include "IdentifierLengthCheck.h" #include "IdentifierNamingCheck.h" -#include "IfBlockSizeCheck.h" +#include "BlockSizeCheck.h" #include "ImplicitBoolConversionCheck.h" #include "InconsistentDeclarationParameterNameCheck.h" #include "InconsistentIfElseBracesCheck.h" @@ -118,8 +118,8 @@ class ReadabilityModule : public ClangTidyModule { "readability-identifier-length"); CheckFactories.registerCheck<IdentifierNamingCheck>( "readability-identifier-naming"); - CheckFactories.registerCheck<IfBlockSizeCheck>( - "readability-if-block-size"); + CheckFactories.registerCheck<BlockSizeCheck>( + "readability-block-size"); CheckFactories.registerCheck<ImplicitBoolConversionCheck>( "readability-implicit-bool-conversion"); CheckFactories.registerCheck<InconsistentIfElseBracesCheck>( diff --git a/clang-tools-extra/docs/ReleaseNotes.md b/clang-tools-extra/docs/ReleaseNotes.md index 134660e3fd7db..503782883a72d 100644 --- a/clang-tools-extra/docs/ReleaseNotes.md +++ b/clang-tools-extra/docs/ReleaseNotes.md @@ -119,8 +119,8 @@ infrastructure are described first, followed by tool-specific sections. Finds uses of `#pragma comment` and, for `lib` or `linker` comments, suggests using the build system for improved portability. -- New {doc}`readability-if-block-size - <clang-tidy/checks/readability/if-block-size>` check. +- New {doc}`readability-block-size + <clang-tidy/checks/readability/block-size>` check. FIXME: Write a short description. diff --git a/clang-tools-extra/docs/clang-tidy/checks/list.md b/clang-tools-extra/docs/clang-tidy/checks/list.md index 7d824b1b5392b..a1028efbacfec 100644 --- a/clang-tools-extra/docs/clang-tidy/checks/list.md +++ b/clang-tools-extra/docs/clang-tidy/checks/list.md @@ -385,6 +385,7 @@ readability/* | {doc}`readability-avoid-nested-conditional-operator <readability/avoid-nested-conditional-operator>` | | | {doc}`readability-avoid-return-with-void-value <readability/avoid-return-with-void-value>` | Yes | | {doc}`readability-avoid-unconditional-preprocessor-if <readability/avoid-unconditional-preprocessor-if>` | | +| {doc}`readability-block-size <readability/block-size>` | | | {doc}`readability-braces-around-statements <readability/braces-around-statements>` | Yes | | {doc}`readability-const-return-type <readability/const-return-type>` | Yes | | {doc}`readability-container-contains <readability/container-contains>` | Yes | @@ -399,7 +400,6 @@ readability/* | {doc}`readability-function-size <readability/function-size>` | | | {doc}`readability-identifier-length <readability/identifier-length>` | | | {doc}`readability-identifier-naming <readability/identifier-naming>` | Yes | -| {doc}`readability-if-block-size <readability/if-block-size>` | Yes | | {doc}`readability-implicit-bool-conversion <readability/implicit-bool-conversion>` | Yes | | {doc}`readability-inconsistent-declaration-parameter-name <readability/inconsistent-declaration-parameter-name>` | Yes | | {doc}`readability-inconsistent-ifelse-braces <readability/inconsistent-ifelse-braces>` | Yes | diff --git a/clang-tools-extra/docs/clang-tidy/checks/readability/if-block-size.md b/clang-tools-extra/docs/clang-tidy/checks/readability/block-size.md similarity index 51% rename from clang-tools-extra/docs/clang-tidy/checks/readability/if-block-size.md rename to clang-tools-extra/docs/clang-tidy/checks/readability/block-size.md index 0289f5c11ce76..949ca40ebb010 100644 --- a/clang-tools-extra/docs/clang-tidy/checks/readability/if-block-size.md +++ b/clang-tools-extra/docs/clang-tidy/checks/readability/block-size.md @@ -1,6 +1,6 @@ -```{title} clang-tidy - readability-if-block-size +```{title} clang-tidy - readability-block-size ``` -# readability-if-block-size +# readability-block-size FIXME: Describe what patterns does the check detect and why. Give examples. diff --git a/clang-tools-extra/test/clang-tidy/checkers/readability/if-block-size.cpp b/clang-tools-extra/test/clang-tidy/checkers/readability/block-size.cpp similarity index 97% rename from clang-tools-extra/test/clang-tidy/checkers/readability/if-block-size.cpp rename to clang-tools-extra/test/clang-tidy/checkers/readability/block-size.cpp index 232b9dc021643..2345afcb56017 100644 --- a/clang-tools-extra/test/clang-tidy/checkers/readability/if-block-size.cpp +++ b/clang-tools-extra/test/clang-tidy/checkers/readability/block-size.cpp @@ -1,8 +1,8 @@ -// RUN: %check_clang_tidy %s readability-if-block-size %t +// RUN: %check_clang_tidy %s readability-block-size %t void should_warn(){ if (true){ // 1 -// CHECK-MESSAGES: :[[@LINE-1]]:5: warning: if block spans 21 lines of code, which exceeds the threshold of 20 lines [readability-if-block-size] +// CHECK-MESSAGES: :[[@LINE-1]]:5: warning: if block spans 21 lines of code, which exceeds the threshold of 20 lines [readability-block-size] int sum = 3 + 4 + 5 @@ -27,7 +27,7 @@ void should_warn(){ if (true){ // 1 int sum = 2; } else { // 3 1 -// CHECK-MESSAGES: :[[@LINE-1]]:12: warning: else block spans 21 lines of code, which exceeds the threshold of 20 lines [readability-if-block-size] +// CHECK-MESSAGES: :[[@LINE-1]]:12: warning: else block spans 21 lines of code, which exceeds the threshold of 20 lines [readability-block-size] int sum = 5 // 3 + 6 // 4 + 7 // 5 @@ -52,7 +52,7 @@ void should_warn(){ if (true){ // 1 int sum = 2; } else if (true){ // 1 -// CHECK-MESSAGES: :[[@LINE-1]]:12: warning: if block spans 21 lines of code, which exceeds the threshold of 20 lines [readability-if-block-size] +// CHECK-MESSAGES: :[[@LINE-1]]:12: warning: if block spans 21 lines of code, which exceeds the threshold of 20 lines [readability-block-size] int sum = 5 // 3 + 6 // 4 + 7 // 5 @@ -77,7 +77,7 @@ void should_warn(){ for (int i = 0; i < 10; ++i) { -// CHECK-MESSAGES: :[[@LINE-1]]:5: warning: for loop spans 21 lines of code, which exceeds the threshold of 20 lines [readability-if-block-size] +// CHECK-MESSAGES: :[[@LINE-1]]:5: warning: for loop spans 21 lines of code, which exceeds the threshold of 20 lines [readability-block-size] int sum = 3 + 4 + 5 @@ -99,7 +99,7 @@ void should_warn(){ } while (true) { -// CHECK-MESSAGES: :[[@LINE-1]]:5: warning: while loop spans 21 lines of code, which exceeds the threshold of 20 lines [readability-if-block-size] +// CHECK-MESSAGES: :[[@LINE-1]]:5: warning: while loop spans 21 lines of code, which exceeds the threshold of 20 lines [readability-block-size] int sum = 3 + 4 + 5 >From 87dfe4ca1de9814b74d0e6bbfa8fbace7301bc4f Mon Sep 17 00:00:00 2001 From: Alex Dutka <[email protected]> Date: Fri, 28 Aug 2026 23:30:43 +0200 Subject: [PATCH 07/11] replace the unique hardcoded threshold with proper options --- .../clang-tidy/readability/BlockSizeCheck.cpp | 35 +++- .../clang-tidy/readability/BlockSizeCheck.h | 8 +- .../checkers/readability/block-size.cpp | 187 ++++-------------- 3 files changed, 65 insertions(+), 165 deletions(-) diff --git a/clang-tools-extra/clang-tidy/readability/BlockSizeCheck.cpp b/clang-tools-extra/clang-tidy/readability/BlockSizeCheck.cpp index 5335c8c30b55d..971d3aee38b1a 100644 --- a/clang-tools-extra/clang-tidy/readability/BlockSizeCheck.cpp +++ b/clang-tools-extra/clang-tidy/readability/BlockSizeCheck.cpp @@ -15,6 +15,25 @@ using namespace clang::ast_matchers; namespace clang::tidy::readability { +const unsigned DefaultIfLineCountThreshold = 20; +const unsigned DefaultForLineCountThreshold = 30; +const unsigned DefaultWhileLineCountThreshold = 30; + +BlockSizeCheck::BlockSizeCheck(StringRef Name, ClangTidyContext *Context) + : ClangTidyCheck(Name, Context), + IfLineCountThreshold( + Options.get("IfLineCountThreshold", DefaultIfLineCountThreshold)), + ForLineCountThreshold( + Options.get("ForLineCountThreshold", DefaultForLineCountThreshold)), + WhileLineCountThreshold(Options.get("WhileLineCountThreshold", + DefaultWhileLineCountThreshold)) {} + +void BlockSizeCheck::storeOptions(ClangTidyOptions::OptionMap &Opts) { + Options.store(Opts, "IfLineCountThreshold", IfLineCountThreshold); + Options.store(Opts, "ForLineCountThreshold", ForLineCountThreshold); + Options.store(Opts, "WhileLineCountThreshold", WhileLineCountThreshold); +} + void BlockSizeCheck::registerMatchers(MatchFinder *Finder) { Finder->addMatcher(ifStmt().bind("if"), this); Finder->addMatcher(forStmt().bind("for"), this); @@ -36,11 +55,11 @@ void BlockSizeCheck::check(const MatchFinder::MatchResult &Result) { }(); const unsigned LineCount = LastLine - FirstLine + 1; - if (LineCount > LineCountThreshold) + if (LineCount > IfLineCountThreshold) diag(IfBlk->getBeginLoc(), "if block spans %0 lines of code, which exceeds " "the threshold of %1 lines") - << LineCount << LineCountThreshold; + << LineCount << IfLineCountThreshold; if (ElseBlk != nullptr && isa<CompoundStmt>(ElseBlk)) { // i.e. is not an else if @@ -48,11 +67,11 @@ void BlockSizeCheck::check(const MatchFinder::MatchResult &Result) { SrcMgr->getSpellingLineNumber(IfBlk->getEndLoc()); const unsigned ElseLineCount = ElseLastLine - LastLine + 1; - if (ElseLineCount > LineCountThreshold) + if (ElseLineCount > IfLineCountThreshold) diag(ElseBlk->getBeginLoc(), "else block spans %0 lines of code, which exceeds " "the threshold of %1 lines") - << ElseLineCount << LineCountThreshold; + << ElseLineCount << IfLineCountThreshold; } return; @@ -65,10 +84,10 @@ void BlockSizeCheck::check(const MatchFinder::MatchResult &Result) { SrcMgr->getSpellingLineNumber(ForLoop->getEndLoc()); const unsigned LineCount = LastLine - FirstLine + 1; - if (LineCount > LineCountThreshold) { + if (LineCount > ForLineCountThreshold) { diag(ForLoop->getBeginLoc(), "for loop spans %0 lines of code, which " "exceeds the threshold of %1 lines") - << LineCount << LineCountThreshold; + << LineCount << ForLineCountThreshold; } return; @@ -81,10 +100,10 @@ void BlockSizeCheck::check(const MatchFinder::MatchResult &Result) { SrcMgr->getSpellingLineNumber(WhileLoop->getEndLoc()); const unsigned LineCount = LastLine - FirstLine + 1; - if (LineCount > LineCountThreshold) { + if (LineCount > WhileLineCountThreshold) { diag(WhileLoop->getBeginLoc(), "while loop spans %0 lines of code, which " "exceeds the threshold of %1 lines") - << LineCount << LineCountThreshold; + << LineCount << WhileLineCountThreshold; } return; diff --git a/clang-tools-extra/clang-tidy/readability/BlockSizeCheck.h b/clang-tools-extra/clang-tidy/readability/BlockSizeCheck.h index acf4ffe7f8692..b6f1af55e1bfd 100644 --- a/clang-tools-extra/clang-tidy/readability/BlockSizeCheck.h +++ b/clang-tools-extra/clang-tidy/readability/BlockSizeCheck.h @@ -19,8 +19,8 @@ namespace clang::tidy::readability { /// https://clang.llvm.org/extra/clang-tidy/checks/readability/block-size.html class BlockSizeCheck : public ClangTidyCheck { public: - BlockSizeCheck(StringRef Name, ClangTidyContext *Context) - : ClangTidyCheck(Name, Context) {} + BlockSizeCheck(StringRef Name, ClangTidyContext *Context); + void storeOptions(ClangTidyOptions::OptionMap &Opts) override; void registerMatchers(ast_matchers::MatchFinder *Finder) override; void check(const ast_matchers::MatchFinder::MatchResult &Result) override; bool isLanguageVersionSupported(const LangOptions &LangOpts) const override { @@ -28,7 +28,9 @@ class BlockSizeCheck : public ClangTidyCheck { } private: - const unsigned LineCountThreshold = 20; + const unsigned IfLineCountThreshold; + const unsigned ForLineCountThreshold; + const unsigned WhileLineCountThreshold; }; } // namespace clang::tidy::readability diff --git a/clang-tools-extra/test/clang-tidy/checkers/readability/block-size.cpp b/clang-tools-extra/test/clang-tidy/checkers/readability/block-size.cpp index 2345afcb56017..c26a42c0ee9c2 100644 --- a/clang-tools-extra/test/clang-tidy/checkers/readability/block-size.cpp +++ b/clang-tools-extra/test/clang-tidy/checkers/readability/block-size.cpp @@ -1,123 +1,55 @@ -// RUN: %check_clang_tidy %s readability-block-size %t +// RUN: %check_clang_tidy %s readability-block-size %t \ +// RUN: -config='{CheckOptions: { \ +// RUN: readability-block-size.IfLineCountThreshold: 5, \ +// RUN: readability-block-size.ForLineCountThreshold: 6, \ +// RUN: readability-block-size.WhileLineCountThreshold: 7 }}' void should_warn(){ if (true){ // 1 -// CHECK-MESSAGES: :[[@LINE-1]]:5: warning: if block spans 21 lines of code, which exceeds the threshold of 20 lines [readability-block-size] +// CHECK-MESSAGES: :[[@LINE-1]]:5: warning: if block spans 6 lines of code, which exceeds the threshold of 5 lines [readability-block-size] int sum = 3 + 4 - + 5 - + 6 - + 7 - + 8 - + 9 - + 10 - + 11 - + 12 - + 13 - + 14 - + 15 - + 16 - + 17 - + 18 - + 19 - + 20; - } // 21 + + 5; + } // 6 if (true){ // 1 int sum = 2; - } else { // 3 1 -// CHECK-MESSAGES: :[[@LINE-1]]:12: warning: else block spans 21 lines of code, which exceeds the threshold of 20 lines [readability-block-size] - int sum = 5 // 3 - + 6 // 4 - + 7 // 5 - + 8 // 6 - + 9 // 7 - + 10 // 8 - + 11 // 9 - + 12 // 10 - + 13 // 11 - + 14 // 12 - + 15 // 13 - + 16 // 14 - + 17 // 15 - + 18 // 16 - + 19 // 17 - + 20 // 18 - + 21 // 19 - + 22; // 20 - } // 23 21 + } else { // 3 1 +// CHECK-MESSAGES: :[[@LINE-1]]:12: warning: else block spans 6 lines of code, which exceeds the threshold of 5 lines [readability-block-size] + int sum = 5 // 3 + + 6 // 4 + + 7; // 5 + } // 8 6 if (true){ // 1 int sum = 2; } else if (true){ // 1 -// CHECK-MESSAGES: :[[@LINE-1]]:12: warning: if block spans 21 lines of code, which exceeds the threshold of 20 lines [readability-block-size] +// CHECK-MESSAGES: :[[@LINE-1]]:12: warning: if block spans 6 lines of code, which exceeds the threshold of 5 lines [readability-block-size] int sum = 5 // 3 + 6 // 4 - + 7 // 5 - + 8 // 6 - + 9 // 7 - + 10 // 8 - + 11 // 9 - + 12 // 10 - + 13 // 11 - + 14 // 12 - + 15 // 13 - + 16 // 14 - + 17 // 15 - + 18 // 16 - + 19 // 17 - + 20 // 18 - + 21 // 19 - + 22; // 20 - } else { // 23 21 - int sum = 24; - } // 25 + + 7; // 5 + } else { // 8 6 + int sum = 9; + } // 10 for (int i = 0; i < 10; ++i) { -// CHECK-MESSAGES: :[[@LINE-1]]:5: warning: for loop spans 21 lines of code, which exceeds the threshold of 20 lines [readability-block-size] +// CHECK-MESSAGES: :[[@LINE-1]]:5: warning: for loop spans 7 lines of code, which exceeds the threshold of 6 lines [readability-block-size] int sum = 3 + 4 + 5 - + 6 - + 7 - + 8 - + 9 - + 10 - + 11 - + 12 - + 13 - + 14 - + 15 - + 16 - + 17 - + 18 - + 19 - + 20; + + 6; } while (true) { -// CHECK-MESSAGES: :[[@LINE-1]]:5: warning: while loop spans 21 lines of code, which exceeds the threshold of 20 lines [readability-block-size] +// CHECK-MESSAGES: :[[@LINE-1]]:5: warning: while loop spans 8 lines of code, which exceeds the threshold of 7 lines [readability-block-size] int sum = 3 + 4 + 5 + 6 - + 7 - + 8 - + 9 - + 10 - + 11 - + 12 - + 13 - + 14 - + 15 - + 16 - + 17 - + 18 - + 19 - + 20; + + 7; } } @@ -125,47 +57,21 @@ void should_not_warn(){ if (true){ // 1 int sum = 2 + 3 - + 4 - + 5 - + 6 - + 7 - + 8 - + 9 - + 10 - + 11 - + 12 - + 13 - + 14 - + 15 - + 16 - + 17 - + 18 - + 19; - } // 20 + + 4; + } // 5 bool a = true; bool b = false; if (a && b){ int sum = 2 - + 3 - + 4 - + 5 - + 6; + + 3; } else if (a || b) { - int sum = 8 - + 9 - + 10 - + 11 - + 12 - + 13 - + 14 - + 15; + int sum = 5 + + 6 + + 7; } else { - int sum = 17 - + 18 - + 19 - + 20 - + 21; + int sum = 9 + + 10; } @@ -173,21 +79,7 @@ void should_not_warn(){ int sum = 2 + 3 + 4 - + 5 - + 6 - + 7 - + 8 - + 9 - + 10 - + 11 - + 12 - + 13 - + 14 - + 15 - + 16 - + 17 - + 18 - + 19; + + 5; } while (true) { @@ -195,19 +87,6 @@ void should_not_warn(){ + 3 + 4 + 5 - + 6 - + 7 - + 8 - + 9 - + 10 - + 11 - + 12 - + 13 - + 14 - + 15 - + 16 - + 17 - + 18 - + 19; + + 6; } } >From 983a3a1cac7ae9bfb1b36521ce325b82468d0392 Mon Sep 17 00:00:00 2001 From: Alex Dutka <[email protected]> Date: Fri, 28 Aug 2026 23:44:20 +0200 Subject: [PATCH 08/11] add documentation --- clang-tools-extra/docs/ReleaseNotes.md | 3 +- .../checks/readability/block-size.md | 33 ++++++++++++++++++- 2 files changed, 34 insertions(+), 2 deletions(-) diff --git a/clang-tools-extra/docs/ReleaseNotes.md b/clang-tools-extra/docs/ReleaseNotes.md index 503782883a72d..ac2a3a82eff74 100644 --- a/clang-tools-extra/docs/ReleaseNotes.md +++ b/clang-tools-extra/docs/ReleaseNotes.md @@ -122,7 +122,8 @@ infrastructure are described first, followed by tool-specific sections. - New {doc}`readability-block-size <clang-tidy/checks/readability/block-size>` check. - FIXME: Write a short description. + Warns on `if`, `else`, `for` and `while` blocks which exceed a given number + of lines of code. - New {doc}`readability-redundant-zero-initializer <clang-tidy/checks/readability/redundant-zero-initializer>` check. diff --git a/clang-tools-extra/docs/clang-tidy/checks/readability/block-size.md b/clang-tools-extra/docs/clang-tidy/checks/readability/block-size.md index 949ca40ebb010..6bb230ac7f365 100644 --- a/clang-tools-extra/docs/clang-tidy/checks/readability/block-size.md +++ b/clang-tools-extra/docs/clang-tidy/checks/readability/block-size.md @@ -3,4 +3,35 @@ # readability-block-size -FIXME: Describe what patterns does the check detect and why. Give examples. +This check warns when `if`, `else`, `for` or `while` blocks exceed a given +number of lines of code, and thus flags control flow structures which are +likely difficult to reason about due to their size. + +```cpp +// This block will raise a warning if N > IfLineCountThreshold +if (some_condition()){ // line #1 + call_some_fn(); // line #2 + // ... + do_something_else(); // line #N-1 +} // line #N +``` + +## Options + +```{option} IfLineCountThreshold + +This option sets the number of lines of code beyond which an `if` (or `else`) +block will be flagged as too long. The default value is 20. +``` + +```{option} ForLineCountThreshold + +This option sets the number of lines of code beyond which a `for` loop will be +flagged as too long. The default value is 30. +``` + +```{option} WhileLineCountThreshold + +This option sets the number of lines of code beyond which a `while` loop will +be flagged as too long. The default value is 30. +``` >From e13530084026160434dfaaec497f27ab6704f105 Mon Sep 17 00:00:00 2001 From: Alex Dutka <[email protected]> Date: Sat, 29 Aug 2026 00:32:42 +0200 Subject: [PATCH 09/11] format --- .../clang-tidy/readability/ReadabilityTidyModule.cpp | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/clang-tools-extra/clang-tidy/readability/ReadabilityTidyModule.cpp b/clang-tools-extra/clang-tidy/readability/ReadabilityTidyModule.cpp index c1a06f1601dcc..429a060842cff 100644 --- a/clang-tools-extra/clang-tidy/readability/ReadabilityTidyModule.cpp +++ b/clang-tools-extra/clang-tidy/readability/ReadabilityTidyModule.cpp @@ -13,6 +13,7 @@ #include "AvoidNestedConditionalOperatorCheck.h" #include "AvoidReturnWithVoidValueCheck.h" #include "AvoidUnconditionalPreprocessorIfCheck.h" +#include "BlockSizeCheck.h" #include "BracesAroundStatementsCheck.h" #include "ConstReturnTypeCheck.h" #include "ContainerContainsCheck.h" @@ -27,7 +28,6 @@ #include "FunctionSizeCheck.h" #include "IdentifierLengthCheck.h" #include "IdentifierNamingCheck.h" -#include "BlockSizeCheck.h" #include "ImplicitBoolConversionCheck.h" #include "InconsistentDeclarationParameterNameCheck.h" #include "InconsistentIfElseBracesCheck.h" @@ -118,8 +118,7 @@ class ReadabilityModule : public ClangTidyModule { "readability-identifier-length"); CheckFactories.registerCheck<IdentifierNamingCheck>( "readability-identifier-naming"); - CheckFactories.registerCheck<BlockSizeCheck>( - "readability-block-size"); + CheckFactories.registerCheck<BlockSizeCheck>("readability-block-size"); CheckFactories.registerCheck<ImplicitBoolConversionCheck>( "readability-implicit-bool-conversion"); CheckFactories.registerCheck<InconsistentIfElseBracesCheck>( >From b3c47be200432bdf27574ad91e970eea52ca303f Mon Sep 17 00:00:00 2001 From: Alex Dutka <[email protected]> Date: Sat, 29 Aug 2026 17:53:47 +0200 Subject: [PATCH 10/11] Apply batched suggestions from code review Co-authored-by: EugeneZelenko <[email protected]> --- .../docs/clang-tidy/checks/readability/block-size.md | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/clang-tools-extra/docs/clang-tidy/checks/readability/block-size.md b/clang-tools-extra/docs/clang-tidy/checks/readability/block-size.md index 6bb230ac7f365..7f2379bf4decd 100644 --- a/clang-tools-extra/docs/clang-tidy/checks/readability/block-size.md +++ b/clang-tools-extra/docs/clang-tidy/checks/readability/block-size.md @@ -21,17 +21,17 @@ if (some_condition()){ // line #1 ```{option} IfLineCountThreshold This option sets the number of lines of code beyond which an `if` (or `else`) -block will be flagged as too long. The default value is 20. +block will be flagged as too long. The default value is `20`. ``` ```{option} ForLineCountThreshold This option sets the number of lines of code beyond which a `for` loop will be -flagged as too long. The default value is 30. +flagged as too long. The default value is `30`. ``` ```{option} WhileLineCountThreshold This option sets the number of lines of code beyond which a `while` loop will -be flagged as too long. The default value is 30. +be flagged as too long. The default value is `30`. ``` >From e76c552f489a2aee6afc38928b5fb4b1eaf46b49 Mon Sep 17 00:00:00 2001 From: Alex Dutka <[email protected]> Date: Sat, 29 Aug 2026 17:58:53 +0200 Subject: [PATCH 11/11] Remove "this check" --- .../docs/clang-tidy/checks/readability/block-size.md | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/clang-tools-extra/docs/clang-tidy/checks/readability/block-size.md b/clang-tools-extra/docs/clang-tidy/checks/readability/block-size.md index 7f2379bf4decd..4eb859cd55924 100644 --- a/clang-tools-extra/docs/clang-tidy/checks/readability/block-size.md +++ b/clang-tools-extra/docs/clang-tidy/checks/readability/block-size.md @@ -3,9 +3,9 @@ # readability-block-size -This check warns when `if`, `else`, `for` or `while` blocks exceed a given -number of lines of code, and thus flags control flow structures which are -likely difficult to reason about due to their size. +Warns when `if`, `else`, `for` or `while` blocks exceed a given number of lines +of code, and thus flags control flow structures which are likely difficult to +reason about due to their size. ```cpp // This block will raise a warning if N > IfLineCountThreshold _______________________________________________ cfe-commits mailing list [email protected] https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
