File tree Expand file tree Collapse file tree 4 files changed +69
-1
lines changed Expand file tree Collapse file tree 4 files changed +69
-1
lines changed Original file line number Diff line number Diff line change @@ -179,6 +179,9 @@ C23 Feature Support
179
179
- Clang now supports `N3018 The constexpr specifier for object definitions `
180
180
<https://www.open-std.org/jtc1/sc22/wg14/www/docs/n3018.htm>`_.
181
181
182
+ - Properly promote bit-fields of bit-precise integer types to the field's type
183
+ rather than to ``int ``. #GH87641
184
+
182
185
Non-comprehensive list of changes in this release
183
186
-------------------------------------------------
184
187
Original file line number Diff line number Diff line change @@ -7241,6 +7241,14 @@ QualType ASTContext::isPromotableBitField(Expr *E) const {
7241
7241
// We perform that promotion here to match GCC and C++.
7242
7242
// FIXME: C does not permit promotion of an enum bit-field whose rank is
7243
7243
// greater than that of 'int'. We perform that promotion to match GCC.
7244
+ //
7245
+ // C23 6.3.1.1p2:
7246
+ // The value from a bit-field of a bit-precise integer type is converted to
7247
+ // the corresponding bit-precise integer type. (The rest is the same as in
7248
+ // C11.)
7249
+ if (QualType QT = Field->getType(); QT->isBitIntType())
7250
+ return QT;
7251
+
7244
7252
if (BitWidth < IntSize)
7245
7253
return IntTy;
7246
7254
Original file line number Diff line number Diff line change @@ -154,7 +154,10 @@ template <bool Signed> class IntegralAP final {
154
154
}
155
155
156
156
IntegralAP truncate (unsigned BitWidth) const {
157
- return IntegralAP (V.trunc (BitWidth));
157
+ if constexpr (Signed)
158
+ return IntegralAP (V.trunc (BitWidth).sextOrTrunc (this ->bitWidth ()));
159
+ else
160
+ return IntegralAP (V.trunc (BitWidth).zextOrTrunc (this ->bitWidth ()));
158
161
}
159
162
160
163
IntegralAP<false > toUnsigned () const {
Original file line number Diff line number Diff line change
1
+ // RUN: %clang_cc1 -fsyntax-only -verify -std=c23 %s
2
+
3
+ // GH87641 noticed that integer promotion of a bit-field of bit-precise integer
4
+ // type was promoting to int rather than the type of the bit-field.
5
+ struct S {
6
+ unsigned _BitInt (7 ) x : 2 ;
7
+ unsigned _BitInt (2 ) y : 2 ;
8
+ unsigned _BitInt (72 ) z : 28 ;
9
+ _BitInt (31 ) a : 12 ;
10
+ _BitInt (33 ) b : 33 ;
11
+ };
12
+
13
+ // We don't have to worry about promotion cases where the bit-precise type is
14
+ // smaller than the width of the bit-field; that can't happen.
15
+ struct T {
16
+ unsigned _BitInt (28 ) oh_no : 72 ; // expected-error {{width of bit-field 'oh_no' (72 bits) exceeds the width of its type (28 bits)}}
17
+ };
18
+
19
+ static_assert (
20
+ _Generic(+ (struct S ){}.x ,
21
+ int : 0 ,
22
+ unsigned _BitInt (7 ) : 1 ,
23
+ unsigned _BitInt (2 ) : 2
24
+ ) == 1 );
25
+
26
+ static_assert (
27
+ _Generic(+ (struct S ){}.y ,
28
+ int : 0 ,
29
+ unsigned _BitInt (7 ) : 1 ,
30
+ unsigned _BitInt (2 ) : 2
31
+ ) == 2 );
32
+
33
+ static_assert (
34
+ _Generic(+ (struct S ){}.z ,
35
+ int : 0 ,
36
+ unsigned _BitInt (72 ) : 1 ,
37
+ unsigned _BitInt (28 ) : 2
38
+ ) == 1 );
39
+
40
+ static_assert (
41
+ _Generic(+ (struct S ){}.a ,
42
+ int : 0 ,
43
+ _BitInt (31 ) : 1 ,
44
+ _BitInt (12 ) : 2 ,
45
+ unsigned _BitInt (31 ) : 3
46
+ ) == 1 );
47
+
48
+ static_assert (
49
+ _Generic(+ (struct S ){}.b ,
50
+ int : 0 ,
51
+ long long : 1 ,
52
+ _BitInt (33 ) : 2 ,
53
+ unsigned _BitInt (33 ) : 3
54
+ ) == 2 );
You can’t perform that action at this time.
0 commit comments