https://github.com/zeyi2 updated https://github.com/llvm/llvm-project/pull/174329
>From d3154561b0379546e9996a10c4a5e5df6eb85c72 Mon Sep 17 00:00:00 2001 From: mtx <[email protected]> Date: Sun, 4 Jan 2026 20:30:49 +0800 Subject: [PATCH 1/3] [clang-tidy] fix false positives for bugprone-macro-parentheses in C++ templates --- .../bugprone/MacroParenthesesCheck.cpp | 17 +++++++++++++---- clang-tools-extra/docs/ReleaseNotes.rst | 14 +++++++++----- .../checkers/bugprone/macro-parentheses.cpp | 17 +++++++++++++++++ 3 files changed, 39 insertions(+), 9 deletions(-) diff --git a/clang-tools-extra/clang-tidy/bugprone/MacroParenthesesCheck.cpp b/clang-tools-extra/clang-tidy/bugprone/MacroParenthesesCheck.cpp index 6467fb58de925..1e4dc6bb3b024 100644 --- a/clang-tools-extra/clang-tidy/bugprone/MacroParenthesesCheck.cpp +++ b/clang-tools-extra/clang-tidy/bugprone/MacroParenthesesCheck.cpp @@ -52,7 +52,8 @@ static bool isSurroundedRight(const Token &T) { /// Is given TokenKind a keyword? static bool isKeyword(const Token &T) { // FIXME: better matching of keywords to avoid false positives. - return T.isOneOf(tok::kw_if, tok::kw_case, tok::kw_const, tok::kw_struct); + return T.isOneOf(tok::kw_if, tok::kw_case, tok::kw_const, tok::kw_volatile, + tok::kw_struct); } /// Warning is written when one of these operators are not within parentheses. @@ -235,9 +236,17 @@ void MacroParenthesesPPCallbacks::argument(const Token &MacroNameTok, continue; // C++ template parameters. - if (PP->getLangOpts().CPlusPlus && Prev.isOneOf(tok::comma, tok::less) && - Next.isOneOf(tok::comma, tok::greater)) - continue; + if (PP->getLangOpts().CPlusPlus && Prev.isOneOf(tok::comma, tok::less)) { + const auto *NextIt = TI + 1; + while (NextIt != MI->tokens_end() && + NextIt->isOneOf(tok::star, tok::amp, tok::ampamp, tok::kw_const, + tok::kw_volatile)) + ++NextIt; + + if (NextIt != MI->tokens_end() && + NextIt->isOneOf(tok::comma, tok::greater)) + continue; + } // Namespaces. if (Prev.is(tok::kw_namespace)) diff --git a/clang-tools-extra/docs/ReleaseNotes.rst b/clang-tools-extra/docs/ReleaseNotes.rst index 7d878f7d28386..b1b30baf26285 100644 --- a/clang-tools-extra/docs/ReleaseNotes.rst +++ b/clang-tools-extra/docs/ReleaseNotes.rst @@ -111,10 +111,10 @@ Hover Code completion ^^^^^^^^^^^^^^^ -- Added a new ``MacroFilter`` configuration option to ``Completion`` to - allow fuzzy-matching with the ``FuzzyMatch`` option when suggesting - macros. ``ExactPrefix`` is the default, which retains previous - behavior of suggesting macros which match the prefix exactly. +- Added a new ``MacroFilter`` configuration option to ``Completion`` to + allow fuzzy-matching with the ``FuzzyMatch`` option when suggesting + macros. ``ExactPrefix`` is the default, which retains previous + behavior of suggesting macros which match the prefix exactly. Code actions ^^^^^^^^^^^^ @@ -205,7 +205,7 @@ Improvements to clang-tidy - Improved :program:`clang-tidy` by adding the `--removed-arg` option to remove arguments sent to the compiler when invoking Clang-Tidy. This option was also - added to :program:`run-clang-tidy.py` and :program:`clang-tidy-diff.py` and + added to :program:`run-clang-tidy.py` and :program:`clang-tidy-diff.py` and can be configured in the config file through the `RemovedArgs` option. - Deprecated the :program:`clang-tidy` ``zircon`` module. All checks have been @@ -392,6 +392,10 @@ Changes in existing checks <clang-tidy/checks/bugprone/invalid-enum-default-initialization>` with new `IgnoredEnums` option to ignore specified enums during analysis. +- Improved :doc:`bugprone-macro-parentheses + <clang-tidy/checks/bugprone/macro-parentheses>` check by fixing false + positives when using C++ template parameters. + - Improved :doc:`bugprone-narrowing-conversions <clang-tidy/checks/bugprone/narrowing-conversions>` check by fixing false positive from analysis of a conditional expression in C. diff --git a/clang-tools-extra/test/clang-tidy/checkers/bugprone/macro-parentheses.cpp b/clang-tools-extra/test/clang-tidy/checkers/bugprone/macro-parentheses.cpp index 6c2f42dd2dcd6..5897de03d8cec 100644 --- a/clang-tools-extra/test/clang-tidy/checkers/bugprone/macro-parentheses.cpp +++ b/clang-tools-extra/test/clang-tidy/checkers/bugprone/macro-parentheses.cpp @@ -54,3 +54,20 @@ // These are allowed for now.. #define MAYBE1 *12.34 #define MAYBE2 <<3 +#define MAYBE3 a < b * c + +#define CAST1(type, p) (reinterpret_cast<type*>(p)) +#define CAST2(type, p) (static_cast<type*>(p)) +#define CAST3(type, p) (const_cast<type*>(p)) +#define CAST4(type, p) (dynamic_cast<type*>(p)) +#define CAST5(type, p) (static_cast<type&>(p)) +#define CAST6(type, p) (static_cast<type&&>(p)) +#define CAST7(type, p) (static_cast<const type*>(p)) +#define CAST8(type, p) (static_cast<volatile type*>(p)) +#define CAST9(type, p) (static_cast<type const*>(p)) +#define CAST10(type, p) (reinterpret_cast<type * const &>(p)) + +#define TEMPLATE1(T) (std::vector<T*>) +#define TEMPLATE2(T) (std::vector<T&>) +#define TEMPLATE3(T) (std::vector<const T*>) +#define TEMPLATE4(T) (std::map<T*, T*>) >From 9503771fcb9375326ab8814dc272f1b788f0c019 Mon Sep 17 00:00:00 2001 From: mtx <[email protected]> Date: Mon, 5 Jan 2026 03:24:36 +0800 Subject: [PATCH 2/3] Address review feedback --- .../bugprone/MacroParenthesesCheck.cpp | 17 +++++++++-------- .../checkers/bugprone/macro-parentheses.cpp | 16 ++++++++++++++++ 2 files changed, 25 insertions(+), 8 deletions(-) diff --git a/clang-tools-extra/clang-tidy/bugprone/MacroParenthesesCheck.cpp b/clang-tools-extra/clang-tidy/bugprone/MacroParenthesesCheck.cpp index 1e4dc6bb3b024..b15369ec73913 100644 --- a/clang-tools-extra/clang-tidy/bugprone/MacroParenthesesCheck.cpp +++ b/clang-tools-extra/clang-tidy/bugprone/MacroParenthesesCheck.cpp @@ -130,19 +130,19 @@ void MacroParenthesesPPCallbacks::replacementList(const Token &MacroNameTok, // Heuristic for macros that are clearly not intended to be enclosed in // parentheses, macro starts with operator. For example: // #define X *10 - if (TI == MI->tokens_begin() && (TI + 1) != TE && + if (TI == MI->tokens_begin() && std::next(TI) != TE && !Tok.isOneOf(tok::plus, tok::minus)) return; // Don't warn about this macro if the last token is a star. For example: // #define X void * - if ((TE - 1)->is(tok::star)) + if (std::prev(TE)->is(tok::star)) return; Loc = Tok.getLocation(); } } if (Loc.isValid()) { - const Token &Last = *(MI->tokens_end() - 1); + const Token &Last = *std::prev(MI->tokens_end()); Check->diag(Loc, "macro replacement list should be enclosed in parentheses") << FixItHint::CreateInsertion(MI->tokens_begin()->getLocation(), "(") << FixItHint::CreateInsertion(Last.getLocation().getLocWithOffset( @@ -165,11 +165,11 @@ void MacroParenthesesPPCallbacks::argument(const Token &MacroNameTok, continue; // Last token. - if ((TI + 1) == MI->tokens_end()) + if (std::next(TI) == MI->tokens_end()) continue; - const Token &Prev = *(TI - 1); - const Token &Next = *(TI + 1); + const Token &Prev = *std::prev(TI); + const Token &Next = *std::next(TI); const Token &Tok = *TI; @@ -228,7 +228,8 @@ void MacroParenthesesPPCallbacks::argument(const Token &MacroNameTok, // Cast. if (Prev.is(tok::l_paren) && Next.is(tok::star) && - TI + 2 != MI->tokens_end() && (TI + 2)->is(tok::r_paren)) + std::next(TI, 2) != MI->tokens_end() && + std::next(TI, 2)->is(tok::r_paren)) continue; // Assignment/return, i.e. '=x;' or 'return x;'. @@ -237,7 +238,7 @@ void MacroParenthesesPPCallbacks::argument(const Token &MacroNameTok, // C++ template parameters. if (PP->getLangOpts().CPlusPlus && Prev.isOneOf(tok::comma, tok::less)) { - const auto *NextIt = TI + 1; + const auto *NextIt = std::next(TI); while (NextIt != MI->tokens_end() && NextIt->isOneOf(tok::star, tok::amp, tok::ampamp, tok::kw_const, tok::kw_volatile)) diff --git a/clang-tools-extra/test/clang-tidy/checkers/bugprone/macro-parentheses.cpp b/clang-tools-extra/test/clang-tidy/checkers/bugprone/macro-parentheses.cpp index 5897de03d8cec..6598e89c607f8 100644 --- a/clang-tools-extra/test/clang-tidy/checkers/bugprone/macro-parentheses.cpp +++ b/clang-tools-extra/test/clang-tidy/checkers/bugprone/macro-parentheses.cpp @@ -71,3 +71,19 @@ #define TEMPLATE2(T) (std::vector<T&>) #define TEMPLATE3(T) (std::vector<const T*>) #define TEMPLATE4(T) (std::map<T*, T*>) + +#define BAD_TEMPLATE1(T) (std::vector<T*2>) +// CHECK-MESSAGES: :[[@LINE-1]]:40: warning: macro argument should be enclosed in parentheses [bugprone-macro-parentheses] +#define BAD_TEMPLATE2(T) (std::map<T*2, int>) +// CHECK-MESSAGES: :[[@LINE-1]]:37: warning: macro argument should be enclosed in parentheses [bugprone-macro-parentheses] +#define BAD_TEMPLATE3(T) (std::map<int, T*2>) +// CHECK-MESSAGES: :[[@LINE-1]]:42: warning: macro argument should be enclosed in parentheses [bugprone-macro-parentheses] +#define BAD_TEMPLATE4(T) (std::vector<T+1>) +// CHECK-MESSAGES: :[[@LINE-1]]:40: warning: macro argument should be enclosed in parentheses [bugprone-macro-parentheses] +#define BAD_TEMPLATE5(T) (std::vector<T*T>) +// CHECK-MESSAGES: :[[@LINE-1]]:40: warning: macro argument should be enclosed in parentheses [bugprone-macro-parentheses] +// CHECK-MESSAGES: :[[@LINE-2]]:42: warning: macro argument should be enclosed in parentheses [bugprone-macro-parentheses] +#define BAD_CAST1(T) (reinterpret_cast<T*2>(0)) +// CHECK-MESSAGES: :[[@LINE-1]]:45: warning: macro argument should be enclosed in parentheses [bugprone-macro-parentheses] +#define BAD_CAST2(T) (reinterpret_cast<T+1>(0)) +// CHECK-MESSAGES: :[[@LINE-1]]:45: warning: macro argument should be enclosed in parentheses [bugprone-macro-parentheses] >From c794a05b7ecee1429c9ac42871d00e5e3e0ac951 Mon Sep 17 00:00:00 2001 From: mtx <[email protected]> Date: Tue, 6 Jan 2026 13:12:42 +0800 Subject: [PATCH 3/3] Address review feedback --- .../clang-tidy/bugprone/MacroParenthesesCheck.cpp | 10 +++++----- .../clang-tidy/checkers/bugprone/macro-parentheses.cpp | 2 ++ 2 files changed, 7 insertions(+), 5 deletions(-) diff --git a/clang-tools-extra/clang-tidy/bugprone/MacroParenthesesCheck.cpp b/clang-tools-extra/clang-tidy/bugprone/MacroParenthesesCheck.cpp index b15369ec73913..67cad02e5e2e5 100644 --- a/clang-tools-extra/clang-tidy/bugprone/MacroParenthesesCheck.cpp +++ b/clang-tools-extra/clang-tidy/bugprone/MacroParenthesesCheck.cpp @@ -238,11 +238,11 @@ void MacroParenthesesPPCallbacks::argument(const Token &MacroNameTok, // C++ template parameters. if (PP->getLangOpts().CPlusPlus && Prev.isOneOf(tok::comma, tok::less)) { - const auto *NextIt = std::next(TI); - while (NextIt != MI->tokens_end() && - NextIt->isOneOf(tok::star, tok::amp, tok::ampamp, tok::kw_const, - tok::kw_volatile)) - ++NextIt; + const auto *NextIt = + std::find_if_not(std::next(TI), MI->tokens_end(), [](const Token &T) { + return T.isOneOf(tok::star, tok::amp, tok::ampamp, tok::kw_const, + tok::kw_volatile); + }); if (NextIt != MI->tokens_end() && NextIt->isOneOf(tok::comma, tok::greater)) diff --git a/clang-tools-extra/test/clang-tidy/checkers/bugprone/macro-parentheses.cpp b/clang-tools-extra/test/clang-tidy/checkers/bugprone/macro-parentheses.cpp index 6598e89c607f8..1f943e8681e44 100644 --- a/clang-tools-extra/test/clang-tidy/checkers/bugprone/macro-parentheses.cpp +++ b/clang-tools-extra/test/clang-tidy/checkers/bugprone/macro-parentheses.cpp @@ -83,6 +83,8 @@ #define BAD_TEMPLATE5(T) (std::vector<T*T>) // CHECK-MESSAGES: :[[@LINE-1]]:40: warning: macro argument should be enclosed in parentheses [bugprone-macro-parentheses] // CHECK-MESSAGES: :[[@LINE-2]]:42: warning: macro argument should be enclosed in parentheses [bugprone-macro-parentheses] +#define BAD_TEMPLATE6(T) (std::vector<2*T>) +// CHECK-MESSAGES: :[[@LINE-1]]:47: warning: macro argument should be enclosed in parentheses [bugprone-macro-parentheses] #define BAD_CAST1(T) (reinterpret_cast<T*2>(0)) // CHECK-MESSAGES: :[[@LINE-1]]:45: warning: macro argument should be enclosed in parentheses [bugprone-macro-parentheses] #define BAD_CAST2(T) (reinterpret_cast<T+1>(0)) _______________________________________________ cfe-commits mailing list [email protected] https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
