[m-rev.] for discussion: undefined behaviours in int.m

Julien Fischer jfischer at opturion.com
Sat Oct 22 17:38:51 AEDT 2016


Hi Peter,

On Fri, 21 Oct 2016, Peter Wang wrote:

> On Fri, 21 Oct 2016 02:56:26 +1100 (AEDT), Julien Fischer <jfischer at opturion.com> wrote:
>>
>> Hi Peter,
>>
>> On Thu, 20 Oct 2016, Peter Wang wrote:
>>>
>>> Not quite the same thing, but perhaps in future the compiler could
>>> optionally warn about uses of unchecked operations.  It might be a
>>> generalisation of pragma obsolete, like "annotations" in some languages?
>>> The user could label predicates as "unchecked" or "unsafe" or anything
>>> they like, and the compiler would warn wherever those predicates are used.
>>> A pragma or scope would allow the programmer to suppress warnings for
>>> some uses, asserting that integer overflow is impossible here, array
>>> indexing without bounds checking is safe here, etc.
>>
>> Like what we do for impurity?
>>
>
> Not like impurity.
>
> Like pragma obsolete, we could mark predicates which do not check for
> overflow, e.g.
>
>    :- pragma unchecked((+)/2).
>
> If the user code makes a call to int.+/2
>
>    :- func twice(int) = int.
>    twice(X) = X + X.
>
> the compiler can optionally warn the user that twice/1 calls int.+/2,
> which may overflow.  The user can get rid of the warning by replacing
> the call to + with a call to det_checked_add, or suppress the warning
> because twice/1 cannot overflow in practice:
>
>    :- pragma no_warn_unchecked(twice/1).
>
> The user may also wish to be told about uses of other predicates that
> require some care (usually named "unsafe" already), so the next step was
> to allow arbitrary labels/annotations to be attached to predicates or
> functions, e.g.
>
> 	% in int.m
>    :- pragma annotate((+)/2, [unchecked]).
>
> 	% in array.m
>    :- pragma annotate(unsafe_lookup/3, [unsafe]).
>
> then user can ask for warnings about uses of so-labelled predicates,
> e.g. --warn-on-use=unchecked --warn-on-use=unsafe
>
> And suppress some warnings:
>
>    :- pragma no_warn(twice/1, [unchecked]).
>
> pragma obsolete would just be a shorthand for the "obsolete" annotation.
> You could suppress warnings about calls to obsolete predicates.
>
> Perhaps predicates which use the current input/output streams could have
> been annotated with "implicit_streams", as a quick version of the
> recently added style check?
>
> Well, it's just an idea.

I think there's some merit in it.  I would definitely like a way of
saying to the compiler "this thing is unsafe" and having some way of
controlling where that unsafety propagates to (e.g. promise_safe or
something like that).  That was the basis for my comparison to impurity.

>>> I have read that C compilers take advantage of the undefined behaviour
>>> of signed integer overflow to allow optimisations that would be invalid
>>> with wrapping.  I don't know how much we would miss out on by using
>>> unsigned operations to get defined overflow behaviour.  I think that
>>> wrapping on signed ints is not that useful, though.
>>
>> Is there any reason not to require 2's complement integer representation for
>> Mercury ints?  Both C# and Java require this (so that's what you're getting for
>> those backends anyway).  In C grades, we are assuming that we have a 2's
>> complement representation in a number of spots anyway.
>
> We'd need to use unsigned integer operations to get _defined_ overflow
> behaviour, or rely on compiler switches like gcc -fwrapv or gcc
> -fno-strict-overflow.  Otherwise, the C compiler can assume that signed
> integer overflow does not happen, and generate code accordingly.
>
> I don't know if there are any performance implications for us.

I wouldn't have thought so.  The sense I've always got is that C
compilers are basically being a bit naughty doing that anyway.

>>> I have a related proposal: add unsigned_int (or 'uint') to the library,
>>> and only the library to begin with.  The standard library would use it
>>> to implement sparse_bitset, hash functions, perhaps the PRNG, avoiding
>>> the undefined behaviours of signed ints.  It would be useful to expose
>>> for users as well even without other support, which could be added
>>> incrementally (if ever).
>>
>> I have no objections to adding 'uint'.
>
> Great, it looks like there are no objections.

Actually, I've started the work of adding 'uint' as a builtin type, so
it would be helpful if you could avoid adding anything along those lines
until that has bootstrapped.

Julien.


More information about the reviews mailing list