112a9d9c8Sopenharmony_ci//! Intermediate representation of variables.
212a9d9c8Sopenharmony_ci
312a9d9c8Sopenharmony_ciuse super::super::codegen::MacroTypeVariation;
412a9d9c8Sopenharmony_ciuse super::context::{BindgenContext, TypeId};
512a9d9c8Sopenharmony_ciuse super::dot::DotAttributes;
612a9d9c8Sopenharmony_ciuse super::function::cursor_mangling;
712a9d9c8Sopenharmony_ciuse super::int::IntKind;
812a9d9c8Sopenharmony_ciuse super::item::Item;
912a9d9c8Sopenharmony_ciuse super::ty::{FloatKind, TypeKind};
1012a9d9c8Sopenharmony_ciuse crate::callbacks::{ItemInfo, ItemKind, MacroParsingBehavior};
1112a9d9c8Sopenharmony_ciuse crate::clang;
1212a9d9c8Sopenharmony_ciuse crate::clang::ClangToken;
1312a9d9c8Sopenharmony_ciuse crate::parse::{ClangSubItemParser, ParseError, ParseResult};
1412a9d9c8Sopenharmony_ciuse cexpr;
1512a9d9c8Sopenharmony_ciuse std::io;
1612a9d9c8Sopenharmony_ciuse std::num::Wrapping;
1712a9d9c8Sopenharmony_ci
1812a9d9c8Sopenharmony_ci/// The type for a constant variable.
1912a9d9c8Sopenharmony_ci#[derive(Debug)]
2012a9d9c8Sopenharmony_cipub enum VarType {
2112a9d9c8Sopenharmony_ci    /// A boolean.
2212a9d9c8Sopenharmony_ci    Bool(bool),
2312a9d9c8Sopenharmony_ci    /// An integer.
2412a9d9c8Sopenharmony_ci    Int(i64),
2512a9d9c8Sopenharmony_ci    /// A floating point number.
2612a9d9c8Sopenharmony_ci    Float(f64),
2712a9d9c8Sopenharmony_ci    /// A character.
2812a9d9c8Sopenharmony_ci    Char(u8),
2912a9d9c8Sopenharmony_ci    /// A string, not necessarily well-formed utf-8.
3012a9d9c8Sopenharmony_ci    String(Vec<u8>),
3112a9d9c8Sopenharmony_ci}
3212a9d9c8Sopenharmony_ci
3312a9d9c8Sopenharmony_ci/// A `Var` is our intermediate representation of a variable.
3412a9d9c8Sopenharmony_ci#[derive(Debug)]
3512a9d9c8Sopenharmony_cipub struct Var {
3612a9d9c8Sopenharmony_ci    /// The name of the variable.
3712a9d9c8Sopenharmony_ci    name: String,
3812a9d9c8Sopenharmony_ci    /// The mangled name of the variable.
3912a9d9c8Sopenharmony_ci    mangled_name: Option<String>,
4012a9d9c8Sopenharmony_ci    /// The type of the variable.
4112a9d9c8Sopenharmony_ci    ty: TypeId,
4212a9d9c8Sopenharmony_ci    /// The value of the variable, that needs to be suitable for `ty`.
4312a9d9c8Sopenharmony_ci    val: Option<VarType>,
4412a9d9c8Sopenharmony_ci    /// Whether this variable is const.
4512a9d9c8Sopenharmony_ci    is_const: bool,
4612a9d9c8Sopenharmony_ci}
4712a9d9c8Sopenharmony_ci
4812a9d9c8Sopenharmony_ciimpl Var {
4912a9d9c8Sopenharmony_ci    /// Construct a new `Var`.
5012a9d9c8Sopenharmony_ci    pub fn new(
5112a9d9c8Sopenharmony_ci        name: String,
5212a9d9c8Sopenharmony_ci        mangled_name: Option<String>,
5312a9d9c8Sopenharmony_ci        ty: TypeId,
5412a9d9c8Sopenharmony_ci        val: Option<VarType>,
5512a9d9c8Sopenharmony_ci        is_const: bool,
5612a9d9c8Sopenharmony_ci    ) -> Var {
5712a9d9c8Sopenharmony_ci        assert!(!name.is_empty());
5812a9d9c8Sopenharmony_ci        Var {
5912a9d9c8Sopenharmony_ci            name,
6012a9d9c8Sopenharmony_ci            mangled_name,
6112a9d9c8Sopenharmony_ci            ty,
6212a9d9c8Sopenharmony_ci            val,
6312a9d9c8Sopenharmony_ci            is_const,
6412a9d9c8Sopenharmony_ci        }
6512a9d9c8Sopenharmony_ci    }
6612a9d9c8Sopenharmony_ci
6712a9d9c8Sopenharmony_ci    /// Is this variable `const` qualified?
6812a9d9c8Sopenharmony_ci    pub fn is_const(&self) -> bool {
6912a9d9c8Sopenharmony_ci        self.is_const
7012a9d9c8Sopenharmony_ci    }
7112a9d9c8Sopenharmony_ci
7212a9d9c8Sopenharmony_ci    /// The value of this constant variable, if any.
7312a9d9c8Sopenharmony_ci    pub fn val(&self) -> Option<&VarType> {
7412a9d9c8Sopenharmony_ci        self.val.as_ref()
7512a9d9c8Sopenharmony_ci    }
7612a9d9c8Sopenharmony_ci
7712a9d9c8Sopenharmony_ci    /// Get this variable's type.
7812a9d9c8Sopenharmony_ci    pub fn ty(&self) -> TypeId {
7912a9d9c8Sopenharmony_ci        self.ty
8012a9d9c8Sopenharmony_ci    }
8112a9d9c8Sopenharmony_ci
8212a9d9c8Sopenharmony_ci    /// Get this variable's name.
8312a9d9c8Sopenharmony_ci    pub fn name(&self) -> &str {
8412a9d9c8Sopenharmony_ci        &self.name
8512a9d9c8Sopenharmony_ci    }
8612a9d9c8Sopenharmony_ci
8712a9d9c8Sopenharmony_ci    /// Get this variable's mangled name.
8812a9d9c8Sopenharmony_ci    pub fn mangled_name(&self) -> Option<&str> {
8912a9d9c8Sopenharmony_ci        self.mangled_name.as_deref()
9012a9d9c8Sopenharmony_ci    }
9112a9d9c8Sopenharmony_ci}
9212a9d9c8Sopenharmony_ci
9312a9d9c8Sopenharmony_ciimpl DotAttributes for Var {
9412a9d9c8Sopenharmony_ci    fn dot_attributes<W>(
9512a9d9c8Sopenharmony_ci        &self,
9612a9d9c8Sopenharmony_ci        _ctx: &BindgenContext,
9712a9d9c8Sopenharmony_ci        out: &mut W,
9812a9d9c8Sopenharmony_ci    ) -> io::Result<()>
9912a9d9c8Sopenharmony_ci    where
10012a9d9c8Sopenharmony_ci        W: io::Write,
10112a9d9c8Sopenharmony_ci    {
10212a9d9c8Sopenharmony_ci        if self.is_const {
10312a9d9c8Sopenharmony_ci            writeln!(out, "<tr><td>const</td><td>true</td></tr>")?;
10412a9d9c8Sopenharmony_ci        }
10512a9d9c8Sopenharmony_ci
10612a9d9c8Sopenharmony_ci        if let Some(ref mangled) = self.mangled_name {
10712a9d9c8Sopenharmony_ci            writeln!(
10812a9d9c8Sopenharmony_ci                out,
10912a9d9c8Sopenharmony_ci                "<tr><td>mangled name</td><td>{}</td></tr>",
11012a9d9c8Sopenharmony_ci                mangled
11112a9d9c8Sopenharmony_ci            )?;
11212a9d9c8Sopenharmony_ci        }
11312a9d9c8Sopenharmony_ci
11412a9d9c8Sopenharmony_ci        Ok(())
11512a9d9c8Sopenharmony_ci    }
11612a9d9c8Sopenharmony_ci}
11712a9d9c8Sopenharmony_ci
11812a9d9c8Sopenharmony_cifn default_macro_constant_type(ctx: &BindgenContext, value: i64) -> IntKind {
11912a9d9c8Sopenharmony_ci    if value < 0 ||
12012a9d9c8Sopenharmony_ci        ctx.options().default_macro_constant_type ==
12112a9d9c8Sopenharmony_ci            MacroTypeVariation::Signed
12212a9d9c8Sopenharmony_ci    {
12312a9d9c8Sopenharmony_ci        if value < i32::min_value() as i64 || value > i32::max_value() as i64 {
12412a9d9c8Sopenharmony_ci            IntKind::I64
12512a9d9c8Sopenharmony_ci        } else if !ctx.options().fit_macro_constants ||
12612a9d9c8Sopenharmony_ci            value < i16::min_value() as i64 ||
12712a9d9c8Sopenharmony_ci            value > i16::max_value() as i64
12812a9d9c8Sopenharmony_ci        {
12912a9d9c8Sopenharmony_ci            IntKind::I32
13012a9d9c8Sopenharmony_ci        } else if value < i8::min_value() as i64 ||
13112a9d9c8Sopenharmony_ci            value > i8::max_value() as i64
13212a9d9c8Sopenharmony_ci        {
13312a9d9c8Sopenharmony_ci            IntKind::I16
13412a9d9c8Sopenharmony_ci        } else {
13512a9d9c8Sopenharmony_ci            IntKind::I8
13612a9d9c8Sopenharmony_ci        }
13712a9d9c8Sopenharmony_ci    } else if value > u32::max_value() as i64 {
13812a9d9c8Sopenharmony_ci        IntKind::U64
13912a9d9c8Sopenharmony_ci    } else if !ctx.options().fit_macro_constants ||
14012a9d9c8Sopenharmony_ci        value > u16::max_value() as i64
14112a9d9c8Sopenharmony_ci    {
14212a9d9c8Sopenharmony_ci        IntKind::U32
14312a9d9c8Sopenharmony_ci    } else if value > u8::max_value() as i64 {
14412a9d9c8Sopenharmony_ci        IntKind::U16
14512a9d9c8Sopenharmony_ci    } else {
14612a9d9c8Sopenharmony_ci        IntKind::U8
14712a9d9c8Sopenharmony_ci    }
14812a9d9c8Sopenharmony_ci}
14912a9d9c8Sopenharmony_ci
15012a9d9c8Sopenharmony_ci/// Parses tokens from a CXCursor_MacroDefinition pointing into a function-like
15112a9d9c8Sopenharmony_ci/// macro, and calls the func_macro callback.
15212a9d9c8Sopenharmony_cifn handle_function_macro(
15312a9d9c8Sopenharmony_ci    cursor: &clang::Cursor,
15412a9d9c8Sopenharmony_ci    callbacks: &dyn crate::callbacks::ParseCallbacks,
15512a9d9c8Sopenharmony_ci) {
15612a9d9c8Sopenharmony_ci    let is_closing_paren = |t: &ClangToken| {
15712a9d9c8Sopenharmony_ci        // Test cheap token kind before comparing exact spellings.
15812a9d9c8Sopenharmony_ci        t.kind == clang_sys::CXToken_Punctuation && t.spelling() == b")"
15912a9d9c8Sopenharmony_ci    };
16012a9d9c8Sopenharmony_ci    let tokens: Vec<_> = cursor.tokens().iter().collect();
16112a9d9c8Sopenharmony_ci    if let Some(boundary) = tokens.iter().position(is_closing_paren) {
16212a9d9c8Sopenharmony_ci        let mut spelled = tokens.iter().map(ClangToken::spelling);
16312a9d9c8Sopenharmony_ci        // Add 1, to convert index to length.
16412a9d9c8Sopenharmony_ci        let left = spelled.by_ref().take(boundary + 1);
16512a9d9c8Sopenharmony_ci        let left = left.collect::<Vec<_>>().concat();
16612a9d9c8Sopenharmony_ci        if let Ok(left) = String::from_utf8(left) {
16712a9d9c8Sopenharmony_ci            let right: Vec<_> = spelled.collect();
16812a9d9c8Sopenharmony_ci            callbacks.func_macro(&left, &right);
16912a9d9c8Sopenharmony_ci        }
17012a9d9c8Sopenharmony_ci    }
17112a9d9c8Sopenharmony_ci}
17212a9d9c8Sopenharmony_ci
17312a9d9c8Sopenharmony_ciimpl ClangSubItemParser for Var {
17412a9d9c8Sopenharmony_ci    fn parse(
17512a9d9c8Sopenharmony_ci        cursor: clang::Cursor,
17612a9d9c8Sopenharmony_ci        ctx: &mut BindgenContext,
17712a9d9c8Sopenharmony_ci    ) -> Result<ParseResult<Self>, ParseError> {
17812a9d9c8Sopenharmony_ci        use cexpr::expr::EvalResult;
17912a9d9c8Sopenharmony_ci        use cexpr::literal::CChar;
18012a9d9c8Sopenharmony_ci        use clang_sys::*;
18112a9d9c8Sopenharmony_ci        match cursor.kind() {
18212a9d9c8Sopenharmony_ci            CXCursor_MacroDefinition => {
18312a9d9c8Sopenharmony_ci                for callbacks in &ctx.options().parse_callbacks {
18412a9d9c8Sopenharmony_ci                    match callbacks.will_parse_macro(&cursor.spelling()) {
18512a9d9c8Sopenharmony_ci                        MacroParsingBehavior::Ignore => {
18612a9d9c8Sopenharmony_ci                            return Err(ParseError::Continue);
18712a9d9c8Sopenharmony_ci                        }
18812a9d9c8Sopenharmony_ci                        MacroParsingBehavior::Default => {}
18912a9d9c8Sopenharmony_ci                    }
19012a9d9c8Sopenharmony_ci
19112a9d9c8Sopenharmony_ci                    if cursor.is_macro_function_like() {
19212a9d9c8Sopenharmony_ci                        handle_function_macro(&cursor, callbacks.as_ref());
19312a9d9c8Sopenharmony_ci                        // We handled the macro, skip macro processing below.
19412a9d9c8Sopenharmony_ci                        return Err(ParseError::Continue);
19512a9d9c8Sopenharmony_ci                    }
19612a9d9c8Sopenharmony_ci                }
19712a9d9c8Sopenharmony_ci
19812a9d9c8Sopenharmony_ci                let value = parse_macro(ctx, &cursor);
19912a9d9c8Sopenharmony_ci
20012a9d9c8Sopenharmony_ci                let (id, value) = match value {
20112a9d9c8Sopenharmony_ci                    Some(v) => v,
20212a9d9c8Sopenharmony_ci                    None => return Err(ParseError::Continue),
20312a9d9c8Sopenharmony_ci                };
20412a9d9c8Sopenharmony_ci
20512a9d9c8Sopenharmony_ci                assert!(!id.is_empty(), "Empty macro name?");
20612a9d9c8Sopenharmony_ci
20712a9d9c8Sopenharmony_ci                let previously_defined = ctx.parsed_macro(&id);
20812a9d9c8Sopenharmony_ci
20912a9d9c8Sopenharmony_ci                // NB: It's important to "note" the macro even if the result is
21012a9d9c8Sopenharmony_ci                // not an integer, otherwise we might loose other kind of
21112a9d9c8Sopenharmony_ci                // derived macros.
21212a9d9c8Sopenharmony_ci                ctx.note_parsed_macro(id.clone(), value.clone());
21312a9d9c8Sopenharmony_ci
21412a9d9c8Sopenharmony_ci                if previously_defined {
21512a9d9c8Sopenharmony_ci                    let name = String::from_utf8(id).unwrap();
21612a9d9c8Sopenharmony_ci                    warn!("Duplicated macro definition: {}", name);
21712a9d9c8Sopenharmony_ci                    return Err(ParseError::Continue);
21812a9d9c8Sopenharmony_ci                }
21912a9d9c8Sopenharmony_ci
22012a9d9c8Sopenharmony_ci                // NOTE: Unwrapping, here and above, is safe, because the
22112a9d9c8Sopenharmony_ci                // identifier of a token comes straight from clang, and we
22212a9d9c8Sopenharmony_ci                // enforce utf8 there, so we should have already panicked at
22312a9d9c8Sopenharmony_ci                // this point.
22412a9d9c8Sopenharmony_ci                let name = String::from_utf8(id).unwrap();
22512a9d9c8Sopenharmony_ci                let (type_kind, val) = match value {
22612a9d9c8Sopenharmony_ci                    EvalResult::Invalid => return Err(ParseError::Continue),
22712a9d9c8Sopenharmony_ci                    EvalResult::Float(f) => {
22812a9d9c8Sopenharmony_ci                        (TypeKind::Float(FloatKind::Double), VarType::Float(f))
22912a9d9c8Sopenharmony_ci                    }
23012a9d9c8Sopenharmony_ci                    EvalResult::Char(c) => {
23112a9d9c8Sopenharmony_ci                        let c = match c {
23212a9d9c8Sopenharmony_ci                            CChar::Char(c) => {
23312a9d9c8Sopenharmony_ci                                assert_eq!(c.len_utf8(), 1);
23412a9d9c8Sopenharmony_ci                                c as u8
23512a9d9c8Sopenharmony_ci                            }
23612a9d9c8Sopenharmony_ci                            CChar::Raw(c) => {
23712a9d9c8Sopenharmony_ci                                assert!(c <= ::std::u8::MAX as u64);
23812a9d9c8Sopenharmony_ci                                c as u8
23912a9d9c8Sopenharmony_ci                            }
24012a9d9c8Sopenharmony_ci                        };
24112a9d9c8Sopenharmony_ci
24212a9d9c8Sopenharmony_ci                        (TypeKind::Int(IntKind::U8), VarType::Char(c))
24312a9d9c8Sopenharmony_ci                    }
24412a9d9c8Sopenharmony_ci                    EvalResult::Str(val) => {
24512a9d9c8Sopenharmony_ci                        let char_ty = Item::builtin_type(
24612a9d9c8Sopenharmony_ci                            TypeKind::Int(IntKind::U8),
24712a9d9c8Sopenharmony_ci                            true,
24812a9d9c8Sopenharmony_ci                            ctx,
24912a9d9c8Sopenharmony_ci                        );
25012a9d9c8Sopenharmony_ci                        for callbacks in &ctx.options().parse_callbacks {
25112a9d9c8Sopenharmony_ci                            callbacks.str_macro(&name, &val);
25212a9d9c8Sopenharmony_ci                        }
25312a9d9c8Sopenharmony_ci                        (TypeKind::Pointer(char_ty), VarType::String(val))
25412a9d9c8Sopenharmony_ci                    }
25512a9d9c8Sopenharmony_ci                    EvalResult::Int(Wrapping(value)) => {
25612a9d9c8Sopenharmony_ci                        let kind = ctx
25712a9d9c8Sopenharmony_ci                            .options()
25812a9d9c8Sopenharmony_ci                            .last_callback(|c| c.int_macro(&name, value))
25912a9d9c8Sopenharmony_ci                            .unwrap_or_else(|| {
26012a9d9c8Sopenharmony_ci                                default_macro_constant_type(ctx, value)
26112a9d9c8Sopenharmony_ci                            });
26212a9d9c8Sopenharmony_ci
26312a9d9c8Sopenharmony_ci                        (TypeKind::Int(kind), VarType::Int(value))
26412a9d9c8Sopenharmony_ci                    }
26512a9d9c8Sopenharmony_ci                };
26612a9d9c8Sopenharmony_ci
26712a9d9c8Sopenharmony_ci                let ty = Item::builtin_type(type_kind, true, ctx);
26812a9d9c8Sopenharmony_ci
26912a9d9c8Sopenharmony_ci                Ok(ParseResult::New(
27012a9d9c8Sopenharmony_ci                    Var::new(name, None, ty, Some(val), true),
27112a9d9c8Sopenharmony_ci                    Some(cursor),
27212a9d9c8Sopenharmony_ci                ))
27312a9d9c8Sopenharmony_ci            }
27412a9d9c8Sopenharmony_ci            CXCursor_VarDecl => {
27512a9d9c8Sopenharmony_ci                let mut name = cursor.spelling();
27612a9d9c8Sopenharmony_ci                if cursor.linkage() == CXLinkage_External {
27712a9d9c8Sopenharmony_ci                    if let Some(nm) = ctx.options().last_callback(|callbacks| {
27812a9d9c8Sopenharmony_ci                        callbacks.generated_name_override(ItemInfo {
27912a9d9c8Sopenharmony_ci                            name: name.as_str(),
28012a9d9c8Sopenharmony_ci                            kind: ItemKind::Var,
28112a9d9c8Sopenharmony_ci                        })
28212a9d9c8Sopenharmony_ci                    }) {
28312a9d9c8Sopenharmony_ci                        name = nm;
28412a9d9c8Sopenharmony_ci                    }
28512a9d9c8Sopenharmony_ci                }
28612a9d9c8Sopenharmony_ci                // No more changes to name
28712a9d9c8Sopenharmony_ci                let name = name;
28812a9d9c8Sopenharmony_ci
28912a9d9c8Sopenharmony_ci                if name.is_empty() {
29012a9d9c8Sopenharmony_ci                    warn!("Empty constant name?");
29112a9d9c8Sopenharmony_ci                    return Err(ParseError::Continue);
29212a9d9c8Sopenharmony_ci                }
29312a9d9c8Sopenharmony_ci
29412a9d9c8Sopenharmony_ci                let ty = cursor.cur_type();
29512a9d9c8Sopenharmony_ci
29612a9d9c8Sopenharmony_ci                // TODO(emilio): do we have to special-case constant arrays in
29712a9d9c8Sopenharmony_ci                // some other places?
29812a9d9c8Sopenharmony_ci                let is_const = ty.is_const() ||
29912a9d9c8Sopenharmony_ci                    ([CXType_ConstantArray, CXType_IncompleteArray]
30012a9d9c8Sopenharmony_ci                        .contains(&ty.kind()) &&
30112a9d9c8Sopenharmony_ci                        ty.elem_type()
30212a9d9c8Sopenharmony_ci                            .map_or(false, |element| element.is_const()));
30312a9d9c8Sopenharmony_ci
30412a9d9c8Sopenharmony_ci                let ty = match Item::from_ty(&ty, cursor, None, ctx) {
30512a9d9c8Sopenharmony_ci                    Ok(ty) => ty,
30612a9d9c8Sopenharmony_ci                    Err(e) => {
30712a9d9c8Sopenharmony_ci                        assert!(
30812a9d9c8Sopenharmony_ci                            matches!(ty.kind(), CXType_Auto | CXType_Unexposed),
30912a9d9c8Sopenharmony_ci                            "Couldn't resolve constant type, and it \
31012a9d9c8Sopenharmony_ci                             wasn't an nondeductible auto type or unexposed \
31112a9d9c8Sopenharmony_ci                             type!"
31212a9d9c8Sopenharmony_ci                        );
31312a9d9c8Sopenharmony_ci                        return Err(e);
31412a9d9c8Sopenharmony_ci                    }
31512a9d9c8Sopenharmony_ci                };
31612a9d9c8Sopenharmony_ci
31712a9d9c8Sopenharmony_ci                // Note: Ty might not be totally resolved yet, see
31812a9d9c8Sopenharmony_ci                // tests/headers/inner_const.hpp
31912a9d9c8Sopenharmony_ci                //
32012a9d9c8Sopenharmony_ci                // That's fine because in that case we know it's not a literal.
32112a9d9c8Sopenharmony_ci                let canonical_ty = ctx
32212a9d9c8Sopenharmony_ci                    .safe_resolve_type(ty)
32312a9d9c8Sopenharmony_ci                    .and_then(|t| t.safe_canonical_type(ctx));
32412a9d9c8Sopenharmony_ci
32512a9d9c8Sopenharmony_ci                let is_integer = canonical_ty.map_or(false, |t| t.is_integer());
32612a9d9c8Sopenharmony_ci                let is_float = canonical_ty.map_or(false, |t| t.is_float());
32712a9d9c8Sopenharmony_ci
32812a9d9c8Sopenharmony_ci                // TODO: We could handle `char` more gracefully.
32912a9d9c8Sopenharmony_ci                // TODO: Strings, though the lookup is a bit more hard (we need
33012a9d9c8Sopenharmony_ci                // to look at the canonical type of the pointee too, and check
33112a9d9c8Sopenharmony_ci                // is char, u8, or i8 I guess).
33212a9d9c8Sopenharmony_ci                let value = if is_integer {
33312a9d9c8Sopenharmony_ci                    let kind = match *canonical_ty.unwrap().kind() {
33412a9d9c8Sopenharmony_ci                        TypeKind::Int(kind) => kind,
33512a9d9c8Sopenharmony_ci                        _ => unreachable!(),
33612a9d9c8Sopenharmony_ci                    };
33712a9d9c8Sopenharmony_ci
33812a9d9c8Sopenharmony_ci                    let mut val = cursor.evaluate().and_then(|v| v.as_int());
33912a9d9c8Sopenharmony_ci                    if val.is_none() || !kind.signedness_matches(val.unwrap()) {
34012a9d9c8Sopenharmony_ci                        val = get_integer_literal_from_cursor(&cursor);
34112a9d9c8Sopenharmony_ci                    }
34212a9d9c8Sopenharmony_ci
34312a9d9c8Sopenharmony_ci                    val.map(|val| {
34412a9d9c8Sopenharmony_ci                        if kind == IntKind::Bool {
34512a9d9c8Sopenharmony_ci                            VarType::Bool(val != 0)
34612a9d9c8Sopenharmony_ci                        } else {
34712a9d9c8Sopenharmony_ci                            VarType::Int(val)
34812a9d9c8Sopenharmony_ci                        }
34912a9d9c8Sopenharmony_ci                    })
35012a9d9c8Sopenharmony_ci                } else if is_float {
35112a9d9c8Sopenharmony_ci                    cursor
35212a9d9c8Sopenharmony_ci                        .evaluate()
35312a9d9c8Sopenharmony_ci                        .and_then(|v| v.as_double())
35412a9d9c8Sopenharmony_ci                        .map(VarType::Float)
35512a9d9c8Sopenharmony_ci                } else {
35612a9d9c8Sopenharmony_ci                    cursor
35712a9d9c8Sopenharmony_ci                        .evaluate()
35812a9d9c8Sopenharmony_ci                        .and_then(|v| v.as_literal_string())
35912a9d9c8Sopenharmony_ci                        .map(VarType::String)
36012a9d9c8Sopenharmony_ci                };
36112a9d9c8Sopenharmony_ci
36212a9d9c8Sopenharmony_ci                let mangling = cursor_mangling(ctx, &cursor);
36312a9d9c8Sopenharmony_ci                let var = Var::new(name, mangling, ty, value, is_const);
36412a9d9c8Sopenharmony_ci
36512a9d9c8Sopenharmony_ci                Ok(ParseResult::New(var, Some(cursor)))
36612a9d9c8Sopenharmony_ci            }
36712a9d9c8Sopenharmony_ci            _ => {
36812a9d9c8Sopenharmony_ci                /* TODO */
36912a9d9c8Sopenharmony_ci                Err(ParseError::Continue)
37012a9d9c8Sopenharmony_ci            }
37112a9d9c8Sopenharmony_ci        }
37212a9d9c8Sopenharmony_ci    }
37312a9d9c8Sopenharmony_ci}
37412a9d9c8Sopenharmony_ci
37512a9d9c8Sopenharmony_ci/// Try and parse a macro using all the macros parsed until now.
37612a9d9c8Sopenharmony_cifn parse_macro(
37712a9d9c8Sopenharmony_ci    ctx: &BindgenContext,
37812a9d9c8Sopenharmony_ci    cursor: &clang::Cursor,
37912a9d9c8Sopenharmony_ci) -> Option<(Vec<u8>, cexpr::expr::EvalResult)> {
38012a9d9c8Sopenharmony_ci    use cexpr::expr;
38112a9d9c8Sopenharmony_ci
38212a9d9c8Sopenharmony_ci    let cexpr_tokens = cursor.cexpr_tokens();
38312a9d9c8Sopenharmony_ci
38412a9d9c8Sopenharmony_ci    let parser = expr::IdentifierParser::new(ctx.parsed_macros());
38512a9d9c8Sopenharmony_ci
38612a9d9c8Sopenharmony_ci    match parser.macro_definition(&cexpr_tokens) {
38712a9d9c8Sopenharmony_ci        Ok((_, (id, val))) => Some((id.into(), val)),
38812a9d9c8Sopenharmony_ci        _ => None,
38912a9d9c8Sopenharmony_ci    }
39012a9d9c8Sopenharmony_ci}
39112a9d9c8Sopenharmony_ci
39212a9d9c8Sopenharmony_cifn parse_int_literal_tokens(cursor: &clang::Cursor) -> Option<i64> {
39312a9d9c8Sopenharmony_ci    use cexpr::expr;
39412a9d9c8Sopenharmony_ci    use cexpr::expr::EvalResult;
39512a9d9c8Sopenharmony_ci
39612a9d9c8Sopenharmony_ci    let cexpr_tokens = cursor.cexpr_tokens();
39712a9d9c8Sopenharmony_ci
39812a9d9c8Sopenharmony_ci    // TODO(emilio): We can try to parse other kinds of literals.
39912a9d9c8Sopenharmony_ci    match expr::expr(&cexpr_tokens) {
40012a9d9c8Sopenharmony_ci        Ok((_, EvalResult::Int(Wrapping(val)))) => Some(val),
40112a9d9c8Sopenharmony_ci        _ => None,
40212a9d9c8Sopenharmony_ci    }
40312a9d9c8Sopenharmony_ci}
40412a9d9c8Sopenharmony_ci
40512a9d9c8Sopenharmony_cifn get_integer_literal_from_cursor(cursor: &clang::Cursor) -> Option<i64> {
40612a9d9c8Sopenharmony_ci    use clang_sys::*;
40712a9d9c8Sopenharmony_ci    let mut value = None;
40812a9d9c8Sopenharmony_ci    cursor.visit(|c| {
40912a9d9c8Sopenharmony_ci        match c.kind() {
41012a9d9c8Sopenharmony_ci            CXCursor_IntegerLiteral | CXCursor_UnaryOperator => {
41112a9d9c8Sopenharmony_ci                value = parse_int_literal_tokens(&c);
41212a9d9c8Sopenharmony_ci            }
41312a9d9c8Sopenharmony_ci            CXCursor_UnexposedExpr => {
41412a9d9c8Sopenharmony_ci                value = get_integer_literal_from_cursor(&c);
41512a9d9c8Sopenharmony_ci            }
41612a9d9c8Sopenharmony_ci            _ => (),
41712a9d9c8Sopenharmony_ci        }
41812a9d9c8Sopenharmony_ci        if value.is_some() {
41912a9d9c8Sopenharmony_ci            CXChildVisit_Break
42012a9d9c8Sopenharmony_ci        } else {
42112a9d9c8Sopenharmony_ci            CXChildVisit_Continue
42212a9d9c8Sopenharmony_ci        }
42312a9d9c8Sopenharmony_ci    });
42412a9d9c8Sopenharmony_ci    value
42512a9d9c8Sopenharmony_ci}
426