From fc981892eaceb352a8d3edf469023be61802fee1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Emilio=20Cobos=20=C3=81lvarez?= Date: Thu, 9 Jun 2022 19:47:23 +0200 Subject: [PATCH] bindings: Peel through typedefs for struct constant generation. This allows the workaround in #767 to work. --- src/bindgen/bindings.rs | 37 ++++++++++++++++++++++++++++++++++--- src/bindgen/library.rs | 2 ++ 2 files changed, 36 insertions(+), 3 deletions(-) diff --git a/src/bindgen/bindings.rs b/src/bindgen/bindings.rs index 2b0f86a9a..845a4c69c 100644 --- a/src/bindgen/bindings.rs +++ b/src/bindgen/bindings.rs @@ -2,6 +2,7 @@ * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ +use std::borrow::Cow; use std::cell::RefCell; use std::collections::HashMap; use std::fs; @@ -12,7 +13,7 @@ use std::rc::Rc; use crate::bindgen::config::{Config, Language}; use crate::bindgen::ir::{ - Constant, Function, ItemContainer, ItemMap, Path as BindgenPath, Static, Struct, + Constant, Function, ItemContainer, ItemMap, Path as BindgenPath, Static, Struct, Typedef, }; use crate::bindgen::writer::{Source, SourceWriter}; @@ -22,6 +23,7 @@ pub struct Bindings { /// The map from path to struct, used to lookup whether a given type is a /// transparent struct. This is needed to generate code for constants. struct_map: ItemMap, + typedef_map: ItemMap, struct_fileds_memo: RefCell>>>, globals: Vec, constants: Vec, @@ -39,9 +41,11 @@ enum NamespaceOperation { } impl Bindings { + #[allow(clippy::too_many_arguments)] pub(crate) fn new( config: Config, struct_map: ItemMap, + typedef_map: ItemMap, constants: Vec, globals: Vec, items: Vec, @@ -51,6 +55,7 @@ impl Bindings { Bindings { config, struct_map, + typedef_map, struct_fileds_memo: Default::default(), globals, constants, @@ -67,9 +72,30 @@ impl Bindings { any } + /// Peels through typedefs to allow resolving structs. + fn resolved_struct_path<'a>(&self, path: &'a BindgenPath) -> Cow<'a, BindgenPath> { + use crate::bindgen::ir::Type; + + let mut resolved_path = Cow::Borrowed(path); + loop { + let mut found = None; + self.typedef_map.for_items(&resolved_path, |item| { + if let Type::Path(ref p) = item.aliased { + found = Some(p.path().clone()); + } + }); + resolved_path = match found { + Some(p) => Cow::Owned(p), + None => break, + } + } + resolved_path + } + pub fn struct_exists(&self, path: &BindgenPath) -> bool { let mut any = false; - self.struct_map.for_items(path, |_| any = true); + self.struct_map + .for_items(&self.resolved_struct_path(path), |_| any = true); any } @@ -79,8 +105,10 @@ impl Bindings { return memo.clone(); } + let resolved_path = self.resolved_struct_path(path); + let mut fields = Vec::::new(); - self.struct_map.for_items(path, |st| { + self.struct_map.for_items(&resolved_path, |st| { let mut pos: usize = 0; for field in &st.fields { if let Some(found_pos) = fields.iter().position(|v| *v == field.name) { @@ -94,6 +122,9 @@ impl Bindings { let fields = Rc::new(fields); memos.insert(path.clone(), fields.clone()); + if let Cow::Owned(p) = resolved_path { + memos.insert(p, fields.clone()); + } fields } diff --git a/src/bindgen/library.rs b/src/bindgen/library.rs index e7a1891e2..23ec38dc6 100644 --- a/src/bindgen/library.rs +++ b/src/bindgen/library.rs @@ -67,6 +67,7 @@ impl Library { Default::default(), Default::default(), Default::default(), + Default::default(), true, )); } @@ -147,6 +148,7 @@ impl Library { Ok(Bindings::new( self.config, self.structs, + self.typedefs, constants, globals, items,