[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