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