13#include "clang/AST/CXXInheritance.h"
14#include "clang/Lex/PPCallbacks.h"
15#include "clang/Lex/Token.h"
16#include "llvm/ADT/ArrayRef.h"
17#include "llvm/ADT/StringRef.h"
18#include "llvm/Support/Debug.h"
19#include "llvm/Support/Path.h"
20#include "llvm/Support/Regex.h"
21#include "llvm/Support/YAMLParser.h"
24#define DEBUG_TYPE "clang-tidy"
33 std::pair<readability::IdentifierNamingCheck::CaseType, StringRef>>
49 "Leading_upper_snake_case"}};
55 readability::IdentifierNamingCheck::HungarianPrefixType> {
58 static llvm::ArrayRef<std::pair<HungarianPrefixType, StringRef>>
60 static constexpr std::pair<HungarianPrefixType, StringRef> Mapping[] = {
61 {HungarianPrefixType::HPT_Off,
"Off"},
62 {HungarianPrefixType::HPT_On,
"On"},
63 {HungarianPrefixType::HPT_LowerCase,
"LowerCase"},
64 {HungarianPrefixType::HPT_CamelCase,
"CamelCase"}};
69namespace readability {
72#define NAMING_KEYS(m) \
77 m(ScopedEnumConstant) \
78 m(ConstexprVariable) \
87 m(GlobalConstexprVariable) \
89 m(GlobalConstantPointer) \
92 m(LocalConstexprVariable) \
94 m(LocalConstantPointer) \
98 m(StaticConstexprVariable) \
103 m(ConstantParameter) \
106 m(PointerParameter) \
107 m(ConstantPointerParameter) \
114 m(ConstexprFunction) \
124 m(TypeTemplateParameter) \
125 m(ValueTemplateParameter) \
126 m(TemplateTemplateParameter) \
127 m(TemplateParameter) \
134#define ENUMERATE(v) SK_ ## v,
142#define STRINGIZE(v) #v,
147#define HUNGARIAN_NOTATION_PRIMITIVE_TYPES(m) \
171 m(signed-short-int) \
172 m(signed-long-long-int) \
173 m(signed-long-long) \
177 m(unsigned-long-long-int) \
178 m(unsigned-long-long) \
179 m(unsigned-long-int) \
181 m(unsigned-short-int) \
195#define STRINGIZE(v) #v,
200#define HUNGARIAN_NOTATION_USER_DEFINED_TYPES(m) \
231#define STRINGIZE(v) #v,
241 std::optional<IdentifierNamingCheck::CaseType> Case, StringRef Prefix,
242 StringRef Suffix, StringRef IgnoredRegexpStr, HungarianPrefixType HPType)
243 : Case(Case), Prefix(Prefix), Suffix(Suffix),
244 IgnoredRegexpStr(IgnoredRegexpStr), HPType(HPType) {
245 if (!IgnoredRegexpStr.empty()) {
246 IgnoredRegexp = llvm::Regex(SmallString<128>({
"^", IgnoredRegexpStr,
"$"}));
247 if (!IgnoredRegexp.isValid())
248 llvm::errs() <<
"Invalid IgnoredRegexp regular expression: "
254 const ClangTidyCheck::OptionsView &Options)
const {
262 SmallString<64> StyleString;
263 for (
unsigned I = 0; I <
SK_Count; ++I) {
264 const size_t StyleSize =
StyleNames[I].size();
265 StyleString.assign({
StyleNames[I],
"HungarianPrefix"});
270 configurationDiag(
"invalid identifier naming option '%0'") << StyleString;
272 memcpy(&StyleString[StyleSize],
"IgnoredRegexp", 13);
273 StyleString.truncate(StyleSize + 13);
274 const std::optional<StringRef> IgnoredRegexpStr = Options.get(StyleString);
275 memcpy(&StyleString[StyleSize],
"Prefix", 6);
276 StyleString.truncate(StyleSize + 6);
277 const std::optional<StringRef> Prefix(Options.get(StyleString));
279 memcpy(&StyleString[StyleSize],
"Suf", 3);
280 const std::optional<StringRef> Postfix(Options.get(StyleString));
281 memcpy(&StyleString[StyleSize],
"Case", 4);
282 StyleString.pop_back_n(2);
283 std::optional<CaseType> CaseOptional =
286 if (CaseOptional || Prefix || Postfix || IgnoredRegexpStr || HPTOpt)
287 Styles[I].emplace(std::move(CaseOptional), Prefix.value_or(
""),
288 Postfix.value_or(
""), IgnoredRegexpStr.value_or(
""),
291 const bool IgnoreMainLike = Options.get(
"IgnoreMainLikeFunctions",
false);
292 const bool CheckAnonFieldInParent =
293 Options.get(
"CheckAnonFieldInParent",
false);
294 const bool TypedefInheritAnonTagConfig =
295 Options.get(
"TypedefInheritAnonTagConfig",
false);
296 const bool AllowTrailingUnderscore =
297 Options.get(
"AllowTrailingUnderscore",
false);
298 return {std::move(Styles),
301 CheckAnonFieldInParent,
302 TypedefInheritAnonTagConfig,
303 AllowTrailingUnderscore};
307 const NamedDecl *ND)
const {
308 const auto *VD = dyn_cast<ValueDecl>(ND);
312 if (isa<FunctionDecl, EnumConstantDecl>(ND))
316 const auto &SM = VD->getASTContext().getSourceManager();
317 const char *Begin = SM.getCharacterData(VD->getBeginLoc());
318 const char *End = SM.getCharacterData(VD->getEndLoc());
319 intptr_t StrLen = End - Begin;
325 const char *EOL = strchr(Begin,
'\n');
327 EOL = Begin + strlen(Begin);
329 const char *
const PosList[] = {strchr(Begin,
'='), strchr(Begin,
';'),
330 strchr(Begin,
','), strchr(Begin,
')'), EOL};
331 for (
const auto &Pos : PosList)
333 EOL = std::min(EOL, Pos);
335 StrLen = EOL - Begin;
336 std::string TypeName;
338 std::string Type(Begin, StrLen);
340 static constexpr StringRef Keywords[] = {
342 "constexpr",
"constinit",
"consteval",
344 "const",
"volatile",
"restrict",
"mutable",
346 "register",
"static",
"extern",
"thread_local",
351 for (
const StringRef Kw : Keywords)
352 for (
size_t Pos = 0; (Pos = Type.find(Kw, Pos)) != std::string::npos;)
353 Type.replace(Pos, Kw.size(),
"");
354 TypeName = Type.erase(0, Type.find_first_not_of(
' '));
357 const size_t Pos = Type.find(
'<');
358 if (Pos != std::string::npos)
359 TypeName = Type.erase(Pos, Type.size() - Pos);
362 for (
size_t Pos = 0; (Pos = Type.find(
" ", Pos)) != std::string::npos;
363 Pos += strlen(
" ")) {
364 Type.replace(Pos, strlen(
" "),
" ");
368 for (
size_t Pos = 0; (Pos = Type.find(
" &", Pos)) != std::string::npos;
369 Pos += strlen(
"&")) {
370 Type.replace(Pos, strlen(
" &"),
"&");
374 for (
size_t Pos = 0; (Pos = Type.find(
" *", Pos)) != std::string::npos;
375 Pos += strlen(
"*")) {
376 Type.replace(Pos, strlen(
" *"),
"* ");
380 static constexpr StringRef TailsOfMultiWordType[] = {
381 " int",
" char",
" double",
" long",
" short"};
382 bool RedundantRemoved =
false;
383 for (
auto Kw : TailsOfMultiWordType) {
384 const size_t Pos = Type.rfind(Kw);
385 if (Pos != std::string::npos) {
387 Type = Type.substr(0, Pos + Kw.size() + PtrCount);
388 RedundantRemoved =
true;
393 TypeName = Type.erase(0, Type.find_first_not_of(
' '));
394 if (!RedundantRemoved) {
395 const std::size_t FoundSpace = Type.find(
' ');
396 if (FoundSpace != std::string::npos)
397 Type = Type.substr(0, FoundSpace);
400 TypeName = Type.erase(0, Type.find_first_not_of(
' '));
402 const QualType QT = VD->getType();
403 if (!QT.isNull() && QT->isArrayType())
404 TypeName.append(
"[]");
413 GetConfigPerFile(Options.get(
"GetConfigPerFile", true)),
414 IgnoreFailedSplit(Options.get(
"IgnoreFailedSplit", false)) {
415 const auto IterAndInserted = NamingStylesCache.try_emplace(
416 llvm::sys::path::parent_path(Context->getCurrentFile()),
418 assert(IterAndInserted.second &&
"Couldn't insert Style");
421 MainFileStyle = &IterAndInserted.first->getValue();
427 int StyleKindIndex)
const {
428 if (StyleKindIndex == SK_Default)
431 if ((StyleKindIndex >= SK_EnumConstant) &&
432 (StyleKindIndex <= SK_ConstantParameter))
435 if ((StyleKindIndex >= SK_Parameter) && (StyleKindIndex <= SK_Enum))
442 StringRef OptionKey,
const llvm::StringMap<std::string> &StrMap)
const {
443 if (OptionKey.empty())
446 const auto Iter = StrMap.find(OptionKey);
447 if (Iter == StrMap.end())
450 return llvm::yaml::parseBool(Iter->getValue()).value_or(
false);
454 const ClangTidyCheck::OptionsView &Options,
456 static constexpr StringRef HNOpts[] = {
"TreatStructAsClass"};
457 static constexpr StringRef HNDerivedTypes[] = {
"Array",
"Pointer",
460 const StringRef Section =
"HungarianNotation.";
462 SmallString<128> Buffer = {Section,
"General."};
463 size_t DefSize = Buffer.size();
464 for (
const auto &Opt : HNOpts) {
465 Buffer.truncate(DefSize);
467 const StringRef Val = Options.get(Buffer,
"");
469 HNOption.
General[Opt] = Val.str();
472 Buffer = {Section,
"DerivedType."};
473 DefSize = Buffer.size();
474 for (
const auto &Type : HNDerivedTypes) {
475 Buffer.truncate(DefSize);
477 const StringRef Val = Options.get(Buffer,
"");
482 static constexpr std::pair<StringRef, StringRef> HNCStrings[] = {
483 {
"CharPointer",
"char*"},
484 {
"CharArray",
"char[]"},
485 {
"WideCharPointer",
"wchar_t*"},
486 {
"WideCharArray",
"wchar_t[]"}};
488 Buffer = {Section,
"CString."};
489 DefSize = Buffer.size();
490 for (
const auto &CStr : HNCStrings) {
491 Buffer.truncate(DefSize);
492 Buffer.append(CStr.first);
493 const StringRef Val = Options.get(Buffer,
"");
495 HNOption.
CString[CStr.second] = Val.str();
498 Buffer = {Section,
"PrimitiveType."};
499 DefSize = Buffer.size();
501 Buffer.truncate(DefSize);
502 Buffer.append(PrimType);
503 const StringRef Val = Options.get(Buffer,
"");
505 std::string Type = PrimType.str();
506 llvm::replace(Type,
'-',
' ');
511 Buffer = {Section,
"UserDefinedType."};
512 DefSize = Buffer.size();
514 Buffer.truncate(DefSize);
516 const StringRef Val = Options.get(Buffer,
"");
527 const auto *ND = dyn_cast<NamedDecl>(D);
532 if (
const auto *ECD = dyn_cast<EnumConstantDecl>(ND)) {
534 }
else if (
const auto *CRD = dyn_cast<CXXRecordDecl>(ND)) {
536 }
else if (isa<VarDecl, FieldDecl, RecordDecl>(ND)) {
538 if (!TypeName.empty())
548 if (Words.size() <= 1)
551 const std::string CorrectName = Words[0].str();
552 const std::vector<llvm::StringMap<std::string>> MapList = {
556 for (
const auto &Map : MapList) {
557 for (
const auto &Str : Map) {
558 if (Str.getValue() == CorrectName) {
559 Words.erase(Words.begin(), Words.begin() + 1);
569 StringRef TypeName,
const NamedDecl *ND,
571 if (!ND || TypeName.empty())
572 return TypeName.str();
574 std::string ModifiedTypeName(TypeName);
577 std::string PrefixStr;
578 if (
const auto *TD = dyn_cast<ValueDecl>(ND)) {
579 const QualType QT = TD->getType();
580 if (QT->isFunctionPointerType()) {
581 PrefixStr = HNOption.
DerivedType.lookup(
"FunctionPointer");
582 }
else if (QT->isPointerType()) {
583 for (
const auto &CStr : HNOption.
CString) {
584 const std::string Key = CStr.getKey().str();
585 if (ModifiedTypeName.find(Key) == 0) {
586 PrefixStr = CStr.getValue();
587 ModifiedTypeName = ModifiedTypeName.substr(
588 Key.size(), ModifiedTypeName.size() - Key.size());
592 }
else if (QT->isArrayType()) {
593 for (
const auto &CStr : HNOption.
CString) {
594 const std::string Key = CStr.getKey().str();
595 if (ModifiedTypeName.find(Key) == 0) {
596 PrefixStr = CStr.getValue();
600 if (PrefixStr.empty())
602 }
else if (QT->isReferenceType()) {
603 const size_t Pos = ModifiedTypeName.find_last_of(
'&');
604 if (Pos != std::string::npos)
605 ModifiedTypeName = ModifiedTypeName.substr(0, Pos);
612 ModifiedTypeName = [&](std::string Str, StringRef From, StringRef To) {
614 while ((StartPos = Str.find(From, StartPos)) != std::string::npos) {
615 Str.replace(StartPos, From.size(), To);
616 StartPos += To.size();
619 }(ModifiedTypeName,
"*",
"");
623 if (PrefixStr.empty()) {
625 if (ModifiedTypeName == Type.getKey()) {
626 PrefixStr = Type.getValue();
633 if (PrefixStr.empty()) {
635 if (ModifiedTypeName == Type.getKey()) {
636 PrefixStr = Type.getValue();
642 for (
size_t Idx = 0; Idx < PtrCount; Idx++)
643 PrefixStr.insert(0, HNOption.
DerivedType.lookup(
"Pointer"));
649 const CXXRecordDecl *CRD,
654 if (CRD->isStruct() &&
658 return CRD->hasDefinition() && CRD->isAbstract() ?
"I" :
"C";
662 const EnumConstantDecl *ECD)
const {
663 const auto *ED = cast<EnumDecl>(ECD->getDeclContext());
665 std::string Name = ED->getName().str();
666 if (StringRef(Name).contains(
"enum")) {
667 Name = Name.substr(strlen(
"enum"), Name.length() - strlen(
"enum"));
668 Name = Name.erase(0, Name.find_first_not_of(
' '));
671 static const llvm::Regex Splitter(
672 "([a-z0-9A-Z]*)(_+)|([A-Z]?[a-z0-9]+)([A-Z]|$)|([A-Z]+)([A-Z]|$)");
674 const StringRef EnumName(Name);
676 EnumName.split(Substrs,
"_", -1,
false);
680 for (
auto Substr : Substrs) {
681 while (!Substr.empty()) {
683 if (!Splitter.match(Substr, &Groups))
686 if (!Groups[2].empty()) {
687 Words.push_back(Groups[1]);
688 Substr = Substr.substr(Groups[0].size());
689 }
else if (!Groups[3].empty()) {
690 Words.push_back(Groups[3]);
691 Substr = Substr.substr(Groups[0].size() - Groups[4].size());
692 }
else if (!Groups[5].empty()) {
693 Words.push_back(Groups[5]);
694 Substr = Substr.substr(Groups[0].size() - Groups[6].size());
700 for (
const StringRef Word : Words)
701 Initial += tolower(Word[0]);
707 const std::string &TypeName)
const {
708 size_t Pos = TypeName.find(
'*');
710 for (; Pos < TypeName.length(); Pos++, Count++)
711 if (
'*' != TypeName[Pos])
717 const std::string &TypeName,
const NamedDecl *ND)
const {
719 if (
const auto *TD = dyn_cast<ValueDecl>(ND)) {
720 const QualType QT = TD->getType();
721 if (QT->isPointerType())
730 static constexpr std::pair<StringRef, StringRef> General[] = {
731 {
"TreatStructAsClass",
"false"}};
732 for (
const auto &G : General)
733 HNOption.
General.try_emplace(G.first, G.second);
736 static constexpr std::pair<StringRef, StringRef> DerivedTypes[] = {
737 {
"Array",
"a"}, {
"Pointer",
"p"}, {
"FunctionPointer",
"fn"}};
738 for (
const auto &DT : DerivedTypes)
739 HNOption.
DerivedType.try_emplace(DT.first, DT.second);
742 static constexpr std::pair<StringRef, StringRef> CStrings[] = {
746 {
"wchar_t[]",
"wsz"}};
747 for (
const auto &CStr : CStrings)
748 HNOption.
CString.try_emplace(CStr.first, CStr.second);
751 static constexpr std::pair<StringRef, StringRef> PrimitiveTypes[] = {
757 {
"uint16_t",
"u16" },
758 {
"uint32_t",
"u32" },
759 {
"uint64_t",
"u64" },
761 {
"char16_t",
"c16" },
762 {
"char32_t",
"c32" },
771 {
"short int",
"si" },
773 {
"signed int",
"si" },
774 {
"signed short",
"ss" },
775 {
"signed short int",
"ssi" },
776 {
"signed long long int",
"slli"},
777 {
"signed long long",
"sll" },
778 {
"signed long int",
"sli" },
779 {
"signed long",
"sl" },
781 {
"unsigned long long int",
"ulli"},
782 {
"unsigned long long",
"ull" },
783 {
"unsigned long int",
"uli" },
784 {
"unsigned long",
"ul" },
785 {
"unsigned short int",
"usi" },
786 {
"unsigned short",
"us" },
787 {
"unsigned int",
"ui" },
788 {
"unsigned char",
"uc" },
790 {
"long long int",
"lli" },
791 {
"long double",
"ld" },
792 {
"long long",
"ll" },
798 for (
const auto &PT : PrimitiveTypes)
802 static constexpr std::pair<StringRef, StringRef> UserDefinedTypes[] = {
819 {
"ULONGLONG",
"ull" },
833 for (
const auto &UDT : UserDefinedTypes)
839 SmallString<64> StyleString;
840 const ArrayRef<std::optional<NamingStyle>> Styles =
841 MainFileStyle->getStyles();
842 for (
size_t I = 0; I <
SK_Count; ++I) {
843 const auto &StyleOpt = Styles[I];
847 const size_t StyleSize =
StyleNames[I].size();
848 StyleString.assign({
StyleNames[I],
"HungarianPrefix"});
850 Options.store(Opts, StyleString, Style.HPType);
852 memcpy(&StyleString[StyleSize],
"IgnoredRegexp", 13);
853 StyleString.truncate(StyleSize + 13);
854 Options.store(Opts, StyleString, Style.IgnoredRegexpStr);
855 memcpy(&StyleString[StyleSize],
"Prefix", 6);
856 StyleString.truncate(StyleSize + 6);
857 Options.store(Opts, StyleString, Style.Prefix);
859 memcpy(&StyleString[StyleSize],
"Suf", 3);
860 Options.store(Opts, StyleString, Style.Suffix);
862 memcpy(&StyleString[StyleSize],
"Case", 4);
863 StyleString.pop_back_n(2);
864 Options.store(Opts, StyleString, *Style.Case);
867 Options.store(Opts,
"GetConfigPerFile", GetConfigPerFile);
868 Options.store(Opts,
"IgnoreFailedSplit", IgnoreFailedSplit);
869 Options.store(Opts,
"IgnoreMainLikeFunctions",
870 MainFileStyle->isIgnoringMainLikeFunction());
871 Options.store(Opts,
"CheckAnonFieldInParent",
872 MainFileStyle->isCheckingAnonFieldInParentScope());
873 Options.store(Opts,
"TypedefInheritAnonTagConfig",
874 MainFileStyle->isTypedefInheritingAnonTagConfig());
875 Options.store(Opts,
"AllowTrailingUnderscore",
876 MainFileStyle->isAllowingTrailingUnderscore());
880 StringRef Type, StringRef Name,
883 const NamedDecl *Decl,
bool AllowTrailingUnderscore)
const {
884 static const llvm::Regex Matchers[] = {
886 llvm::Regex(
"^[a-z][a-z0-9_]*$"),
887 llvm::Regex(
"^[a-z][a-zA-Z0-9]*$"),
888 llvm::Regex(
"^[A-Z][A-Z0-9_]*$"),
889 llvm::Regex(
"^[A-Z][a-zA-Z0-9]*$"),
890 llvm::Regex(
"^[A-Z]+([a-z0-9]*_[A-Z0-9]+)*[a-z0-9]*$"),
891 llvm::Regex(
"^[a-z]+([a-z0-9]*_[A-Z0-9]+)*[a-z0-9]*$"),
892 llvm::Regex(
"^[A-Z]([a-z0-9_]*[a-z])*$"),
895 if (!Name.consume_front(Style.Prefix))
897 if (!((AllowTrailingUnderscore && Name.consume_back(Style.Suffix +
"_")) ||
898 Name.consume_back(Style.Suffix)))
902 if (!HNPrefix.empty()) {
903 if (!Name.consume_front(HNPrefix))
907 !Name.consume_front(
"_"))
914 if (Name.starts_with(
'_') || Name.ends_with(
'_'))
917 if (Style.Case && !Matchers[
static_cast<size_t>(*Style.Case)].match(Name))
924 StringRef Type, StringRef Name,
const Decl *D,
928 static const llvm::Regex Splitter(
929 "([a-z0-9A-Z]*)(_+)|([A-Z]?[a-z0-9]+)([A-Z]|$)|([A-Z]+)([A-Z]|$)");
932 Name.split(Substrs,
"_", -1,
false);
936 for (
auto Substr : Substrs) {
937 while (!Substr.empty()) {
939 if (!Splitter.match(Substr, &Groups))
942 if (!Groups[2].empty()) {
943 Words.push_back(Groups[1]);
944 Substr = Substr.substr(Groups[0].size());
945 }
else if (!Groups[3].empty()) {
946 Words.push_back(Groups[3]);
947 Substr = Substr.substr(Groups[0].size() - Groups[4].size());
948 }
else if (!Groups[5].empty()) {
949 Words.push_back(Groups[5]);
950 Substr = Substr.substr(Groups[0].size() - Groups[6].size());
961 SmallString<128> Fixup;
968 for (
const auto &Word : Words) {
969 if (&Word != &Words.front())
971 Fixup += Word.lower();
976 for (
const auto &Word : Words) {
977 if (&Word != &Words.front())
979 Fixup += Word.upper();
984 for (
const auto &Word : Words) {
985 Fixup += toupper(Word.front());
986 Fixup += Word.substr(1).lower();
991 for (
const auto &Word : Words) {
992 if (&Word == &Words.front()) {
993 Fixup += Word.lower();
995 Fixup += toupper(Word.front());
996 Fixup += Word.substr(1).lower();
1002 for (
const auto &Word : Words) {
1003 if (&Word != &Words.front())
1005 Fixup += toupper(Word.front());
1006 Fixup += Word.substr(1).lower();
1011 for (
const auto &Word : Words) {
1012 if (&Word != &Words.front()) {
1014 Fixup += toupper(Word.front());
1016 Fixup += tolower(Word.front());
1018 Fixup += Word.substr(1).lower();
1023 for (
const auto &Word : Words) {
1024 if (&Word != &Words.front()) {
1026 Fixup += Word.lower();
1028 Fixup += toupper(Word.front());
1029 Fixup += Word.substr(1).lower();
1035 return Fixup.str().str();
1039 const ParmVarDecl &ParmDecl,
bool IncludeMainLike)
const {
1041 dyn_cast_or_null<FunctionDecl>(ParmDecl.getParentFunctionOrMethod());
1044 if (FDecl->isMain())
1046 if (!IncludeMainLike)
1048 if (FDecl->getAccess() != AS_public && FDecl->getAccess() != AS_none)
1052 if (!FDecl->getDeclName().isIdentifier())
1054 enum MainType { None, Main, WMain };
1055 const auto IsCharPtrPtr = [](QualType QType) -> MainType {
1058 if (QType = QType->getPointeeType(), QType.isNull())
1060 if (QType = QType->getPointeeType(), QType.isNull())
1062 if (QType->isCharType())
1064 if (QType->isWideCharType())
1068 const auto IsIntType = [](QualType QType) {
1071 if (
const auto *Builtin =
1072 dyn_cast<BuiltinType>(QType->getUnqualifiedDesugaredType())) {
1073 return Builtin->getKind() == BuiltinType::Int;
1077 if (!IsIntType(FDecl->getReturnType()))
1079 if (FDecl->getNumParams() < 2 || FDecl->getNumParams() > 3)
1081 if (!IsIntType(FDecl->parameters()[0]->getType()))
1083 const MainType Type = IsCharPtrPtr(FDecl->parameters()[1]->getType());
1086 if (FDecl->getNumParams() == 3 &&
1087 IsCharPtrPtr(FDecl->parameters()[2]->getType()) != Type)
1091 static const llvm::Regex Matcher(
1092 "(^[Mm]ain([_A-Z]|$))|([a-z0-9_]Main([_A-Z]|$))|(_main(_|$))");
1093 assert(Matcher.isValid() &&
"Invalid Matcher for main like functions.");
1094 return Matcher.match(FDecl->getName());
1096 static const llvm::Regex Matcher(
1097 "(^((W[Mm])|(wm))ain([_A-Z]|$))|([a-z0-9_]W[Mm]"
1098 "ain([_A-Z]|$))|(_wmain(_|$))");
1099 assert(Matcher.isValid() &&
"Invalid Matcher for wmain like functions.");
1100 return Matcher.match(FDecl->getName());
1104 StringRef Type, StringRef Name,
1107 const Decl *D,
bool AllowTrailingUnderscore)
const {
1108 Name.consume_front(Style.Prefix);
1109 const bool KeepTrailingUnderscore =
1110 AllowTrailingUnderscore && Name.consume_back(Style.Suffix +
"_");
1111 if (!KeepTrailingUnderscore)
1112 Name.consume_back(Style.Suffix);
1114 Type, Name, D, Style, HNOption,
1117 std::string HungarianPrefix;
1121 if (!HungarianPrefix.empty()) {
1123 HungarianPrefix +=
'_';
1126 Fixed[0] = toupper(Fixed[0]);
1129 StringRef Mid = StringRef(Fixed).trim(
"_");
1133 return (Style.Prefix + HungarianPrefix + Mid + Style.Suffix +
1134 (KeepTrailingUnderscore ?
"_" :
""))
1141 const std::optional<IdentifierNamingCheck::NamingStyle> &Style) {
1143 (Style->Case || !Style->Prefix.empty() || !Style->Suffix.empty());
1148 ArrayRef<std::optional<IdentifierNamingCheck::NamingStyle>> NamingStyles,
1149 bool IgnoreMainLikeFunctions,
bool CheckAnonFieldInParentScope,
1150 bool TypedefInheritAnonTagConfig)
const {
1151 assert(D && D->getIdentifier() && !D->getName().empty() && !D->isImplicit() &&
1152 "Decl must be an explicit identifier with a name.");
1154 if (isa<ObjCIvarDecl>(D) && NamingStyles[SK_ObjcIvar])
1160 if (TypedefInheritAnonTagConfig && isa<TypedefDecl, TypeAliasDecl>(D)) {
1161 const TagDecl *Tag =
1162 cast<TypedefNameDecl>(D)->getUnderlyingType()->getAsTagDecl();
1163 if (Tag && Tag->getTypedefNameForAnonDecl() == D) {
1164 const StyleKind SK = findStyleKindForTag(Tag, NamingStyles);
1170 if (isa<TypedefDecl>(D) && NamingStyles[SK_Typedef])
1173 if (isa<TypeAliasDecl>(D) && NamingStyles[SK_TypeAlias])
1174 return SK_TypeAlias;
1176 if (isa<NamespaceAliasDecl>(D) && NamingStyles[SK_Namespace])
1177 return SK_Namespace;
1179 if (
const auto *Decl = dyn_cast<NamespaceDecl>(D)) {
1180 if (Decl->isAnonymousNamespace())
1183 if (Decl->isInline() && NamingStyles[SK_InlineNamespace])
1184 return SK_InlineNamespace;
1186 if (NamingStyles[SK_Namespace])
1187 return SK_Namespace;
1190 if (isa<EnumDecl>(D) && NamingStyles[SK_Enum])
1193 if (
const auto *EnumConst = dyn_cast<EnumConstantDecl>(D)) {
1194 if (cast<EnumDecl>(EnumConst->getDeclContext())->isScoped() &&
1195 NamingStyles[SK_ScopedEnumConstant])
1196 return SK_ScopedEnumConstant;
1198 if (NamingStyles[SK_EnumConstant])
1199 return SK_EnumConstant;
1201 if (NamingStyles[SK_Constant])
1204 return undefinedStyle(NamingStyles);
1207 if (
const auto *Decl = dyn_cast<RecordDecl>(D)) {
1208 if (Decl->isAnonymousStructOrUnion())
1211 const StyleKind SK = findStyleKindForTag(Decl, NamingStyles);
1215 return undefinedStyle(NamingStyles);
1218 if (
const auto *Decl = dyn_cast<FieldDecl>(D)) {
1219 if (CheckAnonFieldInParentScope) {
1220 const RecordDecl *Record = Decl->getParent();
1221 if (Record->isAnonymousStructOrUnion())
1222 return findStyleKindForAnonField(Decl, NamingStyles);
1225 return findStyleKindForField(Decl, Decl->getType(), NamingStyles);
1228 if (
const auto *Decl = dyn_cast<ParmVarDecl>(D)) {
1231 const QualType Type = Decl->getType();
1233 if (Decl->isConstexpr() && NamingStyles[SK_ConstexprVariable])
1234 return SK_ConstexprVariable;
1236 if (!Type.isNull() && Type.isConstQualified()) {
1237 if (Type.getTypePtr()->isAnyPointerType() &&
1238 NamingStyles[SK_ConstantPointerParameter])
1239 return SK_ConstantPointerParameter;
1241 if (NamingStyles[SK_ConstantParameter])
1242 return SK_ConstantParameter;
1244 if (NamingStyles[SK_Constant])
1248 if (Decl->isParameterPack() && NamingStyles[SK_ParameterPack])
1249 return SK_ParameterPack;
1251 if (!Type.isNull() && Type.getTypePtr()->isAnyPointerType() &&
1252 NamingStyles[SK_PointerParameter])
1253 return SK_PointerParameter;
1255 if (NamingStyles[SK_Parameter])
1256 return SK_Parameter;
1258 return undefinedStyle(NamingStyles);
1261 if (
const auto *Decl = dyn_cast<VarDecl>(D))
1262 return findStyleKindForVar(Decl, Decl->getType(), NamingStyles);
1266 if (
const auto *BD = dyn_cast<BindingDecl>(D)) {
1267 if (
const DecompositionDecl *Decomp = BD->getDecomposedDecl();
1268 Decomp && !BD->getType().isNull())
1269 return findStyleKindForVar(Decomp, BD->getType(), NamingStyles);
1273 if (
const auto *Decl = dyn_cast<CXXMethodDecl>(D)) {
1274 if (Decl->isMain() || !Decl->isUserProvided() ||
1275 Decl->size_overridden_methods() > 0 || Decl->hasAttr<OverrideAttr>())
1280 for (
const CXXBaseSpecifier &Base : Decl->getParent()->bases())
1281 if (
const auto *RD = Base.getType()->getAsCXXRecordDecl();
1282 RD && RD->hasMemberName(Decl->getDeclName()))
1285 if (Decl->isConstexpr() && NamingStyles[SK_ConstexprMethod])
1286 return SK_ConstexprMethod;
1288 if (Decl->isConstexpr() && NamingStyles[SK_ConstexprFunction])
1289 return SK_ConstexprFunction;
1291 if (Decl->isStatic() && NamingStyles[SK_ClassMethod])
1292 return SK_ClassMethod;
1294 if (Decl->isVirtual() && NamingStyles[SK_VirtualMethod])
1295 return SK_VirtualMethod;
1297 if (Decl->getAccess() == AS_private && NamingStyles[SK_PrivateMethod])
1298 return SK_PrivateMethod;
1300 if (Decl->getAccess() == AS_protected && NamingStyles[SK_ProtectedMethod])
1301 return SK_ProtectedMethod;
1303 if (Decl->getAccess() == AS_public && NamingStyles[SK_PublicMethod])
1304 return SK_PublicMethod;
1306 if (NamingStyles[SK_Method])
1309 if (NamingStyles[SK_Function])
1312 return undefinedStyle(NamingStyles);
1315 if (
const auto *Decl = dyn_cast<FunctionDecl>(D)) {
1319 if (Decl->isConstexpr() && NamingStyles[SK_ConstexprFunction])
1320 return SK_ConstexprFunction;
1322 if (Decl->isGlobal() && NamingStyles[SK_GlobalFunction])
1323 return SK_GlobalFunction;
1325 if (NamingStyles[SK_Function])
1332 if (isa<FunctionTemplateDecl, ClassTemplateDecl, VarTemplateDecl,
1333 TypeAliasTemplateDecl>(D))
1336 if (isa<TemplateTypeParmDecl>(D)) {
1337 if (NamingStyles[SK_TypeTemplateParameter])
1338 return SK_TypeTemplateParameter;
1340 if (NamingStyles[SK_TemplateParameter])
1341 return SK_TemplateParameter;
1343 return undefinedStyle(NamingStyles);
1346 if (isa<NonTypeTemplateParmDecl>(D)) {
1347 if (NamingStyles[SK_ValueTemplateParameter])
1348 return SK_ValueTemplateParameter;
1350 if (NamingStyles[SK_TemplateParameter])
1351 return SK_TemplateParameter;
1353 return undefinedStyle(NamingStyles);
1356 if (isa<TemplateTemplateParmDecl>(D)) {
1357 if (NamingStyles[SK_TemplateTemplateParameter])
1358 return SK_TemplateTemplateParameter;
1360 if (NamingStyles[SK_TemplateParameter])
1361 return SK_TemplateParameter;
1363 return undefinedStyle(NamingStyles);
1366 if (isa<ConceptDecl>(D) && NamingStyles[SK_Concept])
1369 return undefinedStyle(NamingStyles);
1372std::optional<RenamerClangTidyCheck::FailureInfo>
1374 StringRef Type, StringRef Name,
const NamedDecl *ND,
1376 ArrayRef<std::optional<IdentifierNamingCheck::NamingStyle>> NamingStyles,
1378 StyleKind SK,
const SourceManager &SM,
bool IgnoreFailedSplit,
1379 bool AllowTrailingUnderscore)
const {
1381 return std::nullopt;
1383 const auto &StyleOpt = NamingStyles[SK];
1385 return std::nullopt;
1388 if (Style.IgnoredRegexp.isValid() && Style.IgnoredRegexp.match(Name))
1389 return std::nullopt;
1391 if (
matchesStyle(Type, Name, Style, HNOption, ND, AllowTrailingUnderscore))
1392 return std::nullopt;
1394 std::string KindName =
1399 llvm::replace(KindName,
'_',
' ');
1402 fixupWithStyle(Type, Name, Style, HNOption, ND, AllowTrailingUnderscore);
1403 if (StringRef(Fixup) == Name) {
1404 if (!IgnoreFailedSplit) {
1405 LLVM_DEBUG(
Location.print(llvm::dbgs(), SM);
1406 llvm::dbgs() <<
": unable to split words for " << KindName
1407 <<
" '" << Name <<
"'\n");
1409 return std::nullopt;
1415std::optional<RenamerClangTidyCheck::FailureInfo>
1416IdentifierNamingCheck::getDeclFailureInfo(
const NamedDecl *Decl,
1417 const SourceManager &SM)
const {
1419 if (Decl->isImplicit())
1420 return std::nullopt;
1422 const SourceLocation Loc = Decl->getLocation();
1423 const SourceLocation SpellingLoc = SM.getSpellingLoc(Loc);
1424 const FileStyle &FileStyle = getStyleForFile(SM.getFilename(SpellingLoc));
1425 if (!FileStyle.isActive())
1426 return std::nullopt;
1430 FileStyle.getStyles(), FileStyle.getHNOption(),
1432 FileStyle.isIgnoringMainLikeFunction(),
1433 FileStyle.isCheckingAnonFieldInParentScope(),
1434 FileStyle.isTypedefInheritingAnonTagConfig()),
1435 SM, IgnoreFailedSplit, FileStyle.isAllowingTrailingUnderscore());
1438std::optional<RenamerClangTidyCheck::FailureInfo>
1439IdentifierNamingCheck::getMacroFailureInfo(
const Token &MacroNameTok,
1440 const SourceManager &SM)
const {
1441 const SourceLocation Loc = MacroNameTok.getLocation();
1442 const FileStyle &Style = getStyleForFile(SM.getFilename(Loc));
1443 if (!Style.isActive())
1444 return std::nullopt;
1446 const auto &Styles = Style.getStyles();
1447 const StyleKind UsedKind = !Styles[SK_MacroDefinition] && Styles[SK_Default]
1449 : SK_MacroDefinition;
1451 return getFailureInfo(
"", MacroNameTok.getIdentifierInfo()->getName(),
1452 nullptr, Loc, Style.getStyles(), Style.getHNOption(),
1453 UsedKind, SM, IgnoreFailedSplit,
1454 Style.isAllowingTrailingUnderscore());
1457RenamerClangTidyCheck::DiagInfo
1459 const NamingCheckFailure &Failure)
const {
1460 return DiagInfo{
"invalid case style for %0 '%1'",
1461 [&](DiagnosticBuilder &Diag) {
1462 Diag << Failure.Info.KindName << ID.second;
1466StringRef IdentifierNamingCheck::getRealFileName(StringRef FileName)
const {
1467 const auto Iter = RealFileNameCache.try_emplace(FileName);
1468 SmallString<256U> &RealFileName = Iter.first->getValue();
1470 return RealFileName;
1471 llvm::sys::fs::real_path(FileName, RealFileName);
1472 return RealFileName;
1475const IdentifierNamingCheck::FileStyle &
1476IdentifierNamingCheck::getStyleForFile(StringRef FileName)
const {
1477 if (!GetConfigPerFile)
1478 return *MainFileStyle;
1480 const StringRef RealFileName = getRealFileName(FileName);
1481 const StringRef Parent = llvm::sys::path::parent_path(RealFileName);
1482 const auto Iter = NamingStylesCache.find(Parent);
1483 if (Iter != NamingStylesCache.end())
1484 return Iter->getValue();
1486 const StringRef CheckName = getID();
1487 ClangTidyOptions Options = Context->getOptionsForFile(RealFileName);
1488 if (Options.
Checks && GlobList(*Options.
Checks).contains(CheckName)) {
1489 const auto It = NamingStylesCache.try_emplace(
1493 return It.first->getValue();
1496 const auto It = NamingStylesCache.try_emplace(Parent);
1498 return It.first->getValue();
1501StyleKind IdentifierNamingCheck::findStyleKindForAnonField(
1502 const FieldDecl *AnonField,
1503 ArrayRef<std::optional<NamingStyle>> NamingStyles)
const {
1504 const IndirectFieldDecl *IFD =
1506 assert(IFD &&
"Found an anonymous record field without an IndirectFieldDecl");
1508 const QualType
Type = AnonField->getType();
1510 if (
const auto *F = dyn_cast<FieldDecl>(IFD->chain().front()))
1511 return findStyleKindForField(F, Type, NamingStyles);
1513 if (
const auto *V = IFD->getVarDecl())
1514 return findStyleKindForVar(V, Type, NamingStyles);
1516 return undefinedStyle(NamingStyles);
1519StyleKind IdentifierNamingCheck::findStyleKindForField(
1520 const FieldDecl *Field, QualType Type,
1521 ArrayRef<std::optional<NamingStyle>> NamingStyles)
const {
1522 if (!
Type.isNull() &&
Type.isConstQualified()) {
1523 if (NamingStyles[SK_ConstantMember])
1524 return SK_ConstantMember;
1526 if (NamingStyles[SK_Constant])
1530 if (
Field->getAccess() == AS_private && NamingStyles[SK_PrivateMember])
1531 return SK_PrivateMember;
1533 if (
Field->getAccess() == AS_protected && NamingStyles[SK_ProtectedMember])
1534 return SK_ProtectedMember;
1536 if (
Field->getAccess() == AS_public && NamingStyles[SK_PublicMember])
1537 return SK_PublicMember;
1539 if (NamingStyles[SK_Member])
1542 return undefinedStyle(NamingStyles);
1545StyleKind IdentifierNamingCheck::findStyleKindForTag(
1547 ArrayRef<std::optional<NamingStyle>> NamingStyles)
const {
1548 if (isa<EnumDecl>(Tag) && NamingStyles[SK_Enum])
1551 const auto *
Record = dyn_cast<RecordDecl>(Tag);
1555 if (
const auto *Definition =
Record->getDefinition()) {
1556 if (
const auto *CxxRecordDecl = dyn_cast<CXXRecordDecl>(Definition)) {
1557 if (CxxRecordDecl->isAbstract() && NamingStyles[SK_AbstractClass])
1558 return SK_AbstractClass;
1561 if (
Definition->isStruct() && NamingStyles[SK_Struct])
1564 if (
Definition->isStruct() && NamingStyles[SK_Class])
1567 if (
Definition->isClass() && NamingStyles[SK_Class])
1570 if (
Definition->isClass() && NamingStyles[SK_Struct])
1573 if (
Definition->isUnion() && NamingStyles[SK_Union])
1580StyleKind IdentifierNamingCheck::findStyleKindForVar(
1581 const VarDecl *Var, QualType Type,
1582 ArrayRef<std::optional<NamingStyle>> NamingStyles)
const {
1583 if (Var->isInitCapture() && NamingStyles[SK_LambdaCapture])
1584 return SK_LambdaCapture;
1586 if (Var->isConstexpr()) {
1587 if (Var->isStaticDataMember() && NamingStyles[SK_ClassConstexpr])
1588 return SK_ClassConstexpr;
1590 if (Var->isFileVarDecl() && NamingStyles[SK_GlobalConstexprVariable])
1591 return SK_GlobalConstexprVariable;
1593 if (Var->isStaticLocal() && NamingStyles[SK_StaticConstexprVariable])
1594 return SK_StaticConstexprVariable;
1596 if (Var->isLocalVarDecl() && NamingStyles[SK_LocalConstexprVariable])
1597 return SK_LocalConstexprVariable;
1599 if (NamingStyles[SK_ConstexprVariable])
1600 return SK_ConstexprVariable;
1603 if (!
Type.isNull() &&
Type.isConstQualified()) {
1604 if (Var->isStaticDataMember() && NamingStyles[SK_ClassConstant])
1605 return SK_ClassConstant;
1607 if (Var->isFileVarDecl() &&
Type.getTypePtr()->isAnyPointerType() &&
1608 NamingStyles[SK_GlobalConstantPointer])
1609 return SK_GlobalConstantPointer;
1611 if (Var->isFileVarDecl() && NamingStyles[SK_GlobalConstant])
1612 return SK_GlobalConstant;
1614 if (Var->isStaticLocal() && NamingStyles[SK_StaticConstant])
1615 return SK_StaticConstant;
1617 if (Var->isLocalVarDecl() &&
Type.getTypePtr()->isAnyPointerType() &&
1618 NamingStyles[SK_LocalConstantPointer])
1619 return SK_LocalConstantPointer;
1621 if (Var->isLocalVarDecl() && NamingStyles[SK_LocalConstant])
1622 return SK_LocalConstant;
1624 if (Var->isFunctionOrMethodVarDecl() && NamingStyles[SK_LocalConstant])
1625 return SK_LocalConstant;
1627 if (NamingStyles[SK_Constant])
1631 if (Var->isStaticDataMember() && NamingStyles[SK_ClassMember])
1632 return SK_ClassMember;
1634 if (Var->isFileVarDecl() &&
Type.getTypePtr()->isAnyPointerType() &&
1635 NamingStyles[SK_GlobalPointer])
1636 return SK_GlobalPointer;
1638 if (Var->isFileVarDecl() && NamingStyles[SK_GlobalVariable])
1639 return SK_GlobalVariable;
1641 if (Var->isStaticLocal() && NamingStyles[SK_StaticVariable])
1642 return SK_StaticVariable;
1644 if (Var->isLocalVarDecl() &&
Type.getTypePtr()->isAnyPointerType() &&
1645 NamingStyles[SK_LocalPointer])
1646 return SK_LocalPointer;
1648 if (Var->isLocalVarDecl() && NamingStyles[SK_LocalVariable])
1649 return SK_LocalVariable;
1651 if (Var->isFunctionOrMethodVarDecl() && NamingStyles[SK_LocalVariable])
1652 return SK_LocalVariable;
1654 if (NamingStyles[SK_Variable])
1657 return undefinedStyle(NamingStyles);
1660StyleKind IdentifierNamingCheck::undefinedStyle(
1661 ArrayRef<std::optional<NamingStyle>> NamingStyles)
const {
1662 return NamingStyles[SK_Default] ? SK_Default :
SK_Invalid;
#define HUNGARIAN_NOTATION_PRIMITIVE_TYPES(m)
#define HUNGARIAN_NOTATION_USER_DEFINED_TYPES(m)
Every ClangTidyCheck reports errors through a DiagnosticsEngine provided by this context.
std::pair< SourceLocation, StringRef > NamingCheckId
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.
IdentifierNamingCheck(StringRef Name, ClangTidyContext *Context)
std::optional< RenamerClangTidyCheck::FailureInfo > getFailureInfo(StringRef Type, StringRef Name, const NamedDecl *ND, SourceLocation Location, ArrayRef< std::optional< IdentifierNamingCheck::NamingStyle > > NamingStyles, const IdentifierNamingCheck::HungarianNotationOption &HNOption, StyleKind SK, const SourceManager &SM, bool IgnoreFailedSplit, bool AllowTrailingUnderscore) const
bool matchesStyle(StringRef Type, StringRef Name, const IdentifierNamingCheck::NamingStyle &Style, const IdentifierNamingCheck::HungarianNotationOption &HNOption, const NamedDecl *Decl, bool AllowTrailingUnderscore) const
std::string fixupWithCase(StringRef Type, StringRef Name, const Decl *D, const IdentifierNamingCheck::NamingStyle &Style, const IdentifierNamingCheck::HungarianNotationOption &HNOption, IdentifierNamingCheck::CaseType Case) const
StyleKind findStyleKind(const NamedDecl *D, ArrayRef< std::optional< IdentifierNamingCheck::NamingStyle > > NamingStyles, bool IgnoreMainLikeFunctions, bool CheckAnonFieldInParentScope, bool TypedefInheritAnonTagConfig) const
~IdentifierNamingCheck() override
IdentifierNamingCheck::FileStyle getFileStyleFromOptions(const ClangTidyCheck::OptionsView &Options) const
bool isParamInMainLikeFunction(const ParmVarDecl &ParmDecl, bool IncludeMainLike) const
@ CT_LeadingUpperSnakeCase
std::string fixupWithStyle(StringRef Type, StringRef Name, const IdentifierNamingCheck::NamingStyle &Style, const IdentifierNamingCheck::HungarianNotationOption &HNOption, const Decl *D, bool AllowTrailingUnderscore) const
void storeOptions(ClangTidyOptions::OptionMap &Opts) override
@ Type
An inlay hint that for a type annotation.
llvm::SmallVector< uint64_t, 1024 > Record
static StringRef const HungarianNotationPrimitiveTypes[]
static bool canConstrainName(const std::optional< IdentifierNamingCheck::NamingStyle > &Style)
Returns true if Style can reject a name.
static StringRef const HungarianNotationUserDefinedTypes[]
static StringRef const StyleNames[]
const IndirectFieldDecl * findOutermostIndirectFieldDeclForField(const FieldDecl *FD)
OptionMap CheckOptions
Key-value mapping used to store check-specific options.
std::optional< std::string > Checks
Checks filter.
llvm::StringMap< ClangTidyValue > OptionMap
static llvm::ArrayRef< std::pair< readability::IdentifierNamingCheck::CaseType, StringRef > > getEnumMapping()
static llvm::ArrayRef< std::pair< HungarianPrefixType, StringRef > > getEnumMapping()
readability::IdentifierNamingCheck::HungarianPrefixType HungarianPrefixType
This class should be specialized by any enum type that needs to be converted to and from an llvm::Str...
Information describing a failed check.
llvm::StringMap< std::string > UserDefinedType
llvm::StringMap< std::string > DerivedType
llvm::StringMap< std::string > CString
llvm::StringMap< std::string > General
llvm::StringMap< std::string > PrimitiveType
std::string getDeclTypeName(const NamedDecl *ND) const
bool isOptionEnabled(StringRef OptionKey, const llvm::StringMap< std::string > &StrMap) const
StringRef getClassPrefix(const CXXRecordDecl *CRD, const IdentifierNamingCheck::HungarianNotationOption &HNOption) const
bool removeDuplicatedPrefix(SmallVector< StringRef, 8 > &Words, const IdentifierNamingCheck::HungarianNotationOption &HNOption) const
void loadFileConfig(const ClangTidyCheck::OptionsView &Options, IdentifierNamingCheck::HungarianNotationOption &HNOption) const
void loadDefaultConfig(IdentifierNamingCheck::HungarianNotationOption &HNOption) const
std::string getEnumPrefix(const EnumConstantDecl *ECD) const
bool checkOptionValid(int StyleKindIndex) const
std::string getPrefix(const Decl *D, const IdentifierNamingCheck::HungarianNotationOption &HNOption) const
size_t getAsteriskCount(const std::string &TypeName) const
std::string getDataTypePrefix(StringRef TypeName, const NamedDecl *ND, const IdentifierNamingCheck::HungarianNotationOption &HNOption) const