Index: clang/lib/AST/FormatString.cpp =================================================================== --- clang/lib/AST/FormatString.cpp +++ clang/lib/AST/FormatString.cpp @@ -401,8 +401,21 @@ case BuiltinType::UInt: return T == C.IntTy ? Match : NoMatch; case BuiltinType::Long: + // Win32 platform mixes long and int for size_t-like purposes. + // ssize_t is int, but platform type SSIZE_T is long. + if ((isSizeT() || isPtrdiffT()) && + C.getTargetInfo().getTriple().isOSMSVCRT() && + C.getTargetInfo().getTriple().isArch32Bit()) + return Match; return T == C.UnsignedLongTy ? Match : NoMatch; case BuiltinType::ULong: + // Win32 platform mixes long and int for size_t-like purposes. + // size_t is unsigned int, but platform type SIZE_T is unsigned + // long. + if ((isSizeT() || isPtrdiffT()) && + C.getTargetInfo().getTriple().isOSMSVCRT() && + C.getTargetInfo().getTriple().isArch32Bit()) + return Match; return T == C.LongTy ? Match : NoMatch; case BuiltinType::LongLong: return T == C.UnsignedLongLongTy ? Match : NoMatch; Index: clang/lib/AST/PrintfFormatString.cpp =================================================================== --- clang/lib/AST/PrintfFormatString.cpp +++ clang/lib/AST/PrintfFormatString.cpp @@ -527,8 +527,8 @@ return ArgType::makeSizeT(ArgType(Ctx.getSignedSizeType(), "ssize_t")); case LengthModifier::AsInt3264: return Ctx.getTargetInfo().getTriple().isArch64Bit() - ? ArgType(Ctx.LongLongTy, "__int64") - : ArgType(Ctx.IntTy, "__int32"); + ? ArgType::makeSizeT(ArgType(Ctx.LongLongTy, "__int64")) + : ArgType::makeSizeT(ArgType(Ctx.IntTy, "__int32")); case LengthModifier::AsPtrDiff: return ArgType::makePtrdiffT( ArgType(Ctx.getPointerDiffType(), "ptrdiff_t")); @@ -562,8 +562,10 @@ return ArgType::makeSizeT(ArgType(Ctx.getSizeType(), "size_t")); case LengthModifier::AsInt3264: return Ctx.getTargetInfo().getTriple().isArch64Bit() - ? ArgType(Ctx.UnsignedLongLongTy, "unsigned __int64") - : ArgType(Ctx.UnsignedIntTy, "unsigned __int32"); + ? ArgType::makeSizeT( + ArgType(Ctx.UnsignedLongLongTy, "unsigned __int64")) + : ArgType::makeSizeT( + ArgType(Ctx.UnsignedIntTy, "unsigned __int32")); case LengthModifier::AsPtrDiff: return ArgType::makePtrdiffT( ArgType(Ctx.getUnsignedPointerDiffType(), "unsigned ptrdiff_t")); Index: clang/test/Sema/format-strings-ms.c =================================================================== --- clang/test/Sema/format-strings-ms.c +++ clang/test/Sema/format-strings-ms.c @@ -21,17 +21,35 @@ void signed_test() { short val = 30; printf("val = %I64d\n", val); // expected-warning{{format specifies type '__int64' (aka 'long long') but the argument has type 'short'}} + printf("val = %Id\n", val); long long bigval = 30; printf("val = %I32d\n", bigval); // expected-warning{{format specifies type '__int32' (aka 'int') but the argument has type 'long long'}} printf("val = %Id\n", bigval); // expected-warning{{format specifies type '__int32' (aka 'int') but the argument has type 'long long'}} + int ival = 30; + printf("%Id", ival); + printf("%zd", ival); + printf("%td", ival); + long lval = 30; + printf("%Id", lval); + printf("%zd", lval); + printf("%td", lval); } void unsigned_test() { unsigned short val = 30; printf("val = %I64u\n", val); // expected-warning{{format specifies type 'unsigned __int64' (aka 'unsigned long long') but the argument has type 'unsigned short'}} + printf("val = %Iu\n", val); unsigned long long bigval = 30; printf("val = %I32u\n", bigval); // expected-warning{{format specifies type 'unsigned __int32' (aka 'unsigned int') but the argument has type 'unsigned long long'}} printf("val = %Iu\n", bigval); // expected-warning{{format specifies type 'unsigned __int32' (aka 'unsigned int') but the argument has type 'unsigned long long'}} + unsigned int ival = 30; + printf("%Iu", ival); + printf("%zu", ival); + printf("%tu", ival); + unsigned long lval = 30; + printf("%Iu", lval); + printf("%zu", lval); + printf("%tu", lval); } void w_test(wchar_t c, wchar_t *s) {