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:
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();
}
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;
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();
}
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();
}
}
+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