[m-rev.] for review: Fix how large negative integers are written for C89.
Julien Fischer
jfischer at opturion.com
Thu Sep 3 12:12:35 AEST 2015
Hi Peter,
On Wed, 2 Sep 2015, Peter Wang wrote:
> C does not have negative integer constants so "(MR_Integer) -nnnn"
> is the negation of a positive integer constant nnnn, converted to
> MR_Integer.
>
> In C89/C90 an unsuffixed decimal integer constant must be typed
> `int' or `long int' or `unsigned long int', whichever fits first.
> The negated result will have the same type. If nnnn > LONG_MAX then
> it will be typed `unsigned long int'. If MR_Integer is wider than
> `unsigned long int' then the conversion to MR_Integer yields a positive
> value, not negative.
>
> The solution here is essentially to write "-(MR_Integer) nnnn" so the
> integer constant is converted to a signed MR_Integer before negation.
This diff presumably shuts up the warnings we occasionally get from GCC.
It's probably worth mentioning that in the log message.
...
> diff --git a/compiler/c_util.m b/compiler/c_util.m
> index f815d0e..a6c7dc9 100644
> --- a/compiler/c_util.m
> +++ b/compiler/c_util.m
> @@ -118,6 +118,15 @@
>
> %-----------------------------------------------------------------------------%
> %
> +% Integer literals.
> +%
> +
> + % Write out an int as a C expression.
> + %
> +:- pred output_int_expr(int::in, io::di, io::uo) is det.
> +
> +%-----------------------------------------------------------------------------%
> +%
> % Float literals.
> %
>
> @@ -201,6 +210,8 @@
>
> :- import_module bool.
> :- import_module int.
> +:- import_module integer.
> +:- import_module list.
> :- import_module require.
> :- import_module string.
>
> @@ -569,6 +580,58 @@ unicode_escape_any_char(Char, EscapeCodeChars) :-
>
> %-----------------------------------------------------------------------------%
> %
> +% Integer literals.
> +%
> +
> +output_int_expr(N, !IO) :-
> + % We need to cast to (MR_Integer) to ensure things like 1 << 32 work
> + % when `MR_Integer' is 64 bits but `int' is 32 bits.
> + %
> + % C does not have negative integer constants so "(MR_Integer) -nnnn"
> + % is the negation of a positive integer constant nnnn, converted to
> + % MR_Integer.
> + %
> + % In C89/C90 an unsuffixed decimal integer constant must be typed
> + % `int' or `long int' or `unsigned long int', whichever fits first.
> + % The negated result will have the same type. If nnnn > LONG_MAX then
> + % it will be typed `unsigned long int'. If MR_Integer is wider than
> + % `unsigned long int' then the conversion to MR_Integer yields a positive
> + % value, not negative.
> + %
> + % C99 has different integer constant type rules. The unsuffixed decimal
> + % integer constant must be typed `int' or `long int' or `long long int'
> + % but not `unsigned long int'. Therefore the same problem does not occur.
> +
> + ( N >= -2147483647 ->
> + % Write integers >= -LONG_MAX in the most readable way.
> + % This is the minimum magnitude of LONG_MAX in C.
I would reword that comment to refer to the constant INT32_MAX rather
than LONG_MAX, since that avoids the need for asides about the minimum
magnitude of LONG_MAX etc.
The rest of the diff looks fine.
Julien.
More information about the reviews
mailing list