From: Hans Wennborg Date: Thu, 4 Sep 2014 21:39:52 +0000 (+0000) Subject: MS format strings: allow the 'h' length modifier with C, C, s and S (PR20808) X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=3d8ef1f21dac3c604364613fe49b70156b8dd170;p=clang MS format strings: allow the 'h' length modifier with C, C, s and S (PR20808) git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@217196 91177308-0d34-0410-b5e6-96231b3b80d8 --- diff --git a/lib/Analysis/FormatString.cpp b/lib/Analysis/FormatString.cpp index e4d84ec670..4959854a07 100644 --- a/lib/Analysis/FormatString.cpp +++ b/lib/Analysis/FormatString.cpp @@ -612,8 +612,20 @@ bool FormatSpecifier::hasValidLengthModifier(const TargetInfo &Target) const { return true; // Handle most integer flags - case LengthModifier::AsChar: case LengthModifier::AsShort: + if (Target.getTriple().isOSMSVCRT()) { + switch (CS.getKind()) { + case ConversionSpecifier::cArg: + case ConversionSpecifier::CArg: + case ConversionSpecifier::sArg: + case ConversionSpecifier::SArg: + return true; + default: + break; + } + } + // Fall through. + case LengthModifier::AsChar: case LengthModifier::AsLongLong: case LengthModifier::AsQuad: case LengthModifier::AsIntMax: diff --git a/lib/Analysis/PrintfFormatString.cpp b/lib/Analysis/PrintfFormatString.cpp index 38dc8ae5a0..1bb3aac887 100644 --- a/lib/Analysis/PrintfFormatString.cpp +++ b/lib/Analysis/PrintfFormatString.cpp @@ -266,10 +266,14 @@ ArgType PrintfSpecifier::getArgType(ASTContext &Ctx, if (CS.getKind() == ConversionSpecifier::cArg) switch (LM.getKind()) { - case LengthModifier::None: return Ctx.IntTy; + case LengthModifier::None: + return Ctx.IntTy; case LengthModifier::AsLong: case LengthModifier::AsWide: return ArgType(ArgType::WIntTy, "wint_t"); + case LengthModifier::AsShort: + if (Ctx.getTargetInfo().getTriple().isOSMSVCRT()) + return Ctx.IntTy; default: return ArgType::Invalid(); } @@ -395,10 +399,16 @@ ArgType PrintfSpecifier::getArgType(ASTContext &Ctx, if (IsObjCLiteral) return ArgType(Ctx.getPointerType(Ctx.UnsignedShortTy.withConst()), "const unichar *"); + if (Ctx.getTargetInfo().getTriple().isOSMSVCRT() && + LM.getKind() == LengthModifier::AsShort) + return ArgType::CStrTy; return ArgType(ArgType::WCStrTy, "wchar_t *"); case ConversionSpecifier::CArg: if (IsObjCLiteral) return ArgType(Ctx.UnsignedShortTy, "unichar"); + if (Ctx.getTargetInfo().getTriple().isOSMSVCRT() && + LM.getKind() == LengthModifier::AsShort) + return Ctx.IntTy; return ArgType(Ctx.WideCharTy, "wchar_t"); case ConversionSpecifier::pArg: return ArgType::CPointerTy; diff --git a/lib/Analysis/ScanfFormatString.cpp b/lib/Analysis/ScanfFormatString.cpp index 5fb2d7cced..d484d8e828 100644 --- a/lib/Analysis/ScanfFormatString.cpp +++ b/lib/Analysis/ScanfFormatString.cpp @@ -333,6 +333,9 @@ ArgType ScanfSpecifier::getArgType(ASTContext &Ctx) const { case LengthModifier::AsAllocate: case LengthModifier::AsMAllocate: return ArgType::PtrTo(ArgType::CStrTy); + case LengthModifier::AsShort: + if (Ctx.getTargetInfo().getTriple().isOSMSVCRT()) + return ArgType::PtrTo(ArgType::AnyCharTy); default: return ArgType::Invalid(); } @@ -346,6 +349,9 @@ ArgType ScanfSpecifier::getArgType(ASTContext &Ctx) const { case LengthModifier::AsAllocate: case LengthModifier::AsMAllocate: return ArgType::PtrTo(ArgType(ArgType::WCStrTy, "wchar_t *")); + case LengthModifier::AsShort: + if (Ctx.getTargetInfo().getTriple().isOSMSVCRT()) + return ArgType::PtrTo(ArgType::AnyCharTy); default: return ArgType::Invalid(); } diff --git a/test/Sema/format-strings-ms.c b/test/Sema/format-strings-ms.c index 3daa0e4f1d..4a6f91b559 100644 --- a/test/Sema/format-strings-ms.c +++ b/test/Sema/format-strings-ms.c @@ -63,4 +63,16 @@ void w_test(wchar_t c, wchar_t *s) { } +void h_test(char c, char* s) { + double bad; + printf("%hc", bad); // expected-warning{{format specifies type 'int' but the argument has type 'double'}} + printf("%hC", bad); // expected-warning{{format specifies type 'int' but the argument has type 'double'}} + printf("%hs", bad); // expected-warning{{format specifies type 'char *' but the argument has type 'double'}} + printf("%hS", bad); // expected-warning{{format specifies type 'char *' but the argument has type 'double'}} + scanf("%hc", &bad); // expected-warning{{format specifies type 'char *' but the argument has type 'double *'}} + scanf("%hC", &bad); // expected-warning{{format specifies type 'char *' but the argument has type 'double *'}} + scanf("%hs", &bad); // expected-warning{{format specifies type 'char *' but the argument has type 'double *'}} + scanf("%hS", &bad); // expected-warning{{format specifies type 'char *' but the argument has type 'double *'}} +} + #endif