/*
* This file is part of cparser.
- * Copyright (C) 2007-2008 Matthias Braun <matze@braunis.de>
+ * 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
* 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"
-warning_t warning = {
- .aggregate_return = false,
- .attribute = true,
- .cast_qual = false,
- .char_subscripts = true,
- .comment = false,
- .declaration_after_statement = false,
- .deprecated_declarations = true,
- .div_by_zero = true,
- .empty_statement = false,
- .fatal_errors = false,
- .float_equal = false,
- .format = true,
- .implicit_function_declaration = true,
- .implicit_int = true,
- .long_long = false,
- .main = true,
- .missing_declarations = false,
- .missing_noreturn = false,
- .missing_prototypes = false,
- .multichar = true,
- .nested_externs = false,
- .nonnull = true,
- .pointer_arith = true,
- .redundant_decls = true,
- .return_type = true,
- .s_are_errors = false,
- .shadow = false,
- .sign_compare = false,
- .strict_prototypes = true,
- .switch_default = false,
- .switch_enum = false,
- .unknown_pragmas = true,
- .unreachable_code = false,
- .unused_function = false,
- .unused_label = false,
- .unused_parameter = false,
- .unused_value = true,
- .unused_variable = false,
- .write_strings = false
+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;
+ 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;
+ }
- /* "no-" prefix */
- if (s[0] == 'n' && s[1] == 'o' && s[2] == '-') {
- s += 3;
- state = false;
+ for (warning_switch_t* i = warning; i != endof(warning); ++i) {
+ if (strcmp(i->name, s) == 0) {
+ i->state = (i->state & ~off) | on;
+ return;
+ }
}
- if (0) {}
+ if (s[0] == '\0') { // -W is an alias for -Wextra
+ goto extra;
+ }
#define OPTX(x) else if (strcmp(s, x) == 0)
-#define SET(y) (void)(warning.y = state)
-#define OPT(x, y) OPTX(x) SET(y)
+#define SET(y) (void)(warning[y].state = (warning[y].state & ~off) | on)
OPTX("all") {
- /* Note: this switched on a lot of more warnings than gcc's -Wall */
- SET(attribute);
- SET(char_subscripts);
- SET(comment);
- SET(empty_statement);
- SET(format);
- SET(implicit_function_declaration);
- SET(implicit_int);
- SET(main);
- SET(nonnull);
- SET(pointer_arith);
- SET(redundant_decls);
- SET(return_type);
- SET(shadow);
- SET(sign_compare);
- SET(strict_prototypes);
- SET(switch_enum);
- SET(unknown_pragmas);
- SET(unreachable_code);
- SET(unused_function);
- SET(unused_label);
- SET(unused_parameter);
- SET(unused_value);
- SET(unused_variable);
+ /* 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);
}
- OPT("aggregate-return", aggregate_return);
- OPT("attribute", attribute);
- OPT("cast-qual", cast_qual);
- OPT("char-subscripts", char_subscripts);
- OPT("comment", comment);
- OPT("declaration-after-statement", declaration_after_statement);
- OPT("deprecated-declarations", deprecated_declarations);
- OPT("div_by_zero", div_by_zero);
- OPT("empty-statement", empty_statement);
- OPT("error", s_are_errors);
OPTX("extra") {
+extra:
/* TODO */
// TODO SET(function_end_without_return);
- SET(empty_statement);
+ SET(WARN_EMPTY_STATEMENT);
// TODO SET(incomplete_aggregate_init);
// TODO SET(missing_field_initializers);
// TODO SET(pointless_comparison);
- SET(unused_parameter);
- SET(unused_value);
- }
- OPT("fatal-errors", fatal_errors);
- OPT("float-equal", float_equal);
- OPTX("format") {
- SET(format);
- SET(nonnull);
+ 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("long-long", long_long);
- OPT("main", main);
- OPT("missing-declarations", missing_declarations);
- OPT("missing-noreturn", missing_noreturn);
- OPT("missing-prototypes", missing_prototypes);
- OPT("multichar", multichar);
- OPT("nested-externs", nested_externs);
- OPT("nonnull", nonnull);
- OPT("pointer_arith", pointer_arith);
- OPT("redundant-decls", redundant_decls);
- OPT("return-type", return_type);
- OPT("shadow", shadow);
- OPT("sign-compare", sign_compare);
- OPT("strict-prototypes", strict_prototypes);
- OPT("switch-default", switch_default);
- OPT("switch-enum", switch_enum);
- OPT("unknown-pragmas", unknown_pragmas);
- OPT("unreachable-code", unreachable_code);
OPTX("unused") {
- SET(unused_function);
- SET(unused_label);
- SET(unused_parameter);
- SET(unused_value);
- SET(unused_variable);
+ SET(WARN_UNUSED_FUNCTION);
+ SET(WARN_UNUSED_LABEL);
+ SET(WARN_UNUSED_PARAMETER);
+ SET(WARN_UNUSED_VALUE);
+ SET(WARN_UNUSED_VARIABLE);
}
- OPT("unused-function", unused_function);
- OPT("unused-label", unused_label);
- OPT("unused-parameter", unused_parameter);
- OPT("unused-value", unused_value);
- OPT("unused-variable", unused_variable);
- OPT("write-strings", write_strings);
-#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);
}
}
+
+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;
+ }
+ }
+}