+/*
+ * This file is part of cparser.
+ * Copyright (C) 2007-2009 Matthias Braun <matze@braunis.de>
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
+ * 02111-1307, USA.
+ */
+#include <assert.h>
#include <stdio.h>
#include <string.h>
+
+#include "adt/util.h"
#include "warning.h"
+#include "help.h"
+
+static warning_switch_t warning[] = {
+ [WARN_ADDRESS] = { WARN_STATE_ON, "address" },
+ [WARN_AGGREGATE_RETURN] = { WARN_STATE_NONE, "aggregate-return" },
+ [WARN_ATTRIBUTE] = { WARN_STATE_ON, "attribute" },
+ [WARN_CAST_QUAL] = { WARN_STATE_NONE, "cast-qual", },
+ [WARN_CHAR_SUBSCRIPTS] = { WARN_STATE_ON, "char-subscripts", },
+ [WARN_COMMENT] = { WARN_STATE_NONE, "comment", },
+ [WARN_CONVERSION] = { WARN_STATE_NONE, "conversion", },
+ [WARN_DECLARATION_AFTER_STATEMENT] = { WARN_STATE_NONE, "declaration-after-statement", },
+ [WARN_DEPRECATED_DECLARATIONS] = { WARN_STATE_ON, "deprecated-declarations", },
+ [WARN_DIV_BY_ZERO] = { WARN_STATE_ON, "div-by-zero", },
+ [WARN_EMPTY_STATEMENT] = { WARN_STATE_NONE, "empty-statement", },
+ [WARN_ERROR] = { WARN_STATE_NONE, "error" },
+ [WARN_FATAL_ERRORS] = { WARN_STATE_NONE, "fatal-errors" },
+ [WARN_FLOAT_EQUAL] = { WARN_STATE_NONE, "float-equal", },
+ [WARN_FORMAT] = { WARN_STATE_ON, "format" },
+ [WARN_IMPLICIT_FUNCTION_DECLARATION] = { WARN_STATE_ON, "implicit-function-declaration" },
+ [WARN_IMPLICIT_INT] = { WARN_STATE_ON, "implicit-int" },
+ [WARN_INIT_SELF] = { WARN_STATE_ON, "init-self", },
+ [WARN_LONG_LONG] = { WARN_STATE_NONE, "long-long" },
+ [WARN_MAIN] = { WARN_STATE_ON, "main", },
+ [WARN_MISSING_DECLARATIONS] = { WARN_STATE_NONE, "missing-declarations", },
+ [WARN_MISSING_NORETURN] = { WARN_STATE_NONE, "missing-noreturn", },
+ [WARN_MISSING_PROTOTYPES] = { WARN_STATE_NONE, "missing-prototypes", },
+ [WARN_MULTICHAR] = { WARN_STATE_ON, "multichar", },
+ [WARN_NESTED_EXTERNS] = { WARN_STATE_NONE, "nested-externs" },
+ [WARN_NONNULL] = { WARN_STATE_ON, "nonnull", },
+ [WARN_OLD_STYLE_DEFINITION] = { WARN_STATE_NONE, "old-style-definition", },
+ [WARN_OTHER] = { WARN_STATE_ON, "other" },
+ [WARN_PACKED] = { WARN_STATE_NONE, "packed", },
+ [WARN_PADDED] = { WARN_STATE_NONE, "padded", },
+ [WARN_PARENTHESES] = { WARN_STATE_NONE, "parentheses", },
+ [WARN_POINTER_ARITH] = { WARN_STATE_ON, "pointer-arith", },
+ [WARN_REDUNDANT_DECLS] = { WARN_STATE_ON, "redundant-decls", },
+ [WARN_RETURN_TYPE] = { WARN_STATE_ON, "return-type", },
+ [WARN_SHADOW] = { WARN_STATE_NONE, "shadow", },
+ [WARN_SHADOW_LOCAL] = { WARN_STATE_NONE, "shadow-local", },
+ [WARN_SIGN_COMPARE] = { WARN_STATE_NONE, "sign-compare", },
+ [WARN_STRICT_PROTOTYPES] = { WARN_STATE_ON, "strict-prototypes" },
+ [WARN_SWITCH_DEFAULT] = { WARN_STATE_NONE, "switch-default", },
+ [WARN_SWITCH_ENUM] = { WARN_STATE_NONE, "switch-enum", },
+ [WARN_TRADITIONAL] = { WARN_STATE_NONE, "traditional" },
+ [WARN_UNINITIALIZED] = { WARN_STATE_ON, "uninitialized", },
+ [WARN_UNKNOWN_PRAGMAS] = { WARN_STATE_ON, "unknown-pragmas", },
+ [WARN_UNREACHABLE_CODE] = { WARN_STATE_NONE, "unreachable-code" },
+ [WARN_UNUSED_FUNCTION] = { WARN_STATE_NONE, "unused-function", },
+ [WARN_UNUSED_LABEL] = { WARN_STATE_NONE, "unused-label", },
+ [WARN_UNUSED_PARAMETER] = { WARN_STATE_NONE, "unused-parameter", },
+ [WARN_UNUSED_VALUE] = { WARN_STATE_ON, "unused-value", },
+ [WARN_UNUSED_VARIABLE] = { WARN_STATE_NONE, "unused-variable", },
+ [WARN_WRITE_STRINGS] = { WARN_STATE_NONE, "write-strings", },
+};
+
+warning_switch_t const *get_warn_switch(warning_t const w)
+{
+ assert((size_t)w < lengthof(warning));
+ assert(warning[w].name);
+ return &warning[w];
+}
+
+void print_warning_opt_help(void)
+{
+ /* TODO: write explanations */
+ for (warning_switch_t* i = warning; i != endof(warning); ++i) {
+ put_help(i->name, "");
+ }
+}
void set_warning_opt(const char *const opt)
{
- const char* s = opt;
+ /* Process prefixes: -W[no-][error=] */
+ char const *s = opt;
+ bool const no = strncmp(s, "no-", 3) == 0 ? s += 3, true : false;
+ bool const error = strncmp(s, "error=", 6) == 0 ? s += 6, true : false;
- bool state = true;
- /* no- modifier */
- if (s[0] == 'n' && s[1] == 'o' && s[2] == '-') {
- s += 3;
- state = false;
+ warn_state_t on = WARN_STATE_NONE;
+ warn_state_t off = WARN_STATE_NONE;
+ if (!no || !error)
+ on |= WARN_STATE_ON;
+ if (error) {
+ on |= WARN_STATE_ERROR;
+ off |= WARN_STATE_NO_ERROR;
+ }
+ if (no) {
+ warn_state_t const tmp = on;
+ on = off;
+ off = tmp;
}
- if (0) {}
+ for (warning_switch_t* i = warning; i != endof(warning); ++i) {
+ if (strcmp(i->name, s) == 0) {
+ i->state = (i->state & ~off) | on;
+ return;
+ }
+ }
+
+ if (s[0] == '\0') { // -W is an alias for -Wextra
+ goto extra;
+ }
#define OPTX(x) else if (strcmp(s, x) == 0)
-#define SET(y) warning.y = state;
-#define OPT(x, y) OPTX(x) SET(y)
- OPT("char-subscripts", char_subscripts)
- OPT("empty-statement", empty_statement)
- OPT("error", s_are_errors)
- OPT("fatal-errors", fatal_errors)
- OPT("float-equal", float_equal)
- OPT("format", check_format)
+#define SET(y) (void)(warning[y].state = (warning[y].state & ~off) | on)
+ OPTX("all") {
+ /* Note: this switched on a lot more warnings than gcc's -Wall */
+ SET(WARN_ADDRESS);
+ SET(WARN_ATTRIBUTE);
+ SET(WARN_CHAR_SUBSCRIPTS);
+ SET(WARN_COMMENT);
+ SET(WARN_EMPTY_STATEMENT);
+ SET(WARN_FORMAT);
+ SET(WARN_IMPLICIT_FUNCTION_DECLARATION);
+ SET(WARN_IMPLICIT_INT);
+ SET(WARN_INIT_SELF);
+ SET(WARN_MAIN);
+ SET(WARN_MISSING_DECLARATIONS);
+ SET(WARN_NONNULL);
+ SET(WARN_OTHER);
+ SET(WARN_PARENTHESES);
+ SET(WARN_POINTER_ARITH);
+ SET(WARN_REDUNDANT_DECLS);
+ SET(WARN_RETURN_TYPE);
+ SET(WARN_SHADOW_LOCAL);
+ SET(WARN_SIGN_COMPARE);
+ SET(WARN_STRICT_PROTOTYPES);
+ SET(WARN_SWITCH_ENUM);
+ SET(WARN_UNINITIALIZED);
+ SET(WARN_UNKNOWN_PRAGMAS);
+ SET(WARN_UNREACHABLE_CODE);
+ SET(WARN_UNUSED_FUNCTION);
+ SET(WARN_UNUSED_LABEL);
+ SET(WARN_UNUSED_PARAMETER);
+ SET(WARN_UNUSED_VALUE);
+ SET(WARN_UNUSED_VARIABLE);
+ }
+ OPTX("extra") {
+extra:
+ /* TODO */
+ // TODO SET(function_end_without_return);
+ SET(WARN_EMPTY_STATEMENT);
+ // TODO SET(incomplete_aggregate_init);
+ // TODO SET(missing_field_initializers);
+ // TODO SET(pointless_comparison);
+ SET(WARN_SHADOW);
+ SET(WARN_UNUSED_PARAMETER);
+ SET(WARN_UNUSED_VALUE);
+ }
OPTX("implicit") {
- SET(implicit_function_declaration)
- SET(implicit_int)
+ SET(WARN_IMPLICIT_FUNCTION_DECLARATION);
+ SET(WARN_IMPLICIT_INT);
}
- OPT("implicit-function-declaration", implicit_function_declaration)
- OPT("implicit-int", implicit_int)
- OPT("main", main)
- OPT("missing-declarations", missing_declarations)
- OPT("missing-prototypes", missing_prototypes)
- OPT("redundant-decls", redundant_decls)
- OPT("strict-prototypes", strict_prototypes)
- OPT("switch-default", switch_default)
- OPT("unknown-pragmas", unknown_pragmas)
- OPT("unused-label", unused_label)
- OPT("unused-parameter", unused_parameter)
- OPT("unused-variable", unused_variable)
-#if 0
OPTX("unused") {
- SET(unused_function)
- SET(unused_label)
- SET(unused_parameter)
- SET(unused_variable)
- SET(unused_value)
+ SET(WARN_UNUSED_FUNCTION);
+ SET(WARN_UNUSED_LABEL);
+ SET(WARN_UNUSED_PARAMETER);
+ SET(WARN_UNUSED_VALUE);
+ SET(WARN_UNUSED_VARIABLE);
}
-#endif
- OPT("unused-value", unused_value)
-#undef OPT
#undef SET
#undef OPT_X
+ else if (strcmp(opt /* sic */, "error-implicit-function-declaration") == 0) {
+ /* GCC legacy: This way it only can be activated. */
+ warning[WARN_IMPLICIT_FUNCTION_DECLARATION].state = WARN_STATE_ON | WARN_STATE_ERROR;
+ return;
+ }
else {
fprintf(stderr, "warning: ignoring unknown option -W%s\n", opt);
}
}
-warning_t warning = {
- .char_subscripts = true,
- .check_format = true,
- .empty_statement = false,
- .fatal_errors = false,
- .float_equal = false,
- .implicit_function_declaration = true,
- .implicit_int = true,
- .main = true,
- .missing_declarations = false,
- .missing_prototypes = false,
- .redundant_decls = true,
- .s_are_errors = false,
- .strict_prototypes = true,
- .switch_default = false,
- .unknown_pragmas = true,
- .unused_label = false,
- .unused_parameter = false,
- .unused_variable = false,
- .unused_value = true
-};
+void disable_all_warnings(void)
+{
+ for (warning_switch_t* i = warning; i != endof(warning); ++i) {
+ if (i != &warning[WARN_ERROR] &&
+ i != &warning[WARN_FATAL_ERRORS]) {
+ i->state &= ~WARN_STATE_ON;
+ }
+ }
+}