Index: clang-tidy/cppcoreguidelines/MacroUsageCheck.h =================================================================== --- clang-tidy/cppcoreguidelines/MacroUsageCheck.h +++ clang-tidy/cppcoreguidelines/MacroUsageCheck.h @@ -28,17 +28,20 @@ MacroUsageCheck(StringRef Name, ClangTidyContext *Context) : ClangTidyCheck(Name, Context), AllowedRegexp(Options.get("AllowedRegexp", "^DEBUG_*")), - CheckCapsOnly(Options.get("CheckCapsOnly", 0)) {} + CheckCapsOnly(Options.get("CheckCapsOnly", 0)), + IgnoreLocationless(Options.get("IgnoreLocationless", 1)) {} void storeOptions(ClangTidyOptions::OptionMap &Opts) override; void registerPPCallbacks(CompilerInstance &Compiler) override; - void warnMacro(const MacroDirective *MD); - void warnNaming(const MacroDirective *MD); + void warnMacro(const MacroDirective *MD, StringRef MacroName); + void warnNaming(const MacroDirective *MD, StringRef MacroName); private: /// A regular expression that defines how allowed macros must look like. std::string AllowedRegexp; /// Control if only the check shall only test on CAPS_ONLY macros. bool CheckCapsOnly; + /// Should the macros without a valid location be diagnosed? + bool IgnoreLocationless; }; } // namespace cppcoreguidelines Index: clang-tidy/cppcoreguidelines/MacroUsageCheck.cpp =================================================================== --- clang-tidy/cppcoreguidelines/MacroUsageCheck.cpp +++ clang-tidy/cppcoreguidelines/MacroUsageCheck.cpp @@ -31,32 +31,40 @@ class MacroUsageCallbacks : public PPCallbacks { public: - MacroUsageCallbacks(MacroUsageCheck *Check, StringRef RegExp, bool CapsOnly) - : Check(Check), RegExp(RegExp), CheckCapsOnly(CapsOnly) {} + MacroUsageCallbacks(MacroUsageCheck *Check, const SourceManager &SM, + StringRef RegExp, bool CapsOnly, bool Locationless) + : Check(Check), SM(SM), RegExp(RegExp), CheckCapsOnly(CapsOnly), + IgnoreLocationless(Locationless) {} void MacroDefined(const Token &MacroNameTok, const MacroDirective *MD) override { if (MD->getMacroInfo()->isUsedForHeaderGuard() || MD->getMacroInfo()->getNumTokens() == 0) return; + if (IgnoreLocationless && SM.isWrittenInCommandLineFile(MD->getLocation())) + return; + StringRef MacroName = MacroNameTok.getIdentifierInfo()->getName(); if (!CheckCapsOnly && !llvm::Regex(RegExp).match(MacroName)) - Check->warnMacro(MD); + Check->warnMacro(MD, MacroName); if (CheckCapsOnly && !isCapsOnly(MacroName)) - Check->warnNaming(MD); + Check->warnNaming(MD, MacroName); } private: MacroUsageCheck *Check; + const SourceManager &SM; StringRef RegExp; bool CheckCapsOnly; + bool IgnoreLocationless; }; } // namespace void MacroUsageCheck::storeOptions(ClangTidyOptions::OptionMap &Opts) { Options.store(Opts, "AllowedRegexp", AllowedRegexp); Options.store(Opts, "CheckCapsOnly", CheckCapsOnly); + Options.store(Opts, "IgnoreLocationless", IgnoreLocationless); } void MacroUsageCheck::registerPPCallbacks(CompilerInstance &Compiler) { @@ -64,31 +72,34 @@ return; Compiler.getPreprocessor().addPPCallbacks( - llvm::make_unique(this, AllowedRegexp, - CheckCapsOnly)); + llvm::make_unique(this, Compiler.getSourceManager(), + AllowedRegexp, CheckCapsOnly, + IgnoreLocationless)); } -void MacroUsageCheck::warnMacro(const MacroDirective *MD) { +void MacroUsageCheck::warnMacro(const MacroDirective *MD, StringRef MacroName) { StringRef Message = - "macro used to declare a constant; consider using a 'constexpr' " + "macro '%0' used to declare a constant; consider using a 'constexpr' " "constant"; /// A variadic macro is function-like at the same time. Therefore variadic /// macros are checked first and will be excluded for the function-like /// diagnostic. if (MD->getMacroInfo()->isVariadic()) - Message = "variadic macro used; consider using a 'constexpr' " + Message = "variadic macro '%0' used; consider using a 'constexpr' " "variadic template function"; else if (MD->getMacroInfo()->isFunctionLike()) - Message = "function-like macro used; consider a 'constexpr' template " + Message = "function-like macro '%0' used; consider a 'constexpr' template " "function"; - diag(MD->getLocation(), Message); + diag(MD->getLocation(), Message) << MacroName; } -void MacroUsageCheck::warnNaming(const MacroDirective *MD) { +void MacroUsageCheck::warnNaming(const MacroDirective *MD, + StringRef MacroName) { diag(MD->getLocation(), "macro definition does not define the macro name " - "using all uppercase characters"); + "'%0' using all uppercase characters") + << MacroName; } } // namespace cppcoreguidelines Index: docs/clang-tidy/checks/cppcoreguidelines-macro-usage.rst =================================================================== --- docs/clang-tidy/checks/cppcoreguidelines-macro-usage.rst +++ docs/clang-tidy/checks/cppcoreguidelines-macro-usage.rst @@ -26,3 +26,8 @@ Boolean flag to warn on all macros except those with CAPS_ONLY names. This option is intended to ease introduction of this check into older code bases. Default value is `0`/`false`. + +.. option:: IgnoreLocationless + + Boolean flag to toggle ignoring command-line-defined macros. + Default value is `1`/`true`. Index: test/clang-tidy/cppcoreguidelines-macro-usage-caps-only.cpp =================================================================== --- test/clang-tidy/cppcoreguidelines-macro-usage-caps-only.cpp +++ test/clang-tidy/cppcoreguidelines-macro-usage-caps-only.cpp @@ -6,16 +6,16 @@ #define INCLUDE_GUARD #define problematic_constant 0 -// CHECK-MESSAGES: [[@LINE-1]]:9: warning: macro definition does not define the macro name using all uppercase characters +// CHECK-MESSAGES: [[@LINE-1]]:9: warning: macro definition does not define the macro name 'problematic_constant' using all uppercase characters #define problematic_function(x, y) ((a) > (b) ? (a) : (b)) -// CHECK-MESSAGES: [[@LINE-1]]:9: warning: macro definition does not define the macro name using all uppercase characters +// CHECK-MESSAGES: [[@LINE-1]]:9: warning: macro definition does not define the macro name 'problematic_function' using all uppercase characters #define problematic_variadic(...) (__VA_ARGS__) -// CHECK-MESSAGES: [[@LINE-1]]:9: warning: macro definition does not define the macro name using all uppercase characters +// CHECK-MESSAGES: [[@LINE-1]]:9: warning: macro definition does not define the macro name 'problematic_variadic' using all uppercase characters // #define problematic_variadic2(x, ...) (__VA_ARGS__) -// CHECK-MESSAGES: [[@LINE-1]]:9: warning: macro definition does not define the macro name using all uppercase characters +// CHECK-MESSAGES: [[@LINE-1]]:9: warning: macro definition does not define the macro name 'problematic_variadic2' using all uppercase characters #define OKISH_CONSTANT 42 #define OKISH_FUNCTION(x, y) ((a) > (b) ? (a) : (b)) Index: test/clang-tidy/cppcoreguidelines-macro-usage-command-line-macros.cpp =================================================================== --- /dev/null +++ test/clang-tidy/cppcoreguidelines-macro-usage-command-line-macros.cpp @@ -0,0 +1,8 @@ +// RUN: %check_clang_tidy -check-suffixes=NORMAL %s cppcoreguidelines-macro-usage %t -- -- -D_ZZZ_IM_A_MACRO +// RUN: %check_clang_tidy -check-suffixes=NORMAL %s cppcoreguidelines-macro-usage %t -- -config='{CheckOptions: [{key: cppcoreguidelines-macro-usage.IgnoreLocationless, value: 1}]}' -- -D_ZZZ_IM_A_MACRO +// RUN: %check_clang_tidy -check-suffixes=NORMAL,CL %s cppcoreguidelines-macro-usage %t -- -config='{CheckOptions: [{key: cppcoreguidelines-macro-usage.IgnoreLocationless, value: 0}]}' -- -D_ZZZ_IM_A_MACRO + +// CHECK-MESSAGES-CL: warning: macro '_ZZZ_IM_A_MACRO' used to declare a constant; consider using a 'constexpr' constant + +#define PROBLEMATIC_CONSTANT 0 +// CHECK-MESSAGES-NORMAL: [[@LINE-1]]:9: warning: macro 'PROBLEMATIC_CONSTANT' used to declare a constant; consider using a 'constexpr' constant Index: test/clang-tidy/cppcoreguidelines-macro-usage-custom.cpp =================================================================== --- test/clang-tidy/cppcoreguidelines-macro-usage-custom.cpp +++ test/clang-tidy/cppcoreguidelines-macro-usage-custom.cpp @@ -6,16 +6,16 @@ #define INCLUDE_GUARD #define PROBLEMATIC_CONSTANT 0 -// CHECK-MESSAGES: [[@LINE-1]]:9: warning: macro used to declare a constant; consider using a 'constexpr' constant +// CHECK-MESSAGES: [[@LINE-1]]:9: warning: macro 'PROBLEMATIC_CONSTANT' used to declare a constant; consider using a 'constexpr' constant #define PROBLEMATIC_FUNCTION(x, y) ((a) > (b) ? (a) : (b)) -// CHECK-MESSAGES: [[@LINE-1]]:9: warning: function-like macro used; consider a 'constexpr' template function +// CHECK-MESSAGES: [[@LINE-1]]:9: warning: function-like macro 'PROBLEMATIC_FUNCTION' used; consider a 'constexpr' template function #define PROBLEMATIC_VARIADIC(...) (__VA_ARGS__) -// CHECK-MESSAGES: [[@LINE-1]]:9: warning: variadic macro used; consider using a 'constexpr' variadic template function +// CHECK-MESSAGES: [[@LINE-1]]:9: warning: variadic macro 'PROBLEMATIC_VARIADIC' used; consider using a 'constexpr' variadic template function #define PROBLEMATIC_VARIADIC2(x, ...) (__VA_ARGS__) -// CHECK-MESSAGES: [[@LINE-1]]:9: warning: variadic macro used; consider using a 'constexpr' variadic template function +// CHECK-MESSAGES: [[@LINE-1]]:9: warning: variadic macro 'PROBLEMATIC_VARIADIC2' used; consider using a 'constexpr' variadic template function #define DEBUG_CONSTANT 0 #define DEBUG_FUNCTION(x, y) ((a) > (b) ? (a) : (b)) Index: test/clang-tidy/cppcoreguidelines-macro-usage.cpp =================================================================== --- test/clang-tidy/cppcoreguidelines-macro-usage.cpp +++ test/clang-tidy/cppcoreguidelines-macro-usage.cpp @@ -4,15 +4,15 @@ #define INCLUDE_GUARD #define PROBLEMATIC_CONSTANT 0 -// CHECK-MESSAGES: [[@LINE-1]]:9: warning: macro used to declare a constant; consider using a 'constexpr' constant +// CHECK-MESSAGES: [[@LINE-1]]:9: warning: macro 'PROBLEMATIC_CONSTANT' used to declare a constant; consider using a 'constexpr' constant #define PROBLEMATIC_FUNCTION(x, y) ((a) > (b) ? (a) : (b)) -// CHECK-MESSAGES: [[@LINE-1]]:9: warning: function-like macro used; consider a 'constexpr' template function +// CHECK-MESSAGES: [[@LINE-1]]:9: warning: function-like macro 'PROBLEMATIC_FUNCTION' used; consider a 'constexpr' template function #define PROBLEMATIC_VARIADIC(...) (__VA_ARGS__) -// CHECK-MESSAGES: [[@LINE-1]]:9: warning: variadic macro used; consider using a 'constexpr' variadic template function +// CHECK-MESSAGES: [[@LINE-1]]:9: warning: variadic macro 'PROBLEMATIC_VARIADIC' used; consider using a 'constexpr' variadic template function #define PROBLEMATIC_VARIADIC2(x, ...) (__VA_ARGS__) -// CHECK-MESSAGES: [[@LINE-1]]:9: warning: variadic macro used; consider using a 'constexpr' variadic template function +// CHECK-MESSAGES: [[@LINE-1]]:9: warning: variadic macro 'PROBLEMATIC_VARIADIC2' used; consider using a 'constexpr' variadic template function #endif