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}