r372247 - [Sema] Suppress -Wformat diagnostics for bool types when printed using %hhd
Erik Pilkington via cfe-commits
cfe-commits at lists.llvm.org
Wed Sep 18 12:05:15 PDT 2019
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__
+ at interface NSString
++(NSString *)stringWithFormat:(NSString *)fmt, ...
+ __attribute__((format(__NSString__, 1, 2)));
+ at end
+
+#define YES __objc_yes
+#define NO __objc_no
+#endif
+
+int main() {
+ p("%d", b);
+ p("%hd", b);
+#ifdef PEDANTIC
+ // expected-warning at -2 {{format specifies type 'short' but the argument has type}}
+#endif
+ p("%hhd", b);
+ p("%u", b);
+ p("%hu", b);
+#ifdef PEDANTIC
+ // expected-warning at -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
+}
More information about the cfe-commits
mailing list