/* { dg-options "-Wformat -fdiagnostics-show-caret" } */ #include "format.h" /* Various format tests, some containing type mismatches. Verify that for the type mismatch cases that we offer "good" suggestions. Specifically, any suggestions should preserve flags characters, field width and precision, and, if possible, the conversion specifier character, whilst giving a corrected length modifier appropriate to the argument type. */ /* Tests of "x" without a length modifier, with various param types. Suggestions should preserve the "x" for integer arguments. */ void test_x (char *d, int iexpr, unsigned int uiexpr, long lexpr, unsigned long ulexpr, long long llexpr, unsigned long long ullexpr, float fexpr, double dexpr, long double ldexpr, void *ptr) { /* Integer arguments. */ sprintf (d, " %-8x ", iexpr); sprintf (d, " %-8x ", uiexpr); sprintf (d, " %-8x ", lexpr); /* { dg-warning "20: format '%x' expects argument of type 'unsigned int', but argument 3 has type 'long int'" } */ /* { dg-begin-multiline-output "" } sprintf (d, " %-8x ", lexpr); ~~~^ ~~~~~ | | | long int unsigned int %-8lx { dg-end-multiline-output "" } */ sprintf (d, " %-8x ", ulexpr); /* { dg-warning "20: format '%x' expects argument of type 'unsigned int', but argument 3 has type 'long unsigned int'" } */ /* { dg-begin-multiline-output "" } sprintf (d, " %-8x ", ulexpr); ~~~^ ~~~~~~ | | | long unsigned int unsigned int %-8lx { dg-end-multiline-output "" } */ sprintf (d, " %-8x ", llexpr); /* { dg-warning "20: format '%x' expects argument of type 'unsigned int', but argument 3 has type 'long long int'" } */ /* { dg-begin-multiline-output "" } sprintf (d, " %-8x ", llexpr); ~~~^ ~~~~~~ | | | long long int unsigned int %-8llx { dg-end-multiline-output "" } */ sprintf (d, " %-8x ", ullexpr); /* { dg-warning "20: format '%x' expects argument of type 'unsigned int', but argument 3 has type 'long long unsigned int'" } */ /* { dg-begin-multiline-output "" } sprintf (d, " %-8x ", ullexpr); ~~~^ ~~~~~~~ | | | long long unsigned int unsigned int %-8llx { dg-end-multiline-output "" } */ /* Floating-point arguments. */ sprintf (d, " %-8x ", fexpr); /* { dg-warning "20: format '%x' expects argument of type 'unsigned int', but argument 3 has type 'double'" } */ /* { dg-begin-multiline-output "" } sprintf (d, " %-8x ", fexpr); ~~~^ ~~~~~ | | | double unsigned int %-8f { dg-end-multiline-output "" } */ sprintf (d, " %-8x ", dexpr); /* { dg-warning "20: format '%x' expects argument of type 'unsigned int', but argument 3 has type 'double'" } */ /* { dg-begin-multiline-output "" } sprintf (d, " %-8x ", dexpr); ~~~^ ~~~~~ | | | double unsigned int %-8f { dg-end-multiline-output "" } */ sprintf (d, " %-8x ", ldexpr); /* { dg-warning "20: format '%x' expects argument of type 'unsigned int', but argument 3 has type 'long double'" } */ /* { dg-begin-multiline-output "" } sprintf (d, " %-8x ", ldexpr); ~~~^ ~~~~~~ | | | long double unsigned int %-8Lf { dg-end-multiline-output "" } */ /* Pointer. */ sprintf (d, " %-8x ", ptr); /* { dg-warning "20: format '%x' expects argument of type 'unsigned int', but argument 3 has type 'void \\*'" } */ /* { dg-begin-multiline-output "" } sprintf (d, " %-8x ", ptr); ~~~^ ~~~ | | | void * unsigned int %-8p { dg-end-multiline-output "" } */ /* Something unrecognized. */ struct s { int i; }; struct s s; sprintf (d, " %-8x ", s); /* { dg-warning "20: format '%x' expects argument of type 'unsigned int', but argument 3 has type 'struct s'" } */ /* { dg-begin-multiline-output "" } sprintf (d, " %-8x ", s); ~~~^ ~ | | | struct s unsigned int { dg-end-multiline-output "" } */ } /* Tests of "x" with "l", with various param types. Suggestions should preserve the "x" for integer arguments. */ void test_lx (char *d, int iexpr, unsigned int uiexpr, long lexpr, unsigned long ulexpr, long long llexpr, unsigned long long ullexpr, float fexpr, double dexpr, long double ldexpr) { /* Integer arguments. */ sprintf (d, " %-8lx ", iexpr); /* { dg-warning "21: format '%lx' expects argument of type 'long unsigned int', but argument 3 has type 'int'" } */ /* { dg-begin-multiline-output "" } sprintf (d, " %-8lx ", iexpr); ~~~~^ ~~~~~ | | | int long unsigned int %-8x { dg-end-multiline-output "" } */ sprintf (d, " %-8lx ", uiexpr); /* { dg-warning "21: format '%lx' expects argument of type 'long unsigned int', but argument 3 has type 'unsigned int'" } */ /* { dg-begin-multiline-output "" } sprintf (d, " %-8lx ", uiexpr); ~~~~^ ~~~~~~ | | | unsigned int long unsigned int %-8x { dg-end-multiline-output "" } */ sprintf (d, " %-8lx ", lexpr); sprintf (d, " %-8lx ", ulexpr); sprintf (d, " %-8lx ", llexpr); /* { dg-warning "21: format '%lx' expects argument of type 'long unsigned int', but argument 3 has type 'long long int'" } */ /* { dg-begin-multiline-output "" } sprintf (d, " %-8lx ", llexpr); ~~~~^ ~~~~~~ | | | long long int long unsigned int %-8llx { dg-end-multiline-output "" } */ sprintf (d, " %-8lx ", ullexpr); /* { dg-warning "21: format '%lx' expects argument of type 'long unsigned int', but argument 3 has type 'long long unsigned int'" } */ /* { dg-begin-multiline-output "" } sprintf (d, " %-8lx ", ullexpr); ~~~~^ ~~~~~~~ | | | long long unsigned int long unsigned int %-8llx { dg-end-multiline-output "" } */ /* Floating-point arguments. */ sprintf (d, " %-8lx ", fexpr); /* { dg-warning "21: format '%lx' expects argument of type 'long unsigned int', but argument 3 has type 'double'" } */ /* { dg-begin-multiline-output "" } sprintf (d, " %-8lx ", fexpr); ~~~~^ ~~~~~ | | | double long unsigned int %-8f { dg-end-multiline-output "" } */ sprintf (d, " %-8lx ", dexpr); /* { dg-warning "21: format '%lx' expects argument of type 'long unsigned int', but argument 3 has type 'double'" } */ /* { dg-begin-multiline-output "" } sprintf (d, " %-8lx ", dexpr); ~~~~^ ~~~~~ | | | double long unsigned int %-8f { dg-end-multiline-output "" } */ sprintf (d, " %-8lx ", ldexpr); /* { dg-warning "21: format '%lx' expects argument of type 'long unsigned int', but argument 3 has type 'long double'" } */ /* { dg-begin-multiline-output "" } sprintf (d, " %-8lx ", ldexpr); ~~~~^ ~~~~~~ | | | long double long unsigned int %-8Lf { dg-end-multiline-output "" } */ } /* Tests of "o" without a length modifier, with various param types. Suggestions should preserve the "o" for integer arguments. */ void test_o (char *d, int iexpr, unsigned int uiexpr, long lexpr, unsigned long ulexpr, long long llexpr, unsigned long long ullexpr) { /* Integer arguments. */ sprintf (d, " %-8o ", iexpr); sprintf (d, " %-8o ", uiexpr); sprintf (d, " %-8o ", lexpr); /* { dg-warning "20: format '%o' expects argument of type 'unsigned int', but argument 3 has type 'long int'" } */ /* { dg-begin-multiline-output "" } sprintf (d, " %-8o ", lexpr); ~~~^ ~~~~~ | | | long int unsigned int %-8lo { dg-end-multiline-output "" } */ sprintf (d, " %-8o ", ulexpr); /* { dg-warning "20: format '%o' expects argument of type 'unsigned int', but argument 3 has type 'long unsigned int'" } */ /* { dg-begin-multiline-output "" } sprintf (d, " %-8o ", ulexpr); ~~~^ ~~~~~~ | | | long unsigned int unsigned int %-8lo { dg-end-multiline-output "" } */ sprintf (d, " %-8o ", llexpr); /* { dg-warning "20: format '%o' expects argument of type 'unsigned int', but argument 3 has type 'long long int'" } */ /* { dg-begin-multiline-output "" } sprintf (d, " %-8o ", llexpr); ~~~^ ~~~~~~ | | | long long int unsigned int %-8llo { dg-end-multiline-output "" } */ sprintf (d, " %-8o ", ullexpr); /* { dg-warning "20: format '%o' expects argument of type 'unsigned int', but argument 3 has type 'long long unsigned int'" } */ /* { dg-begin-multiline-output "" } sprintf (d, " %-8o ", ullexpr); ~~~^ ~~~~~~~ | | | long long unsigned int unsigned int %-8llo { dg-end-multiline-output "" } */ } /* Tests of "o" with "l", with various param types. Suggestions should preserve the "o" for integer arguments. */ void test_lo (char *d, int iexpr, unsigned int uiexpr, long lexpr, unsigned long ulexpr, long long llexpr, unsigned long long ullexpr) { /* Integer arguments. */ sprintf (d, " %-8lo ", iexpr); /* { dg-warning "21: format '%lo' expects argument of type 'long unsigned int', but argument 3 has type 'int'" } */ /* { dg-begin-multiline-output "" } sprintf (d, " %-8lo ", iexpr); ~~~~^ ~~~~~ | | | int long unsigned int %-8o { dg-end-multiline-output "" } */ sprintf (d, " %-8lo ", uiexpr); /* { dg-warning "21: format '%lo' expects argument of type 'long unsigned int', but argument 3 has type 'unsigned int'" } */ /* { dg-begin-multiline-output "" } sprintf (d, " %-8lo ", uiexpr); ~~~~^ ~~~~~~ | | | unsigned int long unsigned int %-8o { dg-end-multiline-output "" } */ sprintf (d, " %-8lo ", lexpr); sprintf (d, " %-8lo ", ulexpr); sprintf (d, " %-8lo ", llexpr); /* { dg-warning "21: format '%lo' expects argument of type 'long unsigned int', but argument 3 has type 'long long int'" } */ /* { dg-begin-multiline-output "" } sprintf (d, " %-8lo ", llexpr); ~~~~^ ~~~~~~ | | | long long int long unsigned int %-8llo { dg-end-multiline-output "" } */ sprintf (d, " %-8lo ", ullexpr); /* { dg-warning "21: format '%lo' expects argument of type 'long unsigned int', but argument 3 has type 'long long unsigned int'" } */ /* { dg-begin-multiline-output "" } sprintf (d, " %-8lo ", ullexpr); ~~~~^ ~~~~~~~ | | | long long unsigned int long unsigned int %-8llo { dg-end-multiline-output "" } */ } /* Tests of "e" without a length modifier, with various param types. Suggestions should preserve the "e" for float arguments. */ void test_e (char *d, int iexpr, float fexpr, double dexpr, long double ldexpr) { /* Integer arguments. */ sprintf (d, " %-8e ", iexpr); /* { dg-warning "20: format '%e' expects argument of type 'double', but argument 3 has type 'int'" } */ /* { dg-begin-multiline-output "" } sprintf (d, " %-8e ", iexpr); ~~~^ ~~~~~ | | | int double %-8d { dg-end-multiline-output "" } */ /* Floating-point arguments. */ sprintf (d, " %-8e ", fexpr); sprintf (d, " %-8e ", dexpr); sprintf (d, " %-8e ", ldexpr); /* { dg-warning "20: format '%e' expects argument of type 'double', but argument 3 has type 'long double'" } */ /* { dg-begin-multiline-output "" } sprintf (d, " %-8e ", ldexpr); ~~~^ ~~~~~~ | | | long double double %-8Le { dg-end-multiline-output "" } */ } /* Tests of "e" with "L", with various param types. Suggestions should preserve the "e" for float arguments. */ void test_Le (char *d, int iexpr, float fexpr, double dexpr, long double ldexpr) { /* Integer arguments. */ sprintf (d, " %-8Le ", iexpr); /* { dg-warning "21: format '%Le' expects argument of type 'long double', but argument 3 has type 'int'" } */ /* { dg-begin-multiline-output "" } sprintf (d, " %-8Le ", iexpr); ~~~~^ ~~~~~ | | | int long double %-8d { dg-end-multiline-output "" } */ /* Floating-point arguments. */ sprintf (d, " %-8Le ", fexpr); /* { dg-warning "21: format '%Le' expects argument of type 'long double', but argument 3 has type 'double'" } */ /* { dg-begin-multiline-output "" } sprintf (d, " %-8Le ", fexpr); ~~~~^ ~~~~~ | | | double long double %-8e { dg-end-multiline-output "" } */ sprintf (d, " %-8Le ", dexpr); /* { dg-warning "21: format '%Le' expects argument of type 'long double', but argument 3 has type 'double'" } */ /* { dg-begin-multiline-output "" } sprintf (d, " %-8Le ", dexpr); ~~~~^ ~~~~~ | | | double long double %-8e { dg-end-multiline-output "" } */ sprintf (d, " %-8Le ", ldexpr); } /* Tests of "E" without a length modifier, with various param types. Suggestions should preserve the "E" for floating-point arguments. */ void test_E (char *d, int iexpr, float fexpr, double dexpr, long double ldexpr) { /* Integer arguments. */ sprintf (d, " %-8E ", iexpr); /* { dg-warning "20: format '%E' expects argument of type 'double', but argument 3 has type 'int'" } */ /* { dg-begin-multiline-output "" } sprintf (d, " %-8E ", iexpr); ~~~^ ~~~~~ | | | int double %-8d { dg-end-multiline-output "" } */ /* Floating-point arguments. */ sprintf (d, " %-8E ", fexpr); sprintf (d, " %-8E ", dexpr); sprintf (d, " %-8E ", ldexpr); /* { dg-warning "20: format '%E' expects argument of type 'double', but argument 3 has type 'long double'" } */ /* { dg-begin-multiline-output "" } sprintf (d, " %-8E ", ldexpr); ~~~^ ~~~~~~ | | | long double double %-8LE { dg-end-multiline-output "" } */ } /* Tests of "E" with "L", with various param types. Suggestions should preserve the "E" for floating-point arguments. */ void test_LE (char *d, int iexpr, float fexpr, double dexpr, long double ldexpr) { /* Integer arguments. */ sprintf (d, " %-8LE ", iexpr); /* { dg-warning "21: format '%LE' expects argument of type 'long double', but argument 3 has type 'int'" } */ /* { dg-begin-multiline-output "" } sprintf (d, " %-8LE ", iexpr); ~~~~^ ~~~~~ | | | int long double %-8d { dg-end-multiline-output "" } */ sprintf (d, " %-8LE ", fexpr); /* { dg-warning "21: format '%LE' expects argument of type 'long double', but argument 3 has type 'double'" } */ /* { dg-begin-multiline-output "" } sprintf (d, " %-8LE ", fexpr); ~~~~^ ~~~~~ | | | double long double %-8E { dg-end-multiline-output "" } */ sprintf (d, " %-8LE ", dexpr); /* { dg-warning "21: format '%LE' expects argument of type 'long double', but argument 3 has type 'double'" } */ /* { dg-begin-multiline-output "" } sprintf (d, " %-8LE ", dexpr); ~~~~^ ~~~~~ | | | double long double %-8E { dg-end-multiline-output "" } */ sprintf (d, " %-8LE ", ldexpr); } /* Test of a suggestion for a conversion specification containing all features (flags, width, precision, length modifier), where all the other arguments have mismatching types. */ void test_everything (char *d, long lexpr) { sprintf (d, "before %-+*.*lld after", lexpr, lexpr, lexpr); /* { dg-line test_everything_sprintf } */ /* { dg-warning "26: field width specifier '\\*' expects argument of type 'int', but argument 3 has type 'long int'" "" { target *-*-* } test_everything_sprintf } */ /* { dg-begin-multiline-output "" } sprintf (d, "before %-+*.*lld after", lexpr, lexpr, lexpr); ~~~^~~~~~ ~~~~~ | | int long int { dg-end-multiline-output "" } */ /* { dg-warning "28: field precision specifier '\\.\\*' expects argument of type 'int', but argument 4 has type 'long int'" "" { target *-*-* } test_everything_sprintf } */ /* { dg-begin-multiline-output "" } sprintf (d, "before %-+*.*lld after", lexpr, lexpr, lexpr); ~~~~~^~~~ ~~~~~ | | int long int { dg-end-multiline-output "" } */ /* { dg-warning "31: format '%lld' expects argument of type 'long long int', but argument 5 has type 'long int'" "" { target *-*-* } test_everything_sprintf } */ /* { dg-begin-multiline-output "" } sprintf (d, "before %-+*.*lld after", lexpr, lexpr, lexpr); ~~~~~~~~^ ~~~~~ | | long long int long int %-+*.*ld { dg-end-multiline-output "" } */ }