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}