CWG3225 [conv.integral] Conversion of bool to width-1 signed integer type #365
Description
Full name of submitter: Janet Cobb
Reference (section label): [conv.integral]
Issue description:
A signed integer type of width 1 has possible values -1 to 0 per [basic.fundamental].
[conv.integral] states that:
A prvalue of an integer type can be converted to a prvalue of another integer type. A prvalue of an unscoped enumeration type can be converted to a prvalue of an integer type.
If the destination type is bool, see [conv.bool]. If the source type is bool, the value false is converted to zero and the value true is converted to one.
Otherwise, the result is the unique value of the destination type that is congruent to the source integer modulo 2^N, where N is the width of the destination type.
Converting true to a width-1 signed integer type therefore should result in the value 1, which is not representable in the target type. This likely results in undefined behavior per [expr.pre]/4.
Suggested resolution (explicitly define the behavior):
If the destination type is bool, see [conv.bool]. If the source type is bool, the value
falseisconverted toconsidered to be zero and the valuetrueisconverted toconsidered to be one.
Otherwise, theThe result is the unique value of the destination type that is congruent to the source integer modulo 2^N, where N is the width of the destination type.
This would result in false being converted to 0 and true being converted to -1.
Alternative resolution (explicitly note the behavior is undefined):
If the destination type is bool, see [conv.bool]. If the source type is bool, the value false is converted to zero and the value true is converted to one. If that value cannot be represented in the target type, the behavior is undefined. [Note: this occurs if the destination type is a signed integer type of width 1.]
Otherwise, the result is the unique value of the destination type that is congruent to the source integer modulo 2^N, where N is the width of the destination type.
Activity
jensmaurer commentedon Jul 16, 2023
I don't think there are any integer types with width 1; [implimits] doesn't allow that.
randomnetcat commentedon Jul 16, 2023
Sorry, which part of [implimits] prohibits such a type? It isn't immediately obvious to me.
JohelEGP commentedon Jul 16, 2023
https://eel.is/c++draft/basic.fundamental#4.sentence-1
specifies the minimum width to be 8.
randomnetcat commentedon Jul 16, 2023
I don't see a way to read that as applying to extended integer types.
JohelEGP commentedon Jul 16, 2023
An extended integer type is an integer type.
So it applies.
Unless you can point to where that restriction is lifted.
jensmaurer commentedon Jul 16, 2023
Sorry, it's in [basic.fundamental], as @JohelEGP has pointed out.
JohelEGP commentedon Jul 16, 2023
https://eel.is/c++draft/basic.fundamental#4.sentence-1
applies to "signed integer type",
which is defined at https://eel.is/c++draft/basic.fundamental#def:type,signed_integer
and includes extended signed integer types.
jensmaurer commentedon Jul 16, 2023
I think that sentence should read "standard signed integer type". Otherwise, we couldn't have extended integer types at all (because the referenced table is exhaustive).
jensmaurer commentedon Jul 16, 2023
[conv.rank] doesn't help either. Looks like we don't exclude "small" extended integer types. I wonder if we should.
frederick-vs-ja commentedon Jul 25, 2023
FYI, the minimum width of C23's signed
_BitInttypes is 2 (1 for unsigned_BitInt) (see N2709, N3096).But C doesn't seem to forbid "small" extended integer types either.
jensmaurer commentedon Oct 22, 2023
A related question is whether an "int" bit-field of width 1 can faithfully store a "bool" value. [class.bit] p4 doesn't read to me like it could.
JohelEGP commentedon Oct 22, 2023
Isn't that because it falls out from other rules?
Initializing a non-
boolbit-field from a value ofboolstores0or1.jensmaurer commentedon Oct 22, 2023
But a signed bit-field with width 1 can store the values 0 and -1 only. So, what do we do with the
bool1?JohelEGP commentedon Oct 22, 2023
Ah, I see.
So if it doesn't fall out from other rules, it would be UB by omission.
Maybe you can tag someone who's trying to document or get rid of UB in the standard.
Halalaluyafail3 commentedon Jun 24, 2026
C2Y supports
_BitInt(1)now because N3747 was accepted.eisenwave commentedon Jun 25, 2026
I think this deserves a CWG issue now.
We now say "The width of each standard signed integer type shall not be less than the values specified in Table 14." in [basic.fundamental], so this no longer applies to extended integer types.
It would be possible for the implementation to provide an
_ExtInt(1)extended signed integer type with a single bit, so it's unclear whatstatic_cast<_ExtInt(1)>(true)does. P3666 would concretely introduce a_BitInt(1)type as well, and that's past EWG, but the defect is pre-existing.The C standard is also not super helpful here https://cstd.eisie.net/c2y.html#6.3.2.3p3
true -> _BitInt(1)either gives an implementation-defined result or raises a signal, and C compilers don't support_BitInt(1)yet so we don't know yet how they'll deal with this case.In my opinion, this should be ill-formed in C++, which would keep the door open to future standardization that aligns with different behavior in C2y.
Halalaluyafail3 commentedon Jun 25, 2026
GCC documents what will happen here: https://gcc.gnu.org/onlinedocs/gcc/Integers-implementation.html
bool to _BitInt(1) conversions would be ill-formed? That seems very arbitrary when any other integer type can be converted to _BitInt(1). Also I have created C Issue 1063 which discusses this so perhaps the wording can be changed.
[-][conv.integral] Conversion of bool to width-1 signed integer type[/-][+]CWG3225 [conv.integral] Conversion of bool to width-1 signed integer type[/+]jensmaurer commentedon Aug 30, 2026
CWG3225