8
8
9
9
#include " IdentifierNamingCheck.h"
10
10
11
- #include " ../utils/ASTUtils.h"
12
- #include " clang/ASTMatchers/ASTMatchFinder.h"
13
11
#include " clang/AST/CXXInheritance.h"
14
- #include " clang/Frontend/CompilerInstance.h"
15
12
#include " clang/Lex/PPCallbacks.h"
16
13
#include " clang/Lex/Preprocessor.h"
17
14
#include " llvm/ADT/DenseMapInfo.h"
18
15
#include " llvm/Support/Debug.h"
19
16
#include " llvm/Support/Format.h"
17
+ #include " llvm/Support/Regex.h"
20
18
21
19
#define DEBUG_TYPE " clang-tidy"
22
20
@@ -126,7 +124,9 @@ class IdentifierNamingCheckPPCallbacks : public PPCallbacks {
126
124
127
125
IdentifierNamingCheck::IdentifierNamingCheck (StringRef Name,
128
126
ClangTidyContext *Context)
129
- : RenamerClangTidyCheck(Name, Context) {
127
+ : RenamerClangTidyCheck(Name, Context),
128
+ IgnoreFailedSplit (Options.get(" IgnoreFailedSplit" , 0 )),
129
+ IgnoreMainLikeFunctions(Options.get(" IgnoreMainLikeFunctions" , 0 )) {
130
130
auto const fromString = [](StringRef Str) {
131
131
return llvm::StringSwitch<llvm::Optional<CaseType>>(Str)
132
132
.Case (" aNy_CasE" , CT_AnyCase)
@@ -151,8 +151,6 @@ IdentifierNamingCheck::IdentifierNamingCheck(StringRef Name,
151
151
NamingStyles.push_back (llvm::None);
152
152
}
153
153
}
154
-
155
- IgnoreFailedSplit = Options.get (" IgnoreFailedSplit" , 0 );
156
154
}
157
155
158
156
IdentifierNamingCheck::~IdentifierNamingCheck () = default ;
@@ -193,6 +191,7 @@ void IdentifierNamingCheck::storeOptions(ClangTidyOptions::OptionMap &Opts) {
193
191
}
194
192
195
193
Options.store (Opts, " IgnoreFailedSplit" , IgnoreFailedSplit);
194
+ Options.store (Opts, " IgnoreMainLikeFunctions" , IgnoreMainLikeFunctions);
196
195
}
197
196
198
197
static bool matchesStyle (StringRef Name,
@@ -324,6 +323,67 @@ static std::string fixupWithCase(StringRef Name,
324
323
return Fixup;
325
324
}
326
325
326
+ static bool isParamInMainLikeFunction (const ParmVarDecl &ParmDecl,
327
+ bool IncludeMainLike) {
328
+ const auto *FDecl =
329
+ dyn_cast_or_null<FunctionDecl>(ParmDecl.getParentFunctionOrMethod ());
330
+ if (!FDecl)
331
+ return false ;
332
+ if (FDecl->isMain ())
333
+ return true ;
334
+ if (!IncludeMainLike)
335
+ return false ;
336
+ if (FDecl->getAccess () != AS_public && FDecl->getAccess () != AS_none)
337
+ return false ;
338
+ enum MainType { None, Main, WMain };
339
+ auto IsCharPtrPtr = [](QualType QType) -> MainType {
340
+ if (QType.isNull ())
341
+ return None;
342
+ if (QType = QType->getPointeeType (), QType.isNull ())
343
+ return None;
344
+ if (QType = QType->getPointeeType (), QType.isNull ())
345
+ return None;
346
+ if (QType->isCharType ())
347
+ return Main;
348
+ if (QType->isWideCharType ())
349
+ return WMain;
350
+ return None;
351
+ };
352
+ auto IsIntType = [](QualType QType) {
353
+ if (QType.isNull ())
354
+ return false ;
355
+ if (const auto *Builtin =
356
+ dyn_cast<BuiltinType>(QType->getUnqualifiedDesugaredType ())) {
357
+ return Builtin->getKind () == BuiltinType::Int;
358
+ }
359
+ return false ;
360
+ };
361
+ if (!IsIntType (FDecl->getReturnType ()))
362
+ return false ;
363
+ if (FDecl->getNumParams () < 2 || FDecl->getNumParams () > 3 )
364
+ return false ;
365
+ if (!IsIntType (FDecl->parameters ()[0 ]->getType ()))
366
+ return false ;
367
+ MainType Type = IsCharPtrPtr (FDecl->parameters ()[1 ]->getType ());
368
+ if (Type == None)
369
+ return false ;
370
+ if (FDecl->getNumParams () == 3 &&
371
+ IsCharPtrPtr (FDecl->parameters ()[2 ]->getType ()) != Type)
372
+ return false ;
373
+
374
+ if (Type == Main) {
375
+ static llvm::Regex Matcher (
376
+ " (^[Mm]ain([_A-Z]|$))|([a-z0-9_]Main([_A-Z]|$))|(_main(_|$))" );
377
+ assert (Matcher.isValid () && " Invalid Matcher for main like functions." );
378
+ return Matcher.match (FDecl->getName ());
379
+ } else {
380
+ static llvm::Regex Matcher (" (^((W[Mm])|(wm))ain([_A-Z]|$))|([a-z0-9_]W[Mm]"
381
+ " ain([_A-Z]|$))|(_wmain(_|$))" );
382
+ assert (Matcher.isValid () && " Invalid Matcher for wmain like functions." );
383
+ return Matcher.match (FDecl->getName ());
384
+ }
385
+ }
386
+
327
387
static std::string
328
388
fixupWithStyle (StringRef Name,
329
389
const IdentifierNamingCheck::NamingStyle &Style) {
@@ -338,7 +398,8 @@ fixupWithStyle(StringRef Name,
338
398
static StyleKind findStyleKind (
339
399
const NamedDecl *D,
340
400
const std::vector<llvm::Optional<IdentifierNamingCheck::NamingStyle>>
341
- &NamingStyles) {
401
+ &NamingStyles,
402
+ bool IgnoreMainLikeFunctions) {
342
403
assert (D && D->getIdentifier () && !D->getName ().empty () && !D->isImplicit () &&
343
404
" Decl must be an explicit identifier with a name." );
344
405
@@ -434,6 +495,8 @@ static StyleKind findStyleKind(
434
495
}
435
496
436
497
if (const auto *Decl = dyn_cast<ParmVarDecl>(D)) {
498
+ if (isParamInMainLikeFunction (*Decl, IgnoreMainLikeFunctions))
499
+ return SK_Invalid;
437
500
QualType Type = Decl->getType ();
438
501
439
502
if (Decl->isConstexpr () && NamingStyles[SK_ConstexprVariable])
@@ -615,7 +678,7 @@ static StyleKind findStyleKind(
615
678
llvm::Optional<RenamerClangTidyCheck::FailureInfo>
616
679
IdentifierNamingCheck::GetDeclFailureInfo (const NamedDecl *Decl,
617
680
const SourceManager &SM) const {
618
- StyleKind SK = findStyleKind (Decl, NamingStyles);
681
+ StyleKind SK = findStyleKind (Decl, NamingStyles, IgnoreMainLikeFunctions );
619
682
if (SK == SK_Invalid)
620
683
return None;
621
684
0 commit comments