]> git.saurik.com Git - bison.git/blame - src/complain.c
glr: allow spaces between "%?" and "{" in predicates
[bison.git] / src / complain.c
CommitLineData
a0f6b076 1/* Declaration for error-reporting function for Bison.
2cec9080 2
7d6bad19 3 Copyright (C) 2000-2002, 2004-2006, 2009-2013 Free Software
575619af 4 Foundation, Inc.
a0f6b076 5
f16b0819
PE
6 This program is free software: you can redistribute it and/or modify
7 it under the terms of the GNU General Public License as published by
8 the Free Software Foundation, either version 3 of the License, or
9 (at your option) any later version.
a0f6b076
AD
10
11 This program is distributed in the hope that it will be useful,
12 but WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 GNU General Public License for more details.
15
16 You should have received a copy of the GNU General Public License
f16b0819 17 along with this program. If not, see <http://www.gnu.org/licenses/>. */
a0f6b076
AD
18
19/* Based on error.c and error.h,
20 written by David MacKenzie <djm@gnu.ai.mit.edu>. */
21
2cec9080 22#include <config.h>
342b8b6e 23#include "system.h"
a0f6b076 24
12bc1c9e 25#include <argmatch.h>
21184140 26#include <stdarg.h>
4d699f44 27#include <progname.h>
a0f6b076 28
a0f6b076 29#include "complain.h"
4b68955b 30#include "files.h"
89eb3c76 31#include "getargs.h"
1dc927a7 32#include "quote.h"
a0f6b076 33
808e523d 34err_status complaint_status = status_none;
d0f11c1b 35
808e523d 36bool warnings_are_errors = false;
12bc1c9e 37
e4678430
AD
38/** Whether -Werror/-Wno-error was applied to a warning. */
39typedef enum
40 {
41 errority_unset = 0, /** No explict status. */
42 errority_disabled = 1, /** Explictly disabled with -Wno-error=foo. */
43 errority_enabled = 2 /** Explictly enabled with -Werror=foo. */
44 } errority;
45
46/** For each warning type, its errority. */
47static errority errority_flag[warnings_size];
48
12bc1c9e
AD
49/** Diagnostics severity. */
50typedef enum
51 {
2b7fe38c
AD
52 severity_disabled = 0, /**< Explicitly disabled via -Wno-foo. */
53 severity_unset = 1, /**< Unspecified status. */
54 severity_warning = 2, /**< A warning. */
55 severity_error = 3, /**< An error (continue, but die soon). */
56 severity_fatal = 4 /**< Fatal error (die now). */
12bc1c9e
AD
57 } severity;
58
59
60/** For each warning type, its severity. */
61static severity warnings_flag[warnings_size];
9503b0a4 62
66381412 63static unsigned *indent_ptr = 0;
12bc1c9e
AD
64
65/*------------------------.
66| --warnings's handling. |
67`------------------------*/
68
69static const char * const warnings_args[] =
70{
71 "none",
72 "midrule-values",
73 "yacc",
74 "conflicts-sr",
75 "conflicts-rr",
76 "deprecated",
f68a49ed 77 "empty-rule",
12bc1c9e
AD
78 "precedence",
79 "other",
80 "all",
81 "error",
f24695ef 82 "everything",
12bc1c9e
AD
83 0
84};
85
86static const int warnings_types[] =
87{
88 Wnone,
89 Wmidrule_values,
90 Wyacc,
91 Wconflicts_sr,
92 Wconflicts_rr,
93 Wdeprecated,
f68a49ed 94 Wempty_rule,
12bc1c9e
AD
95 Wprecedence,
96 Wother,
97 Wall,
f24695ef
AD
98 Werror,
99 Weverything
12bc1c9e
AD
100};
101
102ARGMATCH_VERIFY (warnings_args, warnings_types);
103
104void
105warning_argmatch (char const *arg, size_t no, size_t err)
106{
107 int value = XARGMATCH ("--warning", arg + no + err,
108 warnings_args, warnings_types);
109
f24695ef 110 /* -Wnone == -Wno-everything, and -Wno-none == -Weverything. */
12bc1c9e
AD
111 if (!value)
112 {
f24695ef 113 value = Weverything;
12bc1c9e
AD
114 no = !no;
115 }
116
e4678430
AD
117 size_t b;
118 for (b = 0; b < warnings_size; ++b)
119 if (value & 1 << b)
120 {
121 if (err && no)
122 /* -Wno-error=foo. */
123 errority_flag[b] = errority_disabled;
124 else if (err && !no)
12bc1c9e 125 {
e4678430
AD
126 /* -Werror=foo: enables -Wfoo. */
127 errority_flag[b] = errority_enabled;
128 warnings_flag[b] = severity_warning;
12bc1c9e 129 }
e4678430
AD
130 else if (no)
131 /* -Wno-foo. */
132 warnings_flag[b] = severity_disabled;
133 else
134 /* -Wfoo. */
135 warnings_flag[b] = severity_warning;
136 }
12bc1c9e
AD
137}
138
139/** Decode a comma-separated list of arguments from -W.
140 *
141 * \param args comma separated list of effective subarguments to decode.
142 * If 0, then activate all the flags.
143 */
144
145void
146warnings_argmatch (char *args)
147{
148 if (args)
149 for (args = strtok (args, ","); args; args = strtok (NULL, ","))
150 if (STREQ (args, "error"))
151 warnings_are_errors = true;
152 else if (STREQ (args, "no-error"))
e4678430 153 warnings_are_errors = false;
12bc1c9e
AD
154 else
155 {
2b7fe38c 156 // The length of the possible 'no-' prefix: 3, or 0.
12bc1c9e 157 size_t no = STRPREFIX_LIT ("no-", args) ? 3 : 0;
2b7fe38c
AD
158 // The length of the possible 'error=' (possibly after
159 // 'no-') prefix: 6, or 0.
12bc1c9e
AD
160 size_t err = STRPREFIX_LIT ("error=", args + no) ? 6 : 0;
161
162 warning_argmatch (args, no, err);
163 }
164 else
165 warning_argmatch ("all", 0, 0);
166}
167
168
169/*-----------.
170| complain. |
171`-----------*/
a0f6b076 172
808e523d
AD
173void
174complain_init (void)
175{
176 warnings warnings_default =
177 Wconflicts_sr | Wconflicts_rr | Wdeprecated | Wother;
178
179 size_t b;
180 for (b = 0; b < warnings_size; ++b)
e4678430
AD
181 {
182 warnings_flag[b] = (1 << b & warnings_default
183 ? severity_warning
184 : severity_unset);
185 errority_flag[b] = errority_unset;
186 }
808e523d
AD
187}
188
e4678430
AD
189
190/* A diagnostic with FLAGS is about to be issued. With what severity?
191 (severity_fatal, severity_error, severity_disabled, or
192 severity_warning.) */
193
808e523d
AD
194static severity
195warning_severity (warnings flags)
196{
197 if (flags & fatal)
e4678430 198 /* Diagnostics about fatal errors. */
808e523d
AD
199 return severity_fatal;
200 else if (flags & complaint)
e4678430 201 /* Diagnostics about errors. */
808e523d
AD
202 return severity_error;
203 else
204 {
e4678430 205 /* Diagnostics about warnings. */
808e523d
AD
206 severity res = severity_disabled;
207 size_t b;
208 for (b = 0; b < warnings_size; ++b)
209 if (flags & 1 << b)
e4678430
AD
210 {
211 res = res < warnings_flag[b] ? warnings_flag[b] : res;
212 /* If the diagnostic is enabled, and -Werror is enabled,
213 and -Wno-error=foo was not explicitly requested, this
214 is an error. */
215 if (res == severity_warning
216 && (errority_flag[b] == errority_enabled
217 || (warnings_are_errors
218 && errority_flag[b] != errority_disabled)))
219 res = severity_error;
220 }
808e523d
AD
221 return res;
222 }
223}
224
42d101da
AD
225bool
226warning_is_unset (warnings flags)
227{
228 size_t b;
229 for (b = 0; b < warnings_size; ++b)
230 if (flags & 1 << b && warnings_flag[b] != severity_unset)
231 return false;
232 return true;
233}
808e523d 234
219458e2
AD
235/** Display a "[-Wyacc]" like message on \a f. */
236
237static void
238warnings_print_categories (warnings warn_flags, FILE *f)
b6403170 239{
219458e2 240 /* Display only the first match, the second is "-Wall". */
808e523d 241 size_t i;
219458e2
AD
242 for (i = 0; warnings_args[i]; ++i)
243 if (warn_flags & warnings_types[i])
244 {
808e523d
AD
245 severity s = warning_severity (warnings_types[i]);
246 fprintf (f, " [-W%s%s]",
247 s == severity_error ? "error=" : "",
248 warnings_args[i]);
249 return;
219458e2 250 }
b6403170 251}
a0f6b076 252
23eb2a69
AD
253/** Report an error message.
254 *
255 * \param loc the location, defaulting to the current file,
256 * or the program name.
6fb8b256 257 * \param flags the category for this message.
23eb2a69 258 * \param prefix put before the message (e.g., "warning").
2bfcac9a
JD
259 * \param message the error message, a printf format string. Iff it
260 * ends with ": ", then no trailing newline is printed,
261 * and the caller should print the remaining
262 * newline-terminated message to stderr.
23eb2a69
AD
263 * \param args the arguments of the format string.
264 */
265static
e9955c83 266void
6fb8b256 267error_message (const location *loc, warnings flags, const char *prefix,
e9690142 268 const char *message, va_list args)
e9955c83 269{
66381412
AR
270 unsigned pos = 0;
271
23eb2a69 272 if (loc)
b805eca7 273 pos += location_print (*loc, stderr);
23eb2a69 274 else
46b7d74c
TR
275 pos += fprintf (stderr, "%s", current_file ? current_file : program_name);
276 pos += fprintf (stderr, ": ");
66381412
AR
277
278 if (indent_ptr)
279 {
a686f6cd
TR
280 if (*indent_ptr)
281 prefix = NULL;
66381412
AR
282 if (!*indent_ptr)
283 *indent_ptr = pos;
284 else if (*indent_ptr > pos)
285 fprintf (stderr, "%*s", *indent_ptr - pos, "");
286 indent_ptr = 0;
287 }
e9955c83 288
23eb2a69
AD
289 if (prefix)
290 fprintf (stderr, "%s: ", prefix);
291
52489d44 292 vfprintf (stderr, message, args);
219458e2
AD
293 if (! (flags & silent))
294 warnings_print_categories (flags, stderr);
2bfcac9a
JD
295 {
296 size_t l = strlen (message);
3f5d1b2c 297 if (l < 2 || message[l - 2] != ':' || message[l - 1] != ' ')
aed41cf9
AD
298 {
299 putc ('\n', stderr);
300 fflush (stderr);
ea9e670d 301 if (loc && feature_flag & feature_caret && !(flags & no_caret))
b805eca7 302 location_caret (*loc, stderr);
aed41cf9 303 }
2bfcac9a 304 }
3f5d1b2c 305 fflush (stderr);
23eb2a69
AD
306}
307
808e523d 308/** Raise a complaint. That can be a fatal error, an error or just a
6fb8b256 309 warning. */
808e523d
AD
310
311static void
6fb8b256
VS
312complains (const location *loc, warnings flags, const char *message,
313 va_list args)
89eb3c76 314{
808e523d 315 severity s = warning_severity (flags);
697a8022
TR
316 if ((flags & complaint) && complaint_status < status_complaint)
317 complaint_status = status_complaint;
808e523d
AD
318
319 if (severity_warning <= s)
320 {
321 const char* prefix =
322 s == severity_fatal ? _("fatal error")
323 : s == severity_error ? _("error")
324 : _("warning");
325 if (severity_error <= s && ! complaint_status)
326 complaint_status = status_warning_as_error;
327 error_message (loc, flags, prefix, message, args);
328 }
329
1048a1c9 330 if (flags & fatal)
a686f6cd 331 exit (EXIT_FAILURE);
66381412
AR
332}
333
52489d44 334void
b999409e 335complain (location const *loc, warnings flags, const char *message, ...)
52489d44 336{
6fb8b256
VS
337 va_list args;
338 va_start (args, message);
bb8e56ff 339 complains (loc, flags, message, args);
6fb8b256 340 va_end (args);
23eb2a69 341}
52489d44 342
e9955c83 343void
b999409e
TR
344complain_indent (location const *loc, warnings flags, unsigned *indent,
345 const char *message, ...)
e9955c83 346{
6fb8b256 347 va_list args;
66381412 348 indent_ptr = indent;
6fb8b256 349 va_start (args, message);
b999409e 350 complains (loc, flags, message, args);
6fb8b256 351 va_end (args);
e9955c83 352}
782e8187
TR
353
354void
c6c8de16
TR
355complain_args (location const *loc, warnings w, unsigned *indent,
356 int argc, char *argv[])
782e8187
TR
357{
358 switch (argc)
359 {
f60321dc
TR
360 case 1:
361 complain_indent (loc, w, indent, "%s", _(argv[0]));
362 break;
782e8187 363 case 2:
f60321dc 364 complain_indent (loc, w, indent, _(argv[0]), argv[1]);
782e8187
TR
365 break;
366 case 3:
f60321dc 367 complain_indent (loc, w, indent, _(argv[0]), argv[1], argv[2]);
782e8187
TR
368 break;
369 case 4:
f60321dc 370 complain_indent (loc, w, indent, _(argv[0]), argv[1], argv[2], argv[3]);
782e8187
TR
371 break;
372 case 5:
f60321dc
TR
373 complain_indent (loc, w, indent, _(argv[0]), argv[1], argv[2], argv[3],
374 argv[4]);
782e8187
TR
375 break;
376 default:
377 complain (loc, fatal, "too many arguments for complains");
378 break;
379 }
1dc927a7
AD
380}
381
382void
383deprecated_directive (location const *loc, char const *old, char const *upd)
384{
385 if (feature_flag & feature_caret)
386 complain (loc, Wdeprecated,
387 _("deprecated directive, use %s"),
388 quote_n (1, upd));
389 else
390 complain (loc, Wdeprecated,
391 _("deprecated directive: %s, use %s"),
392 quote (old), quote_n (1, upd));
782e8187 393}
0fe5a72a
AD
394
395void
396duplicate_directive (char const *directive,
397 location first, location second)
398{
399 unsigned i = 0;
400 complain (&second, complaint, _("only one %s allowed per rule"), directive);
401 i += SUB_INDENT;
402 complain_indent (&first, complaint, &i, _("previous declaration"));
403}