blob: 96dfa97055cf0e8edced21557418ffba9c85c9c4 [file] [log] [blame]
/* { 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 "" } */
}