Skip to content

Commit e74acce

Browse files
author
bors-servo
authored
Auto merge of #260 - emilio:macro-str, r=fitzgen
Constant variable improvements. Fixes #256. r? @fitzgen
2 parents c800ad4 + 19d36d4 commit e74acce

20 files changed

+384
-59
lines changed

libbindgen/build.rs

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -38,13 +38,14 @@ mod testgen {
3838
.replace(|c| !char::is_alphanumeric(c), "_")
3939
.replace("__", "_")
4040
.to_lowercase();
41-
let _ = writeln!(dst, "test_header!(header_{}, {:?});",
42-
func, entry.path());
41+
writeln!(dst, "test_header!(header_{}, {:?});",
42+
func, entry.path()).unwrap();
4343
}
4444
_ => {}
4545
}
4646
}
47-
let _ = dst.flush();
47+
48+
dst.flush().unwrap();
4849
}
4950
}
5051

libbindgen/src/clang.rs

Lines changed: 76 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -264,7 +264,7 @@ impl Cursor {
264264

265265
/// Given that this cursor's referent is reference type, get the cursor
266266
/// pointing to the referenced type.
267-
pub fn referenced(&self) -> Option<Cursor> {
267+
pub fn referenced(&self) -> Option<Cursor> {
268268
unsafe {
269269
let ret = Cursor {
270270
x: clang_getCursorReferenced(self.x),
@@ -475,6 +475,11 @@ impl Cursor {
475475
pub fn is_virtual_base(&self) -> bool {
476476
unsafe { clang_isVirtualBase(self.x) != 0 }
477477
}
478+
479+
/// Try to evaluate this cursor.
480+
pub fn evaluate(&self) -> EvalResult {
481+
EvalResult::new(*self)
482+
}
478483
}
479484

480485
extern "C" fn visit_children<Visitor>(cur: CXCursor,
@@ -933,7 +938,9 @@ impl Into<String> for CXString {
933938
}
934939
unsafe {
935940
let c_str = CStr::from_ptr(clang_getCString(self) as *const _);
936-
c_str.to_string_lossy().into_owned()
941+
let ret = c_str.to_string_lossy().into_owned();
942+
clang_disposeString(self);
943+
ret
937944
}
938945
}
939946
}
@@ -1259,3 +1266,70 @@ pub fn ast_dump(c: &Cursor, depth: isize) -> Enum_CXVisitorResult {
12591266
pub fn extract_clang_version() -> String {
12601267
unsafe { clang_getClangVersion().into() }
12611268
}
1269+
1270+
/// A wrapper for the result of evaluating an expression.
1271+
#[derive(Debug)]
1272+
pub struct EvalResult {
1273+
x: CXEvalResult,
1274+
}
1275+
1276+
#[cfg(feature = "llvm_stable")]
1277+
impl EvalResult {
1278+
/// Create a dummy EvalResult.
1279+
pub fn new(_: Cursor) -> Self {
1280+
EvalResult {
1281+
x: ptr::null_mut(),
1282+
}
1283+
}
1284+
1285+
/// Not useful in llvm 3.8.
1286+
pub fn as_double(&self) -> Option<f64> {
1287+
None
1288+
}
1289+
1290+
/// Not useful in llvm 3.8.
1291+
pub fn as_int(&self) -> Option<i32> {
1292+
None
1293+
}
1294+
}
1295+
1296+
#[cfg(not(feature = "llvm_stable"))]
1297+
impl EvalResult {
1298+
/// Evaluate `cursor` and return the result.
1299+
pub fn new(cursor: Cursor) -> Self {
1300+
EvalResult {
1301+
x: unsafe { clang_Cursor_Evaluate(cursor.x) },
1302+
}
1303+
}
1304+
1305+
fn kind(&self) -> Enum_CXEvalResultKind {
1306+
unsafe { clang_EvalResult_getKind(self.x) }
1307+
}
1308+
1309+
/// Try to get back the result as a double.
1310+
pub fn as_double(&self) -> Option<f64> {
1311+
match self.kind() {
1312+
CXEval_Float => {
1313+
Some(unsafe { clang_EvalResult_getAsDouble(self.x) } as f64)
1314+
}
1315+
_ => None,
1316+
}
1317+
}
1318+
1319+
/// Try to get back the result as an integer.
1320+
pub fn as_int(&self) -> Option<i32> {
1321+
match self.kind() {
1322+
CXEval_Int => {
1323+
Some(unsafe { clang_EvalResult_getAsInt(self.x) } as i32)
1324+
}
1325+
_ => None,
1326+
}
1327+
}
1328+
}
1329+
1330+
#[cfg(not(feature = "llvm_stable"))]
1331+
impl Drop for EvalResult {
1332+
fn drop(&mut self) {
1333+
unsafe { clang_EvalResult_dispose(self.x) };
1334+
}
1335+
}

libbindgen/src/clangll.rs

Lines changed: 28 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,22 @@
77
#![allow(non_upper_case_globals)]
88
#![cfg_attr(rustfmt, rustfmt_skip)]
99

10-
use ::std::os::raw::{ c_char, c_int, c_long, c_longlong, c_uint, c_ulong, c_ulonglong, c_void};
10+
use ::std::os::raw::{c_char, c_int, c_long, c_longlong, c_uint, c_ulong, c_ulonglong, c_void};
11+
12+
#[cfg(not(feature = "llvm_stable"))]
13+
use std::os::raw::c_double;
14+
15+
16+
pub type CXEvalResult = *mut c_void;
17+
pub type Enum_CXEvalResultKind = c_uint;
18+
19+
pub const CXEval_Int: c_uint = 1;
20+
pub const CXEval_Float: c_uint = 2;
21+
pub const CXEval_ObjCStrLiteral: c_uint = 3;
22+
pub const CXEval_StrLiteral: c_uint = 4;
23+
pub const CXEval_CFStr: c_uint = 5;
24+
pub const CXEval_Other: c_uint = 6;
25+
pub const CXEval_UnExposed: c_uint = 0;
1126

1227
pub type ptrdiff_t = c_long;
1328
pub type size_t = c_ulong;
@@ -1436,4 +1451,16 @@ extern "C" {
14361451
offset: *mut c_uint);
14371452
pub fn clang_indexLoc_getCXSourceLocation(loc: CXIdxLoc) ->
14381453
CXSourceLocation;
1454+
#[cfg(not(feature="llvm_stable"))]
1455+
pub fn clang_Cursor_Evaluate(C: CXCursor) -> CXEvalResult;
1456+
#[cfg(not(feature="llvm_stable"))]
1457+
pub fn clang_EvalResult_getKind(E: CXEvalResult) -> Enum_CXEvalResultKind;
1458+
#[cfg(not(feature="llvm_stable"))]
1459+
pub fn clang_EvalResult_getAsInt(E: CXEvalResult) -> c_int;
1460+
#[cfg(not(feature="llvm_stable"))]
1461+
pub fn clang_EvalResult_getAsDouble(E: CXEvalResult) -> c_double;
1462+
#[cfg(not(feature="llvm_stable"))]
1463+
pub fn clang_EvalResult_getAsStr(E: CXEvalResult) -> *const c_char;
1464+
#[cfg(not(feature="llvm_stable"))]
1465+
pub fn clang_EvalResult_dispose(E: CXEvalResult);
14391466
}

libbindgen/src/codegen/helpers.rs

Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -132,4 +132,37 @@ pub mod ast_ty {
132132
expr.int(val)
133133
}
134134
}
135+
136+
pub fn byte_array_expr(bytes: &[u8]) -> P<ast::Expr> {
137+
let mut vec = Vec::with_capacity(bytes.len() + 1);
138+
for byte in bytes {
139+
vec.push(int_expr(*byte as i64));
140+
}
141+
vec.push(int_expr(0));
142+
143+
let kind = ast::ExprKind::Vec(vec);
144+
145+
aster::AstBuilder::new().expr().build_expr_kind(kind)
146+
}
147+
148+
pub fn cstr_expr(mut string: String) -> P<ast::Expr> {
149+
string.push('\0');
150+
aster::AstBuilder::new()
151+
.expr()
152+
.build_lit(aster::AstBuilder::new().lit().byte_str(string))
153+
}
154+
155+
pub fn float_expr(f: f64) -> P<ast::Expr> {
156+
use aster::str::ToInternedString;
157+
let mut string = f.to_string();
158+
159+
// So it gets properly recognised as a floating point constant.
160+
if !string.contains('.') {
161+
string.push('.');
162+
}
163+
164+
let interned_str = string.as_str().to_interned_string();
165+
let kind = ast::LitKind::FloatUnsuffixed(interned_str);
166+
aster::AstBuilder::new().expr().lit().build_lit(kind)
167+
}
135168
}

libbindgen/src/codegen/mod.rs

Lines changed: 39 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -304,6 +304,7 @@ impl CodeGenerator for Var {
304304
ctx: &BindgenContext,
305305
result: &mut CodegenResult,
306306
item: &Item) {
307+
use ir::var::VarType;
307308
debug!("<Var as CodeGenerator>::codegen: item = {:?}", item);
308309

309310
let canonical_name = item.canonical_name(ctx);
@@ -320,10 +321,44 @@ impl CodeGenerator for Var {
320321
.item()
321322
.pub_()
322323
.const_(canonical_name)
323-
.expr()
324-
.build(helpers::ast_ty::int_expr(val))
325-
.build(ty);
326-
result.push(const_item)
324+
.expr();
325+
let item = match *val {
326+
VarType::Int(val) => {
327+
const_item.build(helpers::ast_ty::int_expr(val))
328+
.build(ty)
329+
}
330+
VarType::String(ref bytes) => {
331+
// Account the trailing zero.
332+
//
333+
// TODO: Here we ignore the type we just made up, probably
334+
// we should refactor how the variable type and ty id work.
335+
let len = bytes.len() + 1;
336+
let ty = quote_ty!(ctx.ext_cx(), [u8; $len]);
337+
338+
match String::from_utf8(bytes.clone()) {
339+
Ok(string) => {
340+
const_item.build(helpers::ast_ty::cstr_expr(string))
341+
.build(quote_ty!(ctx.ext_cx(), &'static $ty))
342+
}
343+
Err(..) => {
344+
const_item
345+
.build(helpers::ast_ty::byte_array_expr(bytes))
346+
.build(ty)
347+
}
348+
}
349+
}
350+
VarType::Float(f) => {
351+
const_item.build(helpers::ast_ty::float_expr(f))
352+
.build(ty)
353+
}
354+
VarType::Char(c) => {
355+
const_item
356+
.build(aster::AstBuilder::new().expr().lit().byte(c))
357+
.build(ty)
358+
}
359+
};
360+
361+
result.push(item);
327362
} else {
328363
let mut attrs = vec![];
329364
if let Some(mangled) = self.mangled_name() {

libbindgen/src/ir/context.rs

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -222,7 +222,7 @@ impl<'ctx> BindgenContext<'ctx> {
222222
error!("Valid declaration with no USR: {:?}, {:?}",
223223
declaration,
224224
location);
225-
return;
225+
TypeKey::Declaration(declaration)
226226
};
227227

228228
let old = self.types.insert(key, id);
@@ -609,8 +609,7 @@ impl<'ctx> BindgenContext<'ctx> {
609609
-> Option<ItemId> {
610610
use clangll::{CXCursor_ClassTemplate,
611611
CXCursor_ClassTemplatePartialSpecialization,
612-
CXCursor_TypeAliasTemplateDecl,
613-
CXCursor_TypeRef};
612+
CXCursor_TypeAliasTemplateDecl, CXCursor_TypeRef};
614613
debug!("builtin_or_resolved_ty: {:?}, {:?}, {:?}",
615614
ty,
616615
location,

libbindgen/src/ir/item.rs

Lines changed: 1 addition & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -840,11 +840,7 @@ impl ClangItemParser for Item {
840840
ctx: &mut BindgenContext)
841841
-> ItemId {
842842
let id = ctx.next_item_id();
843-
Self::from_ty_or_ref_with_id(id,
844-
ty,
845-
location,
846-
parent_id,
847-
ctx)
843+
Self::from_ty_or_ref_with_id(id, ty, location, parent_id, ctx)
848844
}
849845

850846
/// Parse a C++ type. If we find a reference to a type that has not been

libbindgen/src/ir/ty.rs

Lines changed: 10 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -123,6 +123,14 @@ impl Type {
123123
Self::new(Some(name), None, kind, false)
124124
}
125125

126+
/// Is this a floating point type?
127+
pub fn is_float(&self) -> bool {
128+
match self.kind {
129+
TypeKind::Float(..) => true,
130+
_ => false,
131+
}
132+
}
133+
126134
/// Is this an integer type?
127135
pub fn is_integer(&self) -> bool {
128136
match self.kind {
@@ -667,7 +675,7 @@ impl Type {
667675
TypeKind::TemplateAlias(inner.unwrap(), args)
668676
}
669677
CXCursor_TemplateRef => {
670-
let referenced = location.referenced().expect("expected value, got none");
678+
let referenced = location.referenced().unwrap();
671679
let referenced_ty = referenced.cur_type();
672680
let referenced_declaration =
673681
Some(referenced_ty.declaration());
@@ -679,7 +687,7 @@ impl Type {
679687
ctx);
680688
}
681689
CXCursor_TypeRef => {
682-
let referenced = location.referenced().expect("expected value, got none");
690+
let referenced = location.referenced().unwrap();
683691
let referenced_ty = referenced.cur_type();
684692
let referenced_declaration =
685693
Some(referenced_ty.declaration());

0 commit comments

Comments
 (0)