Commit 65e736c0 by David Malcolm Committed by David Malcolm

Fix caret locations in format_type_warning (PR c/72857)

gcc/c-family/ChangeLog:
	PR c/72857
	* c-common.c (substring_loc::get_range): Rename to...
	(substring_loc::get_location): ...this, converting param from a
	source_range * to a location_t *.  Call
	get_source_location_for_substring rather than
	get_source_range_for_substring, and pass in m_caret_idx.
	* c-common.h (substring_loc::substring_loc): Add param "caret_idx".
	(substring_loc::get_range): Replace with...
	(substring_loc::get_location): ...this.
	(substring_loc::set_caret_index): New method.
	(substring_loc): Add field m_caret_idx.
	* c-format.c (format_warning_va): Update for above changes.
	Rename local "substring_loc" to "fmt_substring_loc" to avoid
	clashing with type name.
	(format_warning_at_char): Add caret_idx param to substring_loc ctor.
	(check_argument_type): Likewise.
	(format_type_warning): Rename param "fmt_loc" to "whole_fmt_loc"
	Use a copy when emitting warnings, setting the caret index from TYPE.

gcc/ChangeLog:
	PR c/72857
	* input.c (get_source_range_for_substring): Rename to...
	(get_source_location_for_substring): ...this, adding param
	"caret_idx", and converting output param from source_range * to
	location_t *.
	(get_source_range_for_char): New function.
	(get_num_source_ranges_for_substring): Update comment to reflect
	above renaming.
	(assert_char_at_range): Update to use get_source_range_for_char
	rather than get_source_range_for_substring.
	(test_lexer_string_locations_concatenation_2): Likewise.
	* substring-locations.h (get_source_range_for_substring): Rename
	to...
	(get_source_location_for_substring): ...this, and adding param
	"caret_idx", and converting output param from source_range * to
	location_t *.

gcc/testsuite/ChangeLog:
	PR c/72857
	* gcc.dg/format/asm_fprintf-1.c: Restore column numbers
	for embedded NUL.
	* gcc.dg/format/c90-printf-1.c: Restore column numbers.
	* gcc.dg/format/diagnostic-ranges.c (test_hex): Update expected
	caret placement.
	(test_oct): Likewise.
	(test_multiple): Likewise.
	(test_field_width_specifier): Likewise.
	(test_field_width_specifier_2): New function.
	(test_field_precision_specifier): New function.
	(test_embedded_nul): Update expected caret placement.
	(test_non_contiguous_strings): Update line number.
	* gcc.dg/plugin/diagnostic-test-string-literals-1.c
	(__emit_string_literal_range): Add "caret_idx" param.
	(test_simple_string_literal): Add value for new param, updating
	expected output..
	(test_concatenated_string_literal): Likewise.
	(test_multiline_string_literal): Likewise.
	(test_hex): Likewise.
	(test_oct): Likewise.
	(test_multiple): Likewise.
	(test_ucn4): Likewise.
	(test_ucn8): Likewise.
	(test_u8): Likewise.
	(test_u): Likewise; update expected message, from "range" to
	"location".
	(test_U): Likewise.
	(test_L): Likewise.
	(test_macro): Add value for new param.
	* gcc.dg/plugin/diagnostic-test-string-literals-2.c
	(__emit_string_literal_range): Add "caret_idx" param.
	(test_stringified_token_1): Add value for new param.  Update
	expected message, from "range" to "location".
	(test_stringized_token_2): Likewise, adding param to macro.
	(test_stringified_token_3): Likewise.
	* gcc.dg/plugin/diagnostic_plugin_test_string_literals.c
	(emit_warning): Convert param from source_range to location_t.
	(test_string_literals): Add caret_idx param, and use it when
	constructing a substring_loc.  Update error message, from
	"range" to "location".

From-SVN: r239510
parent eb3a5bcc
2016-08-16 David Malcolm <dmalcolm@redhat.com>
PR c/72857
* input.c (get_source_range_for_substring): Rename to...
(get_source_location_for_substring): ...this, adding param
"caret_idx", and converting output param from source_range * to
location_t *.
(get_source_range_for_char): New function.
(get_num_source_ranges_for_substring): Update comment to reflect
above renaming.
(assert_char_at_range): Update to use get_source_range_for_char
rather than get_source_range_for_substring.
(test_lexer_string_locations_concatenation_2): Likewise.
* substring-locations.h (get_source_range_for_substring): Rename
to...
(get_source_location_for_substring): ...this, and adding param
"caret_idx", and converting output param from source_range * to
location_t *.
2016-08-16 David Malcolm <dmalcolm@redhat.com>
* input.c (class selftest::temp_source_file): Move to
selftest.h.
(selftest::temp_source_file::temp_source_file): Move to
......
2016-08-16 David Malcolm <dmalcolm@redhat.com>
PR c/72857
* c-common.c (substring_loc::get_range): Rename to...
(substring_loc::get_location): ...this, converting param from a
source_range * to a location_t *. Call
get_source_location_for_substring rather than
get_source_range_for_substring, and pass in m_caret_idx.
* c-common.h (substring_loc::substring_loc): Add param "caret_idx".
(substring_loc::get_range): Replace with...
(substring_loc::get_location): ...this.
(substring_loc::set_caret_index): New method.
(substring_loc): Add field m_caret_idx.
* c-format.c (format_warning_va): Update for above changes.
Rename local "substring_loc" to "fmt_substring_loc" to avoid
clashing with type name.
(format_warning_at_char): Add caret_idx param to substring_loc ctor.
(check_argument_type): Likewise.
(format_type_warning): Rename param "fmt_loc" to "whole_fmt_loc"
Use a copy when emitting warnings, setting the caret index from TYPE.
2016-08-16 Eric Botcazou <ebotcazou@adacore.com>
Arnaud Charlet <charlet@adacore.com>
......
......@@ -1140,24 +1140,24 @@ get_cpp_ttype_from_string_type (tree string_type)
GTY(()) string_concat_db *g_string_concat_db;
/* Attempt to determine the source range of the substring.
If successful, return NULL and write the source range to *OUT_RANGE.
/* Attempt to determine the source location of the substring.
If successful, return NULL and write the source location to *OUT_LOC.
Otherwise return an error message. Error messages are intended
for GCC developers (to help debugging) rather than for end-users. */
const char *
substring_loc::get_range (source_range *out_range) const
substring_loc::get_location (location_t *out_loc) const
{
gcc_assert (out_range);
gcc_assert (out_loc);
enum cpp_ttype tok_type = get_cpp_ttype_from_string_type (m_string_type);
if (tok_type == CPP_OTHER)
return "unrecognized string type";
return get_source_range_for_substring (parse_in, g_string_concat_db,
return get_source_location_for_substring (parse_in, g_string_concat_db,
m_fmt_string_loc, tok_type,
m_start_idx, m_end_idx,
out_range);
m_caret_idx, m_start_idx, m_end_idx,
out_loc);
}
......
......@@ -1124,17 +1124,20 @@ class substring_loc
{
public:
substring_loc (location_t fmt_string_loc, tree string_type,
int start_idx, int end_idx)
int caret_idx, int start_idx, int end_idx)
: m_fmt_string_loc (fmt_string_loc), m_string_type (string_type),
m_start_idx (start_idx), m_end_idx (end_idx) {}
m_caret_idx (caret_idx), m_start_idx (start_idx), m_end_idx (end_idx) {}
const char *get_range (source_range *out_range) const;
void set_caret_index (int caret_idx) { m_caret_idx = caret_idx; }
const char *get_location (location_t *out_loc) const;
location_t get_fmt_string_loc () const { return m_fmt_string_loc; }
private:
location_t m_fmt_string_loc;
tree m_string_type;
int m_caret_idx;
int m_start_idx;
int m_end_idx;
};
......
......@@ -146,26 +146,23 @@ format_warning_va (const substring_loc &fmt_loc, source_range *param_range,
{
bool substring_within_range = false;
location_t primary_loc;
location_t substring_loc = UNKNOWN_LOCATION;
location_t fmt_substring_loc = UNKNOWN_LOCATION;
source_range fmt_loc_range
= get_range_from_loc (line_table, fmt_loc.get_fmt_string_loc ());
source_range fmt_substring_range;
const char *err = fmt_loc.get_range (&fmt_substring_range);
const char *err = fmt_loc.get_location (&fmt_substring_loc);
source_range fmt_substring_range
= get_range_from_loc (line_table, fmt_substring_loc);
if (err)
/* Case 3: unable to get substring location. */
primary_loc = fmt_loc.get_fmt_string_loc ();
else
{
substring_loc = make_location (fmt_substring_range.m_finish,
fmt_substring_range.m_start,
fmt_substring_range.m_finish);
if (fmt_substring_range.m_start >= fmt_loc_range.m_start
&& fmt_substring_range.m_finish <= fmt_loc_range.m_finish)
/* Case 1. */
{
substring_within_range = true;
primary_loc = substring_loc;
primary_loc = fmt_substring_loc;
}
else
/* Case 2. */
......@@ -193,11 +190,11 @@ format_warning_va (const substring_loc &fmt_loc, source_range *param_range,
diagnostic.option_index = opt;
bool warned = report_diagnostic (&diagnostic);
if (!err && substring_loc && !substring_within_range)
if (!err && fmt_substring_loc && !substring_within_range)
/* Case 2. */
if (warned)
{
rich_location substring_richloc (line_table, substring_loc);
rich_location substring_richloc (line_table, fmt_substring_loc);
if (corrected_substring)
substring_richloc.add_fixit_replace (fmt_substring_range,
corrected_substring);
......@@ -247,7 +244,8 @@ format_warning_at_char (location_t fmt_string_loc, tree format_string_cst,
be emitted. Fix it. */
char_idx -= 1;
substring_loc fmt_loc (fmt_string_loc, string_type, char_idx, char_idx);
substring_loc fmt_loc (fmt_string_loc, string_type, char_idx, char_idx,
char_idx);
bool warned = format_warning_va (fmt_loc, NULL, NULL, opt, gmsgid, &ap);
va_end (ap);
......@@ -2809,7 +2807,9 @@ check_argument_type (const format_char_info *fci,
{
ptrdiff_t offset_to_format_start = (start_of_this_format - 1) - orig_format_chars;
ptrdiff_t offset_to_format_end = (format_chars - 1) - orig_format_chars;
/* By default, use the end of the range for the caret location. */
substring_loc fmt_loc (fmt_param_loc, TREE_TYPE (format_string_cst),
offset_to_format_end,
offset_to_format_start, offset_to_format_end);
check_format_types (fmt_loc, first_wanted_type, fki);
}
......@@ -3262,8 +3262,10 @@ get_format_for_type (const format_kind_info *fki, tree arg_type)
return NULL;
}
/* Give a warning at FMT_LOC about a format argument of different type
from that expected. If non-NULL, PARAM_RANGE is the source range of the
/* Give a warning about a format argument of different type from that expected.
The range of the diagnostic is taken from WHOLE_FMT_LOC; the caret location
is based on the location of the char at TYPE->offset_loc.
If non-NULL, PARAM_RANGE is the source range of the
relevant argument. WANTED_TYPE is the type the argument should have,
possibly stripped of pointer dereferences. The description (such as "field
precision"), the placement in the format string, a possibly more
......@@ -3271,7 +3273,7 @@ get_format_for_type (const format_kind_info *fki, tree arg_type)
are taken from TYPE. ARG_TYPE is the type of the actual argument,
or NULL if it is missing. */
static void
format_type_warning (const substring_loc &fmt_loc,
format_type_warning (const substring_loc &whole_fmt_loc,
source_range *param_range,
format_wanted_type *type,
tree wanted_type, tree arg_type,
......@@ -3316,6 +3318,12 @@ format_type_warning (const substring_loc &fmt_loc,
p[pointer_count + 1] = 0;
}
/* WHOLE_FMT_LOC has the caret at the end of the range.
Set the caret to be at the offset from TYPE. Subtract one
from the offset for the same reason as in format_warning_at_char. */
substring_loc fmt_loc (whole_fmt_loc);
fmt_loc.set_caret_index (type->offset_loc - 1);
/* Attempt to provide hints for argument types, but not for field widths
and precisions. */
char *format_for_type = NULL;
......
......@@ -1402,10 +1402,17 @@ get_substring_ranges_for_loc (cpp_reader *pfile,
return NULL;
}
/* Attempt to populate *OUT_RANGE with source location information on the
range of given characters within the string literal found at STRLOC.
START_IDX and END_IDX refer to offsets within the execution character
set.
/* Attempt to populate *OUT_LOC with source location information on the
given characters within the string literal found at STRLOC.
CARET_IDX, START_IDX, and END_IDX refer to offsets within the execution
character set.
For example, given CARET_IDX = 4, START_IDX = 3, END_IDX = 7
and string literal "012345\n789"
*OUT_LOC is written to with:
"012345\n789"
~^~~~~
If CONCATS is non-NULL, then any string literals that the token at
STRLOC was concatenated with are also considered.
......@@ -1416,16 +1423,17 @@ get_substring_ranges_for_loc (cpp_reader *pfile,
than for end-users. */
const char *
get_source_range_for_substring (cpp_reader *pfile,
get_source_location_for_substring (cpp_reader *pfile,
string_concat_db *concats,
location_t strloc,
enum cpp_ttype type,
int start_idx, int end_idx,
source_range *out_range)
int caret_idx, int start_idx, int end_idx,
source_location *out_loc)
{
gcc_checking_assert (caret_idx >= 0);
gcc_checking_assert (start_idx >= 0);
gcc_checking_assert (end_idx >= 0);
gcc_assert (out_range);
gcc_assert (out_loc);
cpp_substring_ranges ranges;
const char *err
......@@ -1433,17 +1441,56 @@ get_source_range_for_substring (cpp_reader *pfile,
if (err)
return err;
if (caret_idx >= ranges.get_num_ranges ())
return "caret_idx out of range";
if (start_idx >= ranges.get_num_ranges ())
return "start_idx out of range";
if (end_idx >= ranges.get_num_ranges ())
return "end_idx out of range";
out_range->m_start = ranges.get_range (start_idx).m_start;
out_range->m_finish = ranges.get_range (end_idx).m_finish;
*out_loc = make_location (ranges.get_range (caret_idx).m_start,
ranges.get_range (start_idx).m_start,
ranges.get_range (end_idx).m_finish);
return NULL;
}
/* As get_source_range_for_substring, but write to *OUT the number
/* Attempt to populate *OUT_RANGE with source location information on the
given character within the string literal found at STRLOC.
CHAR_IDX refers to an offset within the execution character set.
If CONCATS is non-NULL, then any string literals that the token at
STRLOC was concatenated with are also considered.
This is implemented by re-parsing the relevant source line(s).
Return NULL if successful, or an error message if any errors occurred.
Error messages are intended for GCC developers (to help debugging) rather
than for end-users. */
static const char *
get_source_range_for_char (cpp_reader *pfile,
string_concat_db *concats,
location_t strloc,
enum cpp_ttype type,
int char_idx,
source_range *out_range)
{
gcc_checking_assert (char_idx >= 0);
gcc_assert (out_range);
cpp_substring_ranges ranges;
const char *err
= get_substring_ranges_for_loc (pfile, concats, strloc, type, ranges);
if (err)
return err;
if (char_idx >= ranges.get_num_ranges ())
return "char_idx out of range";
*out_range = ranges.get_range (char_idx);
return NULL;
}
/* As get_source_range_for_char, but write to *OUT the number
of ranges that are available. */
const char *
......@@ -1939,8 +1986,8 @@ assert_char_at_range (const location &loc,
source_range actual_range;
const char *err
= get_source_range_for_substring (pfile, concats, strloc, type,
idx, idx, &actual_range);
= get_source_range_for_char (pfile, concats, strloc, type, idx,
&actual_range);
if (should_have_column_data_p (strloc))
ASSERT_EQ_AT (loc, NULL, err);
else
......@@ -2789,9 +2836,8 @@ test_lexer_string_locations_concatenation_2 (const line_table_case &case_)
this case. */
source_range actual_range;
const char *err
= get_source_range_for_substring (test.m_parser, &test.m_concats,
initial_loc, type, 0, 0,
&actual_range);
= get_source_range_for_char (test.m_parser, &test.m_concats,
initial_loc, type, 0, &actual_range);
ASSERT_STREQ ("range starts after LINE_MAP_MAX_LOCATION_WITH_COLS", err);
return;
}
......
......@@ -20,11 +20,12 @@ along with GCC; see the file COPYING3. If not see
#ifndef GCC_SUBSTRING_LOCATIONS_H
#define GCC_SUBSTRING_LOCATIONS_H
extern const char *get_source_range_for_substring (cpp_reader *pfile,
extern const char *get_source_location_for_substring (cpp_reader *pfile,
string_concat_db *concats,
location_t strloc,
enum cpp_ttype type,
int caret_idx,
int start_idx, int end_idx,
source_range *out_range);
location_t *out_loc);
#endif /* ! GCC_SUBSTRING_LOCATIONS_H */
2016-08-16 David Malcolm <dmalcolm@redhat.com>
PR c/72857
* gcc.dg/format/asm_fprintf-1.c: Restore column numbers
for embedded NUL.
* gcc.dg/format/c90-printf-1.c: Restore column numbers.
* gcc.dg/format/diagnostic-ranges.c (test_hex): Update expected
caret placement.
(test_oct): Likewise.
(test_multiple): Likewise.
(test_field_width_specifier): Likewise.
(test_field_width_specifier_2): New function.
(test_field_precision_specifier): New function.
(test_embedded_nul): Update expected caret placement.
(test_non_contiguous_strings): Update line number.
* gcc.dg/plugin/diagnostic-test-string-literals-1.c
(__emit_string_literal_range): Add "caret_idx" param.
(test_simple_string_literal): Add value for new param, updating
expected output..
(test_concatenated_string_literal): Likewise.
(test_multiline_string_literal): Likewise.
(test_hex): Likewise.
(test_oct): Likewise.
(test_multiple): Likewise.
(test_ucn4): Likewise.
(test_ucn8): Likewise.
(test_u8): Likewise.
(test_u): Likewise; update expected message, from "range" to
"location".
(test_U): Likewise.
(test_L): Likewise.
(test_macro): Add value for new param.
* gcc.dg/plugin/diagnostic-test-string-literals-2.c
(__emit_string_literal_range): Add "caret_idx" param.
(test_stringified_token_1): Add value for new param. Update
expected message, from "range" to "location".
(test_stringized_token_2): Likewise, adding param to macro.
(test_stringified_token_3): Likewise.
* gcc.dg/plugin/diagnostic_plugin_test_string_literals.c
(emit_warning): Convert param from source_range to location_t.
(test_string_literals): Add caret_idx param, and use it when
constructing a substring_loc. Update error message, from
"range" to "location".
2016-08-16 Jakub Jelinek <jakub@redhat.com>
PR target/71910
......
......@@ -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 "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 ("\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 (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 "16:format" "bogus %%" { target *-*-* } 60 } */
/* { dg-warning "15:format" "bogus %%" { target *-*-* } 60 } */
printf ("%5%\n"); /* { dg-warning "13:format" "bogus %%" } */
/* { dg-warning "16:format" "bogus %%" { target *-*-* } 62 } */
/* { dg-warning "15:format" "bogus %%" { target *-*-* } 62 } */
printf ("%h%\n"); /* { dg-warning "13:format" "bogus %%" } */
/* { dg-warning "16:format" "bogus %%" { target *-*-* } 64 } */
/* { dg-warning "15: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 "16:field" "bad * argument types" } */
printf ("%*.*d", i1, l, i); /* { dg-warning "16:field" "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 ("%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 "13:embedded" "warning for embedded NUL" } */
printf ("%d\0", i); /* { dg-warning "15:embedded" "warning for embedded NUL" } */
printf ("\0"); /* { dg-warning "12:embedded" "warning for embedded NUL" } */
printf ("%d\0", i); /* { dg-warning "14: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" } */
......
......@@ -87,7 +87,7 @@ void test_hex (const char *msg)
/* TODO: ideally would also underline "msg". */
/* { dg-begin-multiline-output "" }
printf("hello \x25\x69", msg);
~~~~~~~^
~~~~^~~~
%s
{ dg-end-multiline-output "" } */
}
......@@ -101,7 +101,7 @@ void test_oct (const char *msg)
/* TODO: ideally would also underline "msg". */
/* { dg-begin-multiline-output "" }
printf("hello \045\151", msg);
~~~~~~~^
~~~~^~~~
%s
{ dg-end-multiline-output "" } */
}
......@@ -120,7 +120,7 @@ void test_multiple (const char *msg)
/* TODO: ideally would also underline "msg". */
/* { dg-begin-multiline-output "" }
printf("prefix" "\x25" "\151" "suffix",
~~~~~~~~~~~^
~~~~~~~~^~~~
%s
{ dg-end-multiline-output "" } */
}
......@@ -148,10 +148,44 @@ void test_param (long long_i, long long_j)
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'" } */
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);
~~~~^
~^~~~
{ 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'" } */
/* TODO: ideally we'd underline the first "foo" here". */
/* { dg-begin-multiline-output "" }
__builtin_sprintf (d, " %*ld ", foo, foo);
~^~~
{ 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);
~^~~ ~~~~~~~~~
{ 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'" } */
/* TODO: ideally we'd underline the first "foo" here". */
/* { dg-begin-multiline-output "" }
__builtin_sprintf (d, " %.*ld ", foo, foo);
~~^~~
{ 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);
~~^~~ ~~~~~~~~~
{ dg-end-multiline-output "" } */
}
......@@ -200,10 +234,10 @@ void test_conversion_lacks_type (void)
void test_embedded_nul (void)
{
printf (" \0 "); /* { dg-warning "14:embedded" "warning for embedded NUL" } */
printf (" \0 "); /* { dg-warning "13:embedded" "warning for embedded NUL" } */
/* { dg-begin-multiline-output "" }
printf (" \0 ");
~^
^~
{ dg-end-multiline-output "" } */
}
......@@ -225,7 +259,7 @@ void test_macro (const char *msg)
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 *-*-* } 227 } */
/* { dg-message "26: format string is defined here" "" { target *-*-* } 261 } */
/* { dg-begin-multiline-output "" }
__builtin_printf(" %" "d ", 0.5);
^~~~
......
......@@ -13,14 +13,14 @@
LITERAL is a const void * to allow testing the various kinds of wide
string literal, rather than just const char *. */
extern void __emit_string_literal_range (const void *literal,
extern void __emit_string_literal_range (const void *literal, int caret_idx,
int start_idx, int end_idx);
void
test_simple_string_literal (void)
{
__emit_string_literal_range ("0123456789", /* { dg-warning "range" } */
6, 7);
6, 6, 7);
/* { dg-begin-multiline-output "" }
__emit_string_literal_range ("0123456789",
^~
......@@ -31,10 +31,10 @@ void
test_concatenated_string_literal (void)
{
__emit_string_literal_range ("01234" "56789", /* { dg-warning "range" } */
3, 6);
4, 3, 6);
/* { dg-begin-multiline-output "" }
__emit_string_literal_range ("01234" "56789",
^~~~~~~
~^~~~~~
{ dg-end-multiline-output "" } */
}
......@@ -43,14 +43,14 @@ test_multiline_string_literal (void)
{
__emit_string_literal_range ("01234" /* { dg-warning "range" } */
"56789",
3, 6);
4, 3, 6);
/* { dg-begin-multiline-output "" }
__emit_string_literal_range ("01234"
^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
~^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
"56789",
~~~
{ dg-end-multiline-output "" } */
/* FIXME: why does the above need two trailing spaces? */
/* FIXME: why does the above need three trailing spaces? */
}
/* Tests of various unicode encodings.
......@@ -79,10 +79,10 @@ test_hex (void)
and with a space in place of digit 6, to terminate the escaped
hex code. */
__emit_string_literal_range ("01234\x35 789", /* { dg-warning "range" } */
3, 7);
4, 3, 7);
/* { dg-begin-multiline-output "" }
__emit_string_literal_range ("01234\x35 789"
^~~~~~~~
~^~~~~~~
{ dg-end-multiline-output "" } */
}
......@@ -93,10 +93,10 @@ test_oct (void)
and with a space in place of digit 6, to terminate the escaped
octal code. */
__emit_string_literal_range ("01234\065 789", /* { dg-warning "range" } */
3, 7);
4, 3, 7);
/* { dg-begin-multiline-output "" }
__emit_string_literal_range ("01234\065 789"
^~~~~~~~
~^~~~~~~
{ dg-end-multiline-output "" } */
}
......@@ -106,10 +106,10 @@ test_multiple (void)
/* Digits 0-9, expressing digit 5 in ASCII as hex "\x35"
digit 6 in ASCII as octal "\066", concatenating multiple strings. */
__emit_string_literal_range ("01234" "\x35" "\066" "789", /* { dg-warning "range" } */
3, 8);
5, 3, 8);
/* { dg-begin-multiline-output "" }
__emit_string_literal_range ("01234" "\x35" "\066" "789",
^~~~~~~~~~~~~~~~~~~~~~~~
~~~~~~^~~~~~~~~~~~~~~~~~
{ dg-end-multiline-output "" } */
}
......@@ -123,10 +123,10 @@ test_ucn4 (void)
Hence to underline digits 4-7 we need to underling using bytes 4-11 in
the UTF-8 encoding. */
__emit_string_literal_range ("01234\u2174\u2175789", /* { dg-warning "range" } */
4, 11);
5, 4, 11);
/* { dg-begin-multiline-output "" }
__emit_string_literal_range ("01234\u2174\u2175789",
^~~~~~~~~~~~~~
~^~~~~~~~~~~~~
{ dg-end-multiline-output "" } */
}
......@@ -138,10 +138,10 @@ test_ucn8 (void)
has the same UTF-8 encoding, and so we again need to underline bytes
4-11 in the UTF-8 encoding in order to underline digits 4-7. */
__emit_string_literal_range ("01234\U00002174\U00002175789", /* { dg-warning "range" } */
4, 11);
5, 4, 11);
/* { dg-begin-multiline-output "" }
__emit_string_literal_range ("01234\U00002174\U00002175789",
^~~~~~~~~~~~~~~~~~~~~~
~^~~~~~~~~~~~~~~~~~~~~
{ dg-end-multiline-output "" } */
}
......@@ -150,10 +150,10 @@ test_u8 (void)
{
/* Digits 0-9. */
__emit_string_literal_range (u8"0123456789", /* { dg-warning "range" } */
4, 7);
6, 4, 7);
/* { dg-begin-multiline-output "" }
__emit_string_literal_range (u8"0123456789",
^~~~
~~^~
{ dg-end-multiline-output "" } */
}
......@@ -161,8 +161,8 @@ void
test_u (void)
{
/* Digits 0-9. */
__emit_string_literal_range (u"0123456789", /* { dg-error "unable to read substring range: execution character set != source character set" } */
4, 7);
__emit_string_literal_range (u"0123456789", /* { dg-error "unable to read substring location: execution character set != source character set" } */
6, 4, 7);
/* { dg-begin-multiline-output "" }
__emit_string_literal_range (u"0123456789",
^~~~~~~~~~~~~
......@@ -173,8 +173,8 @@ void
test_U (void)
{
/* Digits 0-9. */
__emit_string_literal_range (U"0123456789", /* { dg-error "unable to read substring range: execution character set != source character set" } */
4, 7);
__emit_string_literal_range (U"0123456789", /* { dg-error "unable to read substring location: execution character set != source character set" } */
6, 4, 7);
/* { dg-begin-multiline-output "" }
__emit_string_literal_range (U"0123456789",
^~~~~~~~~~~~~
......@@ -185,8 +185,8 @@ void
test_L (void)
{
/* Digits 0-9. */
__emit_string_literal_range (L"0123456789", /* { dg-error "unable to read substring range: execution character set != source character set" } */
4, 7);
__emit_string_literal_range (L"0123456789", /* { dg-error "unable to read substring location: execution character set != source character set" } */
6, 4, 7);
/* { dg-begin-multiline-output "" }
__emit_string_literal_range (L"0123456789",
^~~~~~~~~~~~~
......@@ -199,10 +199,10 @@ test_macro (void)
#define START "01234" /* { dg-warning "range" } */
__emit_string_literal_range (START
"56789",
3, 6);
4, 3, 6);
/* { dg-begin-multiline-output "" }
#define START "01234"
^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
~^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
__emit_string_literal_range (START
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
"56789",
......
......@@ -3,7 +3,7 @@
/* See the notes in diagnostic-test-string-literals-1.c.
This test case has caret-printing disabled. */
extern void __emit_string_literal_range (const void *literal,
extern void __emit_string_literal_range (const void *literal, int caret_idx,
int start_idx, int end_idx);
/* Test of a stringified macro argument, by itself. */
......@@ -12,8 +12,8 @@ test_stringified_token_1 (int x)
{
#define STRINGIFY(EXPR) #EXPR
__emit_string_literal_range (STRINGIFY(x > 0), /* { dg-error "unable to read substring range: macro expansion" } */
0, 4);
__emit_string_literal_range (STRINGIFY(x > 0), /* { dg-error "unable to read substring location: macro expansion" } */
0, 0, 4);
#undef STRINGIFY
}
......@@ -23,14 +23,14 @@ test_stringified_token_1 (int x)
void
test_stringized_token_2 (int x)
{
#define EXAMPLE(EXPR, START_IDX, END_IDX) \
#define EXAMPLE(EXPR, CARET_IDX, START_IDX, END_IDX) \
do { \
__emit_string_literal_range (" before " #EXPR " after \n", \
START_IDX, END_IDX); \
CARET_IDX, START_IDX, END_IDX); \
} while (0)
EXAMPLE(x > 0, 1, 6);
/* { dg-error "unable to read substring range: cpp_interpret_string_1 failed" "" { target *-*-* } 28 } */
EXAMPLE(x > 0, 1, 1, 6);
/* { dg-error "unable to read substring location: cpp_interpret_string_1 failed" "" { target *-*-* } 28 } */
#undef EXAMPLE
}
......@@ -43,8 +43,8 @@ test_stringified_token_3 (int x)
#define XSTR(s) STR(s)
#define STR(s) #s
#define FOO 123456789
__emit_string_literal_range (XSTR (FOO), /* { dg-error "unable to read substring range: macro expansion" } */
2, 3);
__emit_string_literal_range (XSTR (FOO), /* { dg-error "unable to read substring location: macro expansion" } */
2, 2, 3);
#undef XSTR
#undef STR
......
......@@ -95,14 +95,12 @@ check_for_named_call (gimple *stmt,
return call;
}
/* Emit a warning covering SRC_RANGE, with the caret at the start of
SRC_RANGE. */
/* Emit a warning at LOC. */
static void
emit_warning (source_range src_range)
emit_warning (location_t loc)
{
location_t loc
= make_location (src_range.m_start, src_range.m_start, src_range.m_finish);
source_range src_range = get_range_from_loc (line_table, loc);
warning_at (loc, 0, "range %i:%i-%i:%i",
LOCATION_LINE (src_range.m_start),
LOCATION_COLUMN (src_range.m_start),
......@@ -114,14 +112,14 @@ emit_warning (source_range src_range)
within string literals, for use by diagnostic-test-string-literals-*.c.
Emit a warning showing the range of a string literal, for each call to
a function named "__emit_string_literal_range".
The initial argument should be a string literal; arguments 2 and 3
should be integer constants, giving the range within the string
The initial argument should be a string literal; arguments 2, 3, and 4
should be integer constants, giving the caret and range within the string
to be printed. */
static void
test_string_literals (gimple *stmt)
{
gcall *call = check_for_named_call (stmt, "__emit_string_literal_range", 3);
gcall *call = check_for_named_call (stmt, "__emit_string_literal_range", 4);
if (!call)
return;
......@@ -141,32 +139,40 @@ test_string_literals (gimple *stmt)
return;
}
tree t_start_idx = gimple_call_arg (call, 1);
if (TREE_CODE (t_start_idx) != INTEGER_CST)
tree t_caret_idx = gimple_call_arg (call, 1);
if (TREE_CODE (t_caret_idx) != INTEGER_CST)
{
error_at (call->location, "integer constant required for arg 2");
return;
}
int caret_idx = TREE_INT_CST_LOW (t_caret_idx);
tree t_start_idx = gimple_call_arg (call, 2);
if (TREE_CODE (t_start_idx) != INTEGER_CST)
{
error_at (call->location, "integer constant required for arg 3");
return;
}
int start_idx = TREE_INT_CST_LOW (t_start_idx);
tree t_end_idx = gimple_call_arg (call, 2);
tree t_end_idx = gimple_call_arg (call, 3);
if (TREE_CODE (t_end_idx) != INTEGER_CST)
{
error_at (call->location, "integer constant required for arg 3");
error_at (call->location, "integer constant required for arg 4");
return;
}
int end_idx = TREE_INT_CST_LOW (t_end_idx);
/* A STRING_CST doesn't have a location, but the ADDR_EXPR does. */
location_t strloc = EXPR_LOCATION (t_addr_string);
source_range src_range;
location_t loc;
substring_loc substr_loc (strloc, TREE_TYPE (t_string),
start_idx, end_idx);
const char *err = substr_loc.get_range (&src_range);
caret_idx, start_idx, end_idx);
const char *err = substr_loc.get_location (&loc);
if (err)
error_at (strloc, "unable to read substring range: %s", err);
error_at (strloc, "unable to read substring location: %s", err);
else
emit_warning (src_range);
emit_warning (loc);
}
/* Call test_string_literals on every statement within FUN. */
......
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