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