Topic: signed overflow is UB, what should numeric_limits<int>::is_modulo be?
Author: algrant@myrealbox.com (Al Grant)
Date: Thu, 26 Feb 2004 12:54:57 CST Raw View
James Dennett <jdennett@acm.org> wrote in message news:<bIW_b.2434$506.1977@fed1read05>...
> scott douglass wrote:
> > In this implementation, what should numeric_limits<int>::is_modulo be?
>
> It would seem, just looking at what you've quoted above, that
> the only options for an implementation that conforms to LIA-1
> are either modular arithmetic or notification on overflow.
But the question is what is_modulo should be set to in an
implementation that doesn't conform to LIA-1. Specifically in the
UB case, setting it to false means a safety-conscious programmer
might complain "I added two positive numbers and got a number that
is less - but you told me this could never happen!" while setting
it to true means someone might say "You told me arithmetic 'wraps'
but I do not observe well-defined 'wrapping' behavior here."
My feeling is that the first programmer has a more serious and
more justified complaint and so is_modulo should be set to 'true'
if in doubt. Also, reading the standard literally would suggest
a 'true' setting on the grounds that anything is _possible_ in UB.
On the other hand on an implementation that defines integer arithmetic
to saturate (not allowed by LIA-1 but quite reasonable) the condition
"if it is possible to add two positive numbers and have a result that
wraps around to a third number that is less" is now not met and so
is_modulo must be set to false - but there is still no trap.
---
[ comp.std.c++ is moderated. To submit articles, try just posting with ]
[ your news-reader. If that fails, use mailto:std-c++@ncar.ucar.edu ]
[ --- Please see the FAQ before posting. --- ]
[ FAQ: http://www.jamesd.demon.co.uk/csc/faq.html ]
Author: Gabriel Dos Reis <gdr@cs.tamu.edu>
Date: Sat, 28 Feb 2004 20:07:31 CST Raw View
Alberto Barbati <AlbertoBarbati@libero.it> writes:
| Gabriel Dos Reis wrote:
| > I think LIA-1 words should apply and numeric_limits<int>::is_modulo
| > should be
| > (1) false, by default; and
| > (2) true only, when an implementation does chose to define the
| > "undefined behaviour" to be a modulo arithmetic -- in which
| > case, it cannot do arbitrary things.
|
| I am no LIA-1 expert, but I just found this
| http://anubis.dkuug.dk/jtc1/sc22/wg14/www/docs/n750.htm
| and, if I interpret it well, it contradicts you. About modulo
| (H.2.2.1), it sais that:
|
| "The parameter modulo is always true for the unsigned types [...].
| The parameter modulo is true when INT_OUT_OF_BOUNDS is 1 (wrap) or
| false when INT_OUT_OF_BOUNDS is 2 (notify) and covers all LIA-1
| conformant signed types. The implementation picks the value of
| modulo. It is implementation defined if the user can change the value
| of modulo."
|
| That is (for signed types):
| (1) false: notify about overflow via exception
| (2) true: wrap modulo INT_MAX-INT_MIN+1
|
| "Undefined behaviour" is not allowed.
|
| It's interesting to notice that LIA-1 allows implementation to change
| the value of modulo, however C++ defines is_modulo to be a const bool
| and not a function, so the current definition is inadeguate to express
| the LIA-1 requirements.
No, you're confused.
First of all, the document you quoted is NOT the LIA-1 specification.
It is a proposal for *C9X binding*, and anything it says does not
translate word for word to C++. The LIA-1 specification is described
in ISO/IEC 10967-1.
Second, LAI-1 does not require that the value of is_modulo can be
changed. Actually, from the LIA-1 specification, if you change that
value then you change the integer type. Here is what LIA-1 has to
say:
5.1 Integer Types
An integer type I shall be a subset of ZZ, characterized by four
parameters
bounded \in Boolean (whether the set is finite)
modulo \in Boolean (whether out-of-bounds results "wrap")
minint \in I (the smallest integer in I)
maxint \in I (the largest integer in I)
I bounded is false, the set I satisfies
I = ZZ
In this case, modulo shall be false, and the value of minint and
maxint are not meaningful.
If bounded is true, the set I satisfies
I = { x\in ZZ | minint <= x <= maxint }
and minint and maxing shall satisfy
maxint > 0
and one of: minint = 0
minint = -(maxint)
minint = -(maxint + 1)
[...]
As you can see, the parameter is_modulo is a *defining characteristic*
of an integer type. LIA-1 does make *no* guarantee that user can set
that parameter, and a fortiori whether changing that parameter gives you
back the same integer type as before (presumably it would not, since
the meanings of the supported operations change too). The only thing
LIA-1 requires is that user program has mean *to query* the value of
that parameter. In the (informative) appendices, you can read:
8 Documentation requirements
In order to conform to this part of ISO/IEC 10967, an
implementation shall include documentation providing the following
information to programmers.
[...]
b) for each integer type, the values of the parameters: bounded,
modulo, minint, maxint. (see 5.1).
In that regard, the C++ definition for numeric_limits<T>::is_modulo
fulfills the spirit and the letter of the LIA specification.
--
Gabriel Dos Reis
gdr@cs.tamu.edu
Texas A&M University -- Computer Science Department
301, Bright Building -- College Station, TX 77843-3112
---
[ comp.std.c++ is moderated. To submit articles, try just posting with ]
[ your news-reader. If that fails, use mailto:std-c++@ncar.ucar.edu ]
[ --- Please see the FAQ before posting. --- ]
[ FAQ: http://www.jamesd.demon.co.uk/csc/faq.html ]
Author: Gabriel Dos Reis <gdr@cs.tamu.edu>
Date: Sat, 28 Feb 2004 20:07:40 CST Raw View
algrant@myrealbox.com (Al Grant) writes:
| James Dennett <jdennett@acm.org> wrote in message news:<bIW_b.2434$506.1977@fed1read05>...
| > scott douglass wrote:
| > > In this implementation, what should numeric_limits<int>::is_modulo be?
| >
| > It would seem, just looking at what you've quoted above, that
| > the only options for an implementation that conforms to LIA-1
| > are either modular arithmetic or notification on overflow.
|
| But the question is what is_modulo should be set to in an
| implementation that doesn't conform to LIA-1. Specifically in the
| UB case, setting it to false means a safety-conscious programmer
| might complain "I added two positive numbers and got a number that
| is less - but you told me this could never happen!" while setting
| it to true means someone might say "You told me arithmetic 'wraps'
| but I do not observe well-defined 'wrapping' behavior here."
But, since the implementation says that overflow/underflow is
undefined behaviour, the former programmer cannot complain.
Undefined behaviour overrides the meaning of is_modulo.
There is no contradiction there. The only way that user can
possibly figure out that the value is wrapped is to take an action
that makes the user non-eligible to complain.
--
Gabriel Dos Reis
gdr@cs.tamu.edu
Texas A&M University -- Computer Science Department
301, Bright Building -- College Station, TX 77843-3112
---
[ comp.std.c++ is moderated. To submit articles, try just posting with ]
[ your news-reader. If that fails, use mailto:std-c++@ncar.ucar.edu ]
[ --- Please see the FAQ before posting. --- ]
[ FAQ: http://www.jamesd.demon.co.uk/csc/faq.html ]
Author: Gabriel Dos Reis <gdr@cs.tamu.edu>
Date: Sun, 29 Feb 2004 16:18:32 CST Raw View
Alberto Barbati <AlbertoBarbati@libero.it> writes:
| Gabriel Dos Reis wrote:
|
| > Alberto Barbati <AlbertoBarbati@libero.it> writes:
| > | Gabriel Dos Reis wrote:
| > | > I think LIA-1 words should apply and numeric_limits<int>::is_modulo
| > | > should be
| > | > (1) false, by default; and
| > | > (2) true only, when an implementation does chose to define the
| > | > "undefined behaviour" to be a modulo arithmetic -- in which
| > | > case, it cannot do arbitrary things.
| > | | I am no LIA-1 expert, but I just found this
| > | http://anubis.dkuug.dk/jtc1/sc22/wg14/www/docs/n750.htm
| > | and, if I interpret it well, it contradicts you. About modulo
| > | (H.2.2.1), it sais that:
| > | | "The parameter modulo is always true for the unsigned types
| > [...].
| > | The parameter modulo is true when INT_OUT_OF_BOUNDS is 1 (wrap) or
| > | false when INT_OUT_OF_BOUNDS is 2 (notify) and covers all LIA-1
| > | conformant signed types. The implementation picks the value of
| > | modulo. It is implementation defined if the user can change the value
| > | of modulo."
| > | | That is (for signed types):
| > | (1) false: notify about overflow via exception
| > | (2) true: wrap modulo INT_MAX-INT_MIN+1
| > | | "Undefined behaviour" is not allowed.
| > | | It's interesting to notice that LIA-1 allows implementation to
| > change
| > | the value of modulo, however C++ defines is_modulo to be a const bool
| > | and not a function, so the current definition is inadeguate to express
| > | the LIA-1 requirements.
| > No, you're confused.
| > [...]
| > In that regard, the C++ definition for numeric_limits<T>::is_modulo
| > fulfills the spirit and the letter of the LIA specification.
| >
|
| Thanks Gabriel, you have been very informative. Is there a copy of ISO
| 10967-1 publicly available on the net? I looked here:
| http://std.dkuug.dk/JTC1/SC22/WG11/ but it seems that access to the
| full document is restricted.
At the best of my knowledge, there is no publically available copy of
LIA-* -- though you might try the drafts or working papers (with the
usual caveats that they are not the final standards).
| Your remarks are only about my last statement, however. As you look to
| be very competent in this area and it seems that you have access to
| restricted documents, would you mind discussing my other statement, in
| particular the one about the meaning of is_modulo==false which would
| mean "notify" rather than "UB"?
You're right that I completely missed that part when replying.
Both C99 and C++ do not require LIA-1 semantics. As a consequence,
when the C++ standard says overflow/underflow leads to undefined
behaviour, that specification overrides anything else.
Now, an implementation is free to chose to define that "undefined
bahaviour"; for example, it may say that an exception is thrown.
But that is no standard requirement. Therefore, I stand by my earlier
statement, namely:
numeric_limits<int>::is_modulo should be
(1) false, by default; and
(2) true only, when an implementation does chose to define the
"undefined behaviour" to be a modulo arithmetic -- in which
case, it cannot do arbitrary things.
Note however that the situation would be completely different did the
C++ standard require LIA-1. In such case, an implementation would
not have the latitude it currently has. In particular,
(1) if numeric_limits<int>::is_modulo is false, then it must notify
underflow/overflow in a non-ambiguous manner -- presumably using
exceptions as recommanded (not but required) by LIA-1 for
programming languages that have exception support;
(2) if numeric_limits<int>::is_modulo is true, the the "wrapping"
function should be documented. That would correspond to a
vaste majority of *modern* architectures.
I guess the C++ standards committee might probably want to revisit
this issue as part of "upgrading" the built-in types facilities.
--
Gabriel Dos Reis
gdr@cs.tamu.edu
Texas A&M University -- Computer Science Department
301, Bright Building -- College Station, TX 77843-3112
---
[ comp.std.c++ is moderated. To submit articles, try just posting with ]
[ your news-reader. If that fails, use mailto:std-c++@ncar.ucar.edu ]
[ --- Please see the FAQ before posting. --- ]
[ FAQ: http://www.jamesd.demon.co.uk/csc/faq.html ]
Author: Gabriel Dos Reis <gdr@cs.tamu.edu>
Date: Wed, 25 Feb 2004 14:17:09 CST Raw View
scott douglass <sdouglass@arm.com> writes:
| Hi,
|
| In the C++ standard signed int overflow is undefined behavior
| (clause 5 para 5) [and the same is true in C]. Suppose a compiler
| takes advantage of this to optimize, for example:
| bool f(int i) { return i + 1 < i; }
| into this
| bool f(int) { return false; }
|
| Now, how should numeric_limits<int>::is_modulo (18.2.1.2 para 56) be
| set? The definition in the C++ standard seems pretty weak:
|
| >>
| A type is modulo if it is possible to add two positive numbers and have a
| result that wraps around to a third number that is less.
| <<
|
| The footnote there says "Required by LIA-1". LIA-1 gives a stronger
| definition of modulo in 5.1.2:
| modulo is true if certain particular operations "wrap" and
| modulo is false if overflows cause a notification
|
| But C++ allows more than these two possibilities. For the
| implementatin I'm considering some cases will wrap and some will
| silently give results different from the wrapped results.
|
| In this implementation, what should numeric_limits<int>::is_modulo be?
It is known that the wordings for numeric_limits<> are quite weak and do
not clearly reflect the intent (as indicated in the footnotes).
Those should be fixed in C++0x.
I think LIA-1 words should apply and numeric_limits<int>::is_modulo
should be
(1) false, by default; and
(2) true only, when an implementation does chose to define the
"undefined behaviour" to be a modulo arithmetic -- in which
case, it cannot do arbitrary things.
--
Gabriel Dos Reis
gdr@cs.tamu.edu
Texas A&M University -- Computer Science Department
301, Bright Building -- College Station, TX 77843-3112
---
[ comp.std.c++ is moderated. To submit articles, try just posting with ]
[ your news-reader. If that fails, use mailto:std-c++@ncar.ucar.edu ]
[ --- Please see the FAQ before posting. --- ]
[ FAQ: http://www.jamesd.demon.co.uk/csc/faq.html ]