Skip to content
This repository has been archived by the owner on Mar 28, 2020. It is now read-only.

Commit

Permalink
[Sema] Don't warn on printf('%hd', [char]) (PR41467)
Browse files Browse the repository at this point in the history
Summary: Link: https://bugs.llvm.org/show_bug.cgi?id=41467

Reviewers: rsmith, nickdesaulniers, aaron.ballman, lebedev.ri

Reviewed By: nickdesaulniers, aaron.ballman, lebedev.ri

Subscribers: lebedev.ri, nickdesaulniers, cfe-commits

Tags: #clang

Differential Revision: https://reviews.llvm.org/D66186

git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@369791 91177308-0d34-0410-b5e6-96231b3b80d8
  • Loading branch information
nhukc authored and epilk committed Sep 18, 2019
1 parent 2aa1beb commit ecef9e0
Show file tree
Hide file tree
Showing 6 changed files with 25 additions and 11 deletions.
2 changes: 2 additions & 0 deletions lib/AST/FormatString.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -386,6 +386,8 @@ ArgType::matchesType(ASTContext &C, QualType argTy) const {
case BuiltinType::SChar:
case BuiltinType::Char_U:
case BuiltinType::UChar:
if (T == C.UnsignedShortTy || T == C.ShortTy)
return NoMatchPedantic;
return T == C.UnsignedCharTy || T == C.SignedCharTy ? Match
: NoMatch;
case BuiltinType::Short:
Expand Down
8 changes: 6 additions & 2 deletions lib/Sema/SemaChecking.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -8082,9 +8082,13 @@ CheckPrintfHandler::checkFormatExpr(const analyze_printf::PrintfSpecifier &FS,
// function.
if (ICE->getType() == S.Context.IntTy ||
ICE->getType() == S.Context.UnsignedIntTy) {
// All further checking is done on the subexpression.
if (AT.matchesType(S.Context, ExprTy))
// All further checking is done on the subexpression
const analyze_printf::ArgType::MatchKind ImplicitMatch =
AT.matchesType(S.Context, ExprTy);
if (ImplicitMatch == analyze_printf::ArgType::Match)
return true;
if (ImplicitMatch == analyze_printf::ArgType::NoMatchPedantic)
Pedantic = true;
}
}
} else if (const CharacterLiteral *CL = dyn_cast<CharacterLiteral>(E)) {
Expand Down
4 changes: 1 addition & 3 deletions test/FixIt/format.m
Original file line number Diff line number Diff line change
Expand Up @@ -205,9 +205,7 @@ void test_percent_C() {
// CHECK: fix-it:"{{.*}}":{[[@LINE-1]]:11-[[@LINE-1]]:13}:"%f"
// CHECK-NOT: fix-it:"{{.*}}":{[[@LINE-2]]:16-[[@LINE-2]]:16}:"(unichar)"

NSLog(@"%C", (char)0x260300); // expected-warning{{format specifies type 'unichar' (aka 'unsigned short') but the argument has type 'char'}}
// CHECK: fix-it:"{{.*}}":{[[@LINE-1]]:11-[[@LINE-1]]:13}:"%c"
// CHECK-NOT: fix-it:"{{.*}}":{[[@LINE-2]]:16-[[@LINE-2]]:22}:"(unichar)"
NSLog(@"%C", (char)0x260300);

NSLog(@"%C", 'a'); // expected-warning{{format specifies type 'unichar' (aka 'unsigned short') but the argument has type 'char'}}
// CHECK: fix-it:"{{.*}}":{[[@LINE-1]]:11-[[@LINE-1]]:13}:"%c"
Expand Down
8 changes: 4 additions & 4 deletions test/Sema/format-strings-enum-fixed-type.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -79,10 +79,10 @@ void testChar(CharEnum input) {
printf("%hhd", input); // no-warning
printf("%hhd", CharConstant); // no-warning

// This is not correct but it is safe. We warn because '%hd' shows intent.
printf("%hd", input); // expected-warning{{format specifies type 'short' but the argument has underlying type 'char'}}
printf("%hd", CharConstant); // expected-warning{{format specifies type 'short'}}
// This is not correct, but it is safe. Only warned in pedantic mode because '%hd' shows intent.
printf("%hd", input);
printf("%hd", CharConstant);

// This is not correct but it matches the promotion rules (and is safe).
printf("%d", input); // no-warning
printf("%d", CharConstant); // no-warning
Expand Down
10 changes: 10 additions & 0 deletions test/Sema/format-strings-pedantic.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
// RUN: %clang_cc1 -fsyntax-only -verify -Wformat -Wformat-pedantic -isystem %S/Inputs %s

int printf(const char *restrict, ...);

typedef unsigned char uint8_t;

void print_char_as_short() {
printf("%hu\n", (unsigned char)1); // expected-warning{{format specifies type 'unsigned short' but the argument has type 'unsigned char'}}
printf("%hu\n", (uint8_t)1); // expected-warning{{format specifies type 'unsigned short' but the argument has type 'uint8_t' (aka 'unsigned char')}}
}
4 changes: 2 additions & 2 deletions test/Sema/format-strings.c
Original file line number Diff line number Diff line change
Expand Up @@ -277,8 +277,8 @@ typedef unsigned char uint8_t;

void should_understand_small_integers() {
printf("%hhu", (short) 10); // expected-warning{{format specifies type 'unsigned char' but the argument has type 'short'}}
printf("%hu\n", (unsigned char) 1); // expected-warning{{format specifies type 'unsigned short' but the argument has type 'unsigned char'}}
printf("%hu\n", (uint8_t)1); // expected-warning{{format specifies type 'unsigned short' but the argument has type 'uint8_t'}}
printf("%hu\n", (unsigned char)1); // warning with -Wformat-pedantic only
printf("%hu\n", (uint8_t)1); // warning with -Wformat-pedantic only
}

void test11(void *p, char *s) {
Expand Down

0 comments on commit ecef9e0

Please sign in to comment.