diff --git a/src/bindgen/cdecl.rs b/src/bindgen/cdecl.rs index 8075f97e5..f86c912a1 100644 --- a/src/bindgen/cdecl.rs +++ b/src/bindgen/cdecl.rs @@ -99,7 +99,9 @@ impl CDecl { fn build_type(&mut self, t: &Type, is_const: bool, config: &Config) { match t { - Type::Path(ref generic) => { + Type::Path { + path: ref generic, .. + } => { if is_const { assert!( self.type_qualifers.is_empty(), diff --git a/src/bindgen/ir/enumeration.rs b/src/bindgen/ir/enumeration.rs index ec8607731..776573d52 100644 --- a/src/bindgen/ir/enumeration.rs +++ b/src/bindgen/ir/enumeration.rs @@ -116,7 +116,7 @@ impl EnumVariant { if inline_tag_field { res.push(Field::from_name_and_type( inline_name.map_or_else(|| "tag".to_string(), |name| format!("{}_tag", name)), - Type::Path(GenericPath::new(Path::new("Tag"), vec![])), + Type::for_path(GenericPath::new(Path::new("Tag"), vec![])), )); } @@ -507,7 +507,7 @@ impl Item for Enum { if let VariantBody::Body { ref mut body, .. } = variant.body { let path = Path::new(new_tag.clone()); let generic_path = GenericPath::new(path, vec![]); - body.fields[0].ty = Type::Path(generic_path); + body.fields[0].ty = Type::for_path(generic_path); } } } diff --git a/src/bindgen/ir/function.rs b/src/bindgen/ir/function.rs index 6d310aaa8..dc8ac0778 100644 --- a/src/bindgen/ir/function.rs +++ b/src/bindgen/ir/function.rs @@ -17,6 +17,7 @@ use crate::bindgen::library::Library; use crate::bindgen::monomorph::Monomorphs; use crate::bindgen::rename::{IdentifierType, RenameRule}; use crate::bindgen::reserved; +use crate::bindgen::transparent_types::TransparentTypes; use crate::bindgen::utilities::IterHelpers; use crate::bindgen::writer::{Source, SourceWriter}; @@ -127,10 +128,14 @@ impl Function { &self.path } - pub fn simplify_standard_types(&mut self, config: &Config) { - self.ret.simplify_standard_types(config); + pub fn simplify_standard_types( + &mut self, + config: &Config, + transparent_types: &TransparentTypes, + ) { + self.ret.simplify_standard_types(config, transparent_types); for arg in &mut self.args { - arg.ty.simplify_standard_types(config); + arg.ty.simplify_standard_types(config, transparent_types); } } @@ -347,7 +352,7 @@ trait SynFnArgHelpers { } fn gen_self_type(receiver: &syn::Receiver) -> Type { - let self_ty = Type::Path(GenericPath::self_path()); + let self_ty = Type::for_path(GenericPath::self_path()); if receiver.reference.is_none() { return self_ty; } diff --git a/src/bindgen/ir/global.rs b/src/bindgen/ir/global.rs index a9d989df8..047f6b96c 100644 --- a/src/bindgen/ir/global.rs +++ b/src/bindgen/ir/global.rs @@ -10,6 +10,7 @@ use crate::bindgen::declarationtyperesolver::DeclarationTypeResolver; use crate::bindgen::dependencies::Dependencies; use crate::bindgen::ir::{AnnotationSet, Cfg, Documentation, Item, ItemContainer, Path, Type}; use crate::bindgen::library::Library; +use crate::bindgen::transparent_types::TransparentTypes; use crate::bindgen::writer::{Source, SourceWriter}; #[derive(Debug, Clone)] @@ -61,8 +62,12 @@ impl Static { } } - pub fn simplify_standard_types(&mut self, config: &Config) { - self.ty.simplify_standard_types(config); + pub fn simplify_standard_types( + &mut self, + config: &Config, + transparent_types: &TransparentTypes, + ) { + self.ty.simplify_standard_types(config, transparent_types); } } diff --git a/src/bindgen/ir/structure.rs b/src/bindgen/ir/structure.rs index 206f04c8e..23f5465e7 100644 --- a/src/bindgen/ir/structure.rs +++ b/src/bindgen/ir/structure.rs @@ -16,6 +16,7 @@ use crate::bindgen::mangle; use crate::bindgen::monomorph::Monomorphs; use crate::bindgen::rename::{IdentifierType, RenameRule}; use crate::bindgen::reserved; +use crate::bindgen::transparent_types::TransparentTypes; use crate::bindgen::utilities::IterHelpers; use crate::bindgen::writer::{ListType, Source, SourceWriter}; @@ -142,9 +143,13 @@ impl Struct { } } - pub fn simplify_standard_types(&mut self, config: &Config) { + pub fn simplify_standard_types( + &mut self, + config: &Config, + transparent_types: &TransparentTypes, + ) { for field in &mut self.fields { - field.ty.simplify_standard_types(config); + field.ty.simplify_standard_types(config, transparent_types); } } diff --git a/src/bindgen/ir/ty.rs b/src/bindgen/ir/ty.rs index e4452f391..895cf68ed 100644 --- a/src/bindgen/ir/ty.rs +++ b/src/bindgen/ir/ty.rs @@ -12,6 +12,7 @@ use crate::bindgen::dependencies::Dependencies; use crate::bindgen::ir::{GenericParams, GenericPath, Path}; use crate::bindgen::library::Library; use crate::bindgen::monomorph::Monomorphs; +use crate::bindgen::transparent_types::TransparentTypes; use crate::bindgen::utilities::IterHelpers; use crate::bindgen::writer::{Source, SourceWriter}; @@ -340,7 +341,11 @@ pub enum Type { // to code generation or something. is_ref: bool, }, - Path(GenericPath), + Path { + path: GenericPath, + is_nullable: bool, + is_zeroable: bool, + }, Primitive(PrimitiveType), Array(Box, ArrayLength), FuncPtr { @@ -360,6 +365,16 @@ impl Type { } } + pub fn for_path(path: GenericPath) -> Self { + Type::Path { + path, + // Assume that the type this name refers to is both nullable and zeroable, until we + // find otherwise. + is_nullable: true, + is_zeroable: true, + } + } + pub fn load(ty: &syn::Type) -> Result, String> { let converted = match *ty { syn::Type::Reference(ref reference) => { @@ -408,7 +423,7 @@ impl Type { } Type::Primitive(prim) } else { - Type::Path(generic_path) + Type::for_path(generic_path) } } syn::Type::Array(syn::TypeArray { @@ -509,21 +524,45 @@ impl Type { } } + pub fn is_zeroable(&self) -> bool { + match *self { + Type::Primitive(PrimitiveType::Integer { zeroable, .. }) => zeroable, + Type::Path { is_zeroable, .. } => is_zeroable, + _ => true, + } + } + pub fn make_zeroable(&self) -> Option { - let (kind, signed) = match *self { + match *self { Type::Primitive(PrimitiveType::Integer { + kind, + signed, zeroable: false, + }) => Some(Type::Primitive(PrimitiveType::Integer { kind, signed, - }) => (kind, signed), - _ => return None, - }; + zeroable: true, + })), + Type::Path { + ref path, + is_nullable, + is_zeroable: false, + } => Some(Type::Path { + path: path.clone(), + is_nullable, + is_zeroable: true, + }), + _ => None, + } + } - Some(Type::Primitive(PrimitiveType::Integer { - kind, - signed, - zeroable: true, - })) + pub fn is_nullable(&self) -> bool { + match *self { + Type::Ptr { is_nullable, .. } => is_nullable, + Type::FuncPtr { is_nullable, .. } => is_nullable, + Type::Path { is_nullable, .. } => is_nullable, + _ => true, + } } pub fn make_nullable(&self) -> Option { @@ -548,13 +587,22 @@ impl Type { args: args.clone(), is_nullable: true, }), + Type::Path { + ref path, + is_nullable: false, + is_zeroable, + } => Some(Type::Path { + path: path.clone(), + is_nullable: true, + is_zeroable, + }), _ => None, } } fn nonzero_to_primitive(&self) -> Option { let path = match *self { - Type::Path(ref p) => p, + Type::Path { ref path, .. } => path, _ => return None, }; @@ -588,14 +636,44 @@ impl Type { })) } - fn simplified_type(&self, config: &Config) -> Option { + fn simplified_type( + &self, + config: &Config, + transparent_types: &TransparentTypes, + ) -> Option { let path = match *self { - Type::Path(ref p) => p, + Type::Path { ref path, .. } => path, _ => return None, }; if path.generics().is_empty() { - return self.nonzero_to_primitive(); + let primitive = self.nonzero_to_primitive(); + if primitive.is_some() { + return primitive; + } + } + + // Repeatedly follow any typedefs or transparent structs until we reach a "real" type, and + // look up whether it is nullable and/or zeroable, saving that information so that we can + // use it later. + if let Some(transparent) = transparent_types.is_transparent(self) { + // Make sure to do another round of simplifying each time we follow a typedef or + // transparent struct link. + let mut current = match transparent.simplified_type(config, transparent_types) { + Some(current) => current, + None => transparent, + }; + while let Some(transparent) = transparent_types.is_transparent(¤t) { + current = match transparent.simplified_type(config, transparent_types) { + Some(current) => current, + None => transparent, + }; + } + return Some(Type::Path { + path: path.clone(), + is_nullable: current.is_nullable(), + is_zeroable: current.is_zeroable(), + }); } if path.generics().len() != 1 { @@ -603,7 +681,7 @@ impl Type { } let unsimplified_generic = &path.generics()[0]; - let generic = match unsimplified_generic.simplified_type(config) { + let generic = match unsimplified_generic.simplified_type(config, transparent_types) { Some(generic) => Cow::Owned(generic), None => Cow::Borrowed(unsimplified_generic), }; @@ -637,15 +715,23 @@ impl Type { } } - pub fn simplify_standard_types(&mut self, config: &Config) { - self.visit_types(|ty| ty.simplify_standard_types(config)); - if let Some(ty) = self.simplified_type(config) { + pub fn simplify_standard_types( + &mut self, + config: &Config, + transparent_types: &TransparentTypes, + ) { + self.visit_types(|ty| ty.simplify_standard_types(config, transparent_types)); + if let Some(ty) = self.simplified_type(config, transparent_types) { *self = ty; } } pub fn replace_self_with(&mut self, self_ty: &Path) { - if let Type::Path(ref mut generic_path) = *self { + if let Type::Path { + path: ref mut generic_path, + .. + } = *self + { generic_path.replace_self_with(self_ty); } self.visit_types(|ty| ty.replace_self_with(self_ty)) @@ -654,7 +740,7 @@ impl Type { fn visit_types(&mut self, mut visitor: impl FnMut(&mut Type)) { match *self { Type::Array(ref mut ty, ..) | Type::Ptr { ref mut ty, .. } => visitor(ty), - Type::Path(ref mut path) => { + Type::Path { ref mut path, .. } => { for generic in path.generics_mut() { visitor(generic); } @@ -678,7 +764,9 @@ impl Type { loop { match *current { Type::Ptr { ref ty, .. } => current = ty, - Type::Path(ref generic) => { + Type::Path { + path: ref generic, .. + } => { return Some(generic.path().clone()); } Type::Primitive(..) => { @@ -707,7 +795,10 @@ impl Type { is_nullable, is_ref, }, - Type::Path(ref generic_path) => { + Type::Path { + path: ref generic_path, + .. + } => { for &(param, value) in mappings { if generic_path.path() == param { return value.clone(); @@ -722,7 +813,7 @@ impl Type { .map(|x| x.specialize(mappings)) .collect(), ); - Type::Path(specialized) + Type::for_path(specialized) } Type::Primitive(ref primitive) => Type::Primitive(primitive.clone()), Type::Array(ref ty, ref constant) => { @@ -754,7 +845,9 @@ impl Type { Type::Ptr { ref ty, .. } => { ty.add_dependencies_ignoring_generics(generic_params, library, out); } - Type::Path(ref generic) => { + Type::Path { + path: ref generic, .. + } => { for generic_value in generic.generics() { generic_value.add_dependencies_ignoring_generics(generic_params, library, out); } @@ -804,7 +897,9 @@ impl Type { Type::Ptr { ref ty, .. } => { ty.add_monomorphs(library, out); } - Type::Path(ref generic) => { + Type::Path { + path: ref generic, .. + } => { if generic.generics().is_empty() || out.contains(&generic) { return; } @@ -836,7 +931,9 @@ impl Type { Type::Ptr { ref mut ty, .. } => { ty.rename_for_config(config, generic_params); } - Type::Path(ref mut ty) => { + Type::Path { + path: ref mut ty, .. + } => { ty.rename_for_config(config, generic_params); } Type::Primitive(_) => {} @@ -862,7 +959,10 @@ impl Type { Type::Ptr { ref mut ty, .. } => { ty.resolve_declaration_types(resolver); } - Type::Path(ref mut generic_path) => { + Type::Path { + path: ref mut generic_path, + .. + } => { generic_path.resolve_declaration_types(resolver); } Type::Primitive(_) => {} @@ -887,7 +987,10 @@ impl Type { Type::Ptr { ref mut ty, .. } => { ty.mangle_paths(monomorphs); } - Type::Path(ref mut generic_path) => { + Type::Path { + path: ref mut generic_path, + .. + } => { if generic_path.generics().is_empty() { return; } @@ -923,7 +1026,7 @@ impl Type { match *self { // FIXME: Shouldn't this look at ty.can_cmp_order() as well? Type::Ptr { is_ref, .. } => !is_ref, - Type::Path(..) => true, + Type::Path { .. } => true, Type::Primitive(ref p) => p.can_cmp_order(), Type::Array(..) => false, Type::FuncPtr { .. } => false, @@ -933,7 +1036,7 @@ impl Type { pub fn can_cmp_eq(&self) -> bool { match *self { Type::Ptr { ref ty, is_ref, .. } => !is_ref || ty.can_cmp_eq(), - Type::Path(..) => true, + Type::Path { .. } => true, Type::Primitive(ref p) => p.can_cmp_eq(), Type::Array(..) => false, Type::FuncPtr { .. } => true, diff --git a/src/bindgen/ir/typedef.rs b/src/bindgen/ir/typedef.rs index d7e02a344..43838c223 100644 --- a/src/bindgen/ir/typedef.rs +++ b/src/bindgen/ir/typedef.rs @@ -15,6 +15,7 @@ use crate::bindgen::ir::{ use crate::bindgen::library::Library; use crate::bindgen::mangle; use crate::bindgen::monomorph::Monomorphs; +use crate::bindgen::transparent_types::TransparentTypes; use crate::bindgen::writer::{Source, SourceWriter}; /// A type alias that is represented as a C typedef @@ -66,8 +67,13 @@ impl Typedef { } } - pub fn simplify_standard_types(&mut self, config: &Config) { - self.aliased.simplify_standard_types(config); + pub fn simplify_standard_types( + &mut self, + config: &Config, + transparent_types: &TransparentTypes, + ) { + self.aliased + .simplify_standard_types(config, transparent_types); } pub fn transfer_annotations(&mut self, out: &mut HashMap) { diff --git a/src/bindgen/ir/union.rs b/src/bindgen/ir/union.rs index 6254a99b6..efa2a5772 100644 --- a/src/bindgen/ir/union.rs +++ b/src/bindgen/ir/union.rs @@ -15,6 +15,7 @@ use crate::bindgen::library::Library; use crate::bindgen::mangle; use crate::bindgen::monomorph::Monomorphs; use crate::bindgen::rename::{IdentifierType, RenameRule}; +use crate::bindgen::transparent_types::TransparentTypes; use crate::bindgen::utilities::IterHelpers; use crate::bindgen::writer::{ListType, Source, SourceWriter}; @@ -95,9 +96,13 @@ impl Union { } } - pub fn simplify_standard_types(&mut self, config: &Config) { + pub fn simplify_standard_types( + &mut self, + config: &Config, + transparent_types: &TransparentTypes, + ) { for field in &mut self.fields { - field.ty.simplify_standard_types(config); + field.ty.simplify_standard_types(config, transparent_types); } } diff --git a/src/bindgen/library.rs b/src/bindgen/library.rs index b1f9eb457..8cbceb2d6 100644 --- a/src/bindgen/library.rs +++ b/src/bindgen/library.rs @@ -12,6 +12,7 @@ use crate::bindgen::error::Error; use crate::bindgen::ir::{Constant, Enum, Function, Item, ItemContainer, ItemMap}; use crate::bindgen::ir::{OpaqueItem, Path, Static, Struct, Typedef, Union}; use crate::bindgen::monomorph::Monomorphs; +use crate::bindgen::transparent_types::TransparentTypes; use crate::bindgen::ItemType; #[derive(Debug, Clone)] @@ -358,21 +359,24 @@ impl Library { fn simplify_standard_types(&mut self) { let config = &self.config; + let mut transparent_types = TransparentTypes::default(); + transparent_types.add_structs(&self.structs); + transparent_types.add_typedefs(&self.typedefs); self.structs.for_all_items_mut(|x| { - x.simplify_standard_types(config); + x.simplify_standard_types(config, &transparent_types); }); self.unions.for_all_items_mut(|x| { - x.simplify_standard_types(config); + x.simplify_standard_types(config, &transparent_types); }); self.globals.for_all_items_mut(|x| { - x.simplify_standard_types(config); + x.simplify_standard_types(config, &transparent_types); }); self.typedefs.for_all_items_mut(|x| { - x.simplify_standard_types(config); + x.simplify_standard_types(config, &transparent_types); }); for x in &mut self.functions { - x.simplify_standard_types(config); + x.simplify_standard_types(config, &transparent_types); } } diff --git a/src/bindgen/mangle.rs b/src/bindgen/mangle.rs index 909b4659c..d260916e1 100644 --- a/src/bindgen/mangle.rs +++ b/src/bindgen/mangle.rs @@ -66,7 +66,9 @@ impl<'a> Mangler<'a> { fn append_mangled_type(&mut self, ty: &Type, last: bool) { match *ty { - Type::Path(ref generic) => { + Type::Path { + path: ref generic, .. + } => { let sub_path = Mangler::new(generic.export_name(), generic.generics(), last, self.config) .mangle(); @@ -163,7 +165,7 @@ fn generics() { fn generic_path(path: &str, generics: &[Type]) -> Type { let path = Path::new(path); let generic_path = GenericPath::new(path, generics.to_owned()); - Type::Path(generic_path) + Type::for_path(generic_path) } // Foo => Foo_f32 diff --git a/src/bindgen/mod.rs b/src/bindgen/mod.rs index d0789da2e..d535986c8 100644 --- a/src/bindgen/mod.rs +++ b/src/bindgen/mod.rs @@ -52,6 +52,7 @@ mod monomorph; mod parser; mod rename; mod reserved; +mod transparent_types; mod utilities; mod writer; diff --git a/src/bindgen/transparent_types.rs b/src/bindgen/transparent_types.rs new file mode 100644 index 000000000..9a027bf7a --- /dev/null +++ b/src/bindgen/transparent_types.rs @@ -0,0 +1,49 @@ +/* This Source Code Form is subject to the terms of the Mozilla Public + * 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::HashMap; + +use crate::bindgen::ir::{GenericParams, ItemMap, Path, Struct, Type, Typedef}; + +/// Keeps track of named types that have the same underlying representation as some other type. +/// This happens via `#[repr(transparent)]` structs and via typedefs. +#[derive(Default)] +pub struct TransparentTypes { + transparent: HashMap, +} + +impl TransparentTypes { + pub fn add_structs(&mut self, structs: &ItemMap) { + structs.for_all_items(|s| { + if s.is_transparent { + self.transparent.insert( + s.path.clone(), + (s.fields[0].ty.clone(), s.generic_params.clone()), + ); + } + }); + } + + pub fn add_typedefs(&mut self, structs: &ItemMap) { + structs.for_all_items(|t| { + self.transparent.insert( + t.path.clone(), + (t.aliased.clone(), t.generic_params.clone()), + ); + }); + } + + pub fn is_transparent(&self, ty: &Type) -> Option { + let generic_path = match ty { + Type::Path { path, .. } => path, + _ => return None, + }; + let (resolved, generic_params) = self.transparent.get(generic_path.path())?; + let mappings = generic_params + .iter() + .zip(generic_path.generics()) + .collect::>(); + Some(resolved.specialize(&mappings)) + } +} diff --git a/tests/expectations/exclude_generic_monomorph.both.c b/tests/expectations/exclude_generic_monomorph.both.c index 09b5455dd..3cd22c934 100644 --- a/tests/expectations/exclude_generic_monomorph.both.c +++ b/tests/expectations/exclude_generic_monomorph.both.c @@ -21,8 +21,10 @@ ctypedef uint64_t Option_Foo #include #include +typedef uint64_t Foo; + typedef struct Bar { - Option_Foo foo; + Foo foo; } Bar; void root(struct Bar f); diff --git a/tests/expectations/exclude_generic_monomorph.both.compat.c b/tests/expectations/exclude_generic_monomorph.both.compat.c index 3c1037efc..ff29fd834 100644 --- a/tests/expectations/exclude_generic_monomorph.both.compat.c +++ b/tests/expectations/exclude_generic_monomorph.both.compat.c @@ -21,8 +21,10 @@ ctypedef uint64_t Option_Foo #include #include +typedef uint64_t Foo; + typedef struct Bar { - Option_Foo foo; + Foo foo; } Bar; #ifdef __cplusplus diff --git a/tests/expectations/exclude_generic_monomorph.c b/tests/expectations/exclude_generic_monomorph.c index a593dd7ab..0c1d6df95 100644 --- a/tests/expectations/exclude_generic_monomorph.c +++ b/tests/expectations/exclude_generic_monomorph.c @@ -21,8 +21,10 @@ ctypedef uint64_t Option_Foo #include #include +typedef uint64_t Foo; + typedef struct { - Option_Foo foo; + Foo foo; } Bar; void root(Bar f); diff --git a/tests/expectations/exclude_generic_monomorph.compat.c b/tests/expectations/exclude_generic_monomorph.compat.c index 5c10d43a1..3db201cbd 100644 --- a/tests/expectations/exclude_generic_monomorph.compat.c +++ b/tests/expectations/exclude_generic_monomorph.compat.c @@ -21,8 +21,10 @@ ctypedef uint64_t Option_Foo #include #include +typedef uint64_t Foo; + typedef struct { - Option_Foo foo; + Foo foo; } Bar; #ifdef __cplusplus diff --git a/tests/expectations/exclude_generic_monomorph.cpp b/tests/expectations/exclude_generic_monomorph.cpp index 09b5455dd..3cd22c934 100644 --- a/tests/expectations/exclude_generic_monomorph.cpp +++ b/tests/expectations/exclude_generic_monomorph.cpp @@ -21,8 +21,10 @@ ctypedef uint64_t Option_Foo #include #include +typedef uint64_t Foo; + typedef struct Bar { - Option_Foo foo; + Foo foo; } Bar; void root(struct Bar f); diff --git a/tests/expectations/exclude_generic_monomorph.pyx b/tests/expectations/exclude_generic_monomorph.pyx index 48cd1e242..685ff9b56 100644 --- a/tests/expectations/exclude_generic_monomorph.pyx +++ b/tests/expectations/exclude_generic_monomorph.pyx @@ -24,7 +24,9 @@ cdef extern from *: cdef extern from *: + ctypedef uint64_t Foo; + ctypedef struct Bar: - Option_Foo foo; + Foo foo; void root(Bar f); diff --git a/tests/expectations/exclude_generic_monomorph.tag.c b/tests/expectations/exclude_generic_monomorph.tag.c index 116a170fc..cc50effd0 100644 --- a/tests/expectations/exclude_generic_monomorph.tag.c +++ b/tests/expectations/exclude_generic_monomorph.tag.c @@ -21,8 +21,10 @@ ctypedef uint64_t Option_Foo #include #include +typedef uint64_t Foo; + struct Bar { - Option_Foo foo; + Foo foo; }; void root(struct Bar f); diff --git a/tests/expectations/exclude_generic_monomorph.tag.compat.c b/tests/expectations/exclude_generic_monomorph.tag.compat.c index fa8e3a101..3bd4d5037 100644 --- a/tests/expectations/exclude_generic_monomorph.tag.compat.c +++ b/tests/expectations/exclude_generic_monomorph.tag.compat.c @@ -21,8 +21,10 @@ ctypedef uint64_t Option_Foo #include #include +typedef uint64_t Foo; + struct Bar { - Option_Foo foo; + Foo foo; }; #ifdef __cplusplus diff --git a/tests/expectations/exclude_generic_monomorph.tag.pyx b/tests/expectations/exclude_generic_monomorph.tag.pyx index 934536f40..514f5fa88 100644 --- a/tests/expectations/exclude_generic_monomorph.tag.pyx +++ b/tests/expectations/exclude_generic_monomorph.tag.pyx @@ -24,7 +24,9 @@ cdef extern from *: cdef extern from *: + ctypedef uint64_t Foo; + cdef struct Bar: - Option_Foo foo; + Foo foo; void root(Bar f); diff --git a/tests/expectations/nested_nonnull.both.c b/tests/expectations/nested_nonnull.both.c new file mode 100644 index 000000000..8266b1a88 --- /dev/null +++ b/tests/expectations/nested_nonnull.both.c @@ -0,0 +1,21 @@ +#include +#include +#include +#include + +typedef int32_t (*DoFn)(int32_t x, int32_t y); + +typedef struct StructWithOptionalFunctionPointer { + DoFn func; + DoFn maybe_func; +} StructWithOptionalFunctionPointer; + +typedef uint32_t *NonNullAlias_u32; + +typedef struct StructWithOptionalNonNullPointer { + NonNullAlias_u32 data; + NonNullAlias_u32 maybe_data; +} StructWithOptionalNonNullPointer; + +void root(struct StructWithOptionalFunctionPointer swofp, + struct StructWithOptionalNonNullPointer swonnp); diff --git a/tests/expectations/nested_nonnull.both.compat.c b/tests/expectations/nested_nonnull.both.compat.c new file mode 100644 index 000000000..fe7e48ef3 --- /dev/null +++ b/tests/expectations/nested_nonnull.both.compat.c @@ -0,0 +1,29 @@ +#include +#include +#include +#include + +typedef int32_t (*DoFn)(int32_t x, int32_t y); + +typedef struct StructWithOptionalFunctionPointer { + DoFn func; + DoFn maybe_func; +} StructWithOptionalFunctionPointer; + +typedef uint32_t *NonNullAlias_u32; + +typedef struct StructWithOptionalNonNullPointer { + NonNullAlias_u32 data; + NonNullAlias_u32 maybe_data; +} StructWithOptionalNonNullPointer; + +#ifdef __cplusplus +extern "C" { +#endif // __cplusplus + +void root(struct StructWithOptionalFunctionPointer swofp, + struct StructWithOptionalNonNullPointer swonnp); + +#ifdef __cplusplus +} // extern "C" +#endif // __cplusplus diff --git a/tests/expectations/nested_nonnull.c b/tests/expectations/nested_nonnull.c new file mode 100644 index 000000000..a18005013 --- /dev/null +++ b/tests/expectations/nested_nonnull.c @@ -0,0 +1,20 @@ +#include +#include +#include +#include + +typedef int32_t (*DoFn)(int32_t x, int32_t y); + +typedef struct { + DoFn func; + DoFn maybe_func; +} StructWithOptionalFunctionPointer; + +typedef uint32_t *NonNullAlias_u32; + +typedef struct { + NonNullAlias_u32 data; + NonNullAlias_u32 maybe_data; +} StructWithOptionalNonNullPointer; + +void root(StructWithOptionalFunctionPointer swofp, StructWithOptionalNonNullPointer swonnp); diff --git a/tests/expectations/nested_nonnull.compat.c b/tests/expectations/nested_nonnull.compat.c new file mode 100644 index 000000000..b679f087a --- /dev/null +++ b/tests/expectations/nested_nonnull.compat.c @@ -0,0 +1,28 @@ +#include +#include +#include +#include + +typedef int32_t (*DoFn)(int32_t x, int32_t y); + +typedef struct { + DoFn func; + DoFn maybe_func; +} StructWithOptionalFunctionPointer; + +typedef uint32_t *NonNullAlias_u32; + +typedef struct { + NonNullAlias_u32 data; + NonNullAlias_u32 maybe_data; +} StructWithOptionalNonNullPointer; + +#ifdef __cplusplus +extern "C" { +#endif // __cplusplus + +void root(StructWithOptionalFunctionPointer swofp, StructWithOptionalNonNullPointer swonnp); + +#ifdef __cplusplus +} // extern "C" +#endif // __cplusplus diff --git a/tests/expectations/nested_nonnull.cpp b/tests/expectations/nested_nonnull.cpp new file mode 100644 index 000000000..a969d0de0 --- /dev/null +++ b/tests/expectations/nested_nonnull.cpp @@ -0,0 +1,26 @@ +#include +#include +#include +#include +#include + +using DoFn = int32_t(*)(int32_t x, int32_t y); + +struct StructWithOptionalFunctionPointer { + DoFn func; + DoFn maybe_func; +}; + +template +using NonNullAlias = T*; + +struct StructWithOptionalNonNullPointer { + NonNullAlias data; + NonNullAlias maybe_data; +}; + +extern "C" { + +void root(StructWithOptionalFunctionPointer swofp, StructWithOptionalNonNullPointer swonnp); + +} // extern "C" diff --git a/tests/expectations/nested_nonnull.pyx b/tests/expectations/nested_nonnull.pyx new file mode 100644 index 000000000..df06a788a --- /dev/null +++ b/tests/expectations/nested_nonnull.pyx @@ -0,0 +1,21 @@ +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 *: + + ctypedef int32_t (*DoFn)(int32_t x, int32_t y); + + ctypedef struct StructWithOptionalFunctionPointer: + DoFn func; + DoFn maybe_func; + + ctypedef uint32_t *NonNullAlias_u32; + + ctypedef struct StructWithOptionalNonNullPointer: + NonNullAlias_u32 data; + NonNullAlias_u32 maybe_data; + + void root(StructWithOptionalFunctionPointer swofp, StructWithOptionalNonNullPointer swonnp); diff --git a/tests/expectations/nested_nonnull.tag.c b/tests/expectations/nested_nonnull.tag.c new file mode 100644 index 000000000..31822455e --- /dev/null +++ b/tests/expectations/nested_nonnull.tag.c @@ -0,0 +1,21 @@ +#include +#include +#include +#include + +typedef int32_t (*DoFn)(int32_t x, int32_t y); + +struct StructWithOptionalFunctionPointer { + DoFn func; + DoFn maybe_func; +}; + +typedef uint32_t *NonNullAlias_u32; + +struct StructWithOptionalNonNullPointer { + NonNullAlias_u32 data; + NonNullAlias_u32 maybe_data; +}; + +void root(struct StructWithOptionalFunctionPointer swofp, + struct StructWithOptionalNonNullPointer swonnp); diff --git a/tests/expectations/nested_nonnull.tag.compat.c b/tests/expectations/nested_nonnull.tag.compat.c new file mode 100644 index 000000000..766e6b85d --- /dev/null +++ b/tests/expectations/nested_nonnull.tag.compat.c @@ -0,0 +1,29 @@ +#include +#include +#include +#include + +typedef int32_t (*DoFn)(int32_t x, int32_t y); + +struct StructWithOptionalFunctionPointer { + DoFn func; + DoFn maybe_func; +}; + +typedef uint32_t *NonNullAlias_u32; + +struct StructWithOptionalNonNullPointer { + NonNullAlias_u32 data; + NonNullAlias_u32 maybe_data; +}; + +#ifdef __cplusplus +extern "C" { +#endif // __cplusplus + +void root(struct StructWithOptionalFunctionPointer swofp, + struct StructWithOptionalNonNullPointer swonnp); + +#ifdef __cplusplus +} // extern "C" +#endif // __cplusplus diff --git a/tests/expectations/nested_nonnull.tag.pyx b/tests/expectations/nested_nonnull.tag.pyx new file mode 100644 index 000000000..c8fd406a5 --- /dev/null +++ b/tests/expectations/nested_nonnull.tag.pyx @@ -0,0 +1,21 @@ +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 *: + + ctypedef int32_t (*DoFn)(int32_t x, int32_t y); + + cdef struct StructWithOptionalFunctionPointer: + DoFn func; + DoFn maybe_func; + + ctypedef uint32_t *NonNullAlias_u32; + + cdef struct StructWithOptionalNonNullPointer: + NonNullAlias_u32 data; + NonNullAlias_u32 maybe_data; + + void root(StructWithOptionalFunctionPointer swofp, StructWithOptionalNonNullPointer swonnp); diff --git a/tests/expectations/nested_nonzero.both.c b/tests/expectations/nested_nonzero.both.c new file mode 100644 index 000000000..3d4681839 --- /dev/null +++ b/tests/expectations/nested_nonzero.both.c @@ -0,0 +1,13 @@ +#include +#include +#include +#include + +typedef uint32_t Handle_File; + +typedef struct Node { + Handle_File file; + Handle_File maybe_file; +} Node; + +void root(const struct Node *node); diff --git a/tests/expectations/nested_nonzero.both.compat.c b/tests/expectations/nested_nonzero.both.compat.c new file mode 100644 index 000000000..ce6910853 --- /dev/null +++ b/tests/expectations/nested_nonzero.both.compat.c @@ -0,0 +1,21 @@ +#include +#include +#include +#include + +typedef uint32_t Handle_File; + +typedef struct Node { + Handle_File file; + Handle_File maybe_file; +} Node; + +#ifdef __cplusplus +extern "C" { +#endif // __cplusplus + +void root(const struct Node *node); + +#ifdef __cplusplus +} // extern "C" +#endif // __cplusplus diff --git a/tests/expectations/nested_nonzero.c b/tests/expectations/nested_nonzero.c new file mode 100644 index 000000000..baddb521b --- /dev/null +++ b/tests/expectations/nested_nonzero.c @@ -0,0 +1,13 @@ +#include +#include +#include +#include + +typedef uint32_t Handle_File; + +typedef struct { + Handle_File file; + Handle_File maybe_file; +} Node; + +void root(const Node *node); diff --git a/tests/expectations/nested_nonzero.compat.c b/tests/expectations/nested_nonzero.compat.c new file mode 100644 index 000000000..b5a88240d --- /dev/null +++ b/tests/expectations/nested_nonzero.compat.c @@ -0,0 +1,21 @@ +#include +#include +#include +#include + +typedef uint32_t Handle_File; + +typedef struct { + Handle_File file; + Handle_File maybe_file; +} Node; + +#ifdef __cplusplus +extern "C" { +#endif // __cplusplus + +void root(const Node *node); + +#ifdef __cplusplus +} // extern "C" +#endif // __cplusplus diff --git a/tests/expectations/nested_nonzero.cpp b/tests/expectations/nested_nonzero.cpp new file mode 100644 index 000000000..4197f261a --- /dev/null +++ b/tests/expectations/nested_nonzero.cpp @@ -0,0 +1,21 @@ +#include +#include +#include +#include +#include + +struct File; + +template +using Handle = uint32_t; + +struct Node { + Handle file; + Handle maybe_file; +}; + +extern "C" { + +void root(const Node *node); + +} // extern "C" diff --git a/tests/expectations/nested_nonzero.pyx b/tests/expectations/nested_nonzero.pyx new file mode 100644 index 000000000..318cdb4d4 --- /dev/null +++ b/tests/expectations/nested_nonzero.pyx @@ -0,0 +1,15 @@ +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 *: + + ctypedef uint32_t Handle_File; + + ctypedef struct Node: + Handle_File file; + Handle_File maybe_file; + + void root(const Node *node); diff --git a/tests/expectations/nested_nonzero.tag.c b/tests/expectations/nested_nonzero.tag.c new file mode 100644 index 000000000..d079c2765 --- /dev/null +++ b/tests/expectations/nested_nonzero.tag.c @@ -0,0 +1,13 @@ +#include +#include +#include +#include + +typedef uint32_t Handle_File; + +struct Node { + Handle_File file; + Handle_File maybe_file; +}; + +void root(const struct Node *node); diff --git a/tests/expectations/nested_nonzero.tag.compat.c b/tests/expectations/nested_nonzero.tag.compat.c new file mode 100644 index 000000000..5de240ea6 --- /dev/null +++ b/tests/expectations/nested_nonzero.tag.compat.c @@ -0,0 +1,21 @@ +#include +#include +#include +#include + +typedef uint32_t Handle_File; + +struct Node { + Handle_File file; + Handle_File maybe_file; +}; + +#ifdef __cplusplus +extern "C" { +#endif // __cplusplus + +void root(const struct Node *node); + +#ifdef __cplusplus +} // extern "C" +#endif // __cplusplus diff --git a/tests/expectations/nested_nonzero.tag.pyx b/tests/expectations/nested_nonzero.tag.pyx new file mode 100644 index 000000000..752d93cef --- /dev/null +++ b/tests/expectations/nested_nonzero.tag.pyx @@ -0,0 +1,15 @@ +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 *: + + ctypedef uint32_t Handle_File; + + cdef struct Node: + Handle_File file; + Handle_File maybe_file; + + void root(const Node *node); diff --git a/tests/rust/nested_nonnull.rs b/tests/rust/nested_nonnull.rs new file mode 100644 index 000000000..ead2702a9 --- /dev/null +++ b/tests/rust/nested_nonnull.rs @@ -0,0 +1,21 @@ +type DoFn = extern "C" fn(x: i32, y: i32) -> i32; +type NonNullAlias = std::ptr::NonNull; + +#[repr(C)] +struct StructWithOptionalFunctionPointer { + func: DoFn, + maybe_func: Option, +} + +#[repr(C)] +struct StructWithOptionalNonNullPointer { + data: NonNullAlias, + maybe_data: Option>, +} + +#[no_mangle] +pub extern "C" fn root( + swofp: StructWithOptionalFunctionPointer, + swonnp: StructWithOptionalNonNullPointer, +) { +} diff --git a/tests/rust/nested_nonzero.rs b/tests/rust/nested_nonzero.rs new file mode 100644 index 000000000..ab05fc73a --- /dev/null +++ b/tests/rust/nested_nonzero.rs @@ -0,0 +1,16 @@ +#[repr(transparent)] +struct Handle { + value: std::num::NonZeroU32, + _phantom: std::marker::PhantomData, +} + +struct File; + +#[repr(C)] +struct Node { + file: Handle, + maybe_file: Option>, +} + +#[no_mangle] +pub extern "C" fn root(node: &Node) {}