[clang-tools-extra] [clang-tidy] identifier-naming: TrimPrefixSuffix option to avoid concatenating multiple pre(suf)fixes (PR #181502)

Brice Decaestecker via cfe-commits cfe-commits at lists.llvm.org
Sat Feb 14 11:26:03 PST 2026


https://github.com/NyuB created https://github.com/llvm/llvm-project/pull/181502

This pull request proposal is intended to smooth a use cases such as:  'prefix all members by `m_`, local variables by `l_` and function parameters by `p_`

We use this check at work in combination with cland to enforce such coding guidelines. When extracting a function from a local block of code or auto-generating a constructor via clangd and applying the check, the naming end up looking like `p_m_foo`, `p_l_foo`, `m_l_foo` ... and we are back at tediously _searchandreplacing_ by ourselves.

This pull request introduces an option and the associated logic to trim all known prefixes and suffixes from a given identifer before applying the correct prefix/suffix, solving the issue.



>From b1669fef265623eb9e1f4a591a3972483b80794c Mon Sep 17 00:00:00 2001
From: Brice Decaestecker <brice.decaestecker at gmx.fr>
Date: Sat, 14 Feb 2026 12:17:30 +0100
Subject: [PATCH] [clang-tidy] Avoid identifier-naming concatenating multiple
 (pre/su)ffixes, introducing an option to strip out any other known
 (pre/su)ffix before renaming

---
 .../readability/IdentifierNamingCheck.cpp     |  41 ++++-
 .../readability/IdentifierNamingCheck.h       |   5 +-
 .../checks/readability/identifier-naming.rst  | 165 ++++++++++++++++++
 3 files changed, 205 insertions(+), 6 deletions(-)

diff --git a/clang-tools-extra/clang-tidy/readability/IdentifierNamingCheck.cpp b/clang-tools-extra/clang-tidy/readability/IdentifierNamingCheck.cpp
index 83fc3727cb5c8..8de8d7089288c 100644
--- a/clang-tools-extra/clang-tidy/readability/IdentifierNamingCheck.cpp
+++ b/clang-tools-extra/clang-tidy/readability/IdentifierNamingCheck.cpp
@@ -238,9 +238,11 @@ static StringRef const HungarianNotationUserDefinedTypes[] = {
 
 IdentifierNamingCheck::NamingStyle::NamingStyle(
     std::optional<IdentifierNamingCheck::CaseType> Case, StringRef Prefix,
-    StringRef Suffix, StringRef IgnoredRegexpStr, HungarianPrefixType HPType)
+    StringRef Suffix, StringRef IgnoredRegexpStr, HungarianPrefixType HPType,
+    bool TrimPrefixSuffix)
     : Case(Case), Prefix(Prefix), Suffix(Suffix),
-      IgnoredRegexpStr(IgnoredRegexpStr), HPType(HPType) {
+      IgnoredRegexpStr(IgnoredRegexpStr), HPType(HPType),
+      TrimPrefixSuffix(TrimPrefixSuffix) {
   if (!IgnoredRegexpStr.empty()) {
     IgnoredRegexp =
         llvm::Regex(llvm::SmallString<128>({"^", IgnoredRegexpStr, "$"}));
@@ -269,9 +271,13 @@ IdentifierNamingCheck::FileStyle IdentifierNamingCheck::getFileStyleFromOptions(
     if (HPTOpt && !HungarianNotation.checkOptionValid(I))
       configurationDiag("invalid identifier naming option '%0'") << StyleString;
 
+    memcpy(&StyleString[StyleSize], "TrimPrefixSuffix", 16);
+    StyleString.truncate(StyleSize + 16);
+    const std::optional<bool> TrimPrefixSuffix =
+        Options.get<bool>(StyleString);
     memcpy(&StyleString[StyleSize], "IgnoredRegexp", 13);
     StyleString.truncate(StyleSize + 13);
-    const std::optional<StringRef> IgnoredRegexpStr = Options.get(StyleString);
+    std::optional<StringRef> IgnoredRegexpStr = Options.get(StyleString);
     memcpy(&StyleString[StyleSize], "Prefix", 6);
     StyleString.truncate(StyleSize + 6);
     const std::optional<StringRef> Prefix(Options.get(StyleString));
@@ -286,7 +292,8 @@ IdentifierNamingCheck::FileStyle IdentifierNamingCheck::getFileStyleFromOptions(
     if (CaseOptional || Prefix || Postfix || IgnoredRegexpStr || HPTOpt)
       Styles[I].emplace(std::move(CaseOptional), Prefix.value_or(""),
                         Postfix.value_or(""), IgnoredRegexpStr.value_or(""),
-                        HPTOpt.value_or(IdentifierNamingCheck::HPT_Off));
+                        HPTOpt.value_or(IdentifierNamingCheck::HPT_Off),
+                        TrimPrefixSuffix.value_or(false));
   }
   const bool IgnoreMainLike = Options.get("IgnoreMainLikeFunctions", false);
   const bool CheckAnonFieldInParent =
@@ -1084,9 +1091,30 @@ bool IdentifierNamingCheck::isParamInMainLikeFunction(
   return Matcher.match(FDecl->getName());
 }
 
+static void trimPrefixesAndSuffixes(
+    StringRef &Mid,
+    ArrayRef<std::optional<IdentifierNamingCheck::NamingStyle>> NamingStyles) {
+  bool LoopWhileToRemove = true;
+  while (LoopWhileToRemove) {
+    LoopWhileToRemove = false;
+    for (unsigned I = 0; I < SK_Count; ++I) {
+      if (const std::optional<IdentifierNamingCheck::NamingStyle> &OtherStyle =
+              NamingStyles[I]) {
+        while (!OtherStyle->Prefix.empty() &&
+               Mid.consume_front(OtherStyle->Prefix))
+          LoopWhileToRemove = true;
+
+        while (!OtherStyle->Suffix.empty() && Mid.consume_back(OtherStyle->Suffix))
+          LoopWhileToRemove = true;
+      }
+    }
+  }
+}
+
 std::string IdentifierNamingCheck::fixupWithStyle(
     StringRef Type, StringRef Name,
     const IdentifierNamingCheck::NamingStyle &Style,
+    ArrayRef<std::optional<IdentifierNamingCheck::NamingStyle>> NamingStyles,
     const IdentifierNamingCheck::HungarianNotationOption &HNOption,
     const Decl *D) const {
   Name.consume_front(Style.Prefix);
@@ -1108,6 +1136,8 @@ std::string IdentifierNamingCheck::fixupWithStyle(
     }
   }
   StringRef Mid = StringRef(Fixed).trim("_");
+  if (Style.TrimPrefixSuffix)
+    trimPrefixesAndSuffixes(Mid, NamingStyles);
   if (Mid.empty())
     Mid = "_";
 
@@ -1359,7 +1389,8 @@ IdentifierNamingCheck::getFailureInfo(
                           IdentifierNamingCheck::CT_LowerCase);
   llvm::replace(KindName, '_', ' ');
 
-  std::string Fixup = fixupWithStyle(Type, Name, Style, HNOption, ND);
+  std::string Fixup =
+      fixupWithStyle(Type, Name, Style, NamingStyles, HNOption, ND);
   if (StringRef(Fixup) == Name) {
     if (!IgnoreFailedSplit) {
       LLVM_DEBUG(Location.print(llvm::dbgs(), SM);
diff --git a/clang-tools-extra/clang-tidy/readability/IdentifierNamingCheck.h b/clang-tools-extra/clang-tidy/readability/IdentifierNamingCheck.h
index b016556cc2ab8..bdac7f5b1e8b9 100644
--- a/clang-tools-extra/clang-tidy/readability/IdentifierNamingCheck.h
+++ b/clang-tools-extra/clang-tidy/readability/IdentifierNamingCheck.h
@@ -72,7 +72,7 @@ class IdentifierNamingCheck final : public RenamerClangTidyCheck {
 
     NamingStyle(std::optional<CaseType> Case, StringRef Prefix,
                 StringRef Suffix, StringRef IgnoredRegexpStr,
-                HungarianPrefixType HPType);
+                HungarianPrefixType HPType, bool TrimPrefixSuffix);
     NamingStyle(const NamingStyle &O) = delete;
     NamingStyle &operator=(NamingStyle &&O) = default;
     NamingStyle(NamingStyle &&O) = default;
@@ -86,6 +86,8 @@ class IdentifierNamingCheck final : public RenamerClangTidyCheck {
     std::string IgnoredRegexpStr;
 
     HungarianPrefixType HPType;
+
+    bool TrimPrefixSuffix;
   };
 
   struct HungarianNotation {
@@ -176,6 +178,7 @@ class IdentifierNamingCheck final : public RenamerClangTidyCheck {
   std::string
   fixupWithStyle(StringRef Type, StringRef Name,
                  const IdentifierNamingCheck::NamingStyle &Style,
+                 ArrayRef<std::optional<IdentifierNamingCheck::NamingStyle>> NamingStyles,
                  const IdentifierNamingCheck::HungarianNotationOption &HNOption,
                  const Decl *D) const;
 
diff --git a/clang-tools-extra/docs/clang-tidy/checks/readability/identifier-naming.rst b/clang-tools-extra/docs/clang-tidy/checks/readability/identifier-naming.rst
index c8f87dcba8c0a..34d440f45dae2 100644
--- a/clang-tools-extra/docs/clang-tidy/checks/readability/identifier-naming.rst
+++ b/clang-tools-extra/docs/clang-tidy/checks/readability/identifier-naming.rst
@@ -276,6 +276,11 @@ A detailed description of each option is presented below:
     When defined, the check will ensure all names by default will add the
     suffix with the given value (regardless of casing).
 
+.. option:: DefaultTrimPrefixSuffix
+
+    When enabled, the check ensures that the declared identifier does not
+    start or end with any other prefix or suffix defined for this check
+
 .. option:: DefaultHungarianPrefix
 
     When enabled, the check ensures that the declared identifier will
@@ -301,6 +306,11 @@ A detailed description of each option is presented below:
     When defined, the check will ensure abstract class names will add the
     suffix with the given value (regardless of casing).
 
+.. option:: AbstractClassTrimPrefixSuffix
+
+    When enabled, the check ensures that the declared identifier does not
+    start or end with any other prefix or suffix defined for this check
+
 .. option:: AbstractClassHungarianPrefix
 
     When enabled, the check ensures that the declared identifier will
@@ -438,6 +448,11 @@ and thus no warnings will be emitted.
     When defined, the check will ensure class names will add the
     suffix with the given value (regardless of casing).
 
+.. option:: ClassTrimPrefixSuffix
+
+    When enabled, the check ensures that the declared identifier does not
+    start or end with any other prefix or suffix defined for this check
+
 .. option:: ClassHungarianPrefix
 
     When enabled, the check ensures that the declared identifier will
@@ -492,6 +507,11 @@ After:
     When defined, the check will ensure class ``constexpr`` names will add the
     suffix with the given value (regardless of casing).
 
+.. option:: ClassConstexprTrimPrefixSuffix
+
+    When enabled, the check ensures that the declared identifier does not
+    start or end with any other prefix or suffix defined for this check
+
 .. option:: ClassConstexprHungarianPrefix
 
     When enabled, the check ensures that the declared identifier will have a
@@ -544,6 +564,11 @@ After:
     When defined, the check will ensure class constant names will add the
     suffix with the given value (regardless of casing).
 
+.. option:: ClassConstantTrimPrefixSuffix
+
+    When enabled, the check ensures that the declared identifier does not
+    start or end with any other prefix or suffix defined for this check
+
 .. option:: ClassConstantHungarianPrefix
 
     When enabled, the check ensures that the declared identifier will
@@ -596,6 +621,11 @@ After:
     When defined, the check will ensure class member names will add the
     suffix with the given value (regardless of casing).
 
+.. option:: ClassMemberTrimPrefixSuffix
+
+    When enabled, the check ensures that the declared identifier does not
+    start or end with any other prefix or suffix defined for this check
+
 .. option:: ClassMemberHungarianPrefix
 
     When enabled, the check ensures that the declared identifier will
@@ -734,6 +764,11 @@ After:
     When defined, the check will ensure constant names will add the
     suffix with the given value (regardless of casing).
 
+.. option:: ConstantTrimPrefixSuffix
+
+    When enabled, the check ensures that the declared identifier does not
+    start or end with any other prefix or suffix defined for this check
+
 .. option:: ConstantHungarianPrefix
 
     When enabled, the check ensures that the declared identifier will
@@ -780,6 +815,11 @@ After:
     When defined, the check will ensure constant member names will add the
     suffix with the given value (regardless of casing).
 
+.. option:: ConstantMemberTrimPrefixSuffix
+
+    When enabled, the check ensures that the declared identifier does not
+    start or end with any other prefix or suffix defined for this check
+
 .. option:: ConstantMemberHungarianPrefix
 
     When enabled, the check ensures that the declared identifier will
@@ -830,6 +870,11 @@ After:
     When defined, the check will ensure constant parameter names will add the
     suffix with the given value (regardless of casing).
 
+.. option:: ConstantParameterTrimPrefixSuffix
+
+    When enabled, the check ensures that the declared identifier does not
+    start or end with any other prefix or suffix defined for this check
+
 .. option:: ConstantParameterHungarianPrefix
 
     When enabled, the check ensures that the declared identifier will
@@ -876,6 +921,11 @@ After:
     When defined, the check will ensure constant pointer parameter names will add the
     suffix with the given value (regardless of casing).
 
+.. option:: ConstantPointerParameterTrimPrefixSuffix
+
+    When enabled, the check ensures that the declared identifier does not
+    start or end with any other prefix or suffix defined for this check
+
 .. option:: ConstantPointerParameterHungarianPrefix
 
     When enabled, the check ensures that the declared identifier will
@@ -1008,6 +1058,11 @@ After:
     When defined, the check will ensure constexpr variable names will add the
     suffix with the given value (regardless of casing).
 
+.. option:: ConstexprVariableTrimPrefixSuffix
+
+    When enabled, the check ensures that the declared identifier does not
+    start or end with any other prefix or suffix defined for this check
+
 .. option:: ConstexprVariableHungarianPrefix
 
     When enabled, the check ensures that the declared identifier will
@@ -1094,6 +1149,11 @@ After:
     When defined, the check will ensure enumeration constant names will add the
     suffix with the given value (regardless of casing).
 
+.. option:: EnumConstantTrimPrefixSuffix
+
+    When enabled, the check ensures that the declared identifier does not
+    start or end with any other prefix or suffix defined for this check
+
 .. option:: EnumConstantHungarianPrefix
 
     When enabled, the check ensures that the declared identifier will
@@ -1187,6 +1247,11 @@ After:
     When defined, the check will ensure global ``constexpr`` variable names
     will add the suffix with the given value (regardless of casing).
 
+.. option:: GlobalConstexprVariableTrimPrefixSuffix
+
+    When enabled, the check ensures that the declared identifier does not
+    start or end with any other prefix or suffix defined for this check
+
 .. option:: GlobalConstexprVariableHungarianPrefix
 
     When enabled, the check ensures that the declared identifier will have a
@@ -1233,6 +1298,11 @@ After:
     When defined, the check will ensure global constant names will add the
     suffix with the given value (regardless of casing).
 
+.. option:: GlobalConstantTrimPrefixSuffix
+
+    When enabled, the check ensures that the declared identifier does not
+    start or end with any other prefix or suffix defined for this check
+
 .. option:: GlobalConstantHungarianPrefix
 
     When enabled, the check ensures that the declared identifier will
@@ -1279,6 +1349,11 @@ After:
     When defined, the check will ensure global constant pointer names will add the
     suffix with the given value (regardless of casing).
 
+.. option:: GlobalConstantPointerTrimPrefixSuffix
+
+    When enabled, the check ensures that the declared identifier does not
+    start or end with any other prefix or suffix defined for this check
+
 .. option:: GlobalConstantPointerHungarianPrefix
 
     When enabled, the check ensures that the declared identifier will
@@ -1365,6 +1440,11 @@ After:
     When defined, the check will ensure global pointer names will add the
     suffix with the given value (regardless of casing).
 
+.. option:: GlobalPointerTrimPrefixSuffix
+
+    When enabled, the check ensures that the declared identifier does not
+    start or end with any other prefix or suffix defined for this check
+
 .. option:: GlobalPointerHungarianPrefix
 
     When enabled, the check ensures that the declared identifier will
@@ -1411,6 +1491,11 @@ After:
     When defined, the check will ensure global variable names will add the
     suffix with the given value (regardless of casing).
 
+.. option:: GlobalVariableTrimPrefixSuffix
+
+    When enabled, the check ensures that the declared identifier does not
+    start or end with any other prefix or suffix defined for this check
+
 .. option:: GlobalVariableHungarianPrefix
 
     When enabled, the check ensures that the declared identifier will
@@ -1511,6 +1596,11 @@ After:
     When defined, the check will ensure local ``constexpr`` variable names will
     add the suffix with the given value (regardless of casing).
 
+.. option:: LocalConstexprVariableTrimPrefixSuffix
+
+    When enabled, the check ensures that the declared identifier does not
+    start or end with any other prefix or suffix defined for this check
+
 .. option:: LocalConstexprVariableHungarianPrefix
 
     When enabled, the check ensures that the declared identifier will have a
@@ -1557,6 +1647,11 @@ After:
     When defined, the check will ensure local constant names will add the
     suffix with the given value (regardless of casing).
 
+.. option:: LocalConstantTrimPrefixSuffix
+
+    When enabled, the check ensures that the declared identifier does not
+    start or end with any other prefix or suffix defined for this check
+
 .. option:: LocalConstantHungarianPrefix
 
     When enabled, the check ensures that the declared identifier will
@@ -1603,6 +1698,11 @@ After:
     When defined, the check will ensure local constant pointer names will add the
     suffix with the given value (regardless of casing).
 
+.. option:: LocalConstantPointerTrimPrefixSuffix
+
+    When enabled, the check ensures that the declared identifier does not
+    start or end with any other prefix or suffix defined for this check
+
 .. option:: LocalConstantPointerHungarianPrefix
 
     When enabled, the check ensures that the declared identifier will
@@ -1649,6 +1749,11 @@ After:
     When defined, the check will ensure local pointer names will add the
     suffix with the given value (regardless of casing).
 
+.. option:: LocalPointerTrimPrefixSuffix
+
+    When enabled, the check ensures that the declared identifier does not
+    start or end with any other prefix or suffix defined for this check
+
 .. option:: LocalPointerHungarianPrefix
 
     When enabled, the check ensures that the declared identifier will
@@ -1703,6 +1808,11 @@ camel case check applied to other variables.
     When defined, the check will ensure local variable names will add the
     suffix with the given value (regardless of casing).
 
+.. option:: LocalVariableTrimPrefixSuffix
+
+    When enabled, the check ensures that the declared identifier does not
+    start or end with any other prefix or suffix defined for this check
+
 .. option:: LocalVariableHungarianPrefix
 
     When enabled, the check ensures that the declared identifier will
@@ -1792,6 +1902,11 @@ command line using the ``-D`` flag.
     When defined, the check will ensure member names will add the
     suffix with the given value (regardless of casing).
 
+.. option:: MemberTrimPrefixSuffix
+
+    When enabled, the check ensures that the declared identifier does not
+    start or end with any other prefix or suffix defined for this check
+
 .. option:: MemberHungarianPrefix
 
     When enabled, the check ensures that the declared identifier will
@@ -1930,6 +2045,11 @@ After:
     When defined, the check will ensure parameter names will add the
     suffix with the given value (regardless of casing).
 
+.. option:: ParameterTrimPrefixSuffix
+
+    When enabled, the check ensures that the declared identifier does not
+    start or end with any other prefix or suffix defined for this check
+
 .. option:: ParameterHungarianPrefix
 
     When enabled, the check ensures that the declared identifier will
@@ -2020,6 +2140,11 @@ After:
     When defined, the check will ensure pointer parameter names will add the
     suffix with the given value (regardless of casing).
 
+.. option:: PointerParameterTrimPrefixSuffix
+
+    When enabled, the check ensures that the declared identifier does not
+    start or end with any other prefix or suffix defined for this check
+
 .. option:: PointerParameterHungarianPrefix
 
     When enabled, the check ensures that the declared identifier will
@@ -2066,6 +2191,11 @@ After:
     When defined, the check will ensure private member names will add the
     suffix with the given value (regardless of casing).
 
+.. option:: PrivateMemberTrimPrefixSuffix
+
+    When enabled, the check ensures that the declared identifier does not
+    start or end with any other prefix or suffix defined for this check
+
 .. option:: PrivateMemberHungarianPrefix
 
     When enabled, the check ensures that the declared identifier will
@@ -2164,6 +2294,11 @@ After:
     When defined, the check will ensure protected member names will add the
     suffix with the given value (regardless of casing).
 
+.. option:: ProtectedMemberTrimPrefixSuffix
+
+    When enabled, the check ensures that the declared identifier does not
+    start or end with any other prefix or suffix defined for this check
+
 .. option:: ProtectedMemberHungarianPrefix
 
     When enabled, the check ensures that the declared identifier will
@@ -2262,6 +2397,11 @@ After:
     When defined, the check will ensure public member names will add the
     suffix with the given value (regardless of casing).
 
+.. option:: PublicMemberTrimPrefixSuffix
+
+    When enabled, the check ensures that the declared identifier does not
+    start or end with any other prefix or suffix defined for this check
+
 .. option:: PublicMemberHungarianPrefix
 
     When enabled, the check ensures that the declared identifier will
@@ -2360,6 +2500,11 @@ After:
     When defined, the check will ensure scoped enum constant names will add the
     suffix with the given value (regardless of casing).
 
+.. option:: ScopedEnumConstantTrimPrefixSuffix
+
+    When enabled, the check ensures that the declared identifier does not
+    start or end with any other prefix or suffix defined for this check
+
 .. option:: ScopedEnumConstantHungarianPrefix
 
     When enabled, the check ensures that the declared identifier will
@@ -2406,6 +2551,11 @@ After:
     When defined, the check will ensure static ``constexpr`` variable names
     will add the suffix with the given value (regardless of casing).
 
+.. option:: StaticConstexprVariableTrimPrefixSuffix
+
+    When enabled, the check ensures that the declared identifier does not
+    start or end with any other prefix or suffix defined for this check
+
 .. option:: StaticConstexprVariableHungarianPrefix
 
     When enabled, the check ensures that the declared identifier will have a
@@ -2452,6 +2602,11 @@ After:
     When defined, the check will ensure static constant names will add the
     suffix with the given value (regardless of casing).
 
+.. option:: StaticConstantTrimPrefixSuffix
+
+    When enabled, the check ensures that the declared identifier does not
+    start or end with any other prefix or suffix defined for this check
+
 .. option:: StaticConstantHungarianPrefix
 
     When enabled, the check ensures that the declared identifier will
@@ -2498,6 +2653,11 @@ After:
     When defined, the check will ensure static variable names will add the
     suffix with the given value (regardless of casing).
 
+.. option:: StaticVariableTrimPrefixSuffix
+
+    When enabled, the check ensures that the declared identifier does not
+    start or end with any other prefix or suffix defined for this check
+
 .. option:: StaticVariableHungarianPrefix
 
     When enabled, the check ensures that the declared identifier will
@@ -2882,6 +3042,11 @@ After:
     When defined, the check will ensure variable names will add the
     suffix with the given value (regardless of casing).
 
+.. option:: VariableTrimPrefixSuffix
+
+    When enabled, the check ensures that the declared identifier does not
+    start or end with any other prefix or suffix defined for this check
+
 .. option:: VariableHungarianPrefix
 
     When enabled, the check ensures that the declared identifier will



More information about the cfe-commits mailing list