https://github.com/YexuanXiao updated 
https://github.com/llvm/llvm-project/pull/174684

>From 0a5cc7154cc1d2c4c02e8df6940e1fbfcb1ce865 Mon Sep 17 00:00:00 2001
From: Yexuan Xiao <[email protected]>
Date: Wed, 7 Jan 2026 10:06:51 +0800
Subject: [PATCH 1/3] [Sema] Make matchSizeTPtrdiffT correctly handle _Bool

---
 clang/lib/AST/FormatString.cpp   |  3 +++
 clang/test/Sema/format-strings.c | 32 ++++++++++++++++++++++++++++++++
 2 files changed, 35 insertions(+)

diff --git a/clang/lib/AST/FormatString.cpp b/clang/lib/AST/FormatString.cpp
index d4cb89b43ae87..057a6fb4399d1 100644
--- a/clang/lib/AST/FormatString.cpp
+++ b/clang/lib/AST/FormatString.cpp
@@ -371,6 +371,9 @@ static clang::analyze_format_string::ArgType::MatchKind
 matchesSizeTPtrdiffT(ASTContext &C, QualType T, QualType E) {
   using MatchKind = clang::analyze_format_string::ArgType::MatchKind;
 
+  if (T->isBooleanType())
+    return MatchKind::NoMatch;
+
   if (!T->isIntegerType())
     return MatchKind::NoMatch;
 
diff --git a/clang/test/Sema/format-strings.c b/clang/test/Sema/format-strings.c
index 5280549adc3d7..a26c7447e9cea 100644
--- a/clang/test/Sema/format-strings.c
+++ b/clang/test/Sema/format-strings.c
@@ -983,3 +983,35 @@ void test_promotion(void) {
   // pointers
   printf("%s", i); // expected-warning{{format specifies type 'char *' but the 
argument has type 'int'}}
 }
+
+void test_bool(_Bool b, _Bool* bp)
+{
+  printf("%zu", b); // expected-warning{{format specifies type 'size_t' (aka 
'unsigned long') but the argument has type '_Bool'}}
+  printf("%td", b); // expected-warning{{format specifies type 'ptrdiff_t' 
(aka 'long') but the argument has type '_Bool'}}
+  printf("%jd", b); // expected-warning{{format specifies type 'intmax_t' (aka 
'long') but the argument has type '_Bool'}}
+  printf("%lld", b); // expected-warning{{format specifies type 'long long' 
but the argument has type '_Bool'}}
+  printf("%ld", b); // expected-warning{{format specifies type 'long' but the 
argument has type '_Bool'}}
+  printf("%d", b); // promoted from _Bool to int
+  printf("%hhd", b); // promoted from _Bool to int
+  printf("%hd", b); // promoted from _Bool to int
+#if !defined(__Fuchsia__) && !defined(__ANDROID__) //'%n' specifier not 
supported on this platform
+  // The n conversion specifier only supports signed types
+  printf("%zn", bp); // expected-warning{{format specifies type 'signed size_t 
*' (aka 'long *') but the argument has type '_Bool *'}}
+  printf("%jn", bp); // expected-warning{{format specifies type 'intmax_t *' 
(aka 'long *') but the argument has type '_Bool *'}}
+  printf("%lln", bp); // expected-warning{{format specifies type 'long long *' 
but the argument has type '_Bool *'}}
+  printf("%ln", bp); // expected-warning{{format specifies type 'long *' but 
the argument has type '_Bool *'}}
+  printf("%n", bp); // expected-warning{{format specifies type 'int *' but the 
argument has type '_Bool *'}}
+  printf("%hhn", bp); // expected-warning{{format specifies type 'signed char 
*' but the argument has type '_Bool *'}}
+  printf("%hn", bp); // belong to -Wformat-type-confusion
+#endif
+  printf("%c", b); // expected-warning{{using '%c' format specifier, but 
argument has boolean value}}
+  printf("%s", b); // expected-warning{{format specifies type 'char *' but the 
argument has type '_Bool'}}
+  printf("%d", b); // promoted from _Bool to int
+  printf("%o", b); // promoted from _Bool to int
+  printf("%x", b); // promoted from _Bool to int
+  printf("%u", b); // promoted from _Bool to int
+  printf("%f", b); // expected-warning{{format specifies type 'double' but the 
argument has type '_Bool'}}
+  printf("%e", b); // expected-warning{{format specifies type 'double' but the 
argument has type '_Bool'}}
+  printf("%a", b); // expected-warning{{format specifies type 'double' but the 
argument has type '_Bool'}}
+  printf("%g", b); // expected-warning{{format specifies type 'double' but the 
argument has type '_Bool'}}
+}

>From 1bc32ccfa1b510ce74de1d4881fe9040ecadb5b4 Mon Sep 17 00:00:00 2001
From: Yexuan Xiao <[email protected]>
Date: Wed, 7 Jan 2026 11:16:39 +0800
Subject: [PATCH 2/3] Use expected-warning-re to avoid test failures on Windows

---
 clang/test/Sema/format-strings.c | 10 +++++-----
 1 file changed, 5 insertions(+), 5 deletions(-)

diff --git a/clang/test/Sema/format-strings.c b/clang/test/Sema/format-strings.c
index a26c7447e9cea..cdac83fc0bb91 100644
--- a/clang/test/Sema/format-strings.c
+++ b/clang/test/Sema/format-strings.c
@@ -986,9 +986,9 @@ void test_promotion(void) {
 
 void test_bool(_Bool b, _Bool* bp)
 {
-  printf("%zu", b); // expected-warning{{format specifies type 'size_t' (aka 
'unsigned long') but the argument has type '_Bool'}}
-  printf("%td", b); // expected-warning{{format specifies type 'ptrdiff_t' 
(aka 'long') but the argument has type '_Bool'}}
-  printf("%jd", b); // expected-warning{{format specifies type 'intmax_t' (aka 
'long') but the argument has type '_Bool'}}
+  printf("%zu", b); // expected-warning-re{{format specifies type 'size_t' 
(aka '{{.+}}') but the argument has type '_Bool'}}
+  printf("%td", b); // expected-warning-re{{format specifies type 'ptrdiff_t' 
(aka '{{.+}}') but the argument has type '_Bool'}}
+  printf("%jd", b); // expected-warning-re{{format specifies type 'intmax_t' 
(aka '{{.+}}') but the argument has type '_Bool'}}
   printf("%lld", b); // expected-warning{{format specifies type 'long long' 
but the argument has type '_Bool'}}
   printf("%ld", b); // expected-warning{{format specifies type 'long' but the 
argument has type '_Bool'}}
   printf("%d", b); // promoted from _Bool to int
@@ -996,8 +996,8 @@ void test_bool(_Bool b, _Bool* bp)
   printf("%hd", b); // promoted from _Bool to int
 #if !defined(__Fuchsia__) && !defined(__ANDROID__) //'%n' specifier not 
supported on this platform
   // The n conversion specifier only supports signed types
-  printf("%zn", bp); // expected-warning{{format specifies type 'signed size_t 
*' (aka 'long *') but the argument has type '_Bool *'}}
-  printf("%jn", bp); // expected-warning{{format specifies type 'intmax_t *' 
(aka 'long *') but the argument has type '_Bool *'}}
+  printf("%zn", bp); // expected-warning-re{{format specifies type 'signed 
size_t *' (aka '{{.+}}') but the argument has type '_Bool *'}}
+  printf("%jn", bp); // expected-warning-re{{format specifies type 'intmax_t 
*' (aka '{{.+}}') but the argument has type '_Bool *'}}
   printf("%lln", bp); // expected-warning{{format specifies type 'long long *' 
but the argument has type '_Bool *'}}
   printf("%ln", bp); // expected-warning{{format specifies type 'long *' but 
the argument has type '_Bool *'}}
   printf("%n", bp); // expected-warning{{format specifies type 'int *' but the 
argument has type '_Bool *'}}

>From 6923e18f0ba6a8b593a5587748647c3f34873646 Mon Sep 17 00:00:00 2001
From: Yexuan Xiao <[email protected]>
Date: Fri, 9 Jan 2026 18:48:40 +0800
Subject: [PATCH 3/3] Combine if statements

---
 clang/lib/AST/FormatString.cpp | 5 +----
 1 file changed, 1 insertion(+), 4 deletions(-)

diff --git a/clang/lib/AST/FormatString.cpp b/clang/lib/AST/FormatString.cpp
index 057a6fb4399d1..36c5f57671631 100644
--- a/clang/lib/AST/FormatString.cpp
+++ b/clang/lib/AST/FormatString.cpp
@@ -371,10 +371,7 @@ static clang::analyze_format_string::ArgType::MatchKind
 matchesSizeTPtrdiffT(ASTContext &C, QualType T, QualType E) {
   using MatchKind = clang::analyze_format_string::ArgType::MatchKind;
 
-  if (T->isBooleanType())
-    return MatchKind::NoMatch;
-
-  if (!T->isIntegerType())
+  if (!T->isIntegerType() || T->isBooleanType())
     return MatchKind::NoMatch;
 
   if (C.hasSameType(T, E))

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

Reply via email to