Skip to content

Commit 5741d19

Browse files
committed
[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 llvm-svn: 372247
1 parent 79983be commit 5741d19

File tree

4 files changed

+67
-0
lines changed

4 files changed

+67
-0
lines changed

clang/include/clang/Basic/DiagnosticSemaKinds.td

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8145,6 +8145,9 @@ def warn_printf_invalid_objc_flag: Warning<
81458145
def warn_scanf_scanlist_incomplete : Warning<
81468146
"no closing ']' for '%%[' in scanf format string">,
81478147
InGroup<Format>;
8148+
def warn_format_bool_as_character : Warning<
8149+
"using '%0' format specifier, but argument has boolean value">,
8150+
InGroup<Format>;
81488151
def note_format_string_defined : Note<"format string is defined here">;
81498152
def note_format_fix_specifier : Note<"did you mean to use '%0'?">;
81508153
def note_printf_c_str: Note<"did you mean to call the %0 method?">;

clang/lib/AST/FormatString.cpp

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -359,6 +359,7 @@ ArgType::matchesType(ASTContext &C, QualType argTy) const {
359359
case BuiltinType::SChar:
360360
case BuiltinType::UChar:
361361
case BuiltinType::Char_U:
362+
case BuiltinType::Bool:
362363
return Match;
363364
}
364365
return NoMatch;
@@ -386,6 +387,7 @@ ArgType::matchesType(ASTContext &C, QualType argTy) const {
386387
case BuiltinType::SChar:
387388
case BuiltinType::Char_U:
388389
case BuiltinType::UChar:
390+
case BuiltinType::Bool:
389391
if (T == C.UnsignedShortTy || T == C.ShortTy)
390392
return NoMatchPedantic;
391393
return T == C.UnsignedCharTy || T == C.SignedCharTy ? Match

clang/lib/Sema/SemaChecking.cpp

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8109,6 +8109,22 @@ CheckPrintfHandler::checkFormatExpr(const analyze_printf::PrintfSpecifier &FS,
81098109
ExprTy = TET->getUnderlyingExpr()->getType();
81108110
}
81118111

8112+
// Diagnose attempts to print a boolean value as a character. Unlike other
8113+
// -Wformat diagnostics, this is fine from a type perspective, but it still
8114+
// doesn't make sense.
8115+
if (FS.getConversionSpecifier().getKind() == ConversionSpecifier::cArg &&
8116+
E->isKnownToHaveBooleanValue()) {
8117+
const CharSourceRange &CSR =
8118+
getSpecifierRange(StartSpecifier, SpecifierLen);
8119+
SmallString<4> FSString;
8120+
llvm::raw_svector_ostream os(FSString);
8121+
FS.toString(os);
8122+
EmitFormatDiagnostic(S.PDiag(diag::warn_format_bool_as_character)
8123+
<< FSString,
8124+
E->getExprLoc(), false, CSR);
8125+
return true;
8126+
}
8127+
81128128
const analyze_printf::ArgType::MatchKind Match =
81138129
AT.matchesType(S.Context, ExprTy);
81148130
bool Pedantic = Match == analyze_printf::ArgType::NoMatchPedantic;

clang/test/Sema/format-bool.c

Lines changed: 46 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,46 @@
1+
// RUN: %clang_cc1 -xc %s -verify -DBOOL=_Bool
2+
// RUN: %clang_cc1 -xc++ %s -verify -DBOOL=bool
3+
// RUN: %clang_cc1 -xobjective-c %s -verify -DBOOL=_Bool
4+
// RUN: %clang_cc1 -xc %s -verify -DBOOL=_Bool -Wformat-pedantic -DPEDANTIC
5+
// RUN: %clang_cc1 -xc++ %s -verify -DBOOL=bool -Wformat-pedantic -DPEDANTIC
6+
7+
__attribute__((format(__printf__, 1, 2)))
8+
int p(const char *fmt, ...);
9+
10+
BOOL b;
11+
12+
#ifdef __OBJC__
13+
@interface NSString
14+
+(NSString *)stringWithFormat:(NSString *)fmt, ...
15+
__attribute__((format(__NSString__, 1, 2)));
16+
@end
17+
18+
#define YES __objc_yes
19+
#define NO __objc_no
20+
#endif
21+
22+
int main() {
23+
p("%d", b);
24+
p("%hd", b);
25+
#ifdef PEDANTIC
26+
// expected-warning@-2 {{format specifies type 'short' but the argument has type}}
27+
#endif
28+
p("%hhd", b);
29+
p("%u", b);
30+
p("%hu", b);
31+
#ifdef PEDANTIC
32+
// expected-warning@-2 {{format specifies type 'unsigned short' but the argument has type}}
33+
#endif
34+
p("%hhu", b);
35+
p("%c", b); // expected-warning {{using '%c' format specifier, but argument has boolean value}}
36+
p("%lc", b); // expected-warning {{using '%lc' format specifier, but argument has boolean value}}
37+
p("%c", 1 == 1); // expected-warning {{using '%c' format specifier, but argument has boolean value}}
38+
p("%f", b); // expected-warning{{format specifies type 'double' but the argument has type}}
39+
p("%ld", b); // expected-warning{{format specifies type 'long' but the argument has type}}
40+
p("%lld", b); // expected-warning{{format specifies type 'long long' but the argument has type}}
41+
42+
#ifdef __OBJC__
43+
[NSString stringWithFormat: @"%c", 0]; // probably fine?
44+
[NSString stringWithFormat: @"%c", NO]; // expected-warning {{using '%c' format specifier, but argument has boolean value}}
45+
#endif
46+
}

0 commit comments

Comments
 (0)