1*67e74705SXin Li// RUN: %clang_cc1 -triple i386-apple-darwin9 -fsyntax-only -fblocks -Wformat-non-iso -verify %s 2*67e74705SXin Li// RUN: %clang_cc1 -triple x86_64-apple-darwin9 -fsyntax-only -fblocks -Wformat-non-iso -verify %s 3*67e74705SXin Li 4*67e74705SXin Li// RUN: %clang_cc1 -triple i386-apple-darwin9 -fdiagnostics-parseable-fixits -fblocks -Wformat-non-iso %s 2>&1 | FileCheck -check-prefix=CHECK -check-prefix=CHECK-32 %s 5*67e74705SXin Li// RUN: %clang_cc1 -triple x86_64-apple-darwin9 -fdiagnostics-parseable-fixits -fblocks -Wformat-non-iso %s 2>&1 | FileCheck -check-prefix=CHECK -check-prefix=CHECK-64 %s 6*67e74705SXin Li 7*67e74705SXin Liint printf(const char * restrict, ...); 8*67e74705SXin Li 9*67e74705SXin Li#if __LP64__ 10*67e74705SXin Litypedef long NSInteger; 11*67e74705SXin Litypedef unsigned long NSUInteger; 12*67e74705SXin Litypedef int SInt32; 13*67e74705SXin Litypedef unsigned int UInt32; 14*67e74705SXin Li 15*67e74705SXin Li#else 16*67e74705SXin Li 17*67e74705SXin Litypedef int NSInteger; 18*67e74705SXin Litypedef unsigned int NSUInteger; 19*67e74705SXin Litypedef long SInt32; 20*67e74705SXin Litypedef unsigned long UInt32; 21*67e74705SXin Li#endif 22*67e74705SXin Li 23*67e74705SXin Litypedef SInt32 OSStatus; 24*67e74705SXin Li 25*67e74705SXin Litypedef enum NSIntegerEnum : NSInteger { 26*67e74705SXin Li EnumValueA, 27*67e74705SXin Li EnumValueB 28*67e74705SXin Li} NSIntegerEnum; 29*67e74705SXin Li 30*67e74705SXin LiNSInteger getNSInteger(); 31*67e74705SXin LiNSUInteger getNSUInteger(); 32*67e74705SXin LiSInt32 getSInt32(); 33*67e74705SXin LiUInt32 getUInt32(); 34*67e74705SXin LiNSIntegerEnum getNSIntegerEnum(); 35*67e74705SXin Li 36*67e74705SXin Livoid testCorrectionInAllCases() { 37*67e74705SXin Li printf("%s", getNSInteger()); // expected-warning{{values of type 'NSInteger' should not be used as format arguments; add an explicit cast to 'long' instead}} 38*67e74705SXin Li printf("%s", getNSUInteger()); // expected-warning{{values of type 'NSUInteger' should not be used as format arguments; add an explicit cast to 'unsigned long' instead}} 39*67e74705SXin Li printf("%s", getSInt32()); // expected-warning{{values of type 'SInt32' should not be used as format arguments; add an explicit cast to 'int' instead}} 40*67e74705SXin Li printf("%s", getUInt32()); // expected-warning{{values of type 'UInt32' should not be used as format arguments; add an explicit cast to 'unsigned int' instead}} 41*67e74705SXin Li 42*67e74705SXin Li // CHECK: fix-it:"{{.*}}":{[[@LINE-5]]:11-[[@LINE-5]]:13}:"%ld" 43*67e74705SXin Li // CHECK: fix-it:"{{.*}}":{[[@LINE-6]]:16-[[@LINE-6]]:16}:"(long)" 44*67e74705SXin Li 45*67e74705SXin Li // CHECK: fix-it:"{{.*}}":{[[@LINE-7]]:11-[[@LINE-7]]:13}:"%lu" 46*67e74705SXin Li // CHECK: fix-it:"{{.*}}":{[[@LINE-8]]:16-[[@LINE-8]]:16}:"(unsigned long)" 47*67e74705SXin Li 48*67e74705SXin Li // CHECK: fix-it:"{{.*}}":{[[@LINE-9]]:11-[[@LINE-9]]:13}:"%d" 49*67e74705SXin Li // CHECK: fix-it:"{{.*}}":{[[@LINE-10]]:16-[[@LINE-10]]:16}:"(int)" 50*67e74705SXin Li 51*67e74705SXin Li // CHECK: fix-it:"{{.*}}":{[[@LINE-11]]:11-[[@LINE-11]]:13}:"%u" 52*67e74705SXin Li // CHECK: fix-it:"{{.*}}":{[[@LINE-12]]:16-[[@LINE-12]]:16}:"(unsigned int)" 53*67e74705SXin Li 54*67e74705SXin Li printf("%s", getNSIntegerEnum()); // expected-warning{{enum values with underlying type 'NSInteger' should not be used as format arguments; add an explicit cast to 'long' instead}} 55*67e74705SXin Li 56*67e74705SXin Li // CHECK: fix-it:"{{.*}}":{[[@LINE-2]]:11-[[@LINE-2]]:13}:"%ld" 57*67e74705SXin Li // CHECK: fix-it:"{{.*}}":{[[@LINE-3]]:16-[[@LINE-3]]:16}:"(long)" 58*67e74705SXin Li} 59*67e74705SXin Li 60*67e74705SXin Li@interface Foo { 61*67e74705SXin Li@public 62*67e74705SXin Li NSInteger _value; 63*67e74705SXin Li} 64*67e74705SXin Li- (NSInteger)getInteger; 65*67e74705SXin Li 66*67e74705SXin Li@property NSInteger value; 67*67e74705SXin Li@end 68*67e74705SXin Li 69*67e74705SXin Listruct Bar { 70*67e74705SXin Li NSInteger value; 71*67e74705SXin Li}; 72*67e74705SXin Li 73*67e74705SXin Li 74*67e74705SXin Livoid testParens(Foo *obj, struct Bar *record) { 75*67e74705SXin Li NSInteger arr[4] = {0}; 76*67e74705SXin Li NSInteger i = 0; 77*67e74705SXin Li 78*67e74705SXin Li // These cases match the relevant cases in CheckPrintfHandler::checkFormatExpr. 79*67e74705SXin Li printf("%s", arr[0]); // expected-warning{{values of type 'NSInteger' should not be used as format arguments; add an explicit cast to 'long' instead}} 80*67e74705SXin Li printf("%s", getNSInteger()); // expected-warning{{values of type 'NSInteger' should not be used as format arguments; add an explicit cast to 'long' instead}} 81*67e74705SXin Li printf("%s", i); // expected-warning{{values of type 'NSInteger' should not be used as format arguments; add an explicit cast to 'long' instead}} 82*67e74705SXin Li printf("%s", obj->_value); // expected-warning{{values of type 'NSInteger' should not be used as format arguments; add an explicit cast to 'long' instead}} 83*67e74705SXin Li printf("%s", [obj getInteger]); // expected-warning{{values of type 'NSInteger' should not be used as format arguments; add an explicit cast to 'long' instead}} 84*67e74705SXin Li printf("%s", obj.value); // expected-warning{{values of type 'NSInteger' should not be used as format arguments; add an explicit cast to 'long' instead}} 85*67e74705SXin Li printf("%s", record->value); // expected-warning{{values of type 'NSInteger' should not be used as format arguments; add an explicit cast to 'long' instead}} 86*67e74705SXin Li printf("%s", (i ? i : i)); // expected-warning{{values of type 'NSInteger' should not be used as format arguments; add an explicit cast to 'long' instead}} 87*67e74705SXin Li printf("%s", *arr); // expected-warning{{values of type 'NSInteger' should not be used as format arguments; add an explicit cast to 'long' instead}} 88*67e74705SXin Li 89*67e74705SXin Li // CHECK-NOT: fix-it:{{.*}}:")" 90*67e74705SXin Li 91*67e74705SXin Li printf("%s", i ? i : i); // expected-warning{{values of type 'NSInteger' should not be used as format arguments; add an explicit cast to 'long' instead}} 92*67e74705SXin Li 93*67e74705SXin Li // CHECK: fix-it:"{{.*}}":{[[@LINE-2]]:11-[[@LINE-2]]:13}:"%ld" 94*67e74705SXin Li // CHECK: fix-it:"{{.*}}":{[[@LINE-3]]:16-[[@LINE-3]]:16}:"(long)(" 95*67e74705SXin Li // CHECK: fix-it:"{{.*}}":{[[@LINE-4]]:25-[[@LINE-4]]:25}:")" 96*67e74705SXin Li} 97*67e74705SXin Li 98*67e74705SXin Li 99*67e74705SXin Li#if __LP64__ 100*67e74705SXin Li 101*67e74705SXin Livoid testWarn() { 102*67e74705SXin Li printf("%d", getNSInteger()); // expected-warning{{values of type 'NSInteger' should not be used as format arguments; add an explicit cast to 'long' instead}} 103*67e74705SXin Li printf("%u", getNSUInteger()); // expected-warning{{values of type 'NSUInteger' should not be used as format arguments; add an explicit cast to 'unsigned long' instead}} 104*67e74705SXin Li printf("%ld", getSInt32()); // expected-warning{{values of type 'SInt32' should not be used as format arguments; add an explicit cast to 'int' instead}} 105*67e74705SXin Li printf("%lu", getUInt32()); // expected-warning{{values of type 'UInt32' should not be used as format arguments; add an explicit cast to 'unsigned int' instead}} 106*67e74705SXin Li 107*67e74705SXin Li // CHECK-64: fix-it:"{{.*}}":{[[@LINE-5]]:11-[[@LINE-5]]:13}:"%ld" 108*67e74705SXin Li // CHECK-64: fix-it:"{{.*}}":{[[@LINE-6]]:16-[[@LINE-6]]:16}:"(long)" 109*67e74705SXin Li 110*67e74705SXin Li // CHECK-64: fix-it:"{{.*}}":{[[@LINE-7]]:11-[[@LINE-7]]:13}:"%lu" 111*67e74705SXin Li // CHECK-64: fix-it:"{{.*}}":{[[@LINE-8]]:16-[[@LINE-8]]:16}:"(unsigned long)" 112*67e74705SXin Li 113*67e74705SXin Li // CHECK-64: fix-it:"{{.*}}":{[[@LINE-9]]:11-[[@LINE-9]]:14}:"%d" 114*67e74705SXin Li // CHECK-64: fix-it:"{{.*}}":{[[@LINE-10]]:17-[[@LINE-10]]:17}:"(int)" 115*67e74705SXin Li 116*67e74705SXin Li // CHECK-64: fix-it:"{{.*}}":{[[@LINE-11]]:11-[[@LINE-11]]:14}:"%u" 117*67e74705SXin Li // CHECK-64: fix-it:"{{.*}}":{[[@LINE-12]]:17-[[@LINE-12]]:17}:"(unsigned int)" 118*67e74705SXin Li 119*67e74705SXin Li printf("%d", getNSIntegerEnum()); // expected-warning{{enum values with underlying type 'NSInteger' should not be used as format arguments; add an explicit cast to 'long' instead}} 120*67e74705SXin Li 121*67e74705SXin Li // CHECK-64: fix-it:"{{.*}}":{[[@LINE-2]]:11-[[@LINE-2]]:13}:"%ld" 122*67e74705SXin Li // CHECK-64: fix-it:"{{.*}}":{[[@LINE-3]]:16-[[@LINE-3]]:16}:"(long)" 123*67e74705SXin Li} 124*67e74705SXin Li 125*67e74705SXin Livoid testPreserveHex() { 126*67e74705SXin Li printf("%x", getNSInteger()); // expected-warning{{values of type 'NSInteger' should not be used as format arguments; add an explicit cast to 'long' instead}} 127*67e74705SXin Li printf("%x", getNSUInteger()); // expected-warning{{values of type 'NSUInteger' should not be used as format arguments; add an explicit cast to 'unsigned long' instead}} 128*67e74705SXin Li 129*67e74705SXin Li // CHECK-64: fix-it:"{{.*}}":{[[@LINE-3]]:11-[[@LINE-3]]:13}:"%lx" 130*67e74705SXin Li // CHECK-64: fix-it:"{{.*}}":{[[@LINE-4]]:16-[[@LINE-4]]:16}:"(long)" 131*67e74705SXin Li 132*67e74705SXin Li // CHECK-64: fix-it:"{{.*}}":{[[@LINE-5]]:11-[[@LINE-5]]:13}:"%lx" 133*67e74705SXin Li // CHECK-64: fix-it:"{{.*}}":{[[@LINE-6]]:16-[[@LINE-6]]:16}:"(unsigned long)" 134*67e74705SXin Li} 135*67e74705SXin Li 136*67e74705SXin Livoid testSignedness(NSInteger i, NSUInteger u) { 137*67e74705SXin Li printf("%d", u); // expected-warning{{values of type 'NSUInteger' should not be used as format arguments; add an explicit cast to 'unsigned long' instead}} 138*67e74705SXin Li printf("%i", u); // expected-warning{{values of type 'NSUInteger' should not be used as format arguments; add an explicit cast to 'unsigned long' instead}} 139*67e74705SXin Li printf("%u", i); // expected-warning{{values of type 'NSInteger' should not be used as format arguments; add an explicit cast to 'long' instead}} 140*67e74705SXin Li 141*67e74705SXin Li // CHECK-64: fix-it:"{{.*}}":{[[@LINE-4]]:11-[[@LINE-4]]:13}:"%lu" 142*67e74705SXin Li // CHECK-64: fix-it:"{{.*}}":{[[@LINE-4]]:11-[[@LINE-4]]:13}:"%lu" 143*67e74705SXin Li // CHECK-64: fix-it:"{{.*}}":{[[@LINE-4]]:11-[[@LINE-4]]:13}:"%ld" 144*67e74705SXin Li} 145*67e74705SXin Li 146*67e74705SXin Livoid testNoWarn() { 147*67e74705SXin Li printf("%ld", getNSInteger()); // no-warning 148*67e74705SXin Li printf("%lu", getNSUInteger()); // no-warning 149*67e74705SXin Li printf("%d", getSInt32()); // no-warning 150*67e74705SXin Li printf("%u", getUInt32()); // no-warning 151*67e74705SXin Li printf("%ld", getNSIntegerEnum()); // no-warning 152*67e74705SXin Li} 153*67e74705SXin Li 154*67e74705SXin Li#else 155*67e74705SXin Li 156*67e74705SXin Livoid testWarn() { 157*67e74705SXin Li printf("%ld", getNSInteger()); // expected-warning{{values of type 'NSInteger' should not be used as format arguments; add an explicit cast to 'long' instead}} 158*67e74705SXin Li printf("%lu", getNSUInteger()); // expected-warning{{values of type 'NSUInteger' should not be used as format arguments; add an explicit cast to 'unsigned long' instead}} 159*67e74705SXin Li printf("%d", getSInt32()); // expected-warning{{values of type 'SInt32' should not be used as format arguments; add an explicit cast to 'int' instead}} 160*67e74705SXin Li printf("%u", getUInt32()); // expected-warning{{values of type 'UInt32' should not be used as format arguments; add an explicit cast to 'unsigned int' instead}} 161*67e74705SXin Li 162*67e74705SXin Li // CHECK-32: fix-it:"{{.*}}":{[[@LINE-5]]:17-[[@LINE-5]]:17}:"(long)" 163*67e74705SXin Li // CHECK-32: fix-it:"{{.*}}":{[[@LINE-5]]:17-[[@LINE-5]]:17}:"(unsigned long)" 164*67e74705SXin Li // CHECK-32: fix-it:"{{.*}}":{[[@LINE-5]]:16-[[@LINE-5]]:16}:"(int)" 165*67e74705SXin Li // CHECK-32: fix-it:"{{.*}}":{[[@LINE-5]]:16-[[@LINE-5]]:16}:"(unsigned int)" 166*67e74705SXin Li 167*67e74705SXin Li printf("%ld", getNSIntegerEnum()); // expected-warning{{enum values with underlying type 'NSInteger' should not be used as format arguments; add an explicit cast to 'long' instead}} 168*67e74705SXin Li 169*67e74705SXin Li // CHECK-32: fix-it:"{{.*}}":{[[@LINE-2]]:17-[[@LINE-2]]:17}:"(long)" 170*67e74705SXin Li} 171*67e74705SXin Li 172*67e74705SXin Livoid testPreserveHex() { 173*67e74705SXin Li printf("%lx", getNSInteger()); // expected-warning{{values of type 'NSInteger' should not be used as format arguments; add an explicit cast to 'long' instead}} 174*67e74705SXin Li printf("%lx", getNSUInteger()); // expected-warning{{values of type 'NSUInteger' should not be used as format arguments; add an explicit cast to 'unsigned long' instead}} 175*67e74705SXin Li 176*67e74705SXin Li // CHECK-32: fix-it:"{{.*}}":{[[@LINE-3]]:17-[[@LINE-3]]:17}:"(long)" 177*67e74705SXin Li // CHECK-32: fix-it:"{{.*}}":{[[@LINE-3]]:17-[[@LINE-3]]:17}:"(unsigned long)" 178*67e74705SXin Li} 179*67e74705SXin Li 180*67e74705SXin Livoid testNoWarn() { 181*67e74705SXin Li printf("%d", getNSInteger()); // no-warning 182*67e74705SXin Li printf("%u", getNSUInteger()); // no-warning 183*67e74705SXin Li printf("%ld", getSInt32()); // no-warning 184*67e74705SXin Li printf("%lu", getUInt32()); // no-warning 185*67e74705SXin Li printf("%d", getNSIntegerEnum()); // no-warning 186*67e74705SXin Li} 187*67e74705SXin Li 188*67e74705SXin Livoid testSignedness(NSInteger i, NSUInteger u) { 189*67e74705SXin Li // It is valid to use a specifier with the opposite signedness as long as 190*67e74705SXin Li // the type is correct. 191*67e74705SXin Li printf("%d", u); // no-warning 192*67e74705SXin Li printf("%i", u); // no-warning 193*67e74705SXin Li printf("%u", i); // no-warning 194*67e74705SXin Li} 195*67e74705SXin Li 196*67e74705SXin Li#endif 197*67e74705SXin Li 198*67e74705SXin Li 199*67e74705SXin Livoid testCasts() { 200*67e74705SXin Li printf("%s", (NSInteger)0); // expected-warning{{values of type 'NSInteger' should not be used as format arguments; add an explicit cast to 'long' instead}} 201*67e74705SXin Li printf("%s", (NSUInteger)0); // expected-warning{{values of type 'NSUInteger' should not be used as format arguments; add an explicit cast to 'unsigned long' instead}} 202*67e74705SXin Li printf("%s", (SInt32)0); // expected-warning{{values of type 'SInt32' should not be used as format arguments; add an explicit cast to 'int' instead}} 203*67e74705SXin Li printf("%s", (UInt32)0); // expected-warning{{values of type 'UInt32' should not be used as format arguments; add an explicit cast to 'unsigned int' instead}} 204*67e74705SXin Li 205*67e74705SXin Li // CHECK: fix-it:"{{.*}}":{[[@LINE-5]]:11-[[@LINE-5]]:13}:"%ld" 206*67e74705SXin Li // CHECK: fix-it:"{{.*}}":{[[@LINE-6]]:16-[[@LINE-6]]:27}:"(long)" 207*67e74705SXin Li 208*67e74705SXin Li // CHECK: fix-it:"{{.*}}":{[[@LINE-7]]:11-[[@LINE-7]]:13}:"%lu" 209*67e74705SXin Li // CHECK: fix-it:"{{.*}}":{[[@LINE-8]]:16-[[@LINE-8]]:28}:"(unsigned long)" 210*67e74705SXin Li 211*67e74705SXin Li // CHECK: fix-it:"{{.*}}":{[[@LINE-9]]:11-[[@LINE-9]]:13}:"%d" 212*67e74705SXin Li // CHECK: fix-it:"{{.*}}":{[[@LINE-10]]:16-[[@LINE-10]]:24}:"(int)" 213*67e74705SXin Li 214*67e74705SXin Li // CHECK: fix-it:"{{.*}}":{[[@LINE-11]]:11-[[@LINE-11]]:13}:"%u" 215*67e74705SXin Li // CHECK: fix-it:"{{.*}}":{[[@LINE-12]]:16-[[@LINE-12]]:24}:"(unsigned int)" 216*67e74705SXin Li 217*67e74705SXin Li printf("%s", (NSIntegerEnum)0); // expected-warning{{enum values with underlying type 'NSInteger' should not be used as format arguments; add an explicit cast to 'long' instead}} 218*67e74705SXin Li 219*67e74705SXin Li // CHECK: fix-it:"{{.*}}":{[[@LINE-2]]:11-[[@LINE-2]]:13}:"%ld" 220*67e74705SXin Li // CHECK: fix-it:"{{.*}}":{[[@LINE-3]]:16-[[@LINE-3]]:31}:"(long)" 221*67e74705SXin Li} 222*67e74705SXin Li 223*67e74705SXin Livoid testCapitals() { 224*67e74705SXin Li printf("%D", 1); // expected-warning{{conversion specifier is not supported by ISO C}} expected-note {{did you mean to use 'd'?}} 225*67e74705SXin Li printf("%U", 1); // expected-warning{{conversion specifier is not supported by ISO C}} expected-note {{did you mean to use 'u'?}} 226*67e74705SXin Li printf("%O", 1); // expected-warning{{conversion specifier is not supported by ISO C}} expected-note {{did you mean to use 'o'?}} 227*67e74705SXin Li 228*67e74705SXin Li // CHECK: fix-it:"{{.*}}":{[[@LINE-4]]:12-[[@LINE-4]]:13}:"d" 229*67e74705SXin Li // CHECK: fix-it:"{{.*}}":{[[@LINE-4]]:12-[[@LINE-4]]:13}:"u" 230*67e74705SXin Li // CHECK: fix-it:"{{.*}}":{[[@LINE-4]]:12-[[@LINE-4]]:13}:"o" 231*67e74705SXin Li 232*67e74705SXin Li 233*67e74705SXin Li printf("%lD", 1); // expected-warning{{conversion specifier is not supported by ISO C}} expected-note {{did you mean to use 'd'?}} expected-warning{{format specifies type 'long' but the argument has type 'int'}} 234*67e74705SXin Li 235*67e74705SXin Li // FIXME: offering two somewhat-conflicting fixits is less than ideal. 236*67e74705SXin Li // CHECK: fix-it:"{{.*}}":{[[@LINE-3]]:13-[[@LINE-3]]:14}:"d" 237*67e74705SXin Li // CHECK: fix-it:"{{.*}}":{[[@LINE-4]]:11-[[@LINE-4]]:14}:"%D" 238*67e74705SXin Li} 239*67e74705SXin Li 240*67e74705SXin Livoid testLayeredTypedefs(OSStatus i) { 241*67e74705SXin Li printf("%s", i); // expected-warning {{values of type 'OSStatus' should not be used as format arguments}} 242*67e74705SXin Li // CHECK: fix-it:"{{.*}}":{[[@LINE-1]]:11-[[@LINE-1]]:13}:"%d" 243*67e74705SXin Li} 244*67e74705SXin Li 245