From: Ramsay Jones <ramsay@xxxxxxxxxxxxxxxxxxxx> Currently, when used on the kernel, sparse issues a bunch of warnings like: warning: constant 0x100000000 is so big it is long These warning are issued because when there is a discrepancy between the type as indicated by the suffix (or the absence of a suffix) and the real type as selected by the type suffix *and* the value of the constant. Since there is nothing incorrect with this discrepancy, (no bits are lost) these warnings are more annoying than useful. So, make them depending on a new warning flag -Wconstant-suffix and make it off by default. Signed-off-by: Ramsay Jones <ramsay@xxxxxxxxxxxxxxxxxxxx> Signed-off-by: Luc Van Oostenryck <luc.vanoostenryck@xxxxxxxxx> --- cgcc | 2 +- expression.c | 2 +- lib.c | 2 ++ lib.h | 1 + sparse.1 | 12 ++++++++++++ validation/constant-suffix-32.c | 15 +++++++++++++++ validation/constant-suffix-64.c | 15 +++++++++++++++ 7 files changed, 47 insertions(+), 2 deletions(-) create mode 100644 validation/constant-suffix-32.c create mode 100644 validation/constant-suffix-64.c diff --git a/cgcc b/cgcc index 7611dc9ff..736cb704c 100755 --- a/cgcc +++ b/cgcc @@ -101,7 +101,7 @@ exit 0; sub check_only_option { my ($arg) = @_; - return 1 if $arg =~ /^-W(no-?)?(address-space|bitwise|cast-to-as|cast-truncate|context|decl|default-bitfield-sign|designated-init|do-while|enum-mismatch|init-cstring|memcpy-max-count|non-pointer-null|old-initializer|one-bit-signed-bitfield|override-init-all|paren-string|ptr-subtraction-blows|return-void|sizeof-bool|sparse-all|sparse-error|transparent-union|typesign|undef|unknown-attribute)$/; + return 1 if $arg =~ /^-W(no-?)?(address-space|bitwise|cast-to-as|cast-truncate|constant-suffix|context|decl|default-bitfield-sign|designated-init|do-while|enum-mismatch|init-cstring|memcpy-max-count|non-pointer-null|old-initializer|one-bit-signed-bitfield|override-init-all|paren-string|ptr-subtraction-blows|return-void|sizeof-bool|sparse-all|sparse-error|transparent-union|typesign|undef|unknown-attribute)$/; return 1 if $arg =~ /^-v(no-?)?(entry|dead)$/; return 1 if $arg =~ /^-f(dump-ir|memcpy-max-count|diagnostic-prefix)(=\S*)?$/; return 1 if $arg =~ /^-f(mem2reg|optim)(-enable|-disable|=last)?$/; diff --git a/expression.c b/expression.c index 6f4300b9a..f955fb159 100644 --- a/expression.c +++ b/expression.c @@ -324,7 +324,7 @@ static void get_number_value(struct expression *expr, struct token *token) show_token(token)); want_unsigned = 1; got_it: - if (do_warn) + if (do_warn && Wconstant_suffix) warning(expr->pos, "constant %s is so big it is%s%s%s", show_token(token), want_unsigned ? " unsigned":"", diff --git a/lib.c b/lib.c index 07a5b9cda..5c2059f23 100644 --- a/lib.c +++ b/lib.c @@ -251,6 +251,7 @@ int Wbitwise = 1; int Wcast_from_as = 0; int Wcast_to_as = 0; int Wcast_truncate = 1; +int Wconstant_suffix = 0; int Wconstexpr_not_const = 0; int Wcontext = 1; int Wdecl = 1; @@ -686,6 +687,7 @@ static const struct flag warnings[] = { { "cast-from-as", &Wcast_from_as }, { "cast-to-as", &Wcast_to_as }, { "cast-truncate", &Wcast_truncate }, + { "constant-suffix", &Wconstant_suffix }, { "constexpr-not-const", &Wconstexpr_not_const}, { "context", &Wcontext }, { "decl", &Wdecl }, diff --git a/lib.h b/lib.h index cd1af9c4a..cde74e93e 100644 --- a/lib.h +++ b/lib.h @@ -141,6 +141,7 @@ extern int Wbitwise; extern int Wcast_from_as; extern int Wcast_to_as; extern int Wcast_truncate; +extern int Wconstant_suffix; extern int Wconstexpr_not_const; extern int Wcontext; extern int Wdecl; diff --git a/sparse.1 b/sparse.1 index 3e1352352..64323222b 100644 --- a/sparse.1 +++ b/sparse.1 @@ -101,6 +101,18 @@ Sparse issues these warnings by default. To turn them off, use \fB\-Wno\-cast\-truncate\fR. . .TP +.B \-Wconstant\-suffix +Warn if an integer constant is larger than the maximum representable value +of the type indicated by its type suffix (if any). For example, on a +system where ints are 32-bit and longs 64-bit, the constant \fB0x100000000U\fR +is larger than can be represented by an \fBunsigned int\fR but fits in an +\fBunsigned long\fR. So its type is \fBunsigned long\fR but this is not +indicated by its suffix. In this case, the warning could be suppressed by +using the suffix \fBUL\fR: \fB0x100000000UL\fR. + +Sparse does not issue these warnings by default. +. +.TP .B \-Wconstexpr-not-const Warn if a non-constant expression is encountered when really expecting a constant expression instead. diff --git a/validation/constant-suffix-32.c b/validation/constant-suffix-32.c new file mode 100644 index 000000000..dc063a079 --- /dev/null +++ b/validation/constant-suffix-32.c @@ -0,0 +1,15 @@ +#define BIGU 0xfffff00000000000U +#define BIGULL 0xfffff00000000000ULL + +static unsigned long long a = BIGU; +static unsigned long long b = BIGULL; + +/* + * check-name: constant-suffix + * check-command: sparse -m32 -Wconstant-suffix $file + * + * check-error-start +constant-suffix-32.c:4:31: warning: constant 0xfffff00000000000U is so big it is unsigned long long + * check-error-end + */ + diff --git a/validation/constant-suffix-64.c b/validation/constant-suffix-64.c new file mode 100644 index 000000000..e65706b02 --- /dev/null +++ b/validation/constant-suffix-64.c @@ -0,0 +1,15 @@ +#define BIGU 0xfffff00000000000U +#define BIGUL 0xfffff00000000000UL + +static unsigned long a = BIGU; +static unsigned long b = BIGUL; + +/* + * check-name: constant-suffix + * check-command: sparse -m64 -Wconstant-suffix $file + * + * check-error-start +constant-suffix-64.c:4:26: warning: constant 0xfffff00000000000U is so big it is unsigned long + * check-error-end + */ + -- 2.19.0