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
