Fix caret locations in format_type_warning (PR c/72857)
authorDavid Malcolm <dmalcolm@redhat.com>
Tue, 16 Aug 2016 18:19:34 +0000 (18:19 +0000)
committerDavid Malcolm <dmalcolm@gcc.gnu.org>
Tue, 16 Aug 2016 18:19:34 +0000 (18:19 +0000)
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

14 files changed:
gcc/ChangeLog
gcc/c-family/ChangeLog
gcc/c-family/c-common.c
gcc/c-family/c-common.h
gcc/c-family/c-format.c
gcc/input.c
gcc/substring-locations.h
gcc/testsuite/ChangeLog
gcc/testsuite/gcc.dg/format/asm_fprintf-1.c
gcc/testsuite/gcc.dg/format/c90-printf-1.c
gcc/testsuite/gcc.dg/format/diagnostic-ranges.c
gcc/testsuite/gcc.dg/plugin/diagnostic-test-string-literals-1.c
gcc/testsuite/gcc.dg/plugin/diagnostic-test-string-literals-2.c
gcc/testsuite/gcc.dg/plugin/diagnostic_plugin_test_string_literals.c

index dab437d3906352c1b8ec4d610d2d0b9fd6866db2..8bd7dfc794fdde05fc76057a77cf16736364567d 100644 (file)
@@ -1,3 +1,22 @@
+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
index 84f8007bd91d50cc2ff5a702b94f6977c2fee7ec..ada2be00ffacbe3f7c6e0f3708585f8c0372c3c4 100644 (file)
@@ -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>
 
index 51b6ca95f912259636419322e88b4f76f26b3b84..d41314693ca009fb1e701778f9064ebad13fbfbb 100644 (file)
@@ -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);
 }
 
 \f
index 61f9ced2bc8ad6011bc35fb71da5584cf92028da..4673123fa745b733b32fe06d9b78c6ea0fa805fc 100644 (file)
@@ -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;
 };
index 951ffd0037c01c76e5bde4d0abaa2ff267666499..ad434f810ceebf2743e6f35183ed875b8264a756 100644 (file)
@@ -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;
index 0c5f817e83a52cbd8c3f812f6dc4d8773b6d1a2d..10cab77359d369a2d51feacbc063efeb192d45b5 100644 (file)
@@ -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;
     }
index 274ebbe4a987c5ca559dd07cdfa9357b34a1a73b..f839c74563550b68e45243738f1d1b67033052b8 100644 (file)
@@ -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 */
index 3bc6028fa411d8b0ee08aa50bbedb31ca6e9214f..46141a4d7537e021aab3bb74c5843f54edddaf18 100644 (file)
@@ -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
index 50ca57206b1c24d7f58852effbb057d32bf2df62..2eabbf9190e03ebab77e5a3bf2c96aff2d651e88 100644 (file)
@@ -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" } */
index 338b971da0967a2c93ffc8f4ded78f89857f7b95..5329dad83a40d430bc0567e579be5b6ed3e348c8 100644 (file)
@@ -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" } */
index ff518333b6a597b78163892256fa43abc6f2918f..63075c80609e1ca6d42d97a555d49edbce99399a 100644 (file)
@@ -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);
                     ^~~~
index 82689b44f48e0e325fca8b1a2a3f6ea8695129c6..d5be021896ec8802732186f5a9eabad33fc5022d 100644 (file)
    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",
index 7851c02fb08d9c2c2046561d4674883565cc3f8e..25cb3f055d33f0332586744e73a612b9d5c9952a 100644 (file)
@@ -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
index d44612a1d098ee3de953144678f8f20a352c0bea..dff999c3aa96e9675da5c5ae30f352b7e6aa4729 100644 (file)
@@ -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.  */