https://github.com/AayushMainali-Github created 
https://github.com/llvm/llvm-project/pull/219634

The `readability-trailing-comma` check looks at the token immediately before an 
enum's closing brace to decide whether a trailing comma is present. When the 
last enumerators are wrapped in `#ifdef` / `#else` / `#endif`, that token is 
the directive identifier `endif`, so the check reports a missing comma and 
`-fix` inserts `,` after `#endif`. That is outside the enumerator list and 
corrupts the source even when every enumerator already has a trailing comma.

Skip the diagnostic when the token before `}` is a preprocessor directive (`#` 
or a token preceded by `#`). An enumerator whose name happens to be `endif` is 
still diagnosed, because it is not preceded by `#`.

Fixes #218957


>From 7dd38d46d9e069712450d9203e2beab0dd486ce8 Mon Sep 17 00:00:00 2001
From: "Work seamlessly with GitHub from the command line.USAGE  gh command
 subcommand [flags]CORE COMMANDS  auth:        Authenticate gh and git with
 GitHub  browse:      Open the repository in the browser  codespace:   Connect
 to and manage codespaces  gist:        Manage gists  issue:       Manage
 issues  org:         Manage organizations  pr:          Manage pull requests 
 project:     Work with GitHub Projects.  release:     Manage releases  repo: 
       Manage repositoriesGITHUB ACTIONS COMMANDS  cache:       Manage Github
 Actions caches  run:         View details about workflow runs  workflow:   
 View details about GitHub Actions workflowsALIAS COMMANDS  co:          Alias
 for \"pr checkout\"ADDITIONAL COMMANDS  alias:       Create command shortcuts
  api:         Make an authenticated GitHub API request  completion:  Generate
 shell completion scripts  config:      Manage configuration for gh 
 extension:   Manage gh extensions  gpg-key:     Manage GPG keys  label:      
 Manage labels  ruleset:     View info about repo rulesets  search:     
 Search for repositories, issues, and pull requests  secret:      Manage
 GitHub secrets  ssh-key:     Manage SSH keys  status:      Print information
 about relevant issues, pull requests, and notifications across repositories 
 variable:    Manage GitHub Actions variablesHELP TOPICS  actions:     Learn
 about working with GitHub Actions  environment: Environment variables that
 can be used with gh  exit-codes:  Exit codes used by gh  formatting: 
 Formatting options for JSON data exported from gh  mintty:      Information
 about using gh with MinTTY  reference:   A comprehensive reference of all gh
 commandsFLAGS  --help      Show help for command  --version   Show gh
 versionEXAMPLES  $ gh issue create  $ gh repo clone cli/cli  $ gh pr checkout
 321LEARN MORE  Use `gh command subcommand --help` for more information about
 a command.  Read the manual at https://cli.github.com/manual";
 <Work seamlessly with GitHub from the command line.USAGE  gh command 
subcommand [flags]CORE COMMANDS  auth:        Authenticate gh and git with 
GitHub  browse:      Open the repository in the browser  codespace:   Connect 
to and manage codespaces  gist:        Manage gists  issue:       Manage issues 
 org:         Manage organizations  pr:          Manage pull requests  project: 
    Work with GitHub Projects.  release:     Manage releases  repo:        
Manage repositoriesGITHUB ACTIONS COMMANDS  cache:       Manage Github Actions 
caches  run:         View details about workflow runs  workflow:    View 
details about GitHub Actions workflowsALIAS COMMANDS  co:          Alias for 
"pr checkout"ADDITIONAL COMMANDS  alias:       Create command shortcuts  api:   
      Make an authenticated GitHub API request  completion:  Generate shell 
completion scripts  config:      Manage configuration for gh  extension:   
Manage gh extensions  gpg-key:     Manage GPG keys  label:       Manage labels  
ruleset:     View info about repo rulesets  search:      Search for 
repositories, issues, and pull requests  secret:      Manage GitHub secrets  
ssh-key:     Manage SSH keys  status:      Print information about relevant 
issues, pull requests, and notifications across repositories  variable:    
Manage GitHub Actions variablesHELP TOPICS  actions:     Learn about working 
with GitHub Actions  environment: Environment variables that can be used with 
gh  exit-codes:  Exit codes used by gh  formatting:  Formatting options for 
JSON data exported from gh  mintty:      Information about using gh with MinTTY 
 reference:   A comprehensive reference of all gh commandsFLAGS  --help      
Show help for command  --version   Show gh versionEXAMPLES  $ gh issue create  
$ gh repo clone cli/cli  $ gh pr checkout 321LEARN MORE  Use `gh command 
subcommand --help` for more information about a command.  Read the manual at 
https://cli.github.com/[email protected]>
Date: Sat, 29 Aug 2026 05:56:28 +0000
Subject: [PATCH] [clang-tidy] Fix readability-trailing-comma false positive on
 #endif

---
 .../readability/TrailingCommaCheck.cpp        | 28 +++++++++++++--
 .../readability/trailing-comma-cxx11.cpp      | 14 ++++++++
 .../checkers/readability/trailing-comma.cpp   | 34 +++++++++++++++++++
 3 files changed, 73 insertions(+), 3 deletions(-)

diff --git a/clang-tools-extra/clang-tidy/readability/TrailingCommaCheck.cpp 
b/clang-tools-extra/clang-tidy/readability/TrailingCommaCheck.cpp
index cb1a33ba09233..60fa53ddf6556 100644
--- a/clang-tools-extra/clang-tidy/readability/TrailingCommaCheck.cpp
+++ b/clang-tools-extra/clang-tidy/readability/TrailingCommaCheck.cpp
@@ -56,6 +56,19 @@ AST_MATCHER(EnumDecl, isEmptyEnum) { return 
Node.enumerators().empty(); }
 
 AST_MATCHER(InitListExpr, isEmptyInitList) { return Node.getNumInits() == 0; }
 
+// True when Tok is a preprocessor directive (the '#' or the directive
+// identifier such as 'endif'). Those tokens can sit between the last
+// enumerator and '}', and must not be treated as a missing trailing comma.
+static bool isPreprocessorDirectiveToken(const Token &Tok,
+                                         const SourceManager &SM,
+                                         const LangOptions &LangOpts) {
+  if (Tok.is(tok::hash))
+    return true;
+  const std::optional<Token> Prev = Lexer::findPreviousToken(
+      Tok.getLocation(), SM, LangOpts, /*IncludeComments=*/false);
+  return Prev && Prev->is(tok::hash);
+}
+
 } // namespace
 
 TrailingCommaCheck::TrailingCommaCheck(StringRef Name,
@@ -110,12 +123,21 @@ void TrailingCommaCheck::checkEnumDecl(const EnumDecl 
*Enum,
   if (Policy == CommaPolicyKind::Ignore)
     return;
 
-  const std::optional<Token> LastTok =
-      Lexer::findPreviousToken(Enum->getBraceRange().getEnd(),
-                               *Result.SourceManager, getLangOpts(), false);
+  const std::optional<Token> LastTok = Lexer::findPreviousToken(
+      Enum->getBraceRange().getEnd(), *Result.SourceManager, getLangOpts(),
+      /*IncludeComments=*/false);
   if (!LastTok)
     return;
 
+  // `#endif` (and similar directives) can appear immediately before the
+  // closing brace when enumerators are guarded by `#ifdef`. Walking back from
+  // `}` would otherwise treat that directive as the last enumerator and insert
+  // a comma after it, even when every active enumerator already has a trailing
+  // comma.
+  if (isPreprocessorDirectiveToken(*LastTok, *Result.SourceManager,
+                                   getLangOpts()))
+    return;
+
   emitDiag(LastTok->getLocation(), LastTok, DiagKind::Enum, Result, Policy);
 }
 
diff --git 
a/clang-tools-extra/test/clang-tidy/checkers/readability/trailing-comma-cxx11.cpp
 
b/clang-tools-extra/test/clang-tidy/checkers/readability/trailing-comma-cxx11.cpp
index 9f37db2c837c3..80c88fcc2396c 100644
--- 
a/clang-tools-extra/test/clang-tidy/checkers/readability/trailing-comma-cxx11.cpp
+++ 
b/clang-tools-extra/test/clang-tidy/checkers/readability/trailing-comma-cxx11.cpp
@@ -54,3 +54,17 @@ struct PackSingle {
 
 PackSingle<int> p1;
 PackSingle<int, double, char> p3;
+
+// Preprocessor-guarded enumerators already have trailing commas; do not insert
+// a comma after '#endif'.
+enum class color_t : unsigned {
+  RED = 0,
+  GREEN = 1,
+  BLUE = 2,
+  CYAN = 3,
+#ifdef USE_MAGENTA
+  LAST = CYAN,
+#else
+  LAST = BLUE,
+#endif
+};
diff --git 
a/clang-tools-extra/test/clang-tidy/checkers/readability/trailing-comma.cpp 
b/clang-tools-extra/test/clang-tidy/checkers/readability/trailing-comma.cpp
index 76fb4bbf0c37d..daef89b770716 100644
--- a/clang-tools-extra/test/clang-tidy/checkers/readability/trailing-comma.cpp
+++ b/clang-tools-extra/test/clang-tidy/checkers/readability/trailing-comma.cpp
@@ -144,6 +144,40 @@ void nestedMultiLine() {
   // CHECK-FIXES-NEXT:   };
 }
 
+// Preprocessor directives immediately before '}' must not be treated as the
+// last enumerator. Both branches already have trailing commas; a false
+// positive would insert a comma after '#endif'.
+enum color_t {
+  COLOR_RED = 0,
+  COLOR_GREEN = 1,
+  COLOR_BLUE = 2,
+  COLOR_CYAN = 3,
+#ifdef USE_MAGENTA
+  COLOR_LAST = COLOR_CYAN,
+#else
+  COLOR_LAST = COLOR_BLUE,
+#endif
+};
+
+enum GuardedEnumerator {
+  GE_A,
+  GE_B,
+#ifdef USE_EXTRA
+  GE_C,
+#endif
+};
+
+// An enumerator named 'endif' is still diagnosed; only '#endif' is ignored.
+enum EndsWithEndifName {
+  foo,
+  endif
+};
+// CHECK-MESSAGES: :[[@LINE-2]]:8: warning: enum should have a trailing comma
+// CHECK-FIXES: enum EndsWithEndifName {
+// CHECK-FIXES-NEXT:   foo,
+// CHECK-FIXES-NEXT:   endif,
+// CHECK-FIXES-NEXT: };
+
 // Macros are ignored
 #define ENUM(n, a, b) enum n { a, b }
 #define INIT {1, 2}

_______________________________________________
cfe-commits mailing list
[email protected]
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits

Reply via email to