https://github.com/localspook updated https://github.com/llvm/llvm-project/pull/173506
>From f3dcfaf13f73e38eb2c8c464a0f92855c3d3eb6f Mon Sep 17 00:00:00 2001 From: Victor Chernyakin <[email protected]> Date: Wed, 24 Dec 2025 12:12:12 -0700 Subject: [PATCH 1/3] [clang-tidy][NFC] Replace stateless struct with namespace in `readability-identifier-naming` --- .../readability/IdentifierNamingCheck.cpp | 70 +++++++++---------- .../readability/IdentifierNamingCheck.h | 37 ---------- 2 files changed, 35 insertions(+), 72 deletions(-) diff --git a/clang-tools-extra/clang-tidy/readability/IdentifierNamingCheck.cpp b/clang-tools-extra/clang-tidy/readability/IdentifierNamingCheck.cpp index 9cee6ddb93d4d..827bdb8374463 100644 --- a/clang-tools-extra/clang-tidy/readability/IdentifierNamingCheck.cpp +++ b/clang-tools-extra/clang-tidy/readability/IdentifierNamingCheck.cpp @@ -254,8 +254,8 @@ IdentifierNamingCheck::FileStyle IdentifierNamingCheck::getFileStyleFromOptions( const ClangTidyCheck::OptionsView &Options) const { IdentifierNamingCheck::HungarianNotationOption HNOption; - HungarianNotation.loadDefaultConfig(HNOption); - HungarianNotation.loadFileConfig(Options, HNOption); + HungarianNotation::loadDefaultConfig(HNOption); + HungarianNotation::loadFileConfig(Options, HNOption); SmallVector<std::optional<IdentifierNamingCheck::NamingStyle>, 0> Styles; Styles.resize(SK_Count); @@ -266,7 +266,7 @@ IdentifierNamingCheck::FileStyle IdentifierNamingCheck::getFileStyleFromOptions( auto HPTOpt = Options.get<IdentifierNamingCheck::HungarianPrefixType>(StyleString); - if (HPTOpt && !HungarianNotation.checkOptionValid(I)) + if (HPTOpt && !HungarianNotation::checkOptionValid(I)) configurationDiag("invalid identifier naming option '%0'") << StyleString; memcpy(&StyleString[StyleSize], "IgnoredRegexp", 13); @@ -295,8 +295,7 @@ IdentifierNamingCheck::FileStyle IdentifierNamingCheck::getFileStyleFromOptions( CheckAnonFieldInParent}; } -std::string IdentifierNamingCheck::HungarianNotation::getDeclTypeName( - const NamedDecl *ND) const { +static std::string getDeclTypeName(const NamedDecl *ND) { const auto *VD = dyn_cast<ValueDecl>(ND); if (!VD) return {}; @@ -415,8 +414,9 @@ IdentifierNamingCheck::IdentifierNamingCheck(StringRef Name, IdentifierNamingCheck::~IdentifierNamingCheck() = default; -bool IdentifierNamingCheck::HungarianNotation::checkOptionValid( - int StyleKindIndex) const { +namespace HungarianNotation { + +static bool checkOptionValid(int StyleKindIndex) { if ((StyleKindIndex >= SK_EnumConstant) && (StyleKindIndex <= SK_ConstantParameter)) return true; @@ -427,8 +427,8 @@ bool IdentifierNamingCheck::HungarianNotation::checkOptionValid( return false; } -bool IdentifierNamingCheck::HungarianNotation::isOptionEnabled( - StringRef OptionKey, const llvm::StringMap<std::string> &StrMap) const { +static bool isOptionEnabled(StringRef OptionKey, + const llvm::StringMap<std::string> &StrMap) { if (OptionKey.empty()) return false; @@ -439,14 +439,14 @@ bool IdentifierNamingCheck::HungarianNotation::isOptionEnabled( return *llvm::yaml::parseBool(Iter->getValue()); } -void IdentifierNamingCheck::HungarianNotation::loadFileConfig( - const ClangTidyCheck::OptionsView &Options, - IdentifierNamingCheck::HungarianNotationOption &HNOption) const { +static void +loadFileConfig(const ClangTidyCheck::OptionsView &Options, + IdentifierNamingCheck::HungarianNotationOption &HNOption) { static constexpr StringRef HNOpts[] = {"TreatStructAsClass"}; static constexpr StringRef HNDerivedTypes[] = {"Array", "Pointer", "FunctionPointer"}; - const StringRef Section = "HungarianNotation."; + const StringRef Section = "HungarianNotation::"; SmallString<128> Buffer = {Section, "General."}; size_t DefSize = Buffer.size(); @@ -508,9 +508,9 @@ void IdentifierNamingCheck::HungarianNotation::loadFileConfig( } } -std::string IdentifierNamingCheck::HungarianNotation::getPrefix( - const Decl *D, - const IdentifierNamingCheck::HungarianNotationOption &HNOption) const { +static std::string +getPrefix(const Decl *D, + const IdentifierNamingCheck::HungarianNotationOption &HNOption) { if (!D) return {}; const auto *ND = dyn_cast<NamedDecl>(D); @@ -531,9 +531,9 @@ std::string IdentifierNamingCheck::HungarianNotation::getPrefix( return Prefix; } -bool IdentifierNamingCheck::HungarianNotation::removeDuplicatedPrefix( +static bool removeDuplicatedPrefix( SmallVector<StringRef, 8> &Words, - const IdentifierNamingCheck::HungarianNotationOption &HNOption) const { + const IdentifierNamingCheck::HungarianNotationOption &HNOption) { if (Words.size() <= 1) return true; @@ -554,9 +554,9 @@ bool IdentifierNamingCheck::HungarianNotation::removeDuplicatedPrefix( return false; } -std::string IdentifierNamingCheck::HungarianNotation::getDataTypePrefix( +static std::string getDataTypePrefix( StringRef TypeName, const NamedDecl *ND, - const IdentifierNamingCheck::HungarianNotationOption &HNOption) const { + const IdentifierNamingCheck::HungarianNotationOption &HNOption) { if (!ND || TypeName.empty()) return TypeName.str(); @@ -634,9 +634,9 @@ std::string IdentifierNamingCheck::HungarianNotation::getDataTypePrefix( return PrefixStr; } -std::string IdentifierNamingCheck::HungarianNotation::getClassPrefix( - const CXXRecordDecl *CRD, - const IdentifierNamingCheck::HungarianNotationOption &HNOption) const { +static std::string +getClassPrefix(const CXXRecordDecl *CRD, + const IdentifierNamingCheck::HungarianNotationOption &HNOption) { if (CRD->isUnion()) return {}; @@ -647,8 +647,7 @@ std::string IdentifierNamingCheck::HungarianNotation::getClassPrefix( return CRD->isAbstract() ? "I" : "C"; } -std::string IdentifierNamingCheck::HungarianNotation::getEnumPrefix( - const EnumConstantDecl *ECD) const { +static std::string getEnumPrefix(const EnumConstantDecl *ECD) { const auto *ED = cast<EnumDecl>(ECD->getDeclContext()); std::string Name = ED->getName().str(); @@ -692,8 +691,7 @@ std::string IdentifierNamingCheck::HungarianNotation::getEnumPrefix( return Initial; } -size_t IdentifierNamingCheck::HungarianNotation::getAsteriskCount( - const std::string &TypeName) const { +static size_t getAsteriskCount(const std::string &TypeName) { size_t Pos = TypeName.find('*'); size_t Count = 0; for (; Pos < TypeName.length(); Pos++, Count++) @@ -702,8 +700,8 @@ size_t IdentifierNamingCheck::HungarianNotation::getAsteriskCount( return Count; } -size_t IdentifierNamingCheck::HungarianNotation::getAsteriskCount( - const std::string &TypeName, const NamedDecl *ND) const { +static size_t getAsteriskCount(const std::string &TypeName, + const NamedDecl *ND) { size_t PtrCount = 0; if (const auto *TD = dyn_cast<ValueDecl>(ND)) { const QualType QT = TD->getType(); @@ -713,8 +711,8 @@ size_t IdentifierNamingCheck::HungarianNotation::getAsteriskCount( return PtrCount; } -void IdentifierNamingCheck::HungarianNotation::loadDefaultConfig( - IdentifierNamingCheck::HungarianNotationOption &HNOption) const { +static void +loadDefaultConfig(IdentifierNamingCheck::HungarianNotationOption &HNOption) { // Options static constexpr std::pair<StringRef, StringRef> General[] = { {"TreatStructAsClass", "false"}}; @@ -823,6 +821,8 @@ void IdentifierNamingCheck::HungarianNotation::loadDefaultConfig( HNOption.UserDefinedType.try_emplace(UDT.first, UDT.second); } +} // namespace HungarianNotation + void IdentifierNamingCheck::storeOptions(ClangTidyOptions::OptionMap &Opts) { RenamerClangTidyCheck::storeOptions(Opts); SmallString<64> StyleString; @@ -880,7 +880,7 @@ bool IdentifierNamingCheck::matchesStyle( if (!Name.consume_back(Style.Suffix)) return false; if (IdentifierNamingCheck::HungarianPrefixType::HPT_Off != Style.HPType) { - const std::string HNPrefix = HungarianNotation.getPrefix(Decl, HNOption); + const std::string HNPrefix = HungarianNotation::getPrefix(Decl, HNOption); if (!HNPrefix.empty()) { if (!Name.consume_front(HNPrefix)) return false; @@ -938,7 +938,7 @@ std::string IdentifierNamingCheck::fixupWithCase( return Name.str(); if (IdentifierNamingCheck::HungarianPrefixType::HPT_Off != Style.HPType) - HungarianNotation.removeDuplicatedPrefix(Words, HNOption); + HungarianNotation::removeDuplicatedPrefix(Words, HNOption); SmallString<128> Fixup; switch (Case) { @@ -1096,7 +1096,7 @@ std::string IdentifierNamingCheck::fixupWithStyle( std::string HungarianPrefix; using HungarianPrefixType = IdentifierNamingCheck::HungarianPrefixType; if (HungarianPrefixType::HPT_Off != Style.HPType) { - HungarianPrefix = HungarianNotation.getPrefix(D, HNOption); + HungarianPrefix = HungarianNotation::getPrefix(D, HNOption); if (!HungarianPrefix.empty()) { if (Style.HPType == HungarianPrefixType::HPT_LowerCase) HungarianPrefix += "_"; @@ -1379,7 +1379,7 @@ IdentifierNamingCheck::getDeclFailureInfo(const NamedDecl *Decl, return std::nullopt; return getFailureInfo( - HungarianNotation.getDeclTypeName(Decl), Decl->getName(), Decl, Loc, + HungarianNotation::getDeclTypeName(Decl), Decl->getName(), Decl, Loc, FileStyle.getStyles(), FileStyle.getHNOption(), findStyleKind(Decl, FileStyle.getStyles(), FileStyle.isIgnoringMainLikeFunction(), diff --git a/clang-tools-extra/clang-tidy/readability/IdentifierNamingCheck.h b/clang-tools-extra/clang-tidy/readability/IdentifierNamingCheck.h index 87735808dff39..ab945e7477f51 100644 --- a/clang-tools-extra/clang-tidy/readability/IdentifierNamingCheck.h +++ b/clang-tools-extra/clang-tidy/readability/IdentifierNamingCheck.h @@ -88,42 +88,6 @@ class IdentifierNamingCheck final : public RenamerClangTidyCheck { HungarianPrefixType HPType; }; - struct HungarianNotation { - public: - bool checkOptionValid(int StyleKindIndex) const; - bool isOptionEnabled(StringRef OptionKey, - const llvm::StringMap<std::string> &StrMap) const; - - size_t getAsteriskCount(const std::string &TypeName) const; - size_t getAsteriskCount(const std::string &TypeName, - const NamedDecl *ND) const; - - void loadDefaultConfig( - IdentifierNamingCheck::HungarianNotationOption &HNOption) const; - void loadFileConfig( - const ClangTidyCheck::OptionsView &Options, - IdentifierNamingCheck::HungarianNotationOption &HNOption) const; - - bool removeDuplicatedPrefix( - SmallVector<StringRef, 8> &Words, - const IdentifierNamingCheck::HungarianNotationOption &HNOption) const; - - std::string getPrefix( - const Decl *D, - const IdentifierNamingCheck::HungarianNotationOption &HNOption) const; - - std::string getDataTypePrefix( - StringRef TypeName, const NamedDecl *ND, - const IdentifierNamingCheck::HungarianNotationOption &HNOption) const; - - std::string getClassPrefix( - const CXXRecordDecl *CRD, - const IdentifierNamingCheck::HungarianNotationOption &HNOption) const; - - std::string getEnumPrefix(const EnumConstantDecl *ECD) const; - std::string getDeclTypeName(const NamedDecl *ND) const; - }; - struct FileStyle { FileStyle() : IsActive(false), IgnoreMainLikeFunctions(false) {} FileStyle(SmallVectorImpl<std::optional<NamingStyle>> &&Styles, @@ -231,7 +195,6 @@ class IdentifierNamingCheck final : public RenamerClangTidyCheck { ClangTidyContext *Context; const bool GetConfigPerFile; const bool IgnoreFailedSplit; - HungarianNotation HungarianNotation; }; } // namespace readability >From f859100ab1cc69996fca20aaa8f62750b8ae42da Mon Sep 17 00:00:00 2001 From: Victor Chernyakin <[email protected]> Date: Wed, 24 Dec 2025 12:14:03 -0700 Subject: [PATCH 2/3] Move functions up in .cpp file --- .../readability/IdentifierNamingCheck.cpp | 356 +++++++++--------- 1 file changed, 178 insertions(+), 178 deletions(-) diff --git a/clang-tools-extra/clang-tidy/readability/IdentifierNamingCheck.cpp b/clang-tools-extra/clang-tidy/readability/IdentifierNamingCheck.cpp index 827bdb8374463..d155cab5330a7 100644 --- a/clang-tools-extra/clang-tidy/readability/IdentifierNamingCheck.cpp +++ b/clang-tools-extra/clang-tidy/readability/IdentifierNamingCheck.cpp @@ -236,184 +236,6 @@ static StringRef const HungarianNotationUserDefinedTypes[] = { #undef NAMING_KEYS // clang-format on -IdentifierNamingCheck::NamingStyle::NamingStyle( - std::optional<IdentifierNamingCheck::CaseType> Case, StringRef Prefix, - StringRef Suffix, StringRef IgnoredRegexpStr, HungarianPrefixType HPType) - : Case(Case), Prefix(Prefix), Suffix(Suffix), - IgnoredRegexpStr(IgnoredRegexpStr), HPType(HPType) { - if (!IgnoredRegexpStr.empty()) { - IgnoredRegexp = - llvm::Regex(llvm::SmallString<128>({"^", IgnoredRegexpStr, "$"})); - if (!IgnoredRegexp.isValid()) - llvm::errs() << "Invalid IgnoredRegexp regular expression: " - << IgnoredRegexpStr; - } -} - -IdentifierNamingCheck::FileStyle IdentifierNamingCheck::getFileStyleFromOptions( - const ClangTidyCheck::OptionsView &Options) const { - IdentifierNamingCheck::HungarianNotationOption HNOption; - - HungarianNotation::loadDefaultConfig(HNOption); - HungarianNotation::loadFileConfig(Options, HNOption); - - SmallVector<std::optional<IdentifierNamingCheck::NamingStyle>, 0> Styles; - Styles.resize(SK_Count); - SmallString<64> StyleString; - for (unsigned I = 0; I < SK_Count; ++I) { - const size_t StyleSize = StyleNames[I].size(); - StyleString.assign({StyleNames[I], "HungarianPrefix"}); - - auto HPTOpt = - Options.get<IdentifierNamingCheck::HungarianPrefixType>(StyleString); - if (HPTOpt && !HungarianNotation::checkOptionValid(I)) - configurationDiag("invalid identifier naming option '%0'") << StyleString; - - memcpy(&StyleString[StyleSize], "IgnoredRegexp", 13); - StyleString.truncate(StyleSize + 13); - const std::optional<StringRef> IgnoredRegexpStr = Options.get(StyleString); - memcpy(&StyleString[StyleSize], "Prefix", 6); - StyleString.truncate(StyleSize + 6); - const std::optional<StringRef> Prefix(Options.get(StyleString)); - // Fast replacement of [Pre]fix -> [Suf]fix. - memcpy(&StyleString[StyleSize], "Suf", 3); - const std::optional<StringRef> Postfix(Options.get(StyleString)); - memcpy(&StyleString[StyleSize], "Case", 4); - StyleString.pop_back_n(2); - std::optional<CaseType> CaseOptional = - Options.get<IdentifierNamingCheck::CaseType>(StyleString); - - 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)); - } - const bool IgnoreMainLike = Options.get("IgnoreMainLikeFunctions", false); - const bool CheckAnonFieldInParent = - Options.get("CheckAnonFieldInParent", false); - return {std::move(Styles), std::move(HNOption), IgnoreMainLike, - CheckAnonFieldInParent}; -} - -static std::string getDeclTypeName(const NamedDecl *ND) { - const auto *VD = dyn_cast<ValueDecl>(ND); - if (!VD) - return {}; - - if (isa<FunctionDecl, EnumConstantDecl>(ND)) - return {}; - - // Get type text of variable declarations. - auto &SM = VD->getASTContext().getSourceManager(); - const char *Begin = SM.getCharacterData(VD->getBeginLoc()); - const char *End = SM.getCharacterData(VD->getEndLoc()); - intptr_t StrLen = End - Begin; - - // FIXME: Sometimes the value that returns from ValDecl->getEndLoc() - // is wrong(out of location of Decl). This causes `StrLen` will be assigned - // an unexpected large value. Current workaround to find the terminated - // character instead of the `getEndLoc()` function. - const char *EOL = strchr(Begin, '\n'); - if (!EOL) - EOL = Begin + strlen(Begin); - - const char *const PosList[] = {strchr(Begin, '='), strchr(Begin, ';'), - strchr(Begin, ','), strchr(Begin, ')'), EOL}; - for (const auto &Pos : PosList) - if (Pos > Begin) - EOL = std::min(EOL, Pos); - - StrLen = EOL - Begin; - std::string TypeName; - if (StrLen > 0) { - std::string Type(Begin, StrLen); - - static constexpr StringRef Keywords[] = { - // Constexpr specifiers - "constexpr", "constinit", "consteval", - // Qualifier - "const", "volatile", "restrict", "mutable", - // Storage class specifiers - "register", "static", "extern", "thread_local", - // Other keywords - "virtual"}; - - // Remove keywords - for (const StringRef Kw : Keywords) - for (size_t Pos = 0; (Pos = Type.find(Kw, Pos)) != std::string::npos;) - Type.replace(Pos, Kw.size(), ""); - TypeName = Type.erase(0, Type.find_first_not_of(' ')); - - // Remove template parameters - const size_t Pos = Type.find('<'); - if (Pos != std::string::npos) - TypeName = Type.erase(Pos, Type.size() - Pos); - - // Replace spaces with single space. - for (size_t Pos = 0; (Pos = Type.find(" ", Pos)) != std::string::npos; - Pos += strlen(" ")) { - Type.replace(Pos, strlen(" "), " "); - } - - // Replace " &" with "&". - for (size_t Pos = 0; (Pos = Type.find(" &", Pos)) != std::string::npos; - Pos += strlen("&")) { - Type.replace(Pos, strlen(" &"), "&"); - } - - // Replace " *" with "* ". - for (size_t Pos = 0; (Pos = Type.find(" *", Pos)) != std::string::npos; - Pos += strlen("*")) { - Type.replace(Pos, strlen(" *"), "* "); - } - - // Remove redundant tailing. - static constexpr StringRef TailsOfMultiWordType[] = { - " int", " char", " double", " long", " short"}; - bool RedundantRemoved = false; - for (auto Kw : TailsOfMultiWordType) { - const size_t Pos = Type.rfind(Kw); - if (Pos != std::string::npos) { - const size_t PtrCount = getAsteriskCount(Type, ND); - Type = Type.substr(0, Pos + Kw.size() + PtrCount); - RedundantRemoved = true; - break; - } - } - - TypeName = Type.erase(0, Type.find_first_not_of(' ')); - if (!RedundantRemoved) { - const std::size_t FoundSpace = Type.find(' '); - if (FoundSpace != std::string::npos) - Type = Type.substr(0, FoundSpace); - } - - TypeName = Type.erase(0, Type.find_first_not_of(' ')); - - const QualType QT = VD->getType(); - if (!QT.isNull() && QT->isArrayType()) - TypeName.append("[]"); - } - - return TypeName; -} - -IdentifierNamingCheck::IdentifierNamingCheck(StringRef Name, - ClangTidyContext *Context) - : RenamerClangTidyCheck(Name, Context), Context(Context), - GetConfigPerFile(Options.get("GetConfigPerFile", true)), - IgnoreFailedSplit(Options.get("IgnoreFailedSplit", false)) { - auto IterAndInserted = NamingStylesCache.try_emplace( - llvm::sys::path::parent_path(Context->getCurrentFile()), - getFileStyleFromOptions(Options)); - assert(IterAndInserted.second && "Couldn't insert Style"); - // Holding a reference to the data in the vector is safe as it should never - // move. - MainFileStyle = &IterAndInserted.first->getValue(); -} - -IdentifierNamingCheck::~IdentifierNamingCheck() = default; - namespace HungarianNotation { static bool checkOptionValid(int StyleKindIndex) { @@ -823,6 +645,184 @@ loadDefaultConfig(IdentifierNamingCheck::HungarianNotationOption &HNOption) { } // namespace HungarianNotation +IdentifierNamingCheck::NamingStyle::NamingStyle( + std::optional<IdentifierNamingCheck::CaseType> Case, StringRef Prefix, + StringRef Suffix, StringRef IgnoredRegexpStr, HungarianPrefixType HPType) + : Case(Case), Prefix(Prefix), Suffix(Suffix), + IgnoredRegexpStr(IgnoredRegexpStr), HPType(HPType) { + if (!IgnoredRegexpStr.empty()) { + IgnoredRegexp = + llvm::Regex(llvm::SmallString<128>({"^", IgnoredRegexpStr, "$"})); + if (!IgnoredRegexp.isValid()) + llvm::errs() << "Invalid IgnoredRegexp regular expression: " + << IgnoredRegexpStr; + } +} + +IdentifierNamingCheck::FileStyle IdentifierNamingCheck::getFileStyleFromOptions( + const ClangTidyCheck::OptionsView &Options) const { + IdentifierNamingCheck::HungarianNotationOption HNOption; + + HungarianNotation::loadDefaultConfig(HNOption); + HungarianNotation::loadFileConfig(Options, HNOption); + + SmallVector<std::optional<IdentifierNamingCheck::NamingStyle>, 0> Styles; + Styles.resize(SK_Count); + SmallString<64> StyleString; + for (unsigned I = 0; I < SK_Count; ++I) { + const size_t StyleSize = StyleNames[I].size(); + StyleString.assign({StyleNames[I], "HungarianPrefix"}); + + auto HPTOpt = + Options.get<IdentifierNamingCheck::HungarianPrefixType>(StyleString); + if (HPTOpt && !HungarianNotation::checkOptionValid(I)) + configurationDiag("invalid identifier naming option '%0'") << StyleString; + + memcpy(&StyleString[StyleSize], "IgnoredRegexp", 13); + StyleString.truncate(StyleSize + 13); + const std::optional<StringRef> IgnoredRegexpStr = Options.get(StyleString); + memcpy(&StyleString[StyleSize], "Prefix", 6); + StyleString.truncate(StyleSize + 6); + const std::optional<StringRef> Prefix(Options.get(StyleString)); + // Fast replacement of [Pre]fix -> [Suf]fix. + memcpy(&StyleString[StyleSize], "Suf", 3); + const std::optional<StringRef> Postfix(Options.get(StyleString)); + memcpy(&StyleString[StyleSize], "Case", 4); + StyleString.pop_back_n(2); + std::optional<CaseType> CaseOptional = + Options.get<IdentifierNamingCheck::CaseType>(StyleString); + + 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)); + } + const bool IgnoreMainLike = Options.get("IgnoreMainLikeFunctions", false); + const bool CheckAnonFieldInParent = + Options.get("CheckAnonFieldInParent", false); + return {std::move(Styles), std::move(HNOption), IgnoreMainLike, + CheckAnonFieldInParent}; +} + +static std::string getDeclTypeName(const NamedDecl *ND) { + const auto *VD = dyn_cast<ValueDecl>(ND); + if (!VD) + return {}; + + if (isa<FunctionDecl, EnumConstantDecl>(ND)) + return {}; + + // Get type text of variable declarations. + auto &SM = VD->getASTContext().getSourceManager(); + const char *Begin = SM.getCharacterData(VD->getBeginLoc()); + const char *End = SM.getCharacterData(VD->getEndLoc()); + intptr_t StrLen = End - Begin; + + // FIXME: Sometimes the value that returns from ValDecl->getEndLoc() + // is wrong(out of location of Decl). This causes `StrLen` will be assigned + // an unexpected large value. Current workaround to find the terminated + // character instead of the `getEndLoc()` function. + const char *EOL = strchr(Begin, '\n'); + if (!EOL) + EOL = Begin + strlen(Begin); + + const char *const PosList[] = {strchr(Begin, '='), strchr(Begin, ';'), + strchr(Begin, ','), strchr(Begin, ')'), EOL}; + for (const auto &Pos : PosList) + if (Pos > Begin) + EOL = std::min(EOL, Pos); + + StrLen = EOL - Begin; + std::string TypeName; + if (StrLen > 0) { + std::string Type(Begin, StrLen); + + static constexpr StringRef Keywords[] = { + // Constexpr specifiers + "constexpr", "constinit", "consteval", + // Qualifier + "const", "volatile", "restrict", "mutable", + // Storage class specifiers + "register", "static", "extern", "thread_local", + // Other keywords + "virtual"}; + + // Remove keywords + for (const StringRef Kw : Keywords) + for (size_t Pos = 0; (Pos = Type.find(Kw, Pos)) != std::string::npos;) + Type.replace(Pos, Kw.size(), ""); + TypeName = Type.erase(0, Type.find_first_not_of(' ')); + + // Remove template parameters + const size_t Pos = Type.find('<'); + if (Pos != std::string::npos) + TypeName = Type.erase(Pos, Type.size() - Pos); + + // Replace spaces with single space. + for (size_t Pos = 0; (Pos = Type.find(" ", Pos)) != std::string::npos; + Pos += strlen(" ")) { + Type.replace(Pos, strlen(" "), " "); + } + + // Replace " &" with "&". + for (size_t Pos = 0; (Pos = Type.find(" &", Pos)) != std::string::npos; + Pos += strlen("&")) { + Type.replace(Pos, strlen(" &"), "&"); + } + + // Replace " *" with "* ". + for (size_t Pos = 0; (Pos = Type.find(" *", Pos)) != std::string::npos; + Pos += strlen("*")) { + Type.replace(Pos, strlen(" *"), "* "); + } + + // Remove redundant tailing. + static constexpr StringRef TailsOfMultiWordType[] = { + " int", " char", " double", " long", " short"}; + bool RedundantRemoved = false; + for (auto Kw : TailsOfMultiWordType) { + const size_t Pos = Type.rfind(Kw); + if (Pos != std::string::npos) { + const size_t PtrCount = getAsteriskCount(Type, ND); + Type = Type.substr(0, Pos + Kw.size() + PtrCount); + RedundantRemoved = true; + break; + } + } + + TypeName = Type.erase(0, Type.find_first_not_of(' ')); + if (!RedundantRemoved) { + const std::size_t FoundSpace = Type.find(' '); + if (FoundSpace != std::string::npos) + Type = Type.substr(0, FoundSpace); + } + + TypeName = Type.erase(0, Type.find_first_not_of(' ')); + + const QualType QT = VD->getType(); + if (!QT.isNull() && QT->isArrayType()) + TypeName.append("[]"); + } + + return TypeName; +} + +IdentifierNamingCheck::IdentifierNamingCheck(StringRef Name, + ClangTidyContext *Context) + : RenamerClangTidyCheck(Name, Context), Context(Context), + GetConfigPerFile(Options.get("GetConfigPerFile", true)), + IgnoreFailedSplit(Options.get("IgnoreFailedSplit", false)) { + auto IterAndInserted = NamingStylesCache.try_emplace( + llvm::sys::path::parent_path(Context->getCurrentFile()), + getFileStyleFromOptions(Options)); + assert(IterAndInserted.second && "Couldn't insert Style"); + // Holding a reference to the data in the vector is safe as it should never + // move. + MainFileStyle = &IterAndInserted.first->getValue(); +} + +IdentifierNamingCheck::~IdentifierNamingCheck() = default; + void IdentifierNamingCheck::storeOptions(ClangTidyOptions::OptionMap &Opts) { RenamerClangTidyCheck::storeOptions(Opts); SmallString<64> StyleString; >From 225c2059ab6d33bb4a6cad48e1c3584cdd747963 Mon Sep 17 00:00:00 2001 From: Victor Chernyakin <[email protected]> Date: Wed, 24 Dec 2025 12:26:42 -0700 Subject: [PATCH 3/3] Reorder functions --- .../readability/IdentifierNamingCheck.cpp | 354 +++++++++--------- 1 file changed, 177 insertions(+), 177 deletions(-) diff --git a/clang-tools-extra/clang-tidy/readability/IdentifierNamingCheck.cpp b/clang-tools-extra/clang-tidy/readability/IdentifierNamingCheck.cpp index d155cab5330a7..6fcabac7257e0 100644 --- a/clang-tools-extra/clang-tidy/readability/IdentifierNamingCheck.cpp +++ b/clang-tools-extra/clang-tidy/readability/IdentifierNamingCheck.cpp @@ -330,50 +330,164 @@ loadFileConfig(const ClangTidyCheck::OptionsView &Options, } } +static std::string getEnumPrefix(const EnumConstantDecl *ECD) { + const auto *ED = cast<EnumDecl>(ECD->getDeclContext()); + + std::string Name = ED->getName().str(); + if (StringRef(Name).contains("enum")) { + Name = Name.substr(strlen("enum"), Name.length() - strlen("enum")); + Name = Name.erase(0, Name.find_first_not_of(' ')); + } + + static const llvm::Regex Splitter( + "([a-z0-9A-Z]*)(_+)|([A-Z]?[a-z0-9]+)([A-Z]|$)|([A-Z]+)([A-Z]|$)"); + + const StringRef EnumName(Name); + SmallVector<StringRef, 8> Substrs; + EnumName.split(Substrs, "_", -1, false); + + SmallVector<StringRef, 8> Words; + SmallVector<StringRef, 8> Groups; + for (auto Substr : Substrs) { + while (!Substr.empty()) { + Groups.clear(); + if (!Splitter.match(Substr, &Groups)) + break; + + if (!Groups[2].empty()) { + Words.push_back(Groups[1]); + Substr = Substr.substr(Groups[0].size()); + } else if (!Groups[3].empty()) { + Words.push_back(Groups[3]); + Substr = Substr.substr(Groups[0].size() - Groups[4].size()); + } else if (!Groups[5].empty()) { + Words.push_back(Groups[5]); + Substr = Substr.substr(Groups[0].size() - Groups[6].size()); + } + } + } + + std::string Initial; + for (const StringRef Word : Words) + Initial += tolower(Word[0]); + + return Initial; +} + static std::string -getPrefix(const Decl *D, - const IdentifierNamingCheck::HungarianNotationOption &HNOption) { - if (!D) - return {}; - const auto *ND = dyn_cast<NamedDecl>(D); - if (!ND) +getClassPrefix(const CXXRecordDecl *CRD, + const IdentifierNamingCheck::HungarianNotationOption &HNOption) { + if (CRD->isUnion()) return {}; - std::string Prefix; - if (const auto *ECD = dyn_cast<EnumConstantDecl>(ND)) { - Prefix = getEnumPrefix(ECD); - } else if (const auto *CRD = dyn_cast<CXXRecordDecl>(ND)) { - Prefix = getClassPrefix(CRD, HNOption); - } else if (isa<VarDecl, FieldDecl, RecordDecl>(ND)) { - const std::string TypeName = getDeclTypeName(ND); - if (!TypeName.empty()) - Prefix = getDataTypePrefix(TypeName, ND, HNOption); - } + if (CRD->isStruct() && + !isOptionEnabled("TreatStructAsClass", HNOption.General)) + return {}; - return Prefix; + return CRD->isAbstract() ? "I" : "C"; } -static bool removeDuplicatedPrefix( - SmallVector<StringRef, 8> &Words, - const IdentifierNamingCheck::HungarianNotationOption &HNOption) { - if (Words.size() <= 1) - return true; +static std::string getDeclTypeName(const NamedDecl *ND) { + const auto *VD = dyn_cast<ValueDecl>(ND); + if (!VD) + return {}; - const std::string CorrectName = Words[0].str(); - const std::vector<llvm::StringMap<std::string>> MapList = { - HNOption.CString, HNOption.DerivedType, HNOption.PrimitiveType, - HNOption.UserDefinedType}; + if (isa<FunctionDecl, EnumConstantDecl>(ND)) + return {}; - for (const auto &Map : MapList) { - for (const auto &Str : Map) { - if (Str.getValue() == CorrectName) { - Words.erase(Words.begin(), Words.begin() + 1); - return true; + // Get type text of variable declarations. + auto &SM = VD->getASTContext().getSourceManager(); + const char *Begin = SM.getCharacterData(VD->getBeginLoc()); + const char *End = SM.getCharacterData(VD->getEndLoc()); + intptr_t StrLen = End - Begin; + + // FIXME: Sometimes the value that returns from ValDecl->getEndLoc() + // is wrong(out of location of Decl). This causes `StrLen` will be assigned + // an unexpected large value. Current workaround to find the terminated + // character instead of the `getEndLoc()` function. + const char *EOL = strchr(Begin, '\n'); + if (!EOL) + EOL = Begin + strlen(Begin); + + const char *const PosList[] = {strchr(Begin, '='), strchr(Begin, ';'), + strchr(Begin, ','), strchr(Begin, ')'), EOL}; + for (const auto &Pos : PosList) + if (Pos > Begin) + EOL = std::min(EOL, Pos); + + StrLen = EOL - Begin; + std::string TypeName; + if (StrLen > 0) { + std::string Type(Begin, StrLen); + + static constexpr StringRef Keywords[] = { + // Constexpr specifiers + "constexpr", "constinit", "consteval", + // Qualifier + "const", "volatile", "restrict", "mutable", + // Storage class specifiers + "register", "static", "extern", "thread_local", + // Other keywords + "virtual"}; + + // Remove keywords + for (const StringRef Kw : Keywords) + for (size_t Pos = 0; (Pos = Type.find(Kw, Pos)) != std::string::npos;) + Type.replace(Pos, Kw.size(), ""); + TypeName = Type.erase(0, Type.find_first_not_of(' ')); + + // Remove template parameters + const size_t Pos = Type.find('<'); + if (Pos != std::string::npos) + TypeName = Type.erase(Pos, Type.size() - Pos); + + // Replace spaces with single space. + for (size_t Pos = 0; (Pos = Type.find(" ", Pos)) != std::string::npos; + Pos += strlen(" ")) { + Type.replace(Pos, strlen(" "), " "); + } + + // Replace " &" with "&". + for (size_t Pos = 0; (Pos = Type.find(" &", Pos)) != std::string::npos; + Pos += strlen("&")) { + Type.replace(Pos, strlen(" &"), "&"); + } + + // Replace " *" with "* ". + for (size_t Pos = 0; (Pos = Type.find(" *", Pos)) != std::string::npos; + Pos += strlen("*")) { + Type.replace(Pos, strlen(" *"), "* "); + } + + // Remove redundant tailing. + static constexpr StringRef TailsOfMultiWordType[] = { + " int", " char", " double", " long", " short"}; + bool RedundantRemoved = false; + for (auto Kw : TailsOfMultiWordType) { + const size_t Pos = Type.rfind(Kw); + if (Pos != std::string::npos) { + const size_t PtrCount = getAsteriskCount(Type, ND); + Type = Type.substr(0, Pos + Kw.size() + PtrCount); + RedundantRemoved = true; + break; } } + + TypeName = Type.erase(0, Type.find_first_not_of(' ')); + if (!RedundantRemoved) { + const std::size_t FoundSpace = Type.find(' '); + if (FoundSpace != std::string::npos) + Type = Type.substr(0, FoundSpace); + } + + TypeName = Type.erase(0, Type.find_first_not_of(' ')); + + const QualType QT = VD->getType(); + if (!QT.isNull() && QT->isArrayType()) + TypeName.append("[]"); } - return false; + return TypeName; } static std::string getDataTypePrefix( @@ -457,60 +571,49 @@ static std::string getDataTypePrefix( } static std::string -getClassPrefix(const CXXRecordDecl *CRD, - const IdentifierNamingCheck::HungarianNotationOption &HNOption) { - if (CRD->isUnion()) +getPrefix(const Decl *D, + const IdentifierNamingCheck::HungarianNotationOption &HNOption) { + if (!D) return {}; - - if (CRD->isStruct() && - !isOptionEnabled("TreatStructAsClass", HNOption.General)) + const auto *ND = dyn_cast<NamedDecl>(D); + if (!ND) return {}; - return CRD->isAbstract() ? "I" : "C"; -} - -static std::string getEnumPrefix(const EnumConstantDecl *ECD) { - const auto *ED = cast<EnumDecl>(ECD->getDeclContext()); - - std::string Name = ED->getName().str(); - if (StringRef(Name).contains("enum")) { - Name = Name.substr(strlen("enum"), Name.length() - strlen("enum")); - Name = Name.erase(0, Name.find_first_not_of(' ')); + std::string Prefix; + if (const auto *ECD = dyn_cast<EnumConstantDecl>(ND)) { + Prefix = getEnumPrefix(ECD); + } else if (const auto *CRD = dyn_cast<CXXRecordDecl>(ND)) { + Prefix = getClassPrefix(CRD, HNOption); + } else if (isa<VarDecl, FieldDecl, RecordDecl>(ND)) { + const std::string TypeName = getDeclTypeName(ND); + if (!TypeName.empty()) + Prefix = getDataTypePrefix(TypeName, ND, HNOption); } - static const llvm::Regex Splitter( - "([a-z0-9A-Z]*)(_+)|([A-Z]?[a-z0-9]+)([A-Z]|$)|([A-Z]+)([A-Z]|$)"); + return Prefix; +} - const StringRef EnumName(Name); - SmallVector<StringRef, 8> Substrs; - EnumName.split(Substrs, "_", -1, false); +static bool removeDuplicatedPrefix( + SmallVector<StringRef, 8> &Words, + const IdentifierNamingCheck::HungarianNotationOption &HNOption) { + if (Words.size() <= 1) + return true; - SmallVector<StringRef, 8> Words; - SmallVector<StringRef, 8> Groups; - for (auto Substr : Substrs) { - while (!Substr.empty()) { - Groups.clear(); - if (!Splitter.match(Substr, &Groups)) - break; + const std::string CorrectName = Words[0].str(); + const std::vector<llvm::StringMap<std::string>> MapList = { + HNOption.CString, HNOption.DerivedType, HNOption.PrimitiveType, + HNOption.UserDefinedType}; - if (!Groups[2].empty()) { - Words.push_back(Groups[1]); - Substr = Substr.substr(Groups[0].size()); - } else if (!Groups[3].empty()) { - Words.push_back(Groups[3]); - Substr = Substr.substr(Groups[0].size() - Groups[4].size()); - } else if (!Groups[5].empty()) { - Words.push_back(Groups[5]); - Substr = Substr.substr(Groups[0].size() - Groups[6].size()); + for (const auto &Map : MapList) { + for (const auto &Str : Map) { + if (Str.getValue() == CorrectName) { + Words.erase(Words.begin(), Words.begin() + 1); + return true; } } } - std::string Initial; - for (const StringRef Word : Words) - Initial += tolower(Word[0]); - - return Initial; + return false; } static size_t getAsteriskCount(const std::string &TypeName) { @@ -704,109 +807,6 @@ IdentifierNamingCheck::FileStyle IdentifierNamingCheck::getFileStyleFromOptions( CheckAnonFieldInParent}; } -static std::string getDeclTypeName(const NamedDecl *ND) { - const auto *VD = dyn_cast<ValueDecl>(ND); - if (!VD) - return {}; - - if (isa<FunctionDecl, EnumConstantDecl>(ND)) - return {}; - - // Get type text of variable declarations. - auto &SM = VD->getASTContext().getSourceManager(); - const char *Begin = SM.getCharacterData(VD->getBeginLoc()); - const char *End = SM.getCharacterData(VD->getEndLoc()); - intptr_t StrLen = End - Begin; - - // FIXME: Sometimes the value that returns from ValDecl->getEndLoc() - // is wrong(out of location of Decl). This causes `StrLen` will be assigned - // an unexpected large value. Current workaround to find the terminated - // character instead of the `getEndLoc()` function. - const char *EOL = strchr(Begin, '\n'); - if (!EOL) - EOL = Begin + strlen(Begin); - - const char *const PosList[] = {strchr(Begin, '='), strchr(Begin, ';'), - strchr(Begin, ','), strchr(Begin, ')'), EOL}; - for (const auto &Pos : PosList) - if (Pos > Begin) - EOL = std::min(EOL, Pos); - - StrLen = EOL - Begin; - std::string TypeName; - if (StrLen > 0) { - std::string Type(Begin, StrLen); - - static constexpr StringRef Keywords[] = { - // Constexpr specifiers - "constexpr", "constinit", "consteval", - // Qualifier - "const", "volatile", "restrict", "mutable", - // Storage class specifiers - "register", "static", "extern", "thread_local", - // Other keywords - "virtual"}; - - // Remove keywords - for (const StringRef Kw : Keywords) - for (size_t Pos = 0; (Pos = Type.find(Kw, Pos)) != std::string::npos;) - Type.replace(Pos, Kw.size(), ""); - TypeName = Type.erase(0, Type.find_first_not_of(' ')); - - // Remove template parameters - const size_t Pos = Type.find('<'); - if (Pos != std::string::npos) - TypeName = Type.erase(Pos, Type.size() - Pos); - - // Replace spaces with single space. - for (size_t Pos = 0; (Pos = Type.find(" ", Pos)) != std::string::npos; - Pos += strlen(" ")) { - Type.replace(Pos, strlen(" "), " "); - } - - // Replace " &" with "&". - for (size_t Pos = 0; (Pos = Type.find(" &", Pos)) != std::string::npos; - Pos += strlen("&")) { - Type.replace(Pos, strlen(" &"), "&"); - } - - // Replace " *" with "* ". - for (size_t Pos = 0; (Pos = Type.find(" *", Pos)) != std::string::npos; - Pos += strlen("*")) { - Type.replace(Pos, strlen(" *"), "* "); - } - - // Remove redundant tailing. - static constexpr StringRef TailsOfMultiWordType[] = { - " int", " char", " double", " long", " short"}; - bool RedundantRemoved = false; - for (auto Kw : TailsOfMultiWordType) { - const size_t Pos = Type.rfind(Kw); - if (Pos != std::string::npos) { - const size_t PtrCount = getAsteriskCount(Type, ND); - Type = Type.substr(0, Pos + Kw.size() + PtrCount); - RedundantRemoved = true; - break; - } - } - - TypeName = Type.erase(0, Type.find_first_not_of(' ')); - if (!RedundantRemoved) { - const std::size_t FoundSpace = Type.find(' '); - if (FoundSpace != std::string::npos) - Type = Type.substr(0, FoundSpace); - } - - TypeName = Type.erase(0, Type.find_first_not_of(' ')); - - const QualType QT = VD->getType(); - if (!QT.isNull() && QT->isArrayType()) - TypeName.append("[]"); - } - - return TypeName; -} - IdentifierNamingCheck::IdentifierNamingCheck(StringRef Name, ClangTidyContext *Context) : RenamerClangTidyCheck(Name, Context), Context(Context), _______________________________________________ cfe-commits mailing list [email protected] https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
