diff --git a/clang/lib/Sema/SemaChecking.cpp b/clang/lib/Sema/SemaChecking.cpp --- a/clang/lib/Sema/SemaChecking.cpp +++ b/clang/lib/Sema/SemaChecking.cpp @@ -8730,8 +8730,11 @@ } else if (const CharacterLiteral *CL = dyn_cast(E)) { // Special case for 'a', which has type 'int' in C. // Note, however, that we do /not/ want to treat multibyte constants like - // 'MooV' as characters! This form is deprecated but still exists. - if (ExprTy == S.Context.IntTy) + // 'MooV' as characters! This form is deprecated but still exists. In + // addition, don't treat expressions as of type 'char' if one byte length + // modifier is provided. + if (ExprTy == S.Context.IntTy && + FS.getLengthModifier().getKind() != LengthModifier::AsChar) if (llvm::isUIntN(S.Context.getCharWidth(), CL->getValue())) ExprTy = S.Context.CharTy; } diff --git a/clang/test/FixIt/format.m b/clang/test/FixIt/format.m --- a/clang/test/FixIt/format.m +++ b/clang/test/FixIt/format.m @@ -169,6 +169,12 @@ NSLog(@"%@", 'abcd'); // expected-warning{{format specifies type 'id' but the argument has type 'int'}} // CHECK: fix-it:"{{.*}}":{[[@LINE-1]]:11-[[@LINE-1]]:13}:"%d" + + NSLog(@"%hhd", 'a'); // expected-warning{{format specifies type 'char' but the argument has type 'int'}} + // CHECK: fix-it:"{{.*}}":{[[@LINE-1]]:11-[[@LINE-1]]:15}:"%d" + + NSLog(@"%hhu", 'a'); // expected-warning{{format specifies type 'unsigned char' but the argument has type 'int'}} + // CHECK: fix-it:"{{.*}}":{[[@LINE-1]]:11-[[@LINE-1]]:15}:"%d" } void multichar_constants_false_negative() {