comparison gcc/substring-locations.c @ 131:84e7813d76e9

gcc-8.2
author mir3636
date Thu, 25 Oct 2018 07:37:49 +0900
parents 04ced10e8804
children 1830386684a0
comparison
equal deleted inserted replaced
111:04ced10e8804 131:84e7813d76e9
1 /* Source locations within string literals. 1 /* Source locations within string literals.
2 Copyright (C) 2016-2017 Free Software Foundation, Inc. 2 Copyright (C) 2016-2018 Free Software Foundation, Inc.
3 3
4 This file is part of GCC. 4 This file is part of GCC.
5 5
6 GCC is free software; you can redistribute it and/or modify it under 6 GCC is free software; you can redistribute it and/or modify it under
7 the terms of the GNU General Public License as published by the Free 7 the terms of the GNU General Public License as published by the Free
18 <http://www.gnu.org/licenses/>. */ 18 <http://www.gnu.org/licenses/>. */
19 19
20 #include "config.h" 20 #include "config.h"
21 #include "system.h" 21 #include "system.h"
22 #include "coretypes.h" 22 #include "coretypes.h"
23 #include "intl.h"
23 #include "diagnostic.h" 24 #include "diagnostic.h"
24 #include "cpplib.h" 25 #include "cpplib.h"
25 #include "tree.h" 26 #include "tree.h"
26 #include "langhooks.h" 27 #include "langhooks.h"
27 #include "substring-locations.h" 28 #include "substring-locations.h"
28 29 #include "gcc-rich-location.h"
29 /* Emit a warning governed by option OPT, using GMSGID as the format 30
30 string and AP as its arguments. 31 /* format_string_diagnostic_t's ctor, giving information for use by
31 32 the emit_warning* member functions, as follows:
32 Attempt to obtain precise location information within a string 33
34 They attempt to obtain precise location information within a string
33 literal from FMT_LOC. 35 literal from FMT_LOC.
34 36
35 Case 1: if substring location is available, and is within the range of 37 Case 1: if substring location is available, and is within the range of
36 the format string itself, the primary location of the 38 the format string itself, the primary location of the
37 diagnostic is the substring range obtained from FMT_LOC, with the 39 diagnostic is the substring range obtained from FMT_LOC, with the
43 printf ("hello %i", msg); 45 printf ("hello %i", msg);
44 ~^ 46 ~^
45 47
46 Case 2: if the substring location is available, but is not within 48 Case 2: if the substring location is available, but is not within
47 the range of the format string, the primary location is that of the 49 the range of the format string, the primary location is that of the
48 format string, and an note is emitted showing the substring location. 50 format string, and a note is emitted showing the substring location.
49 51
50 For example: 52 For example:
51 test.c:90:10: warning: problem with '%i' here [-Wformat=] 53 test.c:90:10: warning: problem with '%i' here [-Wformat=]
52 printf("hello " INT_FMT " world", msg); 54 printf("hello " INT_FMT " world", msg);
53 ^~~~~~~~~~~~~~~~~~~~~~~~~ 55 ^~~~~~~~~~~~~~~~~~~~~~~~~
84 86
85 test.c:90:10: warning: '%i' here, but arg 2 is "const char *' [-Wformat=] 87 test.c:90:10: warning: '%i' here, but arg 2 is "const char *' [-Wformat=]
86 printf(fmt, msg); 88 printf(fmt, msg);
87 ^~~ ~~~ 89 ^~~ ~~~
88 90
91 If non-NULL, then FMT_LABEL will be used to label the location within the
92 string for cases 1 and 2; if non-NULL, then PARAM_LABEL will be used to label
93 the parameter. For example with case 1:
94
95 test.c:90:16: warning: '%s' here but arg 2 has 'long' type [-Wformat=]
96 printf ("foo %s bar", long_i + long_j);
97 ~^ ~~~~~~~~~~~~~~~
98 |
99 int
100
101 and with case 2:
102
103 test.c:90:10: warning: problem with '%i' here [-Wformat=]
104 printf("hello " INT_FMT " world", msg);
105 ^~~~~~~~~~~~~~~~~~~~~~~~~
106 test.c:19: note: format string is defined here
107 #define INT_FMT "%i"
108 ~^
109 |
110 int
111
89 If CORRECTED_SUBSTRING is non-NULL, use it for cases 1 and 2 to provide 112 If CORRECTED_SUBSTRING is non-NULL, use it for cases 1 and 2 to provide
90 a fix-it hint, suggesting that it should replace the text within the 113 a fix-it hint, suggesting that it should replace the text within the
91 substring range. For example: 114 substring range. For example:
92 115
93 test.c:90:10: warning: problem with '%i' here [-Wformat=] 116 test.c:90:10: warning: problem with '%i' here [-Wformat=]
94 printf ("hello %i", msg); 117 printf ("hello %i", msg);
95 ~^ 118 ~^
96 %s 119 %s
97 120
121 */
122
123 format_string_diagnostic_t::
124 format_string_diagnostic_t (const substring_loc &fmt_loc,
125 const range_label *fmt_label,
126 location_t param_loc,
127 const range_label *param_label,
128 const char *corrected_substring)
129 : m_fmt_loc (fmt_loc),
130 m_fmt_label (fmt_label),
131 m_param_loc (param_loc),
132 m_param_label (param_label),
133 m_corrected_substring (corrected_substring)
134 {
135 }
136
137 /* Emit a warning governed by option OPT, using SINGULAR_GMSGID as the
138 format string (or if PLURAL_GMSGID is different from SINGULAR_GMSGID,
139 using SINGULAR_GMSGID, PLURAL_GMSGID and N as arguments to ngettext)
140 and AP as its arguments.
141
98 Return true if a warning was emitted, false otherwise. */ 142 Return true if a warning was emitted, false otherwise. */
99 143
100 ATTRIBUTE_GCC_DIAG (5,0) 144 bool
101 bool 145 format_string_diagnostic_t::emit_warning_n_va (int opt,
102 format_warning_va (const substring_loc &fmt_loc, 146 unsigned HOST_WIDE_INT n,
103 location_t param_loc, 147 const char *singular_gmsgid,
104 const char *corrected_substring, 148 const char *plural_gmsgid,
105 int opt, const char *gmsgid, va_list *ap) 149 va_list *ap) const
106 { 150 {
107 bool substring_within_range = false; 151 bool substring_within_range = false;
108 location_t primary_loc; 152 location_t primary_loc;
109 location_t fmt_substring_loc = UNKNOWN_LOCATION; 153 location_t fmt_substring_loc = UNKNOWN_LOCATION;
110 source_range fmt_loc_range 154 source_range fmt_loc_range
111 = get_range_from_loc (line_table, fmt_loc.get_fmt_string_loc ()); 155 = get_range_from_loc (line_table, m_fmt_loc.get_fmt_string_loc ());
112 const char *err = fmt_loc.get_location (&fmt_substring_loc); 156 const char *err = m_fmt_loc.get_location (&fmt_substring_loc);
113 source_range fmt_substring_range 157 source_range fmt_substring_range
114 = get_range_from_loc (line_table, fmt_substring_loc); 158 = get_range_from_loc (line_table, fmt_substring_loc);
115 if (err) 159 if (err)
116 /* Case 3: unable to get substring location. */ 160 /* Case 3: unable to get substring location. */
117 primary_loc = fmt_loc.get_fmt_string_loc (); 161 primary_loc = m_fmt_loc.get_fmt_string_loc ();
118 else 162 else
119 { 163 {
120 if (fmt_substring_range.m_start >= fmt_loc_range.m_start 164 if (fmt_substring_range.m_start >= fmt_loc_range.m_start
121 && fmt_substring_range.m_start <= fmt_loc_range.m_finish 165 && fmt_substring_range.m_start <= fmt_loc_range.m_finish
122 && fmt_substring_range.m_finish >= fmt_loc_range.m_start 166 && fmt_substring_range.m_finish >= fmt_loc_range.m_start
128 } 172 }
129 else 173 else
130 /* Case 2. */ 174 /* Case 2. */
131 { 175 {
132 substring_within_range = false; 176 substring_within_range = false;
133 primary_loc = fmt_loc.get_fmt_string_loc (); 177 primary_loc = m_fmt_loc.get_fmt_string_loc ();
134 } 178 }
135 } 179 }
136 180
137 rich_location richloc (line_table, primary_loc); 181 /* Only use fmt_label in the initial warning for case 1. */
138 182 const range_label *primary_label = NULL;
139 if (param_loc != UNKNOWN_LOCATION) 183 if (substring_within_range)
140 richloc.add_range (param_loc, false); 184 primary_label = m_fmt_label;
141 185
142 if (!err && corrected_substring && substring_within_range) 186 auto_diagnostic_group d;
143 richloc.add_fixit_replace (fmt_substring_range, corrected_substring); 187 gcc_rich_location richloc (primary_loc, primary_label);
188
189 if (m_param_loc != UNKNOWN_LOCATION)
190 richloc.add_range (m_param_loc, SHOW_RANGE_WITHOUT_CARET, m_param_label);
191
192 if (!err && m_corrected_substring && substring_within_range)
193 richloc.add_fixit_replace (fmt_substring_range, m_corrected_substring);
144 194
145 diagnostic_info diagnostic; 195 diagnostic_info diagnostic;
146 diagnostic_set_info (&diagnostic, gmsgid, ap, &richloc, DK_WARNING); 196 if (singular_gmsgid != plural_gmsgid)
197 {
198 unsigned long gtn;
199
200 if (sizeof n <= sizeof gtn)
201 gtn = n;
202 else
203 /* Use the largest number ngettext can handle, otherwise
204 preserve the six least significant decimal digits for
205 languages where the plural form depends on them. */
206 gtn = n <= ULONG_MAX ? n : n % 1000000LU + 1000000LU;
207
208 const char *text = ngettext (singular_gmsgid, plural_gmsgid, gtn);
209 diagnostic_set_info_translated (&diagnostic, text, ap, &richloc,
210 DK_WARNING);
211 }
212 else
213 diagnostic_set_info (&diagnostic, singular_gmsgid, ap, &richloc,
214 DK_WARNING);
147 diagnostic.option_index = opt; 215 diagnostic.option_index = opt;
148 bool warned = diagnostic_report_diagnostic (global_dc, &diagnostic); 216 bool warned = diagnostic_report_diagnostic (global_dc, &diagnostic);
149 217
150 if (!err && fmt_substring_loc && !substring_within_range) 218 if (!err && fmt_substring_loc && !substring_within_range)
151 /* Case 2. */ 219 /* Case 2. */
152 if (warned) 220 if (warned)
153 { 221 {
154 rich_location substring_richloc (line_table, fmt_substring_loc); 222 /* Use fmt_label in the note for case 2. */
155 if (corrected_substring) 223 rich_location substring_richloc (line_table, fmt_substring_loc,
224 m_fmt_label);
225 if (m_corrected_substring)
156 substring_richloc.add_fixit_replace (fmt_substring_range, 226 substring_richloc.add_fixit_replace (fmt_substring_range,
157 corrected_substring); 227 m_corrected_substring);
158 inform_at_rich_loc (&substring_richloc, 228 inform (&substring_richloc,
159 "format string is defined here"); 229 "format string is defined here");
160 } 230 }
161 231
162 return warned; 232 return warned;
163 } 233 }
164 234
165 /* Variadic call to format_warning_va. */ 235 /* Singular-only version of the above. */
166 236
167 bool 237 bool
168 format_warning_at_substring (const substring_loc &fmt_loc, 238 format_string_diagnostic_t::emit_warning_va (int opt, const char *gmsgid,
169 location_t param_loc, 239 va_list *ap) const
170 const char *corrected_substring, 240 {
171 int opt, const char *gmsgid, ...) 241 return emit_warning_n_va (opt, 0, gmsgid, gmsgid, ap);
242 }
243
244 /* Variadic version of the above (singular only). */
245
246 bool
247 format_string_diagnostic_t::emit_warning (int opt, const char *gmsgid,
248 ...) const
172 { 249 {
173 va_list ap; 250 va_list ap;
174 va_start (ap, gmsgid); 251 va_start (ap, gmsgid);
175 bool warned = format_warning_va (fmt_loc, param_loc, corrected_substring, 252 bool warned = emit_warning_va (opt, gmsgid, &ap);
176 opt, gmsgid, &ap); 253 va_end (ap);
254
255 return warned;
256 }
257
258 /* Variadic version of the above (singular vs plural). */
259
260 bool
261 format_string_diagnostic_t::emit_warning_n (int opt, unsigned HOST_WIDE_INT n,
262 const char *singular_gmsgid,
263 const char *plural_gmsgid,
264 ...) const
265 {
266 va_list ap;
267 va_start (ap, plural_gmsgid);
268 bool warned = emit_warning_n_va (opt, n, singular_gmsgid, plural_gmsgid,
269 &ap);
177 va_end (ap); 270 va_end (ap);
178 271
179 return warned; 272 return warned;
180 } 273 }
181 274