Skip to main content

cinrs_core/
ast.rs

1//! The C99 abstract syntax tree.
2//!
3//! Three design points matter for the milestones that follow:
4//!
5//! * **Every node carries a [`SourceRange`]**, so a diagnostic raised by sema
6//!   (M0b) or a token emitted by codegen can be attributed to the exact piece
7//!   of C it came from.
8//!
9//! * **Declarators are resolved into a type tree while parsing.** The parser
10//!   never hands out a raw declarator chain; `int (*fp[3])(void)` arrives as
11//!   `array of 3 pointer to function(void) returning int`. Sema therefore only
12//!   ever has to walk [`Type`], which is also the shape codegen needs.
13//!
14//! * **The body of a tag specifier is stored once.** Resolving declarators
15//!   eagerly means one specifier is named by several types — `struct S { … } a,
16//!   b;` is the declaration's specifiers plus the type of each declarator — so
17//!   the member list lives in [`TranslationUnit::records`] and the types carry
18//!   a [`RecordSpecId`]. Copying it instead would double the tree at every
19//!   level of a nested `struct`.
20
21use crate::capture::SourceRange;
22use crate::lex::{CharLit, FloatLit, IntLit, StrLit};
23
24/// A value paired with the source range it came from.
25#[derive(Clone, Debug, PartialEq)]
26pub struct Spanned<T> {
27    /// The value.
28    pub node: T,
29    /// Where it was written.
30    pub range: SourceRange,
31}
32
33impl<T> Spanned<T> {
34    /// Pairs `node` with `range`.
35    pub fn new(node: T, range: SourceRange) -> Self {
36        Self { node, range }
37    }
38}
39
40/// An identifier occurrence.
41#[derive(Clone, Debug, PartialEq)]
42pub struct Ident {
43    /// The spelling.
44    pub name: String,
45    /// Where it was written.
46    pub range: SourceRange,
47}
48
49// ---------------------------------------------------------------------------
50// types
51// ---------------------------------------------------------------------------
52
53/// `const` / `volatile` / `restrict`.
54#[derive(Clone, Copy, Debug, Default, PartialEq, Eq)]
55pub struct TypeQualifiers {
56    /// `const`
57    pub is_const: bool,
58    /// `volatile`
59    pub is_volatile: bool,
60    /// `restrict`
61    pub is_restrict: bool,
62    /// `_Atomic`, written without a parenthesised type name — C11 6.7.3 makes
63    /// it a qualifier there and a type *specifier* in `_Atomic(T)`.
64    ///
65    /// Unlike the other three it changes the type: `_Atomic int` resolves to
66    /// [`crate::ir::Ty::Atomic`], which is a different type from `int` and has
67    /// its own alignment. That is why it is not part of [`TypeQualifiers::any`],
68    /// which asks about the qualifiers a type *name* carries beside its type.
69    pub is_atomic: bool,
70}
71
72impl TypeQualifiers {
73    /// No qualifiers at all.
74    pub const NONE: Self = Self {
75        is_const: false,
76        is_volatile: false,
77        is_restrict: false,
78        is_atomic: false,
79    };
80
81    /// Whether any of the three qualifiers that leave the type alone is set.
82    pub fn any(self) -> bool {
83        self.is_const || self.is_volatile || self.is_restrict
84    }
85
86    /// The union of two qualifier sets.
87    pub fn merge(self, other: Self) -> Self {
88        Self {
89            is_const: self.is_const || other.is_const,
90            is_volatile: self.is_volatile || other.is_volatile,
91            is_restrict: self.is_restrict || other.is_restrict,
92            is_atomic: self.is_atomic || other.is_atomic,
93        }
94    }
95}
96
97/// Signedness of an integer type.
98#[derive(Clone, Copy, Debug, PartialEq, Eq)]
99pub enum Sign {
100    /// `signed` (explicitly or by default).
101    Signed,
102    /// `unsigned`.
103    Unsigned,
104}
105
106/// Rank of a standard integer type.
107#[derive(Clone, Copy, Debug, PartialEq, Eq)]
108pub enum IntSize {
109    /// `short`
110    Short,
111    /// `int`
112    Int,
113    /// `long`
114    Long,
115    /// `long long`
116    LongLong,
117    /// GNU's `__int128`.
118    Int128,
119}
120
121/// Rank of a standard floating type.
122#[derive(Clone, Copy, Debug, PartialEq, Eq)]
123pub enum FloatSize {
124    /// `float`
125    Float,
126    /// `double`
127    Double,
128    /// `long double`
129    LongDouble,
130    /// TS 18661-3's `_Float32`, which is `float`.
131    Float32,
132    /// `_Float64`, which is `double`.
133    Float64,
134    /// `_Float32x`, which is `double`.
135    Float32x,
136    /// `_Float64x`, which is whatever `long double` is.
137    Float64x,
138    /// `_Float128` (and GCC's `__float128`): binary128, which has no Rust type.
139    /// It may be named — in a prototype, a `typedef`, a pointer — but sema
140    /// refuses every value of it.
141    Float128,
142}
143
144impl FloatSize {
145    /// The type as C spells it.
146    pub fn as_str(self) -> &'static str {
147        match self {
148            FloatSize::Float => "float",
149            FloatSize::Double => "double",
150            FloatSize::LongDouble => "long double",
151            FloatSize::Float32 => "_Float32",
152            FloatSize::Float64 => "_Float64",
153            FloatSize::Float32x => "_Float32x",
154            FloatSize::Float64x => "_Float64x",
155            FloatSize::Float128 => "_Float128",
156        }
157    }
158
159    /// Whether this is one of the `_FloatN` spellings, which GCC makes types
160    /// distinct from `float`, `double` and `long double` even where they have
161    /// the same format; see `_Generic` in sema.
162    pub fn is_floatn(self) -> bool {
163        !matches!(
164            self,
165            FloatSize::Float | FloatSize::Double | FloatSize::LongDouble
166        )
167    }
168}
169
170/// `struct` or `union`.
171#[derive(Clone, Copy, Debug, PartialEq, Eq)]
172pub enum RecordKind {
173    /// `struct`
174    Struct,
175    /// `union`
176    Union,
177}
178
179impl RecordKind {
180    /// The keyword that introduces this kind of record.
181    pub fn as_str(self) -> &'static str {
182        match self {
183            RecordKind::Struct => "struct",
184            RecordKind::Union => "union",
185        }
186    }
187}
188
189/// The size of an array derivation.
190#[derive(Clone, Debug, PartialEq)]
191pub enum ArraySize {
192    /// `[]` — an incomplete array type.
193    Unspecified,
194    /// `[*]` — a variable length array of unspecified size, only valid in a
195    /// function prototype.
196    Star,
197    /// `[expr]`. Whether this is a constant array bound or a VLA is decided by
198    /// constant evaluation in sema.
199    Expr(Box<Expr>),
200}
201
202/// A C type, as produced by resolving declaration specifiers and a declarator.
203#[derive(Clone, Debug, PartialEq)]
204pub struct Type {
205    /// What kind of type this is.
206    pub kind: TypeKind,
207    /// Qualifiers applied to *this* type (not to what it points at).
208    pub qualifiers: TypeQualifiers,
209    /// The source range of the construct that produced this type.
210    pub range: SourceRange,
211}
212
213impl Type {
214    /// Builds a type.
215    pub fn new(kind: TypeKind, qualifiers: TypeQualifiers, range: SourceRange) -> Self {
216        Self {
217            kind,
218            qualifiers,
219            range,
220        }
221    }
222
223    /// Builds an unqualified type.
224    pub fn plain(kind: TypeKind, range: SourceRange) -> Self {
225        Self::new(kind, TypeQualifiers::NONE, range)
226    }
227
228    /// Whether this is the placeholder produced by error recovery.
229    pub fn is_error(&self) -> bool {
230        matches!(self.kind, TypeKind::Error)
231    }
232}
233
234/// The shape of a [`Type`].
235#[derive(Clone, Debug, PartialEq)]
236pub enum TypeKind {
237    /// `void`
238    Void,
239    /// `_Bool`
240    Bool,
241    /// `char`, `signed char` or `unsigned char`. `None` means plain `char`,
242    /// which is a distinct type from both of the others.
243    Char(Option<Sign>),
244    /// `short`, `int`, `long`, `long long`, signed or unsigned.
245    Int {
246        /// Signedness.
247        sign: Sign,
248        /// Rank.
249        size: IntSize,
250    },
251    /// `float`, `double`, `long double`.
252    Float(FloatSize),
253    /// `float _Complex` and friends.
254    Complex(FloatSize),
255    /// `float _Imaginary` and friends.
256    Imaginary(FloatSize),
257    /// Pointer to the given type.
258    Pointer(Box<Type>),
259    /// Array derivation.
260    Array {
261        /// Element type.
262        elem: Box<Type>,
263        /// The bound.
264        size: ArraySize,
265        /// Qualifiers written inside the brackets (`int p[const 4]`); only
266        /// meaningful on a parameter.
267        qualifiers: TypeQualifiers,
268        /// Whether `static` was written inside the brackets.
269        is_static: bool,
270    },
271    /// Function derivation.
272    Function(Box<FunctionType>),
273    /// A `struct`/`union` specifier, with or without a body.
274    ///
275    /// The specifier itself lives in [`TranslationUnit::records`]; see
276    /// [`RecordSpecId`] for why it is an id rather than the body.
277    Record(RecordSpecId),
278    /// An `enum` specifier, with or without a body.
279    Enum(EnumSpecId),
280    /// A name introduced by `typedef`, not yet resolved.
281    Typedef(Ident),
282    /// `typeof(…)` / `typeof_unqual(…)` — C23.
283    ///
284    /// The operand lives in [`TranslationUnit::typeofs`]; see [`TypeofId`].
285    Typeof {
286        /// Which operand.
287        id: TypeofId,
288        /// Whether this is `typeof_unqual`, which takes the *unqualified*
289        /// type of its operand (C23 6.7.2.5p3).
290        ///
291        /// Only one qualifier is part of a [`crate::ir::Ty`] at all —
292        /// `_Atomic`, which changes the size, the alignment and what an access
293        /// to the object does — so that is the one this strips.
294        unqual: bool,
295    },
296    /// The type `auto x = e;` infers from the initialiser — C23.
297    Auto,
298    /// Produced by error recovery; sema must not report further errors on it.
299    Error,
300}
301
302/// Identifies one `typeof` operand in [`TranslationUnit::typeofs`].
303///
304/// Stored apart for the reason a [`RecordSpecId`] is: a type name holds both
305/// the specifiers it was written with and the type its declarator produced, so
306/// a `typeof` written inside another one would otherwise be copied twice per
307/// level.
308#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash, PartialOrd, Ord)]
309pub struct TypeofId(pub u32);
310
311impl TypeofId {
312    /// The index into [`TranslationUnit::typeofs`].
313    pub fn index(self) -> usize {
314        self.0 as usize
315    }
316}
317
318/// What `typeof` was applied to.
319//
320// The AST is built once per macro invocation and then walked; boxing the type
321// name to even the variants out would only make sema noisier to write.
322#[allow(clippy::large_enum_variant)]
323#[derive(Clone, Debug, PartialEq)]
324pub enum TypeofOperand {
325    /// `typeof(expr)`, whose operand is not evaluated.
326    Expr(Expr),
327    /// `typeof(type-name)`.
328    Type(TypeName),
329}
330
331/// A function type derivation.
332#[derive(Clone, Debug, PartialEq)]
333pub struct FunctionType {
334    /// The return type.
335    pub ret: Type,
336    /// The declared parameters (empty for `f(void)` and for `f()`).
337    pub params: Vec<ParamDecl>,
338    /// Whether the parameter list ended with `, ...`.
339    pub variadic: bool,
340    /// Where the `...` was written, which is where a diagnostic about it
341    /// belongs.
342    pub ellipsis: Option<SourceRange>,
343    /// Whether a prototype was given at all. `int f()` and `int f(a, b)` have
344    /// no prototype; `int f(void)` and `int f(int)` do.
345    pub has_prototype: bool,
346    /// The identifier list of an old-style (K&R) declarator, e.g. `f(a, b)`.
347    pub kr_names: Vec<Ident>,
348    /// Whether [`FunctionType::params`] came from an identifier list and the
349    /// declaration list of an old-style definition rather than from a
350    /// prototype.
351    ///
352    /// Sema builds that list — see `Sema::old_style_params` — so the rest of
353    /// the front end sees ordinary parameters; the flag is what remembers that
354    /// the *type* still has no prototype and that the generated item takes the
355    /// promoted types (C99 6.9.1p7).
356    pub old_style: bool,
357}
358
359/// One parameter of a function prototype.
360#[derive(Clone, Debug, PartialEq)]
361pub struct ParamDecl {
362    /// The parameter's declaration specifiers.
363    pub specifiers: DeclSpecifiers,
364    /// The parameter name, absent in an abstract declarator.
365    pub name: Option<Ident>,
366    /// The parameter's type after applying its declarator.
367    pub ty: Type,
368    /// Where the parameter was written.
369    pub range: SourceRange,
370}
371
372/// Identifies one `struct`/`union` specifier in [`TranslationUnit::records`].
373///
374/// A declarator is resolved into a [`Type`] as it is parsed, so the specifier
375/// of `struct S { … } a, b;` is named by the type of every declarator that
376/// shares it *and* by the declaration's own specifiers. Storing the member
377/// list once and handing out an index keeps that from copying the body — which,
378/// for a record nested inside a record, would double the data at every level.
379///
380/// An index rather than an `Rc` because the tree crosses the thread boundary
381/// [`crate::analyze`] puts the deep passes behind, and has to stay [`Send`].
382#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash, PartialOrd, Ord)]
383pub struct RecordSpecId(pub u32);
384
385impl RecordSpecId {
386    /// The index into [`TranslationUnit::records`].
387    pub fn index(self) -> usize {
388        self.0 as usize
389    }
390}
391
392/// Identifies one `enum` specifier in [`TranslationUnit::enums`].
393///
394/// See [`RecordSpecId`], which this is the enumeration's counterpart of.
395#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash, PartialOrd, Ord)]
396pub struct EnumSpecId(pub u32);
397
398impl EnumSpecId {
399    /// The index into [`TranslationUnit::enums`].
400    pub fn index(self) -> usize {
401        self.0 as usize
402    }
403}
404
405/// A `struct` or `union` specifier, as written.
406///
407/// One of these lives in [`TranslationUnit::records`] per specifier in the
408/// source, and [`TypeKind::Record`] names it by [`RecordSpecId`].
409#[derive(Clone, Debug, PartialEq)]
410pub struct RecordSpec {
411    /// `struct` or `union`.
412    pub kind: RecordKind,
413    /// The tag, if one was written.
414    pub name: Option<Ident>,
415    /// The member list; `None` for a reference such as `struct S *p`.
416    pub fields: Option<Vec<FieldDecl>>,
417    /// The `_Static_assert` declarations written among the members (C11).
418    ///
419    /// They are kept apart from the members because they declare nothing: a
420    /// member list with one in it lays out exactly as it would without.
421    pub asserts: Vec<StaticAssert>,
422    /// What `__attribute__((packed))` and friends asked of the whole record.
423    pub attrs: Attributes,
424    /// The member alignment `#pragma pack(N)` was asking for where the
425    /// specifier was written, if any.
426    pub pack: Option<u32>,
427    /// Where the specifier was written.
428    pub range: SourceRange,
429}
430
431/// `_Static_assert(expr, "message");` — C11 6.7.10, whose message C23 makes
432/// optional.
433#[derive(Clone, Debug, PartialEq)]
434pub struct StaticAssert {
435    /// The constant expression that must be non-zero.
436    pub cond: Expr,
437    /// The message, as written (quotes included), if one was given.
438    pub message: Option<String>,
439    /// Where the whole declaration was written.
440    pub range: SourceRange,
441}
442
443/// One member of a `struct` or `union`.
444#[derive(Clone, Debug, PartialEq)]
445pub struct FieldDecl {
446    /// The member's declaration specifiers.
447    pub specifiers: DeclSpecifiers,
448    /// The member name; absent for an anonymous bit-field or an anonymous
449    /// struct/union member.
450    pub name: Option<Ident>,
451    /// The member's type.
452    pub ty: Type,
453    /// The bit-field width, if any.
454    pub bit_width: Option<Expr>,
455    /// What `__attribute__((…))` on this member asked for.
456    pub attrs: Attributes,
457    /// Where the member was written.
458    pub range: SourceRange,
459}
460
461/// An `enum` specifier, as written.
462///
463/// Stored in [`TranslationUnit::enums`] and named by [`EnumSpecId`], for the
464/// same reason a [`RecordSpec`] is.
465#[derive(Clone, Debug, PartialEq)]
466pub struct EnumSpec {
467    /// The tag, if one was written.
468    pub name: Option<Ident>,
469    /// The enumerator list; `None` for a reference such as `enum E e`.
470    pub enumerators: Option<Vec<Enumerator>>,
471    /// The fixed underlying type (`enum E : unsigned char { … }`), C23.
472    pub underlying: Option<Type>,
473    /// Where the specifier was written.
474    pub range: SourceRange,
475}
476
477/// One `enum` constant.
478#[derive(Clone, Debug, PartialEq)]
479pub struct Enumerator {
480    /// The constant's name.
481    pub name: Ident,
482    /// Its explicit value, if given.
483    pub value: Option<Expr>,
484    /// Where it was written.
485    pub range: SourceRange,
486}
487
488// ---------------------------------------------------------------------------
489// declarations
490// ---------------------------------------------------------------------------
491
492/// A storage-class specifier.
493#[derive(Clone, Copy, Debug, PartialEq, Eq)]
494pub enum StorageClass {
495    /// `typedef`
496    Typedef,
497    /// `extern`
498    Extern,
499    /// `static`
500    Static,
501    /// `auto`
502    Auto,
503    /// `register`
504    Register,
505    /// `constexpr` — C23.
506    Constexpr,
507}
508
509impl StorageClass {
510    /// The keyword spelling.
511    pub fn as_str(self) -> &'static str {
512        match self {
513            StorageClass::Typedef => "typedef",
514            StorageClass::Extern => "extern",
515            StorageClass::Static => "static",
516            StorageClass::Auto => "auto",
517            StorageClass::Register => "register",
518            StorageClass::Constexpr => "constexpr",
519        }
520    }
521}
522
523/// An `_Alignas` / `alignas` specifier (C11 6.7.5).
524#[derive(Clone, Debug, PartialEq)]
525pub struct Alignment {
526    /// What was written inside the parentheses.
527    pub kind: AlignmentKind,
528    /// Whether this came from `__attribute__((aligned(N)))` rather than from an
529    /// `_Alignas` specifier.
530    ///
531    /// The two ask for the same thing and are folded into one list, but they
532    /// differ on one point: an `_Alignas` weaker than the type's own alignment
533    /// is a constraint violation (C11 6.7.5p4), while GCC's `aligned` "can only
534    /// increase alignment" and a weaker one is simply not applied.
535    pub from_attribute: bool,
536    /// Where the specifier was written.
537    pub range: SourceRange,
538}
539
540/// The operand of an [`Alignment`].
541#[derive(Clone, Debug, PartialEq)]
542pub enum AlignmentKind {
543    /// `_Alignas(16)` — a constant expression.
544    Expr(Expr),
545    /// `_Alignas(double)` — the alignment of a type.
546    Type(Box<TypeName>),
547}
548
549/// What an attribute specifier sequence asked for.
550///
551/// Both spellings — GNU's `__attribute__((…))` and C23's `[[…]]` — produce
552/// this, because they say the same things. Everything the front end does not
553/// act on is dropped while it is parsed, which C23 6.7.13.1p3 explicitly
554/// allows and which GCC does with a warning this crate has no way to raise.
555#[derive(Clone, Debug, Default, PartialEq)]
556pub struct Attributes {
557    /// `noreturn` / `[[noreturn]]`, which says exactly what `_Noreturn` says.
558    pub noreturn: Option<SourceRange>,
559    /// `always_inline`.
560    pub always_inline: Option<SourceRange>,
561    /// `noinline`.
562    pub noinline: Option<SourceRange>,
563    /// `cold`; `hot` clears it again, as GCC's do.
564    pub cold: Option<SourceRange>,
565    /// `deprecated`, with the message it was given.
566    pub deprecated: Option<Spanned<Option<String>>>,
567    /// `packed`, on a record or on one member.
568    pub packed: Option<SourceRange>,
569    /// `aligned(N)`, which is the same request `_Alignas(N)` makes.
570    pub aligned: Option<Alignment>,
571    /// `section("…")`.
572    pub section: Option<Spanned<String>>,
573    /// `target("avx2")`, `target("sse4.2,popcnt")`, `target("avx2", "fma")`:
574    /// the instruction sets the function is compiled for, one entry per name,
575    /// in GCC's spelling and with the range of the attribute that wrote it.
576    ///
577    /// Also what `#pragma GCC target` leaves behind for the functions after
578    /// it; the parser puts the pragma's list here when the declaration writes
579    /// no attribute of its own.
580    pub target: Vec<Spanned<String>>,
581    /// `constructor`, whose priority is parsed and ignored.
582    pub constructor: Option<SourceRange>,
583    /// `destructor`, likewise.
584    pub destructor: Option<SourceRange>,
585    /// `cleanup(f)`, on a variable with automatic storage duration.
586    pub cleanup: Option<Cleanup>,
587    /// `mode(M)`, which replaces the declared type with the one the machine
588    /// mode names, keeping its signedness.
589    pub mode: Option<Spanned<String>>,
590    /// `[[cinrs::safe]]` / `__attribute__((cinrs_safe))`: generate the function
591    /// without `unsafe`, so that `rustc` checks its body.
592    ///
593    /// This crate's own attribute rather than one of GCC's, which is why it is
594    /// spelled in this crate's namespace both ways.
595    pub safe: Option<SourceRange>,
596    /// `weak`, which only sema can answer: it is refused on a definition and
597    /// accepted on a declaration.
598    pub weak: Option<SourceRange>,
599}
600
601/// `__attribute__((cleanup(f)))`: `f(&x)` runs when `x` goes out of scope.
602#[derive(Clone, Debug, PartialEq)]
603pub struct Cleanup {
604    /// The function named, or `None` when the argument was not an identifier
605    /// at all — which GCC refuses with "cleanup argument not an identifier".
606    pub func: Option<Ident>,
607    /// Where the attribute was written.
608    pub range: SourceRange,
609}
610
611impl Attributes {
612    /// Whether nothing was asked for.
613    pub fn is_empty(&self) -> bool {
614        *self == Attributes::default()
615    }
616
617    /// Everything either sequence asked for.
618    ///
619    /// GCC lets the attributes of one declaration be spread over the
620    /// specifiers, the declarator and the definition, and takes the union.
621    pub fn merge(&mut self, other: Attributes) {
622        self.noreturn = self.noreturn.or(other.noreturn);
623        self.always_inline = self.always_inline.or(other.always_inline);
624        self.noinline = self.noinline.or(other.noinline);
625        self.cold = self.cold.or(other.cold);
626        self.deprecated = self.deprecated.take().or(other.deprecated);
627        self.packed = self.packed.or(other.packed);
628        self.aligned = self.aligned.take().or(other.aligned);
629        self.section = self.section.take().or(other.section);
630        // Two `target` attributes on one declaration add up, exactly as two
631        // `-m` switches do: `__attribute__((target("avx2"))) __attribute__
632        // ((target("fma"))) void f(void)` asks for both.
633        self.target.extend(other.target);
634        self.constructor = self.constructor.or(other.constructor);
635        self.destructor = self.destructor.or(other.destructor);
636        self.cleanup = self.cleanup.take().or(other.cleanup);
637        self.mode = self.mode.take().or(other.mode);
638        self.safe = self.safe.or(other.safe);
639        self.weak = self.weak.or(other.weak);
640    }
641}
642
643/// The declaration specifiers shared by all declarators of one declaration.
644#[derive(Clone, Debug, PartialEq)]
645pub struct DeclSpecifiers {
646    /// The storage class, if one was written.
647    pub storage: Option<Spanned<StorageClass>>,
648    /// Where `_Thread_local`, C23's `thread_local` or GNU's `__thread` was
649    /// written, if it was.
650    ///
651    /// It is not a [`StorageClass`], because C11 6.7.1p2 lets it appear
652    /// *beside* one: `static _Thread_local int x;` names a thread-local object
653    /// with internal linkage, and at block scope one of `static` or `extern`
654    /// is required (6.7.1p3).
655    pub thread_local: Option<SourceRange>,
656    /// Whether `inline` was written.
657    pub inline: bool,
658    /// Whether the declaration was marked `_Noreturn`, `[[noreturn]]` or
659    /// `__cinrs_noreturn`.
660    pub noreturn: Option<SourceRange>,
661    /// The alignment specifiers written among these declaration specifiers, in
662    /// the order they were written.
663    ///
664    /// C11 6.7.5p6 allows several and makes the strictest of them the one that
665    /// holds, so they are all kept; `__attribute__((aligned(N)))` written here
666    /// asks for the same thing and is folded in, with
667    /// [`Alignment::from_attribute`] saying which spelling each one came from.
668    pub alignas: Vec<Alignment>,
669    /// What `__attribute__((…))` and `[[…]]` asked for.
670    pub attrs: Attributes,
671    /// The base type built from the type specifiers and qualifiers.
672    pub base: Type,
673    /// Where the specifiers were written.
674    pub range: SourceRange,
675}
676
677impl DeclSpecifiers {
678    /// Whether this declaration introduces `typedef` names.
679    pub fn is_typedef(&self) -> bool {
680        matches!(
681            self.storage,
682            Some(Spanned {
683                node: StorageClass::Typedef,
684                ..
685            })
686        )
687    }
688}
689
690/// A declaration: specifiers plus zero or more declarators.
691#[derive(Clone, Debug, PartialEq)]
692pub struct Decl {
693    /// The shared specifiers.
694    pub specifiers: DeclSpecifiers,
695    /// The declared entities.
696    pub declarators: Vec<InitDeclarator>,
697    /// Where the declaration was written, including its `;`.
698    pub range: SourceRange,
699}
700
701/// One declarator of a [`Decl`], with its optional initialiser.
702#[derive(Clone, Debug, PartialEq)]
703pub struct InitDeclarator {
704    /// The declared name; absent only after error recovery.
705    pub name: Option<Ident>,
706    /// The fully resolved type.
707    pub ty: Type,
708    /// The initialiser, if any.
709    pub init: Option<Initializer>,
710    /// What `__attribute__((…))` written on *this* declarator asked for.
711    pub attrs: Attributes,
712    /// The symbol `__asm__("name")` renamed this declaration to.
713    pub asm_label: Option<Spanned<String>>,
714    /// Where the declarator was written.
715    pub range: SourceRange,
716}
717
718/// An initialiser.
719#[derive(Clone, Debug, PartialEq)]
720pub struct Initializer {
721    /// What kind of initialiser this is.
722    pub kind: InitializerKind,
723    /// Where it was written.
724    pub range: SourceRange,
725}
726
727/// The shape of an [`Initializer`].
728#[derive(Clone, Debug, PartialEq)]
729pub enum InitializerKind {
730    /// `= expr`
731    Expr(Expr),
732    /// `= { … }`
733    List(Vec<InitItem>),
734}
735
736/// One element of a braced initialiser list.
737#[derive(Clone, Debug, PartialEq)]
738pub struct InitItem {
739    /// Designators written before `=`, e.g. `.x` or `[3]`.
740    pub designators: Vec<Designator>,
741    /// The value.
742    pub init: Initializer,
743    /// Where the element was written.
744    pub range: SourceRange,
745}
746
747/// A C99 designator.
748#[derive(Clone, Debug, PartialEq)]
749pub enum Designator {
750    /// `.name`, and the pre-C99 `name:` GNU still accepts.
751    Field(Ident),
752    /// `[expr]`
753    Index(Expr),
754    /// `[low ... high]` — GNU's range designator, which fills every element of
755    /// the range with the same value.
756    Range(Expr, Expr),
757}
758
759/// A type name, as written in a cast, `sizeof(T)` or a compound literal.
760#[derive(Clone, Debug, PartialEq)]
761pub struct TypeName {
762    /// The specifier-qualifier list.
763    pub specifiers: DeclSpecifiers,
764    /// The type after applying the abstract declarator.
765    pub ty: Type,
766    /// Where it was written.
767    pub range: SourceRange,
768}
769
770// ---------------------------------------------------------------------------
771// statements
772// ---------------------------------------------------------------------------
773
774/// A compound statement.
775#[derive(Clone, Debug, PartialEq)]
776pub struct Block {
777    /// Declarations and statements, in source order (C99 allows mixing).
778    pub items: Vec<BlockItem>,
779    /// The labels `__label__ a, b;` declared local to this block.
780    ///
781    /// C gives every label function scope, and so does this crate, so the
782    /// declaration is accepted and the labels behave as they would without it.
783    pub local_labels: Vec<Ident>,
784    /// Where the block was written, including its braces.
785    pub range: SourceRange,
786}
787
788/// An element of a [`Block`].
789//
790// The AST is built once per macro invocation and then walked; boxing every
791// large field to even out the variants would only make sema and codegen
792// noisier to write.
793#[allow(clippy::large_enum_variant)]
794#[derive(Clone, Debug, PartialEq)]
795pub enum BlockItem {
796    /// A declaration.
797    Decl(Decl),
798    /// A statement.
799    Stmt(Stmt),
800    /// `_Static_assert(…);` — C11.
801    StaticAssert(StaticAssert),
802    /// GNU's nested function definition, `int f(void) { int g(int x) { … } }`.
803    ///
804    /// It is a block *item* rather than a declaration or a statement: it
805    /// declares a name in the enclosing block, contributes no statement to it,
806    /// and its body is checked in a scope of its own. Semantic analysis lifts
807    /// it to a file-scope item with a hidden environment; see
808    /// `Sema::nested_function_def`.
809    NestedFunction(FunctionDef),
810}
811
812/// A statement.
813#[derive(Clone, Debug, PartialEq)]
814pub struct Stmt {
815    /// What kind of statement this is.
816    pub kind: StmtKind,
817    /// Where it was written.
818    pub range: SourceRange,
819}
820
821/// The shape of a [`Stmt`].
822#[allow(clippy::large_enum_variant)]
823#[derive(Clone, Debug, PartialEq)]
824pub enum StmtKind {
825    /// `label: stmt`
826    Labeled {
827        /// The label.
828        label: Ident,
829        /// The labelled statement.
830        body: Box<Stmt>,
831    },
832    /// `case expr: stmt`, and GNU's `case low ... high: stmt`.
833    Case {
834        /// The case value, or the low end of a range.
835        value: Expr,
836        /// The high end of a `case low ... high:` range.
837        upper: Option<Expr>,
838        /// The labelled statement.
839        body: Box<Stmt>,
840    },
841    /// `default: stmt`
842    Default {
843        /// The labelled statement.
844        body: Box<Stmt>,
845    },
846    /// `{ … }`
847    Compound(Block),
848    /// `expr;` or the null statement `;`.
849    Expr(Option<Expr>),
850    /// `if (cond) then else otherwise`
851    If {
852        /// The controlling expression.
853        cond: Expr,
854        /// The `then` branch.
855        then_branch: Box<Stmt>,
856        /// The `else` branch, if any.
857        else_branch: Option<Box<Stmt>>,
858    },
859    /// `switch (cond) body`
860    Switch {
861        /// The controlling expression.
862        cond: Expr,
863        /// The switch body.
864        body: Box<Stmt>,
865    },
866    /// `while (cond) body`
867    While {
868        /// The controlling expression.
869        cond: Expr,
870        /// The loop body.
871        body: Box<Stmt>,
872    },
873    /// `do body while (cond);`
874    DoWhile {
875        /// The loop body.
876        body: Box<Stmt>,
877        /// The controlling expression.
878        cond: Expr,
879    },
880    /// `for (init; cond; step) body`
881    For {
882        /// The init clause.
883        init: ForInit,
884        /// The controlling expression, if any.
885        cond: Option<Expr>,
886        /// The iteration expression, if any.
887        step: Option<Expr>,
888        /// The loop body.
889        body: Box<Stmt>,
890    },
891    /// `goto label;`
892    Goto(Ident),
893    /// GNU's computed `goto *expr;`, whose operand is a label address.
894    GotoPtr(Expr),
895    /// `continue;`
896    Continue,
897    /// `break;`
898    Break,
899    /// `return expr;`
900    Return(Option<Expr>),
901    /// GNU's inline assembly statement, basic or extended; see [`AsmStmt`].
902    Asm(Box<AsmStmt>),
903    /// Produced by error recovery.
904    Error,
905}
906
907/// `asm [volatile] [inline] [goto] ( template [: outputs [: inputs [:
908/// clobbers [: labels]]]] ) ;` — GNU inline assembly.
909///
910/// The parser records what was written and nothing more: the template and
911/// the constraints are opaque strings here (adjacent string literals already
912/// concatenated), and deciding what they mean — and what of it `asm!` can
913/// express — is sema's business.
914#[derive(Clone, Debug, PartialEq)]
915pub struct AsmStmt {
916    /// `volatile` or `__volatile__` was written.
917    pub volatile: bool,
918    /// `inline` or `__inline__` was written.
919    pub inline: bool,
920    /// `goto` was written: the statement may jump to one of [`labels`].
921    ///
922    /// [`labels`]: AsmStmt::labels
923    pub goto: bool,
924    /// The assembler template.
925    pub template: Spanned<String>,
926    /// Whether any colon section was written, which is what makes this
927    /// *extended* asm: GCC treats `%` in a basic asm template literally, and
928    /// `asm("" :)` as extended asm with no operands.
929    pub extended: bool,
930    /// The output operands, in order.
931    pub outputs: Vec<AsmOperand>,
932    /// The input operands, in order; GCC numbers them after the outputs.
933    pub inputs: Vec<AsmOperand>,
934    /// The clobber list: register names, `"memory"`, `"cc"`.
935    pub clobbers: Vec<Spanned<String>>,
936    /// The labels of an `asm goto`.
937    pub labels: Vec<Ident>,
938}
939
940/// One operand of an extended [`AsmStmt`]: `[name] "constraint" (expr)`.
941#[derive(Clone, Debug, PartialEq)]
942pub struct AsmOperand {
943    /// The symbolic name `%[name]` refers to it by, if any.
944    pub name: Option<Ident>,
945    /// The constraint string, modifiers (`=`, `+`, `&`) included.
946    pub constraint: Spanned<String>,
947    /// The operand: an lvalue for an output, any expression for an input.
948    pub expr: Expr,
949}
950
951/// The init clause of a `for` statement.
952#[derive(Clone, Debug, PartialEq)]
953pub enum ForInit {
954    /// `for (; …)`
955    None,
956    /// `for (expr; …)`
957    Expr(Expr),
958    /// `for (int i = 0; …)` — C99.
959    Decl(Box<Decl>),
960    /// `for (_Static_assert(1, "…"); …)`.
961    ///
962    /// A static assertion is a *declaration*, so the grammar puts it here,
963    /// and C11 6.8.5p3 then forbids it — the clause may only declare objects
964    /// with automatic or register storage duration, and this declares nothing
965    /// at all. GCC and Clang both accept it anyway (Clang's `C11/n1330.c`
966    /// says so in as many words), it asserts exactly what it would one line
967    /// higher up, and refusing it would be refusing something both compilers
968    /// this crate follows take.
969    StaticAssert(StaticAssert),
970}
971
972// ---------------------------------------------------------------------------
973// expressions
974// ---------------------------------------------------------------------------
975
976/// A prefix or unary operator.
977#[derive(Clone, Copy, Debug, PartialEq, Eq)]
978pub enum UnaryOp {
979    /// `+x`
980    Plus,
981    /// `-x`
982    Minus,
983    /// `!x`
984    LogNot,
985    /// `~x`
986    BitNot,
987    /// `*p`
988    Deref,
989    /// `&x`
990    AddrOf,
991}
992
993impl UnaryOp {
994    /// The operator's spelling.
995    pub fn as_str(self) -> &'static str {
996        match self {
997            UnaryOp::Plus => "+",
998            UnaryOp::Minus => "-",
999            UnaryOp::LogNot => "!",
1000            UnaryOp::BitNot => "~",
1001            UnaryOp::Deref => "*",
1002            UnaryOp::AddrOf => "&",
1003        }
1004    }
1005}
1006
1007/// A binary operator.
1008#[derive(Clone, Copy, Debug, PartialEq, Eq)]
1009#[allow(missing_docs)]
1010pub enum BinaryOp {
1011    Add,
1012    Sub,
1013    Mul,
1014    Div,
1015    Rem,
1016    Shl,
1017    Shr,
1018    Lt,
1019    Gt,
1020    Le,
1021    Ge,
1022    Eq,
1023    Ne,
1024    BitAnd,
1025    BitXor,
1026    BitOr,
1027    LogAnd,
1028    LogOr,
1029}
1030
1031impl BinaryOp {
1032    /// The operator's spelling.
1033    pub fn as_str(self) -> &'static str {
1034        use BinaryOp::*;
1035        match self {
1036            Add => "+",
1037            Sub => "-",
1038            Mul => "*",
1039            Div => "/",
1040            Rem => "%",
1041            Shl => "<<",
1042            Shr => ">>",
1043            Lt => "<",
1044            Gt => ">",
1045            Le => "<=",
1046            Ge => ">=",
1047            Eq => "==",
1048            Ne => "!=",
1049            BitAnd => "&",
1050            BitXor => "^",
1051            BitOr => "|",
1052            LogAnd => "&&",
1053            LogOr => "||",
1054        }
1055    }
1056}
1057
1058/// `++` or `--`.
1059#[derive(Clone, Copy, Debug, PartialEq, Eq)]
1060pub enum IncDec {
1061    /// `++`
1062    Inc,
1063    /// `--`
1064    Dec,
1065}
1066
1067impl IncDec {
1068    /// The operator's spelling.
1069    pub fn as_str(self) -> &'static str {
1070        match self {
1071            IncDec::Inc => "++",
1072            IncDec::Dec => "--",
1073        }
1074    }
1075}
1076
1077/// An expression.
1078#[derive(Clone, Debug, PartialEq)]
1079pub struct Expr {
1080    /// What kind of expression this is.
1081    pub kind: ExprKind,
1082    /// Where it was written.
1083    pub range: SourceRange,
1084}
1085
1086/// The shape of an [`Expr`].
1087#[derive(Clone, Debug, PartialEq)]
1088pub enum ExprKind {
1089    /// An identifier reference.
1090    Ident(Ident),
1091    /// An integer constant.
1092    Int(IntLit),
1093    /// A floating constant.
1094    Float(FloatLit),
1095    /// A character constant.
1096    Char(CharLit),
1097    /// A string literal, after adjacent-literal concatenation.
1098    Str(StrLit),
1099    /// A unary operator application.
1100    Unary {
1101        /// The operator.
1102        op: UnaryOp,
1103        /// The operand.
1104        operand: Box<Expr>,
1105    },
1106    /// A binary operator application.
1107    Binary {
1108        /// The operator.
1109        op: BinaryOp,
1110        /// Left operand.
1111        lhs: Box<Expr>,
1112        /// Right operand.
1113        rhs: Box<Expr>,
1114    },
1115    /// An assignment; `op` is `None` for `=` and `Some(op)` for `op=`.
1116    Assign {
1117        /// The compound operator, if any.
1118        op: Option<BinaryOp>,
1119        /// The assigned-to operand.
1120        lhs: Box<Expr>,
1121        /// The assigned value.
1122        rhs: Box<Expr>,
1123    },
1124    /// `cond ? then_expr : else_expr`, and GNU's `cond ?: else_expr`.
1125    Conditional {
1126        /// The condition.
1127        cond: Box<Expr>,
1128        /// The value when the condition holds; `None` for `a ?: b`, where it
1129        /// is the condition's own value and the condition is evaluated once.
1130        then_expr: Option<Box<Expr>>,
1131        /// The value otherwise.
1132        else_expr: Box<Expr>,
1133    },
1134    /// `lhs, rhs`
1135    Comma {
1136        /// Evaluated and discarded.
1137        lhs: Box<Expr>,
1138        /// The result.
1139        rhs: Box<Expr>,
1140    },
1141    /// `callee(args…)`
1142    Call {
1143        /// The called expression.
1144        callee: Box<Expr>,
1145        /// The arguments.
1146        args: Vec<Expr>,
1147    },
1148    /// `base.field` or `base->field`
1149    Member {
1150        /// The object or pointer.
1151        base: Box<Expr>,
1152        /// Whether `->` was used.
1153        arrow: bool,
1154        /// The member name.
1155        field: Ident,
1156    },
1157    /// `base[index]`
1158    Index {
1159        /// The array or pointer.
1160        base: Box<Expr>,
1161        /// The subscript.
1162        index: Box<Expr>,
1163    },
1164    /// `x++` / `x--`
1165    PostIncDec {
1166        /// Which operator.
1167        op: IncDec,
1168        /// The operand.
1169        operand: Box<Expr>,
1170    },
1171    /// `++x` / `--x`
1172    PreIncDec {
1173        /// Which operator.
1174        op: IncDec,
1175        /// The operand.
1176        operand: Box<Expr>,
1177    },
1178    /// `(T)expr`
1179    Cast {
1180        /// The target type.
1181        ty: Box<TypeName>,
1182        /// The operand.
1183        expr: Box<Expr>,
1184    },
1185    /// GNU's `&&label`: the address of a label of the enclosing function, of
1186    /// type `void *`, which `goto *` jumps to.
1187    LabelAddr(Ident),
1188    /// `sizeof expr`
1189    SizeofExpr(Box<Expr>),
1190    /// `sizeof(T)`
1191    SizeofType(Box<TypeName>),
1192    /// `_Alignof expr` — a GNU extension C never standardised.
1193    AlignofExpr(Box<Expr>),
1194    /// `_Alignof(T)` / `alignof(T)` — C11.
1195    AlignofType(Box<TypeName>),
1196    /// `_Generic(controlling, T: value, …)` — C11.
1197    Generic {
1198        /// The controlling expression, which is never evaluated.
1199        controlling: Box<Expr>,
1200        /// The associations, in the order written.
1201        assocs: Vec<GenericAssoc>,
1202    },
1203    /// `true` / `false` — C23.
1204    Bool(bool),
1205    /// `nullptr` — C23.
1206    Nullptr,
1207    /// `va_arg(ap, T)`.
1208    ///
1209    /// It looks like a call but takes a type name, so — like `sizeof` — the
1210    /// parser has to know about it.
1211    VaArg {
1212        /// The argument list read from.
1213        ap: Box<Expr>,
1214        /// The type of the argument being read.
1215        ty: Box<TypeName>,
1216    },
1217    /// `__builtin_offsetof(T, member)`, which `<stddef.h>`'s `offsetof` is.
1218    ///
1219    /// Another one that takes a type name where an expression would go.
1220    OffsetOf {
1221        /// The `struct` or `union` type.
1222        ty: Box<TypeName>,
1223        /// The first step of the member designator, which C requires to be a
1224        /// member name.
1225        member: Ident,
1226        /// The steps after it — `offsetof(struct S, a.b)` and
1227        /// `offsetof(struct S, a[2].b)` are both member designators
1228        /// (C99 7.17p3). A [`Designator::Range`] never appears here.
1229        path: Vec<Designator>,
1230    },
1231    /// `(T){ … }` — a C99 compound literal.
1232    CompoundLiteral {
1233        /// The literal's type.
1234        ty: Box<TypeName>,
1235        /// The initialiser elements.
1236        init: Vec<InitItem>,
1237    },
1238    /// `({ … })` — GNU's statement expression, whose value is the value of the
1239    /// last expression statement in the block.
1240    StmtExpr(Box<Block>),
1241    /// `__builtin_types_compatible_p(T1, T2)`, an integer constant.
1242    TypesCompatible {
1243        /// The first type.
1244        lhs: Box<TypeName>,
1245        /// The second type.
1246        rhs: Box<TypeName>,
1247    },
1248    /// `__builtin_choose_expr(c, a, b)`.
1249    ///
1250    /// Only the operand the constant condition picks is type checked, which is
1251    /// the whole point of the builtin.
1252    ChooseExpr {
1253        /// The controlling constant expression.
1254        cond: Box<Expr>,
1255        /// Chosen when it is non-zero.
1256        then_expr: Box<Expr>,
1257        /// Chosen otherwise.
1258        else_expr: Box<Expr>,
1259    },
1260    /// `__real__ e` / `__imag__ e`, which need complex arithmetic.
1261    ComplexPart {
1262        /// Whether this is `__real__`.
1263        real: bool,
1264        /// The operand.
1265        operand: Box<Expr>,
1266    },
1267    /// Produced by error recovery.
1268    Error,
1269}
1270
1271/// One association of a `_Generic` selection.
1272#[derive(Clone, Debug, PartialEq)]
1273pub struct GenericAssoc {
1274    /// The type this association is chosen for; `None` for `default:`.
1275    pub ty: Option<TypeName>,
1276    /// The value the selection has when this association is chosen.
1277    pub value: Expr,
1278    /// Where the association was written.
1279    pub range: SourceRange,
1280}
1281
1282// ---------------------------------------------------------------------------
1283// top level
1284// ---------------------------------------------------------------------------
1285
1286/// A function definition.
1287#[derive(Clone, Debug, PartialEq)]
1288pub struct FunctionDef {
1289    /// The declaration specifiers.
1290    pub specifiers: DeclSpecifiers,
1291    /// The function's name.
1292    pub name: Ident,
1293    /// The function's type; always [`TypeKind::Function`] unless recovery
1294    /// kicked in.
1295    pub ty: Type,
1296    /// Old-style parameter declarations (`int f(a) int a; { … }`). Empty for a
1297    /// prototype-style definition; sema decides whether to accept them.
1298    pub kr_decls: Vec<Decl>,
1299    /// What `__attribute__((…))` written after the declarator asked for.
1300    pub attrs: Attributes,
1301    /// The symbol `__asm__("name")` renamed the definition to.
1302    pub asm_label: Option<Spanned<String>>,
1303    /// The body.
1304    pub body: Block,
1305    /// Whether the body takes the address of a label — GNU's `&&label`.
1306    ///
1307    /// Such a function is lowered through a [control-flow
1308    /// graph](crate::cfg), where a computed `goto` is a `switch` over the
1309    /// labels whose address is taken. The parser records it because `&&label` is an
1310    /// *expression* and may sit anywhere one may — an initialiser, an
1311    /// argument, a block-scope `static`'s table — while the rest of the
1312    /// decision is read off the statements; see
1313    /// [`Parser::label_addrs`](crate::parse). A nested function's own
1314    /// `&&label` is its own business and does not set this.
1315    pub uses_label_addrs: bool,
1316    /// Where the definition was written.
1317    pub range: SourceRange,
1318}
1319
1320/// A top-level item.
1321#[allow(clippy::large_enum_variant)]
1322#[derive(Clone, Debug, PartialEq)]
1323pub enum ExternalDecl {
1324    /// A function definition.
1325    Function(FunctionDef),
1326    /// A declaration.
1327    Decl(Decl),
1328    /// `_Static_assert(…);` — C11.
1329    StaticAssert(StaticAssert),
1330}
1331
1332/// A whole translation unit — the contents of one `c99!` invocation.
1333#[derive(Clone, Debug, PartialEq)]
1334pub struct TranslationUnit {
1335    /// The top-level items.
1336    pub items: Vec<ExternalDecl>,
1337    /// Every `struct`/`union` specifier written in the unit, in source order.
1338    ///
1339    /// [`TypeKind::Record`] indexes this; see [`RecordSpecId`].
1340    pub records: Vec<RecordSpec>,
1341    /// Every `enum` specifier written in the unit, in source order.
1342    pub enums: Vec<EnumSpec>,
1343    /// Every `typeof` operand written in the unit, in source order.
1344    pub typeofs: Vec<TypeofOperand>,
1345    /// The range covering the whole input.
1346    pub range: SourceRange,
1347}
1348
1349impl TranslationUnit {
1350    /// The `struct`/`union` specifier `id` names.
1351    pub fn record(&self, id: RecordSpecId) -> &RecordSpec {
1352        &self.records[id.index()]
1353    }
1354
1355    /// The `enum` specifier `id` names.
1356    pub fn enum_spec(&self, id: EnumSpecId) -> &EnumSpec {
1357        &self.enums[id.index()]
1358    }
1359
1360    /// The `typeof` operand `id` names.
1361    pub fn typeof_operand(&self, id: TypeofId) -> &TypeofOperand {
1362        &self.typeofs[id.index()]
1363    }
1364}