1use rucc_base::Symbol;
16use rucc_diag::Span;
17
18use crate::ast::{AttrList, EnumeratorList, MemberList};
19use crate::decl::TypeNameId;
20use crate::expr::ExprId;
21
22pub type DeclSpecsId = rucc_base::Idx<DeclSpecs>;
24
25#[derive(Debug, Clone, Copy, PartialEq, Eq)]
27pub struct DeclSpecs {
28 pub storage: Option<StorageClass>,
30 pub thread_local: bool,
33 pub ty: TypeSpec,
35 pub quals: Quals,
37 pub func: FuncSpecs,
39 pub align: Option<AlignSpec>,
42 pub attrs: AttrList,
44 pub span: Span,
46}
47
48impl DeclSpecs {
49 #[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 #[must_use]
66 pub const fn is_typedef(&self) -> bool {
67 matches!(self.storage, Some(StorageClass::Typedef))
68 }
69}
70
71#[derive(Debug, Clone, Copy, PartialEq, Eq)]
73pub enum StorageClass {
74 Typedef,
76 Extern,
78 Static,
80 Auto,
82 Register,
84 Constexpr,
86}
87
88impl StorageClass {
89 #[must_use]
91 pub const fn spelling(self) -> &'static str {
92 match self {
93 StorageClass::Typedef => "typedef",
94 StorageClass::Extern => "extern",
95 StorageClass::Static => "static",
96 StorageClass::Auto => "auto",
97 StorageClass::Register => "register",
98 StorageClass::Constexpr => "constexpr",
99 }
100 }
101}
102
103#[derive(Debug, Clone, Copy, PartialEq, Eq, Default)]
110pub struct Quals(u8);
111
112impl Quals {
113 pub const NONE: Quals = Quals(0);
115 pub const CONST: Quals = Quals(1);
117 pub const VOLATILE: Quals = Quals(2);
119 pub const RESTRICT: Quals = Quals(4);
121 pub const ATOMIC: Quals = Quals(8);
123
124 #[inline]
126 #[must_use]
127 pub const fn has(self, other: Quals) -> bool {
128 self.0 & other.0 == other.0
129 }
130
131 #[inline]
133 #[must_use]
134 pub const fn with(self, other: Quals) -> Quals {
135 Quals(self.0 | other.0)
136 }
137
138 #[inline]
140 #[must_use]
141 pub const fn is_none(self) -> bool {
142 self.0 == 0
143 }
144}
145
146#[derive(Debug, Clone, Copy, PartialEq, Eq, Default)]
148pub struct FuncSpecs(u8);
149
150impl FuncSpecs {
151 pub const NONE: FuncSpecs = FuncSpecs(0);
153 pub const INLINE: FuncSpecs = FuncSpecs(1);
155 pub const NORETURN: FuncSpecs = FuncSpecs(2);
158
159 #[inline]
161 #[must_use]
162 pub const fn has(self, other: FuncSpecs) -> bool {
163 self.0 & other.0 == other.0
164 }
165
166 #[inline]
168 #[must_use]
169 pub const fn with(self, other: FuncSpecs) -> FuncSpecs {
170 FuncSpecs(self.0 | other.0)
171 }
172
173 #[inline]
175 #[must_use]
176 pub const fn is_none(self) -> bool {
177 self.0 == 0
178 }
179}
180
181#[derive(Debug, Clone, Copy, PartialEq, Eq)]
183pub enum AlignSpec {
184 Type(TypeNameId),
186 Expr(ExprId),
188}
189
190#[derive(Debug, Clone, Copy, PartialEq, Eq)]
192pub enum TypeSpec {
193 None,
195 Builtin(Builtin),
197 Record {
199 kind: RecordKind,
201 tag: Option<Symbol>,
203 fields: Option<MemberList>,
207 attrs: AttrList,
209 },
210 Enum {
212 tag: Option<Symbol>,
214 enumerators: Option<EnumeratorList>,
216 underlying: Option<TypeNameId>,
219 attrs: AttrList,
221 },
222 Typedef(Symbol),
224 Typeof {
226 unqual: bool,
228 operand: TypeofArg,
231 },
232 BitInt(ExprId),
234 Atomic(TypeNameId),
236 Auto,
239}
240
241#[derive(Debug, Clone, Copy, PartialEq, Eq)]
243pub enum RecordKind {
244 Struct,
246 Union,
248}
249
250impl RecordKind {
251 #[must_use]
253 pub const fn spelling(self) -> &'static str {
254 match self {
255 RecordKind::Struct => "struct",
256 RecordKind::Union => "union",
257 }
258 }
259}
260
261#[derive(Debug, Clone, Copy, PartialEq, Eq)]
263pub enum TypeofArg {
264 Expr(ExprId),
266 Type(TypeNameId),
268}
269
270#[derive(Debug, Clone, Copy, PartialEq, Eq, Default)]
277pub struct Builtin {
278 pub set: BuiltinSet,
280 pub longs: u8,
282}
283
284#[derive(Debug, Clone, Copy, PartialEq, Eq, Default)]
286pub struct BuiltinSet(u32);
287
288impl BuiltinSet {
289 pub const NONE: BuiltinSet = BuiltinSet(0);
291 pub const VOID: BuiltinSet = BuiltinSet(1 << 0);
293 pub const BOOL: BuiltinSet = BuiltinSet(1 << 1);
295 pub const CHAR: BuiltinSet = BuiltinSet(1 << 2);
297 pub const SHORT: BuiltinSet = BuiltinSet(1 << 3);
299 pub const INT: BuiltinSet = BuiltinSet(1 << 4);
301 pub const LONG: BuiltinSet = BuiltinSet(1 << 5);
303 pub const SIGNED: BuiltinSet = BuiltinSet(1 << 6);
305 pub const UNSIGNED: BuiltinSet = BuiltinSet(1 << 7);
307 pub const FLOAT: BuiltinSet = BuiltinSet(1 << 8);
309 pub const DOUBLE: BuiltinSet = BuiltinSet(1 << 9);
311 pub const COMPLEX: BuiltinSet = BuiltinSet(1 << 10);
313 pub const IMAGINARY: BuiltinSet = BuiltinSet(1 << 11);
315 pub const INT128: BuiltinSet = BuiltinSet(1 << 12);
317 pub const FLOAT16: BuiltinSet = BuiltinSet(1 << 13);
319 pub const FLOAT32: BuiltinSet = BuiltinSet(1 << 14);
321 pub const FLOAT64: BuiltinSet = BuiltinSet(1 << 15);
323 pub const FLOAT128: BuiltinSet = BuiltinSet(1 << 16);
325 pub const FLOAT32X: BuiltinSet = BuiltinSet(1 << 17);
327 pub const FLOAT64X: BuiltinSet = BuiltinSet(1 << 18);
329 pub const FLOAT128X: BuiltinSet = BuiltinSet(1 << 19);
331 pub const FLOAT80: BuiltinSet = BuiltinSet(1 << 20);
333 pub const DECIMAL32: BuiltinSet = BuiltinSet(1 << 21);
335 pub const DECIMAL64: BuiltinSet = BuiltinSet(1 << 22);
337 pub const DECIMAL128: BuiltinSet = BuiltinSet(1 << 23);
339
340 const DECIMALS: BuiltinSet =
342 BuiltinSet(Self::DECIMAL32.0 | Self::DECIMAL64.0 | Self::DECIMAL128.0);
343 const EXTENDED: BuiltinSet = BuiltinSet(
345 Self::FLOAT16.0
346 | Self::FLOAT32.0
347 | Self::FLOAT64.0
348 | Self::FLOAT128.0
349 | Self::FLOAT32X.0
350 | Self::FLOAT64X.0
351 | Self::FLOAT128X.0
352 | Self::FLOAT80.0,
353 );
354 const INTEGER: BuiltinSet =
356 BuiltinSet(Self::SHORT.0 | Self::INT.0 | Self::LONG.0 | Self::SIGNED.0 | Self::UNSIGNED.0);
357
358 #[inline]
360 #[must_use]
361 pub const fn has(self, other: BuiltinSet) -> bool {
362 self.0 & other.0 == other.0
363 }
364
365 #[inline]
367 #[must_use]
368 pub const fn has_any(self, other: BuiltinSet) -> bool {
369 self.0 & other.0 != 0
370 }
371
372 #[inline]
374 #[must_use]
375 pub const fn with(self, other: BuiltinSet) -> BuiltinSet {
376 BuiltinSet(self.0 | other.0)
377 }
378
379 #[inline]
381 #[must_use]
382 pub const fn without(self, other: BuiltinSet) -> BuiltinSet {
383 BuiltinSet(self.0 & !other.0)
384 }
385
386 #[inline]
388 #[must_use]
389 pub const fn is_none(self) -> bool {
390 self.0 == 0
391 }
392}
393
394#[derive(Debug, Clone, Copy, PartialEq, Eq)]
396pub enum BuiltinError {
397 Duplicate,
399 TooManyLongs,
401}
402
403impl Builtin {
404 pub const NONE: Builtin = Builtin { set: BuiltinSet::NONE, longs: 0 };
406
407 pub const fn add(self, which: BuiltinSet) -> Result<Builtin, BuiltinError> {
418 if which.0 == BuiltinSet::LONG.0 {
419 if self.longs >= 2 {
420 return Err(BuiltinError::TooManyLongs);
421 }
422 return Ok(Builtin { set: self.set.with(which), longs: self.longs + 1 });
423 }
424 if self.set.has(which) {
425 return Err(BuiltinError::Duplicate);
426 }
427 Ok(Builtin { set: self.set.with(which), longs: self.longs })
428 }
429
430 #[must_use]
432 pub const fn is_none(self) -> bool {
433 self.set.is_none()
434 }
435
436 #[must_use]
442 pub fn resolve(self) -> Option<Basic> {
443 let set = self.set;
444 let longs = self.longs;
445
446 let complexity = match (set.has(BuiltinSet::COMPLEX), set.has(BuiltinSet::IMAGINARY)) {
447 (true, true) => return None,
448 (true, false) => Complexity::Complex,
449 (false, true) => Complexity::Imaginary,
450 (false, false) => Complexity::Real,
451 };
452 let set = set.without(BuiltinSet::COMPLEX.with(BuiltinSet::IMAGINARY));
453 let basic = |scalar| Some(Basic { scalar, complexity });
454 let real = |scalar| {
455 if complexity == Complexity::Real { Some(Basic { scalar, complexity }) } else { None }
456 };
457
458 if set.has(BuiltinSet::SIGNED) && set.has(BuiltinSet::UNSIGNED) {
459 return None;
460 }
461 let unsigned = set.has(BuiltinSet::UNSIGNED);
462 let signs = BuiltinSet::SIGNED.with(BuiltinSet::UNSIGNED);
463
464 if set.has(BuiltinSet::VOID) {
467 return if set == BuiltinSet::VOID && longs == 0 { real(Scalar::Void) } else { None };
468 }
469 if set.has(BuiltinSet::BOOL) {
470 return if set == BuiltinSet::BOOL && longs == 0 { real(Scalar::Bool) } else { None };
471 }
472 if set.has(BuiltinSet::CHAR) {
473 if set.without(signs) != BuiltinSet::CHAR || longs != 0 {
474 return None;
475 }
476 return real(match (set.has(BuiltinSet::SIGNED), unsigned) {
477 (true, _) => Scalar::SignedChar,
478 (_, true) => Scalar::UnsignedChar,
479 _ => Scalar::Char,
480 });
481 }
482 if set.has(BuiltinSet::INT128) {
483 if set.without(signs) != BuiltinSet::INT128 || longs != 0 {
484 return None;
485 }
486 return real(if unsigned { Scalar::UnsignedInt128 } else { Scalar::Int128 });
487 }
488 if set.has_any(BuiltinSet::DECIMALS) {
489 if longs != 0 || complexity != Complexity::Real {
490 return None;
491 }
492 return match set {
493 s if s == BuiltinSet::DECIMAL32 => real(Scalar::Decimal32),
494 s if s == BuiltinSet::DECIMAL64 => real(Scalar::Decimal64),
495 s if s == BuiltinSet::DECIMAL128 => real(Scalar::Decimal128),
496 _ => None,
497 };
498 }
499 if set.has_any(BuiltinSet::EXTENDED) {
500 if longs != 0 {
501 return None;
502 }
503 return match set {
504 s if s == BuiltinSet::FLOAT16 => basic(Scalar::Float16),
505 s if s == BuiltinSet::FLOAT32 => basic(Scalar::Float32),
506 s if s == BuiltinSet::FLOAT64 => basic(Scalar::Float64),
507 s if s == BuiltinSet::FLOAT128 => basic(Scalar::Float128),
508 s if s == BuiltinSet::FLOAT32X => basic(Scalar::Float32x),
509 s if s == BuiltinSet::FLOAT64X => basic(Scalar::Float64x),
510 s if s == BuiltinSet::FLOAT128X => basic(Scalar::Float128x),
511 s if s == BuiltinSet::FLOAT80 => basic(Scalar::Float80),
512 _ => None,
513 };
514 }
515 if set.has(BuiltinSet::FLOAT) {
516 return if set == BuiltinSet::FLOAT && longs == 0 {
517 basic(Scalar::Float)
518 } else {
519 None
520 };
521 }
522 if set.has(BuiltinSet::DOUBLE) {
523 if set.without(BuiltinSet::LONG) != BuiltinSet::DOUBLE {
524 return None;
525 }
526 return match longs {
527 0 => basic(Scalar::Double),
528 1 => basic(Scalar::LongDouble),
529 _ => None,
530 };
531 }
532 if set.is_none() {
533 return None;
534 }
535 if !BuiltinSet::INTEGER.has(set) {
538 return None;
539 }
540 if set.has(BuiltinSet::SHORT) {
541 if longs != 0 {
542 return None;
543 }
544 return basic(if unsigned { Scalar::UnsignedShort } else { Scalar::Short });
545 }
546 match longs {
547 0 => basic(if unsigned { Scalar::UnsignedInt } else { Scalar::Int }),
548 1 => basic(if unsigned { Scalar::UnsignedLong } else { Scalar::Long }),
549 2 => basic(if unsigned { Scalar::UnsignedLongLong } else { Scalar::LongLong }),
550 _ => None,
551 }
552 }
553}
554
555#[derive(Debug, Clone, Copy, PartialEq, Eq)]
557pub struct Basic {
558 pub scalar: Scalar,
560 pub complexity: Complexity,
562}
563
564#[derive(Debug, Clone, Copy, PartialEq, Eq)]
566pub enum Complexity {
567 Real,
569 Complex,
571 Imaginary,
573}
574
575#[derive(Debug, Clone, Copy, PartialEq, Eq)]
580pub enum Scalar {
581 Void,
583 Bool,
585 Char,
587 SignedChar,
589 UnsignedChar,
591 Short,
593 UnsignedShort,
595 Int,
597 UnsignedInt,
599 Long,
601 UnsignedLong,
603 LongLong,
605 UnsignedLongLong,
607 Int128,
609 UnsignedInt128,
611 Float,
613 Double,
615 LongDouble,
617 Float16,
619 Float32,
621 Float64,
623 Float128,
625 Float32x,
627 Float64x,
629 Float128x,
631 Float80,
633 Decimal32,
635 Decimal64,
637 Decimal128,
639}
640
641#[cfg(test)]
642mod tests {
643 use super::*;
644
645 fn resolve(keywords: &[BuiltinSet]) -> Option<Basic> {
646 let mut b = Builtin::NONE;
647 for &k in keywords {
648 b = b.add(k).expect("keyword rejected");
649 }
650 b.resolve()
651 }
652
653 fn real(keywords: &[BuiltinSet]) -> Option<Scalar> {
654 resolve(keywords).filter(|b| b.complexity == Complexity::Real).map(|b| b.scalar)
655 }
656
657 #[test]
658 fn the_plain_integer_spellings() {
659 assert_eq!(real(&[BuiltinSet::INT]), Some(Scalar::Int));
660 assert_eq!(real(&[BuiltinSet::SIGNED]), Some(Scalar::Int));
661 assert_eq!(real(&[BuiltinSet::UNSIGNED]), Some(Scalar::UnsignedInt));
662 assert_eq!(real(&[BuiltinSet::SIGNED, BuiltinSet::INT]), Some(Scalar::Int));
663 assert_eq!(real(&[BuiltinSet::SHORT]), Some(Scalar::Short));
664 assert_eq!(real(&[BuiltinSet::SHORT, BuiltinSet::INT]), Some(Scalar::Short));
665 assert_eq!(
666 real(&[BuiltinSet::UNSIGNED, BuiltinSet::SHORT, BuiltinSet::INT]),
667 Some(Scalar::UnsignedShort)
668 );
669 }
670
671 #[test]
672 fn long_counts_rather_than_repeats() {
673 assert_eq!(real(&[BuiltinSet::LONG]), Some(Scalar::Long));
674 assert_eq!(real(&[BuiltinSet::LONG, BuiltinSet::LONG]), Some(Scalar::LongLong));
675 assert_eq!(
676 real(&[BuiltinSet::UNSIGNED, BuiltinSet::LONG, BuiltinSet::LONG, BuiltinSet::INT]),
677 Some(Scalar::UnsignedLongLong)
678 );
679 let three = Builtin::NONE
680 .add(BuiltinSet::LONG)
681 .and_then(|b| b.add(BuiltinSet::LONG))
682 .and_then(|b| b.add(BuiltinSet::LONG));
683 assert_eq!(three, Err(BuiltinError::TooManyLongs));
684 }
685
686 #[test]
687 fn a_repeated_keyword_is_caught_where_it_is_written() {
688 let twice = Builtin::NONE.add(BuiltinSet::INT).and_then(|b| b.add(BuiltinSet::INT));
689 assert_eq!(twice, Err(BuiltinError::Duplicate));
690 }
691
692 #[test]
693 fn plain_char_is_its_own_type() {
694 assert_eq!(real(&[BuiltinSet::CHAR]), Some(Scalar::Char));
695 assert_eq!(real(&[BuiltinSet::SIGNED, BuiltinSet::CHAR]), Some(Scalar::SignedChar));
696 assert_eq!(real(&[BuiltinSet::UNSIGNED, BuiltinSet::CHAR]), Some(Scalar::UnsignedChar));
697 assert_eq!(real(&[BuiltinSet::CHAR, BuiltinSet::INT]), None);
698 assert_eq!(real(&[BuiltinSet::CHAR, BuiltinSet::LONG]), None);
699 }
700
701 #[test]
702 fn long_double_is_a_double_with_one_long() {
703 assert_eq!(real(&[BuiltinSet::DOUBLE]), Some(Scalar::Double));
704 assert_eq!(real(&[BuiltinSet::LONG, BuiltinSet::DOUBLE]), Some(Scalar::LongDouble));
705 assert_eq!(real(&[BuiltinSet::LONG, BuiltinSet::LONG, BuiltinSet::DOUBLE]), None);
706 assert_eq!(real(&[BuiltinSet::LONG, BuiltinSet::FLOAT]), None);
707 assert_eq!(real(&[BuiltinSet::DOUBLE, BuiltinSet::INT]), None);
708 }
709
710 #[test]
711 fn complex_is_a_modifier_and_not_a_type() {
712 assert_eq!(
713 resolve(&[BuiltinSet::COMPLEX, BuiltinSet::DOUBLE]),
714 Some(Basic { scalar: Scalar::Double, complexity: Complexity::Complex })
715 );
716 assert_eq!(
717 resolve(&[BuiltinSet::LONG, BuiltinSet::DOUBLE, BuiltinSet::IMAGINARY]),
718 Some(Basic { scalar: Scalar::LongDouble, complexity: Complexity::Imaginary })
719 );
720 assert_eq!(
722 resolve(&[BuiltinSet::COMPLEX, BuiltinSet::INT]),
723 Some(Basic { scalar: Scalar::Int, complexity: Complexity::Complex })
724 );
725 assert_eq!(resolve(&[BuiltinSet::COMPLEX, BuiltinSet::IMAGINARY, BuiltinSet::FLOAT]), None);
726 assert_eq!(resolve(&[BuiltinSet::COMPLEX, BuiltinSet::DECIMAL64]), None);
728 }
729
730 #[test]
731 fn the_extended_types_stand_alone_or_with_complex() {
732 assert_eq!(real(&[BuiltinSet::FLOAT128]), Some(Scalar::Float128));
733 assert_eq!(
734 resolve(&[BuiltinSet::COMPLEX, BuiltinSet::FLOAT128]),
735 Some(Basic { scalar: Scalar::Float128, complexity: Complexity::Complex })
736 );
737 assert_eq!(real(&[BuiltinSet::FLOAT32X]), Some(Scalar::Float32x));
738 assert_eq!(real(&[BuiltinSet::FLOAT128X]), Some(Scalar::Float128x));
739 assert_eq!(real(&[BuiltinSet::FLOAT16, BuiltinSet::INT]), None);
740 assert_eq!(real(&[BuiltinSet::FLOAT32, BuiltinSet::FLOAT64]), None);
741 }
742
743 #[test]
744 fn the_wide_integers_take_a_sign_and_nothing_else() {
745 assert_eq!(real(&[BuiltinSet::INT128]), Some(Scalar::Int128));
746 assert_eq!(real(&[BuiltinSet::UNSIGNED, BuiltinSet::INT128]), Some(Scalar::UnsignedInt128));
747 assert_eq!(real(&[BuiltinSet::INT128, BuiltinSet::INT]), None);
748 }
749
750 #[test]
751 fn void_and_bool_take_nothing() {
752 assert_eq!(real(&[BuiltinSet::VOID]), Some(Scalar::Void));
753 assert_eq!(real(&[BuiltinSet::BOOL]), Some(Scalar::Bool));
754 assert_eq!(real(&[BuiltinSet::VOID, BuiltinSet::INT]), None);
755 assert_eq!(real(&[BuiltinSet::UNSIGNED, BuiltinSet::BOOL]), None);
756 }
757
758 #[test]
759 fn two_signs_name_no_type() {
760 assert_eq!(real(&[BuiltinSet::SIGNED, BuiltinSet::UNSIGNED]), None);
761 }
762
763 #[test]
764 fn no_keywords_at_all_names_no_type() {
765 assert_eq!(Builtin::NONE.resolve(), None);
766 assert!(Builtin::NONE.is_none());
767 }
768
769 #[test]
770 fn short_and_long_do_not_go_together() {
771 assert_eq!(real(&[BuiltinSet::SHORT, BuiltinSet::LONG]), None);
772 }
773
774 #[test]
775 fn qualifier_sets_add_up() {
776 let q = Quals::NONE.with(Quals::CONST).with(Quals::VOLATILE);
777 assert!(q.has(Quals::CONST));
778 assert!(q.has(Quals::VOLATILE));
779 assert!(!q.has(Quals::RESTRICT));
780 assert!(Quals::NONE.is_none());
781 assert!(!q.is_none());
782 }
783
784 #[test]
785 fn function_specifier_sets_add_up() {
786 let f = FuncSpecs::NONE.with(FuncSpecs::INLINE);
787 assert!(f.has(FuncSpecs::INLINE));
788 assert!(!f.has(FuncSpecs::NORETURN));
789 assert!(FuncSpecs::NONE.is_none());
790 }
791}