@@ -183,8 +183,18 @@ impl ReprOptions {
183
183
184
184
/// Returns the discriminant type, given these `repr` options.
185
185
/// This must only be called on enums!
186
- pub fn discr_type ( & self ) -> IntegerType {
187
- self . int . unwrap_or ( IntegerType :: Pointer ( true ) )
186
+ ///
187
+ /// This is the "typeck type" of the discriminant, which is effectively the maximum size:
188
+ /// discriminant values will be wrapped to fit (with a lint). Layout can later decide to use a
189
+ /// smaller type (which it will do depending on the actual discriminant values, also enforcing
190
+ /// `c_enum_min_size` along the way) and that will work just fine, it just induces casts when
191
+ /// getting/setting the discriminant.
192
+ pub fn discr_type ( & self , cx : & impl HasDataLayout ) -> IntegerType {
193
+ self . int . unwrap_or ( if self . c ( ) {
194
+ IntegerType :: Fixed ( cx. data_layout ( ) . c_enum_max_size , true )
195
+ } else {
196
+ IntegerType :: Pointer ( true )
197
+ } )
188
198
}
189
199
190
200
/// Returns `true` if this `#[repr()]` should inhabit "smart enum
@@ -274,6 +284,8 @@ pub struct TargetDataLayout {
274
284
/// Note: This isn't in LLVM's data layout string, it is `short_enum`
275
285
/// so the only valid spec for LLVM is c_int::BITS or 8
276
286
pub c_enum_min_size : Integer ,
287
+ /// Maximum size of #[repr(C)] enums (defaults to c_longlong::BITS, which is always 64).
288
+ pub c_enum_max_size : Integer ,
277
289
}
278
290
279
291
impl Default for TargetDataLayout {
@@ -307,6 +319,10 @@ impl Default for TargetDataLayout {
307
319
address_space_info : vec ! [ ] ,
308
320
instruction_address_space : AddressSpace :: ZERO ,
309
321
c_enum_min_size : Integer :: I32 ,
322
+ // C23 allows enums to have any integer type. The largest integer type in the standard
323
+ // is `long long`, which is always 64bits (judging from our own definition in
324
+ // `library/core/src/ffi/primitives.rs`).
325
+ c_enum_max_size : Integer :: I64 ,
310
326
}
311
327
}
312
328
}
@@ -327,7 +343,7 @@ impl TargetDataLayout {
327
343
/// [llvm data layout string](https://llvm.org/docs/LangRef.html#data-layout)
328
344
///
329
345
/// This function doesn't fill `c_enum_min_size` and it will always be `I32` since it can not be
330
- /// determined from llvm string.
346
+ /// determined from llvm string. Likewise, it does not fill in `c_enum_max_size`.
331
347
pub fn parse_from_llvm_datalayout_string < ' a > (
332
348
input : & ' a str ,
333
349
default_address_space : AddressSpace ,
0 commit comments