gcc80: Handle TZ specific "%+" format in strftime.
[dragonfly.git] / contrib / gcc-8.0 / gcc / substring-locations.c
1 /* Source locations within string literals.
2    Copyright (C) 2016-2018 Free Software Foundation, Inc.
3
4 This file is part of GCC.
5
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
8 Software Foundation; either version 3, or (at your option) any later
9 version.
10
11 GCC is distributed in the hope that it will be useful, but WITHOUT ANY
12 WARRANTY; without even the implied warranty of MERCHANTABILITY or
13 FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
14 for more details.
15
16 You should have received a copy of the GNU General Public License
17 along with GCC; see the file COPYING3.  If not see
18 <http://www.gnu.org/licenses/>.  */
19
20 #include "config.h"
21 #include "system.h"
22 #include "coretypes.h"
23 #include "intl.h"
24 #include "diagnostic.h"
25 #include "cpplib.h"
26 #include "tree.h"
27 #include "langhooks.h"
28 #include "substring-locations.h"
29
30 /* Emit a warning governed by option OPT, using SINGULAR_GMSGID as the
31    format string (or if PLURAL_GMSGID is different from SINGULAR_GMSGID,
32    using SINGULAR_GMSGID, PLURAL_GMSGID and N as arguments to ngettext)
33    and AP as its arguments.
34
35    Attempt to obtain precise location information within a string
36    literal from FMT_LOC.
37
38    Case 1: if substring location is available, and is within the range of
39    the format string itself, the primary location of the
40    diagnostic is the substring range obtained from FMT_LOC, with the
41    caret at the *end* of the substring range.
42
43    For example:
44
45      test.c:90:10: warning: problem with '%i' here [-Wformat=]
46      printf ("hello %i", msg);
47                     ~^
48
49    Case 2: if the substring location is available, but is not within
50    the range of the format string, the primary location is that of the
51    format string, and an note is emitted showing the substring location.
52
53    For example:
54      test.c:90:10: warning: problem with '%i' here [-Wformat=]
55      printf("hello " INT_FMT " world", msg);
56             ^~~~~~~~~~~~~~~~~~~~~~~~~
57      test.c:19: note: format string is defined here
58      #define INT_FMT "%i"
59                       ~^
60
61    Case 3: if precise substring information is unavailable, the primary
62    location is that of the whole string passed to FMT_LOC's constructor.
63    For example:
64
65      test.c:90:10: warning: problem with '%i' here [-Wformat=]
66      printf(fmt, msg);
67             ^~~
68
69    For each of cases 1-3, if param_loc is not UNKNOWN_LOCATION, then it is used
70    as a secondary range within the warning.  For example, here it
71    is used with case 1:
72
73      test.c:90:16: warning: '%s' here but arg 2 has 'long' type [-Wformat=]
74      printf ("foo %s bar", long_i + long_j);
75                   ~^       ~~~~~~~~~~~~~~~
76
77    and here with case 2:
78
79      test.c:90:16: warning: '%s' here but arg 2 has 'long' type [-Wformat=]
80      printf ("foo " STR_FMT " bar", long_i + long_j);
81              ^~~~~~~~~~~~~~~~~~~~~  ~~~~~~~~~~~~~~~
82      test.c:89:16: note: format string is defined here
83      #define STR_FMT "%s"
84                       ~^
85
86    and with case 3:
87
88      test.c:90:10: warning: '%i' here, but arg 2 is "const char *' [-Wformat=]
89      printf(fmt, msg);
90             ^~~  ~~~
91
92    If CORRECTED_SUBSTRING is non-NULL, use it for cases 1 and 2 to provide
93    a fix-it hint, suggesting that it should replace the text within the
94    substring range.  For example:
95
96      test.c:90:10: warning: problem with '%i' here [-Wformat=]
97      printf ("hello %i", msg);
98                     ~^
99                     %s
100
101    Return true if a warning was emitted, false otherwise.  */
102
103 bool
104 format_warning_n_va (const substring_loc &fmt_loc,
105                      location_t param_loc,
106                      const char *corrected_substring,
107                      int opt, unsigned HOST_WIDE_INT n,
108                      const char *singular_gmsgid,
109                      const char *plural_gmsgid, va_list *ap)
110 {
111   bool substring_within_range = false;
112   location_t primary_loc;
113   location_t fmt_substring_loc = UNKNOWN_LOCATION;
114   source_range fmt_loc_range
115     = get_range_from_loc (line_table, fmt_loc.get_fmt_string_loc ());
116   const char *err = fmt_loc.get_location (&fmt_substring_loc);
117   source_range fmt_substring_range
118     = get_range_from_loc (line_table, fmt_substring_loc);
119   if (err)
120     /* Case 3: unable to get substring location.  */
121     primary_loc = fmt_loc.get_fmt_string_loc ();
122   else
123     {
124       if (fmt_substring_range.m_start >= fmt_loc_range.m_start
125           && fmt_substring_range.m_start <= fmt_loc_range.m_finish
126           && fmt_substring_range.m_finish >= fmt_loc_range.m_start
127           && fmt_substring_range.m_finish <= fmt_loc_range.m_finish)
128         /* Case 1.  */
129         {
130           substring_within_range = true;
131           primary_loc = fmt_substring_loc;
132         }
133       else
134         /* Case 2.  */
135         {
136           substring_within_range = false;
137           primary_loc = fmt_loc.get_fmt_string_loc ();
138         }
139     }
140
141   rich_location richloc (line_table, primary_loc);
142
143   if (param_loc != UNKNOWN_LOCATION)
144     richloc.add_range (param_loc, false);
145
146   if (!err && corrected_substring && substring_within_range)
147     richloc.add_fixit_replace (fmt_substring_range, corrected_substring);
148
149   diagnostic_info diagnostic;
150   if (singular_gmsgid != plural_gmsgid)
151     {
152       unsigned long gtn;
153
154       if (sizeof n <= sizeof gtn)
155         gtn = n;
156       else
157         /* Use the largest number ngettext can handle, otherwise
158            preserve the six least significant decimal digits for
159            languages where the plural form depends on them.  */
160         gtn = n <= ULONG_MAX ? n : n % 1000000LU + 1000000LU;
161
162       const char *text = ngettext (singular_gmsgid, plural_gmsgid, gtn);
163       diagnostic_set_info_translated (&diagnostic, text, ap, &richloc,
164                                       DK_WARNING);
165     }
166   else
167     diagnostic_set_info (&diagnostic, singular_gmsgid, ap, &richloc,
168                          DK_WARNING);
169   diagnostic.option_index = opt;
170   bool warned = diagnostic_report_diagnostic (global_dc, &diagnostic);
171
172   if (!err && fmt_substring_loc && !substring_within_range)
173     /* Case 2.  */
174     if (warned)
175       {
176         rich_location substring_richloc (line_table, fmt_substring_loc);
177         if (corrected_substring)
178           substring_richloc.add_fixit_replace (fmt_substring_range,
179                                                corrected_substring);
180         inform (&substring_richloc,
181                 "format string is defined here");
182       }
183
184   return warned;
185 }
186
187 /* Singular-only version of the above.  */
188
189 bool
190 format_warning_va (const substring_loc &fmt_loc,
191                    location_t param_loc,
192                    const char *corrected_substring,
193                    int opt, const char *gmsgid, va_list *ap)
194 {
195   return format_warning_n_va (fmt_loc, param_loc, corrected_substring, opt,
196                               0, gmsgid, gmsgid, ap);
197 }
198
199 /* Variadic call to format_warning_va.  */
200
201 bool
202 format_warning_at_substring (const substring_loc &fmt_loc,
203                              location_t param_loc,
204                              const char *corrected_substring,
205                              int opt, const char *gmsgid, ...)
206 {
207   va_list ap;
208   va_start (ap, gmsgid);
209   bool warned = format_warning_va (fmt_loc, param_loc, corrected_substring,
210                                    opt, gmsgid, &ap);
211   va_end (ap);
212
213   return warned;
214 }
215
216 /* Variadic call to format_warning_n_va.  */
217
218 bool
219 format_warning_at_substring_n (const substring_loc &fmt_loc,
220                                location_t param_loc,
221                                const char *corrected_substring,
222                                int opt, unsigned HOST_WIDE_INT n,
223                                const char *singular_gmsgid,
224                                const char *plural_gmsgid, ...)
225 {
226   va_list ap;
227   va_start (ap, plural_gmsgid);
228   bool warned = format_warning_n_va (fmt_loc, param_loc, corrected_substring,
229                                      opt, n, singular_gmsgid, plural_gmsgid,
230                                      &ap);
231   va_end (ap);
232
233   return warned;
234 }
235
236 /* Attempt to determine the source location of the substring.
237    If successful, return NULL and write the source location to *OUT_LOC.
238    Otherwise return an error message.  Error messages are intended
239    for GCC developers (to help debugging) rather than for end-users.  */
240
241 const char *
242 substring_loc::get_location (location_t *out_loc) const
243 {
244   gcc_assert (out_loc);
245   return lang_hooks.get_substring_location (*this, out_loc);
246 }