diff --git a/libbindgen/src/ir/var.rs b/libbindgen/src/ir/var.rs index b819bfa4ec..3e900b0d7f 100644 --- a/libbindgen/src/ir/var.rs +++ b/libbindgen/src/ir/var.rs @@ -252,11 +252,13 @@ fn parse_macro(ctx: &BindgenContext, -> Option<(Vec, cexpr::expr::EvalResult)> { use cexpr::{expr, nom}; - let cexpr_tokens = match unit.cexpr_tokens(cursor) { + let mut cexpr_tokens = match unit.cexpr_tokens(cursor) { None => return None, Some(tokens) => tokens, }; + let _ctype = parse_macro_cast(&mut cexpr_tokens); + let parser = expr::IdentifierParser::new(ctx.parsed_macros()); let result = parser.macro_definition(&cexpr_tokens); @@ -266,6 +268,40 @@ fn parse_macro(ctx: &BindgenContext, } } +// try to detect the following pattern: +// #define constant ((int)1) +fn parse_macro_cast(tokens: &mut Vec) -> Option { + // Strip parentheses + loop { + // Match against the first token after the identifier (= #define) + // and the last token. If they are matching parentheses, remove them. + match (tokens.get(1), tokens.last()) { + // matching parentheses + (Some(t1), Some(t2)) if t1.raw[0] == 40 && t2.raw[0] == 41 => {} + _ => break, + } + + tokens.remove(1); + tokens.pop(); + } + + let ctype; + // Match a cast `(type)` + match (tokens.get(1), tokens.get(2), tokens.get(3)) { + (Some(t1), Some(t2), Some(t3)) + if t1.raw[0] == 40 + && t3.raw[0] == 41 + && t2.kind == cexpr::token::Kind::Keyword + => ctype = t2.clone(), + _ => return None, + } + + // remove the tokens + tokens.drain(1..4); + + Some(ctype) +} + fn parse_int_literal_tokens(cursor: &clang::Cursor, unit: &clang::TranslationUnit) -> Option {