diff options
-rw-r--r-- | clang/lib/Analysis/FormatString.cpp | 14 | ||||
-rw-r--r-- | clang/lib/Analysis/PrintfFormatString.cpp | 12 | ||||
-rw-r--r-- | clang/lib/Analysis/ScanfFormatString.cpp | 6 | ||||
-rw-r--r-- | clang/test/Sema/format-strings-ms.c | 12 |
4 files changed, 42 insertions, 2 deletions
diff --git a/clang/lib/Analysis/FormatString.cpp b/clang/lib/Analysis/FormatString.cpp index e4d84ec670b..4959854a078 100644 --- a/clang/lib/Analysis/FormatString.cpp +++ b/clang/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/clang/lib/Analysis/PrintfFormatString.cpp b/clang/lib/Analysis/PrintfFormatString.cpp index 38dc8ae5a0f..1bb3aac8874 100644 --- a/clang/lib/Analysis/PrintfFormatString.cpp +++ b/clang/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/clang/lib/Analysis/ScanfFormatString.cpp b/clang/lib/Analysis/ScanfFormatString.cpp index 5fb2d7ccedd..d484d8e828c 100644 --- a/clang/lib/Analysis/ScanfFormatString.cpp +++ b/clang/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/clang/test/Sema/format-strings-ms.c b/clang/test/Sema/format-strings-ms.c index 3daa0e4f1d5..4a6f91b5598 100644 --- a/clang/test/Sema/format-strings-ms.c +++ b/clang/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 |