view gcc/testsuite/g++.dg/warn/Wformat-ranges.C @ 131:84e7813d76e9

gcc-8.2
author mir3636
date Thu, 25 Oct 2018 07:37:49 +0900
parents
children
line wrap: on
line source

/* { dg-options "-Wformat -fdiagnostics-show-caret" } */

/* This is a copy of gcc.dg/format/diagnostic-ranges.c
   with the following changes:
   - removal of "format.h"
   - "char \\*" -> "char\\*" (space removal)
   - move of test_u8 to Wformat-ranges-c++11.C.  */

#define printf __builtin_printf
typedef __SIZE_TYPE__ size_t;
typedef __SIZE_TYPE__ ssize_t;

extern ssize_t strfmon (char *__restrict __s, size_t __maxsize,
			const char *__restrict, ...)
  __attribute__ ((__format__ (__strfmon__, 3, 4)));

/* See PR 52952. */

void test_mismatching_types (const char *msg)
{
  printf("hello %i", msg);  /* { dg-warning "format '%i' expects argument of type 'int', but argument 2 has type 'const char\\*' " } */

/* { dg-begin-multiline-output "" }
   printf("hello %i", msg);
                 ~^   ~~~
                  |   |
                  int const char*
                 %s
   { dg-end-multiline-output "" } */


  printf("hello %s", 42);  /* { dg-warning "format '%s' expects argument of type 'char\\*', but argument 2 has type 'int'" } */
/* { dg-begin-multiline-output "" }
   printf("hello %s", 42);
                 ~^   ~~
                  |   |
                  |   int
                  char*
                 %d
   { dg-end-multiline-output "" } */

  printf("hello %i", (long)0);  /* { dg-warning "format '%i' expects argument of type 'int', but argument 2 has type 'long int' " } */
/* { dg-begin-multiline-output "" }
   printf("hello %i", (long)0);
                 ~^   ~~~~~~~
                  |   |
                  int long int
                 %li
   { dg-end-multiline-output "" } */
}

void test_multiple_arguments (void)
{
  printf ("arg0: %i  arg1: %s arg 2: %i", /* { dg-warning "29: format '%s'" } */
          100, 101, 102);
/* { dg-begin-multiline-output "" }
   printf ("arg0: %i  arg1: %s arg 2: %i",
                            ~^
                             |
                             char*
                            %d
           100, 101, 102);
                ~~~           
                |
                int
   { dg-end-multiline-output "" } */
}

void test_multiple_arguments_2 (int i, int j)
{
  printf ("arg0: %i  arg1: %s arg 2: %i", /* { dg-warning "29: format '%s'" } */
          100, i + j, 102);
/* { dg-begin-multiline-output "" }
   printf ("arg0: %i  arg1: %s arg 2: %i",
                            ~^
                             |
                             char*
                            %d
           100, i + j, 102);
                ~~~~~         
                  |
                  int
   { dg-end-multiline-output "" } */
}

void multiline_format_string (void) {
  printf ("before the fmt specifier" 
          "%"
          "d" /* { dg-warning "12: format '%d' expects a matching 'int' argument" } */
          "after the fmt specifier");
/* { dg-begin-multiline-output "" }
           "%"
            ~~
           "d"
           ~^
            |
            int
   { dg-end-multiline-output "" } */
}

void test_hex (const char *msg)
{
  /* "%" is \x25
     "i" is \x69 */
  printf("hello \x25\x69", msg);  /* { dg-warning "format '%i' expects argument of type 'int', but argument 2 has type 'const char\\*' " } */

/* { dg-begin-multiline-output "" }
   printf("hello \x25\x69", msg);
                 ~~~~^~~~   ~~~
                     |      |
                     int    const char*
                 \x25s
   { dg-end-multiline-output "" } */
}

void test_oct (const char *msg)
{
  /* "%" is octal 045
     "i" is octal 151.  */
  printf("hello \045\151", msg);  /* { dg-warning "format '%i' expects argument of type 'int', but argument 2 has type 'const char\\*' " } */

/* { dg-begin-multiline-output "" }
   printf("hello \045\151", msg);
                 ~~~~^~~~   ~~~
                     |      |
                     int    const char*
                 \045s
   { dg-end-multiline-output "" } */
}

void test_multiple (const char *msg)
{
  /* "%" is \x25 in hex
     "i" is \151 in octal.  */
  printf("prefix"  "\x25"  "\151"  "suffix",  /* { dg-warning "format '%i'" } */
         msg);
/* { dg-begin-multiline-output "" }
   printf("prefix"  "\x25"  "\151"  "suffix",
                     ~~~~~~~~^~~~
                             |
                             int
                     \x25"  "s
          msg);
          ~~~                 
          |
          const char*
  { dg-end-multiline-output "" } */
}

void test_param (long long_i, long long_j)
{
  printf ("foo %s bar", long_i + long_j); /* { dg-warning "17: format '%s' expects argument of type 'char\\*', but argument 2 has type 'long int'" } */
/* { dg-begin-multiline-output "" }
   printf ("foo %s bar", long_i + long_j);
                ~^       ~~~~~~~~~~~~~~~
                 |              |
                 char*          long int
                %ld
   { dg-end-multiline-output "" } */
}

void test_field_width_specifier (long l, int i1, int i2)
{
  printf (" %*.*d ", l, i1, i2); /* { dg-warning "14: field width specifier '\\*' expects argument of type 'int', but argument 2 has type 'long int'" } */
/* { dg-begin-multiline-output "" }
   printf (" %*.*d ", l, i1, i2);
             ~^~~~    ~
              |       |
              int     long int
   { dg-end-multiline-output "" } */
}

/* PR c/72857.  */

void test_field_width_specifier_2 (char *d, long foo, long bar)
{
  __builtin_sprintf (d, " %*ld ", foo, foo); /* { dg-warning "28: field width specifier '\\*' expects argument of type 'int', but argument 3 has type 'long int'" } */
  /* { dg-begin-multiline-output "" }
   __builtin_sprintf (d, " %*ld ", foo, foo);
                           ~^~~    ~~~
                            |      |
                            int    long int
   { dg-end-multiline-output "" } */

  __builtin_sprintf (d, " %*ld ", foo + bar, foo); /* { dg-warning "28: field width specifier '\\*' expects argument of type 'int', but argument 3 has type 'long int'" } */
  /* { dg-begin-multiline-output "" }
   __builtin_sprintf (d, " %*ld ", foo + bar, foo);
                           ~^~~    ~~~~~~~~~
                            |          |
                            int        long int
   { dg-end-multiline-output "" } */
}

void test_field_precision_specifier (char *d, long foo, long bar)
{
  __builtin_sprintf (d, " %.*ld ", foo, foo); /* { dg-warning "29: field precision specifier '\\.\\*' expects argument of type 'int', but argument 3 has type 'long int'" } */
  /* { dg-begin-multiline-output "" }
   __builtin_sprintf (d, " %.*ld ", foo, foo);
                           ~~^~~    ~~~
                             |      |
                             int    long int
   { dg-end-multiline-output "" } */

  __builtin_sprintf (d, " %.*ld ", foo + bar, foo); /* { dg-warning "29: field precision specifier '\\.\\*' expects argument of type 'int', but argument 3 has type 'long int'" } */
  /* { dg-begin-multiline-output "" }
   __builtin_sprintf (d, " %.*ld ", foo + bar, foo);
                           ~~^~~    ~~~~~~~~~
                             |          |
                             int        long int
   { dg-end-multiline-output "" } */
}

void test_spurious_percent (void)
{
  printf("hello world %"); /* { dg-warning "23: spurious trailing" } */

/* { dg-begin-multiline-output "" }
   printf("hello world %");
                       ^
   { dg-end-multiline-output "" } */
}

void test_empty_precision (char *s, size_t m, double d)
{
  strfmon (s, m, "%#.5n", d); /* { dg-warning "20: empty left precision in gnu_strfmon format" } */
/* { dg-begin-multiline-output "" }
   strfmon (s, m, "%#.5n", d);
                    ^
   { dg-end-multiline-output "" } */

  strfmon (s, m, "%#5.n", d); /* { dg-warning "22: empty precision in gnu_strfmon format" } */
/* { dg-begin-multiline-output "" }
   strfmon (s, m, "%#5.n", d);
                      ^
   { dg-end-multiline-output "" } */
}

void test_repeated (int i)
{
  printf ("%++d", i); /* { dg-warning "14: repeated '\\+' flag in format" } */
/* { dg-begin-multiline-output "" }
   printf ("%++d", i);
              ^
   { dg-end-multiline-output "" } */
}

void test_conversion_lacks_type (void)
{
  printf (" %h"); /* { dg-warning "14:conversion lacks type at end of format" } */
/* { dg-begin-multiline-output "" }
   printf (" %h");
              ^
   { dg-end-multiline-output "" } */
}

void test_embedded_nul (void)
{
  printf (" \0 "); /* { dg-warning "13:embedded" "warning for embedded NUL" } */
/* { dg-begin-multiline-output "" }
   printf (" \0 ");
             ^~
   { dg-end-multiline-output "" } */
}

void test_macro (const char *msg)
{
#define INT_FMT "%i" /* { dg-message "19: format string is defined here" } */
  printf("hello " INT_FMT " world", msg);  /* { dg-warning "10: format '%i' expects argument of type 'int', but argument 2 has type 'const char\\*' " } */
/* { dg-begin-multiline-output "" }
   printf("hello " INT_FMT " world", msg);
          ^~~~~~~~~~~~~~~~~~~~~~~~~  ~~~
                                     |
                                     const char*
   { dg-end-multiline-output "" } */
/* { dg-begin-multiline-output "" }
 #define INT_FMT "%i"
                  ~^
                   |
                   int
                  %s
   { dg-end-multiline-output "" } */
#undef INT_FMT
}

void test_macro_2 (const char *msg)
{
#define PRIu32 "u" /* { dg-message "17: format string is defined here" } */
  printf("hello %" PRIu32 " world", msg);  /* { dg-warning "10: format '%u' expects argument of type 'unsigned int', but argument 2 has type 'const char\\*' " } */
/* { dg-begin-multiline-output "" }
   printf("hello %" PRIu32 " world", msg);
          ^~~~~~~~~~~~~~~~~~~~~~~~~  ~~~
                                     |
                                     const char*
   { dg-end-multiline-output "" } */
/* { dg-begin-multiline-output "" }
 #define PRIu32 "u"
                 ^
                 |
                 unsigned int
   { dg-end-multiline-output "" } */
#undef PRIu32
}

void test_macro_3 (const char *msg)
{
#define FMT_STRING "hello %i world" // { dg-line test_macro_3_macro_line }
/* { dg-warning "20: format '%i' expects argument of type 'int', but argument 2 has type 'const char\\*'" "" { target *-*-* } .-1 } */
  printf(FMT_STRING, msg);  /* { dg-message "10: in expansion of macro 'FMT_STRING" } */
/* { dg-begin-multiline-output "" }
 #define FMT_STRING "hello %i world"
                    ^~~~~~~~~~~~~~~~
   { dg-end-multiline-output "" } */
/* { dg-begin-multiline-output "" }
   printf(FMT_STRING, msg);
          ^~~~~~~~~~
   { dg-end-multiline-output "" } */
/* { dg-message "28: format string is defined here" "" { target *-*-* } test_macro_3_macro_line } */
/* { dg-begin-multiline-output "" }
 #define FMT_STRING "hello %i world"
                           ~^
                            |
                            int
                           %s
   { dg-end-multiline-output "" } */
#undef FMT_STRING
}

void test_macro_4 (const char *msg)
{
#define FMT_STRING "hello %i world" /* { dg-warning "20: format '%i' expects argument of type 'int', but argument 2 has type 'const char\\*' " } */
  printf(FMT_STRING "\n", msg);  /* { dg-message "10: in expansion of macro 'FMT_STRING" } */
/* { dg-begin-multiline-output "" }
 #define FMT_STRING "hello %i world"
                    ^
   { dg-end-multiline-output "" } */
/* { dg-begin-multiline-output "" }
   printf(FMT_STRING "\n", msg);
          ^~~~~~~~~~
   { dg-end-multiline-output "" } */
/* { dg-begin-multiline-output "" }
 #define FMT_STRING "hello %i world"
                           ~^
                            |
                            int
                           %s
   { dg-end-multiline-output "" } */
#undef FMT_STRING
}

void test_non_contiguous_strings (void)
{
  __builtin_printf(" %" "d ", 0.5); /* { dg-warning "26: format .%d. expects argument of type .int., but argument 2 has type .double." } */
  /* { dg-begin-multiline-output "" }
   __builtin_printf(" %" "d ", 0.5);
                      ~~~~^    ~~~
                          |    |
                          int  double
                      %" "f
   { dg-end-multiline-output "" } */
}

void test_const_arrays (void)
{
  /* TODO: ideally we'd highlight both the format string *and* the use of
     it here.  For now, just verify that we gracefully handle this case.  */
  const char a[] = " %d ";
  __builtin_printf(a, 0.5); /* { dg-warning "20: format .%d. expects argument of type .int., but argument 2 has type .double." } */
  /* { dg-begin-multiline-output "" }
   __builtin_printf(a, 0.5);
                    ^  ~~~
                       |
                       double
   { dg-end-multiline-output "" } */
}