xref: /llvm-project/clang/test/Sema/format-strings-signedness.c (revision ea92b1f9d0fc31f1fd97ad04eb0412003a37cb0d)
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