diff --git a/src/bindgen/declarationtyperesolver.rs b/src/bindgen/declarationtyperesolver.rs index bbdca17..e72761e 100644 --- a/src/bindgen/declarationtyperesolver.rs +++ b/src/bindgen/declarationtyperesolver.rs @@ -2,23 +2,9 @@ * 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::collections::HashSet; - use crate::bindgen::ir::Path; - -#[derive(Default)] -pub struct DeclarationTypeResolver { - structs: HashSet, - enums: HashSet, - unions: HashSet, -} - -#[derive(Clone, Copy, PartialEq, PartialOrd, Eq, Ord, Debug, Hash)] -pub enum DeclarationType { - Struct, - Enum, - Union, -} +use std::collections::hash_map::Entry; +use std::collections::HashMap; impl DeclarationType { pub fn to_str(self) -> &'static str { @@ -30,29 +16,42 @@ impl DeclarationType { } } +#[derive(Clone, Copy, PartialEq, PartialOrd, Eq, Ord, Debug, Hash)] +pub enum DeclarationType { + Struct, + Enum, + Union, +} + +#[derive(Default)] +pub struct DeclarationTypeResolver { + types: HashMap>, +} + impl DeclarationTypeResolver { + fn insert(&mut self, path: &Path, ty: Option) { + if let Entry::Vacant(vacant_entry) = self.types.entry(path.clone()) { + vacant_entry.insert(ty); + } + } + pub fn add_enum(&mut self, path: &Path) { - self.enums.insert(path.clone()); + self.insert(path, Some(DeclarationType::Enum)); } pub fn add_struct(&mut self, path: &Path) { - self.structs.insert(path.clone()); + self.insert(path, Some(DeclarationType::Struct)); } pub fn add_union(&mut self, path: &Path) { - self.unions.insert(path.clone()); + self.insert(path, Some(DeclarationType::Union)); + } + + pub fn add_none(&mut self, path: &Path) { + self.insert(path, None); } pub fn type_for(&self, path: &Path) -> Option { - // FIXME: don't look up by name, but by full path: - if self.structs.contains(path) { - Some(DeclarationType::Struct) - } else if self.enums.contains(path) { - Some(DeclarationType::Enum) - } else if self.unions.contains(path) { - Some(DeclarationType::Union) - } else { - None - } + *self.types.get(path)? } } diff --git a/src/bindgen/ir/enumeration.rs b/src/bindgen/ir/enumeration.rs index 7359e19..9d96b4c 100644 --- a/src/bindgen/ir/enumeration.rs +++ b/src/bindgen/ir/enumeration.rs @@ -476,12 +476,17 @@ impl Item for Enum { } fn collect_declaration_types(&self, resolver: &mut DeclarationTypeResolver) { - if self.tag.is_some() && self.repr.style == ReprStyle::C { - resolver.add_struct(&self.path); - } else if self.tag.is_some() && self.repr.style != ReprStyle::C { - resolver.add_union(&self.path); + if self.tag.is_some() { + if self.repr.style == ReprStyle::C { + resolver.add_struct(&self.path); + } else { + resolver.add_union(&self.path); + } } else if self.repr.style == ReprStyle::C { resolver.add_enum(&self.path); + } else { + // This is important to handle conflicting names with opaque items. + resolver.add_none(&self.path); } } diff --git a/src/bindgen/ir/structure.rs b/src/bindgen/ir/structure.rs index 8686758..05539eb 100644 --- a/src/bindgen/ir/structure.rs +++ b/src/bindgen/ir/structure.rs @@ -266,7 +266,9 @@ impl Item for Struct { } fn collect_declaration_types(&self, resolver: &mut DeclarationTypeResolver) { - if !self.is_transparent { + if self.is_transparent { + resolver.add_none(&self.path); + } else { resolver.add_struct(&self.path); } } diff --git a/src/bindgen/ir/typedef.rs b/src/bindgen/ir/typedef.rs index 9c779a4..61c071b 100644 --- a/src/bindgen/ir/typedef.rs +++ b/src/bindgen/ir/typedef.rs @@ -138,6 +138,10 @@ impl Item for Typedef { self.aliased.rename_for_config(config, &self.generic_params); } + fn collect_declaration_types(&self, resolver: &mut DeclarationTypeResolver) { + resolver.add_none(&self.path); + } + fn resolve_declaration_types(&mut self, resolver: &DeclarationTypeResolver) { self.aliased.resolve_declaration_types(resolver); } diff --git a/src/bindgen/library.rs b/src/bindgen/library.rs index 855cca2..b1f9eb4 100644 --- a/src/bindgen/library.rs +++ b/src/bindgen/library.rs @@ -318,10 +318,6 @@ impl Library { x.collect_declaration_types(&mut resolver); }); - self.opaque_items.for_all_items(|x| { - x.collect_declaration_types(&mut resolver); - }); - self.enums.for_all_items(|x| { x.collect_declaration_types(&mut resolver); }); @@ -330,6 +326,16 @@ impl Library { x.collect_declaration_types(&mut resolver); }); + self.typedefs.for_all_items(|x| { + x.collect_declaration_types(&mut resolver); + }); + + // NOTE: Intentionally last, so that in case there's an opaque type + // which is conflicting with a non-opaque one, the later wins. + self.opaque_items.for_all_items(|x| { + x.collect_declaration_types(&mut resolver); + }); + self.enums .for_all_items_mut(|x| x.resolve_declaration_types(&resolver)); diff --git a/tests/expectations/decl_name_conflicting.both.c b/tests/expectations/decl_name_conflicting.both.c new file mode 100644 index 0000000..486b31c --- /dev/null +++ b/tests/expectations/decl_name_conflicting.both.c @@ -0,0 +1,16 @@ +#include +#include +#include +#include + +enum BindingType { + Buffer = 0, + NotBuffer = 1, +}; +typedef uint32_t BindingType; + +typedef struct BindGroupLayoutEntry { + BindingType ty; +} BindGroupLayoutEntry; + +void root(struct BindGroupLayoutEntry entry); diff --git a/tests/expectations/decl_name_conflicting.both.compat.c b/tests/expectations/decl_name_conflicting.both.compat.c new file mode 100644 index 0000000..e8a8d49 --- /dev/null +++ b/tests/expectations/decl_name_conflicting.both.compat.c @@ -0,0 +1,30 @@ +#include +#include +#include +#include + +enum BindingType +#ifdef __cplusplus + : uint32_t +#endif // __cplusplus + { + Buffer = 0, + NotBuffer = 1, +}; +#ifndef __cplusplus +typedef uint32_t BindingType; +#endif // __cplusplus + +typedef struct BindGroupLayoutEntry { + BindingType ty; +} BindGroupLayoutEntry; + +#ifdef __cplusplus +extern "C" { +#endif // __cplusplus + +void root(struct BindGroupLayoutEntry entry); + +#ifdef __cplusplus +} // extern "C" +#endif // __cplusplus diff --git a/tests/expectations/decl_name_conflicting.c b/tests/expectations/decl_name_conflicting.c new file mode 100644 index 0000000..41a148e --- /dev/null +++ b/tests/expectations/decl_name_conflicting.c @@ -0,0 +1,16 @@ +#include +#include +#include +#include + +enum BindingType { + Buffer = 0, + NotBuffer = 1, +}; +typedef uint32_t BindingType; + +typedef struct { + BindingType ty; +} BindGroupLayoutEntry; + +void root(BindGroupLayoutEntry entry); diff --git a/tests/expectations/decl_name_conflicting.compat.c b/tests/expectations/decl_name_conflicting.compat.c new file mode 100644 index 0000000..a78700f --- /dev/null +++ b/tests/expectations/decl_name_conflicting.compat.c @@ -0,0 +1,30 @@ +#include +#include +#include +#include + +enum BindingType +#ifdef __cplusplus + : uint32_t +#endif // __cplusplus + { + Buffer = 0, + NotBuffer = 1, +}; +#ifndef __cplusplus +typedef uint32_t BindingType; +#endif // __cplusplus + +typedef struct { + BindingType ty; +} BindGroupLayoutEntry; + +#ifdef __cplusplus +extern "C" { +#endif // __cplusplus + +void root(BindGroupLayoutEntry entry); + +#ifdef __cplusplus +} // extern "C" +#endif // __cplusplus diff --git a/tests/expectations/decl_name_conflicting.cpp b/tests/expectations/decl_name_conflicting.cpp new file mode 100644 index 0000000..74c2ae1 --- /dev/null +++ b/tests/expectations/decl_name_conflicting.cpp @@ -0,0 +1,20 @@ +#include +#include +#include +#include +#include + +enum class BindingType : uint32_t { + Buffer = 0, + NotBuffer = 1, +}; + +struct BindGroupLayoutEntry { + BindingType ty; +}; + +extern "C" { + +void root(BindGroupLayoutEntry entry); + +} // extern "C" diff --git a/tests/expectations/decl_name_conflicting.pyx b/tests/expectations/decl_name_conflicting.pyx new file mode 100644 index 0000000..d7dbc5e --- /dev/null +++ b/tests/expectations/decl_name_conflicting.pyx @@ -0,0 +1,17 @@ +from libc.stdint cimport int8_t, int16_t, int32_t, int64_t, intptr_t +from libc.stdint cimport uint8_t, uint16_t, uint32_t, uint64_t, uintptr_t +cdef extern from *: + ctypedef bint bool + ctypedef struct va_list + +cdef extern from *: + + cdef enum: + Buffer # = 0, + NotBuffer # = 1, + ctypedef uint32_t BindingType; + + ctypedef struct BindGroupLayoutEntry: + BindingType ty; + + void root(BindGroupLayoutEntry entry); diff --git a/tests/expectations/decl_name_conflicting.tag.c b/tests/expectations/decl_name_conflicting.tag.c new file mode 100644 index 0000000..7504e4a --- /dev/null +++ b/tests/expectations/decl_name_conflicting.tag.c @@ -0,0 +1,16 @@ +#include +#include +#include +#include + +enum BindingType { + Buffer = 0, + NotBuffer = 1, +}; +typedef uint32_t BindingType; + +struct BindGroupLayoutEntry { + BindingType ty; +}; + +void root(struct BindGroupLayoutEntry entry); diff --git a/tests/expectations/decl_name_conflicting.tag.compat.c b/tests/expectations/decl_name_conflicting.tag.compat.c new file mode 100644 index 0000000..6011756 --- /dev/null +++ b/tests/expectations/decl_name_conflicting.tag.compat.c @@ -0,0 +1,30 @@ +#include +#include +#include +#include + +enum BindingType +#ifdef __cplusplus + : uint32_t +#endif // __cplusplus + { + Buffer = 0, + NotBuffer = 1, +}; +#ifndef __cplusplus +typedef uint32_t BindingType; +#endif // __cplusplus + +struct BindGroupLayoutEntry { + BindingType ty; +}; + +#ifdef __cplusplus +extern "C" { +#endif // __cplusplus + +void root(struct BindGroupLayoutEntry entry); + +#ifdef __cplusplus +} // extern "C" +#endif // __cplusplus diff --git a/tests/expectations/decl_name_conflicting.tag.pyx b/tests/expectations/decl_name_conflicting.tag.pyx new file mode 100644 index 0000000..82ebc2f --- /dev/null +++ b/tests/expectations/decl_name_conflicting.tag.pyx @@ -0,0 +1,17 @@ +from libc.stdint cimport int8_t, int16_t, int32_t, int64_t, intptr_t +from libc.stdint cimport uint8_t, uint16_t, uint32_t, uint64_t, uintptr_t +cdef extern from *: + ctypedef bint bool + ctypedef struct va_list + +cdef extern from *: + + cdef enum: + Buffer # = 0, + NotBuffer # = 1, + ctypedef uint32_t BindingType; + + cdef struct BindGroupLayoutEntry: + BindingType ty; + + void root(BindGroupLayoutEntry entry); diff --git a/tests/rust/decl_name_conflicting.rs b/tests/rust/decl_name_conflicting.rs new file mode 100644 index 0000000..39e9658 --- /dev/null +++ b/tests/rust/decl_name_conflicting.rs @@ -0,0 +1,14 @@ +mod uhoh { + enum BindingType { Buffer, NotBuffer } +} + +#[repr(u32)] +pub enum BindingType { Buffer = 0, NotBuffer = 1 } + +#[repr(C)] +pub struct BindGroupLayoutEntry { + pub ty: BindingType, // This is the repr(u32) enum +} + +#[no_mangle] +pub extern "C" fn root(entry: BindGroupLayoutEntry) {}