xref: /aosp_15_r20/external/clang/test/FixIt/format.m (revision 67e74705e28f6214e480b399dd47ea732279e315)
1*67e74705SXin Li// RUN: %clang_cc1 -triple %itanium_abi_triple -fsyntax-only -fblocks -verify %s
2*67e74705SXin Li// RUN: %clang_cc1 -triple %itanium_abi_triple -fdiagnostics-parseable-fixits -fblocks %s 2>&1 | FileCheck %s
3*67e74705SXin Li
4*67e74705SXin Li@class NSString;
5*67e74705SXin Liextern void NSLog(NSString *, ...);
6*67e74705SXin Liint printf(const char * restrict, ...) ;
7*67e74705SXin Li
8*67e74705SXin Livoid test_integer_correction (int x) {
9*67e74705SXin Li  printf("%d", x); // no-warning
10*67e74705SXin Li  printf("%s", x); // expected-warning{{format specifies type 'char *' but the argument has type 'int'}}
11*67e74705SXin Li  printf("%lf", x); // expected-warning{{format specifies type 'double' but the argument has type 'int'}}
12*67e74705SXin Li  // CHECK: fix-it:"{{.*}}":{10:11-10:13}:"%d"
13*67e74705SXin Li  // CHECK: fix-it:"{{.*}}":{11:11-11:14}:"%d"
14*67e74705SXin Li
15*67e74705SXin Li  NSLog(@"%d", x); // no-warning
16*67e74705SXin Li  NSLog(@"%s", x); // expected-warning{{format specifies type 'char *' but the argument has type 'int'}}
17*67e74705SXin Li  NSLog(@"%lf", x); // expected-warning{{format specifies type 'double' but the argument has type 'int'}}
18*67e74705SXin Li  NSLog(@"%@", x); // expected-warning{{format specifies type 'id' but the argument has type 'int'}}
19*67e74705SXin Li  // CHECK: fix-it:"{{.*}}":{16:11-16:13}:"%d"
20*67e74705SXin Li  // CHECK: fix-it:"{{.*}}":{17:11-17:14}:"%d"
21*67e74705SXin Li  // CHECK: fix-it:"{{.*}}":{18:11-18:13}:"%d"
22*67e74705SXin Li}
23*67e74705SXin Li
24*67e74705SXin Livoid test_string_correction (char *x) {
25*67e74705SXin Li  printf("%d", x); // expected-warning{{format specifies type 'int' but the argument has type 'char *'}}
26*67e74705SXin Li  printf("%s", x); // no-warning
27*67e74705SXin Li  printf("%lf", x); // expected-warning{{format specifies type 'double' but the argument has type 'char *'}}
28*67e74705SXin Li  // CHECK: fix-it:"{{.*}}":{25:11-25:13}:"%s"
29*67e74705SXin Li  // CHECK: fix-it:"{{.*}}":{27:11-27:14}:"%s"
30*67e74705SXin Li
31*67e74705SXin Li  NSLog(@"%d", x); // expected-warning{{format specifies type 'int' but the argument has type 'char *'}}
32*67e74705SXin Li  NSLog(@"%s", x); // no-warning
33*67e74705SXin Li  NSLog(@"%lf", x); // expected-warning{{format specifies type 'double' but the argument has type 'char *'}}
34*67e74705SXin Li  NSLog(@"%@", x); // expected-warning{{format specifies type 'id' but the argument has type 'char *'}}
35*67e74705SXin Li  // CHECK: fix-it:"{{.*}}":{31:11-31:13}:"%s"
36*67e74705SXin Li  // CHECK: fix-it:"{{.*}}":{33:11-33:14}:"%s"
37*67e74705SXin Li  // CHECK: fix-it:"{{.*}}":{34:11-34:13}:"%s"
38*67e74705SXin Li}
39*67e74705SXin Li
40*67e74705SXin Livoid test_object_correction (id x) {
41*67e74705SXin Li  NSLog(@"%d", x); // expected-warning{{format specifies type 'int' but the argument has type 'id'}}
42*67e74705SXin Li  NSLog(@"%s", x); // expected-warning{{format specifies type 'char *' but the argument has type 'id'}}
43*67e74705SXin Li  NSLog(@"%lf", x); // expected-warning{{format specifies type 'double' but the argument has type 'id'}}
44*67e74705SXin Li  NSLog(@"%@", x); // no-warning
45*67e74705SXin Li  // CHECK: fix-it:"{{.*}}":{41:11-41:13}:"%@"
46*67e74705SXin Li  // CHECK: fix-it:"{{.*}}":{42:11-42:13}:"%@"
47*67e74705SXin Li  // CHECK: fix-it:"{{.*}}":{43:11-43:14}:"%@"
48*67e74705SXin Li}
49*67e74705SXin Li
50*67e74705SXin Litypedef const struct __CFString * __attribute__((NSObject)) CFStringRef;
51*67e74705SXin Livoid test_cf_object_correction (CFStringRef x) {
52*67e74705SXin Li  NSLog(@"%d", x); // expected-warning{{format specifies type 'int' but the argument has type 'CFStringRef'}}
53*67e74705SXin Li  NSLog(@"%s", x); // expected-warning{{format specifies type 'char *' but the argument has type 'CFStringRef'}}
54*67e74705SXin Li  NSLog(@"%lf", x); // expected-warning{{format specifies type 'double' but the argument has type 'CFStringRef'}}
55*67e74705SXin Li  NSLog(@"%@", x); // no-warning
56*67e74705SXin Li  // CHECK: fix-it:"{{.*}}":{52:11-52:13}:"%@"
57*67e74705SXin Li  // CHECK: fix-it:"{{.*}}":{53:11-53:13}:"%@"
58*67e74705SXin Li  // CHECK: fix-it:"{{.*}}":{54:11-54:14}:"%@"
59*67e74705SXin Li}
60*67e74705SXin Li
61*67e74705SXin Litypedef void (^block_t)(void);
62*67e74705SXin Livoid test_block_correction (block_t x) {
63*67e74705SXin Li  NSLog(@"%d", x); // expected-warning{{format specifies type 'int' but the argument has type 'block_t'}}
64*67e74705SXin Li  NSLog(@"%s", x); // expected-warning{{format specifies type 'char *' but the argument has type 'block_t'}}
65*67e74705SXin Li  NSLog(@"%lf", x); // expected-warning{{format specifies type 'double' but the argument has type 'block_t'}}
66*67e74705SXin Li  NSLog(@"%@", x); // no-warning
67*67e74705SXin Li  // CHECK: fix-it:"{{.*}}":{63:11-63:13}:"%@"
68*67e74705SXin Li  // CHECK: fix-it:"{{.*}}":{64:11-64:13}:"%@"
69*67e74705SXin Li  // CHECK: fix-it:"{{.*}}":{65:11-65:14}:"%@"
70*67e74705SXin Li}
71*67e74705SXin Li
72*67e74705SXin Livoid test_class_correction (Class x) {
73*67e74705SXin Li  NSLog(@"%d", x); // expected-warning{{format specifies type 'int' but the argument has type 'Class'}}
74*67e74705SXin Li  NSLog(@"%s", x); // expected-warning{{format specifies type 'char *' but the argument has type 'Class'}}
75*67e74705SXin Li  NSLog(@"%lf", x); // expected-warning{{format specifies type 'double' but the argument has type 'Class'}}
76*67e74705SXin Li  NSLog(@"%@", x); // no-warning
77*67e74705SXin Li  // CHECK: fix-it:"{{.*}}":{73:11-73:13}:"%@"
78*67e74705SXin Li  // CHECK: fix-it:"{{.*}}":{74:11-74:13}:"%@"
79*67e74705SXin Li  // CHECK: fix-it:"{{.*}}":{75:11-75:14}:"%@"
80*67e74705SXin Li}
81*67e74705SXin Li
82*67e74705SXin Li
83*67e74705SXin Litypedef enum : int { NSUTF8StringEncoding = 8 } NSStringEncoding;
84*67e74705SXin Livoid test_fixed_enum_correction(NSStringEncoding x) {
85*67e74705SXin Li  NSLog(@"%@", x); // expected-warning{{format specifies type 'id' but the argument has underlying type 'int'}}
86*67e74705SXin Li  // CHECK: fix-it:"{{.*}}":{85:11-85:13}:"%d"
87*67e74705SXin Li}
88*67e74705SXin Li
89*67e74705SXin Litypedef __SIZE_TYPE__ size_t;
90*67e74705SXin Lienum SomeSize : size_t { IntegerSize = sizeof(int) };
91*67e74705SXin Livoid test_named_fixed_enum_correction(enum SomeSize x) {
92*67e74705SXin Li  NSLog(@"%@", x); // expected-warning{{format specifies type 'id' but the argument has underlying type 'size_t' (aka}}
93*67e74705SXin Li  // CHECK: fix-it:"{{.*}}":{92:11-92:13}:"%zu"
94*67e74705SXin Li}
95*67e74705SXin Li
96*67e74705SXin Li
97*67e74705SXin Litypedef unsigned char uint8_t;
98*67e74705SXin Livoid test_char(char c, signed char s, unsigned char u, uint8_t n) {
99*67e74705SXin Li  NSLog(@"%s", c); // expected-warning{{format specifies type 'char *' but the argument has type 'char'}}
100*67e74705SXin Li  // CHECK: fix-it:"{{.*}}":{[[@LINE-1]]:11-[[@LINE-1]]:13}:"%c"
101*67e74705SXin Li
102*67e74705SXin Li  NSLog(@"%lf", c); // expected-warning{{format specifies type 'double' but the argument has type 'char'}}
103*67e74705SXin Li  // CHECK: fix-it:"{{.*}}":{[[@LINE-1]]:11-[[@LINE-1]]:14}:"%c"
104*67e74705SXin Li
105*67e74705SXin Li  NSLog(@"%@", c); // expected-warning{{format specifies type 'id' but the argument has type 'char'}}
106*67e74705SXin Li  // CHECK: fix-it:"{{.*}}":{[[@LINE-1]]:11-[[@LINE-1]]:13}:"%c"
107*67e74705SXin Li
108*67e74705SXin Li  NSLog(@"%c", c); // no-warning
109*67e74705SXin Li  // CHECK-NOT: fix-it:"{{.*}}":{[[@LINE-1]]:11-[[@LINE-1]]:13}:"%c"
110*67e74705SXin Li
111*67e74705SXin Li
112*67e74705SXin Li  NSLog(@"%s", s); // expected-warning{{format specifies type 'char *' but the argument has type 'signed char'}}
113*67e74705SXin Li  // CHECK: fix-it:"{{.*}}":{[[@LINE-1]]:11-[[@LINE-1]]:13}:"%c"
114*67e74705SXin Li
115*67e74705SXin Li  NSLog(@"%lf", s); // expected-warning{{format specifies type 'double' but the argument has type 'signed char'}}
116*67e74705SXin Li  // CHECK: fix-it:"{{.*}}":{[[@LINE-1]]:11-[[@LINE-1]]:14}:"%c"
117*67e74705SXin Li
118*67e74705SXin Li  NSLog(@"%@", s); // expected-warning{{format specifies type 'id' but the argument has type 'signed char'}}
119*67e74705SXin Li  // CHECK: fix-it:"{{.*}}":{[[@LINE-1]]:11-[[@LINE-1]]:13}:"%c"
120*67e74705SXin Li
121*67e74705SXin Li  NSLog(@"%c", s); // no-warning
122*67e74705SXin Li  // CHECK-NOT: fix-it:"{{.*}}":{[[@LINE-1]]:11-[[@LINE-1]]:13}:"%c"
123*67e74705SXin Li
124*67e74705SXin Li
125*67e74705SXin Li  NSLog(@"%s", u); // expected-warning{{format specifies type 'char *' but the argument has type 'unsigned char'}}
126*67e74705SXin Li  // CHECK: fix-it:"{{.*}}":{[[@LINE-1]]:11-[[@LINE-1]]:13}:"%c"
127*67e74705SXin Li
128*67e74705SXin Li  NSLog(@"%lf", u); // expected-warning{{format specifies type 'double' but the argument has type 'unsigned char'}}
129*67e74705SXin Li  // CHECK: fix-it:"{{.*}}":{[[@LINE-1]]:11-[[@LINE-1]]:14}:"%c"
130*67e74705SXin Li
131*67e74705SXin Li  NSLog(@"%@", u); // expected-warning{{format specifies type 'id' but the argument has type 'unsigned char'}}
132*67e74705SXin Li  // CHECK: fix-it:"{{.*}}":{[[@LINE-1]]:11-[[@LINE-1]]:13}:"%c"
133*67e74705SXin Li
134*67e74705SXin Li  NSLog(@"%c", u); // no-warning
135*67e74705SXin Li  // CHECK-NOT: fix-it:"{{.*}}":{[[@LINE-1]]:11-[[@LINE-1]]:13}:"%c"
136*67e74705SXin Li
137*67e74705SXin Li
138*67e74705SXin Li  NSLog(@"%s", n); // expected-warning{{format specifies type 'char *' but the argument has type 'uint8_t' (aka 'unsigned char')}}
139*67e74705SXin Li  // CHECK: fix-it:"{{.*}}":{[[@LINE-1]]:11-[[@LINE-1]]:13}:"%hhu"
140*67e74705SXin Li
141*67e74705SXin Li  NSLog(@"%lf", n); // expected-warning{{format specifies type 'double' but the argument has type 'uint8_t' (aka 'unsigned char')}}
142*67e74705SXin Li  // CHECK: fix-it:"{{.*}}":{[[@LINE-1]]:11-[[@LINE-1]]:14}:"%hhu"
143*67e74705SXin Li
144*67e74705SXin Li  NSLog(@"%@", n); // expected-warning{{format specifies type 'id' but the argument has type 'uint8_t' (aka 'unsigned char')}}
145*67e74705SXin Li  // CHECK: fix-it:"{{.*}}":{[[@LINE-1]]:11-[[@LINE-1]]:13}:"%hhu"
146*67e74705SXin Li
147*67e74705SXin Li  NSLog(@"%c", n); // no-warning
148*67e74705SXin Li  // CHECK-NOT: fix-it:"{{.*}}":{[[@LINE-1]]:11-[[@LINE-1]]:13}:"%hhu"
149*67e74705SXin Li
150*67e74705SXin Li
151*67e74705SXin Li  NSLog(@"%s", 'a'); // expected-warning{{format specifies type 'char *' but the argument has type 'char'}}
152*67e74705SXin Li  // CHECK: fix-it:"{{.*}}":{[[@LINE-1]]:11-[[@LINE-1]]:13}:"%c"
153*67e74705SXin Li
154*67e74705SXin Li  NSLog(@"%lf", 'a'); // expected-warning{{format specifies type 'double' but the argument has type 'char'}}
155*67e74705SXin Li  // CHECK: fix-it:"{{.*}}":{[[@LINE-1]]:11-[[@LINE-1]]:14}:"%c"
156*67e74705SXin Li
157*67e74705SXin Li  NSLog(@"%@", 'a'); // expected-warning{{format specifies type 'id' but the argument has type 'char'}}
158*67e74705SXin Li  // CHECK: fix-it:"{{.*}}":{[[@LINE-1]]:11-[[@LINE-1]]:13}:"%c"
159*67e74705SXin Li
160*67e74705SXin Li  NSLog(@"%c", 'a'); // no-warning
161*67e74705SXin Li  // CHECK-NOT: fix-it:"{{.*}}":{[[@LINE-1]]:11-[[@LINE-1]]:13}:"%c"
162*67e74705SXin Li
163*67e74705SXin Li
164*67e74705SXin Li  NSLog(@"%s", 'abcd'); // expected-warning{{format specifies type 'char *' but the argument has type 'int'}}
165*67e74705SXin Li  // CHECK: fix-it:"{{.*}}":{[[@LINE-1]]:11-[[@LINE-1]]:13}:"%d"
166*67e74705SXin Li
167*67e74705SXin Li  NSLog(@"%lf", 'abcd'); // expected-warning{{format specifies type 'double' but the argument has type 'int'}}
168*67e74705SXin Li  // CHECK: fix-it:"{{.*}}":{[[@LINE-1]]:11-[[@LINE-1]]:14}:"%d"
169*67e74705SXin Li
170*67e74705SXin Li  NSLog(@"%@", 'abcd'); // expected-warning{{format specifies type 'id' but the argument has type 'int'}}
171*67e74705SXin Li  // CHECK: fix-it:"{{.*}}":{[[@LINE-1]]:11-[[@LINE-1]]:13}:"%d"
172*67e74705SXin Li}
173*67e74705SXin Li
174*67e74705SXin Livoid multichar_constants_false_negative() {
175*67e74705SXin Li  // The value of a multi-character constant is implementation-defined, but
176*67e74705SXin Li  // almost certainly shouldn't be printed with %c. However, the current
177*67e74705SXin Li  // type-checker expects %c to correspond to an integer argument, because
178*67e74705SXin Li  // many C library functions like fgetc() actually return an int (using -1
179*67e74705SXin Li  // as a sentinel).
180*67e74705SXin Li  NSLog(@"%c", 'abcd'); // missing-warning{{format specifies type 'char' but the argument has type 'int'}}
181*67e74705SXin Li  // CHECK-NOT: fix-it:"{{.*}}":{[[@LINE-1]]:11-[[@LINE-1]]:13}:"%d"
182*67e74705SXin Li}
183*67e74705SXin Li
184*67e74705SXin Li
185*67e74705SXin Livoid test_percent_C() {
186*67e74705SXin Li  const unsigned short data = 'a';
187*67e74705SXin Li  NSLog(@"%C", data);  // no-warning
188*67e74705SXin Li
189*67e74705SXin Li  NSLog(@"%C", 0x260300);  // expected-warning{{format specifies type 'unichar' (aka 'unsigned short') but the argument has type 'int'}}
190*67e74705SXin Li  // CHECK-NOT: fix-it:"{{.*}}":{[[@LINE-1]]:11-[[@LINE-1]]:13}:"%d"
191*67e74705SXin Li  // CHECK: fix-it:"{{.*}}":{[[@LINE-2]]:16-[[@LINE-2]]:16}:"(unsigned short)"
192*67e74705SXin Li
193*67e74705SXin Li  typedef unsigned short unichar;
194*67e74705SXin Li
195*67e74705SXin Li  NSLog(@"%C", 0x260300);  // expected-warning{{format specifies type 'unichar' (aka 'unsigned short') but the argument has type 'int'}}
196*67e74705SXin Li  // CHECK-NOT: fix-it:"{{.*}}":{[[@LINE-1]]:11-[[@LINE-1]]:13}:"%d"
197*67e74705SXin Li  // CHECK: fix-it:"{{.*}}":{[[@LINE-2]]:16-[[@LINE-2]]:16}:"(unichar)"
198*67e74705SXin Li
199*67e74705SXin Li  NSLog(@"%C", data ? 0x2F0000 : 0x260300); // expected-warning{{format specifies type 'unichar' (aka 'unsigned short') but the argument has type 'int'}}
200*67e74705SXin Li  // CHECK-NOT: fix-it:"{{.*}}":{[[@LINE-1]]:11-[[@LINE-1]]:13}:"%d"
201*67e74705SXin Li  // CHECK: fix-it:"{{.*}}":{[[@LINE-2]]:16-[[@LINE-2]]:16}:"(unichar)("
202*67e74705SXin Li  // CHECK: fix-it:"{{.*}}":{[[@LINE-3]]:42-[[@LINE-3]]:42}:")"
203*67e74705SXin Li
204*67e74705SXin Li  NSLog(@"%C", 0.0); // expected-warning{{format specifies type 'unichar' (aka 'unsigned short') but the argument has type 'double'}}
205*67e74705SXin Li  // CHECK: fix-it:"{{.*}}":{[[@LINE-1]]:11-[[@LINE-1]]:13}:"%f"
206*67e74705SXin Li  // CHECK-NOT: fix-it:"{{.*}}":{[[@LINE-2]]:16-[[@LINE-2]]:16}:"(unichar)"
207*67e74705SXin Li
208*67e74705SXin Li  NSLog(@"%C", (char)0x260300); // expected-warning{{format specifies type 'unichar' (aka 'unsigned short') but the argument has type 'char'}}
209*67e74705SXin Li  // CHECK: fix-it:"{{.*}}":{[[@LINE-1]]:11-[[@LINE-1]]:13}:"%c"
210*67e74705SXin Li  // CHECK-NOT: fix-it:"{{.*}}":{[[@LINE-2]]:16-[[@LINE-2]]:22}:"(unichar)"
211*67e74705SXin Li
212*67e74705SXin Li  NSLog(@"%C", 'a'); // expected-warning{{format specifies type 'unichar' (aka 'unsigned short') but the argument has type 'char'}}
213*67e74705SXin Li  // CHECK: fix-it:"{{.*}}":{[[@LINE-1]]:11-[[@LINE-1]]:13}:"%c"
214*67e74705SXin Li  // CHECK-NOT: fix-it:"{{.*}}":{[[@LINE-2]]:16-[[@LINE-2]]:22}:"(unichar)"
215*67e74705SXin Li}
216*67e74705SXin Li
217*67e74705SXin Li
218*67e74705SXin Livoid testSignedness(long i, unsigned long u) {
219*67e74705SXin Li  printf("%d", u); // expected-warning{{format specifies type 'int' but the argument has type 'unsigned long'}}
220*67e74705SXin Li  printf("%i", u); // expected-warning{{format specifies type 'int' but the argument has type 'unsigned long'}}
221*67e74705SXin Li  printf("%u", i); // expected-warning{{format specifies type 'unsigned int' but the argument has type 'long'}}
222*67e74705SXin Li
223*67e74705SXin Li  // CHECK: fix-it:"{{.*}}":{[[@LINE-4]]:11-[[@LINE-4]]:13}:"%lu"
224*67e74705SXin Li  // CHECK: fix-it:"{{.*}}":{[[@LINE-4]]:11-[[@LINE-4]]:13}:"%lu"
225*67e74705SXin Li  // CHECK: fix-it:"{{.*}}":{[[@LINE-4]]:11-[[@LINE-4]]:13}:"%ld"
226*67e74705SXin Li
227*67e74705SXin Li  printf("%+d", u); // expected-warning{{format specifies type 'int' but the argument has type 'unsigned long'}}
228*67e74705SXin Li
229*67e74705SXin Li  // CHECK: fix-it:"{{.*}}":{[[@LINE-2]]:11-[[@LINE-2]]:14}:"%+ld"
230*67e74705SXin Li}
231*67e74705SXin Li
232*67e74705SXin Livoid testEnum() {
233*67e74705SXin Li  typedef enum {
234*67e74705SXin Li    ImplicitA = 1,
235*67e74705SXin Li    ImplicitB = 2
236*67e74705SXin Li  } Implicit;
237*67e74705SXin Li
238*67e74705SXin Li  typedef enum {
239*67e74705SXin Li    ImplicitLLA = 0,
240*67e74705SXin Li    ImplicitLLB = ~0ULL
241*67e74705SXin Li  } ImplicitLongLong;
242*67e74705SXin Li
243*67e74705SXin Li  typedef enum : short {
244*67e74705SXin Li    ExplicitA = 0,
245*67e74705SXin Li    ExplicitB
246*67e74705SXin Li  } ExplicitShort;
247*67e74705SXin Li
248*67e74705SXin Li  printf("%f", (Implicit)0); // expected-warning{{format specifies type 'double' but the argument has underlying type}}
249*67e74705SXin Li  // CHECK: fix-it:"{{.*}}":{[[@LINE-1]]:11-[[@LINE-1]]:13}:"%{{[du]}}"
250*67e74705SXin Li
251*67e74705SXin Li  printf("%f", (ImplicitLongLong)0); // expected-warning{{format specifies type 'double' but the argument has underlying type}}
252*67e74705SXin Li  // CHECK: fix-it:"{{.*}}":{[[@LINE-1]]:11-[[@LINE-1]]:13}:"%{{l*[du]}}"
253*67e74705SXin Li
254*67e74705SXin Li  printf("%f", (ExplicitShort)0); // expected-warning{{format specifies type 'double' but the argument has underlying type 'short'}}
255*67e74705SXin Li  // CHECK: fix-it:"{{.*}}":{[[@LINE-1]]:11-[[@LINE-1]]:13}:"%hd"
256*67e74705SXin Li}
257