Skip to main content

rucc_ast/
spec.rs

1//! Declaration specifiers: what a declaration says before the declarator.
2//!
3//! Design: `spec/06-lexer-and-parser.md` sections 6.5 and 6.6.
4//!
5//! A declaration is a pile of specifiers followed by a list of declarators, and the specifiers
6//! may be written in any order: `unsigned static const long int` is a legal, if unpleasant,
7//! spelling of `static const unsigned long`. So they are accumulated into a record rather than
8//! kept as a sequence, with one exception. The keywords that name a built-in type are kept as
9//! the multiset that was written, in [`Builtin`], and turned into a type by [`Builtin::resolve`]
10//! rather than at the moment they are read, because `long` on its own and `long` before `int`
11//! and `long` after `long` are the same keyword doing three different jobs.
12//!
13//! [`DeclSpecs`] lives in a side table and is not size-capped, unlike the arena nodes.
14
15use rucc_base::Symbol;
16use rucc_diag::Span;
17
18use crate::ast::{AttrList, EnumeratorList, MemberList};
19use crate::decl::TypeNameId;
20use crate::expr::ExprId;
21
22/// A set of declaration specifiers, in the side table.
23pub type DeclSpecsId = rucc_base::Idx<DeclSpecs>;
24
25/// Everything a declaration says before its first declarator.
26#[derive(Debug, Clone, Copy, PartialEq, Eq)]
27pub struct DeclSpecs {
28    /// The storage class, of which there may be at most one.
29    pub storage: Option<StorageClass>,
30    /// Whether `_Thread_local` was written, which is separate because it is a storage class
31    /// specifier that may be combined with another.
32    pub thread_local: bool,
33    /// Whether `constexpr` was written, which is separate for the same reason: C23 6.7.1 lets
34    /// it stand beside `auto`, `register` or `static`, and `static constexpr int x = 1;` is a
35    /// declaration people write.
36    pub constexpr: bool,
37    /// What type was named.
38    pub ty: TypeSpec,
39    /// The qualifiers, which may be written before or after the type.
40    pub quals: Quals,
41    /// `inline` and `_Noreturn`.
42    pub func: FuncSpecs,
43    /// `alignas`, of which there may be several, of which the strictest wins. Only the first is
44    /// kept here; the rest are in the side table alongside it.
45    pub align: Option<AlignSpec>,
46    /// Attributes that appertain to the declaration as a whole.
47    pub attrs: AttrList,
48    /// From the first specifier to the last.
49    pub span: Span,
50}
51
52impl DeclSpecs {
53    /// A specifier list with nothing in it, which is what the parser starts from.
54    #[must_use]
55    pub const fn empty(span: Span) -> DeclSpecs {
56        DeclSpecs {
57            storage: None,
58            thread_local: false,
59            constexpr: false,
60            ty: TypeSpec::None,
61            quals: Quals::NONE,
62            func: FuncSpecs::NONE,
63            align: None,
64            attrs: AttrList::EMPTY,
65            span,
66        }
67    }
68
69    /// Whether this declares type names rather than objects.
70    #[must_use]
71    pub const fn is_typedef(&self) -> bool {
72        matches!(self.storage, Some(StorageClass::Typedef))
73    }
74
75    /// Which spelling asked for a type deduced from an initializer, if either did.
76    #[must_use]
77    pub const fn deduces(&self) -> Option<Deduction> {
78        match self.ty {
79            TypeSpec::Auto(which) => Some(which),
80            _ => None,
81        }
82    }
83}
84
85/// A storage class specifier.
86#[derive(Debug, Clone, Copy, PartialEq, Eq)]
87pub enum StorageClass {
88    /// `typedef`, which the grammar treats as a storage class and which declares no object.
89    Typedef,
90    /// `extern`.
91    Extern,
92    /// `static`.
93    Static,
94    /// `auto`, the old one that means nothing, not the C23 type specifier.
95    Auto,
96    /// `register`.
97    Register,
98}
99
100impl StorageClass {
101    /// The keyword, for the printer and for diagnostics.
102    #[must_use]
103    pub const fn spelling(self) -> &'static str {
104        match self {
105            StorageClass::Typedef => "typedef",
106            StorageClass::Extern => "extern",
107            StorageClass::Static => "static",
108            StorageClass::Auto => "auto",
109            StorageClass::Register => "register",
110        }
111    }
112}
113
114/// The type qualifiers, as a set.
115///
116/// `_Atomic` is here because it can be written in qualifier position, where it qualifies
117/// whatever the declarator arrives at. `_Atomic(T)`, with parentheses, is a different thing and
118/// is [`TypeSpec::Atomic`], because it constructs a type that may not have the same alignment
119/// as `T`. Both spellings mean the same in the end and the difference matters to the parser.
120#[derive(Debug, Clone, Copy, PartialEq, Eq, Default)]
121pub struct Quals(u8);
122
123impl Quals {
124    /// No qualifiers.
125    pub const NONE: Quals = Quals(0);
126    /// `const`.
127    pub const CONST: Quals = Quals(1);
128    /// `volatile`.
129    pub const VOLATILE: Quals = Quals(2);
130    /// `restrict`, which is only a keyword from C99.
131    pub const RESTRICT: Quals = Quals(4);
132    /// `_Atomic` without parentheses.
133    pub const ATOMIC: Quals = Quals(8);
134
135    /// Whether every qualifier in `other` is set here.
136    #[inline]
137    #[must_use]
138    pub const fn has(self, other: Quals) -> bool {
139        self.0 & other.0 == other.0
140    }
141
142    /// This set with `other` added.
143    #[inline]
144    #[must_use]
145    pub const fn with(self, other: Quals) -> Quals {
146        Quals(self.0 | other.0)
147    }
148
149    /// Whether nothing is qualified.
150    #[inline]
151    #[must_use]
152    pub const fn is_none(self) -> bool {
153        self.0 == 0
154    }
155}
156
157/// The function specifiers, as a set.
158#[derive(Debug, Clone, Copy, PartialEq, Eq, Default)]
159pub struct FuncSpecs(u8);
160
161impl FuncSpecs {
162    /// Neither.
163    pub const NONE: FuncSpecs = FuncSpecs(0);
164    /// `inline`.
165    pub const INLINE: FuncSpecs = FuncSpecs(1);
166    /// `_Noreturn`, which C23 deprecated in favour of the attribute and which every real
167    /// header still uses.
168    pub const NORETURN: FuncSpecs = FuncSpecs(2);
169
170    /// Whether every specifier in `other` is set here.
171    #[inline]
172    #[must_use]
173    pub const fn has(self, other: FuncSpecs) -> bool {
174        self.0 & other.0 == other.0
175    }
176
177    /// This set with `other` added.
178    #[inline]
179    #[must_use]
180    pub const fn with(self, other: FuncSpecs) -> FuncSpecs {
181        FuncSpecs(self.0 | other.0)
182    }
183
184    /// Whether neither was written.
185    #[inline]
186    #[must_use]
187    pub const fn is_none(self) -> bool {
188        self.0 == 0
189    }
190}
191
192/// An `alignas` specifier, which takes either a type or a constant expression.
193#[derive(Debug, Clone, Copy, PartialEq, Eq)]
194pub enum AlignSpec {
195    /// `alignas(T)`, which means the alignment of `T`.
196    Type(TypeNameId),
197    /// `alignas(N)`.
198    Expr(ExprId),
199}
200
201/// What type a declaration named.
202#[derive(Debug, Clone, Copy, PartialEq, Eq)]
203pub enum TypeSpec {
204    /// Nothing was written, which is `int` before C23 with a warning and an error in it.
205    None,
206    /// One or more of the keywords that name a built-in type.
207    Builtin(Builtin),
208    /// `struct` or `union`, with or without a tag, with or without a body.
209    Record {
210        /// Which of the two.
211        kind: RecordKind,
212        /// The tag, absent for an anonymous one.
213        tag: Option<Symbol>,
214        /// The members, absent when this is a reference to a tag rather than a definition. An
215        /// empty list is a definition of an empty structure, which is a GNU extension, so the
216        /// difference between `struct S;` and `struct S {};` has to survive.
217        fields: Option<MemberList>,
218        /// Attributes on the tag itself, which GCC allows both before and after the body.
219        attrs: AttrList,
220        /// The `#pragma pack` in effect where the body closed, in bytes, which is not written
221        /// on the declaration and which nothing else in the tree can recover.
222        pack: Option<u32>,
223    },
224    /// `enum`, with C23's optional underlying type.
225    Enum {
226        /// The tag, absent for an anonymous one.
227        tag: Option<Symbol>,
228        /// The enumerators, absent when this is a reference rather than a definition.
229        enumerators: Option<EnumeratorList>,
230        /// The `: T` that C23 added, which fixes the representation instead of leaving it to
231        /// the implementation.
232        underlying: Option<TypeNameId>,
233        /// Attributes on the tag itself.
234        attrs: AttrList,
235    },
236    /// An identifier the parser's scope stack said was a typedef name.
237    Typedef(Symbol),
238    /// `typeof` or `typeof_unqual`, or their `__typeof__` spellings.
239    Typeof {
240        /// Whether the qualifiers come off, which is what `typeof_unqual` is for.
241        unqual: bool,
242        /// The operand, which is an expression or a type name and in the expression case is
243        /// never evaluated.
244        operand: TypeofArg,
245    },
246    /// `_Atomic(T)`, the type constructor rather than the qualifier.
247    Atomic(TypeNameId),
248    /// A type deduced from an initializer, which is C23's `auto` and GNU's `__auto_type`.
249    Auto(Deduction),
250    /// `__builtin_va_list`, whose type is the target's rather than anything the source said.
251    ///
252    /// gcc declares it as a typedef name that is always in scope. It is a keyword here instead,
253    /// which is the same thing seen from the parser's side and one fewer name that a program can
254    /// shadow by accident, and it means the parser does not have to be handed a scope with
255    /// something already in it before it reads the first token.
256    VaList,
257}
258
259/// Which of the two spellings asked for a deduced type.
260///
261/// They deduce the same type and are not the same specifier: gcc names the one that was written
262/// in everything it says about a declaration, and C23's is in scope inside its own initializer
263/// while GNU's is not.
264#[derive(Debug, Clone, Copy, PartialEq, Eq)]
265pub enum Deduction {
266    /// C23's `auto`, which is the storage class keyword with no other type specifier next to it.
267    Auto,
268    /// GNU's `__auto_type`, which C23's is modelled on and which every dialect has.
269    AutoType,
270}
271
272impl Deduction {
273    /// How it was written, for the messages that name it.
274    #[must_use]
275    pub const fn spelling(self) -> &'static str {
276        match self {
277            Deduction::Auto => "auto",
278            Deduction::AutoType => "__auto_type",
279        }
280    }
281}
282
283/// Which of the two record kinds.
284#[derive(Debug, Clone, Copy, PartialEq, Eq)]
285pub enum RecordKind {
286    /// `struct`.
287    Struct,
288    /// `union`.
289    Union,
290}
291
292impl RecordKind {
293    /// The keyword, for the printer and for diagnostics.
294    #[must_use]
295    pub const fn spelling(self) -> &'static str {
296        match self {
297            RecordKind::Struct => "struct",
298            RecordKind::Union => "union",
299        }
300    }
301}
302
303/// What a `typeof` was applied to.
304#[derive(Debug, Clone, Copy, PartialEq, Eq)]
305pub enum TypeofArg {
306    /// An expression, which is not evaluated.
307    Expr(ExprId),
308    /// A type name.
309    Type(TypeNameId),
310}
311
312/// The keywords naming a built-in type, as the multiset that was written.
313///
314/// Kept rather than resolved, because the parser reads one keyword at a time and cannot tell
315/// what `long` will turn out to mean until the specifier list ends. [`Builtin::add`] catches a
316/// keyword written twice, at the place it is written, and [`Builtin::resolve`] catches a
317/// combination that names no type once there are no more keywords coming.
318#[derive(Debug, Clone, Copy, PartialEq, Eq, Default)]
319pub struct Builtin {
320    /// Which keywords were written.
321    pub set: BuiltinSet,
322    /// How many times `long` was written, since it is the one that may repeat.
323    pub longs: u8,
324    /// The width of the `_BitInt`, for the one keyword here that takes one.
325    pub width: Option<ExprId>,
326}
327
328/// The set of built-in type keywords, without the count of `long`.
329#[derive(Debug, Clone, Copy, PartialEq, Eq, Default)]
330pub struct BuiltinSet(u32);
331
332impl BuiltinSet {
333    /// Nothing.
334    pub const NONE: BuiltinSet = BuiltinSet(0);
335    /// `void`.
336    pub const VOID: BuiltinSet = BuiltinSet(1 << 0);
337    /// `bool`, in either spelling.
338    pub const BOOL: BuiltinSet = BuiltinSet(1 << 1);
339    /// `char`.
340    pub const CHAR: BuiltinSet = BuiltinSet(1 << 2);
341    /// `short`.
342    pub const SHORT: BuiltinSet = BuiltinSet(1 << 3);
343    /// `int`.
344    pub const INT: BuiltinSet = BuiltinSet(1 << 4);
345    /// `long`, however many times it was written.
346    pub const LONG: BuiltinSet = BuiltinSet(1 << 5);
347    /// `signed`.
348    pub const SIGNED: BuiltinSet = BuiltinSet(1 << 6);
349    /// `unsigned`.
350    pub const UNSIGNED: BuiltinSet = BuiltinSet(1 << 7);
351    /// `float`.
352    pub const FLOAT: BuiltinSet = BuiltinSet(1 << 8);
353    /// `double`.
354    pub const DOUBLE: BuiltinSet = BuiltinSet(1 << 9);
355    /// `_Complex`.
356    pub const COMPLEX: BuiltinSet = BuiltinSet(1 << 10);
357    /// `_Imaginary`.
358    pub const IMAGINARY: BuiltinSet = BuiltinSet(1 << 11);
359    /// `__int128`.
360    pub const INT128: BuiltinSet = BuiltinSet(1 << 12);
361    /// `_Float16`.
362    pub const FLOAT16: BuiltinSet = BuiltinSet(1 << 13);
363    /// `_Float32`.
364    pub const FLOAT32: BuiltinSet = BuiltinSet(1 << 14);
365    /// `_Float64`.
366    pub const FLOAT64: BuiltinSet = BuiltinSet(1 << 15);
367    /// `_Float128`, whose `__float128` spelling is the same type.
368    pub const FLOAT128: BuiltinSet = BuiltinSet(1 << 16);
369    /// `_Float32x`.
370    pub const FLOAT32X: BuiltinSet = BuiltinSet(1 << 17);
371    /// `_Float64x`.
372    pub const FLOAT64X: BuiltinSet = BuiltinSet(1 << 18);
373    /// `_Float128x`.
374    pub const FLOAT128X: BuiltinSet = BuiltinSet(1 << 19);
375    /// `__float80`.
376    pub const FLOAT80: BuiltinSet = BuiltinSet(1 << 20);
377    /// `_Decimal32`.
378    pub const DECIMAL32: BuiltinSet = BuiltinSet(1 << 21);
379    /// `_Decimal64`.
380    pub const DECIMAL64: BuiltinSet = BuiltinSet(1 << 22);
381    /// `_Decimal128`.
382    pub const DECIMAL128: BuiltinSet = BuiltinSet(1 << 23);
383    /// `_BitInt`, whose width is kept next to the set rather than in it.
384    pub const BIT_INT: BuiltinSet = BuiltinSet(1 << 24);
385
386    /// Everything that names a decimal floating type.
387    const DECIMALS: BuiltinSet =
388        BuiltinSet(Self::DECIMAL32.0 | Self::DECIMAL64.0 | Self::DECIMAL128.0);
389    /// Everything that names one of the `_FloatN` and `_FloatNx` types.
390    const EXTENDED: BuiltinSet = BuiltinSet(
391        Self::FLOAT16.0
392            | Self::FLOAT32.0
393            | Self::FLOAT64.0
394            | Self::FLOAT128.0
395            | Self::FLOAT32X.0
396            | Self::FLOAT64X.0
397            | Self::FLOAT128X.0
398            | Self::FLOAT80.0,
399    );
400    /// Everything that can be part of a standard integer type.
401    const INTEGER: BuiltinSet =
402        BuiltinSet(Self::SHORT.0 | Self::INT.0 | Self::LONG.0 | Self::SIGNED.0 | Self::UNSIGNED.0);
403
404    /// Whether every keyword in `other` is set here.
405    #[inline]
406    #[must_use]
407    pub const fn has(self, other: BuiltinSet) -> bool {
408        self.0 & other.0 == other.0
409    }
410
411    /// Whether any keyword in `other` is set here.
412    #[inline]
413    #[must_use]
414    pub const fn has_any(self, other: BuiltinSet) -> bool {
415        self.0 & other.0 != 0
416    }
417
418    /// This set with `other` added.
419    #[inline]
420    #[must_use]
421    pub const fn with(self, other: BuiltinSet) -> BuiltinSet {
422        BuiltinSet(self.0 | other.0)
423    }
424
425    /// This set with everything in `other` taken out.
426    #[inline]
427    #[must_use]
428    pub const fn without(self, other: BuiltinSet) -> BuiltinSet {
429        BuiltinSet(self.0 & !other.0)
430    }
431
432    /// Whether nothing was written.
433    #[inline]
434    #[must_use]
435    pub const fn is_none(self) -> bool {
436        self.0 == 0
437    }
438}
439
440/// Why a built-in type keyword could not be added.
441#[derive(Debug, Clone, Copy, PartialEq, Eq)]
442pub enum BuiltinError {
443    /// The keyword was already written, and it is not `long`.
444    Duplicate,
445    /// A third `long`, which no type has.
446    TooManyLongs,
447}
448
449impl Builtin {
450    /// Nothing written yet.
451    pub const NONE: Builtin = Builtin { set: BuiltinSet::NONE, longs: 0, width: None };
452
453    /// This with one more keyword.
454    ///
455    /// `long` is the only keyword that may be written twice, so everything else is a duplicate
456    /// the second time and is reported at the keyword rather than at the end of the specifier
457    /// list, which is where the second half of the checking happens.
458    ///
459    /// # Errors
460    ///
461    /// [`BuiltinError::Duplicate`] for a repeat, and [`BuiltinError::TooManyLongs`] for a third
462    /// `long`.
463    pub const fn add(self, which: BuiltinSet) -> Result<Builtin, BuiltinError> {
464        if which.0 == BuiltinSet::LONG.0 {
465            if self.longs >= 2 {
466                return Err(BuiltinError::TooManyLongs);
467            }
468            let set = self.set.with(which);
469            return Ok(Builtin { set, longs: self.longs + 1, width: self.width });
470        }
471        if self.set.has(which) {
472            return Err(BuiltinError::Duplicate);
473        }
474        Ok(Builtin { set: self.set.with(which), longs: self.longs, width: self.width })
475    }
476
477    /// This with `_BitInt(width)` written into it.
478    ///
479    /// The width is the one thing a type keyword carries, and it is kept here rather than in a
480    /// specifier of its own so that `unsigned _BitInt(8)` and `_BitInt(8) unsigned` are the
481    /// same declaration, which is what they are: a sign and a width may be written either way
482    /// round, and neither of them names a type on its own.
483    ///
484    /// # Errors
485    ///
486    /// [`BuiltinError::Duplicate`] when `_BitInt` was already written.
487    pub const fn add_bit_int(self, width: ExprId) -> Result<Builtin, BuiltinError> {
488        if self.set.has(BuiltinSet::BIT_INT) {
489            return Err(BuiltinError::Duplicate);
490        }
491        let set = self.set.with(BuiltinSet::BIT_INT);
492        Ok(Builtin { set, longs: self.longs, width: Some(width) })
493    }
494
495    /// Whether any built-in keyword has been written.
496    #[must_use]
497    pub const fn is_none(self) -> bool {
498        self.set.is_none()
499    }
500
501    /// The type this combination of keywords names, and `None` if it names no type.
502    ///
503    /// The table is the one in 6.7.2 plus the GNU and C23 rows: `_Complex` and `_Imaginary` on
504    /// the floating types, `_Complex` on the integer ones which GCC also allows, `__int128`
505    /// with a sign, and the `_FloatN` and `_DecimalN` families which stand alone.
506    #[must_use]
507    pub fn resolve(self) -> Option<Basic> {
508        let set = self.set;
509        let longs = self.longs;
510
511        let complexity = match (set.has(BuiltinSet::COMPLEX), set.has(BuiltinSet::IMAGINARY)) {
512            (true, true) => return None,
513            (true, false) => Complexity::Complex,
514            (false, true) => Complexity::Imaginary,
515            (false, false) => Complexity::Real,
516        };
517        let set = set.without(BuiltinSet::COMPLEX.with(BuiltinSet::IMAGINARY));
518        let basic = |scalar| Some(Basic { scalar, complexity });
519        let real = |scalar| {
520            if complexity == Complexity::Real { Some(Basic { scalar, complexity }) } else { None }
521        };
522
523        if set.has(BuiltinSet::SIGNED) && set.has(BuiltinSet::UNSIGNED) {
524            return None;
525        }
526        let unsigned = set.has(BuiltinSet::UNSIGNED);
527        let signs = BuiltinSet::SIGNED.with(BuiltinSet::UNSIGNED);
528
529        // Everything below is "these keywords and nothing else", which is what makes `void int`
530        // and `char short` fail here rather than needing a rule each.
531        if set.has(BuiltinSet::VOID) {
532            return if set == BuiltinSet::VOID && longs == 0 { real(Scalar::Void) } else { None };
533        }
534        if set.has(BuiltinSet::BOOL) {
535            return if set == BuiltinSet::BOOL && longs == 0 { real(Scalar::Bool) } else { None };
536        }
537        if set.has(BuiltinSet::CHAR) {
538            if set.without(signs) != BuiltinSet::CHAR || longs != 0 {
539                return None;
540            }
541            return real(match (set.has(BuiltinSet::SIGNED), unsigned) {
542                (true, _) => Scalar::SignedChar,
543                (_, true) => Scalar::UnsignedChar,
544                _ => Scalar::Char,
545            });
546        }
547        if set.has(BuiltinSet::INT128) {
548            if set.without(signs) != BuiltinSet::INT128 || longs != 0 {
549                return None;
550            }
551            return real(if unsigned { Scalar::UnsignedInt128 } else { Scalar::Int128 });
552        }
553        if set.has(BuiltinSet::BIT_INT) {
554            if set.without(signs) != BuiltinSet::BIT_INT || longs != 0 {
555                return None;
556            }
557            // A width of nothing is a `_BitInt` whose parenthesised part did not parse, which
558            // the parser has already reported and which names no type here either.
559            let width = self.width?;
560            return real(Scalar::BitInt { width, unsigned });
561        }
562        if set.has_any(BuiltinSet::DECIMALS) {
563            if longs != 0 || complexity != Complexity::Real {
564                return None;
565            }
566            return match set {
567                s if s == BuiltinSet::DECIMAL32 => real(Scalar::Decimal32),
568                s if s == BuiltinSet::DECIMAL64 => real(Scalar::Decimal64),
569                s if s == BuiltinSet::DECIMAL128 => real(Scalar::Decimal128),
570                _ => None,
571            };
572        }
573        if set.has_any(BuiltinSet::EXTENDED) {
574            if longs != 0 {
575                return None;
576            }
577            return match set {
578                s if s == BuiltinSet::FLOAT16 => basic(Scalar::Float16),
579                s if s == BuiltinSet::FLOAT32 => basic(Scalar::Float32),
580                s if s == BuiltinSet::FLOAT64 => basic(Scalar::Float64),
581                s if s == BuiltinSet::FLOAT128 => basic(Scalar::Float128),
582                s if s == BuiltinSet::FLOAT32X => basic(Scalar::Float32x),
583                s if s == BuiltinSet::FLOAT64X => basic(Scalar::Float64x),
584                s if s == BuiltinSet::FLOAT128X => basic(Scalar::Float128x),
585                s if s == BuiltinSet::FLOAT80 => basic(Scalar::Float80),
586                _ => None,
587            };
588        }
589        if set.has(BuiltinSet::FLOAT) {
590            return if set == BuiltinSet::FLOAT && longs == 0 {
591                basic(Scalar::Float)
592            } else {
593                None
594            };
595        }
596        if set.has(BuiltinSet::DOUBLE) {
597            if set.without(BuiltinSet::LONG) != BuiltinSet::DOUBLE {
598                return None;
599            }
600            return match longs {
601                0 => basic(Scalar::Double),
602                1 => basic(Scalar::LongDouble),
603                _ => None,
604            };
605        }
606        if set.is_none() {
607            return None;
608        }
609        // What is left is the standard integer types, where `int` is implied by any of the
610        // others and every combination is legal except `short long`.
611        if !BuiltinSet::INTEGER.has(set) {
612            return None;
613        }
614        if set.has(BuiltinSet::SHORT) {
615            if longs != 0 {
616                return None;
617            }
618            return basic(if unsigned { Scalar::UnsignedShort } else { Scalar::Short });
619        }
620        match longs {
621            0 => basic(if unsigned { Scalar::UnsignedInt } else { Scalar::Int }),
622            1 => basic(if unsigned { Scalar::UnsignedLong } else { Scalar::Long }),
623            2 => basic(if unsigned { Scalar::UnsignedLongLong } else { Scalar::LongLong }),
624            _ => None,
625        }
626    }
627}
628
629/// A built-in type, once the keywords have been read together.
630#[derive(Debug, Clone, Copy, PartialEq, Eq)]
631pub struct Basic {
632    /// The type itself.
633    pub scalar: Scalar,
634    /// Whether `_Complex` or `_Imaginary` was written.
635    pub complexity: Complexity,
636}
637
638/// Whether a built-in type is real, complex or imaginary.
639#[derive(Debug, Clone, Copy, PartialEq, Eq)]
640pub enum Complexity {
641    /// Neither keyword.
642    Real,
643    /// `_Complex`.
644    Complex,
645    /// `_Imaginary`, which GCC parses and has never implemented.
646    Imaginary,
647}
648
649/// A built-in type named by keywords, with the sign folded in.
650///
651/// `char` is here three times because plain `char` is a third type distinct from both
652/// `signed char` and `unsigned char`, however it is represented on the target.
653#[derive(Debug, Clone, Copy, PartialEq, Eq)]
654pub enum Scalar {
655    /// `void`.
656    Void,
657    /// `bool`.
658    Bool,
659    /// `char`.
660    Char,
661    /// `signed char`.
662    SignedChar,
663    /// `unsigned char`.
664    UnsignedChar,
665    /// `short`.
666    Short,
667    /// `unsigned short`.
668    UnsignedShort,
669    /// `int`.
670    Int,
671    /// `unsigned int`.
672    UnsignedInt,
673    /// `long`.
674    Long,
675    /// `unsigned long`.
676    UnsignedLong,
677    /// `long long`.
678    LongLong,
679    /// `unsigned long long`.
680    UnsignedLongLong,
681    /// `__int128`.
682    Int128,
683    /// `unsigned __int128`.
684    UnsignedInt128,
685    /// `_BitInt(N)`, with the sign written next to it folded in like every other sign here.
686    BitInt {
687        /// The width, which is a constant expression that nothing has evaluated yet.
688        width: ExprId,
689        /// Whether `unsigned` was written, which changes the least width there is as well as
690        /// the range: a signed one needs a bit for the sign and so is never narrower than two.
691        unsigned: bool,
692    },
693    /// `float`.
694    Float,
695    /// `double`.
696    Double,
697    /// `long double`.
698    LongDouble,
699    /// `_Float16`.
700    Float16,
701    /// `_Float32`.
702    Float32,
703    /// `_Float64`.
704    Float64,
705    /// `_Float128`.
706    Float128,
707    /// `_Float32x`.
708    Float32x,
709    /// `_Float64x`.
710    Float64x,
711    /// `_Float128x`.
712    Float128x,
713    /// `__float80`.
714    Float80,
715    /// `_Decimal32`.
716    Decimal32,
717    /// `_Decimal64`.
718    Decimal64,
719    /// `_Decimal128`.
720    Decimal128,
721}
722
723#[cfg(test)]
724mod tests {
725    use super::*;
726
727    fn resolve(keywords: &[BuiltinSet]) -> Option<Basic> {
728        let mut b = Builtin::NONE;
729        for &k in keywords {
730            b = b.add(k).expect("keyword rejected");
731        }
732        b.resolve()
733    }
734
735    fn real(keywords: &[BuiltinSet]) -> Option<Scalar> {
736        resolve(keywords).filter(|b| b.complexity == Complexity::Real).map(|b| b.scalar)
737    }
738
739    #[test]
740    fn the_plain_integer_spellings() {
741        assert_eq!(real(&[BuiltinSet::INT]), Some(Scalar::Int));
742        assert_eq!(real(&[BuiltinSet::SIGNED]), Some(Scalar::Int));
743        assert_eq!(real(&[BuiltinSet::UNSIGNED]), Some(Scalar::UnsignedInt));
744        assert_eq!(real(&[BuiltinSet::SIGNED, BuiltinSet::INT]), Some(Scalar::Int));
745        assert_eq!(real(&[BuiltinSet::SHORT]), Some(Scalar::Short));
746        assert_eq!(real(&[BuiltinSet::SHORT, BuiltinSet::INT]), Some(Scalar::Short));
747        assert_eq!(
748            real(&[BuiltinSet::UNSIGNED, BuiltinSet::SHORT, BuiltinSet::INT]),
749            Some(Scalar::UnsignedShort)
750        );
751    }
752
753    #[test]
754    fn long_counts_rather_than_repeats() {
755        assert_eq!(real(&[BuiltinSet::LONG]), Some(Scalar::Long));
756        assert_eq!(real(&[BuiltinSet::LONG, BuiltinSet::LONG]), Some(Scalar::LongLong));
757        assert_eq!(
758            real(&[BuiltinSet::UNSIGNED, BuiltinSet::LONG, BuiltinSet::LONG, BuiltinSet::INT]),
759            Some(Scalar::UnsignedLongLong)
760        );
761        let three = Builtin::NONE
762            .add(BuiltinSet::LONG)
763            .and_then(|b| b.add(BuiltinSet::LONG))
764            .and_then(|b| b.add(BuiltinSet::LONG));
765        assert_eq!(three, Err(BuiltinError::TooManyLongs));
766    }
767
768    #[test]
769    fn a_repeated_keyword_is_caught_where_it_is_written() {
770        let twice = Builtin::NONE.add(BuiltinSet::INT).and_then(|b| b.add(BuiltinSet::INT));
771        assert_eq!(twice, Err(BuiltinError::Duplicate));
772    }
773
774    #[test]
775    fn plain_char_is_its_own_type() {
776        assert_eq!(real(&[BuiltinSet::CHAR]), Some(Scalar::Char));
777        assert_eq!(real(&[BuiltinSet::SIGNED, BuiltinSet::CHAR]), Some(Scalar::SignedChar));
778        assert_eq!(real(&[BuiltinSet::UNSIGNED, BuiltinSet::CHAR]), Some(Scalar::UnsignedChar));
779        assert_eq!(real(&[BuiltinSet::CHAR, BuiltinSet::INT]), None);
780        assert_eq!(real(&[BuiltinSet::CHAR, BuiltinSet::LONG]), None);
781    }
782
783    #[test]
784    fn long_double_is_a_double_with_one_long() {
785        assert_eq!(real(&[BuiltinSet::DOUBLE]), Some(Scalar::Double));
786        assert_eq!(real(&[BuiltinSet::LONG, BuiltinSet::DOUBLE]), Some(Scalar::LongDouble));
787        assert_eq!(real(&[BuiltinSet::LONG, BuiltinSet::LONG, BuiltinSet::DOUBLE]), None);
788        assert_eq!(real(&[BuiltinSet::LONG, BuiltinSet::FLOAT]), None);
789        assert_eq!(real(&[BuiltinSet::DOUBLE, BuiltinSet::INT]), None);
790    }
791
792    #[test]
793    fn complex_is_a_modifier_and_not_a_type() {
794        assert_eq!(
795            resolve(&[BuiltinSet::COMPLEX, BuiltinSet::DOUBLE]),
796            Some(Basic { scalar: Scalar::Double, complexity: Complexity::Complex })
797        );
798        assert_eq!(
799            resolve(&[BuiltinSet::LONG, BuiltinSet::DOUBLE, BuiltinSet::IMAGINARY]),
800            Some(Basic { scalar: Scalar::LongDouble, complexity: Complexity::Imaginary })
801        );
802        // GCC accepts a complex integer type, so this is not an error here either.
803        assert_eq!(
804            resolve(&[BuiltinSet::COMPLEX, BuiltinSet::INT]),
805            Some(Basic { scalar: Scalar::Int, complexity: Complexity::Complex })
806        );
807        assert_eq!(resolve(&[BuiltinSet::COMPLEX, BuiltinSet::IMAGINARY, BuiltinSet::FLOAT]), None);
808        // There is no complex decimal type in any dialect.
809        assert_eq!(resolve(&[BuiltinSet::COMPLEX, BuiltinSet::DECIMAL64]), None);
810    }
811
812    #[test]
813    fn the_extended_types_stand_alone_or_with_complex() {
814        assert_eq!(real(&[BuiltinSet::FLOAT128]), Some(Scalar::Float128));
815        assert_eq!(
816            resolve(&[BuiltinSet::COMPLEX, BuiltinSet::FLOAT128]),
817            Some(Basic { scalar: Scalar::Float128, complexity: Complexity::Complex })
818        );
819        assert_eq!(real(&[BuiltinSet::FLOAT32X]), Some(Scalar::Float32x));
820        assert_eq!(real(&[BuiltinSet::FLOAT128X]), Some(Scalar::Float128x));
821        assert_eq!(real(&[BuiltinSet::FLOAT16, BuiltinSet::INT]), None);
822        assert_eq!(real(&[BuiltinSet::FLOAT32, BuiltinSet::FLOAT64]), None);
823    }
824
825    #[test]
826    fn the_wide_integers_take_a_sign_and_nothing_else() {
827        assert_eq!(real(&[BuiltinSet::INT128]), Some(Scalar::Int128));
828        assert_eq!(real(&[BuiltinSet::UNSIGNED, BuiltinSet::INT128]), Some(Scalar::UnsignedInt128));
829        assert_eq!(real(&[BuiltinSet::INT128, BuiltinSet::INT]), None);
830    }
831
832    #[test]
833    fn void_and_bool_take_nothing() {
834        assert_eq!(real(&[BuiltinSet::VOID]), Some(Scalar::Void));
835        assert_eq!(real(&[BuiltinSet::BOOL]), Some(Scalar::Bool));
836        assert_eq!(real(&[BuiltinSet::VOID, BuiltinSet::INT]), None);
837        assert_eq!(real(&[BuiltinSet::UNSIGNED, BuiltinSet::BOOL]), None);
838    }
839
840    #[test]
841    fn two_signs_name_no_type() {
842        assert_eq!(real(&[BuiltinSet::SIGNED, BuiltinSet::UNSIGNED]), None);
843    }
844
845    #[test]
846    fn no_keywords_at_all_names_no_type() {
847        assert_eq!(Builtin::NONE.resolve(), None);
848        assert!(Builtin::NONE.is_none());
849    }
850
851    #[test]
852    fn short_and_long_do_not_go_together() {
853        assert_eq!(real(&[BuiltinSet::SHORT, BuiltinSet::LONG]), None);
854    }
855
856    #[test]
857    fn qualifier_sets_add_up() {
858        let q = Quals::NONE.with(Quals::CONST).with(Quals::VOLATILE);
859        assert!(q.has(Quals::CONST));
860        assert!(q.has(Quals::VOLATILE));
861        assert!(!q.has(Quals::RESTRICT));
862        assert!(Quals::NONE.is_none());
863        assert!(!q.is_none());
864    }
865
866    #[test]
867    fn function_specifier_sets_add_up() {
868        let f = FuncSpecs::NONE.with(FuncSpecs::INLINE);
869        assert!(f.has(FuncSpecs::INLINE));
870        assert!(!f.has(FuncSpecs::NORETURN));
871        assert!(FuncSpecs::NONE.is_none());
872    }
873}