diff --git a/lib/Analysis/FormatString.cpp b/lib/Analysis/FormatString.cpp
index e4d84ec670b35359a8bdb8422b67bfd5184e9528..4959854a078b30d093ce282886466d5988ed21b9 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 38dc8ae5a0fefb393e56b4ee7a40a852b457bd85..1bb3aac887497eac715ff2134ee8dd3e345bc004 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 5fb2d7ccedd4a9b93e0b82a936ff668df6647da8..d484d8e828cbaa04d034ffc9dd8b7f8aa81dbd20 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 3daa0e4f1d5fbf08f5eaf7610f723a3b9da6e603..4a6f91b5598c7338351c864fe1bfe7c36ea18dfa 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