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}
246
247/// Which of the two spellings asked for a deduced type.
248///
249/// They deduce the same type and are not the same specifier: gcc names the one that was written
250/// in everything it says about a declaration, and C23's is in scope inside its own initializer
251/// while GNU's is not.
252#[derive(Debug, Clone, Copy, PartialEq, Eq)]
253pub enum Deduction {
254    /// C23's `auto`, which is the storage class keyword with no other type specifier next to it.
255    Auto,
256    /// GNU's `__auto_type`, which C23's is modelled on and which every dialect has.
257    AutoType,
258}
259
260impl Deduction {
261    /// How it was written, for the messages that name it.
262    #[must_use]
263    pub const fn spelling(self) -> &'static str {
264        match self {
265            Deduction::Auto => "auto",
266            Deduction::AutoType => "__auto_type",
267        }
268    }
269}
270
271/// Which of the two record kinds.
272#[derive(Debug, Clone, Copy, PartialEq, Eq)]
273pub enum RecordKind {
274    /// `struct`.
275    Struct,
276    /// `union`.
277    Union,
278}
279
280impl RecordKind {
281    /// The keyword, for the printer and for diagnostics.
282    #[must_use]
283    pub const fn spelling(self) -> &'static str {
284        match self {
285            RecordKind::Struct => "struct",
286            RecordKind::Union => "union",
287        }
288    }
289}
290
291/// What a `typeof` was applied to.
292#[derive(Debug, Clone, Copy, PartialEq, Eq)]
293pub enum TypeofArg {
294    /// An expression, which is not evaluated.
295    Expr(ExprId),
296    /// A type name.
297    Type(TypeNameId),
298}
299
300/// The keywords naming a built-in type, as the multiset that was written.
301///
302/// Kept rather than resolved, because the parser reads one keyword at a time and cannot tell
303/// what `long` will turn out to mean until the specifier list ends. [`Builtin::add`] catches a
304/// keyword written twice, at the place it is written, and [`Builtin::resolve`] catches a
305/// combination that names no type once there are no more keywords coming.
306#[derive(Debug, Clone, Copy, PartialEq, Eq, Default)]
307pub struct Builtin {
308    /// Which keywords were written.
309    pub set: BuiltinSet,
310    /// How many times `long` was written, since it is the one that may repeat.
311    pub longs: u8,
312    /// The width of the `_BitInt`, for the one keyword here that takes one.
313    pub width: Option<ExprId>,
314}
315
316/// The set of built-in type keywords, without the count of `long`.
317#[derive(Debug, Clone, Copy, PartialEq, Eq, Default)]
318pub struct BuiltinSet(u32);
319
320impl BuiltinSet {
321    /// Nothing.
322    pub const NONE: BuiltinSet = BuiltinSet(0);
323    /// `void`.
324    pub const VOID: BuiltinSet = BuiltinSet(1 << 0);
325    /// `bool`, in either spelling.
326    pub const BOOL: BuiltinSet = BuiltinSet(1 << 1);
327    /// `char`.
328    pub const CHAR: BuiltinSet = BuiltinSet(1 << 2);
329    /// `short`.
330    pub const SHORT: BuiltinSet = BuiltinSet(1 << 3);
331    /// `int`.
332    pub const INT: BuiltinSet = BuiltinSet(1 << 4);
333    /// `long`, however many times it was written.
334    pub const LONG: BuiltinSet = BuiltinSet(1 << 5);
335    /// `signed`.
336    pub const SIGNED: BuiltinSet = BuiltinSet(1 << 6);
337    /// `unsigned`.
338    pub const UNSIGNED: BuiltinSet = BuiltinSet(1 << 7);
339    /// `float`.
340    pub const FLOAT: BuiltinSet = BuiltinSet(1 << 8);
341    /// `double`.
342    pub const DOUBLE: BuiltinSet = BuiltinSet(1 << 9);
343    /// `_Complex`.
344    pub const COMPLEX: BuiltinSet = BuiltinSet(1 << 10);
345    /// `_Imaginary`.
346    pub const IMAGINARY: BuiltinSet = BuiltinSet(1 << 11);
347    /// `__int128`.
348    pub const INT128: BuiltinSet = BuiltinSet(1 << 12);
349    /// `_Float16`.
350    pub const FLOAT16: BuiltinSet = BuiltinSet(1 << 13);
351    /// `_Float32`.
352    pub const FLOAT32: BuiltinSet = BuiltinSet(1 << 14);
353    /// `_Float64`.
354    pub const FLOAT64: BuiltinSet = BuiltinSet(1 << 15);
355    /// `_Float128`, whose `__float128` spelling is the same type.
356    pub const FLOAT128: BuiltinSet = BuiltinSet(1 << 16);
357    /// `_Float32x`.
358    pub const FLOAT32X: BuiltinSet = BuiltinSet(1 << 17);
359    /// `_Float64x`.
360    pub const FLOAT64X: BuiltinSet = BuiltinSet(1 << 18);
361    /// `_Float128x`.
362    pub const FLOAT128X: BuiltinSet = BuiltinSet(1 << 19);
363    /// `__float80`.
364    pub const FLOAT80: BuiltinSet = BuiltinSet(1 << 20);
365    /// `_Decimal32`.
366    pub const DECIMAL32: BuiltinSet = BuiltinSet(1 << 21);
367    /// `_Decimal64`.
368    pub const DECIMAL64: BuiltinSet = BuiltinSet(1 << 22);
369    /// `_Decimal128`.
370    pub const DECIMAL128: BuiltinSet = BuiltinSet(1 << 23);
371    /// `_BitInt`, whose width is kept next to the set rather than in it.
372    pub const BIT_INT: BuiltinSet = BuiltinSet(1 << 24);
373
374    /// Everything that names a decimal floating type.
375    const DECIMALS: BuiltinSet =
376        BuiltinSet(Self::DECIMAL32.0 | Self::DECIMAL64.0 | Self::DECIMAL128.0);
377    /// Everything that names one of the `_FloatN` and `_FloatNx` types.
378    const EXTENDED: BuiltinSet = BuiltinSet(
379        Self::FLOAT16.0
380            | Self::FLOAT32.0
381            | Self::FLOAT64.0
382            | Self::FLOAT128.0
383            | Self::FLOAT32X.0
384            | Self::FLOAT64X.0
385            | Self::FLOAT128X.0
386            | Self::FLOAT80.0,
387    );
388    /// Everything that can be part of a standard integer type.
389    const INTEGER: BuiltinSet =
390        BuiltinSet(Self::SHORT.0 | Self::INT.0 | Self::LONG.0 | Self::SIGNED.0 | Self::UNSIGNED.0);
391
392    /// Whether every keyword in `other` is set here.
393    #[inline]
394    #[must_use]
395    pub const fn has(self, other: BuiltinSet) -> bool {
396        self.0 & other.0 == other.0
397    }
398
399    /// Whether any keyword in `other` is set here.
400    #[inline]
401    #[must_use]
402    pub const fn has_any(self, other: BuiltinSet) -> bool {
403        self.0 & other.0 != 0
404    }
405
406    /// This set with `other` added.
407    #[inline]
408    #[must_use]
409    pub const fn with(self, other: BuiltinSet) -> BuiltinSet {
410        BuiltinSet(self.0 | other.0)
411    }
412
413    /// This set with everything in `other` taken out.
414    #[inline]
415    #[must_use]
416    pub const fn without(self, other: BuiltinSet) -> BuiltinSet {
417        BuiltinSet(self.0 & !other.0)
418    }
419
420    /// Whether nothing was written.
421    #[inline]
422    #[must_use]
423    pub const fn is_none(self) -> bool {
424        self.0 == 0
425    }
426}
427
428/// Why a built-in type keyword could not be added.
429#[derive(Debug, Clone, Copy, PartialEq, Eq)]
430pub enum BuiltinError {
431    /// The keyword was already written, and it is not `long`.
432    Duplicate,
433    /// A third `long`, which no type has.
434    TooManyLongs,
435}
436
437impl Builtin {
438    /// Nothing written yet.
439    pub const NONE: Builtin = Builtin { set: BuiltinSet::NONE, longs: 0, width: None };
440
441    /// This with one more keyword.
442    ///
443    /// `long` is the only keyword that may be written twice, so everything else is a duplicate
444    /// the second time and is reported at the keyword rather than at the end of the specifier
445    /// list, which is where the second half of the checking happens.
446    ///
447    /// # Errors
448    ///
449    /// [`BuiltinError::Duplicate`] for a repeat, and [`BuiltinError::TooManyLongs`] for a third
450    /// `long`.
451    pub const fn add(self, which: BuiltinSet) -> Result<Builtin, BuiltinError> {
452        if which.0 == BuiltinSet::LONG.0 {
453            if self.longs >= 2 {
454                return Err(BuiltinError::TooManyLongs);
455            }
456            let set = self.set.with(which);
457            return Ok(Builtin { set, longs: self.longs + 1, width: self.width });
458        }
459        if self.set.has(which) {
460            return Err(BuiltinError::Duplicate);
461        }
462        Ok(Builtin { set: self.set.with(which), longs: self.longs, width: self.width })
463    }
464
465    /// This with `_BitInt(width)` written into it.
466    ///
467    /// The width is the one thing a type keyword carries, and it is kept here rather than in a
468    /// specifier of its own so that `unsigned _BitInt(8)` and `_BitInt(8) unsigned` are the
469    /// same declaration, which is what they are: a sign and a width may be written either way
470    /// round, and neither of them names a type on its own.
471    ///
472    /// # Errors
473    ///
474    /// [`BuiltinError::Duplicate`] when `_BitInt` was already written.
475    pub const fn add_bit_int(self, width: ExprId) -> Result<Builtin, BuiltinError> {
476        if self.set.has(BuiltinSet::BIT_INT) {
477            return Err(BuiltinError::Duplicate);
478        }
479        let set = self.set.with(BuiltinSet::BIT_INT);
480        Ok(Builtin { set, longs: self.longs, width: Some(width) })
481    }
482
483    /// Whether any built-in keyword has been written.
484    #[must_use]
485    pub const fn is_none(self) -> bool {
486        self.set.is_none()
487    }
488
489    /// The type this combination of keywords names, and `None` if it names no type.
490    ///
491    /// The table is the one in 6.7.2 plus the GNU and C23 rows: `_Complex` and `_Imaginary` on
492    /// the floating types, `_Complex` on the integer ones which GCC also allows, `__int128`
493    /// with a sign, and the `_FloatN` and `_DecimalN` families which stand alone.
494    #[must_use]
495    pub fn resolve(self) -> Option<Basic> {
496        let set = self.set;
497        let longs = self.longs;
498
499        let complexity = match (set.has(BuiltinSet::COMPLEX), set.has(BuiltinSet::IMAGINARY)) {
500            (true, true) => return None,
501            (true, false) => Complexity::Complex,
502            (false, true) => Complexity::Imaginary,
503            (false, false) => Complexity::Real,
504        };
505        let set = set.without(BuiltinSet::COMPLEX.with(BuiltinSet::IMAGINARY));
506        let basic = |scalar| Some(Basic { scalar, complexity });
507        let real = |scalar| {
508            if complexity == Complexity::Real { Some(Basic { scalar, complexity }) } else { None }
509        };
510
511        if set.has(BuiltinSet::SIGNED) && set.has(BuiltinSet::UNSIGNED) {
512            return None;
513        }
514        let unsigned = set.has(BuiltinSet::UNSIGNED);
515        let signs = BuiltinSet::SIGNED.with(BuiltinSet::UNSIGNED);
516
517        // Everything below is "these keywords and nothing else", which is what makes `void int`
518        // and `char short` fail here rather than needing a rule each.
519        if set.has(BuiltinSet::VOID) {
520            return if set == BuiltinSet::VOID && longs == 0 { real(Scalar::Void) } else { None };
521        }
522        if set.has(BuiltinSet::BOOL) {
523            return if set == BuiltinSet::BOOL && longs == 0 { real(Scalar::Bool) } else { None };
524        }
525        if set.has(BuiltinSet::CHAR) {
526            if set.without(signs) != BuiltinSet::CHAR || longs != 0 {
527                return None;
528            }
529            return real(match (set.has(BuiltinSet::SIGNED), unsigned) {
530                (true, _) => Scalar::SignedChar,
531                (_, true) => Scalar::UnsignedChar,
532                _ => Scalar::Char,
533            });
534        }
535        if set.has(BuiltinSet::INT128) {
536            if set.without(signs) != BuiltinSet::INT128 || longs != 0 {
537                return None;
538            }
539            return real(if unsigned { Scalar::UnsignedInt128 } else { Scalar::Int128 });
540        }
541        if set.has(BuiltinSet::BIT_INT) {
542            if set.without(signs) != BuiltinSet::BIT_INT || longs != 0 {
543                return None;
544            }
545            // A width of nothing is a `_BitInt` whose parenthesised part did not parse, which
546            // the parser has already reported and which names no type here either.
547            let width = self.width?;
548            return real(Scalar::BitInt { width, unsigned });
549        }
550        if set.has_any(BuiltinSet::DECIMALS) {
551            if longs != 0 || complexity != Complexity::Real {
552                return None;
553            }
554            return match set {
555                s if s == BuiltinSet::DECIMAL32 => real(Scalar::Decimal32),
556                s if s == BuiltinSet::DECIMAL64 => real(Scalar::Decimal64),
557                s if s == BuiltinSet::DECIMAL128 => real(Scalar::Decimal128),
558                _ => None,
559            };
560        }
561        if set.has_any(BuiltinSet::EXTENDED) {
562            if longs != 0 {
563                return None;
564            }
565            return match set {
566                s if s == BuiltinSet::FLOAT16 => basic(Scalar::Float16),
567                s if s == BuiltinSet::FLOAT32 => basic(Scalar::Float32),
568                s if s == BuiltinSet::FLOAT64 => basic(Scalar::Float64),
569                s if s == BuiltinSet::FLOAT128 => basic(Scalar::Float128),
570                s if s == BuiltinSet::FLOAT32X => basic(Scalar::Float32x),
571                s if s == BuiltinSet::FLOAT64X => basic(Scalar::Float64x),
572                s if s == BuiltinSet::FLOAT128X => basic(Scalar::Float128x),
573                s if s == BuiltinSet::FLOAT80 => basic(Scalar::Float80),
574                _ => None,
575            };
576        }
577        if set.has(BuiltinSet::FLOAT) {
578            return if set == BuiltinSet::FLOAT && longs == 0 {
579                basic(Scalar::Float)
580            } else {
581                None
582            };
583        }
584        if set.has(BuiltinSet::DOUBLE) {
585            if set.without(BuiltinSet::LONG) != BuiltinSet::DOUBLE {
586                return None;
587            }
588            return match longs {
589                0 => basic(Scalar::Double),
590                1 => basic(Scalar::LongDouble),
591                _ => None,
592            };
593        }
594        if set.is_none() {
595            return None;
596        }
597        // What is left is the standard integer types, where `int` is implied by any of the
598        // others and every combination is legal except `short long`.
599        if !BuiltinSet::INTEGER.has(set) {
600            return None;
601        }
602        if set.has(BuiltinSet::SHORT) {
603            if longs != 0 {
604                return None;
605            }
606            return basic(if unsigned { Scalar::UnsignedShort } else { Scalar::Short });
607        }
608        match longs {
609            0 => basic(if unsigned { Scalar::UnsignedInt } else { Scalar::Int }),
610            1 => basic(if unsigned { Scalar::UnsignedLong } else { Scalar::Long }),
611            2 => basic(if unsigned { Scalar::UnsignedLongLong } else { Scalar::LongLong }),
612            _ => None,
613        }
614    }
615}
616
617/// A built-in type, once the keywords have been read together.
618#[derive(Debug, Clone, Copy, PartialEq, Eq)]
619pub struct Basic {
620    /// The type itself.
621    pub scalar: Scalar,
622    /// Whether `_Complex` or `_Imaginary` was written.
623    pub complexity: Complexity,
624}
625
626/// Whether a built-in type is real, complex or imaginary.
627#[derive(Debug, Clone, Copy, PartialEq, Eq)]
628pub enum Complexity {
629    /// Neither keyword.
630    Real,
631    /// `_Complex`.
632    Complex,
633    /// `_Imaginary`, which GCC parses and has never implemented.
634    Imaginary,
635}
636
637/// A built-in type named by keywords, with the sign folded in.
638///
639/// `char` is here three times because plain `char` is a third type distinct from both
640/// `signed char` and `unsigned char`, however it is represented on the target.
641#[derive(Debug, Clone, Copy, PartialEq, Eq)]
642pub enum Scalar {
643    /// `void`.
644    Void,
645    /// `bool`.
646    Bool,
647    /// `char`.
648    Char,
649    /// `signed char`.
650    SignedChar,
651    /// `unsigned char`.
652    UnsignedChar,
653    /// `short`.
654    Short,
655    /// `unsigned short`.
656    UnsignedShort,
657    /// `int`.
658    Int,
659    /// `unsigned int`.
660    UnsignedInt,
661    /// `long`.
662    Long,
663    /// `unsigned long`.
664    UnsignedLong,
665    /// `long long`.
666    LongLong,
667    /// `unsigned long long`.
668    UnsignedLongLong,
669    /// `__int128`.
670    Int128,
671    /// `unsigned __int128`.
672    UnsignedInt128,
673    /// `_BitInt(N)`, with the sign written next to it folded in like every other sign here.
674    BitInt {
675        /// The width, which is a constant expression that nothing has evaluated yet.
676        width: ExprId,
677        /// Whether `unsigned` was written, which changes the least width there is as well as
678        /// the range: a signed one needs a bit for the sign and so is never narrower than two.
679        unsigned: bool,
680    },
681    /// `float`.
682    Float,
683    /// `double`.
684    Double,
685    /// `long double`.
686    LongDouble,
687    /// `_Float16`.
688    Float16,
689    /// `_Float32`.
690    Float32,
691    /// `_Float64`.
692    Float64,
693    /// `_Float128`.
694    Float128,
695    /// `_Float32x`.
696    Float32x,
697    /// `_Float64x`.
698    Float64x,
699    /// `_Float128x`.
700    Float128x,
701    /// `__float80`.
702    Float80,
703    /// `_Decimal32`.
704    Decimal32,
705    /// `_Decimal64`.
706    Decimal64,
707    /// `_Decimal128`.
708    Decimal128,
709}
710
711#[cfg(test)]
712mod tests {
713    use super::*;
714
715    fn resolve(keywords: &[BuiltinSet]) -> Option<Basic> {
716        let mut b = Builtin::NONE;
717        for &k in keywords {
718            b = b.add(k).expect("keyword rejected");
719        }
720        b.resolve()
721    }
722
723    fn real(keywords: &[BuiltinSet]) -> Option<Scalar> {
724        resolve(keywords).filter(|b| b.complexity == Complexity::Real).map(|b| b.scalar)
725    }
726
727    #[test]
728    fn the_plain_integer_spellings() {
729        assert_eq!(real(&[BuiltinSet::INT]), Some(Scalar::Int));
730        assert_eq!(real(&[BuiltinSet::SIGNED]), Some(Scalar::Int));
731        assert_eq!(real(&[BuiltinSet::UNSIGNED]), Some(Scalar::UnsignedInt));
732        assert_eq!(real(&[BuiltinSet::SIGNED, BuiltinSet::INT]), Some(Scalar::Int));
733        assert_eq!(real(&[BuiltinSet::SHORT]), Some(Scalar::Short));
734        assert_eq!(real(&[BuiltinSet::SHORT, BuiltinSet::INT]), Some(Scalar::Short));
735        assert_eq!(
736            real(&[BuiltinSet::UNSIGNED, BuiltinSet::SHORT, BuiltinSet::INT]),
737            Some(Scalar::UnsignedShort)
738        );
739    }
740
741    #[test]
742    fn long_counts_rather_than_repeats() {
743        assert_eq!(real(&[BuiltinSet::LONG]), Some(Scalar::Long));
744        assert_eq!(real(&[BuiltinSet::LONG, BuiltinSet::LONG]), Some(Scalar::LongLong));
745        assert_eq!(
746            real(&[BuiltinSet::UNSIGNED, BuiltinSet::LONG, BuiltinSet::LONG, BuiltinSet::INT]),
747            Some(Scalar::UnsignedLongLong)
748        );
749        let three = Builtin::NONE
750            .add(BuiltinSet::LONG)
751            .and_then(|b| b.add(BuiltinSet::LONG))
752            .and_then(|b| b.add(BuiltinSet::LONG));
753        assert_eq!(three, Err(BuiltinError::TooManyLongs));
754    }
755
756    #[test]
757    fn a_repeated_keyword_is_caught_where_it_is_written() {
758        let twice = Builtin::NONE.add(BuiltinSet::INT).and_then(|b| b.add(BuiltinSet::INT));
759        assert_eq!(twice, Err(BuiltinError::Duplicate));
760    }
761
762    #[test]
763    fn plain_char_is_its_own_type() {
764        assert_eq!(real(&[BuiltinSet::CHAR]), Some(Scalar::Char));
765        assert_eq!(real(&[BuiltinSet::SIGNED, BuiltinSet::CHAR]), Some(Scalar::SignedChar));
766        assert_eq!(real(&[BuiltinSet::UNSIGNED, BuiltinSet::CHAR]), Some(Scalar::UnsignedChar));
767        assert_eq!(real(&[BuiltinSet::CHAR, BuiltinSet::INT]), None);
768        assert_eq!(real(&[BuiltinSet::CHAR, BuiltinSet::LONG]), None);
769    }
770
771    #[test]
772    fn long_double_is_a_double_with_one_long() {
773        assert_eq!(real(&[BuiltinSet::DOUBLE]), Some(Scalar::Double));
774        assert_eq!(real(&[BuiltinSet::LONG, BuiltinSet::DOUBLE]), Some(Scalar::LongDouble));
775        assert_eq!(real(&[BuiltinSet::LONG, BuiltinSet::LONG, BuiltinSet::DOUBLE]), None);
776        assert_eq!(real(&[BuiltinSet::LONG, BuiltinSet::FLOAT]), None);
777        assert_eq!(real(&[BuiltinSet::DOUBLE, BuiltinSet::INT]), None);
778    }
779
780    #[test]
781    fn complex_is_a_modifier_and_not_a_type() {
782        assert_eq!(
783            resolve(&[BuiltinSet::COMPLEX, BuiltinSet::DOUBLE]),
784            Some(Basic { scalar: Scalar::Double, complexity: Complexity::Complex })
785        );
786        assert_eq!(
787            resolve(&[BuiltinSet::LONG, BuiltinSet::DOUBLE, BuiltinSet::IMAGINARY]),
788            Some(Basic { scalar: Scalar::LongDouble, complexity: Complexity::Imaginary })
789        );
790        // GCC accepts a complex integer type, so this is not an error here either.
791        assert_eq!(
792            resolve(&[BuiltinSet::COMPLEX, BuiltinSet::INT]),
793            Some(Basic { scalar: Scalar::Int, complexity: Complexity::Complex })
794        );
795        assert_eq!(resolve(&[BuiltinSet::COMPLEX, BuiltinSet::IMAGINARY, BuiltinSet::FLOAT]), None);
796        // There is no complex decimal type in any dialect.
797        assert_eq!(resolve(&[BuiltinSet::COMPLEX, BuiltinSet::DECIMAL64]), None);
798    }
799
800    #[test]
801    fn the_extended_types_stand_alone_or_with_complex() {
802        assert_eq!(real(&[BuiltinSet::FLOAT128]), Some(Scalar::Float128));
803        assert_eq!(
804            resolve(&[BuiltinSet::COMPLEX, BuiltinSet::FLOAT128]),
805            Some(Basic { scalar: Scalar::Float128, complexity: Complexity::Complex })
806        );
807        assert_eq!(real(&[BuiltinSet::FLOAT32X]), Some(Scalar::Float32x));
808        assert_eq!(real(&[BuiltinSet::FLOAT128X]), Some(Scalar::Float128x));
809        assert_eq!(real(&[BuiltinSet::FLOAT16, BuiltinSet::INT]), None);
810        assert_eq!(real(&[BuiltinSet::FLOAT32, BuiltinSet::FLOAT64]), None);
811    }
812
813    #[test]
814    fn the_wide_integers_take_a_sign_and_nothing_else() {
815        assert_eq!(real(&[BuiltinSet::INT128]), Some(Scalar::Int128));
816        assert_eq!(real(&[BuiltinSet::UNSIGNED, BuiltinSet::INT128]), Some(Scalar::UnsignedInt128));
817        assert_eq!(real(&[BuiltinSet::INT128, BuiltinSet::INT]), None);
818    }
819
820    #[test]
821    fn void_and_bool_take_nothing() {
822        assert_eq!(real(&[BuiltinSet::VOID]), Some(Scalar::Void));
823        assert_eq!(real(&[BuiltinSet::BOOL]), Some(Scalar::Bool));
824        assert_eq!(real(&[BuiltinSet::VOID, BuiltinSet::INT]), None);
825        assert_eq!(real(&[BuiltinSet::UNSIGNED, BuiltinSet::BOOL]), None);
826    }
827
828    #[test]
829    fn two_signs_name_no_type() {
830        assert_eq!(real(&[BuiltinSet::SIGNED, BuiltinSet::UNSIGNED]), None);
831    }
832
833    #[test]
834    fn no_keywords_at_all_names_no_type() {
835        assert_eq!(Builtin::NONE.resolve(), None);
836        assert!(Builtin::NONE.is_none());
837    }
838
839    #[test]
840    fn short_and_long_do_not_go_together() {
841        assert_eq!(real(&[BuiltinSet::SHORT, BuiltinSet::LONG]), None);
842    }
843
844    #[test]
845    fn qualifier_sets_add_up() {
846        let q = Quals::NONE.with(Quals::CONST).with(Quals::VOLATILE);
847        assert!(q.has(Quals::CONST));
848        assert!(q.has(Quals::VOLATILE));
849        assert!(!q.has(Quals::RESTRICT));
850        assert!(Quals::NONE.is_none());
851        assert!(!q.is_none());
852    }
853
854    #[test]
855    fn function_specifier_sets_add_up() {
856        let f = FuncSpecs::NONE.with(FuncSpecs::INLINE);
857        assert!(f.has(FuncSpecs::INLINE));
858        assert!(!f.has(FuncSpecs::NORETURN));
859        assert!(FuncSpecs::NONE.is_none());
860    }
861}