On Fri, Oct 25, 2013 at 11:41 AM, Gabriel Dos Reis <gdr@axiomatics.org> wrote:
Matt Austern <austern@google.com> writes:

| On Fri, Oct 25, 2013 at 10:31 AM, Jeffrey Yasskin <jyasskin@google.com> wrote:
|
|
|
|     Richard explicitly asked whether any such C++ users exist or are
|     likely to exist in the future, and nobody's come up with any examples.
|     So we appear to have a choice between helping some theoretical people
|     or helping some actual people. (We help the actual people by telling
|     them what to expect in the standard, while now they have to test and
|     hope they find the right subset of undefined or implementation-defined
|     behavior that's actually guaranteed to work.)
|
|
| It's actually a little worse than that. Testing can reveal what your
| implementation does today, with your particular input, with one set
| of compiler flags. No amount of testing can reveal what guarantees
| your implementation makes.

There are two separate issues here:

  (1) whether we want C++ to continue to support non-two's complement
      binary representation
  (2) what we want to say about overflowing shift arithmetic

Requirint two's complement does not necessarily solve (2).  And solving
(2) does not necessarily imply "no" to (1).

Agreed. It would definitely be interesting to complete Jeffrey's list of the things we could define if we standardized 2s complement, and then investigate how many of these we are comfortable defining without specifying 2s complement. So far, we have:

1) overflowing unsigned->signed conversions
2) right-shifts on negative operands
3) bitwise operators

Are there others?

(1) and (2) are currently implementation-defined; (3) seems underspecified in the current standard.

[I think for consistency we should at least make (3) say that bitwise operators on positive operands act as "expected" (that is, they give the result that a 2s complement, 1s complement or sign-magnitude machine would), and we should make these operations on other machines implementation-defined.

More generally, we should at least say that each integral type must be one of 1s complement, 2s complement or sign-magnitude. C currently requires this (C99/C11 6.2.6.2/2), but C++ does not (3.9.1/7's list of representations is not normative and not restrictive). 7.2/8 implies that we don't support other representations, but there's no normative justification for this assumption.]

If we require that either (1) or (3) acts as-if 2s complement, that actually rules out 1s complement and sign-magnitude representations, because these expressions compute a value that does not exist in the other representations (-2147483648 for a 32-bit integer):

  int(unsigned(INT_MAX) + 1) // for (1)
  int(-1 ^ INT_MAX) // for (3)

We could define that (2) acts as-if 2s complement (divide by 2^N and round down). I think that's the least valuable operation to define of the three, though.