diff --git a/clang-tools-extra/clang-tidy/cppcoreguidelines/MacroUsageCheck.cpp b/clang-tools-extra/clang-tidy/cppcoreguidelines/MacroUsageCheck.cpp index 766cae45f15b5..0836a5c386dd8 100644 --- a/clang-tools-extra/clang-tidy/cppcoreguidelines/MacroUsageCheck.cpp +++ b/clang-tools-extra/clang-tidy/cppcoreguidelines/MacroUsageCheck.cpp @@ -82,6 +82,15 @@ void MacroUsageCheck::registerPPCallbacks(const SourceManager &SM, void MacroUsageCheck::warnMacro(const MacroDirective *MD, StringRef MacroName) { const MacroInfo *Info = MD->getMacroInfo(); StringRef Message; + bool MacroBodyExpressionLike; + if (Info->getNumTokens() > 0) { + const Token &Tok = Info->getReplacementToken(0); + // Now notice that keywords like `__attribute` cannot be a leading + // token in an expression. + MacroBodyExpressionLike = !Tok.is(tok::kw___attribute); + } else { + MacroBodyExpressionLike = true; + } if (llvm::all_of(Info->tokens(), std::mem_fn(&Token::isLiteral))) Message = "macro '%0' used to declare a constant; consider using a " @@ -89,10 +98,10 @@ void MacroUsageCheck::warnMacro(const MacroDirective *MD, StringRef MacroName) { // 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. - else if (Info->isVariadic()) + else if (Info->isVariadic() && MacroBodyExpressionLike) Message = "variadic macro '%0' used; consider using a 'constexpr' " "variadic template function"; - else if (Info->isFunctionLike()) + else if (Info->isFunctionLike() && MacroBodyExpressionLike) Message = "function-like macro '%0' used; consider a 'constexpr' template " "function"; diff --git a/clang-tools-extra/docs/ReleaseNotes.rst b/clang-tools-extra/docs/ReleaseNotes.rst index 061fb114276dc..563e327de1999 100644 --- a/clang-tools-extra/docs/ReleaseNotes.rst +++ b/clang-tools-extra/docs/ReleaseNotes.rst @@ -325,6 +325,12 @@ Changes in existing checks ` check by fixing the insertion location for function pointers with multiple parameters. +- Improved :doc:`cppcoreguidelines-macro-usage + ` check by excluding macro + bodies that starts with ``__attribute__((..))`` keyword. + Such a macro body is unlikely a proper expression and so suggesting users + an impossible rewrite into a template function should be avoided. + - Improved :doc:`cppcoreguidelines-prefer-member-initializer ` check to avoid false positives on inherited members in class templates. diff --git a/clang-tools-extra/test/clang-tidy/checkers/cppcoreguidelines/macro-usage.cpp b/clang-tools-extra/test/clang-tidy/checkers/cppcoreguidelines/macro-usage.cpp index 865ef9df1182e..f3eb8185878f2 100644 --- a/clang-tools-extra/test/clang-tidy/checkers/cppcoreguidelines/macro-usage.cpp +++ b/clang-tools-extra/test/clang-tidy/checkers/cppcoreguidelines/macro-usage.cpp @@ -47,4 +47,6 @@ #define DLLEXPORTS __declspec(dllimport) #endif +#define ATTRIBUTE_MACRO(...) __attribute__(__VA_ARGS__) + #endif