@@ -8,7 +8,15 @@ use super::context::{BindgenContext, ItemId};
8
8
use super :: function:: cursor_mangling;
9
9
use super :: int:: IntKind ;
10
10
use super :: item:: Item ;
11
- use super :: ty:: TypeKind ;
11
+ use super :: ty:: { FloatKind , TypeKind } ;
12
+
13
+ #[ derive( Debug ) ]
14
+ pub enum VarType {
15
+ Int ( i64 ) ,
16
+ Float ( f64 ) ,
17
+ Char ( u8 ) ,
18
+ String ( Vec < u8 > ) ,
19
+ }
12
20
13
21
/// A `Var` is our intermediate representation of a variable.
14
22
#[ derive( Debug ) ]
@@ -19,9 +27,8 @@ pub struct Var {
19
27
mangled_name : Option < String > ,
20
28
/// The type of the variable.
21
29
ty : ItemId ,
22
- /// TODO: support non-integer constants?
23
- /// The integer value of the variable.
24
- val : Option < i64 > ,
30
+ /// The value of the variable, that needs to be suitable for `ty`.
31
+ val : Option < VarType > ,
25
32
/// Whether this variable is const.
26
33
is_const : bool ,
27
34
}
@@ -31,7 +38,7 @@ impl Var {
31
38
pub fn new ( name : String ,
32
39
mangled : Option < String > ,
33
40
ty : ItemId ,
34
- val : Option < i64 > ,
41
+ val : Option < VarType > ,
35
42
is_const : bool )
36
43
-> Var {
37
44
assert ! ( !name. is_empty( ) ) ;
@@ -50,8 +57,8 @@ impl Var {
50
57
}
51
58
52
59
/// The value of this constant variable, if any.
53
- pub fn val ( & self ) -> Option < i64 > {
54
- self . val
60
+ pub fn val ( & self ) -> Option < & VarType > {
61
+ self . val . as_ref ( )
55
62
}
56
63
57
64
/// Get this variable's type.
@@ -76,6 +83,7 @@ impl ClangSubItemParser for Var {
76
83
-> Result < ParseResult < Self > , ParseError > {
77
84
use clangll:: * ;
78
85
use cexpr:: expr:: EvalResult ;
86
+ use cexpr:: literal:: CChar ;
79
87
match cursor. kind ( ) {
80
88
CXCursor_MacroDefinition => {
81
89
let value = parse_macro ( ctx, & cursor, ctx. translation_unit ( ) ) ;
@@ -105,13 +113,32 @@ impl ClangSubItemParser for Var {
105
113
// enforce utf8 there, so we should have already panicked at
106
114
// this point.
107
115
let name = String :: from_utf8 ( id) . unwrap ( ) ;
108
- let ( int_kind, val) = match value {
109
- // TODO(emilio): Handle the non-invalid ones!
110
- EvalResult :: Float ( ..) |
111
- EvalResult :: Char ( ..) |
112
- EvalResult :: Str ( ..) |
116
+ let ( type_kind, val) = match value {
113
117
EvalResult :: Invalid => return Err ( ParseError :: Continue ) ,
114
-
118
+ EvalResult :: Float ( f) => {
119
+ ( TypeKind :: Float ( FloatKind :: Float ) , VarType :: Float ( f) )
120
+ }
121
+ EvalResult :: Char ( c) => {
122
+ let c = match c {
123
+ CChar :: Char ( c) => {
124
+ assert_eq ! ( c. len_utf8( ) , 1 ) ;
125
+ c as u8
126
+ }
127
+ CChar :: Raw ( c) => {
128
+ assert ! ( c <= :: std:: u8 :: MAX as u64 ) ;
129
+ c as u8
130
+ }
131
+ } ;
132
+
133
+ ( TypeKind :: Int ( IntKind :: U8 ) , VarType :: Char ( c) )
134
+ }
135
+ EvalResult :: Str ( val) => {
136
+ let char_ty =
137
+ Item :: builtin_type ( TypeKind :: Int ( IntKind :: U8 ) ,
138
+ true ,
139
+ ctx) ;
140
+ ( TypeKind :: Pointer ( char_ty) , VarType :: String ( val) )
141
+ }
115
142
EvalResult :: Int ( Wrapping ( value) ) => {
116
143
let kind = ctx. options ( )
117
144
. type_chooser
@@ -131,11 +158,11 @@ impl ClangSubItemParser for Var {
131
158
}
132
159
} ) ;
133
160
134
- ( kind, value)
161
+ ( TypeKind :: Int ( kind) , VarType :: Int ( value) )
135
162
}
136
163
} ;
137
164
138
- let ty = Item :: builtin_type ( TypeKind :: Int ( int_kind ) , true , ctx) ;
165
+ let ty = Item :: builtin_type ( type_kind , true , ctx) ;
139
166
140
167
Ok ( ParseResult :: New ( Var :: new ( name, None , ty, Some ( val) , true ) ,
141
168
Some ( cursor) ) )
@@ -159,11 +186,16 @@ impl ClangSubItemParser for Var {
159
186
// tests/headers/inner_const.hpp
160
187
//
161
188
// That's fine because in that case we know it's not a literal.
162
- let is_integer = ctx. safe_resolve_type ( ty)
163
- . and_then ( |t| t. safe_canonical_type ( ctx) )
164
- . map ( |t| t. is_integer ( ) )
165
- . unwrap_or ( false ) ;
189
+ let canonical_ty = ctx. safe_resolve_type ( ty)
190
+ . and_then ( |t| t. safe_canonical_type ( ctx) ) ;
166
191
192
+ let is_integer = canonical_ty. map_or ( false , |t| t. is_integer ( ) ) ;
193
+ let is_float = canonical_ty. map_or ( false , |t| t. is_float ( ) ) ;
194
+
195
+ // TODO: We could handle `char` more gracefully.
196
+ // TODO: Strings, though the lookup is a bit more hard (we need
197
+ // to look at the canonical type of the pointee too, and check
198
+ // is char, u8, or i8 I guess).
167
199
let value = if is_integer {
168
200
cursor. evaluate ( )
169
201
. as_int ( )
@@ -172,16 +204,19 @@ impl ClangSubItemParser for Var {
172
204
let tu = ctx. translation_unit ( ) ;
173
205
get_integer_literal_from_cursor ( & cursor, tu)
174
206
} )
207
+ . map ( VarType :: Int )
208
+ } else if is_float {
209
+ cursor. evaluate ( )
210
+ . as_double ( )
211
+ . map ( VarType :: Float )
175
212
} else {
176
213
None
177
214
} ;
178
215
179
-
180
216
let mangling = cursor_mangling ( & cursor) ;
181
-
182
217
let var = Var :: new ( name, mangling, ty, value, is_const) ;
183
- Ok ( ParseResult :: New ( var, Some ( cursor) ) )
184
218
219
+ Ok ( ParseResult :: New ( var, Some ( cursor) ) )
185
220
}
186
221
_ => {
187
222
/* TODO */
0 commit comments