X-Git-Url: https://git.saurik.com/bison.git/blobdiff_plain/12bc1c9e47a5c043e1d2bba599846732b93d062c..071863b3d88c232c10348b7c38378c47d363857c:/src/complain.c?ds=sidebyside diff --git a/src/complain.c b/src/complain.c index 1162da29..115b7043 100644 --- a/src/complain.c +++ b/src/complain.c @@ -35,14 +35,25 @@ err_status complaint_status = status_none; bool warnings_are_errors = false; +/** Whether -Werror/-Wno-error was applied to a warning. */ +typedef enum + { + errority_unset = 0, /** No explict status. */ + errority_disabled = 1, /** Explictly disabled with -Wno-error=foo. */ + errority_enabled = 2 /** Explictly enabled with -Werror=foo. */ + } errority; + +/** For each warning type, its errority. */ +static errority errority_flag[warnings_size]; + /** Diagnostics severity. */ typedef enum { - severity_disabled = 0, - severity_unset = 1, - severity_warning = 2, - severity_error = 3, - severity_fatal = 4 + severity_disabled = 0, /**< Explicitly disabled via -Wno-foo. */ + severity_unset = 1, /**< Unspecified status. */ + severity_warning = 2, /**< A warning. */ + severity_error = 3, /**< An error (continue, but die soon). */ + severity_fatal = 4 /**< Fatal error (die now). */ } severity; @@ -63,10 +74,12 @@ static const char * const warnings_args[] = "conflicts-sr", "conflicts-rr", "deprecated", + "empty-rule", "precedence", "other", "all", "error", + "everything", 0 }; @@ -78,10 +91,12 @@ static const int warnings_types[] = Wconflicts_sr, Wconflicts_rr, Wdeprecated, + Wempty_rule, Wprecedence, Wother, Wall, - Werror + Werror, + Weverything }; ARGMATCH_VERIFY (warnings_args, warnings_types); @@ -92,39 +107,33 @@ warning_argmatch (char const *arg, size_t no, size_t err) int value = XARGMATCH ("--warning", arg + no + err, warnings_args, warnings_types); - /* -Wnone == -Wno-all, and -Wno-none == -Wall. */ + /* -Wnone == -Wno-everything, and -Wno-none == -Weverything. */ if (!value) { - value = Wall; + value = Weverything; no = !no; } - if (no) - { - size_t b; - for (b = 0; b < warnings_size; ++b) - if (value & 1 << b) + size_t b; + for (b = 0; b < warnings_size; ++b) + if (value & 1 << b) + { + if (err && no) + /* -Wno-error=foo. */ + errority_flag[b] = errority_disabled; + else if (err && !no) { - if (err) - { - /* -Wno-error=foo: if foo enabled as an error, - make it a warning. */ - if (warnings_flag[b] == severity_error) - warnings_flag[b] = severity_warning; - } - else - /* -Wno-foo. */ - warnings_flag[b] = severity_disabled; + /* -Werror=foo: enables -Wfoo. */ + errority_flag[b] = errority_enabled; + warnings_flag[b] = severity_warning; } - } - else - { - size_t b; - for (b = 0; b < warnings_size; ++b) - if (value & 1 << b) - /* -Wfoo and -Werror=foo. */ - warnings_flag[b] = err ? severity_error : severity_warning; - } + else if (no) + /* -Wno-foo. */ + warnings_flag[b] = severity_disabled; + else + /* -Wfoo. */ + warnings_flag[b] = severity_warning; + } } /** Decode a comma-separated list of arguments from -W. @@ -141,13 +150,13 @@ warnings_argmatch (char *args) if (STREQ (args, "error")) warnings_are_errors = true; else if (STREQ (args, "no-error")) - { - warnings_are_errors = false; - warning_argmatch ("no-error=all", 3, 6); - } + warnings_are_errors = false; else { + // The length of the possible 'no-' prefix: 3, or 0. size_t no = STRPREFIX_LIT ("no-", args) ? 3 : 0; + // The length of the possible 'error=' (possibly after + // 'no-') prefix: 6, or 0. size_t err = STRPREFIX_LIT ("error=", args + no) ? 6 : 0; warning_argmatch (args, no, err); @@ -169,31 +178,59 @@ complain_init (void) size_t b; for (b = 0; b < warnings_size; ++b) - warnings_flag[b] = (1 << b & warnings_default - ? severity_warning - : severity_unset); + { + warnings_flag[b] = (1 << b & warnings_default + ? severity_warning + : severity_unset); + errority_flag[b] = errority_unset; + } } + +/* A diagnostic with FLAGS is about to be issued. With what severity? + (severity_fatal, severity_error, severity_disabled, or + severity_warning.) */ + static severity warning_severity (warnings flags) { if (flags & fatal) + /* Diagnostics about fatal errors. */ return severity_fatal; else if (flags & complaint) + /* Diagnostics about errors. */ return severity_error; else { + /* Diagnostics about warnings. */ severity res = severity_disabled; size_t b; for (b = 0; b < warnings_size; ++b) if (flags & 1 << b) - res = res < warnings_flag[b] ? warnings_flag[b] : res; - if (res == severity_warning && warnings_are_errors) - res = severity_error; + { + res = res < warnings_flag[b] ? warnings_flag[b] : res; + /* If the diagnostic is enabled, and -Werror is enabled, + and -Wno-error=foo was not explicitly requested, this + is an error. */ + if (res == severity_warning + && (errority_flag[b] == errority_enabled + || (warnings_are_errors + && errority_flag[b] != errority_disabled))) + res = severity_error; + } return res; } } +bool +warning_is_unset (warnings flags) +{ + size_t b; + for (b = 0; b < warnings_size; ++b) + if (flags & 1 << b && warnings_flag[b] != severity_unset) + return false; + return true; +} /** Display a "[-Wyacc]" like message on \a f. */ @@ -354,3 +391,13 @@ deprecated_directive (location const *loc, char const *old, char const *upd) _("deprecated directive: %s, use %s"), quote (old), quote_n (1, upd)); } + +void +duplicate_directive (char const *directive, + location first, location second) +{ + unsigned i = 0; + complain (&second, complaint, _("only one %s allowed per rule"), directive); + i += SUB_INDENT; + complain_indent (&first, complaint, &i, _("previous declaration")); +}