return;
}
- report_line_at (get_filename (), lineno, REPORT_WARNING, line_start, name_caret, "implicit declaration of function '%s'", name);
+ if (state->warn & WARN_OLD_STYLE) {
+ report_line_at (get_filename (), lineno, REPORT_WARNING, line_start, name_caret, "implicit declaration of function '%s'", name);
+ }
if (add_global_symbol (name, GLOBAL_SYMBOL_FUNCTION, 1, line_start, name_caret, lineno)) {
}
if (current_function_is_void && has_value) {
- report_line_at (get_filename (), ret_line, REPORT_WARNING, ret_start, ret_caret, "return with a value in void function");
+
+ if (state->warn & WARN_NO_RETURN) {
+ report_line_at (get_filename (), ret_line, REPORT_WARNING, ret_start, ret_caret, "return with a value in void function");
+ }
+
} else if (!current_function_is_void && !has_value) {
- report_line_at (get_filename (), ret_line, REPORT_WARNING, ret_start, ret_caret, "return with no value in non-void function");
+
+ if (state->warn & WARN_NO_RETURN) {
+ report_line_at (get_filename (), ret_line, REPORT_WARNING, ret_start, ret_caret, "return with no value in non-void function");
+ }
+
}
if (state->ofp) {
check_goto_labels ();
if (!current_function_is_void && !current_function_has_return_statement) {
- report_line_at (function_filename_copy ? function_filename_copy : get_filename (), function_line, REPORT_WARNING, function_start, function_caret, "control reaches end of non-void function");
+
+ if (state->warn & WARN_NO_RETURN) {
+ report_line_at (function_filename_copy ? function_filename_copy : get_filename (), function_line, REPORT_WARNING, function_start, function_caret, "control reaches end of non-void function");
+ }
+
}
pending_return_jump = 0;
#include "list.h"
#include "vector.h"
+#define WARN_ERROR (1U << 0)
+#define WARN_NO_RETURN (1U << 1)
+#define WARN_SIGNEDNESS (1U << 2)
+#define WARN_CONVERSION (1U << 3)
+#define WARN_DUP_DEFINE (1U << 4)
+#define WARN_UNUSED (1U << 5)
+#define WARN_SHADOW (1U << 6)
+#define WARN_UNREACHABLE (1U << 7)
+#define WARN_FALLTHROUGH (1U << 8)
+#define WARN_OLD_STYLE (1U << 9)
+#define WARN_INITIALIZER (1U << 10)
+
+#define WARN_DEFAULT (WARN_DUP_DEFINE | WARN_UNREACHABLE)
+#define WARN_ALL (WARN_DEFAULT | WARN_NO_RETURN | WARN_SIGNEDNESS | WARN_UNUSED | WARN_FALLTHROUGH | WARN_INITIALIZER)
+#define WARN_EXTRA (WARN_ALL | WARN_CONVERSION | WARN_SHADOW | WARN_OLD_STYLE)
+
struct cc_state {
const char *ifile, *ofile;
int bits, std;
int long64;
int syntax;
+ int warn;
unsigned long max_errors;
long version;
return;
}
- report_line_at (get_filename (), lineno, REPORT_WARNING, line_start, name_caret, "implicit declaration of function '%s'", name);
+ if (state->warn & WARN_OLD_STYLE) {
+ report_line_at (get_filename (), lineno, REPORT_WARNING, line_start, name_caret, "implicit declaration of function '%s'", name);
+ }
if (add_global_symbol (name, GLOBAL_SYMBOL_FUNCTION, 1, line_start, name_caret, lineno)) {
}
if (current_function_is_void && has_value) {
- report_line_at (get_filename (), ret_line, REPORT_WARNING, ret_start, ret_caret, "return with a value in void function");
+
+ if (state->warn & WARN_NO_RETURN) {
+ report_line_at (get_filename (), ret_line, REPORT_WARNING, ret_start, ret_caret, "return with a value in void function");
+ }
+
} else if (!current_function_is_void && !has_value) {
- report_line_at (get_filename (), ret_line, REPORT_WARNING, ret_start, ret_caret, "return with no value in non-void function");
+
+ if (state->warn & WARN_NO_RETURN) {
+ report_line_at (get_filename (), ret_line, REPORT_WARNING, ret_start, ret_caret, "return with no value in non-void function");
+ }
+
}
if (state->ofp) {
check_goto_labels ();
if (!current_function_is_void && !current_function_has_return_statement) {
- report_line_at (function_filename_copy ? function_filename_copy : get_filename (), function_line, REPORT_WARNING, function_start, function_caret, "control reaches end of non-void function");
+
+ if (state->warn & WARN_NO_RETURN) {
+ report_line_at (function_filename_copy ? function_filename_copy : get_filename (), function_line, REPORT_WARNING, function_start, function_caret, "control reaches end of non-void function");
+ }
+
}
pending_return_jump = 0;
#include <ctype.h>
#include <string.h>
+#include "cc.h"
#include "int64.h"
#include "report.h"
if (bits <= 0) {
- if (a->high != 0 || a->low != 0) {
+ if ((state->warn & WARN_CONVERSION) && (a->high != 0 || a->low != 0)) {
report_at (get_filename(), get_line_number(), REPORT_WARNING, "implicit truncation of 0x%08lX%08lX to 0x00000000", a->high, a->low);
}
new_low = a->low & low_mask;
new_high = 0;
- if (a->high != 0 || (a->low & ~low_mask) != 0) {
+ if ((state->warn & WARN_CONVERSION) && (a->high != 0 || (a->low & ~low_mask) != 0)) {
report_at (get_filename(), get_line_number(), REPORT_WARNING, "implicit truncation of 0x%08lX%08lX to 0x%08lX", a->high, a->low, new_low);
}
new_low = a->low;
new_high = 0;
- if (a->high != 0) {
+ if ((state->warn & WARN_CONVERSION) && a->high != 0) {
report_at (get_filename(), get_line_number(), REPORT_WARNING, "implicit truncation of 0x%08lX%08lX to 0x%08lX", a->high, a->low, new_low);
}
new_low = a->low;
new_high = a->high & high_mask;
- if ((a->high & ~high_mask) != 0) {
+ if ((state->warn & WARN_CONVERSION) && (a->high & ~high_mask) != 0) {
report_at (get_filename(), get_line_number(), REPORT_WARNING, "implicit truncation of 0x%08lX%08lX to 0x%08lX%08lX", a->high, a->low, new_high, new_low);
}
#define CC_OPTION_STD 17
#define CC_OPTION_TRANDITIONAL_LINEMARKERS 18
#define CC_OPTION_UNDEF 19
+#define CC_OPTION_WARN 20
static struct cc_option opts[] = {
{ "-E", CC_OPTION_PREPOCESS, CC_OPTION_NO_ARG },
{ "-S", CC_OPTION_COMPILE, CC_OPTION_NO_ARG },
+ { "-W", CC_OPTION_WARN, CC_OPTION_HAS_ARG },
{ "-fno-leading-underscore", CC_OPTION_NO_LEADING_UNDERSCORE, CC_OPTION_NO_ARG },
{ "-fleading-underscore", CC_OPTION_LEADING_UNDERSCORE, CC_OPTION_NO_ARG },
}
+ state->warn = WARN_DEFAULT;
state->bits = 32;
while (optind < argc) {
}
+ case CC_OPTION_WARN: {
+
+ if (strcmp (optarg, "all") == 0) {
+
+ state->warn |= WARN_ALL;
+ break;
+
+ }
+
+ if (strcmp (optarg, "extra") == 0) {
+
+ state->warn |= WARN_EXTRA;
+ break;
+
+ }
+
+ if (strcmp (optarg, "error") == 0) {
+
+ state->warn |= WARN_ERROR;
+ break;
+
+ }
+
+ report_at (program_name, 0, REPORT_ERROR, "unrecognised -W argument");
+ exit (EXIT_FAILURE);
+
+ }
+
default: {
report_at (program_name, 0, REPORT_ERROR, "unsupported option '%s'", r);
void add_macro (char *start, char **pp, int report_line) {
- char *sname, *caret = *pp, *arg;
+ char *sname, *caret = *pp, *arg, *old_value = 0;
unsigned int len;
struct hashtab_name *key;
if ((key = find_macro (sname))) {
- if (report_line) {
- report_line_at (get_filename (), get_line_number (), REPORT_WARNING, start, caret, "\"%s\" redefined", sname);
- } else {
- report_at (get_filename (), get_line_number (), REPORT_WARNING, "\"%s\" redefined", sname);
- }
-
if ((m = hashtab_get (&hashtab_macros, key))) {
+ old_value = xstrdup (m->value);
+
while ((arg = vec_pop (&m->args))) {
free (arg);
}
}
- *pp = skip_whitespace (*pp);
-
- m->value = xstrdup (*pp);
+ m->value = xstrdup (*pp = skip_whitespace (*pp));
len = strlen (m->value);
if (is_end_of_line[(int) m->value[len - 1]]) {
m->value[len - 1] = '\0';
}
+ if (old_value) {
+
+ if (strcmp (m->value, old_value) && state->warn & WARN_DUP_DEFINE) {
+
+ if (report_line) {
+ report_line_at (get_filename (), get_line_number (), REPORT_WARNING, start, caret, "\"%s\" redefined", sname);
+ } else {
+ report_at (get_filename (), get_line_number (), REPORT_WARNING, "\"%s\" redefined", sname);
+ }
+
+ }
+
+ free (old_value);
+
+ }
+
hashtab_put (&hashtab_macros, key, m);
if (!m->is_variadic) {
static void output_message (const char *filename, unsigned long lineno, unsigned long idx, int type, const char *fmt, va_list ap) {
+ if (type == REPORT_WARNING && state && (state->warn & WARN_ERROR)) {
+ type = REPORT_ERROR;
+ }
+
if (has_include_stack ()) {
print_include_stack ();
}