<html>
<head>
<title>P1236R1: Alternative Wording for P0907R4 Signed Integers are Two's Complement</title>

<style type="text/css">
  ins { text-decoration:none; font-weight:bold; background-color:#A0FFA0 }
  .new { text-decoration:none; font-weight:bold; background-color:#D0FFD0 }
  del { text-decoration:line-through; background-color:#FFA0A0 }
  strong { font-weight: inherit; color: #2020ff }
  #xins:checked ~ * ins { display:none; visibility:hidden }
  #xdel:checked ~ * del { display:none; visibility:hidden }
</style>

</head>

<body>
ISO/IEC JTC1 SC22 WG21 P1236R1<br/>
Jens Maurer &lt;Jens.Maurer@gmx.net><br/>
Target audience: CWG<br/>
2018-11-09<br/>

<input type="checkbox" id="xins"/><label for="xins">Hide inserted text</label>
<input type="checkbox" id="xdel"/><label for="xdel">Hide deleted text</label>

<h1>P1236R1: Alternative Wording for P0907R4 Signed Integers are Two's Complement</h1>

This paper presents alternative wording for P0907R3 Signed Integers
are Two's Complement by Jean Fran&ccedil;ois Bastien, avoiding talking
about unobservable bits as much as possible.
<p>
The wording presented here also resolved the following core issues:
<ul>
  <li>CWG 1857 Additional questions about bits</li>
  <li>CWG 1943 Unspecified meaning of "bit"</li>
</ul>

<p>
There are further cleanups in the area of integer types beyond
requiring two's complement notation, not all of which Jean
Fran&ccedil;ois Bastien may agree with.

<h2>Roadmap to changes</h2>

First, the signed and unsigned integer types are introduced.  Instead
of discussing sign and value bits, the range of representable values
is specified by introducing the term "range exponent". Then, "char"
and narrow character types are introduced based on these.  The concept
of "underlying type" is extended to "char", consistent with the use
for wchar_t.
<p>
The semantics of bitwise operators are reformulated based on the
base-2 representation of the operand values.
<p>
Bit-fields now consistently use the term "width" (instead of "length").
<p>
As per EWG decision in San Diego, deviating from P0907R3, bool is
specified to have some integral type as its underlying type, but the
presence of padding bits for "bool" will remain unspecified, as will
the mapping of true and false to values of the underlying type.

<h2>Proposed wording</h2>

Change in 6.7.1 [basic.fundamental] paragraphs 1-7 and insert
paragraph breaks as indicated:

<blockquote>
<del>Objects declared as characters (char) shall be large enough to store
any member of the implementation's basic character set. If a character
from this set is stored in a character object, the integral value of
that character object is equal to the value of the single character
literal form of that character. It is implementation-defined whether a
char object can hold negative values. Characters can be explicitly
declared unsigned or signed.  Plain char, signed char, and unsigned
char are three distinct types, collectively called narrow character
types. A char, a signed char, and an unsigned char occupy the same
amount of storage and have the same alignment requirements (6.6.5);
that is, they have the same object representation. For narrow
character types, all bits of the object representation participate in
the value representation. [Note: A bit-field of narrow character type
whose length is larger than the number of bits in the object
representation of that type has padding bits; see 6.7. -- end note]
For unsigned narrow character types, each possible bit pattern of the
value representation represents a distinct value. These requirements
do not hold for other types. In any particular implementation, a plain
char object can take on either the same values as a signed char or an
unsigned char; which one is implementation-defined. For each value i
of type unsigned char in the range 0 to 255 inclusive, there exists a
value j of type char such that the result of an integral conversion
(7.3.8 [conv.integral]) from i to char is j, and the result of an
integral conversion from j to <code>unsigned char</code> is i.</del>
  
<p>
   
There are five <em>standard signed integer types</em>: "signed char",
"short int", "int", "long int", and "long long int". In this list,
each type provides at least as much storage as those preceding it in
the list. There may also be implementation-defined <em>extended signed
integer types</em>. The standard and extended signed integer types are
collectively called <em>signed integer types</em>.
<ins>The range of representable values for a signed integer type is
-2<sup>N-1</sup> to 2<sup>N-1</sup>-1 (inclusive),
where N is called the <em>range exponent</em> of the type.</ins>
  
<ins>[ Note:</ins> Plain <code>int</code>s have the natural size
suggested by the architecture of the execution environment
<del>[ Footnote: <code>int</code> must also be large enough to contain any
value in the range [INT_MIN, INT_MAX], as defined in the header
  &lt;climits>. ]</del>;
the other signed integer types are provided to meet special needs.
<ins>-- end note ]</ins>
<p>

For each of the standard signed integer types, there exists a
corresponding (but different) <em>standard unsigned integer type</em>:
"unsigned char", "unsigned short int", "unsigned int", "unsigned long
int", and "unsigned long long int"<ins>. 
Likewise, for each of the extended signed
integer types, there exists a corresponding
<em>extended unsigned integer type</em>.
The standard and extended unsigned integer types are collectively called
<em>unsigned integer types</em>.
</ins>
<ins>An unsigned integer type has the same range exponent N as the corresponding
signed integer type. The range of representable values for the unsigned
type is 0 to 2<sup>N</sup>-1 (inclusive); arithmetic
for the unsigned type is performed modulo 2<sup>N</sup>. [
Note: Unsigned arithmetic does not overflow.  Overflow for
signed arithmetic yields undefined behavior (7.1 [expr.pre]).
-- end note ]</ins>

<p>
<ins>An unsigned integer type</ins>
<del>, each of which occupies the same amount of storage and</del> has the same
<ins>object representation, value representation, and</ins>
alignment requirements (6.6.5 [basic.align])
as the corresponding signed integer type<ins>.  For each
value <code>x</code> of a signed integer type, the
value of the corresponding unsigned integer type
congruent to <code>x</code> modulo
2<sup>N</sup> has
the same value of corresponding bits in its value
representation. [ Footnote: This is also known as two's
complement representation. ] [ Example: The value -1 of a signed
integer type has the same representation as the largest value 
of the corresponding
unsigned type. ] </ins>
<p>
<ins>The range exponent of each signed integer type shall not be less than the values specified in
table X.</ins>

<table align="center" class="new">
  <tr><th>type</th><th>minimum range exponent N</th></tr>
<tr><td><code>signed char</code></td> <td>8</td></tr>
<tr><td><code>short</code></td>       <td>16</td></tr>
<tr><td><code>int</code></td>         <td>16</td></tr>
<tr><td><code>long</code></td>        <td>32</td></tr>
<tr><td><code>long long</code></td>   <td>64</td></tr>
</table>
<ins>The value representation of a signed or unsigned integer type
comprises N bits, where N is the respective range exponent.  Each set
of values for any padding bits (6.7 [basic.types]) in the object
representation are alternative representations of the value specified
by the value representation.  [ Note: Padding bits have unspecified
value, but do not cause traps. See also ISO C 6.2.6.2. -- end note ] [
Note: The signed and unsigned integer types satisfy the constraints
given in ISO C 5.2.4.2.1. -- end note ] Except as
specified above, the range exponent of a signed or unsigned integer
type is implementation-defined.</ins>
<del>[ Footnote: See 9.1.7.2 [dcl.type.simple]
regarding the correspondence between types and the sequences of
<em>type-specifier</em>s that designate them.]; that is, each signed
integer type has the same object representation as its corresponding
unsigned integer type</del>.
<del>Likewise, for each of the extended signed integer types there
exists a corresponding <em>extended unsigned integer type</em> with
the same amount of storage and alignment requirements.  The standard
and extended unsigned integer types are collectively called
<em>unsigned integer types</em>.</del>
<p>
<del>The range of non-negative values of a signed
integer type is a subrange of the corresponding unsigned integer type,
the representation of the same value in each of the two types is the
same, and the value representation of each corresponding
signed/unsigned type shall be the same.</del>
<p>
<ins>Each value x of an unsigned integer type with range exponent N
has a unique representation x = x<sub>0</sub> 2<sup>0</sup> +
x<sub>1</sub> 2<sup>1</sup> + ... + x<sub>N-1</sub> 2<sup>N-1</sup>,
where each coefficient x<sub>i</sub> is either 0 or 1; this is called
the <em>base-2 representation</em> of x.  The base-2 representation of
a value of signed integer type is the base-2 representation of the
congruent value of the corresponding unsigned integer type.</ins>
<p>
The standard signed integer types and standard unsigned integer types
are collectively called the <em>standard integer types</em>, and the extended
signed integer types and extended unsigned integer types are
collectively called the <em>extended integer types</em>. <del>The signed and
unsigned integer types shall satisfy the constraints given in the C
standard, subclause 5.2.4.2.1.</del>
<p>
<del>Unsigned integers shall obey the laws of arithmetic modulo
2<sup>n</sup> where n is the number of bits in the value
representation of that particular size of integer. [ Footnote: This
implies that unsigned arithmetic does not overflow because a result
that cannot be represented by the resulting unsigned integer type is
reduced modulo the number that is one greater than the largest value
  that can be represented by the resulting unsigned integer type. ]</del>
<p>
<ins>A fundamental type specified to have a signed or unsigned integer
type as its <em>underlying type</em> has the same object
representation, value representation, alignment requirements (6.6.5
[basic.align]), and range of representable values as
the underlying type.  Further, each value has the same representation
in both types.</ins>
<p>
<ins>Type <code>char</code> is a distinct type that has an
implementation-defined choice of "<code>signed char</code>" or
"<code>unsigned char</code>" as its underlying type. The values of
type <code>char</code> can represent distinct codes for all members of
the implementation's basic character set.  The three
types <code>char</code>, <code>signed char</code>, and <code>unsigned
char</code> are collectively called <em>narrow character
types</em>. For narrow character types, each possible bit pattern of
the object representation represents a distinct value.  [ Note: This
requirement does not hold for other types. -- end note ] [ Note: A
bit-field of narrow character type whose width is larger than the
range exponent of that type has padding bits; see 6.7
[basic.types]. -- end note]</ins>
<p>

Type <code>wchar_t</code> is a distinct type <ins>that has an
implementation-defined signed or unsigned integer type as its
underlying type.  The values of type <code>wchar_t</code></ins>
<del>whose values</del> can
represent distinct codes for all members of the largest extended
character set specified among the supported locales (26.3.1
[locale]). <del>Type <code>wchar_t</code> shall have the same size,
signedness, and alignment requirements (6.6.5 [basic.align]) as one of
the other integral types, called its
underlying type.</del> Types <code>char16_t</code> and <code>char32_t</code>
denote distinct types <del>with the same size, signedness, and
alignment as</del> <ins>whose underlying types are</ins>
<code>uint_least16_t</code> and <code>uint_least32_t</code>,
respectively, in &lt;cstdint><del>, called the underlying types</del>.
<p>
<ins>Type <code>bool</code> is a distinct type that has the
same object representation, value representation, and alignment requirements as
an implementation-defined unsigned integer type.</ins>
<del>Values</del> <ins>The values</ins> of type <code>bool</code> are <del>either</del> true <del>or</del> <ins>and</ins> false.
[ Footnote: Using a bool
value in ways described by this document as "undefined", such as by
examining the value of an uninitialized automatic object, might cause
it to behave as if it is neither true nor false. ]  [Note: There are
no signed, unsigned, short, or long bool types or values. -- end note]
<del>Values of type <code>bool</code> participate in integral promotions
(7.3.6 [conv.prom]).</del>
<p>
Types <code>bool</code>, <code>char</code>, <code>char16_t</code>,
<code>char32_t</code>, <code>wchar_t</code>, and the signed and
unsigned integer types are collectively called
<em>integral types</em>.  <del>[ Footnote: Therefore, enumerations
(9.6 [dcl.enum]) are not integral;
however, enumerations can be promoted to integral
types as specified in 7.3.6 [conv.prom]. ]</del> A
synonym for integral type is <em>integer type</em>.
<ins>[ Note: Enumerations (9.6 [dcl.enum]) are not integral;
however, unscoped enumerations can be promoted to integral
types as specified in 7.3.6 [conv.prom]. -- end note ]</ins>
<del>The
representations of integral types shall define values by use of a pure
binary numeration system.[ Footnote: A positional representation for
integers that uses the binary digits 0 and 1, in which the values
represented by successive bits are additive, begin with 1, and are
multiplied by successive integral power of 2, except perhaps for the
bit with the highest position. (Adapted from the American National
Dictionary for Information Processing Systems.) ] [Example: This
document permits two's complement, ones' complement and signed
magnitude representations for integral types. -- end example]</del>
</blockquote>

Change in [conv.integral] paragraphs 2-4:

<blockquote>
<del>If the destination type is unsigned, the resulting value is the least
unsigned integer congruent to the source integer (modulo 2<sup>n</sup>
where n is the number of bits used to represent the unsigned
type). [Note: In a two's complement representation, this conversion is
conceptual and there is no change in the bit pattern (if there is no
truncation). -- end note]</del>
<p>
<del>If the destination type is signed, the value is unchanged if it can be
represented in the destination type; otherwise, the value is
implementation-defined.</del>
<p>
If the destination type is <code>bool</code>, see 7.3.14
[conv.bool]. If the source type is <code>bool</code>, the value false
is converted to zero and the value true is converted to one.
<p>
<ins>Otherwise, the result is the unique value of the destination type
that is congruent to the source integer modulo 2<sup>N</sup>, where N
is the range exponent of the destination type.</ins>

</blockquote>

Change in 7.6.1.9 [expr.static.cast] paragraph 9:

<blockquote>
A value of a scoped enumeration type (9.6) can be explicitly converted
to an integral type<del>. When that type is cv bool, the resulting value is
false if the original value is zero and true for all other values. For
the remaining integral types, the value is unchanged if the original
value can be represented by the specified type.  Otherwise, the
resulting value is unspecified</del>
<ins>; the result is the same as that of
converting to the enumeration's underlying type and
then to the destination type</ins>.  A value of a scoped enumeration
type can also be explicitly converted to a floating-point type; the
result is the same as that of converting from the original value to
the floating-point type.

</blockquote>

Change in 7.6.7 [expr.shift] paragraphs 1-4:

<blockquote>
The shift operators << and >> group left-to-right.
<pre>    
      <em>shift-expression:
             additive-expression
             shift-expression << additive-expression
             shift-expression >> additive-expression</em>
</pre>
The operands shall be of integral or unscoped enumeration type and integral promotions are performed. The
type of the result is that of the promoted left operand. The behavior is undefined if the right operand is
negative, or greater than or equal to the <del>length in bits</del> <ins>range exponent of the promoted left operand.
<p>
The value of E1 << E2 is <ins>the unique value congruent to
E1 x 2<sup>E2</sup> modulo 2<sup>N</sup>, where N is the range
exponent of the type of the result.
[ Note: </ins>
E1 <ins>is</ins> left-shifted E2 bit positions; vacated
bits are zero-filled. <ins> -- end note ]</ins> <del>If E1 has an
unsigned type, the value of the result is E1 x 2<sup>E2</sup>, reduced
modulo one more than the maximum value representable in the result
type. Otherwise, if E1 has a signed type and non-negative value, and
E1 x 2<sup>E2</sup> is representable in the corresponding unsigned
type of the result type, then that value, converted to the result
type, is the resulting value; otherwise, the behavior is
undefined</del>.
<p>
The value of E1 >> E2 is <ins>E1 / 2<sup>E2</sup>, rounded down.
[ Note:</ins> E1 <ins>is</ins> right-shifted E2 bit positions.
<ins>Right-shift on signed integral types is an arithmetic right
shift, which performs sign-extension. - end note ]</ins>
<del>If E1 has an unsigned type or if E1 has a signed type and a
non-negative value, the value of the result is the integral part of
the quotient of E1/2E2. If E1 has a signed type and a negative value,
the resulting value is implementation-defined.</del>
<p>
The expression E1 is sequenced before the expression E2.
</blockquote>

Change in 7.6.11 [expr.bit.and]:

<blockquote>
<pre>
     <em>and-expression:
           equality-expression
           and-expression & equality-expression</em>
</pre>
<ins>The operands shall be of integral or unscoped enumeration
type.</ins>  The usual arithmetic conversions (7.4 [expr.arith.conv])
are performed<ins>. Given the coefficients x<sub>i</sub>
and y<sub>i</sub> of the base-2 representation (6.7.1
[basic.fundamental]) of the converted operands x and y, the
coefficient r<sub>i</sub> of the base-2 representation of the result r
is 1 if both x<sub>i</sub> and y<sub>i</sub>
are 1, and 0 otherwise. [ Note: The</ins>
<del>; the</del> result is the bitwise AND function of the operands.
<ins> -- end note]</ins>
<del>The operator applies only to integral or unscoped enumeration
operands.</del>
</blockquote>

Change in 7.6.12 [expr.bit.xor]:

<blockquote>
<pre>
     <em>exclusive-or-expression:
           and-expression
           exclusive-or-expression ^ and-expression</em>
</pre>
<ins>The operands shall be of integral or unscoped enumeration
type.</ins>  The usual arithmetic conversions (7.4 [expr.arith.conv])
are performed<ins>. Given the coefficients x<sub>i</sub>
and y<sub>i</sub> of the base-2 representation (6.7.1
[basic.fundamental]) of the converted operands x and y, the
coefficient r<sub>i</sub> of the base-2 representation of the result r
is 1 if either (but not both) of x<sub>i</sub> and
y<sub>i</sub> are 1, and 0 otherwise. [ Note: The</ins>
<del>; the</del> result is the bitwise exclusive OR function of the
operands. <ins> -- end note]</ins>
<del> The operator applies only to integral or unscoped
enumeration operands.</del>
</blockquote>

Change in 7.6.13 [expr.or]:

<blockquote>
<pre>
     <em>inclusive-or-expression:
           exclusive-or-expression
           inclusive-or-expression | exclusive-or-expression</em>
</pre>
<ins>The operands shall be of integral or unscoped enumeration type.</ins>
The usual arithmetic conversions (7.4 [expr.arith.conv]) are
performed<ins>. Given the coefficients x<sub>i</sub>
and y<sub>i</sub> of the base-2 representation (6.7.1
[basic.fundamental]) of the converted operands x and y, the
coefficient r<sub>i</sub> of the base-2 representation of the result r
is 1 if at least one of x<sub>i</sub> and
y<sub>i</sub> is 1, and 0 otherwise. [ Note: The</ins>
<del>; the</del> result is the bitwise inclusive OR function of its
operands. <ins> -- end note]</ins>
<del>The operator applies only to integral or unscoped
enumeration operands.</del>
</blockquote>

Change in 9.6 [dcl.enum] paragraph 8:

<blockquote>
For an enumeration whose underlying type is fixed, the values of the
enumeration are the values of the underlying type. Otherwise, <del>for an
enumeration where e<sub>min</sub> is the smallest enumerator and
e<sub>max</sub> is the largest,</del> the values of the enumeration are the
values <ins>representable by a hypothetical integer types with
minimal range exponent M such that all enumerators can be represented.</ins>
<del>in the range b<sub>min</sub> to b<sub>max</sub>, defined as
follows: <del>Let K be 1 for a two's complement representation and 0
for a ones' complement or sign-magnitude representation.</del> bmax is
the smallest value greater than or equal to max(|emin |
- K, |emax |) and equal to 2<sup>M - 1</sup>,
where M is a non-negative integer. bmin is zero if emin is
non-negative and -(bmax + K)
otherwise.</del> The <del>size</del> <ins>width</ins> of the smallest
bit-field
large enough to hold all the values of the enumeration type
is <ins>M</ins> <del>max(M, 1) if b<sub>min</sub> is zero and M + 1 otherwise</del>. It is possible to
define an enumeration that has values not defined by any of its
enumerators. If the <em>enumerator-list</em> is empty, the values of the
enumeration are as if the enumeration had a single enumerator with
value 0. [ Footnote: ... ]

</blockquote>

Change in 10.3.10 [class.bit] paragraph 1-4:

<blockquote>
A <em>member-declarator</em> of the form
<pre>
  <em>identifier<sub>opt</sub> attribute-specifier-seq<sub>opt</sub></em> : <em>constant-expression brace-or-equal-initializer<sub>opt</sub></em>
</pre>
specifies a bit-field<del>; its length is set off from the bit-field
name by a colon</del>. The optional <em>attribute-specifier-seq</em>
appertains to the entity being declared. <ins>A bit-field shall not be
a static member. A bit-field shall have integral or enumeration type;
the</ins> <del>The</del> bit-field attribute is not part of the
type<del> of the class member</del>.  The <em>constant-expression</em>
shall be an integral constant expression with a value greater than or
equal to zero<ins> and is called the <em>width</em> of the
bit-field</ins>.

<ins>If the width of a bit-field is larger than the range exponent
of the bit-field's type (or, in case of an enumeration type, of its
underlying type),</ins>
<del>The value of the integral constant expression may be larger than
the number of bits in the object representation (6.7 [basic.types]) of
the bit-field's type; in such cases</del> the extra bits are padding
bits (6.7 [basic.types]). Allocation of bit-fields within a class
object is implementation-defined. Alignment of bit-fields is
implementation-defined.  Bit-fields are packed into some addressable
allocation unit. [Note: Bit-fields straddle allocation units on some
machines and not on others. Bit-fields are assigned right-to-left on
some machines, left-to-right on others.  -- end note]
<p>
A declaration for a bit-field that omits the <em>identifier</em> declares an
<em>unnamed bit-field</em>. Unnamed bit-fields are not members and
cannot be initialized. An unnamed bit-field shall not be declared with
a cv-qualified type.  [Note: An unnamed bit-field is useful for
padding to conform to externally-imposed layouts. -- end note] As a
special case, an unnamed bit-field with a width of zero specifies
alignment of the next bit-field at an allocation unit boundary. Only
when declaring an unnamed bit-field may the <del>value of the
constant-expression</del> <ins>width</ins> be <del>equal to</del> zero.
<p>
<del>A bit-field shall not be a static member. A bit-field shall have
integral or enumeration type (6.7.1).</del> <del>A <code>bool</code> value
can successfully be stored in a bit-field of any nonzero size.</del> The
address-of operator & shall not be applied to a bit-field, so there
are no pointers to bit-fields. A non-const reference shall not be
bound to a bit-field (9.3.3). [Note: If the initializer for a
reference of type const T& is an lvalue that refers to a bit-field,
the reference is bound to a temporary initialized to hold the value of
the bit-field; the reference is not bound to the bit-field
directly. See 9.3.3. -- end note]
<p>
<ins>If a value of integral type (other than <code>bool</code>) is
stored into a bit-field of width N and the value would be
representable in a hypothetical signed or unsigned integer type with
range exponent N and the same signedness as the bit-field's
type, the original value and the value of the bit-field
compare equal.</ins>

If the value <code>true</code> or <code>false</code> is stored
into a bit-field of type <code>bool</code> of any size
(including a one bit bit-field), the original <code>bool</code> value
and the value of the bit-field
<del>shall</del> compare equal. If the value of an enumerator is
stored into a bit-field of the same enumeration type and
the <del>number of bits in the bit-field</del> <ins>width</ins> is
large enough to hold all the values of that enumeration type (9.6 [dcl.enum]),
the original enumerator value and the value of the
bit-field <del>shall</del> compare equal. [Example: ...]

</blockquote>

Change in 19.15.4.3 [meta.unary.prop] paragraph 9:

<blockquote>
...  The set of scalar types for which this condition holds is
implementation-defined. [Note: If a type has padding bits, the
condition does not hold; otherwise, the condition holds true for
<del>unsigned</del> integral types. -- end note]

</blockquote>

Change in 19.16.3 [ratio.ratio] paragraph 1:

<blockquote>
If the template argument D is zero or the absolute values of either of
the template arguments N and D is no representable by
type <code>intmax_t</code>, the program is ill-formed. [Note: These
rules ensure that infinite ratios are avoided and that for any
negative input, there exists a representable value of its absolute
value which is positive. <del>In a two's complement representation,
this</del> <ins>This</ins> excludes the most negative value. -- end
note]

</blockquote>


Change in 29.6.2 [atomics.ref.int] paragraph 6:

<blockquote>
<em>Remarks:</em> For signed integer types, <del>arithmetic is defined to
use two's complement representation.</del>
<ins>the result is as if the object value and parameters were
converted to their corresponding unsigned types, the computation
performed on those types, and the result converted back to the signed
type. [ Note:</ins> There are no undefined results <ins>arising from
the computation. -- end note]</ins>

</blockquote>

Change in 29.7.2 [atomics.types.int] paragraph 7:

<blockquote>
<em>Remarks:</em> For signed integer types, <del>arithmetic is defined to
use two's complement representation.</del>
<ins>the result is as if the object value and parameters were
converted to their corresponding unsigned types, the computation
performed on those types, and the result converted back to the signed
type. [ Note:</ins> There are no undefined results <ins>arising from
the computation. -- end note]</ins>

</blockquote>


</body>
</html>
