static void parse_statement_suppressed (void) {
FILE *save_ofp = state->ofp;
+ FILE *discard_ofp = 0;
- state->ofp = 0;
+ /*
+ * Suppressed statements still need to go through the normal expression
+ * parser. Several expression paths use state->ofp == 0 as a special
+ * parsing mode, so simply clearing the output stream can make otherwise
+ * valid dead code fail to parse (for example `return (rc);` after an
+ * infinite loop). Emit into a temporary stream instead and discard it.
+ */
+ if (save_ofp) {
+ discard_ofp = scc_tmpfile ();
+ }
+
+ state->ofp = discard_ofp;
parse_statement ();
state->ofp = save_ofp;
+
+ if (discard_ofp) {
+ scc_close (discard_ofp);
+ }
}
#define WARN_OLD_STYLE (1U << 9)
#define WARN_INITIALIZER (1U << 10)
-#define WARN_DEFAULT (WARN_DUP_DEFINE | WARN_UNREACHABLE)
+#define WARN_DEFAULT (WARN_DUP_DEFINE)
#define WARN_ALL (WARN_DEFAULT | WARN_NO_RETURN | WARN_SIGNEDNESS | WARN_UNUSED | WARN_FALLTHROUGH | WARN_INITIALIZER)
#define WARN_EXTRA (WARN_ALL | WARN_CONVERSION | WARN_OLD_STYLE)
static void parse_statement_suppressed (void) {
FILE *save_ofp = state->ofp;
+ FILE *discard_ofp = 0;
- state->ofp = 0;
+ /*
+ * Suppressed statements still need to go through the normal expression
+ * parser. Several expression paths use state->ofp == 0 as a special
+ * parsing mode, so simply clearing the output stream can make otherwise
+ * valid dead code fail to parse (for example `return (rc);` after an
+ * infinite loop). Emit into a temporary stream instead and discard it.
+ */
+ if (save_ofp) {
+ discard_ofp = scc_tmpfile ();
+ }
+
+ state->ofp = discard_ofp;
parse_statement ();
state->ofp = save_ofp;
+
+ if (discard_ofp) {
+ scc_close (discard_ofp);
+ }
}
fprintf (stderr, " -Werror Treat all warnings as errors.\n");
fprintf (stderr, " -Wextra Print extra (possibly unwanted) warnings.\n");
fprintf (stderr, " -Wshadow Warn when one variable shadows another.\n");
+ fprintf (stderr, " -Wunreachable-code Warn about code that will never be executed.\n");
fprintf (stderr, "\n");
fprintf (stderr, " --traditional-linemarker-format Use #line instead of short form.\n");
}
+ if (strcmp (optarg, "unreachable-code") == 0) {
+
+ state->warn |= WARN_UNREACHABLE;
+ break;
+
+ }
+
report_at (program_name, 0, REPORT_ERROR, "unrecognised -W argument");
exit (EXIT_FAILURE);