Author: epilk Date: Wed Sep 18 12:05:14 2019 New Revision: 372247 URL: http://llvm.org/viewvc/llvm-project?rev=372247&view=rev Log: [Sema] Suppress -Wformat diagnostics for bool types when printed using %hhd
Also, add a diagnostic under -Wformat for printing a boolean value as a character. rdar://54579473 Differential revision: https://reviews.llvm.org/D66856 Added: cfe/trunk/test/Sema/format-bool.c Modified: cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td cfe/trunk/lib/AST/FormatString.cpp cfe/trunk/lib/Sema/SemaChecking.cpp Modified: cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td?rev=372247&r1=372246&r2=372247&view=diff ============================================================================== --- cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td (original) +++ cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td Wed Sep 18 12:05:14 2019 @@ -8145,6 +8145,9 @@ def warn_printf_invalid_objc_flag: Warni def warn_scanf_scanlist_incomplete : Warning< "no closing ']' for '%%[' in scanf format string">, InGroup<Format>; +def warn_format_bool_as_character : Warning< + "using '%0' format specifier, but argument has boolean value">, + InGroup<Format>; def note_format_string_defined : Note<"format string is defined here">; def note_format_fix_specifier : Note<"did you mean to use '%0'?">; def note_printf_c_str: Note<"did you mean to call the %0 method?">; Modified: cfe/trunk/lib/AST/FormatString.cpp URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/AST/FormatString.cpp?rev=372247&r1=372246&r2=372247&view=diff ============================================================================== --- cfe/trunk/lib/AST/FormatString.cpp (original) +++ cfe/trunk/lib/AST/FormatString.cpp Wed Sep 18 12:05:14 2019 @@ -359,6 +359,7 @@ ArgType::matchesType(ASTContext &C, Qual case BuiltinType::SChar: case BuiltinType::UChar: case BuiltinType::Char_U: + case BuiltinType::Bool: return Match; } return NoMatch; @@ -386,6 +387,7 @@ ArgType::matchesType(ASTContext &C, Qual case BuiltinType::SChar: case BuiltinType::Char_U: case BuiltinType::UChar: + case BuiltinType::Bool: if (T == C.UnsignedShortTy || T == C.ShortTy) return NoMatchPedantic; return T == C.UnsignedCharTy || T == C.SignedCharTy ? Match Modified: cfe/trunk/lib/Sema/SemaChecking.cpp URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaChecking.cpp?rev=372247&r1=372246&r2=372247&view=diff ============================================================================== --- cfe/trunk/lib/Sema/SemaChecking.cpp (original) +++ cfe/trunk/lib/Sema/SemaChecking.cpp Wed Sep 18 12:05:14 2019 @@ -8109,6 +8109,22 @@ CheckPrintfHandler::checkFormatExpr(cons ExprTy = TET->getUnderlyingExpr()->getType(); } + // Diagnose attempts to print a boolean value as a character. Unlike other + // -Wformat diagnostics, this is fine from a type perspective, but it still + // doesn't make sense. + if (FS.getConversionSpecifier().getKind() == ConversionSpecifier::cArg && + E->isKnownToHaveBooleanValue()) { + const CharSourceRange &CSR = + getSpecifierRange(StartSpecifier, SpecifierLen); + SmallString<4> FSString; + llvm::raw_svector_ostream os(FSString); + FS.toString(os); + EmitFormatDiagnostic(S.PDiag(diag::warn_format_bool_as_character) + << FSString, + E->getExprLoc(), false, CSR); + return true; + } + const analyze_printf::ArgType::MatchKind Match = AT.matchesType(S.Context, ExprTy); bool Pedantic = Match == analyze_printf::ArgType::NoMatchPedantic; Added: cfe/trunk/test/Sema/format-bool.c URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/Sema/format-bool.c?rev=372247&view=auto ============================================================================== --- cfe/trunk/test/Sema/format-bool.c (added) +++ cfe/trunk/test/Sema/format-bool.c Wed Sep 18 12:05:14 2019 @@ -0,0 +1,46 @@ +// RUN: %clang_cc1 -xc %s -verify -DBOOL=_Bool +// RUN: %clang_cc1 -xc++ %s -verify -DBOOL=bool +// RUN: %clang_cc1 -xobjective-c %s -verify -DBOOL=_Bool +// RUN: %clang_cc1 -xc %s -verify -DBOOL=_Bool -Wformat-pedantic -DPEDANTIC +// RUN: %clang_cc1 -xc++ %s -verify -DBOOL=bool -Wformat-pedantic -DPEDANTIC + +__attribute__((format(__printf__, 1, 2))) +int p(const char *fmt, ...); + +BOOL b; + +#ifdef __OBJC__ +@interface NSString ++(NSString *)stringWithFormat:(NSString *)fmt, ... + __attribute__((format(__NSString__, 1, 2))); +@end + +#define YES __objc_yes +#define NO __objc_no +#endif + +int main() { + p("%d", b); + p("%hd", b); +#ifdef PEDANTIC + // expected-warning@-2 {{format specifies type 'short' but the argument has type}} +#endif + p("%hhd", b); + p("%u", b); + p("%hu", b); +#ifdef PEDANTIC + // expected-warning@-2 {{format specifies type 'unsigned short' but the argument has type}} +#endif + p("%hhu", b); + p("%c", b); // expected-warning {{using '%c' format specifier, but argument has boolean value}} + p("%lc", b); // expected-warning {{using '%lc' format specifier, but argument has boolean value}} + p("%c", 1 == 1); // expected-warning {{using '%c' format specifier, but argument has boolean value}} + p("%f", b); // expected-warning{{format specifies type 'double' but the argument has type}} + p("%ld", b); // expected-warning{{format specifies type 'long' but the argument has type}} + p("%lld", b); // expected-warning{{format specifies type 'long long' but the argument has type}} + +#ifdef __OBJC__ + [NSString stringWithFormat: @"%c", 0]; // probably fine? + [NSString stringWithFormat: @"%c", NO]; // expected-warning {{using '%c' format specifier, but argument has boolean value}} +#endif +} _______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits