https://github.com/maith-s updated https://github.com/llvm/llvm-project/pull/216237
>From 4a0232aac80daf7ae382799af487b042e77454a0 Mon Sep 17 00:00:00 2001 From: Maithili Shingne <[email protected]> Date: Thu, 13 Aug 2026 22:45:23 -0400 Subject: [PATCH 1/2] [clang-tidy] Fix bugprone-macro-parentheses false positive for _Generic Fixes #51678 The check flagged a macro argument used as the type-name in a C11 _Generic selection, e.g.: #define assert_type(expr, type) _Generic((expr), type : (expr)) Parenthesizing `type` there is a syntax error. The check now tracks paren/brace/square nesting via a stack, and recognizes when a macro argument sits directly inside a _Generic's argument list and is followed by ':' -- skipping it the same way other special-cased positions (namespaces, template args, goto labels) already are. Added tests covering the reported case and nested _Generic. --- .../bugprone/MacroParenthesesCheck.cpp | 25 +++++++++++++++++-- .../checkers/bugprone/macro-parentheses.cpp | 7 ++++++ 2 files changed, 30 insertions(+), 2 deletions(-) diff --git a/clang-tools-extra/clang-tidy/bugprone/MacroParenthesesCheck.cpp b/clang-tools-extra/clang-tidy/bugprone/MacroParenthesesCheck.cpp index a51bce1484a42..a482337272c1d 100644 --- a/clang-tools-extra/clang-tidy/bugprone/MacroParenthesesCheck.cpp +++ b/clang-tools-extra/clang-tidy/bugprone/MacroParenthesesCheck.cpp @@ -179,7 +179,25 @@ void MacroParenthesesPPCallbacks::argument(const Token &MacroNameTok, // Skip the goto argument with an arbitrary number of subsequent stars. bool FoundGoto = false; + // Tracks, for each open paren/brace/square, whether it's the argument + // list of a C11 _Generic selection -- e.g. _Generic(expr, type: value). + // An argument in the type-name position must not be parenthesized. + llvm::SmallVector<char, 8> GenericAssocStack; + bool PendingGeneric = false; + for (auto TI = MI->tokens_begin(), TE = MI->tokens_end(); TI != TE; ++TI) { + const Token &Tok = *TI; + + if (Tok.isOneOf(tok::l_paren, tok::l_brace, tok::l_square)) { + GenericAssocStack.push_back(PendingGeneric && Tok.is(tok::l_paren)); + PendingGeneric = false; + } else if (Tok.isOneOf(tok::r_paren, tok::r_brace, tok::r_square)) { + if (!GenericAssocStack.empty()) + GenericAssocStack.pop_back(); + } else if (Tok.is(tok::kw__Generic)) { + PendingGeneric = true; + } + // First token. if (TI == MI->tokens_begin()) continue; @@ -191,8 +209,6 @@ void MacroParenthesesPPCallbacks::argument(const Token &MacroNameTok, const Token &Prev = *std::prev(TI); const Token &Next = *std::next(TI); - const Token &Tok = *TI; - // There should not be extra parentheses in possible variable declaration. if (VarDecl) { if (Tok.isOneOf(tok::equal, tok::semi, tok::l_square, tok::l_paren)) @@ -233,6 +249,11 @@ void MacroParenthesesPPCallbacks::argument(const Token &MacroNameTok, if (Next.is(tok::coloncolon)) continue; + // Argument is the type-name of a C11 _Generic association. + if (Next.is(tok::colon) && !GenericAssocStack.empty() && + GenericAssocStack.back()) + continue; + // String concatenation. if (isStringLiteral(Prev.getKind()) || isStringLiteral(Next.getKind())) continue; 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 a3ce47d3d0885..4db2b0798654f 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 @@ -50,6 +50,13 @@ #define GOOD33(x) if (!a__##x) a_##x = &f(#x) #define GOOD34(x, y) if (x) goto y; #define GOOD35(x, y) if (x) goto *(y); +#if __STDC_VERSION__ >= 201112L +#define GOOD36(expr, type) _Generic((expr), type : (expr)) +#endif +#if __STDC_VERSION__ >= 201112L +#define GOOD37(expr, type, inner_expr, inner_type) \ + _Generic((expr), type : _Generic((inner_expr), inner_type : (inner_expr))) +#endif // These are allowed for now.. #define MAYBE1 *12.34 >From c1f3e03aa95a5965f321b9e0ed6f65d83a369553 Mon Sep 17 00:00:00 2001 From: Maithili Shingne <[email protected]> Date: Sun, 23 Aug 2026 22:49:25 -0400 Subject: [PATCH 2/2] Adding fix to releasenotes.md --- clang-tools-extra/docs/ReleaseNotes.md | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/clang-tools-extra/docs/ReleaseNotes.md b/clang-tools-extra/docs/ReleaseNotes.md index 022fff815aa81..72394f5f64d35 100644 --- a/clang-tools-extra/docs/ReleaseNotes.md +++ b/clang-tools-extra/docs/ReleaseNotes.md @@ -180,6 +180,11 @@ infrastructure are described first, followed by tool-specific sections. <clang-tidy/checks/readability/use-std-min-max>` check by fixing spurious trailing semicolons and lost comments when the `if` body has no braces. +- Improved {doc}`bugprone-macro-parentheses + <clang-tidy/checks/bugprone/macro-parentheses>` check by fixing a false + positive for macro arguments used as the type-name in a C11 `_Generic` + selection, where parenthesizing them would be invalid. + #### Removed checks - Removed the deprecated `zircon-temporary-objects` check. Users should migrate to _______________________________________________ cfe-commits mailing list [email protected] https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
