(root)/
gcc-13.2.0/
gcc/
testsuite/
gcc.dg/
format/
pr72858.c
       1  /* { dg-options "-Wformat -fdiagnostics-show-caret" } */
       2  
       3  #include "format.h"
       4  
       5  /* Various format tests, some containing type mismatches.  Verify that for
       6     the type mismatch cases that we offer "good" suggestions.  Specifically,
       7     any suggestions should preserve flags characters, field width and precision,
       8     and, if possible, the conversion specifier character, whilst giving a
       9     corrected length modifier appropriate to the argument type.  */
      10  
      11  /* Tests of "x" without a length modifier, with various param types.
      12     Suggestions should preserve the "x" for integer arguments.  */
      13  
      14  void
      15  test_x (char *d,
      16  	int iexpr, unsigned int uiexpr,
      17  	long lexpr, unsigned long ulexpr,
      18  	long long llexpr, unsigned long long ullexpr,
      19  	float fexpr, double dexpr, long double ldexpr,
      20  	void *ptr)
      21  {
      22    /* Integer arguments.  */
      23  
      24    sprintf (d, " %-8x ", iexpr);
      25    sprintf (d, " %-8x ", uiexpr);
      26  
      27    sprintf (d, " %-8x ", lexpr); /* { dg-warning "20: format '%x' expects argument of type 'unsigned int', but argument 3 has type 'long int'" } */
      28  /* { dg-begin-multiline-output "" }
      29     sprintf (d, " %-8x ", lexpr);
      30                   ~~~^    ~~~~~
      31                      |    |
      32                      |    long int
      33                      unsigned int
      34                   %-8lx
      35     { dg-end-multiline-output "" } */
      36    sprintf (d, " %-8x ", ulexpr); /* { dg-warning "20: format '%x' expects argument of type 'unsigned int', but argument 3 has type 'long unsigned int'" } */
      37  /* { dg-begin-multiline-output "" }
      38     sprintf (d, " %-8x ", ulexpr);
      39                   ~~~^    ~~~~~~
      40                      |    |
      41                      |    long unsigned int
      42                      unsigned int
      43                   %-8lx
      44     { dg-end-multiline-output "" } */
      45  
      46    sprintf (d, " %-8x ", llexpr); /* { dg-warning "20: format '%x' expects argument of type 'unsigned int', but argument 3 has type 'long long int'" } */
      47  /* { dg-begin-multiline-output "" }
      48     sprintf (d, " %-8x ", llexpr);
      49                   ~~~^    ~~~~~~
      50                      |    |
      51                      |    long long int
      52                      unsigned int
      53                   %-8llx
      54     { dg-end-multiline-output "" } */
      55    sprintf (d, " %-8x ", ullexpr); /* { dg-warning "20: format '%x' expects argument of type 'unsigned int', but argument 3 has type 'long long unsigned int'" } */
      56  /* { dg-begin-multiline-output "" }
      57     sprintf (d, " %-8x ", ullexpr);
      58                   ~~~^    ~~~~~~~
      59                      |    |
      60                      |    long long unsigned int
      61                      unsigned int
      62                   %-8llx
      63     { dg-end-multiline-output "" } */
      64  
      65    /* Floating-point arguments.  */
      66  
      67    sprintf (d, " %-8x ", fexpr); /* { dg-warning "20: format '%x' expects argument of type 'unsigned int', but argument 3 has type 'double'" } */
      68  /* { dg-begin-multiline-output "" }
      69     sprintf (d, " %-8x ", fexpr);
      70                   ~~~^    ~~~~~
      71                      |    |
      72                      |    double
      73                      unsigned int
      74                   %-8f
      75     { dg-end-multiline-output "" } */
      76    sprintf (d, " %-8x ", dexpr); /* { dg-warning "20: format '%x' expects argument of type 'unsigned int', but argument 3 has type 'double'" } */
      77  /* { dg-begin-multiline-output "" }
      78     sprintf (d, " %-8x ", dexpr);
      79                   ~~~^    ~~~~~
      80                      |    |
      81                      |    double
      82                      unsigned int
      83                   %-8f
      84     { dg-end-multiline-output "" } */
      85    sprintf (d, " %-8x ", ldexpr); /* { dg-warning "20: format '%x' expects argument of type 'unsigned int', but argument 3 has type 'long double'" } */
      86  /* { dg-begin-multiline-output "" }
      87     sprintf (d, " %-8x ", ldexpr);
      88                   ~~~^    ~~~~~~
      89                      |    |
      90                      |    long double
      91                      unsigned int
      92                   %-8Lf
      93     { dg-end-multiline-output "" } */
      94  
      95    /* Pointer.  */
      96    sprintf (d, " %-8x ", ptr); /* { dg-warning "20: format '%x' expects argument of type 'unsigned int', but argument 3 has type 'void \\*'" } */
      97  /* { dg-begin-multiline-output "" }
      98     sprintf (d, " %-8x ", ptr);
      99                   ~~~^    ~~~
     100                      |    |
     101                      |    void *
     102                      unsigned int
     103                   %-8p
     104     { dg-end-multiline-output "" } */
     105  
     106    /* Something unrecognized.  */
     107    struct s { int i; };
     108    struct s s;
     109    sprintf (d, " %-8x ", s); /* { dg-warning "20: format '%x' expects argument of type 'unsigned int', but argument 3 has type 'struct s'" } */
     110  /* { dg-begin-multiline-output "" }
     111     sprintf (d, " %-8x ", s);
     112                   ~~~^    ~
     113                      |    |
     114                      |    struct s
     115                      unsigned int
     116     { dg-end-multiline-output "" } */
     117  }
     118  
     119  /* Tests of "x" with "l", with various param types.
     120     Suggestions should preserve the "x" for integer arguments.  */
     121  
     122  void
     123  test_lx (char *d,
     124  	 int iexpr, unsigned int uiexpr,
     125  	 long lexpr, unsigned long ulexpr,
     126  	 long long llexpr, unsigned long long ullexpr,
     127  	 float fexpr, double dexpr, long double ldexpr)
     128  {
     129    /* Integer arguments.  */
     130  
     131    sprintf (d, " %-8lx ", iexpr); /* { dg-warning "21: format '%lx' expects argument of type 'long unsigned int', but argument 3 has type 'int'" } */
     132  /* { dg-begin-multiline-output "" }
     133     sprintf (d, " %-8lx ", iexpr);
     134                   ~~~~^    ~~~~~
     135                       |    |
     136                       |    int
     137                       long unsigned int
     138                   %-8x
     139     { dg-end-multiline-output "" } */
     140    sprintf (d, " %-8lx ", uiexpr); /* { dg-warning "21: format '%lx' expects argument of type 'long unsigned int', but argument 3 has type 'unsigned int'" } */
     141  /* { dg-begin-multiline-output "" }
     142     sprintf (d, " %-8lx ", uiexpr);
     143                   ~~~~^    ~~~~~~
     144                       |    |
     145                       |    unsigned int
     146                       long unsigned int
     147                   %-8x
     148     { dg-end-multiline-output "" } */
     149  
     150    sprintf (d, " %-8lx ", lexpr);
     151    sprintf (d, " %-8lx ", ulexpr);
     152  
     153    sprintf (d, " %-8lx ", llexpr); /* { dg-warning "21: format '%lx' expects argument of type 'long unsigned int', but argument 3 has type 'long long int'" } */
     154  /* { dg-begin-multiline-output "" }
     155     sprintf (d, " %-8lx ", llexpr);
     156                   ~~~~^    ~~~~~~
     157                       |    |
     158                       |    long long int
     159                       long unsigned int
     160                   %-8llx
     161     { dg-end-multiline-output "" } */
     162    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'" } */
     163  /* { dg-begin-multiline-output "" }
     164     sprintf (d, " %-8lx ", ullexpr);
     165                   ~~~~^    ~~~~~~~
     166                       |    |
     167                       |    long long unsigned int
     168                       long unsigned int
     169                   %-8llx
     170     { dg-end-multiline-output "" } */
     171  
     172    /* Floating-point arguments.  */
     173  
     174    sprintf (d, " %-8lx ", fexpr); /* { dg-warning "21: format '%lx' expects argument of type 'long unsigned int', but argument 3 has type 'double'" } */
     175  /* { dg-begin-multiline-output "" }
     176     sprintf (d, " %-8lx ", fexpr);
     177                   ~~~~^    ~~~~~
     178                       |    |
     179                       |    double
     180                       long unsigned int
     181                   %-8f
     182     { dg-end-multiline-output "" } */
     183    sprintf (d, " %-8lx ", dexpr); /* { dg-warning "21: format '%lx' expects argument of type 'long unsigned int', but argument 3 has type 'double'" } */
     184  /* { dg-begin-multiline-output "" }
     185     sprintf (d, " %-8lx ", dexpr);
     186                   ~~~~^    ~~~~~
     187                       |    |
     188                       |    double
     189                       long unsigned int
     190                   %-8f
     191     { dg-end-multiline-output "" } */
     192    sprintf (d, " %-8lx ", ldexpr); /* { dg-warning "21: format '%lx' expects argument of type 'long unsigned int', but argument 3 has type 'long double'" } */
     193  /* { dg-begin-multiline-output "" }
     194     sprintf (d, " %-8lx ", ldexpr);
     195                   ~~~~^    ~~~~~~
     196                       |    |
     197                       |    long double
     198                       long unsigned int
     199                   %-8Lf
     200     { dg-end-multiline-output "" } */
     201  }
     202  
     203  /* Tests of "o" without a length modifier, with various param types.
     204     Suggestions should preserve the "o" for integer arguments.  */
     205  
     206  void
     207  test_o (char *d,
     208  	int iexpr, unsigned int uiexpr,
     209  	long lexpr, unsigned long ulexpr,
     210  	long long llexpr, unsigned long long ullexpr)
     211  {
     212    /* Integer arguments.  */
     213  
     214    sprintf (d, " %-8o ", iexpr);
     215    sprintf (d, " %-8o ", uiexpr);
     216  
     217    sprintf (d, " %-8o ", lexpr); /* { dg-warning "20: format '%o' expects argument of type 'unsigned int', but argument 3 has type 'long int'" } */
     218  /* { dg-begin-multiline-output "" }
     219     sprintf (d, " %-8o ", lexpr);
     220                   ~~~^    ~~~~~
     221                      |    |
     222                      |    long int
     223                      unsigned int
     224                   %-8lo
     225     { dg-end-multiline-output "" } */
     226    sprintf (d, " %-8o ", ulexpr); /* { dg-warning "20: format '%o' expects argument of type 'unsigned int', but argument 3 has type 'long unsigned int'" } */
     227  /* { dg-begin-multiline-output "" }
     228     sprintf (d, " %-8o ", ulexpr);
     229                   ~~~^    ~~~~~~
     230                      |    |
     231                      |    long unsigned int
     232                      unsigned int
     233                   %-8lo
     234     { dg-end-multiline-output "" } */
     235  
     236    sprintf (d, " %-8o ", llexpr); /* { dg-warning "20: format '%o' expects argument of type 'unsigned int', but argument 3 has type 'long long int'" } */
     237  /* { dg-begin-multiline-output "" }
     238     sprintf (d, " %-8o ", llexpr);
     239                   ~~~^    ~~~~~~
     240                      |    |
     241                      |    long long int
     242                      unsigned int
     243                   %-8llo
     244     { dg-end-multiline-output "" } */
     245    sprintf (d, " %-8o ", ullexpr); /* { dg-warning "20: format '%o' expects argument of type 'unsigned int', but argument 3 has type 'long long unsigned int'" } */
     246  /* { dg-begin-multiline-output "" }
     247     sprintf (d, " %-8o ", ullexpr);
     248                   ~~~^    ~~~~~~~
     249                      |    |
     250                      |    long long unsigned int
     251                      unsigned int
     252                   %-8llo
     253     { dg-end-multiline-output "" } */
     254  }
     255  
     256  /* Tests of "o" with "l", with various param types.
     257     Suggestions should preserve the "o" for integer arguments.  */
     258  
     259  void
     260  test_lo (char *d,
     261  	int iexpr, unsigned int uiexpr,
     262  	long lexpr, unsigned long ulexpr,
     263  	long long llexpr, unsigned long long ullexpr)
     264  {
     265    /* Integer arguments.  */
     266  
     267    sprintf (d, " %-8lo ", iexpr); /* { dg-warning "21: format '%lo' expects argument of type 'long unsigned int', but argument 3 has type 'int'" } */
     268  /* { dg-begin-multiline-output "" }
     269     sprintf (d, " %-8lo ", iexpr);
     270                   ~~~~^    ~~~~~
     271                       |    |
     272                       |    int
     273                       long unsigned int
     274                   %-8o
     275     { dg-end-multiline-output "" } */
     276    sprintf (d, " %-8lo ", uiexpr); /* { dg-warning "21: format '%lo' expects argument of type 'long unsigned int', but argument 3 has type 'unsigned int'" } */
     277  /* { dg-begin-multiline-output "" }
     278     sprintf (d, " %-8lo ", uiexpr);
     279                   ~~~~^    ~~~~~~
     280                       |    |
     281                       |    unsigned int
     282                       long unsigned int
     283                   %-8o
     284     { dg-end-multiline-output "" } */
     285  
     286    sprintf (d, " %-8lo ", lexpr);
     287    sprintf (d, " %-8lo ", ulexpr);
     288  
     289    sprintf (d, " %-8lo ", llexpr); /* { dg-warning "21: format '%lo' expects argument of type 'long unsigned int', but argument 3 has type 'long long int'" } */
     290  /* { dg-begin-multiline-output "" }
     291     sprintf (d, " %-8lo ", llexpr);
     292                   ~~~~^    ~~~~~~
     293                       |    |
     294                       |    long long int
     295                       long unsigned int
     296                   %-8llo
     297     { dg-end-multiline-output "" } */
     298    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'" } */
     299  /* { dg-begin-multiline-output "" }
     300     sprintf (d, " %-8lo ", ullexpr);
     301                   ~~~~^    ~~~~~~~
     302                       |    |
     303                       |    long long unsigned int
     304                       long unsigned int
     305                   %-8llo
     306     { dg-end-multiline-output "" } */
     307  }
     308  
     309  /* Tests of "e" without a length modifier, with various param types.
     310     Suggestions should preserve the "e" for float  arguments.  */
     311  
     312  void
     313  test_e (char *d, int iexpr, float fexpr, double dexpr, long double ldexpr)
     314  {
     315    /* Integer arguments.  */
     316  
     317    sprintf (d, " %-8e ", iexpr); /* { dg-warning "20: format '%e' expects argument of type 'double', but argument 3 has type 'int'" } */
     318  /* { dg-begin-multiline-output "" }
     319     sprintf (d, " %-8e ", iexpr);
     320                   ~~~^    ~~~~~
     321                      |    |
     322                      |    int
     323                      double
     324                   %-8d
     325     { dg-end-multiline-output "" } */
     326  
     327    /* Floating-point arguments.  */
     328  
     329    sprintf (d, " %-8e ", fexpr);
     330    sprintf (d, " %-8e ", dexpr);
     331    sprintf (d, " %-8e ", ldexpr); /* { dg-warning "20: format '%e' expects argument of type 'double', but argument 3 has type 'long double'" } */
     332  /* { dg-begin-multiline-output "" }
     333     sprintf (d, " %-8e ", ldexpr);
     334                   ~~~^    ~~~~~~
     335                      |    |
     336                      |    long double
     337                      double
     338                   %-8Le
     339     { dg-end-multiline-output "" } */
     340  }
     341  
     342  /* Tests of "e" with "L", with various param types.
     343     Suggestions should preserve the "e" for float  arguments.  */
     344  
     345  void
     346  test_Le (char *d, int iexpr, float fexpr, double dexpr, long double ldexpr)
     347  {
     348    /* Integer arguments.  */
     349  
     350    sprintf (d, " %-8Le ", iexpr); /* { dg-warning "21: format '%Le' expects argument of type 'long double', but argument 3 has type 'int'" } */
     351  /* { dg-begin-multiline-output "" }
     352     sprintf (d, " %-8Le ", iexpr);
     353                   ~~~~^    ~~~~~
     354                       |    |
     355                       |    int
     356                       long double
     357                   %-8d
     358     { dg-end-multiline-output "" } */
     359  
     360    /* Floating-point arguments.  */
     361  
     362    sprintf (d, " %-8Le ", fexpr); /* { dg-warning "21: format '%Le' expects argument of type 'long double', but argument 3 has type 'double'" } */
     363  /* { dg-begin-multiline-output "" }
     364     sprintf (d, " %-8Le ", fexpr);
     365                   ~~~~^    ~~~~~
     366                       |    |
     367                       |    double
     368                       long double
     369                   %-8e
     370     { dg-end-multiline-output "" } */
     371  
     372    sprintf (d, " %-8Le ", dexpr); /* { dg-warning "21: format '%Le' expects argument of type 'long double', but argument 3 has type 'double'" } */
     373  /* { dg-begin-multiline-output "" }
     374     sprintf (d, " %-8Le ", dexpr);
     375                   ~~~~^    ~~~~~
     376                       |    |
     377                       |    double
     378                       long double
     379                   %-8e
     380     { dg-end-multiline-output "" } */
     381  
     382    sprintf (d, " %-8Le ", ldexpr);
     383  }
     384  
     385  /* Tests of "E" without a length modifier, with various param types.
     386     Suggestions should preserve the "E" for floating-point arguments.  */
     387  
     388  void
     389  test_E (char *d, int iexpr, float fexpr, double dexpr, long double ldexpr)
     390  {
     391    /* Integer arguments.  */
     392  
     393    sprintf (d, " %-8E ", iexpr); /* { dg-warning "20: format '%E' expects argument of type 'double', but argument 3 has type 'int'" } */
     394  /* { dg-begin-multiline-output "" }
     395     sprintf (d, " %-8E ", iexpr);
     396                   ~~~^    ~~~~~
     397                      |    |
     398                      |    int
     399                      double
     400                   %-8d
     401     { dg-end-multiline-output "" } */
     402  
     403    /* Floating-point arguments.  */
     404  
     405    sprintf (d, " %-8E ", fexpr);
     406    sprintf (d, " %-8E ", dexpr);
     407    sprintf (d, " %-8E ", ldexpr); /* { dg-warning "20: format '%E' expects argument of type 'double', but argument 3 has type 'long double'" } */
     408  /* { dg-begin-multiline-output "" }
     409     sprintf (d, " %-8E ", ldexpr);
     410                   ~~~^    ~~~~~~
     411                      |    |
     412                      |    long double
     413                      double
     414                   %-8LE
     415     { dg-end-multiline-output "" } */
     416  }
     417  
     418  /* Tests of "E" with "L", with various param types.
     419     Suggestions should preserve the "E" for floating-point arguments.  */
     420  
     421  void
     422  test_LE (char *d, int iexpr, float fexpr, double dexpr, long double ldexpr)
     423  {
     424    /* Integer arguments.  */
     425  
     426    sprintf (d, " %-8LE ", iexpr); /* { dg-warning "21: format '%LE' expects argument of type 'long double', but argument 3 has type 'int'" } */
     427  /* { dg-begin-multiline-output "" }
     428     sprintf (d, " %-8LE ", iexpr);
     429                   ~~~~^    ~~~~~
     430                       |    |
     431                       |    int
     432                       long double
     433                   %-8d
     434     { dg-end-multiline-output "" } */
     435  
     436    sprintf (d, " %-8LE ", fexpr); /* { dg-warning "21: format '%LE' expects argument of type 'long double', but argument 3 has type 'double'" } */
     437  /* { dg-begin-multiline-output "" }
     438     sprintf (d, " %-8LE ", fexpr);
     439                   ~~~~^    ~~~~~
     440                       |    |
     441                       |    double
     442                       long double
     443                   %-8E
     444     { dg-end-multiline-output "" } */
     445  
     446    sprintf (d, " %-8LE ", dexpr); /* { dg-warning "21: format '%LE' expects argument of type 'long double', but argument 3 has type 'double'" } */
     447  /* { dg-begin-multiline-output "" }
     448     sprintf (d, " %-8LE ", dexpr);
     449                   ~~~~^    ~~~~~
     450                       |    |
     451                       |    double
     452                       long double
     453                   %-8E
     454     { dg-end-multiline-output "" } */
     455  
     456    sprintf (d, " %-8LE ", ldexpr);
     457  }
     458  
     459  /* Test of a suggestion for a conversion specification containing
     460     all features (flags, width, precision, length modifier), where
     461     all the other arguments have mismatching types.  */
     462  
     463  void
     464  test_everything (char *d, long lexpr)
     465  {
     466    sprintf (d, "before %-+*.*lld after", lexpr, lexpr, lexpr); /* { dg-line test_everything_sprintf } */
     467  
     468    /* { dg-warning "26: field width specifier '\\*' expects argument of type 'int', but argument 3 has type 'long int'" "" { target *-*-* } test_everything_sprintf } */
     469    /* { dg-begin-multiline-output "" }
     470     sprintf (d, "before %-+*.*lld after", lexpr, lexpr, lexpr);
     471                         ~~~^~~~~~         ~~~~~
     472                            |              |
     473                            int            long int
     474     { dg-end-multiline-output "" } */
     475  
     476    /* { dg-warning "28: field precision specifier '\\.\\*' expects argument of type 'int', but argument 4 has type 'long int'" "" { target *-*-* } test_everything_sprintf } */
     477    /* { dg-begin-multiline-output "" }
     478     sprintf (d, "before %-+*.*lld after", lexpr, lexpr, lexpr);
     479                         ~~~~~^~~~                ~~~~~
     480                              |                   |
     481                              int                 long int
     482     { dg-end-multiline-output "" } */
     483  
     484    /* { dg-warning "31: format '%lld' expects argument of type 'long long int', but argument 5 has type 'long int'" "" { target *-*-* } test_everything_sprintf } */
     485    /* { dg-begin-multiline-output "" }
     486     sprintf (d, "before %-+*.*lld after", lexpr, lexpr, lexpr);
     487                         ~~~~~~~~^                       ~~~~~
     488                                 |                       |
     489                                 long long int           long int
     490                         %-+*.*ld
     491     { dg-end-multiline-output "" } */
     492  }