aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDavid Malcolm <dmalcolm@redhat.com>2016-08-16 18:19:34 +0000
committerDavid Malcolm <dmalcolm@redhat.com>2016-08-16 18:19:34 +0000
commitceb70819e3d01e0a9eeaf050b0ccd0f65c8a8b3f (patch)
treef13ad9e3631ebbae2255d5fef36928ccaf345409
parente2ca74cabe0d7f18e83491805ef58578afa1a02a (diff)
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". git-svn-id: https://gcc.gnu.org/svn/gcc/trunk@239510 138bc75d-0d04-0410-961f-82ee72b054a4
-rw-r--r--gcc/ChangeLog19
-rw-r--r--gcc/c-family/ChangeLog21
-rw-r--r--gcc/c-family/c-common.c16
-rw-r--r--gcc/c-family/c-common.h9
-rw-r--r--gcc/c-family/c-format.c36
-rw-r--r--gcc/input.c86
-rw-r--r--gcc/substring-locations.h13
-rw-r--r--gcc/testsuite/ChangeLog44
-rw-r--r--gcc/testsuite/gcc.dg/format/asm_fprintf-1.c6
-rw-r--r--gcc/testsuite/gcc.dg/format/c90-printf-1.c14
-rw-r--r--gcc/testsuite/gcc.dg/format/diagnostic-ranges.c50
-rw-r--r--gcc/testsuite/gcc.dg/plugin/diagnostic-test-string-literals-1.c56
-rw-r--r--gcc/testsuite/gcc.dg/plugin/diagnostic-test-string-literals-2.c18
-rw-r--r--gcc/testsuite/gcc.dg/plugin/diagnostic_plugin_test_string_literals.c40
14 files changed, 305 insertions, 123 deletions
diff --git a/gcc/ChangeLog b/gcc/ChangeLog
index dab437d3906..8bd7dfc794f 100644
--- a/gcc/ChangeLog
+++ b/gcc/ChangeLog
@@ -1,5 +1,24 @@
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
diff --git a/gcc/c-family/ChangeLog b/gcc/c-family/ChangeLog
index 84f8007bd91..ada2be00ffa 100644
--- a/gcc/c-family/ChangeLog
+++ b/gcc/c-family/ChangeLog
@@ -1,3 +1,24 @@
+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>
diff --git a/gcc/c-family/c-common.c b/gcc/c-family/c-common.c
index 51b6ca95f91..d41314693ca 100644
--- a/gcc/c-family/c-common.c
+++ b/gcc/c-family/c-common.c
@@ -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,
- m_fmt_string_loc, tok_type,
- m_start_idx, m_end_idx,
- out_range);
+ return get_source_location_for_substring (parse_in, g_string_concat_db,
+ m_fmt_string_loc, tok_type,
+ m_caret_idx, m_start_idx, m_end_idx,
+ out_loc);
}
diff --git a/gcc/c-family/c-common.h b/gcc/c-family/c-common.h
index 61f9ced2bc8..4673123fa74 100644
--- a/gcc/c-family/c-common.h
+++ b/gcc/c-family/c-common.h
@@ -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;
};
diff --git a/gcc/c-family/c-format.c b/gcc/c-family/c-format.c
index 951ffd0037c..ad434f810ce 100644
--- a/gcc/c-family/c-format.c
+++ b/gcc/c-family/c-format.c
@@ -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;
diff --git a/gcc/input.c b/gcc/input.c
index 0c5f817e83a..10cab77359d 100644
--- a/gcc/input.c
+++ b/gcc/input.c
@@ -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,
- string_concat_db *concats,
- location_t strloc,
- enum cpp_ttype type,
- int start_idx, int end_idx,
- source_range *out_range)
-{
+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_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;
+}
+
+/* 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_substring, but write to *OUT the number
+/* 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;
}
diff --git a/gcc/substring-locations.h b/gcc/substring-locations.h
index 274ebbe4a98..f839c745635 100644
--- a/gcc/substring-locations.h
+++ b/gcc/substring-locations.h
@@ -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,
- string_concat_db *concats,
- location_t strloc,
- enum cpp_ttype type,
- int start_idx, int end_idx,
- source_range *out_range);
+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,
+ location_t *out_loc);
#endif /* ! GCC_SUBSTRING_LOCATIONS_H */
diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog
index 3bc6028fa41..46141a4d753 100644
--- a/gcc/testsuite/ChangeLog
+++ b/gcc/testsuite/ChangeLog
@@ -1,3 +1,47 @@
+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
diff --git a/gcc/testsuite/gcc.dg/format/asm_fprintf-1.c b/gcc/testsuite/gcc.dg/format/asm_fprintf-1.c
index 50ca57206b1..2eabbf9190e 100644
--- a/gcc/testsuite/gcc.dg/format/asm_fprintf-1.c
+++ b/gcc/testsuite/gcc.dg/format/asm_fprintf-1.c
@@ -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" } */
diff --git a/gcc/testsuite/gcc.dg/format/c90-printf-1.c b/gcc/testsuite/gcc.dg/format/c90-printf-1.c
index 338b971da09..5329dad83a4 100644
--- a/gcc/testsuite/gcc.dg/format/c90-printf-1.c
+++ b/gcc/testsuite/gcc.dg/format/c90-printf-1.c
@@ -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" } */
diff --git a/gcc/testsuite/gcc.dg/format/diagnostic-ranges.c b/gcc/testsuite/gcc.dg/format/diagnostic-ranges.c
index ff518333b6a..63075c80609 100644
--- a/gcc/testsuite/gcc.dg/format/diagnostic-ranges.c
+++ b/gcc/testsuite/gcc.dg/format/diagnostic-ranges.c
@@ -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);
^~~~
diff --git a/gcc/testsuite/gcc.dg/plugin/diagnostic-test-string-literals-1.c b/gcc/testsuite/gcc.dg/plugin/diagnostic-test-string-literals-1.c
index 82689b44f48..d5be021896e 100644
--- a/gcc/testsuite/gcc.dg/plugin/diagnostic-test-string-literals-1.c
+++ b/gcc/testsuite/gcc.dg/plugin/diagnostic-test-string-literals-1.c
@@ -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",
diff --git a/gcc/testsuite/gcc.dg/plugin/diagnostic-test-string-literals-2.c b/gcc/testsuite/gcc.dg/plugin/diagnostic-test-string-literals-2.c
index 7851c02fb08..25cb3f055d3 100644
--- a/gcc/testsuite/gcc.dg/plugin/diagnostic-test-string-literals-2.c
+++ b/gcc/testsuite/gcc.dg/plugin/diagnostic-test-string-literals-2.c
@@ -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
diff --git a/gcc/testsuite/gcc.dg/plugin/diagnostic_plugin_test_string_literals.c b/gcc/testsuite/gcc.dg/plugin/diagnostic_plugin_test_string_literals.c
index d44612a1d09..dff999c3aa9 100644
--- a/gcc/testsuite/gcc.dg/plugin/diagnostic_plugin_test_string_literals.c
+++ b/gcc/testsuite/gcc.dg/plugin/diagnostic_plugin_test_string_literals.c
@@ -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. */