https://github.com/dutkalex updated https://github.com/llvm/llvm-project/pull/185319
>From 639e834da6e99be43f93f5409669b65b1a326357 Mon Sep 17 00:00:00 2001 From: Alex Dutka <[email protected]> Date: Sun, 8 Mar 2026 19:47:13 +0100 Subject: [PATCH 1/6] Update the readability-identifier-length test file to account for the LineCountThreshold option --- .../readability/identifier-length.cpp | 33 ++++++++++++------- 1 file changed, 21 insertions(+), 12 deletions(-) diff --git a/clang-tools-extra/test/clang-tidy/checkers/readability/identifier-length.cpp b/clang-tools-extra/test/clang-tidy/checkers/readability/identifier-length.cpp index 33b0ac7ce7aa3..1972862d05f3e 100644 --- a/clang-tools-extra/test/clang-tidy/checkers/readability/identifier-length.cpp +++ b/clang-tools-extra/test/clang-tidy/checkers/readability/identifier-length.cpp @@ -1,6 +1,6 @@ // RUN: %check_clang_tidy %s readability-identifier-length %t \ // RUN: -config='{CheckOptions: \ -// RUN: {readability-identifier-length.IgnoredVariableNames: "^[xy]$"}}' \ +// RUN: {readability-identifier-length.IgnoredVariableNames: "^[xy]$", readability-identifier-length.LineCountThreshold: 1}}' \ // RUN: -- -fexceptions struct myexcept { @@ -11,7 +11,8 @@ struct simpleexcept { int other; }; -void doIt(); +template<typename... Ts> +void doIt(Ts...); void tooShortVariableNames(int z) // CHECK-MESSAGES: :[[@LINE-1]]:32: warning: parameter name 'z' is too short, expected at least 3 characters [readability-identifier-length] @@ -25,39 +26,47 @@ void tooShortVariableNames(int z) for (int m = 0; m < 5; ++m) // CHECK-MESSAGES: :[[@LINE-1]]:12: warning: loop variable name 'm' is too short, expected at least 2 characters [readability-identifier-length] { - doIt(); + doIt(i, jj, m); } try { - doIt(); + doIt(z); } catch (const myexcept &x) // CHECK-MESSAGES: :[[@LINE-1]]:28: warning: exception variable name 'x' is too short, expected at least 2 characters [readability-identifier-length] { - doIt(); + doIt(x); } } -void longEnoughVariableNames(int n) // argument 'n' ignored by default configuration +void longEnoughVariableNames(int n, int m) // argument 'n' ignored by default configuration, 'm' is only used on this line { int var = 5; for (int i = 0; i < 42; ++i) // 'i' is default allowed, for historical reasons { - doIt(); + doIt(var, i); + } + + for (int a = 0; a < 42; ++a) // 'a' is only used on this line + { + doIt(); } for (int kk = 0; kk < 42; ++kk) { - doIt(); + doIt(kk); } try { - doIt(); + doIt(n); } catch (const simpleexcept &e) // ignored by default configuration { - doIt(); + doIt(e); } catch (const myexcept &ex) { - doIt(); - } + doIt(ex); + } catch (const int &d) { doIt(d); } // 'd' is only used on this line int x = 5; // ignored by configuration + ++x; + + int b = 0; // 'b' is only used on this line } >From 46030ba3d8b594f3300ff8949283e534b6b24a7c Mon Sep 17 00:00:00 2001 From: Alex Dutka <[email protected]> Date: Sun, 8 Mar 2026 19:49:24 +0100 Subject: [PATCH 2/6] Implement the count of lines until last use to allow for short identifiers if their scope is limited --- .../readability/IdentifierLengthCheck.cpp | 49 ++++++++++++++++++- .../readability/IdentifierLengthCheck.h | 2 + 2 files changed, 50 insertions(+), 1 deletion(-) diff --git a/clang-tools-extra/clang-tidy/readability/IdentifierLengthCheck.cpp b/clang-tools-extra/clang-tidy/readability/IdentifierLengthCheck.cpp index a6204de16224d..4755588b70d18 100644 --- a/clang-tools-extra/clang-tidy/readability/IdentifierLengthCheck.cpp +++ b/clang-tools-extra/clang-tidy/readability/IdentifierLengthCheck.cpp @@ -21,6 +21,7 @@ const char DefaultIgnoredLoopCounterNames[] = "^[ijk_]$"; const char DefaultIgnoredVariableNames[] = ""; const char DefaultIgnoredExceptionVariableNames[] = "^[e]$"; const char DefaultIgnoredParameterNames[] = "^[n]$"; +const unsigned DefaultLineCountThreshold = 0; const char ErrorMessage[] = "%select{variable|exception variable|loop variable|" @@ -49,7 +50,8 @@ IdentifierLengthCheck::IdentifierLengthCheck(StringRef Name, IgnoredExceptionVariableNames(IgnoredExceptionVariableNamesInput), IgnoredParameterNamesInput( Options.get("IgnoredParameterNames", DefaultIgnoredParameterNames)), - IgnoredParameterNames(IgnoredParameterNamesInput) {} + IgnoredParameterNames(IgnoredParameterNamesInput), + LineCountThreshold(Options.get("LineCountThreshold", DefaultLineCountThreshold)) {} void IdentifierLengthCheck::storeOptions(ClangTidyOptions::OptionMap &Opts) { Options.store(Opts, "MinimumVariableNameLength", MinimumVariableNameLength); @@ -62,6 +64,7 @@ void IdentifierLengthCheck::storeOptions(ClangTidyOptions::OptionMap &Opts) { Options.store(Opts, "IgnoredExceptionVariableNames", IgnoredExceptionVariableNamesInput); Options.store(Opts, "IgnoredParameterNames", IgnoredParameterNamesInput); + Options.store(Opts, "LineCountThreshold", LineCountThreshold); } void IdentifierLengthCheck::registerMatchers(MatchFinder *Finder) { @@ -85,6 +88,38 @@ void IdentifierLengthCheck::registerMatchers(MatchFinder *Finder) { this); } +static unsigned countLinesToLastUse(const VarDecl* Var, const SourceManager* SrcMgr, ASTContext* Ctx){ + const unsigned DeclLine = SrcMgr->getSpellingLineNumber(Var->getLocation()); + + class VarUseCallback : public MatchFinder::MatchCallback { + private: + unsigned* LastUseLineNumber; + + public: + explicit VarUseCallback(unsigned* Output): LastUseLineNumber{Output} {} + + void run(const MatchFinder::MatchResult &Result) override { + const DeclRefExpr *Use = Result.Nodes.getNodeAs<DeclRefExpr>("varUse"); + if (Use && LastUseLineNumber) { + auto Loc = Use->getLocation(); + unsigned UseLine = Result.SourceManager->getSpellingLineNumber(Loc); + *LastUseLineNumber = std::max(*LastUseLineNumber, UseLine); + } + } + }; + + unsigned LastUseLine = DeclLine; + VarUseCallback Callback{&LastUseLine}; + + auto Matcher = declRefExpr(to(varDecl(equalsNode(Var)))).bind("varUse"); + + MatchFinder Finder; + Finder.addMatcher(Matcher, &Callback); + Finder.matchAST(*Ctx); + + return LastUseLine - DeclLine + 1; +} + void IdentifierLengthCheck::check(const MatchFinder::MatchResult &Result) { const auto *StandaloneVar = Result.Nodes.getNodeAs<VarDecl>("standaloneVar"); if (StandaloneVar) { @@ -97,6 +132,9 @@ void IdentifierLengthCheck::check(const MatchFinder::MatchResult &Result) { IgnoredVariableNames.match(VarName)) return; + if (LineCountThreshold > 0 && countLinesToLastUse(StandaloneVar, Result.SourceManager, Result.Context) <= LineCountThreshold) + return; + diag(StandaloneVar->getLocation(), ErrorMessage) << 0 << StandaloneVar << MinimumVariableNameLength; } @@ -111,6 +149,9 @@ void IdentifierLengthCheck::check(const MatchFinder::MatchResult &Result) { IgnoredExceptionVariableNames.match(VarName)) return; + if (LineCountThreshold > 0 && countLinesToLastUse(ExceptionVarName, Result.SourceManager, Result.Context) <= LineCountThreshold) + return; + diag(ExceptionVarName->getLocation(), ErrorMessage) << 1 << ExceptionVarName << MinimumExceptionNameLength; } @@ -126,6 +167,9 @@ void IdentifierLengthCheck::check(const MatchFinder::MatchResult &Result) { IgnoredLoopCounterNames.match(VarName)) return; + if (LineCountThreshold > 0 && countLinesToLastUse(LoopVar, Result.SourceManager, Result.Context) <= LineCountThreshold) + return; + diag(LoopVar->getLocation(), ErrorMessage) << 2 << LoopVar << MinimumLoopCounterNameLength; } @@ -141,6 +185,9 @@ void IdentifierLengthCheck::check(const MatchFinder::MatchResult &Result) { IgnoredParameterNames.match(VarName)) return; + if (LineCountThreshold > 0 && countLinesToLastUse(ParamVar, Result.SourceManager, Result.Context) <= LineCountThreshold) + return; + diag(ParamVar->getLocation(), ErrorMessage) << 3 << ParamVar << MinimumParameterNameLength; } diff --git a/clang-tools-extra/clang-tidy/readability/IdentifierLengthCheck.h b/clang-tools-extra/clang-tidy/readability/IdentifierLengthCheck.h index 3adaf50bc57a1..2a59788260f8c 100644 --- a/clang-tools-extra/clang-tidy/readability/IdentifierLengthCheck.h +++ b/clang-tools-extra/clang-tidy/readability/IdentifierLengthCheck.h @@ -42,6 +42,8 @@ class IdentifierLengthCheck : public ClangTidyCheck { std::string IgnoredParameterNamesInput; llvm::Regex IgnoredParameterNames; + + const unsigned LineCountThreshold; }; } // namespace clang::tidy::readability >From ab5af5e216096827158bf36421b60b0cd6927a7b Mon Sep 17 00:00:00 2001 From: Alex Dutka <[email protected]> Date: Sun, 8 Mar 2026 22:53:59 +0100 Subject: [PATCH 3/6] Document the added option --- .../checks/readability/identifier-length.rst | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/clang-tools-extra/docs/clang-tidy/checks/readability/identifier-length.rst b/clang-tools-extra/docs/clang-tidy/checks/readability/identifier-length.rst index c4d39a28a4cb8..ad1450fdb84bb 100644 --- a/clang-tools-extra/docs/clang-tidy/checks/readability/identifier-length.rst +++ b/clang-tools-extra/docs/clang-tidy/checks/readability/identifier-length.rst @@ -18,6 +18,7 @@ The following options are described below: - :option:`MinimumLoopCounterNameLength`, :option:`IgnoredLoopCounterNames` - :option:`MinimumExceptionNameLength`, :option:`IgnoredExceptionVariableNames` + - :option:`LineCountThreshold` .. option:: MinimumVariableNameLength @@ -121,3 +122,16 @@ The following options are described below: catch (const std::exception& e) { // ... } + +.. option:: LineCountThreshold + + Defines the minimum number of lines required between declaration and last + use for a diagnostic to be issued. The default value is 0. + + .. code-block:: c++ + + // In this example, a warning will be issued if LineCountThreshold < N + int a = 0; // First line (declaration line) + a = 1; // Second line + // ... + last_use_of(a); // N-th line >From 8d5dcabb0d20f69d0513d4c2790f4bab66080f21 Mon Sep 17 00:00:00 2001 From: Alex Dutka <[email protected]> Date: Mon, 9 Mar 2026 09:16:49 +0100 Subject: [PATCH 4/6] Apply fixes suggested by clang-tidy --- .../clang-tidy/readability/IdentifierLengthCheck.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/clang-tools-extra/clang-tidy/readability/IdentifierLengthCheck.cpp b/clang-tools-extra/clang-tidy/readability/IdentifierLengthCheck.cpp index 4755588b70d18..fc0d112d53ff1 100644 --- a/clang-tools-extra/clang-tidy/readability/IdentifierLengthCheck.cpp +++ b/clang-tools-extra/clang-tidy/readability/IdentifierLengthCheck.cpp @@ -99,10 +99,10 @@ static unsigned countLinesToLastUse(const VarDecl* Var, const SourceManager* Src explicit VarUseCallback(unsigned* Output): LastUseLineNumber{Output} {} void run(const MatchFinder::MatchResult &Result) override { - const DeclRefExpr *Use = Result.Nodes.getNodeAs<DeclRefExpr>("varUse"); + const auto *Use = Result.Nodes.getNodeAs<DeclRefExpr>("varUse"); if (Use && LastUseLineNumber) { auto Loc = Use->getLocation(); - unsigned UseLine = Result.SourceManager->getSpellingLineNumber(Loc); + const unsigned UseLine = Result.SourceManager->getSpellingLineNumber(Loc); *LastUseLineNumber = std::max(*LastUseLineNumber, UseLine); } } >From 61bee8adf80e0862f8b2018a9755879bf1fe3cd8 Mon Sep 17 00:00:00 2001 From: Alex Dutka <[email protected]> Date: Mon, 9 Mar 2026 10:06:48 +0100 Subject: [PATCH 5/6] Add a ReleaseNotes entry --- clang-tools-extra/docs/ReleaseNotes.rst | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/clang-tools-extra/docs/ReleaseNotes.rst b/clang-tools-extra/docs/ReleaseNotes.rst index 6e1a116a30bf8..767bdf73901d7 100644 --- a/clang-tools-extra/docs/ReleaseNotes.rst +++ b/clang-tools-extra/docs/ReleaseNotes.rst @@ -330,6 +330,11 @@ Changes in existing checks <clang-tidy/checks/readability/suspicious-call-argument>` check by avoiding a crash from invalid ``Abbreviations`` option. +- Improve :doc:`readability-identifier-length + <clang-tidy/checks/readability/readability-identifier-length>` check by adding + a new option to silence warnings for short-lived variables, based on distance + between declaration and last use. + Removed checks ^^^^^^^^^^^^^^ >From a0db70839924e091b0422413736362befb464b4f Mon Sep 17 00:00:00 2001 From: Alex Dutka <[email protected]> Date: Mon, 9 Mar 2026 10:10:08 +0100 Subject: [PATCH 6/6] Apply formatting --- .../readability/IdentifierLengthCheck.cpp | 34 +++++++++++++------ 1 file changed, 23 insertions(+), 11 deletions(-) diff --git a/clang-tools-extra/clang-tidy/readability/IdentifierLengthCheck.cpp b/clang-tools-extra/clang-tidy/readability/IdentifierLengthCheck.cpp index fc0d112d53ff1..9a1e267c9b451 100644 --- a/clang-tools-extra/clang-tidy/readability/IdentifierLengthCheck.cpp +++ b/clang-tools-extra/clang-tidy/readability/IdentifierLengthCheck.cpp @@ -51,7 +51,8 @@ IdentifierLengthCheck::IdentifierLengthCheck(StringRef Name, IgnoredParameterNamesInput( Options.get("IgnoredParameterNames", DefaultIgnoredParameterNames)), IgnoredParameterNames(IgnoredParameterNamesInput), - LineCountThreshold(Options.get("LineCountThreshold", DefaultLineCountThreshold)) {} + LineCountThreshold( + Options.get("LineCountThreshold", DefaultLineCountThreshold)) {} void IdentifierLengthCheck::storeOptions(ClangTidyOptions::OptionMap &Opts) { Options.store(Opts, "MinimumVariableNameLength", MinimumVariableNameLength); @@ -88,21 +89,24 @@ void IdentifierLengthCheck::registerMatchers(MatchFinder *Finder) { this); } -static unsigned countLinesToLastUse(const VarDecl* Var, const SourceManager* SrcMgr, ASTContext* Ctx){ +static unsigned countLinesToLastUse(const VarDecl *Var, + const SourceManager *SrcMgr, + ASTContext *Ctx) { const unsigned DeclLine = SrcMgr->getSpellingLineNumber(Var->getLocation()); class VarUseCallback : public MatchFinder::MatchCallback { - private: - unsigned* LastUseLineNumber; + private: + unsigned *LastUseLineNumber; - public: - explicit VarUseCallback(unsigned* Output): LastUseLineNumber{Output} {} + public: + explicit VarUseCallback(unsigned *Output) : LastUseLineNumber{Output} {} void run(const MatchFinder::MatchResult &Result) override { const auto *Use = Result.Nodes.getNodeAs<DeclRefExpr>("varUse"); if (Use && LastUseLineNumber) { auto Loc = Use->getLocation(); - const unsigned UseLine = Result.SourceManager->getSpellingLineNumber(Loc); + const unsigned UseLine = + Result.SourceManager->getSpellingLineNumber(Loc); *LastUseLineNumber = std::max(*LastUseLineNumber, UseLine); } } @@ -132,7 +136,9 @@ void IdentifierLengthCheck::check(const MatchFinder::MatchResult &Result) { IgnoredVariableNames.match(VarName)) return; - if (LineCountThreshold > 0 && countLinesToLastUse(StandaloneVar, Result.SourceManager, Result.Context) <= LineCountThreshold) + if (LineCountThreshold > 0 && + countLinesToLastUse(StandaloneVar, Result.SourceManager, + Result.Context) <= LineCountThreshold) return; diag(StandaloneVar->getLocation(), ErrorMessage) @@ -149,7 +155,9 @@ void IdentifierLengthCheck::check(const MatchFinder::MatchResult &Result) { IgnoredExceptionVariableNames.match(VarName)) return; - if (LineCountThreshold > 0 && countLinesToLastUse(ExceptionVarName, Result.SourceManager, Result.Context) <= LineCountThreshold) + if (LineCountThreshold > 0 && + countLinesToLastUse(ExceptionVarName, Result.SourceManager, + Result.Context) <= LineCountThreshold) return; diag(ExceptionVarName->getLocation(), ErrorMessage) @@ -167,7 +175,9 @@ void IdentifierLengthCheck::check(const MatchFinder::MatchResult &Result) { IgnoredLoopCounterNames.match(VarName)) return; - if (LineCountThreshold > 0 && countLinesToLastUse(LoopVar, Result.SourceManager, Result.Context) <= LineCountThreshold) + if (LineCountThreshold > 0 && + countLinesToLastUse(LoopVar, Result.SourceManager, Result.Context) <= + LineCountThreshold) return; diag(LoopVar->getLocation(), ErrorMessage) @@ -185,7 +195,9 @@ void IdentifierLengthCheck::check(const MatchFinder::MatchResult &Result) { IgnoredParameterNames.match(VarName)) return; - if (LineCountThreshold > 0 && countLinesToLastUse(ParamVar, Result.SourceManager, Result.Context) <= LineCountThreshold) + if (LineCountThreshold > 0 && + countLinesToLastUse(ParamVar, Result.SourceManager, Result.Context) <= + LineCountThreshold) return; diag(ParamVar->getLocation(), ErrorMessage) _______________________________________________ cfe-commits mailing list [email protected] https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
