1 // RUN: %clang_cc1 -triple=x86_64-pc-linux-gnu -std=c11 -fsyntax-only -verify -Wformat -Wformat-signedness %s
2 // RUN: %clang_cc1 -triple=x86_64-pc-win32 -std=c11 -fsyntax-only -verify -Wformat -Wformat-signedness %s
3
4 // Verify that -Wformat-signedness alone (without -Wformat) trigger the
5 // warnings. Note in gcc this will not trigger the signedness warnings as
6 // -Wformat is default off in gcc.
7 // RUN: %clang_cc1 -triple=x86_64-pc-linux-gnu -std=c11 -fsyntax-only -verify -Wformat-signedness %s
8 // RUN: %clang_cc1 -triple=x86_64-pc-win32 -std=c11 -fsyntax-only -verify -Wformat-signedness %s
9
10 // Verify that -Wformat-signedness warnings are not reported with only -Wformat
11 // (gcc compat).
12 // RUN: %clang_cc1 -triple=x86_64-pc-linux-gnu -std=c11 -fsyntax-only -Wformat -verify=okay %s
13
14 // Verify that -Wformat-signedness with -Wno-format are not reported (gcc compat).
15 // RUN: %clang_cc1 -triple=x86_64-pc-linux-gnu -std=c11 -fsyntax-only -Wformat-signedness -Wno-format -verify=okay %s
16 // RUN: %clang_cc1 -triple=x86_64-pc-linux-gnu -std=c11 -fsyntax-only -Wno-format -Wformat-signedness -verify=okay %s
17 // okay-no-diagnostics
18
19 int printf(const char *restrict format, ...);
20 int scanf(const char * restrict, ...);
21
test_printf_bool(_Bool x)22 void test_printf_bool(_Bool x)
23 {
24 printf("%d", x); // no-warning
25 printf("%u", x); // no-warning
26 printf("%x", x); // no-warning
27 }
28
test_printf_char(char x)29 void test_printf_char(char x)
30 {
31 printf("%c", x); // no-warning
32 }
33
test_printf_unsigned_char(unsigned char x)34 void test_printf_unsigned_char(unsigned char x)
35 {
36 printf("%c", x); // no-warning
37 }
38
test_printf_int(int x)39 void test_printf_int(int x)
40 {
41 printf("%d", x); // no-warning
42 printf("%u", x); // expected-warning{{format specifies type 'unsigned int' but the argument has type 'int'}}
43 printf("%x", x); // expected-warning{{format specifies type 'unsigned int' but the argument has type 'int'}}
44 }
45
test_printf_unsigned(unsigned x)46 void test_printf_unsigned(unsigned x)
47 {
48 printf("%d", x); // expected-warning{{format specifies type 'int' but the argument has type 'unsigned int'}}
49 printf("%u", x); // no-warning
50 printf("%x", x); // no-warning
51 }
52
test_printf_long(long x)53 void test_printf_long(long x)
54 {
55 printf("%ld", x); // no-warning
56 printf("%lu", x); // expected-warning{{format specifies type 'unsigned long' but the argument has type 'long'}}
57 printf("%lx", x); // expected-warning{{format specifies type 'unsigned long' but the argument has type 'long'}}
58 }
59
test_printf_unsigned_long(unsigned long x)60 void test_printf_unsigned_long(unsigned long x)
61 {
62 printf("%ld", x); // expected-warning{{format specifies type 'long' but the argument has type 'unsigned long'}}
63 printf("%lu", x); // no-warning
64 printf("%lx", x); // no-warning
65 }
66
test_printf_long_long(long long x)67 void test_printf_long_long(long long x)
68 {
69 printf("%lld", x); // no-warning
70 printf("%llu", x); // expected-warning{{format specifies type 'unsigned long long' but the argument has type 'long long'}}
71 printf("%llx", x); // expected-warning{{format specifies type 'unsigned long long' but the argument has type 'long long'}}
72 }
73
test_printf_unsigned_long_long(unsigned long long x)74 void test_printf_unsigned_long_long(unsigned long long x)
75 {
76 printf("%lld", x); // expected-warning{{format specifies type 'long long' but the argument has type 'unsigned long long'}}
77 printf("%llu", x); // no-warning
78 printf("%llx", x); // no-warning
79 }
80
81 enum enum_int {
82 minus_1 = -1
83 };
84
test_printf_enum_int(enum enum_int x)85 void test_printf_enum_int(enum enum_int x)
86 {
87 printf("%d", x); // no-warning
88 printf("%u", x); // expected-warning{{format specifies type 'unsigned int' but the argument has underlying type 'int'}}
89 printf("%x", x); // expected-warning{{format specifies type 'unsigned int' but the argument has underlying type 'int'}}
90 }
91
92 #ifndef _WIN32 // Disabled due to enums have different underlying type on _WIN32
93 enum enum_unsigned {
94 zero = 0
95 };
96
test_printf_enum_unsigned(enum enum_unsigned x)97 void test_printf_enum_unsigned(enum enum_unsigned x)
98 {
99 printf("%d", x); // expected-warning{{format specifies type 'int' but the argument has underlying type 'unsigned int'}}
100 printf("%u", x); // no-warning
101 printf("%x", x); // no-warning
102 }
103
104 enum enum_long {
105 minus_one = -1,
106 int_val = __INT_MAX__, // INT_MAX
107 unsigned_val = (unsigned)(-__INT_MAX__ -1) // (unsigned)INT_MIN
108 };
109
test_printf_enum_long(enum enum_long x)110 void test_printf_enum_long(enum enum_long x)
111 {
112 printf("%ld", x); // no-warning
113 printf("%lu", x); // expected-warning{{format specifies type 'unsigned long' but the argument has underlying type 'long'}}
114 printf("%lx", x); // expected-warning{{format specifies type 'unsigned long' but the argument has underlying type 'long'}}
115 }
116
117 enum enum_unsigned_long {
118 uint_max_plus = (unsigned long)(__INT_MAX__ *2U +1U)+1, // (unsigned long)UINT_MAX+1
119 };
120
test_printf_enum_unsigned_long(enum enum_unsigned_long x)121 void test_printf_enum_unsigned_long(enum enum_unsigned_long x)
122 {
123 printf("%ld", x); // expected-warning{{format specifies type 'long' but the argument has underlying type 'unsigned long'}}
124 printf("%lu", x); // no-warning
125 printf("%lx", x); // no-warning
126 }
127 #endif
128
test_scanf_char(char * y)129 void test_scanf_char(char *y) {
130 scanf("%c", y); // no-warning
131 }
132
test_scanf_unsigned_char(unsigned char * y)133 void test_scanf_unsigned_char(unsigned char *y) {
134 scanf("%c", y); // no-warning
135 }
136
test_scanf_int(int * x)137 void test_scanf_int(int *x) {
138 scanf("%d", x); // no-warning
139 scanf("%u", x); // expected-warning{{format specifies type 'unsigned int *' but the argument has type 'int *'}}
140 scanf("%x", x); // expected-warning{{format specifies type 'unsigned int *' but the argument has type 'int *'}}
141 }
142
test_scanf_unsigned(unsigned * x)143 void test_scanf_unsigned(unsigned *x) {
144 scanf("%d", x); // expected-warning{{format specifies type 'int *' but the argument has type 'unsigned int *'}}
145 scanf("%u", x); // no-warning
146 scanf("%x", x); // no-warning
147 }
148
test_scanf_long(long * x)149 void test_scanf_long(long *x) {
150 scanf("%ld", x); // no-warning
151 scanf("%lu", x); // expected-warning{{format specifies type 'unsigned long *' but the argument has type 'long *'}}
152 scanf("%lx", x); // expected-warning{{format specifies type 'unsigned long *' but the argument has type 'long *'}}
153 }
154
test_scanf_unsigned_long(unsigned long * x)155 void test_scanf_unsigned_long(unsigned long *x) {
156 scanf("%ld", x); // expected-warning{{format specifies type 'long *' but the argument has type 'unsigned long *'}}
157 scanf("%lu", x); // no-warning
158 scanf("%lx", x); // no-warning
159 }
160
test_scanf_longlong(long long * x)161 void test_scanf_longlong(long long *x) {
162 scanf("%lld", x); // no-warning
163 scanf("%llu", x); // expected-warning{{format specifies type 'unsigned long long *' but the argument has type 'long long *'}}
164 scanf("%llx", x); // expected-warning{{format specifies type 'unsigned long long *' but the argument has type 'long long *'}}
165 }
166
test_scanf_unsigned_longlong(unsigned long long * x)167 void test_scanf_unsigned_longlong(unsigned long long *x) {
168 scanf("%lld", x); // expected-warning{{format specifies type 'long long *' but the argument has type 'unsigned long long *'}}
169 scanf("%llu", x); // no-warning
170 scanf("%llx", x); // no-warning
171 }
172
test_scanf_enum_int(enum enum_int * x)173 void test_scanf_enum_int(enum enum_int *x) {
174 scanf("%d", x); // no-warning
175 scanf("%u", x); // expected-warning{{format specifies type 'unsigned int *' but the argument has type 'enum enum_int *'}}
176 scanf("%x", x); // expected-warning{{format specifies type 'unsigned int *' but the argument has type 'enum enum_int *'}}
177 }
178
179 #ifndef _WIN32 // Disabled due to enums have different underlying type on _WIN32
test_scanf_enum_unsigned(enum enum_unsigned * x)180 void test_scanf_enum_unsigned(enum enum_unsigned *x) {
181 scanf("%d", x); // expected-warning{{format specifies type 'int *' but the argument has type 'enum enum_unsigned *'}}
182 scanf("%u", x); // no-warning
183 scanf("%x", x); // no-warning
184 }
185
test_scanf_enum_long(enum enum_long * x)186 void test_scanf_enum_long(enum enum_long *x) {
187 scanf("%ld", x); // no-warning
188 scanf("%lu", x); // expected-warning{{format specifies type 'unsigned long *' but the argument has type 'enum enum_long *'}}
189 scanf("%lx", x); // expected-warning{{format specifies type 'unsigned long *' but the argument has type 'enum enum_long *'}}
190 }
191
test_scanf_enum_unsigned_long(enum enum_unsigned_long * x)192 void test_scanf_enum_unsigned_long(enum enum_unsigned_long *x) {
193 scanf("%ld", x); // expected-warning{{format specifies type 'long *' but the argument has type 'enum enum_unsigned_long *'}}
194 scanf("%lu", x); // no-warning
195 scanf("%lx", x); // no-warning
196 }
197 #endif
198
199 // Verify that we get no warnings from <inttypes.h>
200
201 typedef short int int16_t;
202 typedef unsigned short int uint16_t;
203
test_printf_priX16(int16_t x)204 void test_printf_priX16(int16_t x) {
205 printf("PRId16: %" "d" /*PRId16*/ "\n", x); // no-warning
206 printf("PRIi16: %" "i" /*PRIi16*/ "\n", x); // no-warning
207 }
208
test_printf_unsigned_priX16(uint16_t x)209 void test_printf_unsigned_priX16(uint16_t x) {
210 printf("PRIo16: %" "o" /*PRIo16*/ "\n", x); // no-warning
211 printf("PRIu16: %" "u" /*PRIu16*/ "\n", x); // no-warning
212 printf("PRIx16: %" "x" /*PRIx16*/ "\n", x); // no-warning
213 printf("PRIX16: %" "X" /*PRIX16*/ "\n", x); // no-warning
214 }
215
216 // Verify that we can suppress a -Wformat-signedness warning by ignoring
217 // -Wformat (gcc compat).
test_suppress(int x)218 void test_suppress(int x)
219 {
220 #pragma GCC diagnostic ignored "-Wformat"
221 printf("%u", x);
222 }
223