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