xref: /aosp_15_r20/external/clang/test/FixIt/format-darwin.m (revision 67e74705e28f6214e480b399dd47ea732279e315)
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