1 //! Intermediate representation for integral types.
2 
3 /// Which integral type are we dealing with?
4 #[derive(Debug, Copy, Clone, PartialEq, Eq, Hash, PartialOrd, Ord)]
5 pub enum IntKind {
6     /// A `bool`.
7     Bool,
8 
9     /// A `signed char`.
10     SChar,
11 
12     /// An `unsigned char`.
13     UChar,
14 
15     /// An `wchar_t`.
16     WChar,
17 
18     /// A platform-dependent `char` type, with the signedness support.
19     Char {
20         /// Whether the char is signed for the target platform.
21         is_signed: bool,
22     },
23 
24     /// A `short`.
25     Short,
26 
27     /// An `unsigned short`.
28     UShort,
29 
30     /// An `int`.
31     Int,
32 
33     /// An `unsigned int`.
34     UInt,
35 
36     /// A `long`.
37     Long,
38 
39     /// An `unsigned long`.
40     ULong,
41 
42     /// A `long long`.
43     LongLong,
44 
45     /// An `unsigned long long`.
46     ULongLong,
47 
48     /// A 8-bit signed integer.
49     I8,
50 
51     /// A 8-bit unsigned integer.
52     U8,
53 
54     /// A 16-bit signed integer.
55     I16,
56 
57     /// Either a `char16_t` or a `wchar_t`.
58     U16,
59 
60     /// A 32-bit signed integer.
61     I32,
62 
63     /// A 32-bit unsigned integer.
64     U32,
65 
66     /// A 64-bit signed integer.
67     I64,
68 
69     /// A 64-bit unsigned integer.
70     U64,
71 
72     /// An `int128_t`
73     I128,
74 
75     /// A `uint128_t`.
76     U128,
77 
78     /// A custom integer type, used to allow custom macro types depending on
79     /// range.
80     Custom {
81         /// The name of the type, which would be used without modification.
82         name: &'static str,
83         /// Whether the type is signed or not.
84         is_signed: bool,
85     },
86 }
87 
88 impl IntKind {
89     /// Is this integral type signed?
is_signed(&self) -> bool90     pub fn is_signed(&self) -> bool {
91         use self::IntKind::*;
92         match *self {
93             // TODO(emilio): wchar_t can in theory be signed, but we have no way
94             // to know whether it is or not right now (unlike char, there's no
95             // WChar_S / WChar_U).
96             Bool | UChar | UShort | UInt | ULong | ULongLong | U8 | U16 |
97             WChar | U32 | U64 | U128 => false,
98 
99             SChar | Short | Int | Long | LongLong | I8 | I16 | I32 | I64 |
100             I128 => true,
101 
102             Char { is_signed } => is_signed,
103 
104             Custom { is_signed, .. } => is_signed,
105         }
106     }
107 
108     /// If this type has a known size, return it (in bytes). This is to
109     /// alleviate libclang sometimes not giving us a layout (like in the case
110     /// when an enum is defined inside a class with template parameters).
known_size(&self) -> Option<usize>111     pub fn known_size(&self) -> Option<usize> {
112         use self::IntKind::*;
113         Some(match *self {
114             Bool | UChar | SChar | U8 | I8 | Char { .. } => 1,
115             U16 | I16 => 2,
116             U32 | I32 => 4,
117             U64 | I64 => 8,
118             I128 | U128 => 16,
119             _ => return None,
120         })
121     }
122 
123     /// Whether this type's signedness matches the value.
signedness_matches(&self, val: i64) -> bool124     pub fn signedness_matches(&self, val: i64) -> bool {
125         val >= 0 || self.is_signed()
126     }
127 }
128