266 lines · plain
1// RUN: %clang_cc1 -triple i386-apple-darwin9 -fsyntax-only -fblocks -Wformat-non-iso -verify %s2// RUN: %clang_cc1 -triple x86_64-apple-darwin9 -fsyntax-only -fblocks -Wformat-non-iso -verify %s3 4// 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 %s5// 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 %s6 7int printf(const char * restrict, ...);8 9#if __LP64__10typedef long CFIndex;11typedef long NSInteger;12typedef unsigned long NSUInteger;13typedef int SInt32;14typedef unsigned int UInt32;15 16#else17typedef int CFIndex;18typedef int NSInteger;19typedef unsigned int NSUInteger;20typedef long SInt32;21typedef unsigned long UInt32;22#endif23 24typedef SInt32 OSStatus;25 26typedef enum NSIntegerEnum : NSInteger {27 EnumValueA,28 EnumValueB29} NSIntegerEnum;30 31CFIndex getCFIndex(void);32NSInteger getNSInteger(void);33NSUInteger getNSUInteger(void);34SInt32 getSInt32(void);35UInt32 getUInt32(void);36NSIntegerEnum getNSIntegerEnum(void);37 38void testCorrectionInAllCases(void) {39 printf("%s", getNSInteger()); // expected-warning{{values of type 'NSInteger' should not be used as format arguments; add an explicit cast to 'long' instead}}40 printf("%s", getNSUInteger()); // expected-warning{{values of type 'NSUInteger' should not be used as format arguments; add an explicit cast to 'unsigned long' instead}}41 printf("%s", getSInt32()); // expected-warning{{values of type 'SInt32' should not be used as format arguments; add an explicit cast to 'int' instead}}42 printf("%s", getUInt32()); // expected-warning{{values of type 'UInt32' should not be used as format arguments; add an explicit cast to 'unsigned int' instead}}43 44 // CHECK: fix-it:"{{.*}}":{[[@LINE-5]]:11-[[@LINE-5]]:13}:"%ld"45 // CHECK: fix-it:"{{.*}}":{[[@LINE-6]]:16-[[@LINE-6]]:16}:"(long)"46 47 // CHECK: fix-it:"{{.*}}":{[[@LINE-7]]:11-[[@LINE-7]]:13}:"%lu"48 // CHECK: fix-it:"{{.*}}":{[[@LINE-8]]:16-[[@LINE-8]]:16}:"(unsigned long)"49 50 // CHECK: fix-it:"{{.*}}":{[[@LINE-9]]:11-[[@LINE-9]]:13}:"%d"51 // CHECK: fix-it:"{{.*}}":{[[@LINE-10]]:16-[[@LINE-10]]:16}:"(int)"52 53 // CHECK: fix-it:"{{.*}}":{[[@LINE-11]]:11-[[@LINE-11]]:13}:"%u"54 // CHECK: fix-it:"{{.*}}":{[[@LINE-12]]:16-[[@LINE-12]]:16}:"(unsigned int)"55 56 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}}57 58 // CHECK: fix-it:"{{.*}}":{[[@LINE-2]]:11-[[@LINE-2]]:13}:"%ld"59 // CHECK: fix-it:"{{.*}}":{[[@LINE-3]]:16-[[@LINE-3]]:16}:"(long)"60 61 printf("%s", getCFIndex()); // expected-warning{{values of type 'CFIndex' should not be used as format arguments; add an explicit cast to 'long' instead}}62 63 // CHECK: fix-it:"{{.*}}":{[[@LINE-2]]:11-[[@LINE-2]]:13}:"%ld"64 // CHECK: fix-it:"{{.*}}":{[[@LINE-3]]:16-[[@LINE-3]]:16}:"(long)"65}66 67@interface Foo {68@public69 NSInteger _value;70}71- (NSInteger)getInteger;72 73@property NSInteger value;74@end75 76struct Bar {77 NSInteger value;78};79 80 81void testParens(Foo *obj, struct Bar *record) {82 NSInteger arr[4] = {0};83 NSInteger i = 0;84 85 // These cases match the relevant cases in CheckPrintfHandler::checkFormatExpr.86 printf("%s", arr[0]); // expected-warning{{values of type 'NSInteger' should not be used as format arguments; add an explicit cast to 'long' instead}}87 printf("%s", getNSInteger()); // expected-warning{{values of type 'NSInteger' should not be used as format arguments; add an explicit cast to 'long' instead}}88 printf("%s", i); // expected-warning{{values of type 'NSInteger' should not be used as format arguments; add an explicit cast to 'long' instead}}89 printf("%s", obj->_value); // expected-warning{{values of type 'NSInteger' should not be used as format arguments; add an explicit cast to 'long' instead}}90 printf("%s", [obj getInteger]); // expected-warning{{values of type 'NSInteger' should not be used as format arguments; add an explicit cast to 'long' instead}}91 printf("%s", obj.value); // expected-warning{{values of type 'NSInteger' should not be used as format arguments; add an explicit cast to 'long' instead}}92 printf("%s", record->value); // expected-warning{{values of type 'NSInteger' should not be used as format arguments; add an explicit cast to 'long' instead}}93 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}}94 printf("%s", *arr); // expected-warning{{values of type 'NSInteger' should not be used as format arguments; add an explicit cast to 'long' instead}}95 96 // CHECK-NOT: fix-it:{{.*}}:")"97 98 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}}99 100 // CHECK: fix-it:"{{.*}}":{[[@LINE-2]]:11-[[@LINE-2]]:13}:"%ld"101 // CHECK: fix-it:"{{.*}}":{[[@LINE-3]]:16-[[@LINE-3]]:16}:"(long)("102 // CHECK: fix-it:"{{.*}}":{[[@LINE-4]]:25-[[@LINE-4]]:25}:")"103}104 105 106#if __LP64__107 108void testWarn(void) {109 printf("%d", getNSInteger()); // expected-warning{{values of type 'NSInteger' should not be used as format arguments; add an explicit cast to 'long' instead}}110 printf("%u", getNSUInteger()); // expected-warning{{values of type 'NSUInteger' should not be used as format arguments; add an explicit cast to 'unsigned long' instead}}111 printf("%ld", getSInt32()); // expected-warning{{values of type 'SInt32' should not be used as format arguments; add an explicit cast to 'int' instead}}112 printf("%lu", getUInt32()); // expected-warning{{values of type 'UInt32' should not be used as format arguments; add an explicit cast to 'unsigned int' instead}}113 114 // CHECK-64: fix-it:"{{.*}}":{[[@LINE-5]]:11-[[@LINE-5]]:13}:"%ld"115 // CHECK-64: fix-it:"{{.*}}":{[[@LINE-6]]:16-[[@LINE-6]]:16}:"(long)"116 117 // CHECK-64: fix-it:"{{.*}}":{[[@LINE-7]]:11-[[@LINE-7]]:13}:"%lu"118 // CHECK-64: fix-it:"{{.*}}":{[[@LINE-8]]:16-[[@LINE-8]]:16}:"(unsigned long)"119 120 // CHECK-64: fix-it:"{{.*}}":{[[@LINE-9]]:11-[[@LINE-9]]:14}:"%d"121 // CHECK-64: fix-it:"{{.*}}":{[[@LINE-10]]:17-[[@LINE-10]]:17}:"(int)"122 123 // CHECK-64: fix-it:"{{.*}}":{[[@LINE-11]]:11-[[@LINE-11]]:14}:"%u"124 // CHECK-64: fix-it:"{{.*}}":{[[@LINE-12]]:17-[[@LINE-12]]:17}:"(unsigned int)"125 126 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}}127 128 // CHECK-64: fix-it:"{{.*}}":{[[@LINE-2]]:11-[[@LINE-2]]:13}:"%ld"129 // CHECK-64: fix-it:"{{.*}}":{[[@LINE-3]]:16-[[@LINE-3]]:16}:"(long)"130 131 printf("%d", getCFIndex()); // expected-warning{{values of type 'CFIndex' should not be used as format arguments; add an explicit cast to 'long' instead}}132 133 // CHECK-64: fix-it:"{{.*}}":{[[@LINE-2]]:11-[[@LINE-2]]:13}:"%ld"134 // CHECK-64: fix-it:"{{.*}}":{[[@LINE-3]]:16-[[@LINE-3]]:16}:"(long)"135}136 137void testPreserveHex(void) {138 printf("%x", getNSInteger()); // expected-warning{{values of type 'NSInteger' should not be used as format arguments; add an explicit cast to 'long' instead}}139 printf("%x", getNSUInteger()); // expected-warning{{values of type 'NSUInteger' should not be used as format arguments; add an explicit cast to 'unsigned long' instead}}140 141 // CHECK-64: fix-it:"{{.*}}":{[[@LINE-3]]:11-[[@LINE-3]]:13}:"%lx"142 // CHECK-64: fix-it:"{{.*}}":{[[@LINE-4]]:16-[[@LINE-4]]:16}:"(long)"143 144 // CHECK-64: fix-it:"{{.*}}":{[[@LINE-5]]:11-[[@LINE-5]]:13}:"%lx"145 // CHECK-64: fix-it:"{{.*}}":{[[@LINE-6]]:16-[[@LINE-6]]:16}:"(unsigned long)"146}147 148void testSignedness(NSInteger i, NSUInteger u) {149 printf("%d", u); // expected-warning{{values of type 'NSUInteger' should not be used as format arguments; add an explicit cast to 'unsigned long' instead}}150 printf("%i", u); // expected-warning{{values of type 'NSUInteger' should not be used as format arguments; add an explicit cast to 'unsigned long' instead}}151 printf("%u", i); // expected-warning{{values of type 'NSInteger' should not be used as format arguments; add an explicit cast to 'long' instead}}152 153 // CHECK-64: fix-it:"{{.*}}":{[[@LINE-4]]:11-[[@LINE-4]]:13}:"%lu"154 // CHECK-64: fix-it:"{{.*}}":{[[@LINE-4]]:11-[[@LINE-4]]:13}:"%lu"155 // CHECK-64: fix-it:"{{.*}}":{[[@LINE-4]]:11-[[@LINE-4]]:13}:"%ld"156}157 158void testNoWarn(void) {159 printf("%ld", getNSInteger()); // no-warning160 printf("%lu", getNSUInteger()); // no-warning161 printf("%d", getSInt32()); // no-warning162 printf("%u", getUInt32()); // no-warning163 printf("%ld", getNSIntegerEnum()); // no-warning164}165 166#else167 168void testWarn(void) {169 printf("%ld", getNSInteger()); // expected-warning{{values of type 'NSInteger' should not be used as format arguments; add an explicit cast to 'long' instead}}170 printf("%lu", getNSUInteger()); // expected-warning{{values of type 'NSUInteger' should not be used as format arguments; add an explicit cast to 'unsigned long' instead}}171 printf("%d", getSInt32()); // expected-warning{{values of type 'SInt32' should not be used as format arguments; add an explicit cast to 'int' instead}}172 printf("%u", getUInt32()); // expected-warning{{values of type 'UInt32' should not be used as format arguments; add an explicit cast to 'unsigned int' instead}}173 174 // CHECK-32: fix-it:"{{.*}}":{[[@LINE-5]]:17-[[@LINE-5]]:17}:"(long)"175 // CHECK-32: fix-it:"{{.*}}":{[[@LINE-5]]:17-[[@LINE-5]]:17}:"(unsigned long)"176 // CHECK-32: fix-it:"{{.*}}":{[[@LINE-5]]:16-[[@LINE-5]]:16}:"(int)"177 // CHECK-32: fix-it:"{{.*}}":{[[@LINE-5]]:16-[[@LINE-5]]:16}:"(unsigned int)"178 179 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}}180 181 // CHECK-32: fix-it:"{{.*}}":{[[@LINE-2]]:17-[[@LINE-2]]:17}:"(long)"182 183 printf("%ld", getCFIndex()); // expected-warning{{values of type 'CFIndex' should not be used as format arguments; add an explicit cast to 'long' instead}}184 185 // CHECK-32: fix-it:"{{.*}}":{[[@LINE-2]]:17-[[@LINE-2]]:17}:"(long)"186}187 188void testPreserveHex(void) {189 printf("%lx", getNSInteger()); // expected-warning{{values of type 'NSInteger' should not be used as format arguments; add an explicit cast to 'long' instead}}190 printf("%lx", getNSUInteger()); // expected-warning{{values of type 'NSUInteger' should not be used as format arguments; add an explicit cast to 'unsigned long' instead}}191 192 // CHECK-32: fix-it:"{{.*}}":{[[@LINE-3]]:17-[[@LINE-3]]:17}:"(long)"193 // CHECK-32: fix-it:"{{.*}}":{[[@LINE-3]]:17-[[@LINE-3]]:17}:"(unsigned long)"194}195 196void testNoWarn(void) {197 printf("%d", getNSInteger()); // no-warning198 printf("%u", getNSUInteger()); // no-warning199 printf("%ld", getSInt32()); // no-warning200 printf("%lu", getUInt32()); // no-warning201 printf("%d", getNSIntegerEnum()); // no-warning202}203 204void testSignedness(NSInteger i, NSUInteger u) {205 // It is valid to use a specifier with the opposite signedness as long as206 // the type is correct.207 printf("%d", u); // no-warning208 printf("%i", u); // no-warning209 printf("%u", i); // no-warning210}211 212#endif213 214 215void testCasts(void) {216 printf("%s", (NSInteger)0); // expected-warning{{values of type 'NSInteger' should not be used as format arguments; add an explicit cast to 'long' instead}}217 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}}218 printf("%s", (SInt32)0); // expected-warning{{values of type 'SInt32' should not be used as format arguments; add an explicit cast to 'int' instead}}219 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}}220 221 // CHECK: fix-it:"{{.*}}":{[[@LINE-5]]:11-[[@LINE-5]]:13}:"%ld"222 // CHECK: fix-it:"{{.*}}":{[[@LINE-6]]:16-[[@LINE-6]]:27}:"(long)"223 224 // CHECK: fix-it:"{{.*}}":{[[@LINE-7]]:11-[[@LINE-7]]:13}:"%lu"225 // CHECK: fix-it:"{{.*}}":{[[@LINE-8]]:16-[[@LINE-8]]:28}:"(unsigned long)"226 227 // CHECK: fix-it:"{{.*}}":{[[@LINE-9]]:11-[[@LINE-9]]:13}:"%d"228 // CHECK: fix-it:"{{.*}}":{[[@LINE-10]]:16-[[@LINE-10]]:24}:"(int)"229 230 // CHECK: fix-it:"{{.*}}":{[[@LINE-11]]:11-[[@LINE-11]]:13}:"%u"231 // CHECK: fix-it:"{{.*}}":{[[@LINE-12]]:16-[[@LINE-12]]:24}:"(unsigned int)"232 233 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}}234 235 // CHECK: fix-it:"{{.*}}":{[[@LINE-2]]:11-[[@LINE-2]]:13}:"%ld"236 // CHECK: fix-it:"{{.*}}":{[[@LINE-3]]:16-[[@LINE-3]]:31}:"(long)"237 238 printf("%s", (CFIndex)0); // expected-warning{{values of type 'CFIndex' should not be used as format arguments; add an explicit cast to 'long' instead}}239 240 // CHECK: fix-it:"{{.*}}":{[[@LINE-2]]:11-[[@LINE-2]]:13}:"%ld"241 // CHECK: fix-it:"{{.*}}":{[[@LINE-3]]:16-[[@LINE-3]]:25}:"(long)"242}243 244void testCapitals(void) {245 printf("%D", 1); // expected-warning{{conversion specifier is not supported by ISO C}} expected-note {{did you mean to use 'd'?}}246 printf("%U", 1); // expected-warning{{conversion specifier is not supported by ISO C}} expected-note {{did you mean to use 'u'?}}247 printf("%O", 1); // expected-warning{{conversion specifier is not supported by ISO C}} expected-note {{did you mean to use 'o'?}}248 249 // CHECK: fix-it:"{{.*}}":{[[@LINE-4]]:12-[[@LINE-4]]:13}:"d"250 // CHECK: fix-it:"{{.*}}":{[[@LINE-4]]:12-[[@LINE-4]]:13}:"u"251 // CHECK: fix-it:"{{.*}}":{[[@LINE-4]]:12-[[@LINE-4]]:13}:"o"252 253 254 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'}}255 256 // FIXME: offering two somewhat-conflicting fixits is less than ideal.257 // CHECK: fix-it:"{{.*}}":{[[@LINE-3]]:13-[[@LINE-3]]:14}:"d"258 // CHECK: fix-it:"{{.*}}":{[[@LINE-4]]:11-[[@LINE-4]]:14}:"%D"259}260 261void testLayeredTypedefs(OSStatus i) {262 printf("%s", i); // expected-warning {{values of type 'OSStatus' should not be used as format arguments}}263 // CHECK: fix-it:"{{.*}}":{[[@LINE-1]]:11-[[@LINE-1]]:13}:"%d"264}265 266