Re: -Wshift-negative-value
Bruno Haible <[email protected]>
| Newsgroups | gmane.lisp.clisp.devel |
|---|---|
| Message-ID | <5829360.GjYYWCjSof@omega> |
Hi Daniel,
> > > > As I said on 2017-02-08, diagnostics from -Wshift-negative-value are
> > > > most probably just noise.
> > >
> > > Why not disable them then?
> >
> > Feel free to do so. Good idea.
>
> Actually, this is is a very (very) bad idea. Applying a (left) shift to a
> negative value (or shifting by a negative value) is undefined behavior
> since (AFAIK) C99 (which is what we - at least in September - wanted to
> target).
>
> Quote from (C11) standard (draft) [1]:
>
> "The result of E1 << E2 is E1 left-shifted E2 bit positions; vacated bits
> are filled with zeros. [..] If E1 has a signed type and nonnegative value
> [..] otherwise, the behavior is undefined."
> N1570 §6.5.7/4
It is undefined because ISO C supports not only two's complement representation
of signed integers, but also one's complement and sign-magnitude. Quote from
[1] § J.3.5:
"The following are implementation-defined:
...
— Whether signed integer types are represented using sign and magnitude, two’s
complement, or ones’ complement, and whether the extraordinary value is a trap
representation or an ordinary value (6.2.6.2)."
But clisp will never support anything else than two's complement arithmetic.
I haven't heard of any machine with one's complement or sign-magnitude in use
since 1980, and even gnulib - which caters to old and traditional systems -
now no longer attempts to support these odd systems [2].
> Thus every single one of those warnings is a possible Heisenbug.
> Any random optimizer pass of any compiler could horribly break our code.
Indeed. In order for this not to happen, I'm adding the gcc option "-fwrapv"
to the CFLAGS.
If, at some point, we want to get rid of this option and let the C compiler
optimize all it can, we'll need to revisit clisp's uses of signed integer
types with the help of -fsanitize=undefined (which is the successor of
the -ftrapv option [3]. -ftrapv does not catch all situations, see attached
file).
Bruno
[1] http://www.open-std.org/jtc1/sc22/wg14/www/docs/n1570.pdf
[2] http://git.savannah.gnu.org/gitweb/?p=gnulib.git;a=commitdiff;h=67d133ee7b512af59a392f533b17302d71e937db
[3] https://gcc.gnu.org/bugzilla/show_bug.cgi?id=68046#c1
------------------------------------------------------------------------------
Announcing the Oxford Dictionaries API! The API offers world-renowned
dictionary content that is easy and intuitive to access. Sign up for an
account today to start using our lexical data to power your apps and
projects. Get started today and enter our developer competition.
http://sdm.link/oxford
_______________________________________________
clisp-devel mailing list
[email protected]
https://lists.sourceforge.net/lists/listinfo/clisp-devel
test-ftrapv.c
(text/x-csrc, 721 B)
/* https://gcc.gnu.org/bugzilla/show_bug.cgi?id=68046#c1
"-fsanitize=undefined is more recommended instead of -ftrapv"
*/
int main (int argc, char *argv[])
{
int i;
switch (argv[1][0]) {
case '1':
{
int c = (-1000) << 22; /* not caught by -ftrapv */
}
break;
case '2':
{
int x = -1000;
x = x << 22; /* not caught by -ftrapv */
}
break;
case '3':
{
int y = -1000;
for (i = 0; i < 22; i++)
y = y * 2; /* caught by -ftrapv */
}
break;
case '4':
{
int z = -1000;
for (i = 0; i < 22; i++)
z = z + z; /* caught by -ftrapv */
}
break;
}
return 0;
}