11#include "clang/AST/ASTContext.h"
12#include "clang/Lex/Token.h"
29 "declaration uses identifier '%0', which is %select{a reserved "
30 "identifier|not a reserved identifier|reserved in the global namespace}1";
40llvm::SmallVector<llvm::Regex>
41ReservedIdentifierCheck::parseAllowedIdentifiers()
const {
42 llvm::SmallVector<llvm::Regex> AllowedIdentifiers;
43 AllowedIdentifiers.reserve(AllowedIdentifiersRaw.size());
45 for (
const auto &Identifier : AllowedIdentifiersRaw) {
46 AllowedIdentifiers.emplace_back(Identifier.str());
47 if (!AllowedIdentifiers.back().isValid()) {
48 configurationDiag(
"Invalid allowed identifier regex '%0'") << Identifier;
49 AllowedIdentifiers.pop_back();
53 return AllowedIdentifiers;
59 Invert(Options.get(
"Invert", false)),
60 AllowedIdentifiersRaw(
utils::options::parseStringList(
61 Options.get(
"AllowedIdentifiers",
""))),
62 AllowedIdentifiers(parseAllowedIdentifiers()) {}
66 Options.store(Opts,
"Invert", Invert);
67 Options.store(Opts,
"AllowedIdentifiers",
73 std::unique_copy(Str.begin(), Str.end(), std::back_inserter(Result),
74 [C](
char A,
char B) { return A == C && B == C; });
79 const LangOptions &LangOpts) {
80 if (LangOpts.CPlusPlus)
81 return Name.contains(
"__");
82 return Name.starts_with(
"__");
85static std::optional<std::string>
93 return Name.size() >= 2 && Name[0] ==
'_' && std::isupper(Name[1]);
98 return std::string(Name.drop_front(1));
103 bool IsInGlobalNamespace,
105 return !IsMacro && IsInGlobalNamespace && Name.starts_with(
"_");
108static std::optional<std::string>
112 return std::string(Name.drop_front(1));
117 assert(!Name.empty());
118 if (Name[0] ==
'_' || std::isupper(Name[0]))
119 Name.insert(Name.begin(),
'_');
121 Name.insert(Name.begin(), 2,
'_');
125static std::optional<RenamerClangTidyCheck::FailureInfo>
127 const LangOptions &LangOpts,
bool Invert,
128 ArrayRef<llvm::Regex> AllowedIdentifiers) {
129 assert(!Name.empty());
131 if (llvm::any_of(AllowedIdentifiers, [&](
const llvm::Regex &Regex) {
132 return Regex.match(Name);
142 std::optional<FailureInfo> Info;
143 auto AppendFailure = [&](StringRef Kind, std::string &&Fixup) {
145 Info = FailureInfo{std::string(Kind), std::move(Fixup)};
147 Info->KindName += Kind;
148 Info->Fixup = std::move(Fixup);
151 auto InProgressFixup = [&] {
152 return llvm::transformOptional(
154 [](
const FailureInfo &Info) {
return StringRef(Info.Fixup); })
162 InProgressFixup(), IsInGlobalNamespace, IsMacro))
175std::optional<RenamerClangTidyCheck::FailureInfo>
176ReservedIdentifierCheck::getDeclFailureInfo(
const NamedDecl *Decl,
177 const SourceManager &)
const {
178 assert(Decl && Decl->getIdentifier() && !Decl->getName().empty() &&
179 "Decl must be an explicit identifier with a name.");
181 if (Decl->isImplicit())
185 Decl->getName(), isa<TranslationUnitDecl>(Decl->getDeclContext()),
186 false, getLangOpts(), Invert, AllowedIdentifiers);
189std::optional<RenamerClangTidyCheck::FailureInfo>
190ReservedIdentifierCheck::getMacroFailureInfo(
const Token &MacroNameTok,
191 const SourceManager &)
const {
193 true, getLangOpts(), Invert,
197RenamerClangTidyCheck::DiagInfo
198ReservedIdentifierCheck::getDiagInfo(
const NamingCheckId &ID,
199 const NamingCheckFailure &Failure)
const {
200 return DiagInfo{
Message, [&](DiagnosticBuilder &Diag) {
Every ClangTidyCheck reports errors through a DiagnosticsEngine provided by this context.
RenamerClangTidyCheck(StringRef CheckName, ClangTidyContext *Context)
void storeOptions(ClangTidyOptions::OptionMap &Opts) override
Derived classes that override this function should call this method from the overridden method.
ReservedIdentifierCheck(StringRef Name, ClangTidyContext *Context)
void storeOptions(ClangTidyOptions::OptionMap &Opts) override
static std::optional< std::string > getDoubleUnderscoreFixup(StringRef Name, const LangOptions &LangOpts)
static const char DoubleUnderscoreTag[]
static const char GlobalUnderscoreTag[]
static const char Message[]
static std::optional< std::string > getUnderscoreGlobalNamespaceFixup(StringRef Name, bool IsInGlobalNamespace, bool IsMacro)
static const char UnderscoreCapitalTag[]
static std::string getNonReservedFixup(std::string Name)
static const char NonReservedTag[]
static std::optional< RenamerClangTidyCheck::FailureInfo > getFailureInfoImpl(StringRef Name, bool IsInGlobalNamespace, bool IsMacro, const LangOptions &LangOpts, bool Invert, ArrayRef< llvm::Regex > AllowedIdentifiers)
static std::string collapseConsecutive(StringRef Str, char C)
static bool hasReservedDoubleUnderscore(StringRef Name, const LangOptions &LangOpts)
static bool startsWithUnderscoreCapital(StringRef Name)
static bool startsWithUnderscoreInGlobalNamespace(StringRef Name, bool IsInGlobalNamespace, bool IsMacro)
static std::optional< std::string > getUnderscoreCapitalFixup(StringRef Name)
static int getMessageSelectIndex(StringRef Tag)
std::string serializeStringList(ArrayRef< StringRef > Strings)
Serialize a sequence of names that can be parsed by parseStringList.
llvm::StringMap< ClangTidyValue > OptionMap
Information describing a failed check.