[clang-tools-extra] [clang-tidy][readability-identifier-length] Add a line count threshold (PR #185319)
Alex Dutka via cfe-commits
cfe-commits at lists.llvm.org
Sat Apr 11 10:35:16 PDT 2026
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 <97711898+dutkalex at users.noreply.github.com>
Date: Sun, 8 Mar 2026 19:47:13 +0100
Subject: [PATCH 01/13] 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 <97711898+dutkalex at users.noreply.github.com>
Date: Sun, 8 Mar 2026 19:49:24 +0100
Subject: [PATCH 02/13] 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 <97711898+dutkalex at users.noreply.github.com>
Date: Sun, 8 Mar 2026 22:53:59 +0100
Subject: [PATCH 03/13] 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 <97711898+dutkalex at users.noreply.github.com>
Date: Mon, 9 Mar 2026 09:16:49 +0100
Subject: [PATCH 04/13] 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 <97711898+dutkalex at users.noreply.github.com>
Date: Mon, 9 Mar 2026 10:06:48 +0100
Subject: [PATCH 05/13] 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 <97711898+dutkalex at users.noreply.github.com>
Date: Mon, 9 Mar 2026 10:10:08 +0100
Subject: [PATCH 06/13] 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)
>From f80dc4032533328da90c3a26e7c778219dac24cb Mon Sep 17 00:00:00 2001
From: Alex Dutka <97711898+dutkalex at users.noreply.github.com>
Date: Tue, 10 Mar 2026 09:08:08 +0100
Subject: [PATCH 07/13] Fix release note ordering
---
clang-tools-extra/docs/ReleaseNotes.rst | 10 +++++-----
1 file changed, 5 insertions(+), 5 deletions(-)
diff --git a/clang-tools-extra/docs/ReleaseNotes.rst b/clang-tools-extra/docs/ReleaseNotes.rst
index 767bdf73901d7..5ffbf7d23de0e 100644
--- a/clang-tools-extra/docs/ReleaseNotes.rst
+++ b/clang-tools-extra/docs/ReleaseNotes.rst
@@ -312,6 +312,11 @@ Changes in existing checks
now uses separate note diagnostics for each uninitialized enumerator, making
it easier to see which specific enumerators need explicit initialization.
+- Improved :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.
+
- Improved :doc:`readability-non-const-parameter
<clang-tidy/checks/readability/non-const-parameter>` check by avoiding false
positives on parameters used in dependent expressions (e.g. inside generic
@@ -330,11 +335,6 @@ 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 2b57d073ac31a398113185b9c47cea4640a58817 Mon Sep 17 00:00:00 2001
From: Alex Dutka <97711898+dutkalex at users.noreply.github.com>
Date: Sun, 15 Mar 2026 15:44:57 +0100
Subject: [PATCH 08/13] Fix path error in the release notes
---
clang-tools-extra/docs/ReleaseNotes.rst | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/clang-tools-extra/docs/ReleaseNotes.rst b/clang-tools-extra/docs/ReleaseNotes.rst
index 5ffbf7d23de0e..12116b688ff46 100644
--- a/clang-tools-extra/docs/ReleaseNotes.rst
+++ b/clang-tools-extra/docs/ReleaseNotes.rst
@@ -313,8 +313,8 @@ Changes in existing checks
it easier to see which specific enumerators need explicit initialization.
- Improved :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
+ <clang-tidy/checks/readability/identifier-length>` check by adding a new
+ option to silence warnings for short-lived variables, based on distance
between declaration and last use.
- Improved :doc:`readability-non-const-parameter
>From d1ca409ccc87ecf6741206e89862c519b8d2f330 Mon Sep 17 00:00:00 2001
From: Alex Dutka <97711898+dutkalex at users.noreply.github.com>
Date: Fri, 10 Apr 2026 14:02:34 +0200
Subject: [PATCH 09/13] move line count test to a dedicated file
---
...identifier-length-line-count-threshold.cpp | 52 +++++++++++++++++++
.../readability/identifier-length.cpp | 33 +++++-------
2 files changed, 64 insertions(+), 21 deletions(-)
create mode 100644 clang-tools-extra/test/clang-tidy/checkers/readability/identifier-length-line-count-threshold.cpp
diff --git a/clang-tools-extra/test/clang-tidy/checkers/readability/identifier-length-line-count-threshold.cpp b/clang-tools-extra/test/clang-tidy/checkers/readability/identifier-length-line-count-threshold.cpp
new file mode 100644
index 0000000000000..6848ecc455788
--- /dev/null
+++ b/clang-tools-extra/test/clang-tidy/checkers/readability/identifier-length-line-count-threshold.cpp
@@ -0,0 +1,52 @@
+// RUN: %check_clang_tidy %s readability-identifier-length %t \
+// RUN: -config='{CheckOptions: \
+// RUN: {readability-identifier-length.LineCountThreshold: 3}}' \
+// RUN: -- -fexceptions
+
+struct myexcept {
+ int val;
+};
+
+template<typename... Ts>
+void doIt(Ts...);
+
+void shouldWarn(int z)
+// CHECK-MESSAGES: :[[@LINE-1]]:32: warning: parameter name 'z' is too short, expected at least 3 characters [readability-identifier-length]
+{
+ int i = 5;
+ // CHECK-MESSAGES: :[[@LINE-1]]:7: warning: variable name 'i' is too short, expected at least 3 characters [readability-identifier-length]
+
+ 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(i);
+ doIt(m);
+ }
+
+ try {
+ 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(x);
+ }
+}
+
+void shouldNotWarn(int m)
+{
+ doIt(m);
+
+ int v = 5;
+ doIt(v);
+
+ for (int a = 0; a < 42; ++a)
+ {
+ doIt(a);
+ }
+
+ try {
+ doIt();
+ } catch (const myexcept &x) {
+ doIt(x);
+ }
+}
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 1972862d05f3e..33b0ac7ce7aa3 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]$", readability-identifier-length.LineCountThreshold: 1}}' \
+// RUN: {readability-identifier-length.IgnoredVariableNames: "^[xy]$"}}' \
// RUN: -- -fexceptions
struct myexcept {
@@ -11,8 +11,7 @@ struct simpleexcept {
int other;
};
-template<typename... Ts>
-void doIt(Ts...);
+void doIt();
void tooShortVariableNames(int z)
// CHECK-MESSAGES: :[[@LINE-1]]:32: warning: parameter name 'z' is too short, expected at least 3 characters [readability-identifier-length]
@@ -26,47 +25,39 @@ 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(i, jj, m);
+ doIt();
}
try {
- doIt(z);
+ doIt();
} 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(x);
+ doIt();
}
}
-void longEnoughVariableNames(int n, int m) // argument 'n' ignored by default configuration, 'm' is only used on this line
+void longEnoughVariableNames(int n) // argument 'n' ignored by default configuration
{
int var = 5;
for (int i = 0; i < 42; ++i) // 'i' is default allowed, for historical reasons
{
- doIt(var, i);
- }
-
- for (int a = 0; a < 42; ++a) // 'a' is only used on this line
- {
- doIt();
+ doIt();
}
for (int kk = 0; kk < 42; ++kk) {
- doIt(kk);
+ doIt();
}
try {
- doIt(n);
+ doIt();
} catch (const simpleexcept &e) // ignored by default configuration
{
- doIt(e);
+ doIt();
} catch (const myexcept &ex) {
- doIt(ex);
- } catch (const int &d) { doIt(d); } // 'd' is only used on this line
+ doIt();
+ }
int x = 5; // ignored by configuration
- ++x;
-
- int b = 0; // 'b' is only used on this line
}
>From 1541b121699f08d7284fda920bf07c85124b2eb8 Mon Sep 17 00:00:00 2001
From: Alex Dutka <97711898+dutkalex at users.noreply.github.com>
Date: Sat, 11 Apr 2026 17:09:57 +0200
Subject: [PATCH 10/13] fix expected message
---
.../readability/identifier-length-line-count-threshold.cpp | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/clang-tools-extra/test/clang-tidy/checkers/readability/identifier-length-line-count-threshold.cpp b/clang-tools-extra/test/clang-tidy/checkers/readability/identifier-length-line-count-threshold.cpp
index 6848ecc455788..fbeed11b4a8cd 100644
--- a/clang-tools-extra/test/clang-tidy/checkers/readability/identifier-length-line-count-threshold.cpp
+++ b/clang-tools-extra/test/clang-tidy/checkers/readability/identifier-length-line-count-threshold.cpp
@@ -11,7 +11,7 @@ template<typename... Ts>
void doIt(Ts...);
void shouldWarn(int z)
-// CHECK-MESSAGES: :[[@LINE-1]]:32: warning: parameter name 'z' is too short, expected at least 3 characters [readability-identifier-length]
+// CHECK-MESSAGES: :[[@LINE-1]]:21: warning: parameter name 'z' is too short, expected at least 3 characters [readability-identifier-length]
{
int i = 5;
// CHECK-MESSAGES: :[[@LINE-1]]:7: warning: variable name 'i' is too short, expected at least 3 characters [readability-identifier-length]
>From 46f9690fe47cf96b4671fb18dc7d10cb71ba46e4 Mon Sep 17 00:00:00 2001
From: Alex Dutka <97711898+dutkalex at users.noreply.github.com>
Date: Sat, 11 Apr 2026 18:50:31 +0200
Subject: [PATCH 11/13] rewrite last use line search as allDeclRefExprs +
transform_reduce
---
.../readability/IdentifierLengthCheck.cpp | 40 +++++++------------
1 file changed, 14 insertions(+), 26 deletions(-)
diff --git a/clang-tools-extra/clang-tidy/readability/IdentifierLengthCheck.cpp b/clang-tools-extra/clang-tidy/readability/IdentifierLengthCheck.cpp
index 9a1e267c9b451..743422d827351 100644
--- a/clang-tools-extra/clang-tidy/readability/IdentifierLengthCheck.cpp
+++ b/clang-tools-extra/clang-tidy/readability/IdentifierLengthCheck.cpp
@@ -8,6 +8,7 @@
#include "IdentifierLengthCheck.h"
#include "clang/ASTMatchers/ASTMatchFinder.h"
+#include "../utils/DeclRefExprUtils.h"
using namespace clang::ast_matchers;
@@ -92,34 +93,21 @@ void IdentifierLengthCheck::registerMatchers(MatchFinder *Finder) {
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 auto *Use = Result.Nodes.getNodeAs<DeclRefExpr>("varUse");
- if (Use && LastUseLineNumber) {
- auto Loc = Use->getLocation();
- const unsigned UseLine =
- Result.SourceManager->getSpellingLineNumber(Loc);
- *LastUseLineNumber = std::max(*LastUseLineNumber, UseLine);
- }
- }
- };
-
- unsigned LastUseLine = DeclLine;
- VarUseCallback Callback{&LastUseLine};
+ const auto *ParentScope = llvm::dyn_cast<FunctionDecl>(Var->getDeclContext());
+ if (ParentScope == nullptr) {
+ return 1;
+ }
- auto Matcher = declRefExpr(to(varDecl(equalsNode(Var)))).bind("varUse");
+ auto AllRefs =
+ utils::decl_ref_expr::allDeclRefExprs(*Var, *ParentScope, *Ctx);
- MatchFinder Finder;
- Finder.addMatcher(Matcher, &Callback);
- Finder.matchAST(*Ctx);
+ const unsigned DeclLine = SrcMgr->getSpellingLineNumber(Var->getLocation());
+ const unsigned LastUseLine = std::transform_reduce(
+ AllRefs.begin(), AllRefs.end(), DeclLine,
+ [](unsigned Lhs, unsigned Rhs) -> unsigned { return std::max(Lhs, Rhs); },
+ [&](DeclRefExpr const *RefToVar) -> unsigned {
+ return SrcMgr->getSpellingLineNumber(RefToVar->getLocation());
+ });
return LastUseLine - DeclLine + 1;
}
>From 2f1c5834f801bae6f5654faec87e00003b73b988 Mon Sep 17 00:00:00 2001
From: Alex Dutka <97711898+dutkalex at users.noreply.github.com>
Date: Sat, 11 Apr 2026 19:27:31 +0200
Subject: [PATCH 12/13] improve documentation
---
clang-tools-extra/docs/ReleaseNotes.rst | 10 +++++-----
.../checks/readability/identifier-length.rst | 3 ++-
2 files changed, 7 insertions(+), 6 deletions(-)
diff --git a/clang-tools-extra/docs/ReleaseNotes.rst b/clang-tools-extra/docs/ReleaseNotes.rst
index e33286d5df57a..600f34bd1cafe 100644
--- a/clang-tools-extra/docs/ReleaseNotes.rst
+++ b/clang-tools-extra/docs/ReleaseNotes.rst
@@ -311,9 +311,9 @@ Changes in existing checks
- Improved :doc:`cppcoreguidelines-missing-std-forward
<clang-tidy/checks/cppcoreguidelines/missing-std-forward>` check:
-
+
- Fixed false positive for constrained template parameters
-
+
- Fixed false positive with ``std::forward`` in brace-init and paren-init
lambda captures such as ``[t{std::forward<T>(t)}]``.
@@ -474,15 +474,15 @@ Changes in existing checks
- Improved :doc:`readability-identifier-length
<clang-tidy/checks/readability/identifier-length>` check by adding a new
- option to silence warnings for short-lived variables, based on distance
- between declaration and last use.
+ option, named `LineCountThreshold`, to silence warnings for short-lived
+ variables, based on distance between declaration and last use.
- Improved :doc:`readability-identifier-naming
<clang-tidy/checks/readability/identifier-naming>` check:
- Fixed incorrect naming style application to C++17 structured bindings.
- - Fixed a false positive where function templates could be diagnosed as generic
+ - Fixed a false positive where function templates could be diagnosed as generic
identifiers when `DefaultCase` was enabled.
- Improved :doc:`readability-implicit-bool-conversion
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 ad1450fdb84bb..13168aba07d82 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
@@ -126,7 +126,8 @@ The following options are described below:
.. 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.
+ use for a diagnostic to be issued. The default value for this option is 0,
+ which corresponds to all variables being flagged.
.. code-block:: c++
>From 3a00eff134bfcb9c14fee0e8a7355a316f72a718 Mon Sep 17 00:00:00 2001
From: Alex Dutka <97711898+dutkalex at users.noreply.github.com>
Date: Sat, 11 Apr 2026 19:34:54 +0200
Subject: [PATCH 13/13] add tests with variables with multiple usages
---
.../readability/identifier-length-line-count-threshold.cpp | 2 ++
1 file changed, 2 insertions(+)
diff --git a/clang-tools-extra/test/clang-tidy/checkers/readability/identifier-length-line-count-threshold.cpp b/clang-tools-extra/test/clang-tidy/checkers/readability/identifier-length-line-count-threshold.cpp
index fbeed11b4a8cd..b666dbdbcd7bd 100644
--- a/clang-tools-extra/test/clang-tidy/checkers/readability/identifier-length-line-count-threshold.cpp
+++ b/clang-tools-extra/test/clang-tidy/checkers/readability/identifier-length-line-count-threshold.cpp
@@ -15,6 +15,7 @@ void shouldWarn(int z)
{
int i = 5;
// CHECK-MESSAGES: :[[@LINE-1]]:7: warning: variable name 'i' is too short, expected at least 3 characters [readability-identifier-length]
+ ++i;
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]
@@ -37,6 +38,7 @@ void shouldNotWarn(int m)
doIt(m);
int v = 5;
+ ++v;
doIt(v);
for (int a = 0; a < 42; ++a)
More information about the cfe-commits
mailing list