}
// Type check the data argument. It should be an 'int'.
+ // Although not in conformance with C99, we also allow the argument to be
+ // an 'unsigned int' as that is a reasonably safe case. GCC also
+ // doesn't emit a warning for that case.
const Expr *Arg = getDataArg(NumConversions);
QualType T = Arg->getType();
- const BuiltinType *BT = T->getAs<BuiltinType>();
- if (!BT || BT->getKind() != BuiltinType::Int) {
+ const BuiltinType *BT = T->getAs<BuiltinType>();
+ if (!BT || (BT->getKind() != BuiltinType::Int &&
+ BT->getKind() != BuiltinType::UInt)) {
S.Diag(getLocationOfByte(Amt.getStart()), BadTypeDiag)
<< T
<< getFormatSpecifierRange(startSpecifier, specifierLen)
// rdar://6079877
printf("abc"
- "%*d", (unsigned) 1, 1); // expected-warning {{field width should have type 'int'}}
+ "%*d", 1, 1); // no-warning
printf("abc\
def"
- "%*d", (unsigned) 1, 1); // expected-warning {{field width should have type 'int'}}
-
+ "%*d", 1, 1); // no-warning
+
+ // <rdar://problem/6079850>, allow 'unsigned' (instead of 'int') to be used for both
+ // the field width and precision. This deviates from C99, but is reasonably safe
+ // and is also accepted by GCC.
+ printf("%*d", (unsigned) 1, 1); // no-warning
}
void check_conditional_literal(const char* s, int i) {
void torture(va_list v8) {
vprintf ("%*.*d", v8); // no-warning
+
}
void test10(int x, float f, int i) {