1 //===--- IdentifierNamingCheck.cpp - clang-tidy ---------------------------===//
2 //
3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4 // See https://llvm.org/LICENSE.txt for license information.
5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6 //
7 //===----------------------------------------------------------------------===//
8 
9 #include "IdentifierNamingCheck.h"
10 
11 #include "../GlobList.h"
12 #include "clang/AST/CXXInheritance.h"
13 #include "clang/Lex/PPCallbacks.h"
14 #include "clang/Lex/Preprocessor.h"
15 #include "llvm/ADT/ArrayRef.h"
16 #include "llvm/ADT/DenseMapInfo.h"
17 #include "llvm/Support/Debug.h"
18 #include "llvm/Support/Error.h"
19 #include "llvm/Support/FormatVariadic.h"
20 #include "llvm/Support/Path.h"
21 #include "llvm/Support/Regex.h"
22 
23 #define DEBUG_TYPE "clang-tidy"
24 
25 // FixItHint
26 
27 using namespace clang::ast_matchers;
28 
29 namespace clang {
30 namespace tidy {
31 
32 llvm::ArrayRef<
33     std::pair<readability::IdentifierNamingCheck::CaseType, StringRef>>
34 OptionEnumMapping<
getEnumMapping()35     readability::IdentifierNamingCheck::CaseType>::getEnumMapping() {
36   static constexpr std::pair<readability::IdentifierNamingCheck::CaseType,
37                              StringRef>
38       Mapping[] = {
39           {readability::IdentifierNamingCheck::CT_AnyCase, "aNy_CasE"},
40           {readability::IdentifierNamingCheck::CT_LowerCase, "lower_case"},
41           {readability::IdentifierNamingCheck::CT_UpperCase, "UPPER_CASE"},
42           {readability::IdentifierNamingCheck::CT_CamelBack, "camelBack"},
43           {readability::IdentifierNamingCheck::CT_CamelCase, "CamelCase"},
44           {readability::IdentifierNamingCheck::CT_CamelSnakeCase,
45            "Camel_Snake_Case"},
46           {readability::IdentifierNamingCheck::CT_CamelSnakeBack,
47            "camel_Snake_Back"}};
48   return llvm::makeArrayRef(Mapping);
49 }
50 
51 namespace readability {
52 
53 // clang-format off
54 #define NAMING_KEYS(m) \
55     m(Namespace) \
56     m(InlineNamespace) \
57     m(EnumConstant) \
58     m(ScopedEnumConstant) \
59     m(ConstexprVariable) \
60     m(ConstantMember) \
61     m(PrivateMember) \
62     m(ProtectedMember) \
63     m(PublicMember) \
64     m(Member) \
65     m(ClassConstant) \
66     m(ClassMember) \
67     m(GlobalConstant) \
68     m(GlobalConstantPointer) \
69     m(GlobalPointer) \
70     m(GlobalVariable) \
71     m(LocalConstant) \
72     m(LocalConstantPointer) \
73     m(LocalPointer) \
74     m(LocalVariable) \
75     m(StaticConstant) \
76     m(StaticVariable) \
77     m(Constant) \
78     m(Variable) \
79     m(ConstantParameter) \
80     m(ParameterPack) \
81     m(Parameter) \
82     m(PointerParameter) \
83     m(ConstantPointerParameter) \
84     m(AbstractClass) \
85     m(Struct) \
86     m(Class) \
87     m(Union) \
88     m(Enum) \
89     m(GlobalFunction) \
90     m(ConstexprFunction) \
91     m(Function) \
92     m(ConstexprMethod) \
93     m(VirtualMethod) \
94     m(ClassMethod) \
95     m(PrivateMethod) \
96     m(ProtectedMethod) \
97     m(PublicMethod) \
98     m(Method) \
99     m(Typedef) \
100     m(TypeTemplateParameter) \
101     m(ValueTemplateParameter) \
102     m(TemplateTemplateParameter) \
103     m(TemplateParameter) \
104     m(TypeAlias) \
105     m(MacroDefinition) \
106     m(ObjcIvar) \
107 
108 enum StyleKind {
109 #define ENUMERATE(v) SK_ ## v,
110   NAMING_KEYS(ENUMERATE)
111 #undef ENUMERATE
112   SK_Count,
113   SK_Invalid
114 };
115 
116 static StringRef const StyleNames[] = {
117 #define STRINGIZE(v) #v,
118   NAMING_KEYS(STRINGIZE)
119 #undef STRINGIZE
120 };
121 
122 #undef NAMING_KEYS
123 // clang-format on
124 
NamingStyle(llvm::Optional<IdentifierNamingCheck::CaseType> Case,const std::string & Prefix,const std::string & Suffix,const std::string & IgnoredRegexpStr)125 IdentifierNamingCheck::NamingStyle::NamingStyle(
126     llvm::Optional<IdentifierNamingCheck::CaseType> Case,
127     const std::string &Prefix, const std::string &Suffix,
128     const std::string &IgnoredRegexpStr)
129     : Case(Case), Prefix(Prefix), Suffix(Suffix),
130       IgnoredRegexpStr(IgnoredRegexpStr) {
131   if (!IgnoredRegexpStr.empty()) {
132     IgnoredRegexp =
133         llvm::Regex(llvm::SmallString<128>({"^", IgnoredRegexpStr, "$"}));
134     if (!IgnoredRegexp.isValid())
135       llvm::errs() << "Invalid IgnoredRegexp regular expression: "
136                    << IgnoredRegexpStr;
137   }
138 }
139 
140 static IdentifierNamingCheck::FileStyle
getFileStyleFromOptions(const ClangTidyCheck::OptionsView & Options)141 getFileStyleFromOptions(const ClangTidyCheck::OptionsView &Options) {
142   SmallVector<llvm::Optional<IdentifierNamingCheck::NamingStyle>, 0> Styles;
143   Styles.resize(SK_Count);
144   SmallString<64> StyleString;
145   for (unsigned I = 0; I < SK_Count; ++I) {
146     StyleString = StyleNames[I];
147     size_t StyleSize = StyleString.size();
148     StyleString.append("IgnoredRegexp");
149     std::string IgnoredRegexpStr = Options.get(StyleString, "");
150     StyleString.resize(StyleSize);
151     StyleString.append("Prefix");
152     std::string Prefix(Options.get(StyleString, ""));
153     // Fast replacement of [Pre]fix -> [Suf]fix.
154     memcpy(&StyleString[StyleSize], "Suf", 3);
155     std::string Postfix(Options.get(StyleString, ""));
156     memcpy(&StyleString[StyleSize], "Case", 4);
157     StyleString.pop_back();
158     StyleString.pop_back();
159     auto CaseOptional =
160         Options.getOptional<IdentifierNamingCheck::CaseType>(StyleString);
161 
162     if (CaseOptional || !Prefix.empty() || !Postfix.empty() ||
163         !IgnoredRegexpStr.empty())
164       Styles[I].emplace(std::move(CaseOptional), std::move(Prefix),
165                         std::move(Postfix), std::move(IgnoredRegexpStr));
166   }
167   bool IgnoreMainLike = Options.get("IgnoreMainLikeFunctions", false);
168   return {std::move(Styles), IgnoreMainLike};
169 }
170 
IdentifierNamingCheck(StringRef Name,ClangTidyContext * Context)171 IdentifierNamingCheck::IdentifierNamingCheck(StringRef Name,
172                                              ClangTidyContext *Context)
173     : RenamerClangTidyCheck(Name, Context), Context(Context), CheckName(Name),
174       GetConfigPerFile(Options.get("GetConfigPerFile", true)),
175       IgnoreFailedSplit(Options.get("IgnoreFailedSplit", false)) {
176 
177   auto IterAndInserted = NamingStylesCache.try_emplace(
178       llvm::sys::path::parent_path(Context->getCurrentFile()),
179       getFileStyleFromOptions(Options));
180   assert(IterAndInserted.second && "Couldn't insert Style");
181   // Holding a reference to the data in the vector is safe as it should never
182   // move.
183   MainFileStyle = &IterAndInserted.first->getValue();
184 }
185 
186 IdentifierNamingCheck::~IdentifierNamingCheck() = default;
187 
storeOptions(ClangTidyOptions::OptionMap & Opts)188 void IdentifierNamingCheck::storeOptions(ClangTidyOptions::OptionMap &Opts) {
189   RenamerClangTidyCheck::storeOptions(Opts);
190   SmallString<64> StyleString;
191   ArrayRef<llvm::Optional<NamingStyle>> Styles = MainFileStyle->getStyles();
192   for (size_t I = 0; I < SK_Count; ++I) {
193     if (!Styles[I])
194       continue;
195     StyleString = StyleNames[I];
196     size_t StyleSize = StyleString.size();
197     StyleString.append("IgnoredRegexp");
198     Options.store(Opts, StyleString, Styles[I]->IgnoredRegexpStr);
199     StyleString.resize(StyleSize);
200     StyleString.append("Prefix");
201     Options.store(Opts, StyleString, Styles[I]->Prefix);
202     // Fast replacement of [Pre]fix -> [Suf]fix.
203     memcpy(&StyleString[StyleSize], "Suf", 3);
204     Options.store(Opts, StyleString, Styles[I]->Suffix);
205     if (Styles[I]->Case) {
206       memcpy(&StyleString[StyleSize], "Case", 4);
207       StyleString.pop_back();
208       StyleString.pop_back();
209       Options.store(Opts, StyleString, *Styles[I]->Case);
210     }
211   }
212   Options.store(Opts, "GetConfigPerFile", GetConfigPerFile);
213   Options.store(Opts, "IgnoreFailedSplit", IgnoreFailedSplit);
214   Options.store(Opts, "IgnoreMainLikeFunctions",
215                 MainFileStyle->isIgnoringMainLikeFunction());
216 }
217 
matchesStyle(StringRef Name,const IdentifierNamingCheck::NamingStyle & Style)218 static bool matchesStyle(StringRef Name,
219                          const IdentifierNamingCheck::NamingStyle &Style) {
220   static llvm::Regex Matchers[] = {
221       llvm::Regex("^.*$"),
222       llvm::Regex("^[a-z][a-z0-9_]*$"),
223       llvm::Regex("^[a-z][a-zA-Z0-9]*$"),
224       llvm::Regex("^[A-Z][A-Z0-9_]*$"),
225       llvm::Regex("^[A-Z][a-zA-Z0-9]*$"),
226       llvm::Regex("^[A-Z]([a-z0-9]*(_[A-Z])?)*"),
227       llvm::Regex("^[a-z]([a-z0-9]*(_[A-Z])?)*"),
228   };
229 
230   if (!Name.consume_front(Style.Prefix))
231     return false;
232   if (!Name.consume_back(Style.Suffix))
233     return false;
234 
235   // Ensure the name doesn't have any extra underscores beyond those specified
236   // in the prefix and suffix.
237   if (Name.startswith("_") || Name.endswith("_"))
238     return false;
239 
240   if (Style.Case && !Matchers[static_cast<size_t>(*Style.Case)].match(Name))
241     return false;
242 
243   return true;
244 }
245 
fixupWithCase(StringRef Name,IdentifierNamingCheck::CaseType Case)246 static std::string fixupWithCase(StringRef Name,
247                                  IdentifierNamingCheck::CaseType Case) {
248   static llvm::Regex Splitter(
249       "([a-z0-9A-Z]*)(_+)|([A-Z]?[a-z0-9]+)([A-Z]|$)|([A-Z]+)([A-Z]|$)");
250 
251   SmallVector<StringRef, 8> Substrs;
252   Name.split(Substrs, "_", -1, false);
253 
254   SmallVector<StringRef, 8> Words;
255   SmallVector<StringRef, 8> Groups;
256   for (auto Substr : Substrs) {
257     while (!Substr.empty()) {
258       Groups.clear();
259       if (!Splitter.match(Substr, &Groups))
260         break;
261 
262       if (Groups[2].size() > 0) {
263         Words.push_back(Groups[1]);
264         Substr = Substr.substr(Groups[0].size());
265       } else if (Groups[3].size() > 0) {
266         Words.push_back(Groups[3]);
267         Substr = Substr.substr(Groups[0].size() - Groups[4].size());
268       } else if (Groups[5].size() > 0) {
269         Words.push_back(Groups[5]);
270         Substr = Substr.substr(Groups[0].size() - Groups[6].size());
271       }
272     }
273   }
274 
275   if (Words.empty())
276     return Name.str();
277 
278   SmallString<128> Fixup;
279   switch (Case) {
280   case IdentifierNamingCheck::CT_AnyCase:
281     return Name.str();
282     break;
283 
284   case IdentifierNamingCheck::CT_LowerCase:
285     for (auto const &Word : Words) {
286       if (&Word != &Words.front())
287         Fixup += "_";
288       Fixup += Word.lower();
289     }
290     break;
291 
292   case IdentifierNamingCheck::CT_UpperCase:
293     for (auto const &Word : Words) {
294       if (&Word != &Words.front())
295         Fixup += "_";
296       Fixup += Word.upper();
297     }
298     break;
299 
300   case IdentifierNamingCheck::CT_CamelCase:
301     for (auto const &Word : Words) {
302       Fixup += toupper(Word.front());
303       Fixup += Word.substr(1).lower();
304     }
305     break;
306 
307   case IdentifierNamingCheck::CT_CamelBack:
308     for (auto const &Word : Words) {
309       if (&Word == &Words.front()) {
310         Fixup += Word.lower();
311       } else {
312         Fixup += toupper(Word.front());
313         Fixup += Word.substr(1).lower();
314       }
315     }
316     break;
317 
318   case IdentifierNamingCheck::CT_CamelSnakeCase:
319     for (auto const &Word : Words) {
320       if (&Word != &Words.front())
321         Fixup += "_";
322       Fixup += toupper(Word.front());
323       Fixup += Word.substr(1).lower();
324     }
325     break;
326 
327   case IdentifierNamingCheck::CT_CamelSnakeBack:
328     for (auto const &Word : Words) {
329       if (&Word != &Words.front()) {
330         Fixup += "_";
331         Fixup += toupper(Word.front());
332       } else {
333         Fixup += tolower(Word.front());
334       }
335       Fixup += Word.substr(1).lower();
336     }
337     break;
338   }
339 
340   return Fixup.str().str();
341 }
342 
isParamInMainLikeFunction(const ParmVarDecl & ParmDecl,bool IncludeMainLike)343 static bool isParamInMainLikeFunction(const ParmVarDecl &ParmDecl,
344                                       bool IncludeMainLike) {
345   const auto *FDecl =
346       dyn_cast_or_null<FunctionDecl>(ParmDecl.getParentFunctionOrMethod());
347   if (!FDecl)
348     return false;
349   if (FDecl->isMain())
350     return true;
351   if (!IncludeMainLike)
352     return false;
353   if (FDecl->getAccess() != AS_public && FDecl->getAccess() != AS_none)
354     return false;
355   enum MainType { None, Main, WMain };
356   auto IsCharPtrPtr = [](QualType QType) -> MainType {
357     if (QType.isNull())
358       return None;
359     if (QType = QType->getPointeeType(), QType.isNull())
360       return None;
361     if (QType = QType->getPointeeType(), QType.isNull())
362       return None;
363     if (QType->isCharType())
364       return Main;
365     if (QType->isWideCharType())
366       return WMain;
367     return None;
368   };
369   auto IsIntType = [](QualType QType) {
370     if (QType.isNull())
371       return false;
372     if (const auto *Builtin =
373             dyn_cast<BuiltinType>(QType->getUnqualifiedDesugaredType())) {
374       return Builtin->getKind() == BuiltinType::Int;
375     }
376     return false;
377   };
378   if (!IsIntType(FDecl->getReturnType()))
379     return false;
380   if (FDecl->getNumParams() < 2 || FDecl->getNumParams() > 3)
381     return false;
382   if (!IsIntType(FDecl->parameters()[0]->getType()))
383     return false;
384   MainType Type = IsCharPtrPtr(FDecl->parameters()[1]->getType());
385   if (Type == None)
386     return false;
387   if (FDecl->getNumParams() == 3 &&
388       IsCharPtrPtr(FDecl->parameters()[2]->getType()) != Type)
389     return false;
390 
391   if (Type == Main) {
392     static llvm::Regex Matcher(
393         "(^[Mm]ain([_A-Z]|$))|([a-z0-9_]Main([_A-Z]|$))|(_main(_|$))");
394     assert(Matcher.isValid() && "Invalid Matcher for main like functions.");
395     return Matcher.match(FDecl->getName());
396   } else {
397     static llvm::Regex Matcher("(^((W[Mm])|(wm))ain([_A-Z]|$))|([a-z0-9_]W[Mm]"
398                                "ain([_A-Z]|$))|(_wmain(_|$))");
399     assert(Matcher.isValid() && "Invalid Matcher for wmain like functions.");
400     return Matcher.match(FDecl->getName());
401   }
402 }
403 
404 static std::string
fixupWithStyle(StringRef Name,const IdentifierNamingCheck::NamingStyle & Style)405 fixupWithStyle(StringRef Name,
406                const IdentifierNamingCheck::NamingStyle &Style) {
407   const std::string Fixed = fixupWithCase(
408       Name, Style.Case.getValueOr(IdentifierNamingCheck::CaseType::CT_AnyCase));
409   StringRef Mid = StringRef(Fixed).trim("_");
410   if (Mid.empty())
411     Mid = "_";
412   return (Style.Prefix + Mid + Style.Suffix).str();
413 }
414 
findStyleKind(const NamedDecl * D,ArrayRef<llvm::Optional<IdentifierNamingCheck::NamingStyle>> NamingStyles,bool IgnoreMainLikeFunctions)415 static StyleKind findStyleKind(
416     const NamedDecl *D,
417     ArrayRef<llvm::Optional<IdentifierNamingCheck::NamingStyle>> NamingStyles,
418     bool IgnoreMainLikeFunctions) {
419   assert(D && D->getIdentifier() && !D->getName().empty() && !D->isImplicit() &&
420          "Decl must be an explicit identifier with a name.");
421 
422   if (isa<ObjCIvarDecl>(D) && NamingStyles[SK_ObjcIvar])
423     return SK_ObjcIvar;
424 
425   if (isa<TypedefDecl>(D) && NamingStyles[SK_Typedef])
426     return SK_Typedef;
427 
428   if (isa<TypeAliasDecl>(D) && NamingStyles[SK_TypeAlias])
429     return SK_TypeAlias;
430 
431   if (const auto *Decl = dyn_cast<NamespaceDecl>(D)) {
432     if (Decl->isAnonymousNamespace())
433       return SK_Invalid;
434 
435     if (Decl->isInline() && NamingStyles[SK_InlineNamespace])
436       return SK_InlineNamespace;
437 
438     if (NamingStyles[SK_Namespace])
439       return SK_Namespace;
440   }
441 
442   if (isa<EnumDecl>(D) && NamingStyles[SK_Enum])
443     return SK_Enum;
444 
445   if (const auto *EnumConst = dyn_cast<EnumConstantDecl>(D)) {
446     if (cast<EnumDecl>(EnumConst->getDeclContext())->isScoped() &&
447         NamingStyles[SK_ScopedEnumConstant])
448       return SK_ScopedEnumConstant;
449 
450     if (NamingStyles[SK_EnumConstant])
451       return SK_EnumConstant;
452 
453     if (NamingStyles[SK_Constant])
454       return SK_Constant;
455 
456     return SK_Invalid;
457   }
458 
459   if (const auto *Decl = dyn_cast<CXXRecordDecl>(D)) {
460     if (Decl->isAnonymousStructOrUnion())
461       return SK_Invalid;
462 
463     if (!Decl->getCanonicalDecl()->isThisDeclarationADefinition())
464       return SK_Invalid;
465 
466     if (Decl->hasDefinition() && Decl->isAbstract() &&
467         NamingStyles[SK_AbstractClass])
468       return SK_AbstractClass;
469 
470     if (Decl->isStruct() && NamingStyles[SK_Struct])
471       return SK_Struct;
472 
473     if (Decl->isStruct() && NamingStyles[SK_Class])
474       return SK_Class;
475 
476     if (Decl->isClass() && NamingStyles[SK_Class])
477       return SK_Class;
478 
479     if (Decl->isClass() && NamingStyles[SK_Struct])
480       return SK_Struct;
481 
482     if (Decl->isUnion() && NamingStyles[SK_Union])
483       return SK_Union;
484 
485     if (Decl->isEnum() && NamingStyles[SK_Enum])
486       return SK_Enum;
487 
488     return SK_Invalid;
489   }
490 
491   if (const auto *Decl = dyn_cast<FieldDecl>(D)) {
492     QualType Type = Decl->getType();
493 
494     if (!Type.isNull() && Type.isConstQualified()) {
495       if (NamingStyles[SK_ConstantMember])
496         return SK_ConstantMember;
497 
498       if (NamingStyles[SK_Constant])
499         return SK_Constant;
500     }
501 
502     if (Decl->getAccess() == AS_private && NamingStyles[SK_PrivateMember])
503       return SK_PrivateMember;
504 
505     if (Decl->getAccess() == AS_protected && NamingStyles[SK_ProtectedMember])
506       return SK_ProtectedMember;
507 
508     if (Decl->getAccess() == AS_public && NamingStyles[SK_PublicMember])
509       return SK_PublicMember;
510 
511     if (NamingStyles[SK_Member])
512       return SK_Member;
513 
514     return SK_Invalid;
515   }
516 
517   if (const auto *Decl = dyn_cast<ParmVarDecl>(D)) {
518     if (isParamInMainLikeFunction(*Decl, IgnoreMainLikeFunctions))
519       return SK_Invalid;
520     QualType Type = Decl->getType();
521 
522     if (Decl->isConstexpr() && NamingStyles[SK_ConstexprVariable])
523       return SK_ConstexprVariable;
524 
525     if (!Type.isNull() && Type.isConstQualified()) {
526       if (Type.getTypePtr()->isAnyPointerType() && NamingStyles[SK_ConstantPointerParameter])
527         return SK_ConstantPointerParameter;
528 
529       if (NamingStyles[SK_ConstantParameter])
530         return SK_ConstantParameter;
531 
532       if (NamingStyles[SK_Constant])
533         return SK_Constant;
534     }
535 
536     if (Decl->isParameterPack() && NamingStyles[SK_ParameterPack])
537       return SK_ParameterPack;
538 
539     if (!Type.isNull() && Type.getTypePtr()->isAnyPointerType() && NamingStyles[SK_PointerParameter])
540         return SK_PointerParameter;
541 
542     if (NamingStyles[SK_Parameter])
543       return SK_Parameter;
544 
545     return SK_Invalid;
546   }
547 
548   if (const auto *Decl = dyn_cast<VarDecl>(D)) {
549     QualType Type = Decl->getType();
550 
551     if (Decl->isConstexpr() && NamingStyles[SK_ConstexprVariable])
552       return SK_ConstexprVariable;
553 
554     if (!Type.isNull() && Type.isConstQualified()) {
555       if (Decl->isStaticDataMember() && NamingStyles[SK_ClassConstant])
556         return SK_ClassConstant;
557 
558       if (Decl->isFileVarDecl() && Type.getTypePtr()->isAnyPointerType() && NamingStyles[SK_GlobalConstantPointer])
559         return SK_GlobalConstantPointer;
560 
561       if (Decl->isFileVarDecl() && NamingStyles[SK_GlobalConstant])
562         return SK_GlobalConstant;
563 
564       if (Decl->isStaticLocal() && NamingStyles[SK_StaticConstant])
565         return SK_StaticConstant;
566 
567       if (Decl->isLocalVarDecl() && Type.getTypePtr()->isAnyPointerType() && NamingStyles[SK_LocalConstantPointer])
568         return SK_LocalConstantPointer;
569 
570       if (Decl->isLocalVarDecl() && NamingStyles[SK_LocalConstant])
571         return SK_LocalConstant;
572 
573       if (Decl->isFunctionOrMethodVarDecl() && NamingStyles[SK_LocalConstant])
574         return SK_LocalConstant;
575 
576       if (NamingStyles[SK_Constant])
577         return SK_Constant;
578     }
579 
580     if (Decl->isStaticDataMember() && NamingStyles[SK_ClassMember])
581       return SK_ClassMember;
582 
583     if (Decl->isFileVarDecl() && Type.getTypePtr()->isAnyPointerType() && NamingStyles[SK_GlobalPointer])
584       return SK_GlobalPointer;
585 
586     if (Decl->isFileVarDecl() && NamingStyles[SK_GlobalVariable])
587       return SK_GlobalVariable;
588 
589     if (Decl->isStaticLocal() && NamingStyles[SK_StaticVariable])
590       return SK_StaticVariable;
591 
592     if (Decl->isLocalVarDecl() && Type.getTypePtr()->isAnyPointerType() && NamingStyles[SK_LocalPointer])
593       return SK_LocalPointer;
594 
595     if (Decl->isLocalVarDecl() && NamingStyles[SK_LocalVariable])
596       return SK_LocalVariable;
597 
598     if (Decl->isFunctionOrMethodVarDecl() && NamingStyles[SK_LocalVariable])
599       return SK_LocalVariable;
600 
601     if (NamingStyles[SK_Variable])
602       return SK_Variable;
603 
604     return SK_Invalid;
605   }
606 
607   if (const auto *Decl = dyn_cast<CXXMethodDecl>(D)) {
608     if (Decl->isMain() || !Decl->isUserProvided() ||
609         Decl->size_overridden_methods() > 0)
610       return SK_Invalid;
611 
612     // If this method has the same name as any base method, this is likely
613     // necessary even if it's not an override. e.g. CRTP.
614     for (const CXXBaseSpecifier &Base : Decl->getParent()->bases())
615       if (const auto *RD = Base.getType()->getAsCXXRecordDecl())
616         if (RD->hasMemberName(Decl->getDeclName()))
617           return SK_Invalid;
618 
619     if (Decl->isConstexpr() && NamingStyles[SK_ConstexprMethod])
620       return SK_ConstexprMethod;
621 
622     if (Decl->isConstexpr() && NamingStyles[SK_ConstexprFunction])
623       return SK_ConstexprFunction;
624 
625     if (Decl->isStatic() && NamingStyles[SK_ClassMethod])
626       return SK_ClassMethod;
627 
628     if (Decl->isVirtual() && NamingStyles[SK_VirtualMethod])
629       return SK_VirtualMethod;
630 
631     if (Decl->getAccess() == AS_private && NamingStyles[SK_PrivateMethod])
632       return SK_PrivateMethod;
633 
634     if (Decl->getAccess() == AS_protected && NamingStyles[SK_ProtectedMethod])
635       return SK_ProtectedMethod;
636 
637     if (Decl->getAccess() == AS_public && NamingStyles[SK_PublicMethod])
638       return SK_PublicMethod;
639 
640     if (NamingStyles[SK_Method])
641       return SK_Method;
642 
643     if (NamingStyles[SK_Function])
644       return SK_Function;
645 
646     return SK_Invalid;
647   }
648 
649   if (const auto *Decl = dyn_cast<FunctionDecl>(D)) {
650     if (Decl->isMain())
651       return SK_Invalid;
652 
653     if (Decl->isConstexpr() && NamingStyles[SK_ConstexprFunction])
654       return SK_ConstexprFunction;
655 
656     if (Decl->isGlobal() && NamingStyles[SK_GlobalFunction])
657       return SK_GlobalFunction;
658 
659     if (NamingStyles[SK_Function])
660       return SK_Function;
661   }
662 
663   if (isa<TemplateTypeParmDecl>(D)) {
664     if (NamingStyles[SK_TypeTemplateParameter])
665       return SK_TypeTemplateParameter;
666 
667     if (NamingStyles[SK_TemplateParameter])
668       return SK_TemplateParameter;
669 
670     return SK_Invalid;
671   }
672 
673   if (isa<NonTypeTemplateParmDecl>(D)) {
674     if (NamingStyles[SK_ValueTemplateParameter])
675       return SK_ValueTemplateParameter;
676 
677     if (NamingStyles[SK_TemplateParameter])
678       return SK_TemplateParameter;
679 
680     return SK_Invalid;
681   }
682 
683   if (isa<TemplateTemplateParmDecl>(D)) {
684     if (NamingStyles[SK_TemplateTemplateParameter])
685       return SK_TemplateTemplateParameter;
686 
687     if (NamingStyles[SK_TemplateParameter])
688       return SK_TemplateParameter;
689 
690     return SK_Invalid;
691   }
692 
693   return SK_Invalid;
694 }
695 
getFailureInfo(StringRef Name,SourceLocation Location,ArrayRef<llvm::Optional<IdentifierNamingCheck::NamingStyle>> NamingStyles,StyleKind SK,const SourceManager & SM,bool IgnoreFailedSplit)696 static llvm::Optional<RenamerClangTidyCheck::FailureInfo> getFailureInfo(
697     StringRef Name, SourceLocation Location,
698     ArrayRef<llvm::Optional<IdentifierNamingCheck::NamingStyle>> NamingStyles,
699     StyleKind SK, const SourceManager &SM, bool IgnoreFailedSplit) {
700   if (SK == SK_Invalid || !NamingStyles[SK])
701     return None;
702 
703   const IdentifierNamingCheck::NamingStyle &Style = *NamingStyles[SK];
704   if (Style.IgnoredRegexp.isValid() && Style.IgnoredRegexp.match(Name))
705     return None;
706 
707   if (matchesStyle(Name, Style))
708     return None;
709 
710   std::string KindName =
711       fixupWithCase(StyleNames[SK], IdentifierNamingCheck::CT_LowerCase);
712   std::replace(KindName.begin(), KindName.end(), '_', ' ');
713 
714   std::string Fixup = fixupWithStyle(Name, Style);
715   if (StringRef(Fixup).equals(Name)) {
716     if (!IgnoreFailedSplit) {
717       LLVM_DEBUG(Location.print(llvm::dbgs(), SM);
718                  llvm::dbgs()
719                  << llvm::formatv(": unable to split words for {0} '{1}'\n",
720                                   KindName, Name));
721     }
722     return None;
723   }
724   return RenamerClangTidyCheck::FailureInfo{std::move(KindName),
725                                             std::move(Fixup)};
726 }
727 
728 llvm::Optional<RenamerClangTidyCheck::FailureInfo>
GetDeclFailureInfo(const NamedDecl * Decl,const SourceManager & SM) const729 IdentifierNamingCheck::GetDeclFailureInfo(const NamedDecl *Decl,
730                                           const SourceManager &SM) const {
731   SourceLocation Loc = Decl->getLocation();
732   const FileStyle &FileStyle = getStyleForFile(SM.getFilename(Loc));
733   if (!FileStyle.isActive())
734     return llvm::None;
735 
736   return getFailureInfo(Decl->getName(), Loc, FileStyle.getStyles(),
737                         findStyleKind(Decl, FileStyle.getStyles(),
738                                       FileStyle.isIgnoringMainLikeFunction()),
739                         SM, IgnoreFailedSplit);
740 }
741 
742 llvm::Optional<RenamerClangTidyCheck::FailureInfo>
GetMacroFailureInfo(const Token & MacroNameTok,const SourceManager & SM) const743 IdentifierNamingCheck::GetMacroFailureInfo(const Token &MacroNameTok,
744                                            const SourceManager &SM) const {
745   SourceLocation Loc = MacroNameTok.getLocation();
746   const FileStyle &Style = getStyleForFile(SM.getFilename(Loc));
747   if (!Style.isActive())
748     return llvm::None;
749 
750   return getFailureInfo(MacroNameTok.getIdentifierInfo()->getName(), Loc,
751                         Style.getStyles(), SK_MacroDefinition, SM,
752                         IgnoreFailedSplit);
753 }
754 
755 RenamerClangTidyCheck::DiagInfo
GetDiagInfo(const NamingCheckId & ID,const NamingCheckFailure & Failure) const756 IdentifierNamingCheck::GetDiagInfo(const NamingCheckId &ID,
757                                    const NamingCheckFailure &Failure) const {
758   return DiagInfo{"invalid case style for %0 '%1'",
759                   [&](DiagnosticBuilder &Diag) {
760                     Diag << Failure.Info.KindName << ID.second;
761                   }};
762 }
763 
764 const IdentifierNamingCheck::FileStyle &
getStyleForFile(StringRef FileName) const765 IdentifierNamingCheck::getStyleForFile(StringRef FileName) const {
766   if (!GetConfigPerFile)
767     return *MainFileStyle;
768   StringRef Parent = llvm::sys::path::parent_path(FileName);
769   auto Iter = NamingStylesCache.find(Parent);
770   if (Iter != NamingStylesCache.end())
771     return Iter->getValue();
772 
773   ClangTidyOptions Options = Context->getOptionsForFile(FileName);
774   if (Options.Checks && GlobList(*Options.Checks).contains(CheckName)) {
775     auto It = NamingStylesCache.try_emplace(
776         Parent,
777         getFileStyleFromOptions({CheckName, Options.CheckOptions, Context}));
778     assert(It.second);
779     return It.first->getValue();
780   }
781   // Default construction gives an empty style.
782   auto It = NamingStylesCache.try_emplace(Parent);
783   assert(It.second);
784   return It.first->getValue();
785 }
786 
787 } // namespace readability
788 } // namespace tidy
789 } // namespace clang
790