File: | build/source/clang-tools-extra/clang-tidy/readability/IdentifierNamingCheck.cpp |
Warning: | line 302, column 12 Value stored to 'StrLen' during its initialization is never read |
Press '?' to see keyboard shortcuts
Keyboard shortcuts:
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/ADT/StringRef.h" |
18 | #include "llvm/Support/Debug.h" |
19 | #include "llvm/Support/Error.h" |
20 | #include "llvm/Support/FormatVariadic.h" |
21 | #include "llvm/Support/Path.h" |
22 | #include "llvm/Support/Regex.h" |
23 | #include "llvm/Support/YAMLParser.h" |
24 | #include <optional> |
25 | |
26 | #define DEBUG_TYPE"clang-tidy" "clang-tidy" |
27 | |
28 | // FixItHint |
29 | |
30 | using namespace clang::ast_matchers; |
31 | |
32 | namespace clang::tidy { |
33 | |
34 | llvm::ArrayRef< |
35 | std::pair<readability::IdentifierNamingCheck::CaseType, StringRef>> |
36 | OptionEnumMapping< |
37 | readability::IdentifierNamingCheck::CaseType>::getEnumMapping() { |
38 | static constexpr std::pair<readability::IdentifierNamingCheck::CaseType, |
39 | StringRef> |
40 | Mapping[] = { |
41 | {readability::IdentifierNamingCheck::CT_AnyCase, "aNy_CasE"}, |
42 | {readability::IdentifierNamingCheck::CT_LowerCase, "lower_case"}, |
43 | {readability::IdentifierNamingCheck::CT_UpperCase, "UPPER_CASE"}, |
44 | {readability::IdentifierNamingCheck::CT_CamelBack, "camelBack"}, |
45 | {readability::IdentifierNamingCheck::CT_CamelCase, "CamelCase"}, |
46 | {readability::IdentifierNamingCheck::CT_CamelSnakeCase, |
47 | "Camel_Snake_Case"}, |
48 | {readability::IdentifierNamingCheck::CT_CamelSnakeBack, |
49 | "camel_Snake_Back"}}; |
50 | return llvm::ArrayRef(Mapping); |
51 | } |
52 | |
53 | template <> |
54 | struct OptionEnumMapping< |
55 | readability::IdentifierNamingCheck::HungarianPrefixType> { |
56 | using HungarianPrefixType = |
57 | readability::IdentifierNamingCheck::HungarianPrefixType; |
58 | static llvm::ArrayRef<std::pair<HungarianPrefixType, StringRef>> |
59 | getEnumMapping() { |
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"}}; |
65 | return llvm::ArrayRef(Mapping); |
66 | } |
67 | }; |
68 | |
69 | namespace readability { |
70 | |
71 | // clang-format off |
72 | #define NAMING_KEYS(m) \ |
73 | m(Namespace) \ |
74 | m(InlineNamespace) \ |
75 | m(EnumConstant) \ |
76 | m(ScopedEnumConstant) \ |
77 | m(ConstexprVariable) \ |
78 | m(ConstantMember) \ |
79 | m(PrivateMember) \ |
80 | m(ProtectedMember) \ |
81 | m(PublicMember) \ |
82 | m(Member) \ |
83 | m(ClassConstant) \ |
84 | m(ClassMember) \ |
85 | m(GlobalConstant) \ |
86 | m(GlobalConstantPointer) \ |
87 | m(GlobalPointer) \ |
88 | m(GlobalVariable) \ |
89 | m(LocalConstant) \ |
90 | m(LocalConstantPointer) \ |
91 | m(LocalPointer) \ |
92 | m(LocalVariable) \ |
93 | m(StaticConstant) \ |
94 | m(StaticVariable) \ |
95 | m(Constant) \ |
96 | m(Variable) \ |
97 | m(ConstantParameter) \ |
98 | m(ParameterPack) \ |
99 | m(Parameter) \ |
100 | m(PointerParameter) \ |
101 | m(ConstantPointerParameter) \ |
102 | m(AbstractClass) \ |
103 | m(Struct) \ |
104 | m(Class) \ |
105 | m(Union) \ |
106 | m(Enum) \ |
107 | m(GlobalFunction) \ |
108 | m(ConstexprFunction) \ |
109 | m(Function) \ |
110 | m(ConstexprMethod) \ |
111 | m(VirtualMethod) \ |
112 | m(ClassMethod) \ |
113 | m(PrivateMethod) \ |
114 | m(ProtectedMethod) \ |
115 | m(PublicMethod) \ |
116 | m(Method) \ |
117 | m(Typedef) \ |
118 | m(TypeTemplateParameter) \ |
119 | m(ValueTemplateParameter) \ |
120 | m(TemplateTemplateParameter) \ |
121 | m(TemplateParameter) \ |
122 | m(TypeAlias) \ |
123 | m(MacroDefinition) \ |
124 | m(ObjcIvar) \ |
125 | |
126 | enum StyleKind : int { |
127 | #define ENUMERATE(v) SK_ ## v, |
128 | NAMING_KEYS(ENUMERATE) |
129 | #undef ENUMERATE |
130 | SK_Count, |
131 | SK_Invalid |
132 | }; |
133 | |
134 | static StringRef const StyleNames[] = { |
135 | #define STRINGIZE(v) #v, |
136 | NAMING_KEYS(STRINGIZE) |
137 | #undef STRINGIZE |
138 | }; |
139 | |
140 | #define HUNGARIAN_NOTATION_PRIMITIVE_TYPES(m)m(int8_t) m(int16_t) m(int32_t) m(int64_t) m(uint8_t) m(uint16_t ) m(uint32_t) m(uint64_t) m(char8_t) m(char16_t) m(char32_t) m (float) m(double) m(char) m(bool) m(_Bool) m(int) m(size_t) m (wchar_t) m(short-int) m(short) m(signed-int) m(signed-short) m(signed-short-int) m(signed-long-long-int) m(signed-long-long ) m(signed-long-int) m(signed-long) m(signed) m(unsigned-long -long-int) m(unsigned-long-long) m(unsigned-long-int) m(unsigned -long) m(unsigned-short-int) m(unsigned-short) m(unsigned-int ) m(unsigned-char) m(unsigned) m(long-long-int) m(long-double ) m(long-long) m(long-int) m(long) m(ptrdiff_t) m(void) \ |
141 | m(int8_t) \ |
142 | m(int16_t) \ |
143 | m(int32_t) \ |
144 | m(int64_t) \ |
145 | m(uint8_t) \ |
146 | m(uint16_t) \ |
147 | m(uint32_t) \ |
148 | m(uint64_t) \ |
149 | m(char8_t) \ |
150 | m(char16_t) \ |
151 | m(char32_t) \ |
152 | m(float) \ |
153 | m(double) \ |
154 | m(char) \ |
155 | m(bool) \ |
156 | m(_Bool) \ |
157 | m(int) \ |
158 | m(size_t) \ |
159 | m(wchar_t) \ |
160 | m(short-int) \ |
161 | m(short) \ |
162 | m(signed-int) \ |
163 | m(signed-short) \ |
164 | m(signed-short-int) \ |
165 | m(signed-long-long-int) \ |
166 | m(signed-long-long) \ |
167 | m(signed-long-int) \ |
168 | m(signed-long) \ |
169 | m(signed) \ |
170 | m(unsigned-long-long-int) \ |
171 | m(unsigned-long-long) \ |
172 | m(unsigned-long-int) \ |
173 | m(unsigned-long) \ |
174 | m(unsigned-short-int) \ |
175 | m(unsigned-short) \ |
176 | m(unsigned-int) \ |
177 | m(unsigned-char) \ |
178 | m(unsigned) \ |
179 | m(long-long-int) \ |
180 | m(long-double) \ |
181 | m(long-long) \ |
182 | m(long-int) \ |
183 | m(long) \ |
184 | m(ptrdiff_t) \ |
185 | m(void) \ |
186 | |
187 | static StringRef const HungarainNotationPrimitiveTypes[] = { |
188 | #define STRINGIZE(v) #v, |
189 | HUNGARIAN_NOTATION_PRIMITIVE_TYPES(STRINGIZE)STRINGIZE(int8_t) STRINGIZE(int16_t) STRINGIZE(int32_t) STRINGIZE (int64_t) STRINGIZE(uint8_t) STRINGIZE(uint16_t) STRINGIZE(uint32_t ) STRINGIZE(uint64_t) STRINGIZE(char8_t) STRINGIZE(char16_t) STRINGIZE (char32_t) STRINGIZE(float) STRINGIZE(double) STRINGIZE(char) STRINGIZE(bool) STRINGIZE(_Bool) STRINGIZE(int) STRINGIZE(size_t ) STRINGIZE(wchar_t) STRINGIZE(short-int) STRINGIZE(short) STRINGIZE (signed-int) STRINGIZE(signed-short) STRINGIZE(signed-short-int ) STRINGIZE(signed-long-long-int) STRINGIZE(signed-long-long) STRINGIZE(signed-long-int) STRINGIZE(signed-long) STRINGIZE( signed) STRINGIZE(unsigned-long-long-int) STRINGIZE(unsigned- long-long) STRINGIZE(unsigned-long-int) STRINGIZE(unsigned-long ) STRINGIZE(unsigned-short-int) STRINGIZE(unsigned-short) STRINGIZE (unsigned-int) STRINGIZE(unsigned-char) STRINGIZE(unsigned) STRINGIZE (long-long-int) STRINGIZE(long-double) STRINGIZE(long-long) STRINGIZE (long-int) STRINGIZE(long) STRINGIZE(ptrdiff_t) STRINGIZE(void ) |
190 | #undef STRINGIZE |
191 | }; |
192 | |
193 | #define HUNGARIAN_NOTATION_USER_DEFINED_TYPES(m)m(BOOL) m(BOOLEAN) m(BYTE) m(CHAR) m(UCHAR) m(SHORT) m(USHORT ) m(WORD) m(DWORD) m(DWORD32) m(DWORD64) m(LONG) m(ULONG) m(ULONG32 ) m(ULONG64) m(ULONGLONG) m(HANDLE) m(INT) m(INT8) m(INT16) m (INT32) m(INT64) m(UINT) m(UINT8) m(UINT16) m(UINT32) m(UINT64 ) m(PVOID) \ |
194 | m(BOOL) \ |
195 | m(BOOLEAN) \ |
196 | m(BYTE) \ |
197 | m(CHAR) \ |
198 | m(UCHAR) \ |
199 | m(SHORT) \ |
200 | m(USHORT) \ |
201 | m(WORD) \ |
202 | m(DWORD) \ |
203 | m(DWORD32) \ |
204 | m(DWORD64) \ |
205 | m(LONG) \ |
206 | m(ULONG) \ |
207 | m(ULONG32) \ |
208 | m(ULONG64) \ |
209 | m(ULONGLONG) \ |
210 | m(HANDLE) \ |
211 | m(INT) \ |
212 | m(INT8) \ |
213 | m(INT16) \ |
214 | m(INT32) \ |
215 | m(INT64) \ |
216 | m(UINT) \ |
217 | m(UINT8) \ |
218 | m(UINT16) \ |
219 | m(UINT32) \ |
220 | m(UINT64) \ |
221 | m(PVOID) \ |
222 | |
223 | static StringRef const HungarainNotationUserDefinedTypes[] = { |
224 | #define STRINGIZE(v) #v, |
225 | HUNGARIAN_NOTATION_USER_DEFINED_TYPES(STRINGIZE)STRINGIZE(BOOL) STRINGIZE(BOOLEAN) STRINGIZE(BYTE) STRINGIZE( CHAR) STRINGIZE(UCHAR) STRINGIZE(SHORT) STRINGIZE(USHORT) STRINGIZE (WORD) STRINGIZE(DWORD) STRINGIZE(DWORD32) STRINGIZE(DWORD64) STRINGIZE(LONG) STRINGIZE(ULONG) STRINGIZE(ULONG32) STRINGIZE (ULONG64) STRINGIZE(ULONGLONG) STRINGIZE(HANDLE) STRINGIZE(INT ) STRINGIZE(INT8) STRINGIZE(INT16) STRINGIZE(INT32) STRINGIZE (INT64) STRINGIZE(UINT) STRINGIZE(UINT8) STRINGIZE(UINT16) STRINGIZE (UINT32) STRINGIZE(UINT64) STRINGIZE(PVOID) |
226 | #undef STRINGIZE |
227 | }; |
228 | |
229 | |
230 | #undef NAMING_KEYS |
231 | // clang-format on |
232 | |
233 | IdentifierNamingCheck::NamingStyle::NamingStyle( |
234 | std::optional<IdentifierNamingCheck::CaseType> Case, StringRef Prefix, |
235 | StringRef Suffix, StringRef IgnoredRegexpStr, HungarianPrefixType HPType) |
236 | : Case(Case), Prefix(Prefix), Suffix(Suffix), |
237 | IgnoredRegexpStr(IgnoredRegexpStr), HPType(HPType) { |
238 | if (!IgnoredRegexpStr.empty()) { |
239 | IgnoredRegexp = |
240 | llvm::Regex(llvm::SmallString<128>({"^", IgnoredRegexpStr, "$"})); |
241 | if (!IgnoredRegexp.isValid()) |
242 | llvm::errs() << "Invalid IgnoredRegexp regular expression: " |
243 | << IgnoredRegexpStr; |
244 | } |
245 | } |
246 | |
247 | IdentifierNamingCheck::FileStyle IdentifierNamingCheck::getFileStyleFromOptions( |
248 | const ClangTidyCheck::OptionsView &Options) const { |
249 | IdentifierNamingCheck::HungarianNotationOption HNOption; |
250 | |
251 | HungarianNotation.loadDefaultConfig(HNOption); |
252 | HungarianNotation.loadFileConfig(Options, HNOption); |
253 | |
254 | SmallVector<std::optional<IdentifierNamingCheck::NamingStyle>, 0> Styles; |
255 | Styles.resize(SK_Count); |
256 | SmallString<64> StyleString; |
257 | for (unsigned I = 0; I < SK_Count; ++I) { |
258 | size_t StyleSize = StyleNames[I].size(); |
259 | StyleString.assign({StyleNames[I], "HungarianPrefix"}); |
260 | |
261 | auto HPTOpt = |
262 | Options.get<IdentifierNamingCheck::HungarianPrefixType>(StyleString); |
263 | if (HPTOpt && !HungarianNotation.checkOptionValid(I)) |
264 | configurationDiag("invalid identifier naming option '%0'") << StyleString; |
265 | |
266 | memcpy(&StyleString[StyleSize], "IgnoredRegexp", 13); |
267 | StyleString.truncate(StyleSize + 13); |
268 | std::optional<StringRef> IgnoredRegexpStr = Options.get(StyleString); |
269 | memcpy(&StyleString[StyleSize], "Prefix", 6); |
270 | StyleString.truncate(StyleSize + 6); |
271 | std::optional<StringRef> Prefix(Options.get(StyleString)); |
272 | // Fast replacement of [Pre]fix -> [Suf]fix. |
273 | memcpy(&StyleString[StyleSize], "Suf", 3); |
274 | std::optional<StringRef> Postfix(Options.get(StyleString)); |
275 | memcpy(&StyleString[StyleSize], "Case", 4); |
276 | StyleString.pop_back_n(2); |
277 | std::optional<CaseType> CaseOptional = |
278 | Options.get<IdentifierNamingCheck::CaseType>(StyleString); |
279 | |
280 | if (CaseOptional || Prefix || Postfix || IgnoredRegexpStr || HPTOpt) |
281 | Styles[I].emplace(std::move(CaseOptional), Prefix.value_or(""), |
282 | Postfix.value_or(""), IgnoredRegexpStr.value_or(""), |
283 | HPTOpt.value_or(IdentifierNamingCheck::HPT_Off)); |
284 | } |
285 | bool IgnoreMainLike = Options.get("IgnoreMainLikeFunctions", false); |
286 | return {std::move(Styles), std::move(HNOption), IgnoreMainLike}; |
287 | } |
288 | |
289 | std::string IdentifierNamingCheck::HungarianNotation::getDeclTypeName( |
290 | const NamedDecl *ND) const { |
291 | const auto *VD = dyn_cast<ValueDecl>(ND); |
292 | if (!VD) |
293 | return {}; |
294 | |
295 | if (isa<FunctionDecl, EnumConstantDecl>(ND)) |
296 | return {}; |
297 | |
298 | // Get type text of variable declarations. |
299 | auto &SM = VD->getASTContext().getSourceManager(); |
300 | const char *Begin = SM.getCharacterData(VD->getBeginLoc()); |
301 | const char *End = SM.getCharacterData(VD->getEndLoc()); |
302 | intptr_t StrLen = End - Begin; |
Value stored to 'StrLen' during its initialization is never read | |
303 | |
304 | // FIXME: Sometimes the value that returns from ValDecl->getEndLoc() |
305 | // is wrong(out of location of Decl). This causes `StrLen` will be assigned |
306 | // an unexpected large value. Current workaround to find the terminated |
307 | // character instead of the `getEndLoc()` function. |
308 | const char *EOL = strchr(Begin, '\n'); |
309 | if (!EOL) |
310 | EOL = Begin + strlen(Begin); |
311 | |
312 | const char *PosList[] = {strchr(Begin, '='), strchr(Begin, ';'), |
313 | strchr(Begin, ','), strchr(Begin, ')'), EOL}; |
314 | for (const auto &Pos : PosList) { |
315 | if (Pos > Begin) |
316 | EOL = std::min(EOL, Pos); |
317 | } |
318 | |
319 | StrLen = EOL - Begin; |
320 | std::string TypeName; |
321 | if (StrLen > 0) { |
322 | std::string Type(Begin, StrLen); |
323 | |
324 | static constexpr StringRef Keywords[] = { |
325 | // Constexpr specifiers |
326 | "constexpr", "constinit", "consteval", |
327 | // Qualifier |
328 | "const", "volatile", "restrict", "mutable", |
329 | // Storage class specifiers |
330 | "register", "static", "extern", "thread_local", |
331 | // Other keywords |
332 | "virtual"}; |
333 | |
334 | // Remove keywords |
335 | for (StringRef Kw : Keywords) { |
336 | for (size_t Pos = 0; |
337 | (Pos = Type.find(Kw.data(), Pos)) != std::string::npos;) { |
338 | Type.replace(Pos, Kw.size(), ""); |
339 | } |
340 | } |
341 | TypeName = Type.erase(0, Type.find_first_not_of(' ')); |
342 | |
343 | // Remove template parameters |
344 | const size_t Pos = Type.find('<'); |
345 | if (Pos != std::string::npos) { |
346 | TypeName = Type.erase(Pos, Type.size() - Pos); |
347 | } |
348 | |
349 | // Replace spaces with single space. |
350 | for (size_t Pos = 0; (Pos = Type.find(" ", Pos)) != std::string::npos; |
351 | Pos += strlen(" ")) { |
352 | Type.replace(Pos, strlen(" "), " "); |
353 | } |
354 | |
355 | // Replace " &" with "&". |
356 | for (size_t Pos = 0; (Pos = Type.find(" &", Pos)) != std::string::npos; |
357 | Pos += strlen("&")) { |
358 | Type.replace(Pos, strlen(" &"), "&"); |
359 | } |
360 | |
361 | // Replace " *" with "* ". |
362 | for (size_t Pos = 0; (Pos = Type.find(" *", Pos)) != std::string::npos; |
363 | Pos += strlen("*")) { |
364 | Type.replace(Pos, strlen(" *"), "* "); |
365 | } |
366 | |
367 | // Remove redundant tailing. |
368 | static constexpr StringRef TailsOfMultiWordType[] = { |
369 | " int", " char", " double", " long", " short"}; |
370 | bool RedundantRemoved = false; |
371 | for (auto Kw : TailsOfMultiWordType) { |
372 | size_t Pos = Type.rfind(Kw.data()); |
373 | if (Pos != std::string::npos) { |
374 | const size_t PtrCount = getAsteriskCount(Type, ND); |
375 | Type = Type.substr(0, Pos + Kw.size() + PtrCount); |
376 | RedundantRemoved = true; |
377 | break; |
378 | } |
379 | } |
380 | |
381 | TypeName = Type.erase(0, Type.find_first_not_of(' ')); |
382 | if (!RedundantRemoved) { |
383 | std::size_t FoundSpace = Type.find(' '); |
384 | if (FoundSpace != std::string::npos) |
385 | Type = Type.substr(0, FoundSpace); |
386 | } |
387 | |
388 | TypeName = Type.erase(0, Type.find_first_not_of(' ')); |
389 | |
390 | QualType QT = VD->getType(); |
391 | if (!QT.isNull() && QT->isArrayType()) |
392 | TypeName.append("[]"); |
393 | } |
394 | |
395 | return TypeName; |
396 | } |
397 | |
398 | IdentifierNamingCheck::IdentifierNamingCheck(StringRef Name, |
399 | ClangTidyContext *Context) |
400 | : RenamerClangTidyCheck(Name, Context), Context(Context), |
401 | GetConfigPerFile(Options.get("GetConfigPerFile", true)), |
402 | IgnoreFailedSplit(Options.get("IgnoreFailedSplit", false)) { |
403 | |
404 | auto IterAndInserted = NamingStylesCache.try_emplace( |
405 | llvm::sys::path::parent_path(Context->getCurrentFile()), |
406 | getFileStyleFromOptions(Options)); |
407 | assert(IterAndInserted.second && "Couldn't insert Style")(static_cast <bool> (IterAndInserted.second && "Couldn't insert Style" ) ? void (0) : __assert_fail ("IterAndInserted.second && \"Couldn't insert Style\"" , "clang-tools-extra/clang-tidy/readability/IdentifierNamingCheck.cpp" , 407, __extension__ __PRETTY_FUNCTION__)); |
408 | // Holding a reference to the data in the vector is safe as it should never |
409 | // move. |
410 | MainFileStyle = &IterAndInserted.first->getValue(); |
411 | } |
412 | |
413 | IdentifierNamingCheck::~IdentifierNamingCheck() = default; |
414 | |
415 | bool IdentifierNamingCheck::HungarianNotation::checkOptionValid( |
416 | int StyleKindIndex) const { |
417 | if ((StyleKindIndex >= SK_EnumConstant) && |
418 | (StyleKindIndex <= SK_ConstantParameter)) |
419 | return true; |
420 | |
421 | if ((StyleKindIndex >= SK_Parameter) && (StyleKindIndex <= SK_Enum)) |
422 | return true; |
423 | |
424 | return false; |
425 | } |
426 | |
427 | bool IdentifierNamingCheck::HungarianNotation::isOptionEnabled( |
428 | StringRef OptionKey, const llvm::StringMap<std::string> &StrMap) const { |
429 | if (OptionKey.empty()) |
430 | return false; |
431 | |
432 | auto Iter = StrMap.find(OptionKey); |
433 | if (Iter == StrMap.end()) |
434 | return false; |
435 | |
436 | return *llvm::yaml::parseBool(Iter->getValue()); |
437 | } |
438 | |
439 | void IdentifierNamingCheck::HungarianNotation::loadFileConfig( |
440 | const ClangTidyCheck::OptionsView &Options, |
441 | IdentifierNamingCheck::HungarianNotationOption &HNOption) const { |
442 | |
443 | static constexpr StringRef HNOpts[] = {"TreatStructAsClass"}; |
444 | static constexpr StringRef HNDerivedTypes[] = {"Array", "Pointer", |
445 | "FunctionPointer"}; |
446 | |
447 | StringRef Section = "HungarianNotation."; |
448 | |
449 | SmallString<128> Buffer = {Section, "General."}; |
450 | size_t DefSize = Buffer.size(); |
451 | for (const auto &Opt : HNOpts) { |
452 | Buffer.truncate(DefSize); |
453 | Buffer.append(Opt); |
454 | StringRef Val = Options.get(Buffer, ""); |
455 | if (!Val.empty()) |
456 | HNOption.General[Opt] = Val.str(); |
457 | } |
458 | |
459 | Buffer = {Section, "DerivedType."}; |
460 | DefSize = Buffer.size(); |
461 | for (const auto &Type : HNDerivedTypes) { |
462 | Buffer.truncate(DefSize); |
463 | Buffer.append(Type); |
464 | StringRef Val = Options.get(Buffer, ""); |
465 | if (!Val.empty()) |
466 | HNOption.DerivedType[Type] = Val.str(); |
467 | } |
468 | |
469 | static constexpr std::pair<StringRef, StringRef> HNCStrings[] = { |
470 | {"CharPointer", "char*"}, |
471 | {"CharArray", "char[]"}, |
472 | {"WideCharPointer", "wchar_t*"}, |
473 | {"WideCharArray", "wchar_t[]"}}; |
474 | |
475 | Buffer = {Section, "CString."}; |
476 | DefSize = Buffer.size(); |
477 | for (const auto &CStr : HNCStrings) { |
478 | Buffer.truncate(DefSize); |
479 | Buffer.append(CStr.first); |
480 | StringRef Val = Options.get(Buffer, ""); |
481 | if (!Val.empty()) |
482 | HNOption.CString[CStr.second] = Val.str(); |
483 | } |
484 | |
485 | Buffer = {Section, "PrimitiveType."}; |
486 | DefSize = Buffer.size(); |
487 | for (const auto &PrimType : HungarainNotationPrimitiveTypes) { |
488 | Buffer.truncate(DefSize); |
489 | Buffer.append(PrimType); |
490 | StringRef Val = Options.get(Buffer, ""); |
491 | if (!Val.empty()) { |
492 | std::string Type = PrimType.str(); |
493 | std::replace(Type.begin(), Type.end(), '-', ' '); |
494 | HNOption.PrimitiveType[Type] = Val.str(); |
495 | } |
496 | } |
497 | |
498 | Buffer = {Section, "UserDefinedType."}; |
499 | DefSize = Buffer.size(); |
500 | for (const auto &Type : HungarainNotationUserDefinedTypes) { |
501 | Buffer.truncate(DefSize); |
502 | Buffer.append(Type); |
503 | StringRef Val = Options.get(Buffer, ""); |
504 | if (!Val.empty()) |
505 | HNOption.UserDefinedType[Type] = Val.str(); |
506 | } |
507 | } |
508 | |
509 | std::string IdentifierNamingCheck::HungarianNotation::getPrefix( |
510 | const Decl *D, |
511 | const IdentifierNamingCheck::HungarianNotationOption &HNOption) const { |
512 | if (!D) |
513 | return {}; |
514 | const auto *ND = dyn_cast<NamedDecl>(D); |
515 | if (!ND) |
516 | return {}; |
517 | |
518 | std::string Prefix; |
519 | if (const auto *ECD = dyn_cast<EnumConstantDecl>(ND)) { |
520 | Prefix = getEnumPrefix(ECD); |
521 | } else if (const auto *CRD = dyn_cast<CXXRecordDecl>(ND)) { |
522 | Prefix = getClassPrefix(CRD, HNOption); |
523 | } else if (isa<VarDecl, FieldDecl, RecordDecl>(ND)) { |
524 | std::string TypeName = getDeclTypeName(ND); |
525 | if (!TypeName.empty()) |
526 | Prefix = getDataTypePrefix(TypeName, ND, HNOption); |
527 | } |
528 | |
529 | return Prefix; |
530 | } |
531 | |
532 | bool IdentifierNamingCheck::HungarianNotation::removeDuplicatedPrefix( |
533 | SmallVector<StringRef, 8> &Words, |
534 | const IdentifierNamingCheck::HungarianNotationOption &HNOption) const { |
535 | if (Words.size() <= 1) |
536 | return true; |
537 | |
538 | std::string CorrectName = Words[0].str(); |
539 | std::vector<llvm::StringMap<std::string>> MapList = { |
540 | HNOption.CString, HNOption.DerivedType, HNOption.PrimitiveType, |
541 | HNOption.UserDefinedType}; |
542 | |
543 | for (const auto &Map : MapList) { |
544 | for (const auto &Str : Map) { |
545 | if (Str.getValue() == CorrectName) { |
546 | Words.erase(Words.begin(), Words.begin() + 1); |
547 | return true; |
548 | } |
549 | } |
550 | } |
551 | |
552 | return false; |
553 | } |
554 | |
555 | std::string IdentifierNamingCheck::HungarianNotation::getDataTypePrefix( |
556 | StringRef TypeName, const NamedDecl *ND, |
557 | const IdentifierNamingCheck::HungarianNotationOption &HNOption) const { |
558 | if (!ND || TypeName.empty()) |
559 | return TypeName.str(); |
560 | |
561 | std::string ModifiedTypeName(TypeName); |
562 | |
563 | // Derived types |
564 | std::string PrefixStr; |
565 | if (const auto *TD = dyn_cast<ValueDecl>(ND)) { |
566 | QualType QT = TD->getType(); |
567 | if (QT->isFunctionPointerType()) { |
568 | PrefixStr = HNOption.DerivedType.lookup("FunctionPointer"); |
569 | } else if (QT->isPointerType()) { |
570 | for (const auto &CStr : HNOption.CString) { |
571 | std::string Key = CStr.getKey().str(); |
572 | if (ModifiedTypeName.find(Key) == 0) { |
573 | PrefixStr = CStr.getValue(); |
574 | ModifiedTypeName = ModifiedTypeName.substr( |
575 | Key.size(), ModifiedTypeName.size() - Key.size()); |
576 | break; |
577 | } |
578 | } |
579 | } else if (QT->isArrayType()) { |
580 | for (const auto &CStr : HNOption.CString) { |
581 | std::string Key = CStr.getKey().str(); |
582 | if (ModifiedTypeName.find(Key) == 0) { |
583 | PrefixStr = CStr.getValue(); |
584 | break; |
585 | } |
586 | } |
587 | if (PrefixStr.empty()) |
588 | PrefixStr = HNOption.DerivedType.lookup("Array"); |
589 | } else if (QT->isReferenceType()) { |
590 | size_t Pos = ModifiedTypeName.find_last_of('&'); |
591 | if (Pos != std::string::npos) |
592 | ModifiedTypeName = ModifiedTypeName.substr(0, Pos); |
593 | } |
594 | } |
595 | |
596 | // Pointers |
597 | size_t PtrCount = getAsteriskCount(ModifiedTypeName); |
598 | if (PtrCount > 0) { |
599 | ModifiedTypeName = [&](std::string Str, StringRef From, StringRef To) { |
600 | size_t StartPos = 0; |
601 | while ((StartPos = Str.find(From.data(), StartPos)) != |
602 | std::string::npos) { |
603 | Str.replace(StartPos, From.size(), To.data()); |
604 | StartPos += To.size(); |
605 | } |
606 | return Str; |
607 | }(ModifiedTypeName, "*", ""); |
608 | } |
609 | |
610 | // Primitive types |
611 | if (PrefixStr.empty()) { |
612 | for (const auto &Type : HNOption.PrimitiveType) { |
613 | if (ModifiedTypeName == Type.getKey()) { |
614 | PrefixStr = Type.getValue(); |
615 | break; |
616 | } |
617 | } |
618 | } |
619 | |
620 | // User-Defined types |
621 | if (PrefixStr.empty()) { |
622 | for (const auto &Type : HNOption.UserDefinedType) { |
623 | if (ModifiedTypeName == Type.getKey()) { |
624 | PrefixStr = Type.getValue(); |
625 | break; |
626 | } |
627 | } |
628 | } |
629 | |
630 | for (size_t Idx = 0; Idx < PtrCount; Idx++) |
631 | PrefixStr.insert(0, HNOption.DerivedType.lookup("Pointer")); |
632 | |
633 | return PrefixStr; |
634 | } |
635 | |
636 | std::string IdentifierNamingCheck::HungarianNotation::getClassPrefix( |
637 | const CXXRecordDecl *CRD, |
638 | const IdentifierNamingCheck::HungarianNotationOption &HNOption) const { |
639 | |
640 | if (CRD->isUnion()) |
641 | return {}; |
642 | |
643 | if (CRD->isStruct() && |
644 | !isOptionEnabled("TreatStructAsClass", HNOption.General)) |
645 | return {}; |
646 | |
647 | return CRD->isAbstract() ? "I" : "C"; |
648 | } |
649 | |
650 | std::string IdentifierNamingCheck::HungarianNotation::getEnumPrefix( |
651 | const EnumConstantDecl *ECD) const { |
652 | const EnumDecl *ED = cast<EnumDecl>(ECD->getDeclContext()); |
653 | |
654 | std::string Name = ED->getName().str(); |
655 | if (std::string::npos != Name.find("enum")) { |
656 | Name = Name.substr(strlen("enum"), Name.length() - strlen("enum")); |
657 | Name = Name.erase(0, Name.find_first_not_of(' ')); |
658 | } |
659 | |
660 | static llvm::Regex Splitter( |
661 | "([a-z0-9A-Z]*)(_+)|([A-Z]?[a-z0-9]+)([A-Z]|$)|([A-Z]+)([A-Z]|$)"); |
662 | |
663 | StringRef EnumName(Name); |
664 | SmallVector<StringRef, 8> Substrs; |
665 | EnumName.split(Substrs, "_", -1, false); |
666 | |
667 | SmallVector<StringRef, 8> Words; |
668 | SmallVector<StringRef, 8> Groups; |
669 | for (auto Substr : Substrs) { |
670 | while (!Substr.empty()) { |
671 | Groups.clear(); |
672 | if (!Splitter.match(Substr, &Groups)) |
673 | break; |
674 | |
675 | if (Groups[2].size() > 0) { |
676 | Words.push_back(Groups[1]); |
677 | Substr = Substr.substr(Groups[0].size()); |
678 | } else if (Groups[3].size() > 0) { |
679 | Words.push_back(Groups[3]); |
680 | Substr = Substr.substr(Groups[0].size() - Groups[4].size()); |
681 | } else if (Groups[5].size() > 0) { |
682 | Words.push_back(Groups[5]); |
683 | Substr = Substr.substr(Groups[0].size() - Groups[6].size()); |
684 | } |
685 | } |
686 | } |
687 | |
688 | std::string Initial; |
689 | for (StringRef Word : Words) |
690 | Initial += tolower(Word[0]); |
691 | |
692 | return Initial; |
693 | } |
694 | |
695 | size_t IdentifierNamingCheck::HungarianNotation::getAsteriskCount( |
696 | const std::string &TypeName) const { |
697 | size_t Pos = TypeName.find('*'); |
698 | size_t Count = 0; |
699 | for (; Pos < TypeName.length(); Pos++, Count++) { |
700 | if ('*' != TypeName[Pos]) |
701 | break; |
702 | } |
703 | return Count; |
704 | } |
705 | |
706 | size_t IdentifierNamingCheck::HungarianNotation::getAsteriskCount( |
707 | const std::string &TypeName, const NamedDecl *ND) const { |
708 | size_t PtrCount = 0; |
709 | if (const auto *TD = dyn_cast<ValueDecl>(ND)) { |
710 | QualType QT = TD->getType(); |
711 | if (QT->isPointerType()) |
712 | PtrCount = getAsteriskCount(TypeName); |
713 | } |
714 | return PtrCount; |
715 | } |
716 | |
717 | void IdentifierNamingCheck::HungarianNotation::loadDefaultConfig( |
718 | IdentifierNamingCheck::HungarianNotationOption &HNOption) const { |
719 | |
720 | // Options |
721 | static constexpr std::pair<StringRef, StringRef> General[] = { |
722 | {"TreatStructAsClass", "false"}}; |
723 | for (const auto &G : General) |
724 | HNOption.General.try_emplace(G.first, G.second); |
725 | |
726 | // Derived types |
727 | static constexpr std::pair<StringRef, StringRef> DerivedTypes[] = { |
728 | {"Array", "a"}, {"Pointer", "p"}, {"FunctionPointer", "fn"}}; |
729 | for (const auto &DT : DerivedTypes) |
730 | HNOption.DerivedType.try_emplace(DT.first, DT.second); |
731 | |
732 | // C strings |
733 | static constexpr std::pair<StringRef, StringRef> CStrings[] = { |
734 | {"char*", "sz"}, |
735 | {"char[]", "sz"}, |
736 | {"wchar_t*", "wsz"}, |
737 | {"wchar_t[]", "wsz"}}; |
738 | for (const auto &CStr : CStrings) |
739 | HNOption.CString.try_emplace(CStr.first, CStr.second); |
740 | |
741 | // clang-format off |
742 | static constexpr std::pair<StringRef, StringRef> PrimitiveTypes[] = { |
743 | {"int8_t", "i8" }, |
744 | {"int16_t", "i16" }, |
745 | {"int32_t", "i32" }, |
746 | {"int64_t", "i64" }, |
747 | {"uint8_t", "u8" }, |
748 | {"uint16_t", "u16" }, |
749 | {"uint32_t", "u32" }, |
750 | {"uint64_t", "u64" }, |
751 | {"char8_t", "c8" }, |
752 | {"char16_t", "c16" }, |
753 | {"char32_t", "c32" }, |
754 | {"float", "f" }, |
755 | {"double", "d" }, |
756 | {"char", "c" }, |
757 | {"bool", "b" }, |
758 | {"_Bool", "b" }, |
759 | {"int", "i" }, |
760 | {"size_t", "n" }, |
761 | {"wchar_t", "wc" }, |
762 | {"short int", "si" }, |
763 | {"short", "s" }, |
764 | {"signed int", "si" }, |
765 | {"signed short", "ss" }, |
766 | {"signed short int", "ssi" }, |
767 | {"signed long long int", "slli"}, |
768 | {"signed long long", "sll" }, |
769 | {"signed long int", "sli" }, |
770 | {"signed long", "sl" }, |
771 | {"signed", "s" }, |
772 | {"unsigned long long int", "ulli"}, |
773 | {"unsigned long long", "ull" }, |
774 | {"unsigned long int", "uli" }, |
775 | {"unsigned long", "ul" }, |
776 | {"unsigned short int", "usi" }, |
777 | {"unsigned short", "us" }, |
778 | {"unsigned int", "ui" }, |
779 | {"unsigned char", "uc" }, |
780 | {"unsigned", "u" }, |
781 | {"long long int", "lli" }, |
782 | {"long double", "ld" }, |
783 | {"long long", "ll" }, |
784 | {"long int", "li" }, |
785 | {"long", "l" }, |
786 | {"ptrdiff_t", "p" }, |
787 | {"void", "" }}; |
788 | // clang-format on |
789 | for (const auto &PT : PrimitiveTypes) |
790 | HNOption.PrimitiveType.try_emplace(PT.first, PT.second); |
791 | |
792 | // clang-format off |
793 | static constexpr std::pair<StringRef, StringRef> UserDefinedTypes[] = { |
794 | // Windows data types |
795 | {"BOOL", "b" }, |
796 | {"BOOLEAN", "b" }, |
797 | {"BYTE", "by" }, |
798 | {"CHAR", "c" }, |
799 | {"UCHAR", "uc" }, |
800 | {"SHORT", "s" }, |
801 | {"USHORT", "us" }, |
802 | {"WORD", "w" }, |
803 | {"DWORD", "dw" }, |
804 | {"DWORD32", "dw32"}, |
805 | {"DWORD64", "dw64"}, |
806 | {"LONG", "l" }, |
807 | {"ULONG", "ul" }, |
808 | {"ULONG32", "ul32"}, |
809 | {"ULONG64", "ul64"}, |
810 | {"ULONGLONG", "ull" }, |
811 | {"HANDLE", "h" }, |
812 | {"INT", "i" }, |
813 | {"INT8", "i8" }, |
814 | {"INT16", "i16" }, |
815 | {"INT32", "i32" }, |
816 | {"INT64", "i64" }, |
817 | {"UINT", "ui" }, |
818 | {"UINT8", "u8" }, |
819 | {"UINT16", "u16" }, |
820 | {"UINT32", "u32" }, |
821 | {"UINT64", "u64" }, |
822 | {"PVOID", "p" } }; |
823 | // clang-format on |
824 | for (const auto &UDT : UserDefinedTypes) |
825 | HNOption.UserDefinedType.try_emplace(UDT.first, UDT.second); |
826 | } |
827 | |
828 | void IdentifierNamingCheck::storeOptions(ClangTidyOptions::OptionMap &Opts) { |
829 | RenamerClangTidyCheck::storeOptions(Opts); |
830 | SmallString<64> StyleString; |
831 | ArrayRef<std::optional<NamingStyle>> Styles = MainFileStyle->getStyles(); |
832 | for (size_t I = 0; I < SK_Count; ++I) { |
833 | if (!Styles[I]) |
834 | continue; |
835 | size_t StyleSize = StyleNames[I].size(); |
836 | StyleString.assign({StyleNames[I], "HungarianPrefix"}); |
837 | |
838 | Options.store(Opts, StyleString, Styles[I]->HPType); |
839 | |
840 | memcpy(&StyleString[StyleSize], "IgnoredRegexp", 13); |
841 | StyleString.truncate(StyleSize + 13); |
842 | Options.store(Opts, StyleString, Styles[I]->IgnoredRegexpStr); |
843 | memcpy(&StyleString[StyleSize], "Prefix", 6); |
844 | StyleString.truncate(StyleSize + 6); |
845 | Options.store(Opts, StyleString, Styles[I]->Prefix); |
846 | // Fast replacement of [Pre]fix -> [Suf]fix. |
847 | memcpy(&StyleString[StyleSize], "Suf", 3); |
848 | Options.store(Opts, StyleString, Styles[I]->Suffix); |
849 | if (Styles[I]->Case) { |
850 | memcpy(&StyleString[StyleSize], "Case", 4); |
851 | StyleString.pop_back_n(2); |
852 | Options.store(Opts, StyleString, *Styles[I]->Case); |
853 | } |
854 | } |
855 | Options.store(Opts, "GetConfigPerFile", GetConfigPerFile); |
856 | Options.store(Opts, "IgnoreFailedSplit", IgnoreFailedSplit); |
857 | Options.store(Opts, "IgnoreMainLikeFunctions", |
858 | MainFileStyle->isIgnoringMainLikeFunction()); |
859 | } |
860 | |
861 | bool IdentifierNamingCheck::matchesStyle( |
862 | StringRef Type, StringRef Name, |
863 | const IdentifierNamingCheck::NamingStyle &Style, |
864 | const IdentifierNamingCheck::HungarianNotationOption &HNOption, |
865 | const NamedDecl *Decl) const { |
866 | static llvm::Regex Matchers[] = { |
867 | llvm::Regex("^.*$"), |
868 | llvm::Regex("^[a-z][a-z0-9_]*$"), |
869 | llvm::Regex("^[a-z][a-zA-Z0-9]*$"), |
870 | llvm::Regex("^[A-Z][A-Z0-9_]*$"), |
871 | llvm::Regex("^[A-Z][a-zA-Z0-9]*$"), |
872 | llvm::Regex("^[A-Z]([a-z0-9]*(_[A-Z])?)*"), |
873 | llvm::Regex("^[a-z]([a-z0-9]*(_[A-Z])?)*"), |
874 | }; |
875 | |
876 | if (!Name.consume_front(Style.Prefix)) |
877 | return false; |
878 | if (!Name.consume_back(Style.Suffix)) |
879 | return false; |
880 | if (IdentifierNamingCheck::HungarianPrefixType::HPT_Off != Style.HPType) { |
881 | std::string HNPrefix = HungarianNotation.getPrefix(Decl, HNOption); |
882 | if (!Name.consume_front(HNPrefix)) |
883 | return false; |
884 | } |
885 | |
886 | // Ensure the name doesn't have any extra underscores beyond those specified |
887 | // in the prefix and suffix. |
888 | if (Name.startswith("_") || Name.endswith("_")) |
889 | return false; |
890 | |
891 | if (Style.Case && !Matchers[static_cast<size_t>(*Style.Case)].match(Name)) |
892 | return false; |
893 | |
894 | return true; |
895 | } |
896 | |
897 | std::string IdentifierNamingCheck::fixupWithCase( |
898 | StringRef Type, StringRef Name, const Decl *D, |
899 | const IdentifierNamingCheck::NamingStyle &Style, |
900 | const IdentifierNamingCheck::HungarianNotationOption &HNOption, |
901 | IdentifierNamingCheck::CaseType Case) const { |
902 | static llvm::Regex Splitter( |
903 | "([a-z0-9A-Z]*)(_+)|([A-Z]?[a-z0-9]+)([A-Z]|$)|([A-Z]+)([A-Z]|$)"); |
904 | |
905 | SmallVector<StringRef, 8> Substrs; |
906 | Name.split(Substrs, "_", -1, false); |
907 | |
908 | SmallVector<StringRef, 8> Words; |
909 | SmallVector<StringRef, 8> Groups; |
910 | for (auto Substr : Substrs) { |
911 | while (!Substr.empty()) { |
912 | Groups.clear(); |
913 | if (!Splitter.match(Substr, &Groups)) |
914 | break; |
915 | |
916 | if (Groups[2].size() > 0) { |
917 | Words.push_back(Groups[1]); |
918 | Substr = Substr.substr(Groups[0].size()); |
919 | } else if (Groups[3].size() > 0) { |
920 | Words.push_back(Groups[3]); |
921 | Substr = Substr.substr(Groups[0].size() - Groups[4].size()); |
922 | } else if (Groups[5].size() > 0) { |
923 | Words.push_back(Groups[5]); |
924 | Substr = Substr.substr(Groups[0].size() - Groups[6].size()); |
925 | } |
926 | } |
927 | } |
928 | |
929 | if (Words.empty()) |
930 | return Name.str(); |
931 | |
932 | if (IdentifierNamingCheck::HungarianPrefixType::HPT_Off != Style.HPType) { |
933 | HungarianNotation.removeDuplicatedPrefix(Words, HNOption); |
934 | } |
935 | |
936 | SmallString<128> Fixup; |
937 | switch (Case) { |
938 | case IdentifierNamingCheck::CT_AnyCase: |
939 | return Name.str(); |
940 | break; |
941 | |
942 | case IdentifierNamingCheck::CT_LowerCase: |
943 | for (auto const &Word : Words) { |
944 | if (&Word != &Words.front()) |
945 | Fixup += "_"; |
946 | Fixup += Word.lower(); |
947 | } |
948 | break; |
949 | |
950 | case IdentifierNamingCheck::CT_UpperCase: |
951 | for (auto const &Word : Words) { |
952 | if (&Word != &Words.front()) |
953 | Fixup += "_"; |
954 | Fixup += Word.upper(); |
955 | } |
956 | break; |
957 | |
958 | case IdentifierNamingCheck::CT_CamelCase: |
959 | for (auto const &Word : Words) { |
960 | Fixup += toupper(Word.front()); |
961 | Fixup += Word.substr(1).lower(); |
962 | } |
963 | break; |
964 | |
965 | case IdentifierNamingCheck::CT_CamelBack: |
966 | for (auto const &Word : Words) { |
967 | if (&Word == &Words.front()) { |
968 | Fixup += Word.lower(); |
969 | } else { |
970 | Fixup += toupper(Word.front()); |
971 | Fixup += Word.substr(1).lower(); |
972 | } |
973 | } |
974 | break; |
975 | |
976 | case IdentifierNamingCheck::CT_CamelSnakeCase: |
977 | for (auto const &Word : Words) { |
978 | if (&Word != &Words.front()) |
979 | Fixup += "_"; |
980 | Fixup += toupper(Word.front()); |
981 | Fixup += Word.substr(1).lower(); |
982 | } |
983 | break; |
984 | |
985 | case IdentifierNamingCheck::CT_CamelSnakeBack: |
986 | for (auto const &Word : Words) { |
987 | if (&Word != &Words.front()) { |
988 | Fixup += "_"; |
989 | Fixup += toupper(Word.front()); |
990 | } else { |
991 | Fixup += tolower(Word.front()); |
992 | } |
993 | Fixup += Word.substr(1).lower(); |
994 | } |
995 | break; |
996 | } |
997 | |
998 | return Fixup.str().str(); |
999 | } |
1000 | |
1001 | bool IdentifierNamingCheck::isParamInMainLikeFunction( |
1002 | const ParmVarDecl &ParmDecl, bool IncludeMainLike) const { |
1003 | const auto *FDecl = |
1004 | dyn_cast_or_null<FunctionDecl>(ParmDecl.getParentFunctionOrMethod()); |
1005 | if (!FDecl) |
1006 | return false; |
1007 | if (FDecl->isMain()) |
1008 | return true; |
1009 | if (!IncludeMainLike) |
1010 | return false; |
1011 | if (FDecl->getAccess() != AS_public && FDecl->getAccess() != AS_none) |
1012 | return false; |
1013 | // If the function doesn't have a name that's an identifier, can occur if the |
1014 | // function is an operator overload, bail out early. |
1015 | if (!FDecl->getDeclName().isIdentifier()) |
1016 | return false; |
1017 | enum MainType { None, Main, WMain }; |
1018 | auto IsCharPtrPtr = [](QualType QType) -> MainType { |
1019 | if (QType.isNull()) |
1020 | return None; |
1021 | if (QType = QType->getPointeeType(), QType.isNull()) |
1022 | return None; |
1023 | if (QType = QType->getPointeeType(), QType.isNull()) |
1024 | return None; |
1025 | if (QType->isCharType()) |
1026 | return Main; |
1027 | if (QType->isWideCharType()) |
1028 | return WMain; |
1029 | return None; |
1030 | }; |
1031 | auto IsIntType = [](QualType QType) { |
1032 | if (QType.isNull()) |
1033 | return false; |
1034 | if (const auto *Builtin = |
1035 | dyn_cast<BuiltinType>(QType->getUnqualifiedDesugaredType())) { |
1036 | return Builtin->getKind() == BuiltinType::Int; |
1037 | } |
1038 | return false; |
1039 | }; |
1040 | if (!IsIntType(FDecl->getReturnType())) |
1041 | return false; |
1042 | if (FDecl->getNumParams() < 2 || FDecl->getNumParams() > 3) |
1043 | return false; |
1044 | if (!IsIntType(FDecl->parameters()[0]->getType())) |
1045 | return false; |
1046 | MainType Type = IsCharPtrPtr(FDecl->parameters()[1]->getType()); |
1047 | if (Type == None) |
1048 | return false; |
1049 | if (FDecl->getNumParams() == 3 && |
1050 | IsCharPtrPtr(FDecl->parameters()[2]->getType()) != Type) |
1051 | return false; |
1052 | |
1053 | if (Type == Main) { |
1054 | static llvm::Regex Matcher( |
1055 | "(^[Mm]ain([_A-Z]|$))|([a-z0-9_]Main([_A-Z]|$))|(_main(_|$))"); |
1056 | assert(Matcher.isValid() && "Invalid Matcher for main like functions.")(static_cast <bool> (Matcher.isValid() && "Invalid Matcher for main like functions." ) ? void (0) : __assert_fail ("Matcher.isValid() && \"Invalid Matcher for main like functions.\"" , "clang-tools-extra/clang-tidy/readability/IdentifierNamingCheck.cpp" , 1056, __extension__ __PRETTY_FUNCTION__)); |
1057 | return Matcher.match(FDecl->getName()); |
1058 | } |
1059 | static llvm::Regex Matcher("(^((W[Mm])|(wm))ain([_A-Z]|$))|([a-z0-9_]W[Mm]" |
1060 | "ain([_A-Z]|$))|(_wmain(_|$))"); |
1061 | assert(Matcher.isValid() && "Invalid Matcher for wmain like functions.")(static_cast <bool> (Matcher.isValid() && "Invalid Matcher for wmain like functions." ) ? void (0) : __assert_fail ("Matcher.isValid() && \"Invalid Matcher for wmain like functions.\"" , "clang-tools-extra/clang-tidy/readability/IdentifierNamingCheck.cpp" , 1061, __extension__ __PRETTY_FUNCTION__)); |
1062 | return Matcher.match(FDecl->getName()); |
1063 | } |
1064 | |
1065 | std::string IdentifierNamingCheck::fixupWithStyle( |
1066 | StringRef Type, StringRef Name, |
1067 | const IdentifierNamingCheck::NamingStyle &Style, |
1068 | const IdentifierNamingCheck::HungarianNotationOption &HNOption, |
1069 | const Decl *D) const { |
1070 | Name.consume_front(Style.Prefix); |
1071 | Name.consume_back(Style.Suffix); |
1072 | std::string Fixed = fixupWithCase( |
1073 | Type, Name, D, Style, HNOption, |
1074 | Style.Case.value_or(IdentifierNamingCheck::CaseType::CT_AnyCase)); |
1075 | |
1076 | std::string HungarianPrefix; |
1077 | using HungarianPrefixType = IdentifierNamingCheck::HungarianPrefixType; |
1078 | if (HungarianPrefixType::HPT_Off != Style.HPType) { |
1079 | HungarianPrefix = HungarianNotation.getPrefix(D, HNOption); |
1080 | if (!HungarianPrefix.empty()) { |
1081 | if (Style.HPType == HungarianPrefixType::HPT_LowerCase) |
1082 | HungarianPrefix += "_"; |
1083 | |
1084 | if (Style.HPType == HungarianPrefixType::HPT_CamelCase) |
1085 | Fixed[0] = toupper(Fixed[0]); |
1086 | } |
1087 | } |
1088 | StringRef Mid = StringRef(Fixed).trim("_"); |
1089 | if (Mid.empty()) |
1090 | Mid = "_"; |
1091 | |
1092 | return (Style.Prefix + HungarianPrefix + Mid + Style.Suffix).str(); |
1093 | } |
1094 | |
1095 | StyleKind IdentifierNamingCheck::findStyleKind( |
1096 | const NamedDecl *D, |
1097 | ArrayRef<std::optional<IdentifierNamingCheck::NamingStyle>> NamingStyles, |
1098 | bool IgnoreMainLikeFunctions) const { |
1099 | assert(D && D->getIdentifier() && !D->getName().empty() && !D->isImplicit() &&(static_cast <bool> (D && D->getIdentifier() && !D->getName().empty() && !D->isImplicit () && "Decl must be an explicit identifier with a name." ) ? void (0) : __assert_fail ("D && D->getIdentifier() && !D->getName().empty() && !D->isImplicit() && \"Decl must be an explicit identifier with a name.\"" , "clang-tools-extra/clang-tidy/readability/IdentifierNamingCheck.cpp" , 1100, __extension__ __PRETTY_FUNCTION__)) |
1100 | "Decl must be an explicit identifier with a name.")(static_cast <bool> (D && D->getIdentifier() && !D->getName().empty() && !D->isImplicit () && "Decl must be an explicit identifier with a name." ) ? void (0) : __assert_fail ("D && D->getIdentifier() && !D->getName().empty() && !D->isImplicit() && \"Decl must be an explicit identifier with a name.\"" , "clang-tools-extra/clang-tidy/readability/IdentifierNamingCheck.cpp" , 1100, __extension__ __PRETTY_FUNCTION__)); |
1101 | |
1102 | if (isa<ObjCIvarDecl>(D) && NamingStyles[SK_ObjcIvar]) |
1103 | return SK_ObjcIvar; |
1104 | |
1105 | if (isa<TypedefDecl>(D) && NamingStyles[SK_Typedef]) |
1106 | return SK_Typedef; |
1107 | |
1108 | if (isa<TypeAliasDecl>(D) && NamingStyles[SK_TypeAlias]) |
1109 | return SK_TypeAlias; |
1110 | |
1111 | if (const auto *Decl = dyn_cast<NamespaceDecl>(D)) { |
1112 | if (Decl->isAnonymousNamespace()) |
1113 | return SK_Invalid; |
1114 | |
1115 | if (Decl->isInline() && NamingStyles[SK_InlineNamespace]) |
1116 | return SK_InlineNamespace; |
1117 | |
1118 | if (NamingStyles[SK_Namespace]) |
1119 | return SK_Namespace; |
1120 | } |
1121 | |
1122 | if (isa<EnumDecl>(D) && NamingStyles[SK_Enum]) |
1123 | return SK_Enum; |
1124 | |
1125 | if (const auto *EnumConst = dyn_cast<EnumConstantDecl>(D)) { |
1126 | if (cast<EnumDecl>(EnumConst->getDeclContext())->isScoped() && |
1127 | NamingStyles[SK_ScopedEnumConstant]) |
1128 | return SK_ScopedEnumConstant; |
1129 | |
1130 | if (NamingStyles[SK_EnumConstant]) |
1131 | return SK_EnumConstant; |
1132 | |
1133 | if (NamingStyles[SK_Constant]) |
1134 | return SK_Constant; |
1135 | |
1136 | return SK_Invalid; |
1137 | } |
1138 | |
1139 | if (const auto *Decl = dyn_cast<CXXRecordDecl>(D)) { |
1140 | if (Decl->isAnonymousStructOrUnion()) |
1141 | return SK_Invalid; |
1142 | |
1143 | if (!Decl->getCanonicalDecl()->isThisDeclarationADefinition()) |
1144 | return SK_Invalid; |
1145 | |
1146 | if (Decl->hasDefinition() && Decl->isAbstract() && |
1147 | NamingStyles[SK_AbstractClass]) |
1148 | return SK_AbstractClass; |
1149 | |
1150 | if (Decl->isStruct() && NamingStyles[SK_Struct]) |
1151 | return SK_Struct; |
1152 | |
1153 | if (Decl->isStruct() && NamingStyles[SK_Class]) |
1154 | return SK_Class; |
1155 | |
1156 | if (Decl->isClass() && NamingStyles[SK_Class]) |
1157 | return SK_Class; |
1158 | |
1159 | if (Decl->isClass() && NamingStyles[SK_Struct]) |
1160 | return SK_Struct; |
1161 | |
1162 | if (Decl->isUnion() && NamingStyles[SK_Union]) |
1163 | return SK_Union; |
1164 | |
1165 | if (Decl->isEnum() && NamingStyles[SK_Enum]) |
1166 | return SK_Enum; |
1167 | |
1168 | return SK_Invalid; |
1169 | } |
1170 | |
1171 | if (const auto *Decl = dyn_cast<FieldDecl>(D)) { |
1172 | QualType Type = Decl->getType(); |
1173 | |
1174 | if (!Type.isNull() && Type.isConstQualified()) { |
1175 | if (NamingStyles[SK_ConstantMember]) |
1176 | return SK_ConstantMember; |
1177 | |
1178 | if (NamingStyles[SK_Constant]) |
1179 | return SK_Constant; |
1180 | } |
1181 | |
1182 | if (Decl->getAccess() == AS_private && NamingStyles[SK_PrivateMember]) |
1183 | return SK_PrivateMember; |
1184 | |
1185 | if (Decl->getAccess() == AS_protected && NamingStyles[SK_ProtectedMember]) |
1186 | return SK_ProtectedMember; |
1187 | |
1188 | if (Decl->getAccess() == AS_public && NamingStyles[SK_PublicMember]) |
1189 | return SK_PublicMember; |
1190 | |
1191 | if (NamingStyles[SK_Member]) |
1192 | return SK_Member; |
1193 | |
1194 | return SK_Invalid; |
1195 | } |
1196 | |
1197 | if (const auto *Decl = dyn_cast<ParmVarDecl>(D)) { |
1198 | if (isParamInMainLikeFunction(*Decl, IgnoreMainLikeFunctions)) |
1199 | return SK_Invalid; |
1200 | QualType Type = Decl->getType(); |
1201 | |
1202 | if (Decl->isConstexpr() && NamingStyles[SK_ConstexprVariable]) |
1203 | return SK_ConstexprVariable; |
1204 | |
1205 | if (!Type.isNull() && Type.isConstQualified()) { |
1206 | if (Type.getTypePtr()->isAnyPointerType() && |
1207 | NamingStyles[SK_ConstantPointerParameter]) |
1208 | return SK_ConstantPointerParameter; |
1209 | |
1210 | if (NamingStyles[SK_ConstantParameter]) |
1211 | return SK_ConstantParameter; |
1212 | |
1213 | if (NamingStyles[SK_Constant]) |
1214 | return SK_Constant; |
1215 | } |
1216 | |
1217 | if (Decl->isParameterPack() && NamingStyles[SK_ParameterPack]) |
1218 | return SK_ParameterPack; |
1219 | |
1220 | if (!Type.isNull() && Type.getTypePtr()->isAnyPointerType() && |
1221 | NamingStyles[SK_PointerParameter]) |
1222 | return SK_PointerParameter; |
1223 | |
1224 | if (NamingStyles[SK_Parameter]) |
1225 | return SK_Parameter; |
1226 | |
1227 | return SK_Invalid; |
1228 | } |
1229 | |
1230 | if (const auto *Decl = dyn_cast<VarDecl>(D)) { |
1231 | QualType Type = Decl->getType(); |
1232 | |
1233 | if (Decl->isConstexpr() && NamingStyles[SK_ConstexprVariable]) |
1234 | return SK_ConstexprVariable; |
1235 | |
1236 | if (!Type.isNull() && Type.isConstQualified()) { |
1237 | if (Decl->isStaticDataMember() && NamingStyles[SK_ClassConstant]) |
1238 | return SK_ClassConstant; |
1239 | |
1240 | if (Decl->isFileVarDecl() && Type.getTypePtr()->isAnyPointerType() && |
1241 | NamingStyles[SK_GlobalConstantPointer]) |
1242 | return SK_GlobalConstantPointer; |
1243 | |
1244 | if (Decl->isFileVarDecl() && NamingStyles[SK_GlobalConstant]) |
1245 | return SK_GlobalConstant; |
1246 | |
1247 | if (Decl->isStaticLocal() && NamingStyles[SK_StaticConstant]) |
1248 | return SK_StaticConstant; |
1249 | |
1250 | if (Decl->isLocalVarDecl() && Type.getTypePtr()->isAnyPointerType() && |
1251 | NamingStyles[SK_LocalConstantPointer]) |
1252 | return SK_LocalConstantPointer; |
1253 | |
1254 | if (Decl->isLocalVarDecl() && NamingStyles[SK_LocalConstant]) |
1255 | return SK_LocalConstant; |
1256 | |
1257 | if (Decl->isFunctionOrMethodVarDecl() && NamingStyles[SK_LocalConstant]) |
1258 | return SK_LocalConstant; |
1259 | |
1260 | if (NamingStyles[SK_Constant]) |
1261 | return SK_Constant; |
1262 | } |
1263 | |
1264 | if (Decl->isStaticDataMember() && NamingStyles[SK_ClassMember]) |
1265 | return SK_ClassMember; |
1266 | |
1267 | if (Decl->isFileVarDecl() && Type.getTypePtr()->isAnyPointerType() && |
1268 | NamingStyles[SK_GlobalPointer]) |
1269 | return SK_GlobalPointer; |
1270 | |
1271 | if (Decl->isFileVarDecl() && NamingStyles[SK_GlobalVariable]) |
1272 | return SK_GlobalVariable; |
1273 | |
1274 | if (Decl->isStaticLocal() && NamingStyles[SK_StaticVariable]) |
1275 | return SK_StaticVariable; |
1276 | |
1277 | if (Decl->isLocalVarDecl() && Type.getTypePtr()->isAnyPointerType() && |
1278 | NamingStyles[SK_LocalPointer]) |
1279 | return SK_LocalPointer; |
1280 | |
1281 | if (Decl->isLocalVarDecl() && NamingStyles[SK_LocalVariable]) |
1282 | return SK_LocalVariable; |
1283 | |
1284 | if (Decl->isFunctionOrMethodVarDecl() && NamingStyles[SK_LocalVariable]) |
1285 | return SK_LocalVariable; |
1286 | |
1287 | if (NamingStyles[SK_Variable]) |
1288 | return SK_Variable; |
1289 | |
1290 | return SK_Invalid; |
1291 | } |
1292 | |
1293 | if (const auto *Decl = dyn_cast<CXXMethodDecl>(D)) { |
1294 | if (Decl->isMain() || !Decl->isUserProvided() || |
1295 | Decl->size_overridden_methods() > 0 || Decl->hasAttr<OverrideAttr>()) |
1296 | return SK_Invalid; |
1297 | |
1298 | // If this method has the same name as any base method, this is likely |
1299 | // necessary even if it's not an override. e.g. CRTP. |
1300 | for (const CXXBaseSpecifier &Base : Decl->getParent()->bases()) |
1301 | if (const auto *RD = Base.getType()->getAsCXXRecordDecl()) |
1302 | if (RD->hasMemberName(Decl->getDeclName())) |
1303 | return SK_Invalid; |
1304 | |
1305 | if (Decl->isConstexpr() && NamingStyles[SK_ConstexprMethod]) |
1306 | return SK_ConstexprMethod; |
1307 | |
1308 | if (Decl->isConstexpr() && NamingStyles[SK_ConstexprFunction]) |
1309 | return SK_ConstexprFunction; |
1310 | |
1311 | if (Decl->isStatic() && NamingStyles[SK_ClassMethod]) |
1312 | return SK_ClassMethod; |
1313 | |
1314 | if (Decl->isVirtual() && NamingStyles[SK_VirtualMethod]) |
1315 | return SK_VirtualMethod; |
1316 | |
1317 | if (Decl->getAccess() == AS_private && NamingStyles[SK_PrivateMethod]) |
1318 | return SK_PrivateMethod; |
1319 | |
1320 | if (Decl->getAccess() == AS_protected && NamingStyles[SK_ProtectedMethod]) |
1321 | return SK_ProtectedMethod; |
1322 | |
1323 | if (Decl->getAccess() == AS_public && NamingStyles[SK_PublicMethod]) |
1324 | return SK_PublicMethod; |
1325 | |
1326 | if (NamingStyles[SK_Method]) |
1327 | return SK_Method; |
1328 | |
1329 | if (NamingStyles[SK_Function]) |
1330 | return SK_Function; |
1331 | |
1332 | return SK_Invalid; |
1333 | } |
1334 | |
1335 | if (const auto *Decl = dyn_cast<FunctionDecl>(D)) { |
1336 | if (Decl->isMain()) |
1337 | return SK_Invalid; |
1338 | |
1339 | if (Decl->isConstexpr() && NamingStyles[SK_ConstexprFunction]) |
1340 | return SK_ConstexprFunction; |
1341 | |
1342 | if (Decl->isGlobal() && NamingStyles[SK_GlobalFunction]) |
1343 | return SK_GlobalFunction; |
1344 | |
1345 | if (NamingStyles[SK_Function]) |
1346 | return SK_Function; |
1347 | } |
1348 | |
1349 | if (isa<TemplateTypeParmDecl>(D)) { |
1350 | if (NamingStyles[SK_TypeTemplateParameter]) |
1351 | return SK_TypeTemplateParameter; |
1352 | |
1353 | if (NamingStyles[SK_TemplateParameter]) |
1354 | return SK_TemplateParameter; |
1355 | |
1356 | return SK_Invalid; |
1357 | } |
1358 | |
1359 | if (isa<NonTypeTemplateParmDecl>(D)) { |
1360 | if (NamingStyles[SK_ValueTemplateParameter]) |
1361 | return SK_ValueTemplateParameter; |
1362 | |
1363 | if (NamingStyles[SK_TemplateParameter]) |
1364 | return SK_TemplateParameter; |
1365 | |
1366 | return SK_Invalid; |
1367 | } |
1368 | |
1369 | if (isa<TemplateTemplateParmDecl>(D)) { |
1370 | if (NamingStyles[SK_TemplateTemplateParameter]) |
1371 | return SK_TemplateTemplateParameter; |
1372 | |
1373 | if (NamingStyles[SK_TemplateParameter]) |
1374 | return SK_TemplateParameter; |
1375 | |
1376 | return SK_Invalid; |
1377 | } |
1378 | |
1379 | return SK_Invalid; |
1380 | } |
1381 | |
1382 | std::optional<RenamerClangTidyCheck::FailureInfo> |
1383 | IdentifierNamingCheck::getFailureInfo( |
1384 | StringRef Type, StringRef Name, const NamedDecl *ND, |
1385 | SourceLocation Location, |
1386 | ArrayRef<std::optional<IdentifierNamingCheck::NamingStyle>> NamingStyles, |
1387 | const IdentifierNamingCheck::HungarianNotationOption &HNOption, |
1388 | StyleKind SK, const SourceManager &SM, bool IgnoreFailedSplit) const { |
1389 | if (SK == SK_Invalid || !NamingStyles[SK]) |
1390 | return std::nullopt; |
1391 | |
1392 | const IdentifierNamingCheck::NamingStyle &Style = *NamingStyles[SK]; |
1393 | if (Style.IgnoredRegexp.isValid() && Style.IgnoredRegexp.match(Name)) |
1394 | return std::nullopt; |
1395 | |
1396 | if (matchesStyle(Type, Name, Style, HNOption, ND)) |
1397 | return std::nullopt; |
1398 | |
1399 | std::string KindName = |
1400 | fixupWithCase(Type, StyleNames[SK], ND, Style, HNOption, |
1401 | IdentifierNamingCheck::CT_LowerCase); |
1402 | std::replace(KindName.begin(), KindName.end(), '_', ' '); |
1403 | |
1404 | std::string Fixup = fixupWithStyle(Type, Name, Style, HNOption, ND); |
1405 | if (StringRef(Fixup).equals(Name)) { |
1406 | if (!IgnoreFailedSplit) { |
1407 | LLVM_DEBUG(Location.print(llvm::dbgs(), SM);do { if (::llvm::DebugFlag && ::llvm::isCurrentDebugType ("clang-tidy")) { Location.print(llvm::dbgs(), SM); llvm::dbgs () << llvm::formatv(": unable to split words for {0} '{1}'\n" , KindName, Name); } } while (false) |
1408 | llvm::dbgs()do { if (::llvm::DebugFlag && ::llvm::isCurrentDebugType ("clang-tidy")) { Location.print(llvm::dbgs(), SM); llvm::dbgs () << llvm::formatv(": unable to split words for {0} '{1}'\n" , KindName, Name); } } while (false) |
1409 | << llvm::formatv(": unable to split words for {0} '{1}'\n",do { if (::llvm::DebugFlag && ::llvm::isCurrentDebugType ("clang-tidy")) { Location.print(llvm::dbgs(), SM); llvm::dbgs () << llvm::formatv(": unable to split words for {0} '{1}'\n" , KindName, Name); } } while (false) |
1410 | KindName, Name))do { if (::llvm::DebugFlag && ::llvm::isCurrentDebugType ("clang-tidy")) { Location.print(llvm::dbgs(), SM); llvm::dbgs () << llvm::formatv(": unable to split words for {0} '{1}'\n" , KindName, Name); } } while (false); |
1411 | } |
1412 | return std::nullopt; |
1413 | } |
1414 | return RenamerClangTidyCheck::FailureInfo{std::move(KindName), |
1415 | std::move(Fixup)}; |
1416 | } |
1417 | |
1418 | std::optional<RenamerClangTidyCheck::FailureInfo> |
1419 | IdentifierNamingCheck::getDeclFailureInfo(const NamedDecl *Decl, |
1420 | const SourceManager &SM) const { |
1421 | SourceLocation Loc = Decl->getLocation(); |
1422 | const FileStyle &FileStyle = getStyleForFile(SM.getFilename(Loc)); |
1423 | if (!FileStyle.isActive()) |
1424 | return std::nullopt; |
1425 | |
1426 | return getFailureInfo(HungarianNotation.getDeclTypeName(Decl), |
1427 | Decl->getName(), Decl, Loc, FileStyle.getStyles(), |
1428 | FileStyle.getHNOption(), |
1429 | findStyleKind(Decl, FileStyle.getStyles(), |
1430 | FileStyle.isIgnoringMainLikeFunction()), |
1431 | SM, IgnoreFailedSplit); |
1432 | } |
1433 | |
1434 | std::optional<RenamerClangTidyCheck::FailureInfo> |
1435 | IdentifierNamingCheck::getMacroFailureInfo(const Token &MacroNameTok, |
1436 | const SourceManager &SM) const { |
1437 | SourceLocation Loc = MacroNameTok.getLocation(); |
1438 | const FileStyle &Style = getStyleForFile(SM.getFilename(Loc)); |
1439 | if (!Style.isActive()) |
1440 | return std::nullopt; |
1441 | |
1442 | return getFailureInfo("", MacroNameTok.getIdentifierInfo()->getName(), |
1443 | nullptr, Loc, Style.getStyles(), Style.getHNOption(), |
1444 | SK_MacroDefinition, SM, IgnoreFailedSplit); |
1445 | } |
1446 | |
1447 | RenamerClangTidyCheck::DiagInfo |
1448 | IdentifierNamingCheck::getDiagInfo(const NamingCheckId &ID, |
1449 | const NamingCheckFailure &Failure) const { |
1450 | return DiagInfo{"invalid case style for %0 '%1'", |
1451 | [&](DiagnosticBuilder &Diag) { |
1452 | Diag << Failure.Info.KindName << ID.second; |
1453 | }}; |
1454 | } |
1455 | |
1456 | const IdentifierNamingCheck::FileStyle & |
1457 | IdentifierNamingCheck::getStyleForFile(StringRef FileName) const { |
1458 | if (!GetConfigPerFile) |
1459 | return *MainFileStyle; |
1460 | StringRef Parent = llvm::sys::path::parent_path(FileName); |
1461 | auto Iter = NamingStylesCache.find(Parent); |
1462 | if (Iter != NamingStylesCache.end()) |
1463 | return Iter->getValue(); |
1464 | |
1465 | llvm::StringRef CheckName = getID(); |
1466 | ClangTidyOptions Options = Context->getOptionsForFile(FileName); |
1467 | if (Options.Checks && GlobList(*Options.Checks).contains(CheckName)) { |
1468 | auto It = NamingStylesCache.try_emplace( |
1469 | Parent, |
1470 | getFileStyleFromOptions({CheckName, Options.CheckOptions, Context})); |
1471 | assert(It.second)(static_cast <bool> (It.second) ? void (0) : __assert_fail ("It.second", "clang-tools-extra/clang-tidy/readability/IdentifierNamingCheck.cpp" , 1471, __extension__ __PRETTY_FUNCTION__)); |
1472 | return It.first->getValue(); |
1473 | } |
1474 | // Default construction gives an empty style. |
1475 | auto It = NamingStylesCache.try_emplace(Parent); |
1476 | assert(It.second)(static_cast <bool> (It.second) ? void (0) : __assert_fail ("It.second", "clang-tools-extra/clang-tidy/readability/IdentifierNamingCheck.cpp" , 1476, __extension__ __PRETTY_FUNCTION__)); |
1477 | return It.first->getValue(); |
1478 | } |
1479 | |
1480 | } // namespace readability |
1481 | } // namespace clang::tidy |