xref: /llvm-project/clang/test/Sema/format-fixed-point.c (revision 40ba1f60e9f4b186d71272d4bc23b5af6204244d)
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