From: David Malcolm Date: Tue, 16 Aug 2016 18:19:34 +0000 (+0000) Subject: Fix caret locations in format_type_warning (PR c/72857) X-Git-Url: https://git.libre-soc.org/?a=commitdiff_plain;h=65e736c0efc463270764ea3012b9804c495c71bc;p=gcc.git 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 --- diff --git a/gcc/ChangeLog b/gcc/ChangeLog index dab437d3906..8bd7dfc794f 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,22 @@ +2016-08-16 David Malcolm + + 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 * input.c (class selftest::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 + + 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 Arnaud Charlet 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 + + 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 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. */