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 IgnoreCommandLine)
+ : Check(Check), SM(SM), RegExp(RegExp), CheckCapsOnly(CapsOnly),
+ IgnoreCommandLineMacros(IgnoreCommandLine) {}
void MacroDefined(const Token &MacroNameTok,
const MacroDirective *MD) override {
if (MD->getMacroInfo()->isUsedForHeaderGuard() ||
MD->getMacroInfo()->getNumTokens() == 0)
return;
+ if (IgnoreCommandLineMacros &&
+ 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 IgnoreCommandLineMacros;
};
} // namespace
void MacroUsageCheck::storeOptions(ClangTidyOptions::OptionMap &Opts) {
Options.store(Opts, "AllowedRegexp", AllowedRegexp);
Options.store(Opts, "CheckCapsOnly", CheckCapsOnly);
+ Options.store(Opts, "IgnoreCommandLineMacros", IgnoreCommandLineMacros);
}
void MacroUsageCheck::registerPPCallbacks(CompilerInstance &Compiler) {
return;
Compiler.getPreprocessor().addPPCallbacks(
- llvm::make_unique<MacroUsageCallbacks>(this, AllowedRegexp,
- CheckCapsOnly));
+ llvm::make_unique<MacroUsageCallbacks>(this, Compiler.getSourceManager(),
+ AllowedRegexp, CheckCapsOnly,
+ IgnoreCommandLineMacros));
}
-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
MacroUsageCheck(StringRef Name, ClangTidyContext *Context)
: ClangTidyCheck(Name, Context),
AllowedRegexp(Options.get("AllowedRegexp", "^DEBUG_*")),
- CheckCapsOnly(Options.get("CheckCapsOnly", 0)) {}
+ CheckCapsOnly(Options.get("CheckCapsOnly", 0)),
+ IgnoreCommandLineMacros(Options.get("IgnoreCommandLineMacros", 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 IgnoreCommandLineMacros;
};
} // namespace cppcoreguidelines
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:: IgnoreCommandLineMacros
+
+ Boolean flag to toggle ignoring command-line-defined macros.
+ Default value is `1`/`true`.
#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))
--- /dev/null
+// 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.IgnoreCommandLineMacros, 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.IgnoreCommandLineMacros, 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
#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))
#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