[clang] [clang-format] Honor later negated .clang-format-ignore patterns (PR #195432)

via cfe-commits cfe-commits at lists.llvm.org
Sun May 3 05:05:50 PDT 2026


https://github.com/Dudenwatschn updated https://github.com/llvm/llvm-project/pull/195432

>From ab92367cb0f545ea1fe797973966adc9650509cf Mon Sep 17 00:00:00 2001
From: Alexander Imp <alexander.imp at gmx.at>
Date: Thu, 30 Apr 2026 21:34:42 +0200
Subject: [PATCH] [clang-format] Honor later negated .clang-format-ignore
 patterns

---
 clang/test/Format/clang-format-ignore.cpp | 38 +++++++++++++++++++++++
 clang/test/Format/list-ignored.cpp        | 11 +++++++
 clang/tools/clang-format/ClangFormat.cpp  |  7 +++--
 3 files changed, 53 insertions(+), 3 deletions(-)

diff --git a/clang/test/Format/clang-format-ignore.cpp b/clang/test/Format/clang-format-ignore.cpp
index 67d68aebde5d0..6689137b48074 100644
--- a/clang/test/Format/clang-format-ignore.cpp
+++ b/clang/test/Format/clang-format-ignore.cpp
@@ -56,5 +56,43 @@
 // RUN:   | FileCheck %s -check-prefix=CHECK7 -match-full-lines
 // CHECK7: int i;
 
+// RUN: echo "foo.h" > .clang-format-ignore
+// RUN: echo "!foo.c" >> .clang-format-ignore
+// RUN: echo "int i ;" > foo.c
+// RUN: echo "int i ;" > foo.h
+// RUN: clang-format -verbose foo.c 2>&1 \
+// RUN:   | FileCheck %s -check-prefix=CHECK8 -match-full-lines
+// CHECK8: Formatting [1/1] foo.c
+// RUN: clang-format -verbose foo.h 2>&1 \
+// RUN:   | FileCheck %s -check-prefix=CHECK9 -allow-empty
+// CHECK9-NOT: int
+
+// RUN: mkdir -p %t.dir/ignore.dir/format.dir
+// RUN: echo "ignore.dir/*" > .clang-format-ignore
+// RUN: echo "!ignore.dir/format.dir/*" >> .clang-format-ignore
+// RUN: echo "int i ;" > ignore.dir/foo.c
+// RUN: echo "int i ;" > ignore.dir/format.dir/bar.c
+// RUN: clang-format -verbose ignore.dir/**/*.c 2>&1 \
+// RUN:   | FileCheck %s -check-prefix=CHECK10 -match-full-lines
+// CHECK10: {{Formatting \[1/1] .*ignore\.dir[/\\]format\.dir[/\\]bar\.c}}
+
+// RUN: echo "foo.*" > .clang-format-ignore
+// RUN: clang-format -verbose foo.c 2>&1 \
+// RUN:   | FileCheck %s -check-prefix=CHECK11 -allow-empty
+// CHECK11-NOT: int
+// RUN: echo "!foo.c" >> .clang-format-ignore
+// RUN: clang-format -verbose foo.c 2>&1 \
+// RUN:   | FileCheck %s -check-prefix=CHECK12 -match-full-lines
+// CHECK12: Formatting [1/1] foo.c
+
+// RUN: echo "!foo.*" > .clang-format-ignore
+// RUN: clang-format -verbose foo.c 2>&1 \
+// RUN:   | FileCheck %s -check-prefix=CHECK13 -match-full-lines
+// CHECK13: Formatting [1/1] foo.c
+// RUN: echo "foo.c" >> .clang-format-ignore
+// RUN: clang-format -verbose foo.c 2>&1 \
+// RUN:   | FileCheck %s -check-prefix=CHECK14 -allow-empty
+// CHECK14-NOT: int
+
 // RUN: cd ..
 // RUN: rm -r %t.dir
diff --git a/clang/test/Format/list-ignored.cpp b/clang/test/Format/list-ignored.cpp
index 6e65a68a6f996..d5cc449c837f6 100644
--- a/clang/test/Format/list-ignored.cpp
+++ b/clang/test/Format/list-ignored.cpp
@@ -56,5 +56,16 @@
 // CHECK7-NOT: foo.c
 // CHECK7: foo.js
 
+// RUN: echo "!foo.c" > .clang-format-ignore
+// RUN: clang-format -list-ignored foo.c foo.h 2>&1 \
+// RUN:   | FileCheck %s -allow-empty -check-prefix=CHECK8
+// CHECK8-NOT: foo.c
+
+// RUN: echo "*" > .clang-format-ignore
+// RUN: echo "!foo.*" >> .clang-format-ignore
+// RUN: clang-format -list-ignored foo.c 2>&1 \
+// RUN:   | FileCheck %s -allow-empty -check-prefix=CHECK9
+// CHECK9-NOT: foo.c
+
 // RUN: cd ..
 // RUN: rm -r %t.dir
diff --git a/clang/tools/clang-format/ClangFormat.cpp b/clang/tools/clang-format/ClangFormat.cpp
index 37d0eb83414f4..1a38ef195cbac 100644
--- a/clang/tools/clang-format/ClangFormat.cpp
+++ b/clang/tools/clang-format/ClangFormat.cpp
@@ -636,6 +636,7 @@ static bool isIgnored(StringRef FilePath) {
   if (IgnoreDir.empty())
     return false;
 
+  bool IsIgnored = false;
   const auto Pathname{convert_to_slash(AbsPath)};
   for (const auto &Pat : Patterns) {
     const bool IsNegated = Pat[0] == '!';
@@ -657,11 +658,11 @@ static bool isIgnored(StringRef FilePath) {
       Pattern = Path;
     }
 
-    if (clang::format::matchFilePath(Pattern, Pathname) == !IsNegated)
-      return true;
+    if (clang::format::matchFilePath(Pattern, Pathname))
+      IsIgnored = !IsNegated;
   }
 
-  return false;
+  return IsIgnored;
 }
 
 int main(int argc, const char **argv) {



More information about the cfe-commits mailing list