| // RUN: %clang_cc1 -ffixed-point -fsyntax-only -verify -Wformat -isystem %S/Inputs %s |
| // RUN: %clang_cc1 -fsyntax-only -verify -Wformat -isystem %S/Inputs %s -DWITHOUT_FIXED_POINT |
| |
| int printf(const char *restrict, ...); |
| |
| short s; |
| unsigned short us; |
| int i; |
| unsigned int ui; |
| long l; |
| unsigned long ul; |
| float fl; |
| double d; |
| char c; |
| unsigned char uc; |
| |
| #ifndef WITHOUT_FIXED_POINT |
| short _Fract sf; |
| _Fract f; |
| long _Fract lf; |
| unsigned short _Fract usf; |
| unsigned _Fract uf; |
| unsigned long _Fract ulf; |
| short _Accum sa; |
| _Accum a; |
| long _Accum la; |
| unsigned short _Accum usa; |
| unsigned _Accum ua; |
| unsigned long _Accum ula; |
| _Sat short _Fract sat_sf; |
| _Sat _Fract sat_f; |
| _Sat long _Fract sat_lf; |
| _Sat unsigned short _Fract sat_usf; |
| _Sat unsigned _Fract sat_uf; |
| _Sat unsigned long _Fract sat_ulf; |
| _Sat short _Accum sat_sa; |
| _Sat _Accum sat_a; |
| _Sat long _Accum sat_la; |
| _Sat unsigned short _Accum sat_usa; |
| _Sat unsigned _Accum sat_ua; |
| _Sat unsigned long _Accum sat_ula; |
| |
| void test_invalid_args(void) { |
| /// None of these should match against a fixed point type. |
| printf("%r", s); // expected-warning{{format specifies type '_Fract' but the argument has type 'short'}} |
| printf("%r", us); // expected-warning{{format specifies type '_Fract' but the argument has type 'unsigned short'}} |
| printf("%r", i); // expected-warning{{format specifies type '_Fract' but the argument has type 'int'}} |
| printf("%r", ui); // expected-warning{{format specifies type '_Fract' but the argument has type 'unsigned int'}} |
| printf("%r", l); // expected-warning{{format specifies type '_Fract' but the argument has type 'long'}} |
| printf("%r", ul); // expected-warning{{format specifies type '_Fract' but the argument has type 'unsigned long'}} |
| printf("%r", fl); // expected-warning{{format specifies type '_Fract' but the argument has type 'float'}} |
| printf("%r", d); // expected-warning{{format specifies type '_Fract' but the argument has type 'double'}} |
| printf("%r", c); // expected-warning{{format specifies type '_Fract' but the argument has type 'char'}} |
| printf("%r", uc); // expected-warning{{format specifies type '_Fract' but the argument has type 'unsigned char'}} |
| } |
| |
| void test_fixed_point_specifiers(void) { |
| printf("%r", f); |
| printf("%R", uf); |
| printf("%k", a); |
| printf("%K", ua); |
| |
| /// Test different sizes. |
| printf("%r", sf); // expected-warning{{format specifies type '_Fract' but the argument has type 'short _Fract'}} |
| printf("%r", lf); // expected-warning{{format specifies type '_Fract' but the argument has type 'long _Fract'}} |
| printf("%R", usf); // expected-warning{{format specifies type 'unsigned _Fract' but the argument has type 'unsigned short _Fract'}} |
| printf("%R", ulf); // expected-warning{{format specifies type 'unsigned _Fract' but the argument has type 'unsigned long _Fract'}} |
| printf("%k", sa); // expected-warning{{format specifies type '_Accum' but the argument has type 'short _Accum'}} |
| printf("%k", la); // expected-warning{{format specifies type '_Accum' but the argument has type 'long _Accum'}} |
| printf("%K", usa); // expected-warning{{format specifies type 'unsigned _Accum' but the argument has type 'unsigned short _Accum'}} |
| printf("%K", ula); // expected-warning{{format specifies type 'unsigned _Accum' but the argument has type 'unsigned long _Accum'}} |
| |
| /// Test signs. |
| printf("%r", uf); // expected-warning{{format specifies type '_Fract' but the argument has type 'unsigned _Fract'}} |
| printf("%R", f); // expected-warning{{format specifies type 'unsigned _Fract' but the argument has type '_Fract'}} |
| printf("%k", ua); // expected-warning{{format specifies type '_Accum' but the argument has type 'unsigned _Accum'}} |
| printf("%K", a); // expected-warning{{format specifies type 'unsigned _Accum' but the argument has type '_Accum'}} |
| |
| /// Test between types. |
| printf("%r", a); // expected-warning{{format specifies type '_Fract' but the argument has type '_Accum'}} |
| printf("%R", ua); // expected-warning{{format specifies type 'unsigned _Fract' but the argument has type 'unsigned _Accum'}} |
| printf("%k", f); // expected-warning{{format specifies type '_Accum' but the argument has type '_Fract'}} |
| printf("%K", uf); // expected-warning{{format specifies type 'unsigned _Accum' but the argument has type 'unsigned _Fract'}} |
| |
| /// Test saturated types. |
| printf("%r", sat_f); |
| printf("%R", sat_uf); |
| printf("%k", sat_a); |
| printf("%K", sat_ua); |
| } |
| |
| void test_length_modifiers_and_flags(void) { |
| printf("%hr", sf); |
| printf("%lr", lf); |
| printf("%hR", usf); |
| printf("%lR", ulf); |
| printf("%hk", sa); |
| printf("%lk", la); |
| printf("%hK", usa); |
| printf("%lK", ula); |
| |
| printf("%hr", sat_sf); |
| printf("%lr", sat_lf); |
| printf("%hR", sat_usf); |
| printf("%lR", sat_ulf); |
| printf("%hk", sat_sa); |
| printf("%lk", sat_la); |
| printf("%hK", sat_usa); |
| printf("%lK", sat_ula); |
| |
| printf("%10r", f); |
| printf("%10.10r", f); |
| printf("%010r", f); |
| printf("%-10r", f); |
| printf("%.10r", f); |
| printf("%+r", f); |
| printf("% r", f); |
| printf("%#r", f); |
| printf("%#.r", f); |
| printf("%#.0r", f); |
| |
| /// Test some invalid length modifiers. |
| printf("%zr", f); // expected-warning{{length modifier 'z' results in undefined behavior or no effect with 'r' conversion specifier}} |
| printf("%llr", f); // expected-warning{{length modifier 'll' results in undefined behavior or no effect with 'r' conversion specifier}} |
| printf("%hhr", f); // expected-warning{{length modifier 'hh' results in undefined behavior or no effect with 'r' conversion specifier}} |
| |
| // + on an unsigned fixed point type. |
| printf("%+hR", usf); // expected-warning{{flag '+' results in undefined behavior with 'R' conversion specifier}} |
| printf("%+R", uf); // expected-warning{{flag '+' results in undefined behavior with 'R' conversion specifier}} |
| printf("%+lR", ulf); // expected-warning{{flag '+' results in undefined behavior with 'R' conversion specifier}} |
| printf("%+hK", usa); // expected-warning{{flag '+' results in undefined behavior with 'K' conversion specifier}} |
| printf("%+K", ua); // expected-warning{{flag '+' results in undefined behavior with 'K' conversion specifier}} |
| printf("%+lK", ula); // expected-warning{{flag '+' results in undefined behavior with 'K' conversion specifier}} |
| printf("% hR", usf); // expected-warning{{flag ' ' results in undefined behavior with 'R' conversion specifier}} |
| printf("% R", uf); // expected-warning{{flag ' ' results in undefined behavior with 'R' conversion specifier}} |
| printf("% lR", ulf); // expected-warning{{flag ' ' results in undefined behavior with 'R' conversion specifier}} |
| printf("% hK", usa); // expected-warning{{flag ' ' results in undefined behavior with 'K' conversion specifier}} |
| printf("% K", ua); // expected-warning{{flag ' ' results in undefined behavior with 'K' conversion specifier}} |
| printf("% lK", ula); // expected-warning{{flag ' ' results in undefined behavior with 'K' conversion specifier}} |
| } |
| #else |
| void test_fixed_point_specifiers_no_printf() { |
| printf("%k", i); // expected-warning{{invalid conversion specifier 'k'}} |
| printf("%K", i); // expected-warning{{invalid conversion specifier 'K'}} |
| printf("%r", i); // expected-warning{{invalid conversion specifier 'r'}} |
| printf("%R", i); // expected-warning{{invalid conversion specifier 'R'}} |
| } |
| #endif // WITHOUT_FIXED_POINT |