Commit e52ed3fe by David Malcolm Committed by David Malcolm

Use class substring_loc in c-format.c (PR c/52952)

gcc/c-family/ChangeLog:
	PR c/52952
	* c-format.c: Include "diagnostic.h".
	(location_column_from_byte_offset): Delete.
	(location_from_offset): Delete.
	(format_warning_va): New function.
	(format_warning_at_substring): New function.
	(format_warning_at_char): New function.
	(check_format_arg): Capture location of format_tree and pass to
	check_format_info_main.
	(argument_parser): Add fields "start_of_this_format" and
	"format_string_cst".
	(flag_chars_t::validate): Add param "format_string_cst".  Convert
	warning_at call using location_from_offset to call to
	format_warning_at_char.
	(argument_parser::argument_parser): Add param "format_string_cst_"
	and use use it to initialize field "format_string_cst".
	Initialize new field "start_of_this_format".
	(argument_parser::read_format_flags): Convert warning_at call
	using location_from_offset to a call to format_warning_at_char.
	(argument_parser::read_any_format_left_precision): Likewise.
	(argument_parser::read_any_format_precision): Likewise.
	(argument_parser::read_any_other_modifier): Likewise.
	(argument_parser::find_format_char_info): Likewise, in three places.
	(argument_parser::parse_any_scan_set): Likewise, in one place.
	(argument_parser::handle_conversions): Likewise, in two places.
	(argument_parser::check_argument_type): Add param "fmt_param_loc"
	and use it to make a substring_loc.  Pass the latter to
	check_format_types.
	(check_format_info_main): Add params "fmt_param_loc" and
	"format_string_cst".  Convert warning_at calls using
	location_from_offset to calls to format_warning_at_char.  Pass the
	new params to the arg_parser ctor.  Pass "format_string_cst" to
	flag_chars.validate.  Pass "fmt_param_loc" to
	arg_parser.check_argument_type.
	(check_format_types): Convert first param from a location_t
	to a const substring_loc & and rename to "fmt_loc".  Attempt
	to extract the range of the relevant parameter and pass it
	to format_type_warning.
	(format_type_warning): Convert first param from a location_t
	to a const substring_loc & and rename to "fmt_loc".  Add
	params "param_range" and "type".  Replace calls to warning_at
	with calls to format_warning_at_substring.

gcc/testsuite/ChangeLog:
	PR c/52952
	* gcc.dg/cpp/pr66415-1.c: Likewise.
	* gcc.dg/format/asm_fprintf-1.c: Update column numbers.
	* gcc.dg/format/c90-printf-1.c: Likewise.
	* gcc.dg/format/diagnostic-ranges.c: New test case.

From-SVN: r239253
parent f432d128
2016-08-08 David Malcolm <dmalcolm@redhat.com>
PR c/52952
* c-format.c: Include "diagnostic.h".
(location_column_from_byte_offset): Delete.
(location_from_offset): Delete.
(format_warning_va): New function.
(format_warning_at_substring): New function.
(format_warning_at_char): New function.
(check_format_arg): Capture location of format_tree and pass to
check_format_info_main.
(argument_parser): Add fields "start_of_this_format" and
"format_string_cst".
(flag_chars_t::validate): Add param "format_string_cst". Convert
warning_at call using location_from_offset to call to
format_warning_at_char.
(argument_parser::argument_parser): Add param "format_string_cst_"
and use use it to initialize field "format_string_cst".
Initialize new field "start_of_this_format".
(argument_parser::read_format_flags): Convert warning_at call
using location_from_offset to a call to format_warning_at_char.
(argument_parser::read_any_format_left_precision): Likewise.
(argument_parser::read_any_format_precision): Likewise.
(argument_parser::read_any_other_modifier): Likewise.
(argument_parser::find_format_char_info): Likewise, in three places.
(argument_parser::parse_any_scan_set): Likewise, in one place.
(argument_parser::handle_conversions): Likewise, in two places.
(argument_parser::check_argument_type): Add param "fmt_param_loc"
and use it to make a substring_loc. Pass the latter to
check_format_types.
(check_format_info_main): Add params "fmt_param_loc" and
"format_string_cst". Convert warning_at calls using
location_from_offset to calls to format_warning_at_char. Pass the
new params to the arg_parser ctor. Pass "format_string_cst" to
flag_chars.validate. Pass "fmt_param_loc" to
arg_parser.check_argument_type.
(check_format_types): Convert first param from a location_t
to a const substring_loc & and rename to "fmt_loc". Attempt
to extract the range of the relevant parameter and pass it
to format_type_warning.
(format_type_warning): Convert first param from a location_t
to a const substring_loc & and rename to "fmt_loc". Add
params "param_range" and "type". Replace calls to warning_at
with calls to format_warning_at_substring.
2016-08-08 David Malcolm <dmalcolm@redhat.com>
* c-format.c (class flag_chars_t): New class.
(struct length_modifier): New struct.
(class argument_parser): New class.
......
2016-08-08 David Malcolm <dmalcolm@redhat.com>
PR c/52952
* gcc.dg/cpp/pr66415-1.c: Likewise.
* gcc.dg/format/asm_fprintf-1.c: Update column numbers.
* gcc.dg/format/c90-printf-1.c: Likewise.
* gcc.dg/format/diagnostic-ranges.c: New test case.
2016-08-08 Jakub Jelinek <jakub@redhat.com>
PR fortran/72716
......
/* PR c/66415 */
/* { dg-do compile } */
/* { dg-options "-Wformat" } */
/* { dg-options "-Wformat -fdiagnostics-show-caret" } */
void
fn1 (void)
{
__builtin_printf ("xxxxxxxxxxxxxxxxx%dxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"); /* { dg-warning "71:format" } */
/* { dg-begin-multiline-output "" }
__builtin_printf ("xxxxxxxxxxxxxxxxx%dxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx");
~^
{ dg-end-multiline-output "" } */
}
......@@ -66,9 +66,9 @@ foo (int i, int i1, int i2, unsigned int u, double d, char *s, void *p,
asm_fprintf ("%d", i, i); /* { dg-warning "16:arguments" "wrong number of args" } */
/* Miscellaneous bogus constructions. */
asm_fprintf (""); /* { dg-warning "16:zero-length" "warning for empty format" } */
asm_fprintf ("\0"); /* { dg-warning "17:embedded" "warning for embedded NUL" } */
asm_fprintf ("%d\0", i); /* { dg-warning "19:embedded" "warning for embedded NUL" } */
asm_fprintf ("%d\0%d", i, i); /* { dg-warning "19:embedded|too many" "warning for embedded NUL" } */
asm_fprintf ("\0"); /* { dg-warning "18:embedded" "warning for embedded NUL" } */
asm_fprintf ("%d\0", i); /* { dg-warning "20:embedded" "warning for embedded NUL" } */
asm_fprintf ("%d\0%d", i, i); /* { dg-warning "20:embedded|too many" "warning for embedded NUL" } */
asm_fprintf (NULL); /* { dg-warning "null" "null format string warning" } */
asm_fprintf ("%"); /* { dg-warning "17:trailing" "trailing % warning" } */
asm_fprintf ("%++d", i); /* { dg-warning "19:repeated" "repeated flag warning" } */
......
......@@ -58,11 +58,11 @@ foo (int i, int i1, int i2, unsigned int u, double d, char *s, void *p,
printf ("%-%"); /* { dg-warning "13:type" "missing type" } */
/* { dg-warning "14:trailing" "bogus %%" { target *-*-* } 58 } */
printf ("%-%\n"); /* { dg-warning "13:format" "bogus %%" } */
/* { dg-warning "15:format" "bogus %%" { target *-*-* } 60 } */
/* { dg-warning "16:format" "bogus %%" { target *-*-* } 60 } */
printf ("%5%\n"); /* { dg-warning "13:format" "bogus %%" } */
/* { dg-warning "15:format" "bogus %%" { target *-*-* } 62 } */
/* { dg-warning "16:format" "bogus %%" { target *-*-* } 62 } */
printf ("%h%\n"); /* { dg-warning "13:format" "bogus %%" } */
/* { dg-warning "15:format" "bogus %%" { target *-*-* } 64 } */
/* { dg-warning "16:format" "bogus %%" { target *-*-* } 64 } */
/* Valid and invalid %h, %l, %L constructions. */
printf ("%hd", i);
printf ("%hi", i);
......@@ -184,8 +184,8 @@ foo (int i, int i1, int i2, unsigned int u, double d, char *s, void *p,
printf ("%-08G", d); /* { dg-warning "11:flags|ignored" "0 flag ignored with - flag" } */
/* Various tests of bad argument types. */
printf ("%d", l); /* { dg-warning "13:format" "bad argument types" } */
printf ("%*.*d", l, i2, i); /* { dg-warning "13:field" "bad * argument types" } */
printf ("%*.*d", i1, l, i); /* { dg-warning "15:field" "bad * argument types" } */
printf ("%*.*d", l, i2, i); /* { dg-warning "16:field" "bad * argument types" } */
printf ("%*.*d", i1, l, i); /* { dg-warning "16:field" "bad * argument types" } */
printf ("%ld", i); /* { dg-warning "14:format" "bad argument types" } */
printf ("%s", n); /* { dg-warning "13:format" "bad argument types" } */
printf ("%p", i); /* { dg-warning "13:format" "bad argument types" } */
......@@ -231,8 +231,8 @@ foo (int i, int i1, int i2, unsigned int u, double d, char *s, void *p,
printf ("%d", i, i); /* { dg-warning "11:arguments" "wrong number of args" } */
/* Miscellaneous bogus constructions. */
printf (""); /* { dg-warning "11:zero-length" "warning for empty format" } */
printf ("\0"); /* { dg-warning "12:embedded" "warning for embedded NUL" } */
printf ("%d\0", i); /* { dg-warning "14:embedded" "warning for embedded NUL" } */
printf ("\0"); /* { dg-warning "13:embedded" "warning for embedded NUL" } */
printf ("%d\0", i); /* { dg-warning "15:embedded" "warning for embedded NUL" } */
printf ("%d\0%d", i, i); /* { dg-warning "embedded|too many" "warning for embedded NUL" } */
printf (NULL); /* { dg-warning "3:null" "null format string warning" } */
printf ("%"); /* { dg-warning "12:trailing" "trailing % warning" } */
......
/* { dg-options "-Wformat -fdiagnostics-show-caret" } */
/* See PR 52952. */
#include "format.h"
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 \\*' " } */
/* TODO: ideally would also underline "msg". */
/* { dg-begin-multiline-output "" }
printf("hello %i", msg);
~^
{ 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);
/* TODO: ideally would also underline "101". */
/* { dg-begin-multiline-output "" }
printf ("arg0: %i arg1: %s arg 2: %i",
~^
{ 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",
~^
100, i + j, 102);
~~~~~
{ dg-end-multiline-output "" } */
}
void multiline_format_string (void) {
printf ("before the fmt specifier" /* { dg-warning "11: format '%d' expects a matching 'int' argument" } */
/* { dg-begin-multiline-output "" }
printf ("before the fmt specifier"
^~~~~~~~~~~~~~~~~~~~~~~~~~
{ dg-end-multiline-output "" } */
"%"
"d" /* { dg-message "12: format string is defined here" } */
"after the fmt specifier");
/* { dg-begin-multiline-output "" }
"%"
~~
"d"
~^
{ 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 \\*' " } */
/* TODO: ideally would also underline "msg". */
/* { dg-begin-multiline-output "" }
printf("hello \x25\x69", msg);
~~~~~~~^
{ 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 \\*' " } */
/* TODO: ideally would also underline "msg". */
/* { dg-begin-multiline-output "" }
printf("hello \045\151", msg);
~~~~~~~^
{ 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",
^~~~~~~~
{ dg-end-multiline-output "" } */
/* TODO: ideally would also underline "msg". */
/* { dg-begin-multiline-output "" }
printf("prefix" "\x25" "\151" "suffix",
~~~~~~~~~~~^
{ dg-end-multiline-output "" } */
}
void test_u8 (const char *msg)
{
printf(u8"hello %i", msg);/* { dg-warning "format '%i' expects argument of type 'int', but argument 2 has type 'const char \\*' " } */
/* TODO: ideally would also underline "msg". */
/* { dg-begin-multiline-output "" }
printf(u8"hello %i", msg);
~^
{ 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);
~^ ~~~~~~~~~~~~~~~
{ dg-end-multiline-output "" } */
}
void test_field_width_specifier (long l, int i1, int i2)
{
printf (" %*.*d ", l, i1, i2); /* { dg-warning "17: field width specifier '\\*' expects argument of type 'int', but argument 2 has type 'long int'" } */
/* { dg-begin-multiline-output "" }
printf (" %*.*d ", l, i1, i2);
~~~~^
{ 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 "14: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);
^~~~~~~~
{ dg-end-multiline-output "" } */
/* { dg-begin-multiline-output "" }
#define INT_FMT "%i"
~^
{ dg-end-multiline-output "" } */
}
void test_non_contiguous_strings (void)
{
__builtin_printf(" %" "d ", 0.5); /* { dg-warning "20: format .%d. expects argument of type .int., but argument 2 has type .double." } */
/* { dg-message "26: format string is defined here" "" { target *-*-* } 200 } */
/* { dg-begin-multiline-output "" }
__builtin_printf(" %" "d ", 0.5);
^~~~
{ dg-end-multiline-output "" } */
/* { dg-begin-multiline-output "" }
__builtin_printf(" %" "d ", 0.5);
~~~~^
{ 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);
^
{ dg-end-multiline-output "" } */
}
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment