From 29bf94d86fba0babf426e3d25abaae24dd9971bd Mon Sep 17 00:00:00 2001 From: Saleem Abdulrasool Date: Wed, 19 Sep 2018 18:13:34 +0000 Subject: [PATCH] Sema: handle `wint_t` more carefully for printf checking In the case that `win_t` is an `unsigned short` (e.g. on Windows), we would previously incorrectly diagnose the conversion because we would immediately promote the argument type from `wint_t` (aka `unsigned short`) to `int` before checking if the type matched. This should repair the Windows hosted bots. llvm-svn: 342565 --- clang/lib/Analysis/FormatString.cpp | 12 +++++++----- clang/test/Sema/format-strings-ms.c | 3 +-- clang/test/Sema/format-strings.c | 4 ++++ 3 files changed, 12 insertions(+), 7 deletions(-) diff --git a/clang/lib/Analysis/FormatString.cpp b/clang/lib/Analysis/FormatString.cpp index f37e4affae3f..0bab50c569f7 100644 --- a/clang/lib/Analysis/FormatString.cpp +++ b/clang/lib/Analysis/FormatString.cpp @@ -406,12 +406,14 @@ ArgType::matchesType(ASTContext &C, QualType argTy) const { } case WIntTy: { - - QualType PromoArg = - argTy->isPromotableIntegerType() - ? C.getPromotedIntegerType(argTy) : argTy; - QualType WInt = C.getCanonicalType(C.getWIntType()).getUnqualifiedType(); + + if (C.getCanonicalType(argTy).getUnqualifiedType() == WInt) + return Match; + + QualType PromoArg = argTy->isPromotableIntegerType() + ? C.getPromotedIntegerType(argTy) + : argTy; PromoArg = C.getCanonicalType(PromoArg).getUnqualifiedType(); // If the promoted argument is the corresponding signed type of the diff --git a/clang/test/Sema/format-strings-ms.c b/clang/test/Sema/format-strings-ms.c index 9887b461f610..56a349051d42 100644 --- a/clang/test/Sema/format-strings-ms.c +++ b/clang/test/Sema/format-strings-ms.c @@ -13,7 +13,6 @@ void non_iso_warning_test(__int32 i32, __int64 i64, wchar_t c, void *p) { printf("%I32d", i32); // expected-warning{{'I32' length modifier is not supported by ISO C}} printf("%I64d", i64); // expected-warning{{'I64' length modifier is not supported by ISO C}} printf("%wc", c); // expected-warning{{'w' length modifier is not supported by ISO C}} - // expected-warning@-1{{format specifies type 'wint_t' (aka 'unsigned short') but the argument has type 'wchar_t' (aka 'unsigned short')}} printf("%Z", p); // expected-warning{{'Z' conversion specifier is not supported by ISO C}} } @@ -36,7 +35,7 @@ void unsigned_test() { } void w_test(wchar_t c, wchar_t *s) { - printf("%wc", c); // expected-warning{{format specifies type 'wint_t' (aka 'unsigned short') but the argument has type 'wchar_t' (aka 'unsigned short')}} + printf("%wc", c); printf("%wC", c); printf("%C", c); printf("%ws", s); diff --git a/clang/test/Sema/format-strings.c b/clang/test/Sema/format-strings.c index 54651226adc5..6630acdbc28b 100644 --- a/clang/test/Sema/format-strings.c +++ b/clang/test/Sema/format-strings.c @@ -401,7 +401,11 @@ void bug7377_bad_length_mod_usage() { void pr7981(wint_t c, wchar_t c2) { printf("%lc", c); // no-warning printf("%lc", 1.0); // expected-warning{{the argument has type 'double'}} +#if __WINT_WIDTH__ == 4 printf("%lc", (char) 1); // no-warning +#else + printf("%lc", (char) 1); // expected-warning{{the argument has type 'char'}} +#endif printf("%lc", &c); // expected-warning{{the argument has type 'wint_t *'}} // If wint_t and wchar_t are the same width and wint_t is signed where // wchar_t is unsigned, an implicit conversion isn't possible.