Skip to main content

rucc_types/
lib.rs

1//! The C type system, interned, and layout computation.
2//!
3//! Design: `spec/07-types-and-semantics.md`. Layer rank 3, see `spec/18-package-layout.md`.
4//!
5//! There is one [`Types`] per translation unit and it owns every type in it. A [`TypeId`] is
6//! four bytes and two of them are equal exactly when they are the same type, which turns the
7//! question the compiler asks more often than any other into an integer comparison.
8//!
9//! Two ideas shape the rest of it.
10//!
11//! **Sugar is kept and never decided on.** `typedef int32_t;` gives a node that remembers the
12//! name and points at canonical `int`. Every semantic rule reads [`Types::canonical`] and sees
13//! `int`; every diagnostic reads the type as it was written and says `int32_t`. Compilers that
14//! throw the name away produce messages nobody can act on, and compilers that decide on the
15//! name produce wrong answers, and both are common. Sugar is not only at the outermost node,
16//! so `int32_t *` and `int32_t[4]` are sugar too and canonicalising rebuilds them.
17//!
18//! **`_Atomic` is a type, not a qualifier.** `const` and `volatile` and `restrict` are a
19//! bitmask in the interning key, because nothing about them changes what an object is. C lets
20//! `_Atomic` be written in the same position, but `_Atomic(T)` can have a different alignment
21//! from `T`, so it is a type constructor here and the parser is what maps the spelling onto
22//! it. Document 01 recorded a compiler that treated it as a qualifier and lost track of it,
23//! which is exactly the shortcut that makes atomics silently wrong.
24//!
25//! Layout comes out of [`TargetInfo`](rucc_target::TargetInfo) and never out of the host.
26//! `long` is four bytes on Windows and eight on Linux, and `long double` is eight bytes on
27//! Apple and sixteen on SysV x86-64, so a cross compiler that asks its own platform is wrong
28//! twice before it has read a line of C.
29//!
30//! ```
31//! use rucc_target::{TargetInfo, Triple};
32//! use rucc_types::{IntKind, Types, layout};
33//!
34//! let mut types = Types::new();
35//! let linux = TargetInfo::new("x86_64-unknown-linux-gnu".parse::<Triple>().unwrap());
36//! let windows = TargetInfo::new("x86_64-pc-windows-msvc".parse::<Triple>().unwrap());
37//!
38//! let long = types.int(IntKind::Long);
39//! assert_eq!(layout(&types, long, &linux).unwrap().size, 8);
40//! assert_eq!(layout(&types, long, &windows).unwrap().size, 4);
41//! ```
42//!
43//! Records are laid out by [`layout_record`], which takes the members and gives back their
44//! offsets, and the result is handed to [`Types::complete_record`] so that the record then has
45//! a size like any other type. Bit-fields, `packed`, `#pragma pack`, `aligned`, zero width
46//! bit-fields and flexible array members are all in there, and every one of their rules was
47//! measured against gcc and clang rather than read off a document.
48//!
49//! [`promote`] and [`usual_arithmetic`] are 6.3.1.1 and 6.3.1.8, the rules that decide what
50//! type an arithmetic expression has. Their answers were read out of gcc and clang with
51//! `_Generic` naming the type of every interesting pair, which is also how the C23 changes were
52//! pinned down: `_BitInt` does not promote, and an enumeration promotes through whatever it is
53//! represented in.
54//!
55//! `__int128` is one of the integer kinds rather than a `_BitInt(128)` in disguise. The two are
56//! different types: `__int128` is sixteen bytes aligned to sixteen everywhere, `_BitInt(128)` is
57//! aligned to its granule, and `__int128` outranks `long long` where a `_BitInt` is ranked by
58//! width alone. It is available on every target here, because all three architectures are
59//! 64-bit and GCC has it on every 64-bit target it supports.
60//!
61//! [`compatible`] and [`composite`] are 6.2.7, the relation that decides whether two
62//! declarations of one name are talking about the same thing and the type that is left when they
63//! are. Identity is not that relation: `int f(int a[3])` and `int f(int *a)` are different types
64//! and the same function. The composite is what a caller merging two declarations should keep,
65//! because it is the only one of the three types in play that knows both the array size and the
66//! parameter list.
67//!
68//! # Status
69//!
70//! The type universe, the interner, the canonical and sugar split, the qualifier rules, layout
71//! with records included, the arithmetic conversions, compatibility with the composite type, and
72//! [`spell`], which writes a type back as the C declaration it is, are implemented.
73//!
74//! Not here yet, and named so that the gap is not mistaken for a decision: the decimal floating
75//! types.
76//!
77//! Every crate in the workspace is published, and publishing implies a promise. This one is
78//! tier 3: its Rust API is explicitly unstable and will change without a major version bump.
79//! Depend on the `rucc` binary's behaviour, not on this.
80
81#![doc(html_root_url = "https://docs.rs/rucc-types/0.12.3")]
82
83mod classify;
84mod compat;
85mod convert;
86mod granule;
87mod kind;
88mod layout;
89mod print;
90mod record;
91mod types;
92
93pub use crate::classify::{
94    element, is_aggregate, is_arithmetic, is_array, is_atomic, is_complete, is_complex,
95    is_floating, is_function, is_integer, is_modifiable, is_object, is_pointer, is_real,
96    is_real_floating, is_record, is_scalar, is_vector, is_void, lanes, pointee, pointee_as_written,
97    real_part,
98};
99pub use crate::compat::{adjust_parameter, compatible, composite};
100pub use crate::convert::{
101    mask_of, promote, promote_bit_field, usual_arithmetic, vectors_convertible,
102};
103pub use crate::granule::{GRANULE, Keying, Tally, measure, measure_all, report as granule_report};
104pub use crate::kind::{
105    ArrayLen, EnumId, FloatKind, FunctionId, FunctionType, IntKind, Qualifiers, RecordId,
106    RecordKind, Type, TypeKind, VlaId,
107};
108pub use crate::layout::{
109    IntegerInfo, Layout, LayoutError, align, float_format, float_width, int_width, integer_info,
110    layout,
111};
112pub use crate::print::{declare, spell};
113pub use crate::record::{
114    Extent, Field, FieldDecl, RecordError, RecordLayout, RecordOptions, VariableLayout,
115    layout_record,
116};
117pub use crate::types::{Alias, EnumInfo, Enumerator, RecordInfo, Spelled, TypeId, Types};
118
119/// The milestone in `spec/17-milestones.md` that fills this crate in.
120pub const MILESTONE: &str = "M2";
121
122#[cfg(test)]
123mod tests {
124    use std::num::NonZeroU32;
125
126    use rucc_base::{Interner, Symbol};
127    use rucc_target::{TargetInfo, Triple};
128
129    use super::*;
130
131    fn target(triple: &str) -> TargetInfo {
132        TargetInfo::new(triple.parse::<Triple>().expect("a triple the compiler supports"))
133    }
134
135    fn linux() -> TargetInfo {
136        target("x86_64-unknown-linux-gnu")
137    }
138
139    /// The one target in the table that runs Microsoft's bit-field rule. So does
140    /// `x86_64-pc-windows-gnu`, and the tests below say so where it matters, because a rule keyed
141    /// on the environment rather than on the operating system would pass every one of them.
142    fn windows() -> TargetInfo {
143        target("x86_64-pc-windows-msvc")
144    }
145
146    /// AAPCS64 proper, where an unnamed bit-field raises the record's alignment. Apple's AArch64
147    /// dropped that, so `aarch64-apple-darwin` answers the way x86-64 does and is the pair to
148    /// this one wherever the difference is being measured.
149    fn aapcs() -> TargetInfo {
150        target("aarch64-unknown-linux-gnu")
151    }
152
153    /// Lays out a record with no attributes on it, on x86-64 Linux.
154    fn lay_out(types: &Types, kind: RecordKind, fields: &[FieldDecl]) -> RecordLayout {
155        lay_out_on(&linux(), types, kind, fields)
156    }
157
158    /// Lays out a record with no attributes on it, on a named target.
159    fn lay_out_on(
160        target: &TargetInfo,
161        types: &Types,
162        kind: RecordKind,
163        fields: &[FieldDecl],
164    ) -> RecordLayout {
165        layout_record(types, kind, fields, &RecordOptions::default(), target)
166            .expect("a record every member of which has a layout")
167    }
168
169    /// The offsets of the members, in bits, which is what a measurement of a real compiler
170    /// gives back once its byte offsets and its bit dumps are put together.
171    fn offsets(laid_out: &RecordLayout) -> Vec<u128> {
172        laid_out.fields.iter().map(Field::bit_offset).collect()
173    }
174
175    /// A complete record type built out of the given members.
176    fn record(types: &mut Types, kind: RecordKind, fields: &[FieldDecl]) -> TypeId {
177        let id = types.declare_record(kind, None);
178        let laid_out = lay_out(types, kind, fields);
179        types.complete_record(id, laid_out);
180        types.record(id)
181    }
182
183    /// An ordinary member of the given type, unnamed, which is all most of these tests need.
184    fn member(ty: TypeId) -> FieldDecl {
185        FieldDecl::new(None, ty)
186    }
187
188    /// A named bit-field, which is what a measurement of a real compiler has to use to be able
189    /// to read the field back.
190    fn bits(interner: &mut Interner, name: &str, ty: TypeId, width: u32) -> FieldDecl {
191        FieldDecl::bit_field(Some(interner.intern(name)), ty, width)
192    }
193
194    /// An unnamed bit-field, which occupies bits and raises nothing.
195    fn unnamed_bits(ty: TypeId, width: u32) -> FieldDecl {
196        FieldDecl::bit_field(None, ty, width)
197    }
198
199    #[test]
200    fn milestone_is_recorded() {
201        assert!(MILESTONE.starts_with('M'));
202    }
203
204    #[test]
205    fn an_integer_type_answers_with_the_width_of_its_value_and_not_of_its_object() {
206        let mut interner = Interner::new();
207        let mut types = Types::new();
208        let target = linux();
209
210        // A `bool` is one byte and holds one bit, and a `_BitInt(37)` is eight bytes and holds
211        // thirty seven. Folding a constant in the size rather than the width gets both wrong.
212        let boolean = types.boolean();
213        let bits = types.bit_int(true, 37);
214        // Through the sugar, the qualifiers and `_Atomic`, none of which is part of a value.
215        let short = types.int(IntKind::Short);
216        let alias = types.typedef(interner.intern("word"), short);
217        let unsigned_char = types.int(IntKind::UChar);
218        let atomic = types.atomic(unsigned_char);
219
220        let shape = |ty| integer_info(&types, ty, &target).expect("an integer type");
221        assert_eq!(shape(boolean), IntegerInfo::new(false, 1));
222        assert_eq!(shape(bits), IntegerInfo::new(true, 37));
223        assert_eq!(shape(types.int(IntKind::Int)), IntegerInfo::new(true, 32));
224        assert_eq!(shape(types.int(IntKind::ULong)), IntegerInfo::new(false, 64));
225        assert_eq!(shape(alias), IntegerInfo::new(true, 16));
226        assert_eq!(shape(atomic), IntegerInfo::new(false, 8));
227
228        assert_eq!(integer_info(&types, types.float(FloatKind::Double), &target), None);
229    }
230
231    #[test]
232    fn an_enumeration_answers_with_the_type_the_enumerators_are_kept_in() {
233        let mut interner = Interner::new();
234        let mut types = Types::new();
235        let target = linux();
236
237        // An enumeration that has not been completed has no underlying type yet, and the answer
238        // is that there is no answer rather than a guess at `int` that a later `: long` unsays.
239        let colour = types.declare_enum(Some(interner.intern("colour")));
240        let ty = types.enumeration(colour);
241        assert_eq!(integer_info(&types, ty, &target), None);
242
243        let underlying = types.int(IntKind::ULong);
244        types.complete_enum(colour, underlying, true);
245        assert_eq!(integer_info(&types, ty, &target), Some(IntegerInfo::new(false, 64)));
246    }
247
248    #[test]
249    fn a_value_stored_in_an_integer_type_keeps_the_bits_the_type_has_room_for() {
250        let char_type = IntegerInfo::new(true, 8);
251        assert_eq!(char_type.wrap(300), 44);
252        assert!(!char_type.holds(300));
253        assert!(char_type.holds(-128));
254
255        assert_eq!(IntegerInfo::new(false, 32).wrap(-1), 4_294_967_295);
256        assert_eq!(IntegerInfo::new(false, 8).wrap(-1), 255);
257
258        // Every pattern is a value of a hundred and twenty eight bit type, of either signedness,
259        // which is what stops the folding from inventing an overflow at the widest type there is.
260        assert!(IntegerInfo::new(false, 128).holds(i128::MIN));
261        assert!(IntegerInfo::new(true, 128).holds(i128::MIN));
262        assert_eq!(IntegerInfo::new(true, 128).wrap(i128::MAX), i128::MAX);
263    }
264
265    #[test]
266    fn a_long_double_has_a_format_the_size_does_not_give_away() {
267        let target = linux();
268        // Sixteen bytes on SysV x86-64 and eighty bits of x87 inside them. A compiler that
269        // picked the format by the size would fold every one of those constants too finely.
270        assert_eq!(float_width(FloatKind::LongDouble, &target), 128);
271        assert_eq!(
272            float_format(FloatKind::LongDouble, &target),
273            rucc_base::float::Format::X87Extended
274        );
275        assert_eq!(float_format(FloatKind::Float, &target), rucc_base::float::Format::Single);
276    }
277
278    #[test]
279    fn an_interchange_type_names_a_format_and_an_extended_one_names_the_target() {
280        use rucc_base::float::Format;
281
282        // The four `_FloatN` types are the same format everywhere, which is the point of them,
283        // so a program that wants binary128 can say so and get it or get told it cannot.
284        for target in [&linux(), &target("aarch64-apple-darwin")] {
285            assert_eq!(float_format(FloatKind::Float16, target), Format::Half);
286            assert_eq!(float_format(FloatKind::Float32, target), Format::Single);
287            assert_eq!(float_format(FloatKind::Float64, target), Format::Double);
288            assert_eq!(float_format(FloatKind::Float128, target), Format::Quad);
289            assert_eq!(float_width(FloatKind::Float16, target), 16);
290            assert_eq!(float_width(FloatKind::Float32, target), 32);
291            assert_eq!(float_width(FloatKind::Float64, target), 64);
292            assert_eq!(float_width(FloatKind::Float128, target), 128);
293            // `_Float32x` is `double` on every target this compiles for.
294            assert_eq!(float_format(FloatKind::Float32x, target), Format::Double);
295        }
296
297        // `_Float64x` is the one that moves, and it moves with the processor rather than with
298        // the operating system, so it stays eighty bits of x87 on x86-64 where `long double`
299        // is the same thing and is quad on Apple where `long double` is only a `double`.
300        let x86 = linux();
301        assert_eq!(float_format(FloatKind::Float64x, &x86), Format::X87Extended);
302        assert_eq!(float_format(FloatKind::LongDouble, &x86), Format::X87Extended);
303        let mac = target("aarch64-apple-darwin");
304        assert_eq!(float_format(FloatKind::Float64x, &mac), Format::Quad);
305        assert_eq!(float_format(FloatKind::LongDouble, &mac), Format::Double);
306        // Sixteen bytes either way, because the x87 eighty bits are stored padded, which is
307        // the same reason `long double` is sixteen bytes on x86-64 and not ten.
308        assert_eq!(float_width(FloatKind::Float64x, &x86), 128);
309        assert_eq!(float_width(FloatKind::Float64x, &mac), 128);
310    }
311
312    #[test]
313    fn every_floating_type_is_as_wide_as_the_format_it_is_stored_in() {
314        let types = Types::new();
315        let sizes = |target: &TargetInfo| -> Vec<(u64, u64)> {
316            FloatKind::ALL
317                .iter()
318                .map(|&kind| {
319                    let found = layout(&types, types.float(kind), target).expect("a complete type");
320                    (found.size, found.align)
321                })
322                .collect()
323        };
324        // Read off gcc 16 with `sizeof` and `_Alignof`, in the order of `FloatKind::ALL`. The
325        // two targets differ in one place, which is `long double`, and the eighty bit x87 value
326        // that `long double` and `_Float64x` hold on x86-64 takes sixteen bytes to store.
327        assert_eq!(
328            sizes(&linux()),
329            [
330                (2, 2),
331                (4, 4),
332                (4, 4),
333                (8, 8),
334                (8, 8),
335                (8, 8),
336                (16, 16),
337                (16, 16),
338                (16, 16),
339                (4, 4),
340                (8, 8),
341                (16, 16)
342            ]
343        );
344        assert_eq!(
345            sizes(&target("aarch64-apple-darwin")),
346            [
347                (2, 2),
348                (4, 4),
349                (4, 4),
350                (8, 8),
351                (8, 8),
352                (8, 8),
353                (8, 8),
354                (16, 16),
355                (16, 16),
356                (4, 4),
357                (8, 8),
358                (16, 16)
359            ]
360        );
361    }
362
363    #[test]
364    fn every_floating_type_has_a_slot_of_its_own_and_a_name_of_its_own() {
365        // Twelve types and twelve ids, which is what makes `_Float64` and `double` two types that
366        // `_Generic` can tell apart rather than one type with two spellings.
367        let types = Types::new();
368        let mut seen = Vec::new();
369        for kind in FloatKind::ALL {
370            seen.push(types.float(kind));
371        }
372        let mut sorted = seen.clone();
373        sorted.sort_unstable();
374        sorted.dedup();
375        assert_eq!(sorted.len(), seen.len(), "two floating types share an id");
376
377        let names: Vec<&str> = FloatKind::ALL.iter().map(|kind| kind.as_str()).collect();
378        assert_eq!(
379            names,
380            [
381                "_Float16",
382                "float",
383                "_Float32",
384                "double",
385                "_Float32x",
386                "_Float64",
387                "long double",
388                "_Float64x",
389                "_Float128",
390                "_Decimal32",
391                "_Decimal64",
392                "_Decimal128",
393            ]
394        );
395    }
396
397    #[test]
398    fn the_same_type_asked_for_twice_is_the_same_id() {
399        let mut types = Types::new();
400        let a = types.pointer(types.int(IntKind::Int));
401        let b = types.pointer(types.int(IntKind::Int));
402        assert_eq!(a, b, "interning is what makes type identity an integer comparison");
403        let c = types.pointer(types.int(IntKind::Long));
404        assert_ne!(a, c);
405    }
406
407    #[test]
408    fn a_qualifier_makes_a_different_type_with_the_same_shape() {
409        let mut types = Types::new();
410        let int = types.int(IntKind::Int);
411        let konst = types.qualified(int, Qualifiers::CONST);
412        assert_ne!(int, konst);
413        assert_eq!(types.kind(konst), types.kind(int));
414        assert!(types.quals(konst).has(Qualifiers::CONST));
415        assert_eq!(types.unqualified(konst), int);
416    }
417
418    #[test]
419    fn qualifiers_accumulate_and_do_not_depend_on_the_order_they_were_written() {
420        let mut types = Types::new();
421        let int = types.int(IntKind::Int);
422        let a = types.qualified(int, Qualifiers::CONST);
423        let a = types.qualified(a, Qualifiers::VOLATILE);
424        let b = types.qualified(int, Qualifiers::VOLATILE);
425        let b = types.qualified(b, Qualifiers::CONST);
426        assert_eq!(a, b, "`const volatile int` and `volatile const int` are one type");
427    }
428
429    #[test]
430    fn qualifying_an_array_qualifies_its_element() {
431        // 6.7.3p10, and not a shortcut. An array type has no qualifiers of its own, so if this
432        // put the `const` on the array then `const` on an array parameter would mean nothing.
433        let mut types = Types::new();
434        let int = types.int(IntKind::Int);
435        let array = types.array(int, ArrayLen::Fixed(4));
436        let konst = types.qualified(array, Qualifiers::CONST);
437        assert!(types.quals(konst).is_none(), "the array itself is unqualified");
438        let TypeKind::Array { elem, len } = types.kind(konst) else {
439            panic!("still an array");
440        };
441        assert_eq!(len, ArrayLen::Fixed(4));
442        assert!(types.quals(elem).has(Qualifiers::CONST));
443    }
444
445    #[test]
446    fn a_typedef_is_a_different_type_that_means_the_same_thing() {
447        let mut interner = Interner::new();
448        let mut types = Types::new();
449        let int = types.int(IntKind::Int);
450        let name = types.typedef(interner.intern("int32_t"), int);
451        assert_ne!(name, int, "the sugar survives, so a diagnostic can print it");
452        assert_eq!(types.canonical(name), int, "and no rule ever sees it");
453        assert!(types.is_sugar(name));
454        assert!(!types.is_sugar(int));
455    }
456
457    /// The names are a list beside the table and change nothing about what a type is.
458    ///
459    /// Two names for one type are one type, which is the whole reason they are kept here rather
460    /// than interned: the list grows and the identifiers do not, so the equality of two type
461    /// identifiers still means the two are the same type.
462    #[test]
463    fn a_typedef_name_is_recorded_without_making_a_type_of_its_own() {
464        let mut interner = Interner::new();
465        let mut types = Types::new();
466        let int = types.int(IntKind::Int);
467        types.alias(interner.intern("int32_t"), int);
468        types.alias(interner.intern("word"), int);
469        types.alias(interner.intern("int32_t"), int);
470        let names: Vec<_> =
471            types.aliases().iter().map(|had| interner.resolve(had.name).to_owned()).collect();
472        assert_eq!(names, ["int32_t", "word"], "the same name twice is one entry");
473        assert!(types.aliases().iter().all(|had| had.of == int));
474        assert_eq!(types.int(IntKind::Int), int, "and the type is the type it was");
475    }
476
477    #[test]
478    fn sugar_below_the_outermost_node_is_resolved_too() {
479        // The bug this is here for: canonicalising only the top node leaves `int32_t *` and
480        // `int *` as different types, and then every rule stated on pointers stops firing.
481        let mut interner = Interner::new();
482        let mut types = Types::new();
483        let int = types.int(IntKind::Int);
484        let name = types.typedef(interner.intern("int32_t"), int);
485        let sugar_pointer = types.pointer(name);
486        let plain_pointer = types.pointer(int);
487        assert_ne!(sugar_pointer, plain_pointer);
488        assert_eq!(types.canonical(sugar_pointer), plain_pointer);
489
490        let sugar_array = types.array(name, ArrayLen::Fixed(3));
491        let plain_array = types.array(int, ArrayLen::Fixed(3));
492        assert_eq!(types.canonical(sugar_array), plain_array);
493    }
494
495    #[test]
496    fn a_typedef_of_a_typedef_canonicalises_all_the_way_down() {
497        let mut interner = Interner::new();
498        let mut types = Types::new();
499        let int = types.int(IntKind::Int);
500        let mut current = int;
501        for i in 0..8 {
502            current = types.typedef(interner.intern(&format!("t{i}")), current);
503        }
504        assert_eq!(types.canonical(current), int);
505    }
506
507    #[test]
508    fn a_typedef_that_asked_for_an_alignment_says_what_it_is_and_not_what_it_is_at_least() {
509        // `__attribute__((aligned(n)))` in this one position replaces the alignment rather than
510        // raising it, which is what lets `typedef int L __attribute__((aligned(2)))` really be an
511        // `int` at a multiple of two. The size is left where it was, which is gcc's answer and the
512        // reason an array of an over aligned typedef is refused rather than padded.
513        let mut interner = Interner::new();
514        let mut types = Types::new();
515        let target = linux();
516        let int = types.int(IntKind::Int);
517        let low = types.aligned_typedef(interner.intern("L"), int, NonZeroU32::new(2).unwrap());
518        let high = types.aligned_typedef(interner.intern("H"), int, NonZeroU32::new(16).unwrap());
519
520        assert_eq!(layout(&types, low, &target), Ok(Layout::new(4, 2)));
521        assert_eq!(layout(&types, high, &target), Ok(Layout::new(4, 16)));
522        // And the type behind them is what it always was, since the alignment belongs to the name
523        // and not to the `int`.
524        assert_eq!(layout(&types, int, &target), Ok(Layout::new(4, 4)));
525
526        // Two names for one type that asked for different alignments are two types, which is why
527        // the alignment is part of what the table interns them by.
528        assert_ne!(low, high);
529
530        // The nearest one wins, because the outer typedef is the one a declaration was written
531        // with, and one that asked for nothing keeps whatever the one below it asked for.
532        let outer = types.aligned_typedef(interner.intern("M"), low, NonZeroU32::new(8).unwrap());
533        assert_eq!(types.align_override(outer), NonZeroU32::new(8));
534        let plain = types.typedef(interner.intern("N"), low);
535        assert_eq!(types.align_override(plain), NonZeroU32::new(2));
536        // Below the sugar there is nothing to find, since only a typedef can carry one of these.
537        assert_eq!(types.align_override(int), None);
538    }
539
540    #[test]
541    fn a_qualified_typedef_keeps_the_name_and_canonicalises_to_the_qualified_type() {
542        let mut interner = Interner::new();
543        let mut types = Types::new();
544        let int = types.int(IntKind::Int);
545        let name = types.typedef(interner.intern("int32_t"), int);
546        let konst = types.qualified(name, Qualifiers::CONST);
547        assert!(matches!(types.kind(konst), TypeKind::Typedef { .. }), "still prints as int32_t");
548        let want = types.qualified(int, Qualifiers::CONST);
549        assert_eq!(types.canonical(konst), want);
550    }
551
552    #[test]
553    fn a_typedef_of_an_array_pushes_a_qualifier_to_the_element_when_it_canonicalises() {
554        // `typedef int A[4]; const A x;` declares an array of `const int`, which is where the
555        // array rule and the sugar rule have to agree with each other.
556        let mut interner = Interner::new();
557        let mut types = Types::new();
558        let int = types.int(IntKind::Int);
559        let array = types.array(int, ArrayLen::Fixed(4));
560        let name = types.typedef(interner.intern("A"), array);
561        let konst = types.qualified(name, Qualifiers::CONST);
562        let konst_int = types.qualified(int, Qualifiers::CONST);
563        let want = types.array(konst_int, ArrayLen::Fixed(4));
564        assert_eq!(types.canonical(konst), want);
565    }
566
567    #[test]
568    fn a_function_type_is_deduplicated_by_its_signature() {
569        let mut types = Types::new();
570        let int = types.int(IntKind::Int);
571        let long = types.int(IntKind::Long);
572        let make = |types: &mut Types, params: Vec<TypeId>, variadic| {
573            types.function(FunctionType { ret: int, params, variadic, prototyped: true })
574        };
575        let a = make(&mut types, vec![int, long], false);
576        let b = make(&mut types, vec![int, long], false);
577        assert_eq!(a, b);
578        assert_ne!(a, make(&mut types, vec![int, long], true), "`...` is part of the type");
579        assert_ne!(a, make(&mut types, vec![long, int], false));
580    }
581
582    #[test]
583    fn a_function_type_written_with_a_typedef_canonicalises_through_its_signature() {
584        let mut interner = Interner::new();
585        let mut types = Types::new();
586        let int = types.int(IntKind::Int);
587        let name = types.typedef(interner.intern("int32_t"), int);
588        let sugar = types.function(FunctionType {
589            ret: name,
590            params: vec![name],
591            variadic: false,
592            prototyped: true,
593        });
594        let plain = types.function(FunctionType {
595            ret: int,
596            params: vec![int],
597            variadic: false,
598            prototyped: true,
599        });
600        assert_ne!(sugar, plain);
601        assert_eq!(types.canonical(sugar), plain);
602    }
603
604    #[test]
605    fn a_record_is_its_declaration_and_not_its_members() {
606        // Two structs written the same way in one translation unit are different types. The
607        // looser relation that does hold between them is compatibility, which is a separate
608        // question from identity and is answered elsewhere.
609        let mut interner = Interner::new();
610        let mut types = Types::new();
611        let tag = interner.intern("point");
612        let first = types.declare_record(RecordKind::Struct, Some(tag));
613        let second = types.declare_record(RecordKind::Struct, Some(tag));
614        assert_ne!(types.record(first), types.record(second));
615        assert_eq!(types.record(first), types.record(first));
616    }
617
618    #[test]
619    fn a_record_has_no_layout_until_it_has_been_completed() {
620        let mut types = Types::new();
621        let id = types.declare_record(RecordKind::Struct, None);
622        let ty = types.record(id);
623        assert_eq!(layout(&types, ty, &linux()), Err(LayoutError::Incomplete));
624        let long_long = types.int(IntKind::LongLong);
625        let laid_out = lay_out(&types, RecordKind::Struct, &[member(long_long); 2]);
626        types.complete_record(id, laid_out);
627        assert_eq!(layout(&types, ty, &linux()).unwrap(), Layout::new(16, 8));
628    }
629
630    #[test]
631    fn an_enum_takes_the_layout_of_its_underlying_type() {
632        let mut types = Types::new();
633        let id = types.declare_enum(None);
634        let ty = types.enumeration(id);
635        assert_eq!(layout(&types, ty, &linux()), Err(LayoutError::Incomplete));
636        let int = types.int(IntKind::Int);
637        types.complete_enum(id, int, false);
638        assert_eq!(layout(&types, ty, &linux()).unwrap(), Layout::new(4, 4));
639    }
640
641    #[test]
642    fn the_scalar_widths_come_from_the_target() {
643        let mut types = Types::new();
644        let linux = linux();
645        let windows = target("x86_64-pc-windows-msvc");
646        let darwin = target("aarch64-apple-darwin");
647
648        let long = types.int(IntKind::Long);
649        assert_eq!(layout(&types, long, &linux).unwrap(), Layout::new(8, 8));
650        assert_eq!(layout(&types, long, &windows).unwrap(), Layout::new(4, 4), "LLP64");
651
652        let ldouble = types.float(FloatKind::LongDouble);
653        assert_eq!(layout(&types, ldouble, &linux).unwrap(), Layout::new(16, 16));
654        assert_eq!(layout(&types, ldouble, &darwin).unwrap(), Layout::new(8, 8));
655
656        let pointer = types.pointer(types.void());
657        assert_eq!(layout(&types, pointer, &linux).unwrap(), Layout::new(8, 8));
658
659        let boolean = types.boolean();
660        assert_eq!(layout(&types, boolean, &linux).unwrap(), Layout::new(1, 1));
661    }
662
663    #[test]
664    fn a_complex_type_is_two_of_its_component_with_the_components_alignment() {
665        // `_Complex long double` on SysV x86-64 is thirty two bytes aligned to sixteen, which
666        // is the case that catches an implementation that aligns the pair to its own size.
667        let mut types = Types::new();
668        let linux = linux();
669        let cfloat = types.complex_float(FloatKind::Float);
670        assert_eq!(layout(&types, cfloat, &linux).unwrap(), Layout::new(8, 4));
671        let cdouble = types.complex_float(FloatKind::Double);
672        assert_eq!(layout(&types, cdouble, &linux).unwrap(), Layout::new(16, 8));
673        let cldouble = types.complex_float(FloatKind::LongDouble);
674        assert_eq!(layout(&types, cldouble, &linux).unwrap(), Layout::new(32, 16));
675        let darwin = target("aarch64-apple-darwin");
676        assert_eq!(layout(&types, cldouble, &darwin).unwrap(), Layout::new(16, 8));
677    }
678
679    #[test]
680    fn an_atomic_type_can_be_more_aligned_than_the_type_it_wraps() {
681        // The whole reason `_Atomic` is a type here rather than a qualifier. A sixteen byte
682        // record is aligned to eight and the atomic version of it is aligned to sixteen.
683        let mut types = Types::new();
684        let linux = linux();
685        let long_long = types.int(IntKind::LongLong);
686        let plain = record(&mut types, RecordKind::Struct, &[member(long_long); 2]);
687        let atomic = types.atomic(plain);
688        assert_eq!(layout(&types, plain, &linux).unwrap(), Layout::new(16, 8));
689        assert_eq!(layout(&types, atomic, &linux).unwrap(), Layout::new(16, 16));
690
691        // An odd size cannot be accessed atomically in one go, so nothing is raised.
692        let odd = record(&mut types, RecordKind::Struct, &[member(long_long); 3]);
693        let atomic_odd = types.atomic(odd);
694        assert_eq!(layout(&types, atomic_odd, &linux).unwrap(), Layout::new(24, 8));
695
696        let int = types.int(IntKind::Int);
697        let atomic_int = types.atomic(int);
698        assert_eq!(layout(&types, atomic_int, &linux).unwrap(), Layout::new(4, 4));
699    }
700
701    #[test]
702    fn a_bit_int_is_laid_out_like_a_standard_integer_until_it_outgrows_one() {
703        // Measured with clang 18 on x86-64 Linux and clang on AArch64 Darwin. The two disagree
704        // above sixty four bits, which is why the granule is a target fact.
705        let mut types = Types::new();
706        let linux = linux();
707        let darwin = target("aarch64-apple-darwin");
708        let cases = [(7, 1, 1), (8, 1, 1), (9, 2, 2), (17, 4, 4), (33, 8, 8), (64, 8, 8)];
709        for (width, size, align) in cases {
710            let ty = types.bit_int(true, width);
711            assert_eq!(layout(&types, ty, &linux).unwrap(), Layout::new(size, align), "{width}");
712            assert_eq!(layout(&types, ty, &darwin).unwrap(), Layout::new(size, align), "{width}");
713        }
714        for width in [65, 96, 128] {
715            let ty = types.bit_int(false, width);
716            assert_eq!(layout(&types, ty, &linux).unwrap(), Layout::new(16, 8), "{width}");
717            assert_eq!(layout(&types, ty, &darwin).unwrap(), Layout::new(16, 16), "{width}");
718        }
719        let wide = types.bit_int(true, 129);
720        assert_eq!(layout(&types, wide, &linux).unwrap(), Layout::new(24, 8));
721        assert_eq!(layout(&types, wide, &darwin).unwrap(), Layout::new(32, 16));
722    }
723
724    #[test]
725    fn an_array_is_its_element_repeated_and_keeps_its_elements_alignment() {
726        let mut types = Types::new();
727        let linux = linux();
728        let int = types.int(IntKind::Int);
729        let ty = types.array(int, ArrayLen::Fixed(10));
730        assert_eq!(layout(&types, ty, &linux).unwrap(), Layout::new(40, 4));
731        let nested = types.array(ty, ArrayLen::Fixed(3));
732        assert_eq!(layout(&types, nested, &linux).unwrap(), Layout::new(120, 4));
733    }
734
735    #[test]
736    fn an_array_without_a_size_is_incomplete_and_an_impossible_one_says_so() {
737        let mut types = Types::new();
738        let linux = linux();
739        let int = types.int(IntKind::Int);
740        for len in [ArrayLen::Unknown, ArrayLen::Star] {
741            let ty = types.array(int, len);
742            assert_eq!(layout(&types, ty, &linux), Err(LayoutError::Incomplete));
743        }
744        // An array whose length the program computes is a different answer from an incomplete
745        // one, because it is not a mistake: there is a size and this is not the place that
746        // knows it. A caller that only wants a number treats the two the same and a caller
747        // building the arithmetic asks for the members instead.
748        let measured = types.array(int, ArrayLen::Variable(VlaId(0)));
749        assert_eq!(layout(&types, measured, &linux), Err(LayoutError::Variable));
750        assert_eq!(align(&types, measured, &linux), Ok(4));
751        let huge = types.array(int, ArrayLen::Fixed(u64::MAX));
752        assert_eq!(layout(&types, huge, &linux), Err(LayoutError::TooLarge));
753    }
754
755    #[test]
756    fn the_largest_array_is_the_largest_object_and_not_the_largest_number() {
757        // The limit is `PTRDIFF_MAX` rather than wherever the multiplication happens to
758        // overflow, so an array of a byte may be every byte an object may have and one more
759        // than that is refused. gcc 16 gives the same two answers.
760        let mut types = Types::new();
761        let linux = linux();
762        let max = linux.max_object_size();
763        let ch = types.int(IntKind::Char);
764        let fits = types.array(ch, ArrayLen::Fixed(max));
765        assert_eq!(layout(&types, fits, &linux), Ok(Layout::new(max, 1)));
766        let over = types.array(ch, ArrayLen::Fixed(max + 1));
767        assert_eq!(layout(&types, over, &linux), Err(LayoutError::TooLarge));
768    }
769
770    #[test]
771    fn a_record_may_be_as_large_as_an_object_may_be_and_no_larger() {
772        // The shape `991014-1.c` in the gcc.c-torture execution suite asks about: a type
773        // nothing is ever an object of is still a type `sizeof` has to answer about. Counting
774        // the record in bits made the largest one an eighth of this, with the multiply by eight
775        // overflowing rather than any rule saying so.
776        let mut types = Types::new();
777        let linux = linux();
778        let max = linux.max_object_size();
779        let ch = types.int(IntKind::Char);
780        let int = types.int(IntKind::Int);
781        let short = types.int(IntKind::Short);
782
783        let huge = types.array(short, ArrayLen::Fixed((1 << 62) - 256));
784        let members = [member(huge), member(int), member(int), member(int), member(int)];
785        let laid_out = lay_out(&types, RecordKind::Struct, &members);
786        assert_eq!(laid_out.layout, Layout::new((1 << 63) - 496, 4));
787
788        let brim = types.array(ch, ArrayLen::Fixed(max));
789        let laid_out = lay_out(&types, RecordKind::Struct, &[member(brim)]);
790        assert_eq!(laid_out.layout, Layout::new(max, 1));
791
792        let over = [member(brim), member(ch)];
793        let options = RecordOptions::default();
794        let error = layout_record(&types, RecordKind::Struct, &over, &options, &linux);
795        assert_eq!(error, Err(RecordError::TooLarge));
796    }
797
798    #[test]
799    fn a_bit_field_past_where_a_bit_count_fits_is_still_placed() {
800        // Eight times the largest object is more than a `u64` holds, so a bit-field at the end
801        // of a record that large has a bit offset no bit count can name. It is a byte offset
802        // and a bit within it here, which is what lets this be laid out at all, and gcc 16
803        // gives the same size for it.
804        let mut types = Types::new();
805        let linux = linux();
806        let ch = types.int(IntKind::Char);
807        let int = types.int(IntKind::Int);
808        let mut interner = Interner::new();
809        let buf = types.array(ch, ArrayLen::Fixed(linux.max_object_size() - 7));
810        let members = [member(buf), bits(&mut interner, "x", int, 1)];
811        let laid_out = lay_out(&types, RecordKind::Struct, &members);
812        assert_eq!(laid_out.layout, Layout::new(9_223_372_036_854_775_804, 4));
813        let last = laid_out.fields[1];
814        assert_eq!((last.offset, last.bit), (9_223_372_036_854_775_800, 0));
815        assert_eq!(last.bit_offset(), 73_786_976_294_838_206_400);
816    }
817
818    #[test]
819    fn two_variable_length_arrays_of_the_same_element_are_still_different_types() {
820        let mut types = Types::new();
821        let int = types.int(IntKind::Int);
822        let a = types.array(int, ArrayLen::Variable(VlaId(0)));
823        let b = types.array(int, ArrayLen::Variable(VlaId(1)));
824        assert_ne!(a, b);
825    }
826
827    #[test]
828    fn a_vector_is_rounded_up_to_a_power_of_two_and_aligned_to_the_whole_thing() {
829        // What GCC does with a `vector_size` that is not already one, checked against clang on
830        // AArch64 Darwin, which accepts the three element case that GCC rejects outright.
831        let mut types = Types::new();
832        let linux = linux();
833        let int = types.int(IntKind::Int);
834        let four = types.vector(int, 4);
835        assert_eq!(layout(&types, four, &linux).unwrap(), Layout::new(16, 16));
836        let three = types.vector(int, 3);
837        assert_eq!(layout(&types, three, &linux).unwrap(), Layout::new(16, 16));
838        let three_chars = types.vector(types.int(IntKind::Char), 3);
839        assert_eq!(layout(&types, three_chars, &linux).unwrap(), Layout::new(4, 4));
840    }
841
842    #[test]
843    fn the_types_without_a_size_say_which_kind_of_without_they_are() {
844        // Kept apart because GNU C gives both of them a size of one and a different warning,
845        // and because a caller that cannot tell them apart cannot write either message.
846        let mut types = Types::new();
847        let linux = linux();
848        let void = types.void();
849        assert_eq!(layout(&types, void, &linux), Err(LayoutError::Incomplete));
850        let int = types.int(IntKind::Int);
851        let function = types.function(FunctionType {
852            ret: int,
853            params: Vec::new(),
854            variadic: false,
855            prototyped: true,
856        });
857        assert_eq!(layout(&types, function, &linux), Err(LayoutError::Function));
858        let pointer_to_function = types.pointer(function);
859        assert_eq!(layout(&types, pointer_to_function, &linux).unwrap(), Layout::new(8, 8));
860    }
861
862    #[test]
863    fn a_struct_puts_each_member_at_the_next_offset_it_is_allowed_to_start_at() {
864        let types = Types::new();
865        let char_ = types.int(IntKind::Char);
866        let int = types.int(IntKind::Int);
867        let laid_out = lay_out(&types, RecordKind::Struct, &[member(char_), member(int)]);
868        assert_eq!(laid_out.layout, Layout::new(8, 4));
869        assert_eq!(offsets(&laid_out), [0, 32]);
870        assert_eq!(laid_out.fields[1].offset, 4);
871
872        // And the tail is padded, which is what makes an array of the thing work.
873        let long_long = types.int(IntKind::LongLong);
874        let laid_out = lay_out(&types, RecordKind::Struct, &[member(long_long), member(char_)]);
875        assert_eq!(laid_out.layout, Layout::new(16, 8));
876    }
877
878    #[test]
879    fn a_union_starts_every_member_at_zero_and_is_as_large_as_the_largest() {
880        let mut types = Types::new();
881        let char_ = types.int(IntKind::Char);
882        let int = types.int(IntKind::Int);
883        let laid_out = lay_out(&types, RecordKind::Union, &[member(char_), member(int)]);
884        assert_eq!(laid_out.layout, Layout::new(4, 4));
885        assert_eq!(offsets(&laid_out), [0, 0]);
886
887        // Nine bytes and a short is ten, not nine and not sixteen: the size is rounded up to
888        // the alignment rather than to the largest member.
889        let nine = types.array(char_, ArrayLen::Fixed(9));
890        let short = types.int(IntKind::Short);
891        let laid_out = lay_out(&types, RecordKind::Union, &[member(nine), member(short)]);
892        assert_eq!(laid_out.layout, Layout::new(10, 2));
893    }
894
895    #[test]
896    fn bit_fields_share_a_unit_until_one_of_them_would_span_two() {
897        // Measured with gcc 13.3 on x86-64 Linux and clang on AArch64 Darwin, including where
898        // the bits landed, by setting each field to all ones and dumping the bytes.
899        let mut interner = Interner::new();
900        let types = Types::new();
901        let char_ = types.int(IntKind::Char);
902        let int = types.int(IntKind::Int);
903        let long_long = types.int(IntKind::LongLong);
904
905        let fields = [bits(&mut interner, "a", int, 3), bits(&mut interner, "b", int, 5)];
906        let laid_out = lay_out(&types, RecordKind::Struct, &fields);
907        assert_eq!(laid_out.layout, Layout::new(4, 4));
908        assert_eq!(offsets(&laid_out), [0, 3]);
909
910        // Thirty bits do not fit in what is left of the first int, so they start a new one.
911        let fields = [member(char_), bits(&mut interner, "b", int, 30)];
912        let laid_out = lay_out(&types, RecordKind::Struct, &fields);
913        assert_eq!(laid_out.layout, Layout::new(8, 4));
914        assert_eq!(offsets(&laid_out), [0, 32]);
915
916        // Thirty three bits of a `long long` do fit in what is left of the first one, because
917        // the unit is eight bytes rather than four, so they stay where they are.
918        let fields = [member(char_), bits(&mut interner, "b", long_long, 33)];
919        let laid_out = lay_out(&types, RecordKind::Struct, &fields);
920        assert_eq!(laid_out.layout, Layout::new(8, 8));
921        assert_eq!(offsets(&laid_out), [0, 8]);
922
923        // An ordinary member after a bit-field starts at the next byte it is allowed to.
924        let fields = [bits(&mut interner, "a", int, 3), member(char_)];
925        let laid_out = lay_out(&types, RecordKind::Struct, &fields);
926        assert_eq!(offsets(&laid_out), [0, 8]);
927    }
928
929    #[test]
930    fn a_zero_width_bit_field_moves_the_next_member_on_and_nothing_else() {
931        let types = Types::new();
932        let char_ = types.int(IntKind::Char);
933        let int = types.int(IntKind::Int);
934        let fields = [member(char_), unnamed_bits(int, 0), member(char_)];
935        let laid_out = lay_out(&types, RecordKind::Struct, &fields);
936        // Five bytes aligned to one: the zero width field pushed the second `char` to offset
937        // four without giving the record the alignment of an `int`. Both compilers report that.
938        assert_eq!(laid_out.layout, Layout::new(5, 1));
939        assert_eq!(offsets(&laid_out), [0, 32, 32]);
940        assert_eq!(laid_out.fields.len(), 3, "one field per declaration, so indices line up");
941
942        // With nothing after it the padding is still the record's, which is the half of the rule
943        // the case above hides: the second `char` ends further along than the zero width field
944        // does, so whether the field moved the size or only the next member never showed.
945        let trailing = [member(char_), unnamed_bits(int, 0)];
946        assert_eq!(lay_out(&types, RecordKind::Struct, &trailing).layout, Layout::new(4, 1));
947
948        // And a record that is nothing but the zero width field has nothing to pad, so it is the
949        // empty structure with the alignment of whatever the field's type was.
950        let only = [unnamed_bits(int, 0)];
951        assert_eq!(lay_out(&types, RecordKind::Struct, &only).layout, Layout::new(0, 1));
952    }
953
954    #[test]
955    fn an_unnamed_bit_field_does_not_raise_the_records_alignment_but_a_named_one_does() {
956        let mut interner = Interner::new();
957        let types = Types::new();
958        let char_ = types.int(IntKind::Char);
959        let int = types.int(IntKind::Int);
960
961        let unnamed = [member(char_), unnamed_bits(int, 20)];
962        let unnamed = lay_out(&types, RecordKind::Struct, &unnamed);
963        assert_eq!(unnamed.layout, Layout::new(4, 1));
964
965        let named = [member(char_), bits(&mut interner, "b", int, 20)];
966        let named = lay_out(&types, RecordKind::Struct, &named);
967        assert_eq!(named.layout, Layout::new(4, 4));
968        assert_eq!(offsets(&named), [0, 8], "the same place either way");
969
970        // The unit an unnamed field has to fit inside is still its own type's, so this one
971        // moves to bit thirty two and the record is eight bytes aligned to one.
972        let wider = [member(char_), unnamed_bits(int, 30)];
973        let wider = lay_out(&types, RecordKind::Struct, &wider);
974        assert_eq!(wider.layout, Layout::new(8, 1));
975        assert_eq!(offsets(&wider), [0, 32]);
976    }
977
978    #[test]
979    fn aapcs64_lets_an_unnamed_bit_field_raise_the_records_alignment() {
980        let types = Types::new();
981        let char_ = types.int(IntKind::Char);
982        let uint = types.int(IntKind::UInt);
983
984        // The same structure as the test above, on the one ABI in the table that disagrees.
985        let fields = [member(char_), unnamed_bits(uint, 20)];
986        let arm = lay_out_on(&aapcs(), &types, RecordKind::Struct, &fields);
987        assert_eq!(arm.layout, Layout::new(4, 4));
988
989        // The zero width member is the case a program actually writes, and it is where the rule
990        // is visible with nothing else in the record at all.
991        let only = [unnamed_bits(uint, 0)];
992        assert_eq!(
993            lay_out_on(&aapcs(), &types, RecordKind::Struct, &only).layout,
994            Layout::new(0, 4)
995        );
996        assert_eq!(lay_out(&types, RecordKind::Struct, &only).layout, Layout::new(0, 1));
997
998        // And it changes a size rather than only an alignment, because the record is rounded up
999        // to the alignment it ends with. Five bytes on x86-64 and eight here.
1000        let pushed = [member(char_), unnamed_bits(uint, 0), member(char_)];
1001        let pushed = lay_out_on(&aapcs(), &types, RecordKind::Struct, &pushed);
1002        assert_eq!(pushed.layout, Layout::new(8, 4));
1003        assert_eq!(offsets(&pushed), [0, 32, 32]);
1004    }
1005
1006    #[test]
1007    fn windows_allocates_a_bit_field_into_a_unit_of_its_declared_type() {
1008        let mut interner = Interner::new();
1009        let types = Types::new();
1010        let char_ = types.int(IntKind::Char);
1011        let uint = types.int(IntKind::UInt);
1012        let ushort = types.int(IntKind::UShort);
1013        let longlong = types.int(IntKind::LongLong);
1014
1015        // An ordinary member closes the unit, and the unit costs its whole four bytes, so the
1016        // `char` is at offset four rather than at offset one.
1017        let then_member = [bits(&mut interner, "m0", uint, 3), member(char_)];
1018        let ms = lay_out_on(&windows(), &types, RecordKind::Struct, &then_member);
1019        assert_eq!(ms.layout, Layout::new(8, 4));
1020        assert_eq!(offsets(&ms), [0, 32]);
1021        let itanium = lay_out(&types, RecordKind::Struct, &then_member);
1022        assert_eq!(itanium.layout, Layout::new(4, 4));
1023        assert_eq!(offsets(&itanium), [0, 8]);
1024
1025        // A declared type of a different size closes it too, although five bits were free.
1026        let narrower = [bits(&mut interner, "m0", uint, 3), bits(&mut interner, "m1", ushort, 5)];
1027        let ms = lay_out_on(&windows(), &types, RecordKind::Struct, &narrower);
1028        assert_eq!(ms.layout, Layout::new(8, 4));
1029        assert_eq!(offsets(&ms), [0, 32]);
1030        assert_eq!(lay_out(&types, RecordKind::Struct, &narrower).layout, Layout::new(4, 4));
1031
1032        // And the unit is opened at its own alignment, so a `long long` bit-field after a `char`
1033        // starts at offset eight where the Itanium rule leaves it at bit eight.
1034        let wide = [member(char_), bits(&mut interner, "b", longlong, 33)];
1035        let ms = lay_out_on(&windows(), &types, RecordKind::Struct, &wide);
1036        assert_eq!(ms.layout, Layout::new(16, 8));
1037        assert_eq!(offsets(&ms), [0, 64]);
1038        let itanium = lay_out(&types, RecordKind::Struct, &wide);
1039        assert_eq!(itanium.layout, Layout::new(8, 8));
1040        assert_eq!(offsets(&itanium), [0, 8]);
1041    }
1042
1043    #[test]
1044    fn microsofts_zero_width_bit_field_closes_a_unit_and_does_nothing_without_one() {
1045        let mut interner = Interner::new();
1046        let types = Types::new();
1047        let char_ = types.int(IntKind::Char);
1048        let uint = types.int(IntKind::UInt);
1049
1050        // Nothing before it is a bit-field, so there is no run to end and the member is free.
1051        let alone = [member(char_), unnamed_bits(uint, 0)];
1052        assert_eq!(
1053            lay_out_on(&windows(), &types, RecordKind::Struct, &alone).layout,
1054            Layout::new(1, 1)
1055        );
1056        assert_eq!(lay_out(&types, RecordKind::Struct, &alone).layout, Layout::new(4, 1));
1057
1058        // With a unit open it ends it, and the member after starts a unit of its own.
1059        let between = [
1060            bits(&mut interner, "m0", uint, 3),
1061            unnamed_bits(uint, 0),
1062            bits(&mut interner, "m1", uint, 5),
1063            member(char_),
1064        ];
1065        let ms = lay_out_on(&windows(), &types, RecordKind::Struct, &between);
1066        assert_eq!(ms.layout, Layout::new(12, 4));
1067        assert_eq!(offsets(&ms), [0, 32, 32, 64]);
1068        let itanium = lay_out(&types, RecordKind::Struct, &between);
1069        assert_eq!(itanium.layout, Layout::new(8, 4));
1070        assert_eq!(offsets(&itanium), [0, 32, 32, 40]);
1071
1072        // And after a unit narrower than its own type it rounds to its type's alignment and
1073        // raises the record's, which is what gcc on mingw-w64 prints for this one.
1074        let int_ = types.int(IntKind::Int);
1075        let narrow = [
1076            bits(&mut interner, "a", char_, 1),
1077            unnamed_bits(int_, 0),
1078            bits(&mut interner, "b", char_, 1),
1079        ];
1080        for target in [windows(), target("x86_64-pc-windows-gnu")] {
1081            let ms = lay_out_on(&target, &types, RecordKind::Struct, &narrow);
1082            assert_eq!(ms.layout, Layout::new(8, 4));
1083            assert_eq!(offsets(&ms), [0, 32, 32]);
1084        }
1085    }
1086
1087    #[test]
1088    fn msvc_gives_a_unions_bit_field_storage_and_no_say_in_the_alignment() {
1089        let mut interner = Interner::new();
1090        let types = Types::new();
1091        let char_ = types.int(IntKind::Char);
1092        let uint = types.int(IntKind::UInt);
1093
1094        // Four bytes because the unit is an `unsigned`, aligned to one because the only member
1095        // that gets a say is the `char`. An alignment smaller than either member would have.
1096        let fields = [bits(&mut interner, "m0", uint, 3), member(char_)];
1097        assert_eq!(
1098            lay_out_on(&windows(), &types, RecordKind::Union, &fields).layout,
1099            Layout::new(4, 1)
1100        );
1101        assert_eq!(lay_out(&types, RecordKind::Union, &fields).layout, Layout::new(4, 4));
1102        // MinGW's gcc aligns it to four with the same bit-field rule otherwise, and clang aligns
1103        // it to one. gcc is the incumbent there, so its answer is the one taken.
1104        let mingw = target("x86_64-pc-windows-gnu");
1105        assert_eq!(
1106            lay_out_on(&mingw, &types, RecordKind::Union, &fields).layout,
1107            Layout::new(4, 4)
1108        );
1109    }
1110
1111    #[test]
1112    fn a_record_with_no_storage_in_it_is_four_bytes_under_msvc_and_nothing_anywhere_else() {
1113        let mut types = Types::new();
1114        let uint = types.int(IntKind::UInt);
1115        let mingw = target("x86_64-pc-windows-gnu");
1116
1117        // Three shapes that hold nothing, and the reference gives all three the same answer.
1118        let none: [FieldDecl; 0] = [];
1119        let zero_width = [unnamed_bits(uint, 0)];
1120        let flexible = [member(types.array(uint, ArrayLen::Unknown))];
1121        for fields in [&none[..], &zero_width[..], &flexible[..]] {
1122            let msvc = lay_out_on(&windows(), &types, RecordKind::Struct, fields);
1123            assert_eq!(msvc.layout.size, 4, "four bytes under MSVC");
1124            assert_eq!(lay_out_on(&mingw, &types, RecordKind::Struct, fields).layout.size, 0);
1125            assert_eq!(lay_out(&types, RecordKind::Struct, fields).layout.size, 0);
1126        }
1127
1128        // It is the environment that decides and not the operating system, so the two Windows
1129        // targets disagree with each other and mingw agrees with Linux. A rule keyed on the
1130        // operating system would have put both of them at four.
1131        assert_eq!(windows().empty_record_size, 4);
1132        assert_eq!(mingw.empty_record_size, 0);
1133    }
1134
1135    #[test]
1136    fn packed_drops_every_member_to_a_byte_and_bit_fields_to_the_next_free_bit() {
1137        let mut interner = Interner::new();
1138        let types = Types::new();
1139        let char_ = types.int(IntKind::Char);
1140        let int = types.int(IntKind::Int);
1141        let packed = RecordOptions { packed: true, ..RecordOptions::default() };
1142
1143        let fields = [member(char_), member(int)];
1144        let laid_out = layout_record(&types, RecordKind::Struct, &fields, &packed, &linux())
1145            .expect("a packed struct of two complete members");
1146        assert_eq!(laid_out.layout, Layout::new(5, 1));
1147        assert_eq!(offsets(&laid_out), [0, 8]);
1148
1149        let fields = [member(char_), bits(&mut interner, "b", int, 30)];
1150        let laid_out = layout_record(&types, RecordKind::Struct, &fields, &packed, &linux())
1151            .expect("a packed struct with a bit-field");
1152        assert_eq!(laid_out.layout, Layout::new(5, 1));
1153        assert_eq!(offsets(&laid_out), [0, 8], "no boundary left to move to");
1154
1155        // A zero width bit-field still rounds to its own type, packed or not, which is the
1156        // whole reason a program writes one inside a packed structure.
1157        let fields = [member(char_), unnamed_bits(int, 0), member(char_)];
1158        let laid_out = layout_record(&types, RecordKind::Struct, &fields, &packed, &linux())
1159            .expect("a packed struct with a zero width bit-field");
1160        assert_eq!(laid_out.layout, Layout::new(5, 1));
1161        assert_eq!(offsets(&laid_out), [0, 32, 32]);
1162    }
1163
1164    #[test]
1165    fn pragma_pack_caps_alignment_and_leaves_a_bit_field_where_it_already_is() {
1166        let mut interner = Interner::new();
1167        let types = Types::new();
1168        let char_ = types.int(IntKind::Char);
1169        let int = types.int(IntKind::Int);
1170        let pack = RecordOptions { pack: Some(2), ..RecordOptions::default() };
1171
1172        let fields = [member(char_), member(int)];
1173        let laid_out = layout_record(&types, RecordKind::Struct, &fields, &pack, &linux())
1174            .expect("a packed struct of two complete members");
1175        assert_eq!(laid_out.layout, Layout::new(6, 2));
1176        assert_eq!(offsets(&laid_out), [0, 16]);
1177
1178        // Six bytes with the field at bit eight, not at bit sixteen. Once the alignment has
1179        // been capped below the type's own there is no boundary to move to, so the field stays
1180        // put. Measured, because moving it is at least as plausible a reading.
1181        let fields = [member(char_), bits(&mut interner, "b", int, 30)];
1182        let laid_out = layout_record(&types, RecordKind::Struct, &fields, &pack, &linux())
1183            .expect("a packed struct with a bit-field");
1184        assert_eq!(laid_out.layout, Layout::new(6, 2));
1185        assert_eq!(offsets(&laid_out), [0, 8]);
1186
1187        // The same structure with the field unnamed is five bytes aligned to one, because the
1188        // capped alignment reached it through the record and an unnamed field gives none back.
1189        let fields = [member(char_), unnamed_bits(int, 30)];
1190        let laid_out = layout_record(&types, RecordKind::Struct, &fields, &pack, &linux())
1191            .expect("a packed struct with an unnamed bit-field");
1192        assert_eq!(laid_out.layout, Layout::new(5, 1));
1193    }
1194
1195    #[test]
1196    fn an_alignment_the_program_asked_for_raises_the_member_and_the_record() {
1197        let types = Types::new();
1198        let char_ = types.int(IntKind::Char);
1199        let int = types.int(IntKind::Int);
1200
1201        let aligned = FieldDecl { align: Some(16), ..member(int) };
1202        let laid_out = lay_out(&types, RecordKind::Struct, &[member(char_), aligned]);
1203        assert_eq!(laid_out.layout, Layout::new(32, 16));
1204        assert_eq!(offsets(&laid_out), [0, 128]);
1205
1206        // `packed, aligned(4)` together: the members pack and the record does not, which is
1207        // the combination the attribute pair exists for.
1208        let options = RecordOptions { packed: true, align: Some(4), pack: None };
1209        let fields = [member(char_), member(int)];
1210        let laid_out = layout_record(&types, RecordKind::Struct, &fields, &options, &linux())
1211            .expect("a packed struct with an alignment asked for");
1212        assert_eq!(laid_out.layout, Layout::new(8, 4));
1213        assert_eq!(offsets(&laid_out), [0, 8]);
1214    }
1215
1216    #[test]
1217    fn a_flexible_array_member_costs_nothing_but_its_alignment() {
1218        // What makes `malloc(sizeof(struct S) + n)` the idiom it is.
1219        let mut types = Types::new();
1220        let char_ = types.int(IntKind::Char);
1221        let int = types.int(IntKind::Int);
1222        let long_long = types.int(IntKind::LongLong);
1223
1224        let chars = types.array(char_, ArrayLen::Unknown);
1225        let laid_out = lay_out(&types, RecordKind::Struct, &[member(int), member(chars)]);
1226        assert_eq!(laid_out.layout, Layout::new(4, 4));
1227        assert_eq!(offsets(&laid_out), [0, 32]);
1228
1229        // The alignment still applies, so this is eight bytes of which one is the `char`.
1230        let longs = types.array(long_long, ArrayLen::Unknown);
1231        let laid_out = lay_out(&types, RecordKind::Struct, &[member(char_), member(longs)]);
1232        assert_eq!(laid_out.layout, Layout::new(8, 8));
1233        assert_eq!(offsets(&laid_out), [0, 64]);
1234
1235        // Anywhere but last it is an incomplete member, and which member is part of the answer.
1236        let fields = [member(chars), member(int)];
1237        let error =
1238            layout_record(&types, RecordKind::Struct, &fields, &RecordOptions::default(), &linux());
1239        assert_eq!(error, Err(RecordError::Member { index: 0, error: LayoutError::Incomplete }));
1240    }
1241
1242    #[test]
1243    fn a_record_with_no_members_is_zero_bytes_aligned_to_one() {
1244        // The GNU empty structure, which C itself does not have and which real headers do.
1245        let types = Types::new();
1246        let laid_out = lay_out(&types, RecordKind::Struct, &[]);
1247        assert_eq!(laid_out.layout, Layout::new(0, 1));
1248    }
1249
1250    #[test]
1251    fn a_bit_field_wider_than_the_type_it_is_declared_with_is_refused() {
1252        let types = Types::new();
1253        let int = types.int(IntKind::Int);
1254        let fields = [unnamed_bits(int, 33)];
1255        let error =
1256            layout_record(&types, RecordKind::Struct, &fields, &RecordOptions::default(), &linux());
1257        let want = RecordError::BitFieldTooWide { index: 0, width: 33, capacity: 32 };
1258        assert_eq!(error, Err(want));
1259    }
1260
1261    #[test]
1262    fn a_record_reports_its_members_once_it_has_been_completed() {
1263        let mut interner = Interner::new();
1264        let mut types = Types::new();
1265        let char_ = types.int(IntKind::Char);
1266        let int = types.int(IntKind::Int);
1267        let name = interner.intern("count");
1268        let fields = [member(char_), FieldDecl::new(Some(name), int)];
1269        let id = types.declare_record(RecordKind::Struct, None);
1270        let laid_out = lay_out(&types, RecordKind::Struct, &fields);
1271        types.complete_record(id, laid_out);
1272        let ty = types.record(id);
1273        assert_eq!(layout(&types, ty, &linux()).unwrap(), Layout::new(8, 4));
1274        let field = types.field(id, name).expect("the member that was declared");
1275        assert_eq!(field.offset, 4);
1276        assert!(!field.is_bit_field());
1277        assert_eq!(types.field(id, interner.intern("missing")), None);
1278    }
1279
1280    #[test]
1281    fn a_nested_record_brings_its_own_alignment_with_it() {
1282        let mut types = Types::new();
1283        let char_ = types.int(IntKind::Char);
1284        let int = types.int(IntKind::Int);
1285        let inner = record(&mut types, RecordKind::Struct, &[member(char_)]);
1286        let laid_out = lay_out(&types, RecordKind::Struct, &[member(inner), member(int)]);
1287        assert_eq!(laid_out.layout, Layout::new(8, 4));
1288        assert_eq!(offsets(&laid_out), [0, 32]);
1289
1290        // An anonymous member is an ordinary member with no name, so the same code lays it out
1291        // and the four bytes of padding after the `char` are there either way.
1292        let anonymous = record(&mut types, RecordKind::Struct, &[member(int), member(char_)]);
1293        let laid_out = lay_out(&types, RecordKind::Struct, &[member(char_), member(anonymous)]);
1294        assert_eq!(laid_out.layout, Layout::new(12, 4));
1295        assert_eq!(offsets(&laid_out), [0, 32]);
1296    }
1297
1298    #[test]
1299    fn everything_narrower_than_an_int_promotes_to_one() {
1300        // Measured by naming the type of `+x` with `_Generic` in gcc 13.3 and clang 18. Every
1301        // one of these answers `int`, including the unsigned ones, because an `int` holds every
1302        // value a sixteen bit unsigned type has.
1303        let mut types = Types::new();
1304        let linux = linux();
1305        let int = types.int(IntKind::Int);
1306        let narrow =
1307            [IntKind::Char, IntKind::SChar, IntKind::UChar, IntKind::Short, IntKind::UShort];
1308        for kind in narrow {
1309            let ty = types.int(kind);
1310            assert_eq!(promote(&mut types, ty, &linux), int, "{}", kind.as_str());
1311        }
1312        let boolean = types.boolean();
1313        assert_eq!(promote(&mut types, boolean, &linux), int, "C23 made bool a real type");
1314
1315        // From `int` up, a type is its own promotion.
1316        for kind in [IntKind::Int, IntKind::UInt, IntKind::Long, IntKind::ULongLong] {
1317            let ty = types.int(kind);
1318            assert_eq!(promote(&mut types, ty, &linux), ty, "{}", kind.as_str());
1319        }
1320    }
1321
1322    #[test]
1323    fn a_bit_int_is_not_promoted_at_all() {
1324        // C23 6.3.1.1p2, and the point of the type. `_BitInt(8) + _BitInt(8)` stays eight bits
1325        // wide where `char + char` is an `int`, which is what makes the width mean something.
1326        let mut types = Types::new();
1327        let linux = linux();
1328        let small = types.bit_int(true, 8);
1329        assert_eq!(promote(&mut types, small, &linux), small);
1330        assert_eq!(usual_arithmetic(&mut types, small, small, &linux), Some(small));
1331    }
1332
1333    #[test]
1334    fn a_bit_field_is_promoted_by_its_width_and_not_by_its_type() {
1335        let mut types = Types::new();
1336        let linux = linux();
1337        let int = types.int(IntKind::Int);
1338        let uint = types.int(IntKind::UInt);
1339        let ullong = types.int(IntKind::ULongLong);
1340
1341        // Three bits of an unsigned field all fit in an `int`, so it is signed afterwards.
1342        assert_eq!(promote_bit_field(&mut types, uint, 3, &linux), int);
1343        // Thirty two of them do not.
1344        assert_eq!(promote_bit_field(&mut types, uint, 32, &linux), uint);
1345        // Twenty bits of a signed field, which is an `int` either way.
1346        assert_eq!(promote_bit_field(&mut types, int, 20, &linux), int);
1347        // Forty bits are forty bits of value and nothing more. The C17 wording says `unsigned
1348        // int` here, which would silently drop eight of them, and C23 says the declared type,
1349        // which would silently add twenty four. Both compilers give the width instead, so
1350        // `x.b << 32` on such a field is zero rather than a value with a bit above the fortieth.
1351        let forty = types.bit_int(false, 40);
1352        assert_eq!(promote_bit_field(&mut types, ullong, 40, &linux), forty);
1353        // A field as wide as its type is that type, since there is no precision to lose.
1354        assert_eq!(promote_bit_field(&mut types, ullong, 64, &linux), ullong);
1355    }
1356
1357    #[test]
1358    fn an_enumeration_promotes_through_what_it_is_represented_in() {
1359        let mut types = Types::new();
1360        let linux = linux();
1361        let int = types.int(IntKind::Int);
1362        let short = types.int(IntKind::Short);
1363        let uint = types.int(IntKind::UInt);
1364
1365        // `enum E : short` promotes the same way a `short` does, which is to `int`.
1366        let fixed = types.declare_enum(None);
1367        types.complete_enum(fixed, short, true);
1368        let fixed = types.enumeration(fixed);
1369        assert_eq!(promote(&mut types, fixed, &linux), int);
1370
1371        // An enumeration all of whose enumerators are non-negative is represented in
1372        // `unsigned int` by both compilers, and then it promotes to itself.
1373        let unsigned = types.declare_enum(None);
1374        types.complete_enum(unsigned, uint, false);
1375        let unsigned = types.enumeration(unsigned);
1376        assert_eq!(promote(&mut types, unsigned, &linux), uint);
1377
1378        // An enumeration nobody has decided on yet answers `int`, so that an expression using
1379        // one is still checkable while the diagnostic about it is being written.
1380        let undecided = types.declare_enum(None);
1381        let undecided = types.enumeration(undecided);
1382        assert_eq!(promote(&mut types, undecided, &linux), int);
1383    }
1384
1385    #[test]
1386    fn the_qualifiers_and_the_atomic_come_off_before_anything_else() {
1387        // By the time a value is being promoted the lvalue conversion has already happened, so
1388        // `_Atomic const int` and `int` are the same operand.
1389        let mut types = Types::new();
1390        let linux = linux();
1391        let int = types.int(IntKind::Int);
1392        let konst = types.qualified(int, Qualifiers::CONST);
1393        let atomic = types.atomic(konst);
1394        assert_eq!(promote(&mut types, atomic, &linux), int);
1395        assert_eq!(usual_arithmetic(&mut types, atomic, konst, &linux), Some(int));
1396    }
1397
1398    #[test]
1399    fn the_usual_arithmetic_conversions_between_the_standard_integer_types() {
1400        // Every row measured with `_Generic` in gcc 13.3 and clang 18 on x86-64 Linux.
1401        let mut types = Types::new();
1402        let linux = linux();
1403        let cases = [
1404            (IntKind::Int, IntKind::UInt, IntKind::UInt),
1405            (IntKind::Int, IntKind::Long, IntKind::Long),
1406            (IntKind::UInt, IntKind::Long, IntKind::Long),
1407            (IntKind::UInt, IntKind::ULong, IntKind::ULong),
1408            (IntKind::Int, IntKind::LongLong, IntKind::LongLong),
1409            (IntKind::UInt, IntKind::LongLong, IntKind::LongLong),
1410            (IntKind::ULong, IntKind::LongLong, IntKind::ULongLong),
1411            (IntKind::Char, IntKind::Char, IntKind::Int),
1412            (IntKind::UChar, IntKind::UShort, IntKind::Int),
1413        ];
1414        for (left, right, want) in cases {
1415            let left = types.int(left);
1416            let right = types.int(right);
1417            let want = types.int(want);
1418            assert_eq!(usual_arithmetic(&mut types, left, right, &linux), Some(want));
1419            assert_eq!(usual_arithmetic(&mut types, right, left, &linux), Some(want), "either way");
1420        }
1421    }
1422
1423    #[test]
1424    fn int128_is_sixteen_bytes_aligned_to_sixteen_and_outranks_long_long() {
1425        // Measured on gcc 13.3 on x86-64 Linux and clang on AArch64 Darwin, both of which
1426        // report the same size, the same alignment, and an offset of sixteen for a member
1427        // after a `char`.
1428        let mut types = Types::new();
1429        let linux = linux();
1430        let signed = types.int(IntKind::Int128);
1431        let unsigned = types.int(IntKind::UInt128);
1432        for id in [signed, unsigned] {
1433            let laid_out = layout(&types, id, &linux).expect("a complete type");
1434            assert_eq!(laid_out.size, 16);
1435            assert_eq!(laid_out.align, 16);
1436        }
1437
1438        // `__int128 + unsigned long long` is `__int128`, because it wins on rank and is wide
1439        // enough to hold every value the other side had. Both compilers agree, and it is the
1440        // one pair that says the rank is above `long long` rather than beside it.
1441        let ull = types.int(IntKind::ULongLong);
1442        assert_eq!(usual_arithmetic(&mut types, signed, ull, &linux), Some(signed));
1443        // And it is its own promotion, the way every type at or above `int` is.
1444        assert_eq!(promote(&mut types, signed, &linux), signed);
1445    }
1446
1447    #[test]
1448    fn a_bit_int_of_a_hundred_and_twenty_eight_bits_is_not_int128() {
1449        // Same width, different types. The alignment is the visible difference on x86-64,
1450        // where a `_BitInt` is aligned to its sixty four bit granule and `__int128` is not.
1451        let mut types = Types::new();
1452        let linux = linux();
1453        let int128 = types.int(IntKind::Int128);
1454        let bit_int = types.bit_int(true, 128);
1455        assert_ne!(int128, bit_int);
1456        assert!(!compatible(&types, int128, bit_int));
1457        assert_eq!(layout(&types, bit_int, &linux).expect("complete").align, 8);
1458        assert_eq!(layout(&types, int128, &linux).expect("complete").align, 16);
1459    }
1460
1461    #[test]
1462    fn the_last_arm_takes_the_unsigned_type_of_the_wider_one() {
1463        // `unsigned long + long long` is `unsigned long long` on Linux: the `long long` wins on
1464        // rank and cannot hold every value of the `unsigned long`, so neither operand's own
1465        // type is the answer. This is the arm programs are surprised by.
1466        let mut types = Types::new();
1467        let linux = linux();
1468        let ulong = types.int(IntKind::ULong);
1469        let long_long = types.int(IntKind::LongLong);
1470        let want = types.int(IntKind::ULongLong);
1471        assert_eq!(usual_arithmetic(&mut types, ulong, long_long, &linux), Some(want));
1472
1473        // The same pair on Windows, where `long` is thirty two bits, comes out as `long long`,
1474        // because there it does hold every value. A host-driven implementation gets one of
1475        // these two wrong.
1476        let windows = target("x86_64-pc-windows-msvc");
1477        assert_eq!(usual_arithmetic(&mut types, ulong, long_long, &windows), Some(long_long));
1478    }
1479
1480    #[test]
1481    fn a_bit_int_is_ranked_by_its_width_against_the_standard_types() {
1482        // Measured with clang 18 on x86-64 Linux, which is the compiler that has `_BitInt`.
1483        let mut types = Types::new();
1484        let linux = linux();
1485        let b40 = types.bit_int(true, 40);
1486        let ub40 = types.bit_int(false, 40);
1487        let b8 = types.bit_int(true, 8);
1488        let b32 = types.bit_int(true, 32);
1489        let int = types.int(IntKind::Int);
1490        let uint = types.int(IntKind::UInt);
1491        let long = types.int(IntKind::Long);
1492        let char_ = types.int(IntKind::Char);
1493
1494        // Wider than an `int`, so it outranks one.
1495        assert_eq!(usual_arithmetic(&mut types, b40, int, &linux), Some(b40));
1496        // Narrower than a `long`, so it loses to one.
1497        assert_eq!(usual_arithmetic(&mut types, b40, long, &linux), Some(long));
1498        // The same width as an `int`, and a standard type wins the tie.
1499        assert_eq!(usual_arithmetic(&mut types, b32, int, &linux), Some(int));
1500        assert_eq!(usual_arithmetic(&mut types, b32, uint, &linux), Some(uint));
1501        // The other side promotes first, so a `char` next to a narrow `_BitInt` is an `int`
1502        // and the `_BitInt` loses to it.
1503        assert_eq!(usual_arithmetic(&mut types, b8, char_, &linux), Some(int));
1504        // Unsigned and higher ranked wins outright, and unsigned and lower ranked loses to a
1505        // signed type wide enough to hold it.
1506        assert_eq!(usual_arithmetic(&mut types, ub40, int, &linux), Some(ub40));
1507        assert_eq!(usual_arithmetic(&mut types, ub40, long, &linux), Some(long));
1508        // Two bit-precise types of the same width and different signedness.
1509        assert_eq!(usual_arithmetic(&mut types, b40, ub40, &linux), Some(ub40));
1510    }
1511
1512    #[test]
1513    fn a_floating_operand_decides_the_answer_whatever_the_other_side_is() {
1514        let mut types = Types::new();
1515        let linux = linux();
1516        let float = types.float(FloatKind::Float);
1517        let double = types.float(FloatKind::Double);
1518        let long_double = types.float(FloatKind::LongDouble);
1519        let ullong = types.int(IntKind::ULongLong);
1520        let int = types.int(IntKind::Int);
1521
1522        assert_eq!(usual_arithmetic(&mut types, int, float, &linux), Some(float));
1523        assert_eq!(usual_arithmetic(&mut types, float, double, &linux), Some(double));
1524        assert_eq!(usual_arithmetic(&mut types, double, long_double, &linux), Some(long_double));
1525        // Sixty four bits of unsigned integer against a `float`, which is a `float` and loses
1526        // most of them. That is the rule rather than an oversight.
1527        assert_eq!(usual_arithmetic(&mut types, ullong, float, &linux), Some(float));
1528    }
1529
1530    #[test]
1531    fn a_mask_is_the_signed_integers_of_the_lane_width() {
1532        let mut types = Types::new();
1533        let linux = linux();
1534        let int = types.int(IntKind::Int);
1535        let float = types.float(FloatKind::Float);
1536        let short = types.int(IntKind::Short);
1537
1538        // A signed lane is already its own mask, so the answer is the vector it was given.
1539        let four_ints = types.vector(int, 4);
1540        assert_eq!(mask_of(&mut types, four_ints, &linux), Some(four_ints));
1541
1542        // An unsigned lane answers as the signed type of the same width, which is what GCC
1543        // gives a comparison of two `unsigned int` vectors.
1544        let uint = types.int(IntKind::UInt);
1545        let four_uints = types.vector(uint, 4);
1546        assert_eq!(mask_of(&mut types, four_uints, &linux), Some(four_ints));
1547
1548        // A float lane answers as an integer of the same width, since the mask is bits and not
1549        // a number and there is no float that is all ones.
1550        let four_floats = types.vector(float, 4);
1551        assert_eq!(mask_of(&mut types, four_floats, &linux), Some(four_ints));
1552
1553        // The width is the lane's own and not a word, so a `short` lane keeps its two bytes.
1554        let two_shorts = types.vector(short, 2);
1555        assert_eq!(mask_of(&mut types, two_shorts, &linux), Some(two_shorts));
1556
1557        // Not a vector, so there is no mask to give.
1558        assert_eq!(mask_of(&mut types, int, &linux), None);
1559    }
1560
1561    #[test]
1562    fn two_vectors_convert_between_each_other_when_the_bytes_line_up() {
1563        let mut types = Types::new();
1564        let linux = linux();
1565        let int = types.int(IntKind::Int);
1566        let uint = types.int(IntKind::UInt);
1567        let float = types.float(FloatKind::Float);
1568        let short = types.int(IntKind::Short);
1569
1570        let four_ints = types.vector(int, 4);
1571        let four_uints = types.vector(uint, 4);
1572        let four_floats = types.vector(float, 4);
1573        let eight_shorts = types.vector(short, 8);
1574        let two_ints = types.vector(int, 2);
1575
1576        // The case the whole thing exists for: a mask assigned to the unsigned vector it came
1577        // from, which GNU C converts and the standard rules would refuse.
1578        assert!(vectors_convertible(&types, four_uints, four_ints, &linux));
1579        // Both ways round, since assignment happens in both directions.
1580        assert!(vectors_convertible(&types, four_ints, four_uints, &linux));
1581        // The same sixteen bytes cut into eight lanes rather than four, which GCC also allows.
1582        assert!(vectors_convertible(&types, four_ints, eight_shorts, &linux));
1583        // Two floats of the same width, which is the other half of the rule.
1584        assert!(vectors_convertible(&types, four_floats, four_floats, &linux));
1585
1586        // An integer lane against a float lane, which GCC refuses even at the same size,
1587        // because reading one as the other is a cast and not a conversion.
1588        assert!(!vectors_convertible(&types, four_ints, four_floats, &linux));
1589        // Different sizes, so there is nothing to reinterpret.
1590        assert!(!vectors_convertible(&types, four_ints, two_ints, &linux));
1591        // A scalar is not a vector, whichever side it is on.
1592        assert!(!vectors_convertible(&types, four_ints, int, &linux));
1593        assert!(!vectors_convertible(&types, int, four_ints, &linux));
1594    }
1595
1596    /// Insists that `a + b` and `b + a` are both `expected` on this target.
1597    ///
1598    /// Both ways round, because the operands of `+` are not ordered and an implementation that
1599    /// keeps the left one when it cannot decide would pass half of these and be wrong.
1600    fn combines(target: &TargetInfo, a: FloatKind, b: FloatKind, expected: FloatKind) {
1601        let mut types = Types::new();
1602        let left = types.float(a);
1603        let right = types.float(b);
1604        let want = types.float(expected);
1605        assert_eq!(usual_arithmetic(&mut types, left, right, target), Some(want), "{a:?} + {b:?}");
1606        assert_eq!(usual_arithmetic(&mut types, right, left, target), Some(want), "{b:?} + {a:?}");
1607    }
1608
1609    #[test]
1610    fn two_floating_types_of_the_same_format_are_still_two_types_and_one_of_them_wins() {
1611        // Every line here was read off gcc 16 with `_Generic` rather than off the standard, on
1612        // x86-64 Linux, where `long double` and `_Float64x` are both the x87 format and the
1613        // standard type is the one that comes out.
1614        let x86 = linux();
1615        combines(&x86, FloatKind::Double, FloatKind::Float64, FloatKind::Float64);
1616        combines(&x86, FloatKind::Float, FloatKind::Float32, FloatKind::Float32);
1617        combines(&x86, FloatKind::Double, FloatKind::Float32x, FloatKind::Double);
1618        combines(&x86, FloatKind::LongDouble, FloatKind::Float64x, FloatKind::LongDouble);
1619        combines(&x86, FloatKind::Float128, FloatKind::LongDouble, FloatKind::Float128);
1620        combines(&x86, FloatKind::Float64x, FloatKind::Float128, FloatKind::Float128);
1621        combines(&x86, FloatKind::Double, FloatKind::LongDouble, FloatKind::LongDouble);
1622        combines(&x86, FloatKind::Float32x, FloatKind::Float64, FloatKind::Float64);
1623        combines(&x86, FloatKind::Float64x, FloatKind::Float64, FloatKind::Float64x);
1624        combines(&x86, FloatKind::LongDouble, FloatKind::Float64, FloatKind::LongDouble);
1625    }
1626
1627    #[test]
1628    fn the_widest_floating_type_is_a_question_about_the_target_and_not_about_the_names() {
1629        // The same reading against gcc 16 on aarch64-apple-darwin, where `long double` is a
1630        // `double` and loses to the `_Float64x` it beats on x86-64. The name says nothing about
1631        // which of the two is wider, which is why the ordering is worked out from the formats.
1632        let mac = target("aarch64-apple-darwin");
1633        combines(&mac, FloatKind::LongDouble, FloatKind::Float64x, FloatKind::Float64x);
1634        combines(&mac, FloatKind::Double, FloatKind::LongDouble, FloatKind::LongDouble);
1635        combines(&mac, FloatKind::Float128, FloatKind::LongDouble, FloatKind::Float128);
1636        combines(&mac, FloatKind::Float64x, FloatKind::Float64, FloatKind::Float64x);
1637        combines(&mac, FloatKind::Float32x, FloatKind::Float32, FloatKind::Float32x);
1638        combines(&mac, FloatKind::Float32x, FloatKind::Float64, FloatKind::Float64);
1639        combines(&mac, FloatKind::Double, FloatKind::Float64, FloatKind::Float64);
1640        // `_Float16` is the narrowest type there is and does not promote on the way in, so it
1641        // survives an operation only when nothing wider is there.
1642        combines(&mac, FloatKind::Float16, FloatKind::Float, FloatKind::Float);
1643        combines(&mac, FloatKind::Float16, FloatKind::Double, FloatKind::Double);
1644        combines(&mac, FloatKind::Float16, FloatKind::Float16, FloatKind::Float16);
1645    }
1646
1647    #[test]
1648    fn a_complex_operand_makes_the_answer_complex_after_the_real_types_have_combined() {
1649        let mut types = Types::new();
1650        let linux = linux();
1651        let cfloat = types.complex_float(FloatKind::Float);
1652        let cdouble = types.complex_float(FloatKind::Double);
1653        let cldouble = types.complex_float(FloatKind::LongDouble);
1654        let double = types.float(FloatKind::Double);
1655        let long_double = types.float(FloatKind::LongDouble);
1656        let float = types.float(FloatKind::Float);
1657        let int = types.int(IntKind::Int);
1658
1659        assert_eq!(usual_arithmetic(&mut types, cfloat, double, &linux), Some(cdouble));
1660        assert_eq!(usual_arithmetic(&mut types, cfloat, int, &linux), Some(cfloat));
1661        assert_eq!(usual_arithmetic(&mut types, cdouble, long_double, &linux), Some(cldouble));
1662        assert_eq!(usual_arithmetic(&mut types, cfloat, float, &linux), Some(cfloat));
1663    }
1664
1665    #[test]
1666    fn an_operand_that_is_not_arithmetic_has_no_common_type() {
1667        // The caller is the one holding the span, so this says no rather than guessing.
1668        let mut types = Types::new();
1669        let linux = linux();
1670        let int = types.int(IntKind::Int);
1671        let pointer = types.pointer(int);
1672        assert_eq!(usual_arithmetic(&mut types, pointer, int, &linux), None);
1673        assert_eq!(usual_arithmetic(&mut types, pointer, pointer, &linux), None);
1674        let void = types.void();
1675        assert_eq!(usual_arithmetic(&mut types, void, int, &linux), None);
1676        // And a type that is not arithmetic is still its own promotion, so a caller may promote
1677        // first and ask questions afterwards.
1678        assert_eq!(promote(&mut types, pointer, &linux), pointer);
1679    }
1680
1681    #[test]
1682    fn the_conversions_read_through_sugar() {
1683        let mut interner = Interner::new();
1684        let mut types = Types::new();
1685        let linux = linux();
1686        let char_ = types.int(IntKind::Char);
1687        let name = types.typedef(interner.intern("byte"), char_);
1688        let int = types.int(IntKind::Int);
1689        assert_eq!(promote(&mut types, name, &linux), int);
1690    }
1691
1692    /// A prototype returning `void`.
1693    fn prototype(types: &mut Types, params: Vec<TypeId>, variadic: bool) -> TypeId {
1694        let ret = types.void();
1695        types.function(FunctionType { ret, params, variadic, prototyped: true })
1696    }
1697
1698    /// `void f()` as it means before C23: a declaration that says nothing about the parameters.
1699    fn old_style(types: &mut Types) -> TypeId {
1700        let ret = types.void();
1701        types.function(FunctionType { ret, params: Vec::new(), variadic: false, prototyped: false })
1702    }
1703
1704    /// A complete record with the given tag and members.
1705    fn tagged(types: &mut Types, tag: Symbol, fields: &[FieldDecl]) -> RecordId {
1706        let id = types.declare_record(RecordKind::Struct, Some(tag));
1707        let laid_out = lay_out(types, RecordKind::Struct, fields);
1708        types.complete_record(id, laid_out);
1709        id
1710    }
1711
1712    #[test]
1713    fn a_type_is_compatible_with_itself_however_it_was_written() {
1714        let mut interner = Interner::new();
1715        let mut types = Types::new();
1716        let int = types.int(IntKind::Int);
1717        let name = types.typedef(interner.intern("int32_t"), int);
1718        assert!(compatible(&types, name, int), "the sugar is the same type underneath");
1719        assert_eq!(composite(&mut types, name, int), Some(name), "and it keeps its name");
1720
1721        // The qualifiers have to match exactly, which is what keeps `const int *` and `int *`
1722        // apart as parameter types.
1723        let konst = types.qualified(int, Qualifiers::CONST);
1724        assert!(!compatible(&types, konst, int));
1725        let konst_pointer = types.pointer(konst);
1726        let pointer = types.pointer(int);
1727        assert!(!compatible(&types, konst_pointer, pointer));
1728        assert_eq!(composite(&mut types, konst_pointer, pointer), None);
1729
1730        // And a different type is a different type. `char` is not `signed char` even on a target
1731        // where the two have the same range, which is why they are separate kinds here.
1732        let char_ = types.int(IntKind::Char);
1733        let schar = types.int(IntKind::SChar);
1734        assert!(!compatible(&types, char_, schar));
1735        // `_Atomic int` is not `int` either, since it is a type and not a qualifier.
1736        let atomic = types.atomic(int);
1737        assert!(!compatible(&types, atomic, int));
1738    }
1739
1740    #[test]
1741    fn an_enumeration_is_compatible_with_the_type_it_is_represented_in() {
1742        // gcc 13.3 and clang 18 both represent `enum E { A, B }` in `unsigned int`, and both
1743        // accept a redeclaration that writes the representation instead of the tag.
1744        let mut types = Types::new();
1745        let uint = types.int(IntKind::UInt);
1746        let int = types.int(IntKind::Int);
1747        let id = types.declare_enum(None);
1748        types.complete_enum(id, uint, false);
1749        let e = types.enumeration(id);
1750        assert!(compatible(&types, e, uint));
1751        assert!(compatible(&types, uint, e), "and the relation is symmetric");
1752        assert!(!compatible(&types, e, int));
1753
1754        // Two enumeration declarations are two types. Each is compatible with what it is
1755        // represented in, and that does not make them compatible with each other.
1756        let other = types.declare_enum(None);
1757        types.complete_enum(other, uint, false);
1758        let other = types.enumeration(other);
1759        assert!(!compatible(&types, e, other));
1760
1761        // One nobody has decided on yet is compatible with nothing but itself, because the
1762        // answer is not known rather than no.
1763        let undecided = types.declare_enum(None);
1764        let undecided = types.enumeration(undecided);
1765        assert!(!compatible(&types, undecided, uint));
1766        assert!(compatible(&types, undecided, undecided));
1767    }
1768
1769    #[test]
1770    fn an_array_without_a_size_is_compatible_with_one_that_has_it() {
1771        // `extern int a[]; int a[4];` is a complete array of four afterwards, which gcc reports
1772        // as a `sizeof` of sixteen. A compiler that keeps the first type has lost the size.
1773        let mut types = Types::new();
1774        let int = types.int(IntKind::Int);
1775        let unknown = types.array(int, ArrayLen::Unknown);
1776        let four = types.array(int, ArrayLen::Fixed(4));
1777        let five = types.array(int, ArrayLen::Fixed(5));
1778        assert!(compatible(&types, unknown, four));
1779        assert!(!compatible(&types, four, five));
1780        assert_eq!(composite(&mut types, unknown, four), Some(four));
1781        assert_eq!(composite(&mut types, four, unknown), Some(four), "either way round");
1782        assert_eq!(composite(&mut types, four, five), None);
1783
1784        // A variable length array is compatible with both, because its size is not something a
1785        // declaration can be checked against.
1786        let vla = types.array(int, ArrayLen::Variable(VlaId(0)));
1787        assert!(compatible(&types, vla, four));
1788        assert_eq!(composite(&mut types, vla, four), Some(four));
1789
1790        // The element types have to be compatible too, and the composite reaches into them.
1791        let long = types.int(IntKind::Long);
1792        let longs = types.array(long, ArrayLen::Fixed(4));
1793        assert!(!compatible(&types, four, longs));
1794    }
1795
1796    #[test]
1797    fn a_parameter_declared_as_an_array_is_a_pointer() {
1798        // `int fn(int p[3])` and `int fn(int *p)` are one declaration and one definition, which
1799        // both compilers accept. The adjustment is part of forming the parameter type, so two
1800        // functions written either way are not merely compatible but identical.
1801        let mut types = Types::new();
1802        let int = types.int(IntKind::Int);
1803        let three = types.array(int, ArrayLen::Fixed(3));
1804        let pointer = types.pointer(int);
1805        assert_eq!(adjust_parameter(&mut types, three), pointer);
1806
1807        // A function parameter becomes a pointer to the function the same way.
1808        let function = prototype(&mut types, vec![int], false);
1809        let function_pointer = types.pointer(function);
1810        assert_eq!(adjust_parameter(&mut types, function), function_pointer);
1811
1812        // And the qualifiers on the outermost node go, so `void f(const int)` and `void f(int)`
1813        // declare the same function. The pointee of a `const int *` keeps its own.
1814        let konst = types.qualified(int, Qualifiers::CONST);
1815        assert_eq!(adjust_parameter(&mut types, konst), int);
1816        let to_konst = types.pointer(konst);
1817        assert_eq!(adjust_parameter(&mut types, to_konst), to_konst);
1818    }
1819
1820    #[test]
1821    fn an_old_style_declaration_is_compatible_with_the_prototypes_a_call_could_not_tell_from_it() {
1822        // Measured with gcc 13.3 in C17 mode, which is the compiler that still has the old
1823        // meaning of `()`. It names the rule in its own diagnostic: an argument type that has a
1824        // default promotion cannot match an empty parameter name list declaration.
1825        let mut types = Types::new();
1826        let old = old_style(&mut types);
1827        let int = types.int(IntKind::Int);
1828        let long = types.int(IntKind::Long);
1829        let char_ = types.int(IntKind::Char);
1830        let float = types.float(FloatKind::Float);
1831        let double = types.float(FloatKind::Double);
1832
1833        let takes_int = prototype(&mut types, vec![int], false);
1834        assert!(compatible(&types, old, takes_int));
1835        assert!(compatible(&types, takes_int, old), "and the relation is symmetric");
1836        // The composite is the prototype, so the calls written before it can still be checked.
1837        assert_eq!(composite(&mut types, old, takes_int), Some(takes_int));
1838
1839        let pointer = types.pointer(int);
1840        for params in [vec![long], vec![double], vec![pointer], vec![int, long]] {
1841            let ty = prototype(&mut types, params, false);
1842            assert!(compatible(&types, old, ty), "nothing here is touched by a promotion");
1843        }
1844
1845        // A `char` promotes to `int` and a `float` to `double`, so a call through the old style
1846        // declaration would have passed something else and the two conflict.
1847        for params in [vec![char_], vec![float], vec![int, char_]] {
1848            let ty = prototype(&mut types, params, false);
1849            assert!(!compatible(&types, old, ty));
1850            assert_eq!(composite(&mut types, old, ty), None);
1851        }
1852
1853        // An ellipsis conflicts too, which gcc also says in as many words.
1854        let variadic = prototype(&mut types, vec![int], true);
1855        assert!(!compatible(&types, old, variadic));
1856
1857        // An enumeration parameter comes through when what it is represented in does.
1858        let uint = types.int(IntKind::UInt);
1859        let id = types.declare_enum(None);
1860        types.complete_enum(id, uint, false);
1861        let e = types.enumeration(id);
1862        let takes_enum = prototype(&mut types, vec![e], false);
1863        assert!(compatible(&types, old, takes_enum));
1864
1865        // Two old style declarations agree about nothing and so cannot disagree.
1866        assert!(compatible(&types, old, old));
1867
1868        // The return type still has to match, which is the one part `()` does say.
1869        let returns_int = types.function(FunctionType {
1870            ret: int,
1871            params: Vec::new(),
1872            variadic: false,
1873            prototyped: false,
1874        });
1875        assert!(!compatible(&types, returns_int, takes_int));
1876    }
1877
1878    #[test]
1879    fn from_c23_an_empty_parameter_list_is_a_prototype_and_conflicts_where_it_used_to_merge() {
1880        // The dialect decides what `()` means and the parser records the decision, so the same
1881        // pair of declarations is a redeclaration in C17 and a conflict in C23. Both compilers
1882        // report exactly that.
1883        let mut types = Types::new();
1884        let int = types.int(IntKind::Int);
1885        let takes_int = prototype(&mut types, vec![int], false);
1886        let takes_nothing = prototype(&mut types, Vec::new(), false);
1887        let old = old_style(&mut types);
1888        assert!(!compatible(&types, takes_nothing, takes_int));
1889        assert!(compatible(&types, old, takes_int), "the C17 reading of the same source");
1890    }
1891
1892    #[test]
1893    fn two_prototypes_have_to_agree_about_everything() {
1894        let mut types = Types::new();
1895        let int = types.int(IntKind::Int);
1896        let long = types.int(IntKind::Long);
1897        let base = prototype(&mut types, vec![int, int], false);
1898        for other in [vec![int], vec![int, long], vec![int, int, int], Vec::new()] {
1899            let other = prototype(&mut types, other, false);
1900            assert!(!compatible(&types, base, other));
1901        }
1902        let variadic = prototype(&mut types, vec![int, int], true);
1903        assert!(!compatible(&types, base, variadic), "`...` is part of the type");
1904
1905        // The parameters are compared with the same rules as anything else, so an array size
1906        // inside a parameter's type is compared and an unknown one is not.
1907        let four = types.array(int, ArrayLen::Fixed(4));
1908        let unknown = types.array(int, ArrayLen::Unknown);
1909        let to_four = types.pointer(four);
1910        let to_unknown = types.pointer(unknown);
1911        let a = prototype(&mut types, vec![to_four], false);
1912        let b = prototype(&mut types, vec![to_unknown], false);
1913        assert!(compatible(&types, a, b));
1914        // And the composite takes the size, which is the whole reason it exists.
1915        assert_eq!(composite(&mut types, a, b), Some(a));
1916    }
1917
1918    #[test]
1919    fn a_pointer_composite_reaches_through_to_what_is_pointed_at() {
1920        let mut types = Types::new();
1921        let int = types.int(IntKind::Int);
1922        let four = types.array(int, ArrayLen::Fixed(4));
1923        let unknown = types.array(int, ArrayLen::Unknown);
1924        let to_four = types.pointer(four);
1925        let to_unknown = types.pointer(unknown);
1926        assert_eq!(composite(&mut types, to_unknown, to_four), Some(to_four));
1927
1928        // The pointer's own qualifiers survive, since a compatible pair has the same ones.
1929        let konst_to_unknown = types.qualified(to_unknown, Qualifiers::CONST);
1930        let konst_to_four = types.qualified(to_four, Qualifiers::CONST);
1931        assert_eq!(composite(&mut types, konst_to_unknown, konst_to_four), Some(konst_to_four));
1932    }
1933
1934    #[test]
1935    fn two_record_declarations_with_the_same_tag_and_the_same_members_are_compatible() {
1936        // C23 6.2.7p1, which is what lets one header be included twice. clang 18 implements it
1937        // and gcc 13.3 still rejects the redefinition, so this is a divergence rather than a
1938        // reading; in the older dialects the redefinition never gets as far as being compared.
1939        let mut interner = Interner::new();
1940        let mut types = Types::new();
1941        let tag = interner.intern("point");
1942        let x = interner.intern("x");
1943        let y = interner.intern("y");
1944        let int = types.int(IntKind::Int);
1945        let members = [FieldDecl::new(Some(x), int), FieldDecl::new(Some(y), int)];
1946
1947        let first = tagged(&mut types, tag, &members);
1948        let second = tagged(&mut types, tag, &members);
1949        let first = types.record(first);
1950        let second = types.record(second);
1951        assert_ne!(first, second, "still two declarations and two types");
1952        assert!(compatible(&types, first, second));
1953
1954        // A different member name, a different member type, a different count, a different tag
1955        // and a different keyword are each enough to make them different types.
1956        let z = interner.intern("z");
1957        let long = types.int(IntKind::Long);
1958        let renamed = [FieldDecl::new(Some(x), int), FieldDecl::new(Some(z), int)];
1959        let retyped = [FieldDecl::new(Some(x), int), FieldDecl::new(Some(y), long)];
1960        for other in [&renamed[..], &retyped[..], &members[..1]] {
1961            let other = tagged(&mut types, tag, other);
1962            let other = types.record(other);
1963            assert!(!compatible(&types, first, other));
1964        }
1965        let elsewhere = tagged(&mut types, interner.intern("pair"), &members);
1966        let elsewhere = types.record(elsewhere);
1967        assert!(!compatible(&types, first, elsewhere));
1968
1969        // An anonymous record is compatible with nothing but itself: there is no name by which
1970        // a second declaration could be claiming to be the same type.
1971        let anonymous = record(&mut types, RecordKind::Struct, &members);
1972        let also_anonymous = record(&mut types, RecordKind::Struct, &members);
1973        assert!(!compatible(&types, anonymous, also_anonymous));
1974
1975        // Nor is an incomplete declaration, which has no members to compare.
1976        let incomplete = types.declare_record(RecordKind::Struct, Some(tag));
1977        let incomplete = types.record(incomplete);
1978        assert!(!compatible(&types, first, incomplete));
1979        assert!(compatible(&types, incomplete, incomplete));
1980    }
1981
1982    #[test]
1983    fn a_self_referential_record_is_compared_without_going_round_forever() {
1984        // `struct node { int value; struct node *next; }` declared twice. Comparing the two
1985        // reaches the same pair again through the pointer, and the second time it is an
1986        // assumption rather than a question.
1987        let mut interner = Interner::new();
1988        let mut types = Types::new();
1989        let tag = interner.intern("node");
1990        let value = interner.intern("value");
1991        let next = interner.intern("next");
1992        let int = types.int(IntKind::Int);
1993
1994        let node = |types: &mut Types| {
1995            let id = types.declare_record(RecordKind::Struct, Some(tag));
1996            let ty = types.record(id);
1997            let pointer = types.pointer(ty);
1998            let members = [FieldDecl::new(Some(value), int), FieldDecl::new(Some(next), pointer)];
1999            let laid_out = lay_out(types, RecordKind::Struct, &members);
2000            types.complete_record(id, laid_out);
2001            ty
2002        };
2003        let first = node(&mut types);
2004        let second = node(&mut types);
2005        assert_ne!(first, second);
2006        assert!(compatible(&types, first, second));
2007
2008        // The guard is an assumption and not an answer, so a difference below the cycle is still
2009        // found: the same structure with the two members the other way round is a different one.
2010        let id = types.declare_record(RecordKind::Struct, Some(tag));
2011        let ty = types.record(id);
2012        let pointer = types.pointer(ty);
2013        let members = [FieldDecl::new(Some(next), pointer), FieldDecl::new(Some(value), int)];
2014        let laid_out = lay_out(&types, RecordKind::Struct, &members);
2015        types.complete_record(id, laid_out);
2016        assert!(!compatible(&types, first, ty));
2017    }
2018
2019    #[test]
2020    fn layout_reads_through_sugar() {
2021        let mut interner = Interner::new();
2022        let mut types = Types::new();
2023        let long = types.int(IntKind::Long);
2024        let name = types.typedef(interner.intern("word"), long);
2025        let array = types.array(name, ArrayLen::Fixed(4));
2026        assert_eq!(layout(&types, array, &linux()).unwrap(), Layout::new(32, 8));
2027    }
2028
2029    /// A recipe worked out, with `sizes` standing for how large each member turned out to be.
2030    ///
2031    /// The lowering does this with instructions and this does it with numbers, which is what
2032    /// makes a recipe testable here: the tree is the whole answer, and what a member is as long
2033    /// as is the only thing either side has to be told.
2034    fn work_out(recipe: &Extent, sizes: &[u64]) -> u64 {
2035        match recipe {
2036            Extent::Bytes(count) => *count,
2037            Extent::Member(index) => sizes[*index as usize],
2038            Extent::Sum(parts) => parts.iter().map(|part| work_out(part, sizes)).sum(),
2039            Extent::RoundUp(inner, to) => work_out(inner, sizes).next_multiple_of(*to),
2040            Extent::Max(parts) => parts.iter().map(|part| work_out(part, sizes)).max().unwrap_or(0),
2041        }
2042    }
2043
2044    /// An array of `int` whose length the program computes.
2045    fn measured(types: &mut Types, which: u32) -> TypeId {
2046        let int = types.int(IntKind::Int);
2047        types.array(int, ArrayLen::Variable(VlaId(which)))
2048    }
2049
2050    #[test]
2051    fn a_member_of_no_fixed_size_leaves_the_size_and_what_follows_it_to_the_program() {
2052        let mut types = Types::new();
2053        let int = types.int(IntKind::Int);
2054        let rows = measured(&mut types, 0);
2055        let laid_out = lay_out(&types, RecordKind::Struct, &[member(rows), member(int)]);
2056
2057        // Nothing is known here but the alignment, which never varies: it is decided by the
2058        // members rather than by where they land.
2059        assert_eq!(laid_out.layout, Layout::new(0, 4));
2060        let variable = laid_out.variable.expect("a record with a member of no fixed size");
2061        // The member in front of the variable one sits where its number says, and the one after
2062        // it does not. There is no rounding in between, because an array of `int` ends on a four
2063        // byte boundary however long it is.
2064        assert_eq!(variable.offsets[0], None);
2065        let after = variable.offsets[1].as_ref().expect("an offset the program works out");
2066        for count in 0..6u64 {
2067            let sizes = [4 * count, 4];
2068            assert_eq!(work_out(after, &sizes), 4 * count);
2069            assert_eq!(work_out(&variable.size, &sizes), 4 * count + 4);
2070        }
2071        assert_eq!(laid_out.fields[1].align, 4);
2072    }
2073
2074    #[test]
2075    fn a_member_after_one_of_no_fixed_size_is_rounded_up_where_its_alignment_asks_for_it() {
2076        let mut types = Types::new();
2077        let char_ty = types.int(IntKind::Char);
2078        let rows = measured(&mut types, 0);
2079        let double = types.float(FloatKind::Double);
2080        let fields = [member(char_ty), member(rows), member(double)];
2081        let laid_out = lay_out(&types, RecordKind::Struct, &fields);
2082
2083        assert_eq!(laid_out.layout, Layout::new(0, 8));
2084        assert_eq!(offsets(&laid_out)[..2], [0, 32]);
2085        let variable = laid_out.variable.expect("a record with a member of no fixed size");
2086        assert_eq!(variable.offsets[..2], [None, None]);
2087        let after = variable.offsets[2].as_ref().expect("an offset the program works out");
2088        for count in 0..6u64 {
2089            let sizes = [1, 4 * count, 8];
2090            let at = (4 + 4 * count).next_multiple_of(8);
2091            assert_eq!(work_out(after, &sizes), at);
2092            assert_eq!(work_out(&variable.size, &sizes), at + 8);
2093        }
2094    }
2095
2096    #[test]
2097    fn a_union_with_a_member_of_no_fixed_size_is_as_long_as_the_longest_of_them() {
2098        let mut types = Types::new();
2099        let rows = measured(&mut types, 0);
2100        let double = types.float(FloatKind::Double);
2101        let laid_out = lay_out(&types, RecordKind::Union, &[member(rows), member(double)]);
2102
2103        assert_eq!(laid_out.layout, Layout::new(0, 8));
2104        let variable = laid_out.variable.expect("a union with a member of no fixed size");
2105        // Every member of a union starts where the union does, so none of them has an offset the
2106        // program has to work out.
2107        assert!(variable.offsets.iter().all(Option::is_none));
2108        for count in 0..6u64 {
2109            let sizes = [4 * count, 8];
2110            let want = (4 * count).max(8).next_multiple_of(8);
2111            assert_eq!(work_out(&variable.size, &sizes), want);
2112        }
2113    }
2114
2115    #[test]
2116    fn packed_takes_the_rounding_out_of_a_record_the_program_measures() {
2117        let mut types = Types::new();
2118        let char_ty = types.int(IntKind::Char);
2119        let int = types.int(IntKind::Int);
2120        let rows = measured(&mut types, 0);
2121        let fields = [member(char_ty), member(rows), member(int)];
2122        let options = RecordOptions { packed: true, ..RecordOptions::default() };
2123        let laid_out = layout_record(&types, RecordKind::Struct, &fields, &options, &linux())
2124            .expect("a packed record with a member of no fixed size");
2125
2126        assert_eq!(laid_out.layout, Layout::new(0, 1));
2127        assert_eq!(laid_out.fields[2].align, 1);
2128        let variable = laid_out.variable.expect("a record with a member of no fixed size");
2129        let after = variable.offsets[2].as_ref().expect("an offset the program works out");
2130        for count in 0..6u64 {
2131            let sizes = [1, 4 * count, 4];
2132            assert_eq!(work_out(after, &sizes), 1 + 4 * count);
2133            assert_eq!(work_out(&variable.size, &sizes), 1 + 4 * count + 4);
2134        }
2135    }
2136
2137    #[test]
2138    fn bit_fields_after_a_member_of_no_fixed_size_are_placed_one_after_another() {
2139        let mut interner = Interner::new();
2140        let mut types = Types::new();
2141        let int = types.int(IntKind::Int);
2142        let char_ty = types.int(IntKind::Char);
2143        let rows = measured(&mut types, 0);
2144        let fields = [
2145            member(rows),
2146            bits(&mut interner, "b", int, 3),
2147            bits(&mut interner, "c", int, 30),
2148            member(char_ty),
2149        ];
2150        let laid_out = lay_out(&types, RecordKind::Struct, &fields);
2151
2152        // `c` would straddle its `int` if the offset were a number, and gcc 16 puts it at bit
2153        // three all the same, because it only asks that question of an offset it knows. So the
2154        // `char` is five bytes past the array and the record is `4 * n + 8` long.
2155        assert_eq!((laid_out.fields[2].offset, laid_out.fields[2].bit), (0, 3));
2156        let variable = laid_out.variable.expect("a record with a member of no fixed size");
2157        let after = variable.offsets[3].as_ref().expect("an offset the program works out");
2158        for count in 0..6u64 {
2159            let sizes = [4 * count, 4, 4, 1];
2160            assert_eq!(work_out(after, &sizes), 4 * count + 5);
2161            assert_eq!(work_out(&variable.size, &sizes), 4 * count + 8);
2162        }
2163    }
2164
2165    #[test]
2166    fn a_zero_width_bit_field_that_needs_more_alignment_than_is_known_is_turned_down() {
2167        let mut types = Types::new();
2168        let int = types.int(IntKind::Int);
2169        let char_ty = types.int(IntKind::Char);
2170        let letters = types.array(char_ty, ArrayLen::Variable(VlaId(0)));
2171        let fields = [member(letters), unnamed_bits(int, 0)];
2172        let options = RecordOptions::default();
2173        let failed = layout_record(&types, RecordKind::Struct, &fields, &options, &linux());
2174
2175        // A `char` array may end on any byte, so which four byte boundary `int : 0` rounds to is a
2176        // question about an address the program has not worked out yet. The layout says so
2177        // rather than putting the member somewhere plausible.
2178        assert_eq!(failed, Err(RecordError::VariableBitField { index: 1 }));
2179    }
2180}