https://github.com/drodriguez updated https://github.com/llvm/llvm-project/pull/126694
From 6dd960c6cf0550763b986f1909373a5b7e3a069d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Daniel=20Rodri=CC=81guez=20Troitin=CC=83o?= <[email protected]> Date: Mon, 10 Feb 2025 23:23:58 -0800 Subject: [PATCH] [Sema] -Wformat: warn about C23 %b %B when not in C23 language mode The validation of %b and %B was done without taking into account the current language mode, which means that %b and %B could have been used in format strings before they were supported. Change the code to check for the language mode being C23 or after, modify some tests that use %b and %B to specify C23 language mode and add a new test that checks the different behaviour depending on the current language mode. --- .../clang/Basic/DiagnosticSemaKinds.td | 3 ++ clang/lib/AST/PrintfFormatString.cpp | 4 ++- clang/lib/Sema/SemaChecking.cpp | 12 +++++++ clang/test/Sema/format-strings-c23-binary.c | 32 +++++++++++++++++++ clang/test/Sema/format-strings-fixit.c | 6 ++-- clang/test/Sema/format-strings.c | 8 ++--- 6 files changed, 57 insertions(+), 8 deletions(-) create mode 100644 clang/test/Sema/format-strings-c23-binary.c diff --git a/clang/include/clang/Basic/DiagnosticSemaKinds.td b/clang/include/clang/Basic/DiagnosticSemaKinds.td index ef0e29af0f224..d3e42c4e5596b 100644 --- a/clang/include/clang/Basic/DiagnosticSemaKinds.td +++ b/clang/include/clang/Basic/DiagnosticSemaKinds.td @@ -10631,6 +10631,9 @@ def warn_printf_data_arg_not_used : Warning< "data argument not used by format string">, InGroup<FormatExtraArgs>; def warn_format_invalid_conversion : Warning< "invalid conversion specifier '%0'">, InGroup<FormatInvalidSpecifier>; +def warn_format_conversion_specifier_requires_c23 : Warning< + "conversion specifier '%0' requires a C standard library compatible with " + "C23; data argument may not be used by format">, InGroup<Format>; def warn_printf_incomplete_specifier : Warning< "incomplete format specifier">, InGroup<Format>; def warn_missing_format_string : Warning< diff --git a/clang/lib/AST/PrintfFormatString.cpp b/clang/lib/AST/PrintfFormatString.cpp index 855550475721a..2e0adddb70369 100644 --- a/clang/lib/AST/PrintfFormatString.cpp +++ b/clang/lib/AST/PrintfFormatString.cpp @@ -333,7 +333,9 @@ static PrintfSpecifierResult ParsePrintfSpecifier(FormatStringHandler &H, else k = ConversionSpecifier::bArg; break; - case 'B': k = ConversionSpecifier::BArg; break; + case 'B': + k = ConversionSpecifier::BArg; + break; // POSIX specific. case 'C': k = ConversionSpecifier::CArg; break; case 'S': k = ConversionSpecifier::SArg; break; diff --git a/clang/lib/Sema/SemaChecking.cpp b/clang/lib/Sema/SemaChecking.cpp index a49e3883a35a5..a09bf79cfb8ed 100644 --- a/clang/lib/Sema/SemaChecking.cpp +++ b/clang/lib/Sema/SemaChecking.cpp @@ -8863,6 +8863,18 @@ bool CheckPrintfHandler::HandlePrintfSpecifier( if (!FS.hasStandardConversionSpecifier(S.getLangOpts())) HandleNonStandardConversionSpecifier(CS, startSpecifier, specifierLen); + // Warn about C23 %b/%B format specifiers when not in C23 mode. + if ((CS.getKind() == ConversionSpecifier::bArg || + CS.getKind() == ConversionSpecifier::BArg) && + !LangStandard::getLangStandardForKind(S.getLangOpts().LangStd).isC23()) { + EmitFormatDiagnostic( + S.PDiag(diag::warn_format_conversion_specifier_requires_c23) + << CS.toString(), + getLocationOfByte(CS.getStart()), /*IsStringLocation*/ true, + getSpecifierRange(startSpecifier, specifierLen)); + return true; + } + // The remaining checks depend on the data arguments. if (!HasFormatArguments()) return true; diff --git a/clang/test/Sema/format-strings-c23-binary.c b/clang/test/Sema/format-strings-c23-binary.c new file mode 100644 index 0000000000000..a023df82c9a05 --- /dev/null +++ b/clang/test/Sema/format-strings-c23-binary.c @@ -0,0 +1,32 @@ +// RUN: %clang_cc1 -std=c17 -fsyntax-only -verify=c17 -isystem %S/Inputs %s +// RUN: %clang_cc1 -std=c23 -fsyntax-only -verify=c23 -isystem %S/Inputs %s + +#include <stdarg.h> +#include <stddef.h> + +int printf(const char *restrict, ...); + +void test(unsigned char x) { + printf("%lb %lB", (long) 10, (long) 10); // c17-warning{{conversion specifier 'b' requires a C standard library compatible with C23; data argument may not be used by format}} + // c17-warning@-1{{conversion specifier 'B' requires a C standard library compatible with C23; data argument may not be used by format}} + + printf("%llb %llB", (long long) 10, (long long) 10); // c17-warning{{conversion specifier 'b' requires a C standard library compatible with C23; data argument may not be used by format}} + // c17-warning@-1{{conversion specifier 'B' requires a C standard library compatible with C23; data argument may not be used by format}} + + printf("%0b%0B", -1u, -1u); // c17-warning{{conversion specifier 'b' requires a C standard library compatible with C23; data argument may not be used by format}} + // c17-warning@-1{{conversion specifier 'B' requires a C standard library compatible with C23; data argument may not be used by format}} + + printf("%#b %#15.8B\n", 10, 10u); // c17-warning{{conversion specifier 'b' requires a C standard library compatible with C23; data argument may not be used by format}} + // c17-warning@-1{{conversion specifier 'B' requires a C standard library compatible with C23; data argument may not be used by format}} + + printf("%'b\n", 123456789); // c17-warning{{conversion specifier 'b' requires a C standard library compatible with C23; data argument may not be used by format}} + // c17-warning@-1{{results in undefined behavior with 'b' conversion specifier}} + // c23-warning@-2{{results in undefined behavior with 'b' conversion specifier}} + + printf("%'B\n", 123456789); // c17-warning{{conversion specifier 'B' requires a C standard library compatible with C23; data argument may not be used by format}} + // c17-warning@-1{{results in undefined behavior with 'B' conversion specifier}} + // c23-warning@-2{{results in undefined behavior with 'B' conversion specifier}} + + printf("%hhb %hhB", x, x); // c17-warning{{conversion specifier 'b' requires a C standard library compatible with C23; data argument may not be used by format}} + // c17-warning@-1{{conversion specifier 'B' requires a C standard library compatible with C23; data argument may not be used by format}} +} diff --git a/clang/test/Sema/format-strings-fixit.c b/clang/test/Sema/format-strings-fixit.c index 5e37ec76fed21..6fb191e57bcf2 100644 --- a/clang/test/Sema/format-strings-fixit.c +++ b/clang/test/Sema/format-strings-fixit.c @@ -1,7 +1,7 @@ // RUN: cp %s %t -// RUN: %clang_cc1 -pedantic -Wall -fixit %t -// RUN: %clang_cc1 -fsyntax-only -pedantic -Wall -Werror %t -// RUN: %clang_cc1 -E -o - %t | FileCheck %s +// RUN: %clang_cc1 -std=c23 -pedantic -Wall -fixit %t +// RUN: %clang_cc1 -std=c23 -fsyntax-only -pedantic -Wall -Werror %t +// RUN: %clang_cc1 -std=c23 -E -o - %t | FileCheck %s /* This is a test of the various code modification hints that are provided as part of warning or extension diagnostics. All of the diff --git a/clang/test/Sema/format-strings.c b/clang/test/Sema/format-strings.c index bdb4466dc6ae8..956a4dd27255b 100644 --- a/clang/test/Sema/format-strings.c +++ b/clang/test/Sema/format-strings.c @@ -1,7 +1,7 @@ -// RUN: %clang_cc1 -fblocks -fsyntax-only -verify -Wformat-nonliteral -isystem %S/Inputs %s -// RUN: %clang_cc1 -fblocks -fsyntax-only -verify -Wformat-nonliteral -isystem %S/Inputs -fno-signed-char %s -// RUN: %clang_cc1 -fblocks -fsyntax-only -verify -Wformat-nonliteral -isystem %S/Inputs -triple=x86_64-unknown-fuchsia %s -// RUN: %clang_cc1 -fblocks -fsyntax-only -verify -Wformat-nonliteral -isystem %S/Inputs -triple=x86_64-linux-android %s +// RUN: %clang_cc1 -std=c23 -fblocks -fsyntax-only -verify -Wformat-nonliteral -isystem %S/Inputs %s +// RUN: %clang_cc1 -std=c23 -fblocks -fsyntax-only -verify -Wformat-nonliteral -isystem %S/Inputs -fno-signed-char %s +// RUN: %clang_cc1 -std=c23 -fblocks -fsyntax-only -verify -Wformat-nonliteral -isystem %S/Inputs -triple=x86_64-unknown-fuchsia %s +// RUN: %clang_cc1 -std=c23 -fblocks -fsyntax-only -verify -Wformat-nonliteral -isystem %S/Inputs -triple=x86_64-linux-android %s #include <stdarg.h> #include <stddef.h> _______________________________________________ cfe-commits mailing list [email protected] https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
