1 // RUN: %clang_cc1 -ffixed-point -fsyntax-only -verify -Wformat -isystem %S/Inputs %s
2 // RUN: %clang_cc1 -fsyntax-only -verify -Wformat -isystem %S/Inputs %s -DWITHOUT_FIXED_POINT
3
4 int printf(const char *restrict, ...);
5
6 short s;
7 unsigned short us;
8 int i;
9 unsigned int ui;
10 long l;
11 unsigned long ul;
12 float fl;
13 double d;
14 char c;
15 unsigned char uc;
16
17 #ifndef WITHOUT_FIXED_POINT
18 short _Fract sf;
19 _Fract f;
20 long _Fract lf;
21 unsigned short _Fract usf;
22 unsigned _Fract uf;
23 unsigned long _Fract ulf;
24 short _Accum sa;
25 _Accum a;
26 long _Accum la;
27 unsigned short _Accum usa;
28 unsigned _Accum ua;
29 unsigned long _Accum ula;
30 _Sat short _Fract sat_sf;
31 _Sat _Fract sat_f;
32 _Sat long _Fract sat_lf;
33 _Sat unsigned short _Fract sat_usf;
34 _Sat unsigned _Fract sat_uf;
35 _Sat unsigned long _Fract sat_ulf;
36 _Sat short _Accum sat_sa;
37 _Sat _Accum sat_a;
38 _Sat long _Accum sat_la;
39 _Sat unsigned short _Accum sat_usa;
40 _Sat unsigned _Accum sat_ua;
41 _Sat unsigned long _Accum sat_ula;
42
test_invalid_args(void)43 void test_invalid_args(void) {
44 /// None of these should match against a fixed point type.
45 printf("%r", s); // expected-warning{{format specifies type '_Fract' but the argument has type 'short'}}
46 printf("%r", us); // expected-warning{{format specifies type '_Fract' but the argument has type 'unsigned short'}}
47 printf("%r", i); // expected-warning{{format specifies type '_Fract' but the argument has type 'int'}}
48 printf("%r", ui); // expected-warning{{format specifies type '_Fract' but the argument has type 'unsigned int'}}
49 printf("%r", l); // expected-warning{{format specifies type '_Fract' but the argument has type 'long'}}
50 printf("%r", ul); // expected-warning{{format specifies type '_Fract' but the argument has type 'unsigned long'}}
51 printf("%r", fl); // expected-warning{{format specifies type '_Fract' but the argument has type 'float'}}
52 printf("%r", d); // expected-warning{{format specifies type '_Fract' but the argument has type 'double'}}
53 printf("%r", c); // expected-warning{{format specifies type '_Fract' but the argument has type 'char'}}
54 printf("%r", uc); // expected-warning{{format specifies type '_Fract' but the argument has type 'unsigned char'}}
55 }
56
test_fixed_point_specifiers(void)57 void test_fixed_point_specifiers(void) {
58 printf("%r", f);
59 printf("%R", uf);
60 printf("%k", a);
61 printf("%K", ua);
62
63 /// Test different sizes.
64 printf("%r", sf); // expected-warning{{format specifies type '_Fract' but the argument has type 'short _Fract'}}
65 printf("%r", lf); // expected-warning{{format specifies type '_Fract' but the argument has type 'long _Fract'}}
66 printf("%R", usf); // expected-warning{{format specifies type 'unsigned _Fract' but the argument has type 'unsigned short _Fract'}}
67 printf("%R", ulf); // expected-warning{{format specifies type 'unsigned _Fract' but the argument has type 'unsigned long _Fract'}}
68 printf("%k", sa); // expected-warning{{format specifies type '_Accum' but the argument has type 'short _Accum'}}
69 printf("%k", la); // expected-warning{{format specifies type '_Accum' but the argument has type 'long _Accum'}}
70 printf("%K", usa); // expected-warning{{format specifies type 'unsigned _Accum' but the argument has type 'unsigned short _Accum'}}
71 printf("%K", ula); // expected-warning{{format specifies type 'unsigned _Accum' but the argument has type 'unsigned long _Accum'}}
72
73 /// Test signs.
74 printf("%r", uf); // expected-warning{{format specifies type '_Fract' but the argument has type 'unsigned _Fract'}}
75 printf("%R", f); // expected-warning{{format specifies type 'unsigned _Fract' but the argument has type '_Fract'}}
76 printf("%k", ua); // expected-warning{{format specifies type '_Accum' but the argument has type 'unsigned _Accum'}}
77 printf("%K", a); // expected-warning{{format specifies type 'unsigned _Accum' but the argument has type '_Accum'}}
78
79 /// Test between types.
80 printf("%r", a); // expected-warning{{format specifies type '_Fract' but the argument has type '_Accum'}}
81 printf("%R", ua); // expected-warning{{format specifies type 'unsigned _Fract' but the argument has type 'unsigned _Accum'}}
82 printf("%k", f); // expected-warning{{format specifies type '_Accum' but the argument has type '_Fract'}}
83 printf("%K", uf); // expected-warning{{format specifies type 'unsigned _Accum' but the argument has type 'unsigned _Fract'}}
84
85 /// Test saturated types.
86 printf("%r", sat_f);
87 printf("%R", sat_uf);
88 printf("%k", sat_a);
89 printf("%K", sat_ua);
90 }
91
test_length_modifiers_and_flags(void)92 void test_length_modifiers_and_flags(void) {
93 printf("%hr", sf);
94 printf("%lr", lf);
95 printf("%hR", usf);
96 printf("%lR", ulf);
97 printf("%hk", sa);
98 printf("%lk", la);
99 printf("%hK", usa);
100 printf("%lK", ula);
101
102 printf("%hr", sat_sf);
103 printf("%lr", sat_lf);
104 printf("%hR", sat_usf);
105 printf("%lR", sat_ulf);
106 printf("%hk", sat_sa);
107 printf("%lk", sat_la);
108 printf("%hK", sat_usa);
109 printf("%lK", sat_ula);
110
111 printf("%10r", f);
112 printf("%10.10r", f);
113 printf("%010r", f);
114 printf("%-10r", f);
115 printf("%.10r", f);
116 printf("%+r", f);
117 printf("% r", f);
118 printf("%#r", f);
119 printf("%#.r", f);
120 printf("%#.0r", f);
121
122 /// Test some invalid length modifiers.
123 printf("%zr", f); // expected-warning{{length modifier 'z' results in undefined behavior or no effect with 'r' conversion specifier}}
124 printf("%llr", f); // expected-warning{{length modifier 'll' results in undefined behavior or no effect with 'r' conversion specifier}}
125 printf("%hhr", f); // expected-warning{{length modifier 'hh' results in undefined behavior or no effect with 'r' conversion specifier}}
126
127 // + on an unsigned fixed point type.
128 printf("%+hR", usf); // expected-warning{{flag '+' results in undefined behavior with 'R' conversion specifier}}
129 printf("%+R", uf); // expected-warning{{flag '+' results in undefined behavior with 'R' conversion specifier}}
130 printf("%+lR", ulf); // expected-warning{{flag '+' results in undefined behavior with 'R' conversion specifier}}
131 printf("%+hK", usa); // expected-warning{{flag '+' results in undefined behavior with 'K' conversion specifier}}
132 printf("%+K", ua); // expected-warning{{flag '+' results in undefined behavior with 'K' conversion specifier}}
133 printf("%+lK", ula); // expected-warning{{flag '+' results in undefined behavior with 'K' conversion specifier}}
134 printf("% hR", usf); // expected-warning{{flag ' ' results in undefined behavior with 'R' conversion specifier}}
135 printf("% R", uf); // expected-warning{{flag ' ' results in undefined behavior with 'R' conversion specifier}}
136 printf("% lR", ulf); // expected-warning{{flag ' ' results in undefined behavior with 'R' conversion specifier}}
137 printf("% hK", usa); // expected-warning{{flag ' ' results in undefined behavior with 'K' conversion specifier}}
138 printf("% K", ua); // expected-warning{{flag ' ' results in undefined behavior with 'K' conversion specifier}}
139 printf("% lK", ula); // expected-warning{{flag ' ' results in undefined behavior with 'K' conversion specifier}}
140 }
141 #else
test_fixed_point_specifiers_no_printf()142 void test_fixed_point_specifiers_no_printf() {
143 printf("%k", i); // expected-warning{{invalid conversion specifier 'k'}}
144 printf("%K", i); // expected-warning{{invalid conversion specifier 'K'}}
145 printf("%r", i); // expected-warning{{invalid conversion specifier 'r'}}
146 printf("%R", i); // expected-warning{{invalid conversion specifier 'R'}}
147 }
148 #endif // WITHOUT_FIXED_POINT
149