From 8fddc5d0a9d20f545a8a81efe9ffab5b076c716c Mon Sep 17 00:00:00 2001 From: Ingvar Stepanyan <me@rreverser.com> Date: Wed, 15 Nov 2017 22:29:44 +0000 Subject: [PATCH] Emit generics as native templates in C++ --- src/bindgen/bindings.rs | 11 +- src/bindgen/cdecl.rs | 16 +- src/bindgen/ir/generics.rs | 48 ++++ src/bindgen/ir/mod.rs | 2 + src/bindgen/ir/opaque.rs | 14 +- src/bindgen/ir/specialization.rs | 10 +- src/bindgen/ir/structure.rs | 18 +- src/bindgen/ir/ty.rs | 12 +- src/bindgen/ir/union.rs | 16 +- src/bindgen/library.rs | 5 +- src/bindgen/parser.rs | 10 +- src/bindgen/writer.rs | 24 -- tests/expectations/alias.cpp | 34 +-- tests/expectations/annotation.cpp | 4 +- tests/expectations/cdecl.cpp | 4 +- tests/expectations/cfg-2.cpp | 4 +- tests/expectations/cfg.cpp | 4 +- tests/expectations/constant.cpp | 4 +- tests/expectations/enum.cpp | 4 +- tests/expectations/euclid.cpp | 288 ++++++--------------- tests/expectations/extern.cpp | 4 +- tests/expectations/fail-str.cpp | 4 +- tests/expectations/inner_mod.cpp | 4 +- tests/expectations/monomorph-1.cpp | 84 ++---- tests/expectations/monomorph-2.cpp | 29 +-- tests/expectations/monomorph-3.cpp | 50 ++-- tests/expectations/simplify-option-ptr.cpp | 4 +- tests/expectations/static.cpp | 4 +- tests/expectations/std_lib.cpp | 15 +- tests/expectations/struct.cpp | 4 +- tests/expectations/typedef.cpp | 19 +- tests/expectations/union.cpp | 4 +- 32 files changed, 280 insertions(+), 477 deletions(-) create mode 100644 src/bindgen/ir/generics.rs diff --git a/src/bindgen/bindings.rs b/src/bindgen/bindings.rs index ba78cc8..74bf4c9 100644 --- a/src/bindgen/bindings.rs +++ b/src/bindgen/bindings.rs @@ -89,13 +89,10 @@ impl Bindings { out.new_line(); if self.config.language == Language::Cxx { - out.new_line_if_not_start(); - out.write("extern \"C\" {"); - out.new_line(); - self.open_namespaces(&mut out); } + for constant in &self.constants { out.new_line_if_not_start(); constant.write(&self.config, &mut out); @@ -123,6 +120,12 @@ impl Bindings { out.new_line(); } + if self.config.language == Language::Cxx { + out.new_line_if_not_start(); + out.write("extern \"C\" {"); + out.new_line(); + } + for global in &self.globals { out.new_line_if_not_start(); global.write(&self.config, &mut out); diff --git a/src/bindgen/cdecl.rs b/src/bindgen/cdecl.rs index 697fd5b..222285f 100644 --- a/src/bindgen/cdecl.rs +++ b/src/bindgen/cdecl.rs @@ -5,7 +5,7 @@ use std::io::Write; use bindgen::ir::{Function, Type}; -use bindgen::writer::SourceWriter; +use bindgen::writer::{ListType, SourceWriter}; // This code is for translating Rust types into C declarations. // See Section 6.7, Declarations, in the C standard for background. @@ -30,6 +30,7 @@ impl CDeclarator { struct CDecl { type_qualifers: String, type_name: String, + type_generic_args: Vec<Type>, declarators: Vec<CDeclarator> } @@ -38,6 +39,7 @@ impl CDecl { CDecl { type_qualifers: String::new(), type_name: String::new(), + type_generic_args: Vec::new(), declarators: Vec::new(), } } @@ -62,10 +64,6 @@ impl CDecl { fn build_type(&mut self, t: &Type, is_const: bool) { match t { &Type::Path(ref path) => { - // We should be assured that there are no generics by instantiating - // monomorphs and mangling paths. - assert!(path.generics.len() == 0); - if is_const { assert!(self.type_qualifers.len() == 0); self.type_qualifers = "const".to_owned(); @@ -73,6 +71,8 @@ impl CDecl { assert!(self.type_name.len() == 0); self.type_name = path.name.clone(); + assert!(self.type_generic_args.len() == 0); + self.type_generic_args = path.generics.clone(); } &Type::Primitive(ref p) => { if is_const { @@ -114,6 +114,12 @@ impl CDecl { write!(out, "{}", self.type_name); }; + if !self.type_generic_args.is_empty() { + out.write("<"); + out.write_horizontal_source_list(&self.type_generic_args, ListType::Join(", ")); + out.write(">"); + } + // When we have an identifier, put a space between the type and the declarators if ident.is_some() { out.write(" "); diff --git a/src/bindgen/ir/generics.rs b/src/bindgen/ir/generics.rs new file mode 100644 index 0000000..2e3ff92 --- /dev/null +++ b/src/bindgen/ir/generics.rs @@ -0,0 +1,48 @@ +use std::ops::Deref; +use std::io::Write; + +use syn; + +use bindgen::config::{Config, Language}; +use bindgen::writer::{Source, SourceWriter}; + +#[derive(Default, Debug, Clone)] +pub struct GenericParams(pub Vec<String>); + +impl GenericParams { + pub fn new(generics: &syn::Generics) -> Self { + GenericParams( + generics + .ty_params + .iter() + .map(|x| x.ident.to_string()) + .collect::<Vec<_>>(), + ) + } +} + +impl Deref for GenericParams { + type Target = [String]; + + fn deref(&self) -> &[String] { + &self.0 + } +} + +impl Source for GenericParams { + fn write<F: Write>(&self, config: &Config, out: &mut SourceWriter<F>) { + if !self.0.is_empty() { + if config.language == Language::Cxx { + out.write("template<"); + for (i, item) in self.0.iter().enumerate() { + if i != 0 { + out.write(", "); + } + write!(out, "typename {}", item); + } + out.write(">"); + out.new_line(); + } + } + } +} diff --git a/src/bindgen/ir/mod.rs b/src/bindgen/ir/mod.rs index 96c915c..1f2e3cc 100644 --- a/src/bindgen/ir/mod.rs +++ b/src/bindgen/ir/mod.rs @@ -7,6 +7,7 @@ pub mod cfg; pub mod constant; pub mod enumeration; pub mod function; +pub mod generics; pub mod global; pub mod item; pub mod opaque; @@ -24,6 +25,7 @@ pub use self::cfg::*; pub use self::constant::*; pub use self::enumeration::*; pub use self::function::*; +pub use self::generics::*; pub use self::global::*; pub use self::item::*; pub use self::opaque::*; diff --git a/src/bindgen/ir/opaque.rs b/src/bindgen/ir/opaque.rs index bf391ad..3d460e7 100644 --- a/src/bindgen/ir/opaque.rs +++ b/src/bindgen/ir/opaque.rs @@ -8,7 +8,7 @@ use syn; use bindgen::config::{Config, Language}; use bindgen::dependencies::Dependencies; -use bindgen::ir::{AnnotationSet, Cfg, CfgWrite, Documentation, ItemContainer, Item, Path, Specialization, Type}; +use bindgen::ir::{AnnotationSet, Cfg, CfgWrite, Documentation, GenericParams, ItemContainer, Item, Path, Specialization, Type}; use bindgen::library::Library; use bindgen::mangle; use bindgen::monomorph::Monomorphs; @@ -17,7 +17,7 @@ use bindgen::writer::{Source, SourceWriter}; #[derive(Debug, Clone)] pub struct OpaqueItem { pub name: Path, - pub generic_params: Vec<String>, + pub generic_params: GenericParams, pub cfg: Option<Cfg>, pub annotations: AnnotationSet, pub documentation: Documentation, @@ -28,13 +28,9 @@ impl OpaqueItem { generics: &syn::Generics, attrs: &Vec<syn::Attribute>, mod_cfg: &Option<Cfg>) -> OpaqueItem { - let generic_params = generics.ty_params.iter() - .map(|x| x.ident.to_string()) - .collect::<Vec<_>>(); - OpaqueItem { name: name, - generic_params: generic_params, + generic_params: GenericParams::new(generics), cfg: Cfg::append(mod_cfg, Cfg::load(attrs)), annotations: AnnotationSet::load(attrs).unwrap_or(AnnotationSet::new()), documentation: Documentation::load(attrs), @@ -46,7 +42,7 @@ impl OpaqueItem { let monomorph = OpaqueItem { name: mangle::mangle_path(&self.name, generic_values), - generic_params: vec![], + generic_params: GenericParams::default(), cfg: self.cfg.clone(), annotations: self.annotations.clone(), documentation: self.documentation.clone(), @@ -102,6 +98,8 @@ impl Source for OpaqueItem { self.documentation.write(config, out); + self.generic_params.write(config, out); + if config.language == Language::C { write!(out, "typedef struct {} {};", self.name, self.name); } else { diff --git a/src/bindgen/ir/specialization.rs b/src/bindgen/ir/specialization.rs index 6e581e9..3f109d2 100644 --- a/src/bindgen/ir/specialization.rs +++ b/src/bindgen/ir/specialization.rs @@ -6,7 +6,7 @@ use syn; use bindgen::dependencies::Dependencies; use bindgen::ir::{AnnotationSet, Cfg, Documentation}; -use bindgen::ir::{GenericPath, ItemContainer, Item, PrimitiveType}; +use bindgen::ir::{GenericParams, GenericPath, ItemContainer, Item, PrimitiveType}; use bindgen::library::Library; /// A type alias that generates a copy of its aliasee with a new name. If the type @@ -15,7 +15,7 @@ use bindgen::library::Library; #[derive(Debug, Clone)] pub struct Specialization { pub name: String, - pub generic_params: Vec<String>, + pub generic_params: GenericParams, pub aliased: GenericPath, pub cfg: Option<Cfg>, pub annotations: AnnotationSet, @@ -31,10 +31,6 @@ impl Specialization { { match ty { &syn::Ty::Path(ref _q, ref p) => { - let generic_params = generics.ty_params.iter() - .map(|x| x.ident.to_string()) - .collect::<Vec<_>>(); - let path = GenericPath::load(p)?; if PrimitiveType::maybe(&path.name).is_some() { @@ -43,7 +39,7 @@ impl Specialization { Ok(Specialization { name: name, - generic_params: generic_params, + generic_params: GenericParams::new(generics), aliased: path, cfg: Cfg::append(mod_cfg, Cfg::load(attrs)), annotations: AnnotationSet::load(attrs)?, diff --git a/src/bindgen/ir/structure.rs b/src/bindgen/ir/structure.rs index 693f5e8..deb8c7d 100644 --- a/src/bindgen/ir/structure.rs +++ b/src/bindgen/ir/structure.rs @@ -8,7 +8,7 @@ use syn; use bindgen::config::{Config, Language}; use bindgen::dependencies::Dependencies; -use bindgen::ir::{AnnotationSet, Cfg, CfgWrite, Documentation, ItemContainer, Item, Repr, Specialization, Type}; +use bindgen::ir::{AnnotationSet, Cfg, CfgWrite, Documentation, GenericParams, ItemContainer, Item, Repr, Specialization, Type}; use bindgen::library::Library; use bindgen::mangle; use bindgen::monomorph::Monomorphs; @@ -19,7 +19,7 @@ use bindgen::writer::{ListType, Source, SourceWriter}; #[derive(Debug, Clone)] pub struct Struct { pub name: String, - pub generic_params: Vec<String>, + pub generic_params: GenericParams, pub fields: Vec<(String, Type, Documentation)>, pub tuple_struct: bool, pub cfg: Option<Cfg>, @@ -60,13 +60,9 @@ impl Struct { } }; - let generic_params = generics.ty_params.iter() - .map(|x| x.ident.to_string()) - .collect::<Vec<_>>(); - Ok(Struct { name: name, - generic_params: generic_params, + generic_params: GenericParams::new(generics), fields: fields, tuple_struct: tuple_struct, cfg: Cfg::append(mod_cfg, Cfg::load(attrs)), @@ -173,7 +169,7 @@ impl Item for Struct { let monomorph = Struct { name: mangle::mangle_path(&self.name, generic_values), - generic_params: vec![], + generic_params: GenericParams::default(), fields: self.fields.iter() .map(|x| (x.0.clone(), x.1.specialize(&mappings), x.2.clone())) .collect(), @@ -215,12 +211,12 @@ impl Item for Struct { impl Source for Struct { fn write<F: Write>(&self, config: &Config, out: &mut SourceWriter<F>) { - assert!(self.generic_params.is_empty()); - self.cfg.write_before(config, out); self.documentation.write(config, out); + self.generic_params.write(config, out); + if config.language == Language::C { out.write("typedef struct"); } else { @@ -257,7 +253,7 @@ impl Source for Struct { write!(out, "bool operator{}(const {}& {}) const", op, self.name, other); out.open_brace(); out.write("return "); - out.write_vertical_list(&self.fields.iter() + out.write_vertical_source_list(&self.fields.iter() .map(|x| format!("{} {} {}.{}", x.0, op, other, x.0)) .collect(), ListType::Join(&format!(" {}", conjuc))); diff --git a/src/bindgen/ir/ty.rs b/src/bindgen/ir/ty.rs index c406280..82b6c4d 100644 --- a/src/bindgen/ir/ty.rs +++ b/src/bindgen/ir/ty.rs @@ -10,7 +10,7 @@ use syn; use bindgen::cdecl; use bindgen::config::Config; use bindgen::dependencies::Dependencies; -use bindgen::ir::{Documentation, GenericPath, ItemContainer, Item, Path}; +use bindgen::ir::{Documentation, GenericParams, GenericPath, ItemContainer, Item, Path}; use bindgen::library::Library; use bindgen::monomorph::Monomorphs; use bindgen::utilities::IterHelpers; @@ -357,7 +357,7 @@ impl Type { } } - pub fn add_dependencies_ignoring_generics(&self, generic_params: &Vec<String>, library: &Library, out: &mut Dependencies) { + pub fn add_dependencies_ignoring_generics(&self, generic_params: &GenericParams, library: &Library, out: &mut Dependencies) { match self { &Type::ConstPtr(ref ty) => { ty.add_dependencies_ignoring_generics(generic_params, library, out); @@ -400,7 +400,7 @@ impl Type { } pub fn add_dependencies(&self, library: &Library, out: &mut Dependencies) { - self.add_dependencies_ignoring_generics(&Vec::new(), library, out) + self.add_dependencies_ignoring_generics(&GenericParams::default(), library, out) } pub fn add_monomorphs(&self, library: &Library, out: &mut Monomorphs) { @@ -517,6 +517,12 @@ impl Type { } } +impl Source for String { + fn write<F: Write>(&self, _config: &Config, out: &mut SourceWriter<F>) { + write!(out, "{}", self); + } +} + impl Source for Type { fn write<F: Write>(&self, _config: &Config, out: &mut SourceWriter<F>) { cdecl::write_type(out, &self); diff --git a/src/bindgen/ir/union.rs b/src/bindgen/ir/union.rs index a7a1efd..1429ea7 100644 --- a/src/bindgen/ir/union.rs +++ b/src/bindgen/ir/union.rs @@ -8,7 +8,7 @@ use syn; use bindgen::config::{Config, Language}; use bindgen::dependencies::Dependencies; -use bindgen::ir::{AnnotationSet, Cfg, CfgWrite, Documentation, ItemContainer, Item, Repr, Specialization, Type}; +use bindgen::ir::{AnnotationSet, Cfg, CfgWrite, Documentation, GenericParams, ItemContainer, Item, Repr, Specialization, Type}; use bindgen::ir::SynFieldHelpers; use bindgen::library::Library; use bindgen::mangle; @@ -20,7 +20,7 @@ use bindgen::writer::{ListType, Source, SourceWriter}; #[derive(Debug, Clone)] pub struct Union { pub name: String, - pub generic_params: Vec<String>, + pub generic_params: GenericParams, pub fields: Vec<(String, Type, Documentation)>, pub tuple_union: bool, pub cfg: Option<Cfg>, @@ -61,13 +61,9 @@ impl Union { } }; - let generic_params = generics.ty_params.iter() - .map(|x| x.ident.to_string()) - .collect::<Vec<_>>(); - Ok(Union { name: name, - generic_params: generic_params, + generic_params: GenericParams::new(generics), fields: fields, tuple_union: tuple_union, cfg: Cfg::append(mod_cfg, Cfg::load(attrs)), @@ -174,7 +170,7 @@ impl Item for Union { let monomorph = Union { name: mangle::mangle_path(&self.name, generic_values), - generic_params: vec![], + generic_params: GenericParams::default(), fields: self.fields.iter() .map(|x| (x.0.clone(), x.1.specialize(&mappings), x.2.clone())) .collect(), @@ -216,12 +212,12 @@ impl Item for Union { impl Source for Union { fn write<F: Write>(&self, config: &Config, out: &mut SourceWriter<F>) { - assert!(self.generic_params.is_empty()); - self.cfg.write_before(config, out); self.documentation.write(config, out); + self.generic_params.write(config, out); + if config.language == Language::C { out.write("typedef union"); } else { diff --git a/src/bindgen/library.rs b/src/bindgen/library.rs index dc91ea8..3e8a60d 100644 --- a/src/bindgen/library.rs +++ b/src/bindgen/library.rs @@ -60,7 +60,10 @@ impl Library { self.rename_items(); self.specialize_items(); self.simplify_option_to_ptr(); - self.instantiate_monomorphs(); + + if self.config.language == Language::C { + self.instantiate_monomorphs(); + } let mut dependencies = Dependencies::new(); diff --git a/src/bindgen/parser.rs b/src/bindgen/parser.rs index f965b64..93e4451 100644 --- a/src/bindgen/parser.rs +++ b/src/bindgen/parser.rs @@ -10,7 +10,7 @@ use std::path::{Path, PathBuf}; use syn; use bindgen::cargo::{Cargo, PackageRef}; -use bindgen::ir::{AnnotationSet, Cfg, Constant, Documentation, Enum, Function}; +use bindgen::ir::{AnnotationSet, Cfg, Constant, Documentation, Enum, Function, GenericParams}; use bindgen::ir::{ItemMap, OpaqueItem, Specialization, Static, Struct, Typedef, Union}; use bindgen::utilities::{SynAbiHelpers, SynItemHelpers}; @@ -371,9 +371,11 @@ impl Parse { let mut add_opaque = |name: &str, generic_params: Vec<&str>| { self.opaque_items.try_insert(OpaqueItem { name: name.to_owned(), - generic_params: generic_params.iter() - .map(|x| (*x).to_owned()) - .collect(), + generic_params: GenericParams( + generic_params.iter() + .map(|x| (*x).to_owned()) + .collect() + ), cfg: None, annotations: AnnotationSet::new(), documentation: Documentation::none(), diff --git a/src/bindgen/writer.rs b/src/bindgen/writer.rs index d460fde..74267d1 100644 --- a/src/bindgen/writer.rs +++ b/src/bindgen/writer.rs @@ -193,30 +193,6 @@ impl<'a, F: Write> SourceWriter<'a, F> { } } - pub fn write_vertical_list<'b>(&mut self, items: &Vec<String>, list_type: ListType<'b>) { - let align_length = self.line_length_for_align(); - self.push_set_spaces(align_length); - for (i, item) in items.iter().enumerate() { - write!(self, "{}", item); - - match list_type { - ListType::Join(text) => { - if i != items.len() - 1 { - write!(self, "{}", text); - } - } - ListType::Cap(text) => { - write!(self, "{}", text); - } - } - - if i != items.len() - 1 { - self.new_line(); - } - } - self.pop_tab(); - } - pub fn write_vertical_source_list<'b, S: Source>(&mut self, items: &Vec<S>, list_type: ListType<'b>) { let align_length = self.line_length_for_align(); self.push_set_spaces(align_length); diff --git a/tests/expectations/alias.cpp b/tests/expectations/alias.cpp index 63848e5..d770f0c 100644 --- a/tests/expectations/alias.cpp +++ b/tests/expectations/alias.cpp @@ -1,8 +1,6 @@ #include <cstdint> #include <cstdlib> -extern "C" { - enum class Status : uint32_t { Ok = 0, Err = 1, @@ -13,39 +11,23 @@ struct Dep { float b; }; -struct Foo_i32 { - int32_t a; - int32_t b; +template<typename X> +struct Foo { + X a; + X b; Dep c; }; -typedef Foo_i32 IntFoo; +typedef Foo<int32_t> IntFoo; -struct Foo_f64 { - double a; - double b; - Dep c; -}; - -typedef Foo_f64 DoubleFoo; +typedef Foo<double> DoubleFoo; typedef int32_t Unit; typedef Status SpecialStatus; +extern "C" { + void root(IntFoo x, DoubleFoo y, Unit z, SpecialStatus w); } // extern "C" - -template<typename X> -struct Foo; - -template<> -struct Foo<double> : public Foo_f64 { - -}; - -template<> -struct Foo<int32_t> : public Foo_i32 { - -}; diff --git a/tests/expectations/annotation.cpp b/tests/expectations/annotation.cpp index 0115497..0e272ce 100644 --- a/tests/expectations/annotation.cpp +++ b/tests/expectations/annotation.cpp @@ -1,8 +1,6 @@ #include <cstdint> #include <cstdlib> -extern "C" { - enum class C : uint32_t { X = 2, Y = 3, @@ -24,6 +22,8 @@ struct B { float y; }; +extern "C" { + void root(A x, B y, C z); } // extern "C" diff --git a/tests/expectations/cdecl.cpp b/tests/expectations/cdecl.cpp index ffdc54f..dd8c421 100644 --- a/tests/expectations/cdecl.cpp +++ b/tests/expectations/cdecl.cpp @@ -1,8 +1,6 @@ #include <cstdint> #include <cstdlib> -extern "C" { - typedef void (*A)(); typedef void (*B)(); @@ -31,6 +29,8 @@ typedef bool (*M[16])(int32_t, int32_t); typedef void (*N[16])(int32_t, int32_t); +extern "C" { + void (*O())(); void root(A a, B b, C c, D d, E e, F f, G g, H h, I i, J j, K k, L l, M m, N n); diff --git a/tests/expectations/cfg-2.cpp b/tests/expectations/cfg-2.cpp index 44b493f..9b54c4e 100644 --- a/tests/expectations/cfg-2.cpp +++ b/tests/expectations/cfg-2.cpp @@ -1,8 +1,6 @@ #include <cstdint> #include <cstdlib> -extern "C" { - #if (defined(NOT_DEFINED) || defined(DEFINED)) struct Foo { int32_t x; @@ -25,6 +23,8 @@ struct Root { Bar w; }; +extern "C" { + void root(Root a); } // extern "C" diff --git a/tests/expectations/cfg.cpp b/tests/expectations/cfg.cpp index c21480e..4500055 100644 --- a/tests/expectations/cfg.cpp +++ b/tests/expectations/cfg.cpp @@ -1,8 +1,6 @@ #include <cstdint> #include <cstdlib> -extern "C" { - #if (defined(PLATFORM_WIN) || defined(M_32)) enum class BarType : uint32_t { A = 0, @@ -35,6 +33,8 @@ struct BarHandle { }; #endif +extern "C" { + #if (defined(PLATFORM_UNIX) && defined(X11)) void root(FooHandle a); #endif diff --git a/tests/expectations/constant.cpp b/tests/expectations/constant.cpp index 988bc35..df09abd 100644 --- a/tests/expectations/constant.cpp +++ b/tests/expectations/constant.cpp @@ -1,8 +1,6 @@ #include <cstdint> #include <cstdlib> -extern "C" { - static const int32_t FOO = 10; static const float ZOM = 3.14; @@ -11,6 +9,8 @@ struct Foo { int32_t x[FOO]; }; +extern "C" { + void root(Foo x); } // extern "C" diff --git a/tests/expectations/enum.cpp b/tests/expectations/enum.cpp index a51af59..1537c3c 100644 --- a/tests/expectations/enum.cpp +++ b/tests/expectations/enum.cpp @@ -1,8 +1,6 @@ #include <cstdint> #include <cstdlib> -extern "C" { - enum class A : uint32_t { a1 = 0, a2 = 2, @@ -40,6 +38,8 @@ enum class E : intptr_t { struct Opaque; +extern "C" { + void root(Opaque *o, A a, B b, C c, D d, E e); } // extern "C" diff --git a/tests/expectations/euclid.cpp b/tests/expectations/euclid.cpp index 56e65d1..7fd0d9a 100644 --- a/tests/expectations/euclid.cpp +++ b/tests/expectations/euclid.cpp @@ -1,257 +1,115 @@ #include <cstdint> #include <cstdlib> -extern "C" { - struct LayoutUnit; struct UnknownUnit; -struct TypedLength_f32__UnknownUnit { - float _0; -}; - -struct TypedLength_f32__LayoutUnit { - float _0; +template<typename T, typename Unit> +struct TypedLength { + T _0; }; -struct Length_f32 { - float _0; +template<typename T> +struct Length { + T _0; }; -typedef TypedLength_f32__LayoutUnit LayoutLength; +typedef TypedLength<float, LayoutUnit> LayoutLength; -struct TypedSideOffsets2D_f32__UnknownUnit { - float top; - float right; - float bottom; - float left; -}; - -struct TypedSideOffsets2D_f32__LayoutUnit { - float top; - float right; - float bottom; - float left; +template<typename T, typename U> +struct TypedSideOffsets2D { + T top; + T right; + T bottom; + T left; }; -struct SideOffsets2D_f32 { - float top; - float right; - float bottom; - float left; +template<typename T> +struct SideOffsets2D { + T top; + T right; + T bottom; + T left; }; -typedef TypedSideOffsets2D_f32__LayoutUnit LayoutSideOffsets2D; +typedef TypedSideOffsets2D<float, LayoutUnit> LayoutSideOffsets2D; -struct TypedSize2D_f32__UnknownUnit { - float width; - float height; -}; - -struct TypedSize2D_f32__LayoutUnit { - float width; - float height; +template<typename T, typename U> +struct TypedSize2D { + T width; + T height; }; -struct Size2D_f32 { - float width; - float height; +template<typename T> +struct Size2D { + T width; + T height; }; -typedef TypedSize2D_f32__LayoutUnit LayoutSize2D; - -struct TypedPoint2D_f32__UnknownUnit { - float x; - float y; -}; +typedef TypedSize2D<float, LayoutUnit> LayoutSize2D; -struct TypedPoint2D_f32__LayoutUnit { - float x; - float y; +template<typename T, typename U> +struct TypedPoint2D { + T x; + T y; }; -struct Point2D_f32 { - float x; - float y; +template<typename T> +struct Point2D { + T x; + T y; }; -typedef TypedPoint2D_f32__LayoutUnit LayoutPoint2D; - -struct TypedRect_f32__UnknownUnit { - TypedPoint2D_f32__UnknownUnit origin; - TypedSize2D_f32__UnknownUnit size; -}; +typedef TypedPoint2D<float, LayoutUnit> LayoutPoint2D; -struct TypedRect_f32__LayoutUnit { - TypedPoint2D_f32__LayoutUnit origin; - TypedSize2D_f32__LayoutUnit size; +template<typename T, typename U> +struct TypedRect { + TypedPoint2D<T, U> origin; + TypedSize2D<T, U> size; }; -struct Rect_f32 { - TypedPoint2D_f32__UnknownUnit origin; - TypedSize2D_f32__UnknownUnit size; +template<typename T> +struct Rect { + TypedPoint2D<T, UnknownUnit> origin; + TypedSize2D<T, UnknownUnit> size; }; -typedef TypedRect_f32__LayoutUnit LayoutRect; +typedef TypedRect<float, LayoutUnit> LayoutRect; -struct TypedTransform2D_f32__UnknownUnit__LayoutUnit { - float m11; - float m12; - float m21; - float m22; - float m31; - float m32; +template<typename T, typename Src, typename Dst> +struct TypedTransform2D { + T m11; + T m12; + T m21; + T m22; + T m31; + T m32; }; -struct TypedTransform2D_f32__LayoutUnit__UnknownUnit { - float m11; - float m12; - float m21; - float m22; - float m31; - float m32; -}; +extern "C" { -void root(TypedLength_f32__UnknownUnit length_a, - TypedLength_f32__LayoutUnit length_b, - Length_f32 length_c, +void root(TypedLength<float, UnknownUnit> length_a, + TypedLength<float, LayoutUnit> length_b, + Length<float> length_c, LayoutLength length_d, - TypedSideOffsets2D_f32__UnknownUnit side_offsets_a, - TypedSideOffsets2D_f32__LayoutUnit side_offsets_b, - SideOffsets2D_f32 side_offsets_c, + TypedSideOffsets2D<float, UnknownUnit> side_offsets_a, + TypedSideOffsets2D<float, LayoutUnit> side_offsets_b, + SideOffsets2D<float> side_offsets_c, LayoutSideOffsets2D side_offsets_d, - TypedSize2D_f32__UnknownUnit size_a, - TypedSize2D_f32__LayoutUnit size_b, - Size2D_f32 size_c, + TypedSize2D<float, UnknownUnit> size_a, + TypedSize2D<float, LayoutUnit> size_b, + Size2D<float> size_c, LayoutSize2D size_d, - TypedPoint2D_f32__UnknownUnit point_a, - TypedPoint2D_f32__LayoutUnit point_b, - Point2D_f32 point_c, + TypedPoint2D<float, UnknownUnit> point_a, + TypedPoint2D<float, LayoutUnit> point_b, + Point2D<float> point_c, LayoutPoint2D point_d, - TypedRect_f32__UnknownUnit rect_a, - TypedRect_f32__LayoutUnit rect_b, - Rect_f32 rect_c, + TypedRect<float, UnknownUnit> rect_a, + TypedRect<float, LayoutUnit> rect_b, + Rect<float> rect_c, LayoutRect rect_d, - TypedTransform2D_f32__UnknownUnit__LayoutUnit transform_a, - TypedTransform2D_f32__LayoutUnit__UnknownUnit transform_b); + TypedTransform2D<float, UnknownUnit, LayoutUnit> transform_a, + TypedTransform2D<float, LayoutUnit, UnknownUnit> transform_b); } // extern "C" - -template<typename T> -struct Length; - -template<> -struct Length<float> : public Length_f32 { - -}; - -template<typename T> -struct Point2D; - -template<> -struct Point2D<float> : public Point2D_f32 { - -}; - -template<typename T> -struct Rect; - -template<> -struct Rect<float> : public Rect_f32 { - -}; - -template<typename T> -struct SideOffsets2D; - -template<> -struct SideOffsets2D<float> : public SideOffsets2D_f32 { - -}; - -template<typename T> -struct Size2D; - -template<> -struct Size2D<float> : public Size2D_f32 { - -}; - -template<typename T, typename Unit> -struct TypedLength; - -template<> -struct TypedLength<float, LayoutUnit> : public TypedLength_f32__LayoutUnit { - -}; - -template<> -struct TypedLength<float, UnknownUnit> : public TypedLength_f32__UnknownUnit { - -}; - -template<typename T, typename U> -struct TypedPoint2D; - -template<> -struct TypedPoint2D<float, LayoutUnit> : public TypedPoint2D_f32__LayoutUnit { - -}; - -template<> -struct TypedPoint2D<float, UnknownUnit> : public TypedPoint2D_f32__UnknownUnit { - -}; - -template<typename T, typename U> -struct TypedRect; - -template<> -struct TypedRect<float, LayoutUnit> : public TypedRect_f32__LayoutUnit { - -}; - -template<> -struct TypedRect<float, UnknownUnit> : public TypedRect_f32__UnknownUnit { - -}; - -template<typename T, typename U> -struct TypedSideOffsets2D; - -template<> -struct TypedSideOffsets2D<float, LayoutUnit> : public TypedSideOffsets2D_f32__LayoutUnit { - -}; - -template<> -struct TypedSideOffsets2D<float, UnknownUnit> : public TypedSideOffsets2D_f32__UnknownUnit { - -}; - -template<typename T, typename U> -struct TypedSize2D; - -template<> -struct TypedSize2D<float, LayoutUnit> : public TypedSize2D_f32__LayoutUnit { - -}; - -template<> -struct TypedSize2D<float, UnknownUnit> : public TypedSize2D_f32__UnknownUnit { - -}; - -template<typename T, typename Src, typename Dst> -struct TypedTransform2D; - -template<> -struct TypedTransform2D<float, UnknownUnit, LayoutUnit> : public TypedTransform2D_f32__UnknownUnit__LayoutUnit { - -}; - -template<> -struct TypedTransform2D<float, LayoutUnit, UnknownUnit> : public TypedTransform2D_f32__LayoutUnit__UnknownUnit { - -}; diff --git a/tests/expectations/extern.cpp b/tests/expectations/extern.cpp index cd2c839..4e974d6 100644 --- a/tests/expectations/extern.cpp +++ b/tests/expectations/extern.cpp @@ -1,13 +1,13 @@ #include <cstdint> #include <cstdlib> -extern "C" { - struct Normal { int32_t x; float y; }; +extern "C" { + extern void bar(Normal a); extern int32_t foo(); diff --git a/tests/expectations/fail-str.cpp b/tests/expectations/fail-str.cpp index 735cd80..df605c8 100644 --- a/tests/expectations/fail-str.cpp +++ b/tests/expectations/fail-str.cpp @@ -1,12 +1,12 @@ #include <cstdint> #include <cstdlib> -extern "C" { - struct Foo { const str *x; }; +extern "C" { + void root(Foo a, const str *b); } // extern "C" diff --git a/tests/expectations/inner_mod.cpp b/tests/expectations/inner_mod.cpp index 233ce77..d09a366 100644 --- a/tests/expectations/inner_mod.cpp +++ b/tests/expectations/inner_mod.cpp @@ -1,12 +1,12 @@ #include <cstdint> #include <cstdlib> -extern "C" { - struct Foo { float x; }; +extern "C" { + void root(Foo a); } // extern "C" diff --git a/tests/expectations/monomorph-1.cpp b/tests/expectations/monomorph-1.cpp index dae1add..ef1c47e 100644 --- a/tests/expectations/monomorph-1.cpp +++ b/tests/expectations/monomorph-1.cpp @@ -1,77 +1,35 @@ #include <cstdint> #include <cstdlib> -extern "C" { - -struct Bar_Bar_f32; - -struct Bar_Foo_f32; - -struct Bar_f32; - -struct Foo_i32 { - const int32_t *data; -}; - -struct Foo_f32 { - const float *data; -}; - -struct Foo_Bar_f32 { - const Bar_f32 *data; -}; - -struct Tuple_Foo_f32_____f32 { - const Foo_f32 *a; - const float *b; -}; - -struct Indirection_f32 { - const float *a; - const float *b; -}; - -void root(Foo_i32 a, - Foo_f32 b, - Bar_f32 c, - Foo_Bar_f32 d, - Bar_Foo_f32 e, - Bar_Bar_f32 f, - Tuple_Foo_f32_____f32 g, - Indirection_f32 h); - -} // extern "C" - template<typename T> -struct Foo; - -template<> -struct Foo<int32_t> : public Foo_i32 { - -}; - -template<> -struct Foo<float> : public Foo_f32 { +struct Bar; +template<typename T> +struct Foo { + const T *data; }; -template<> -struct Foo<Bar_f32> : public Foo_Bar_f32 { - +template<typename T, typename E> +struct Tuple { + const T *a; + const E *b; }; template<typename T> -struct Indirection; - -template<> -struct Indirection<float> : public Indirection_f32 { - +struct Indirection { + const T *a; + const float *b; }; -template<typename T, typename E> -struct Tuple; +extern "C" { -template<> -struct Tuple<Foo_f32, float> : public Tuple_Foo_f32_____f32 { +void root(Foo<int32_t> a, + Foo<float> b, + Bar<float> c, + Foo<Bar<float>> d, + Bar<Foo<float>> e, + Bar<Bar<float>> f, + Tuple<Foo<float>, float> g, + Indirection<float> h); -}; +} // extern "C" diff --git a/tests/expectations/monomorph-2.cpp b/tests/expectations/monomorph-2.cpp index b458a90..93a4175 100644 --- a/tests/expectations/monomorph-2.cpp +++ b/tests/expectations/monomorph-2.cpp @@ -1,37 +1,20 @@ #include <cstdint> #include <cstdlib> -extern "C" { - struct A; struct B; -struct List_B { - B *members; +template<typename T> +struct List { + T *members; size_t count; }; -struct List_A { - A *members; - size_t count; -}; +extern "C" { -void bar(List_B b); +void bar(List<B> b); -void foo(List_A a); +void foo(List<A> a); } // extern "C" - -template<typename T> -struct List; - -template<> -struct List<B> : public List_B { - -}; - -template<> -struct List<A> : public List_A { - -}; diff --git a/tests/expectations/monomorph-3.cpp b/tests/expectations/monomorph-3.cpp index e3974ff..3a2060d 100644 --- a/tests/expectations/monomorph-3.cpp +++ b/tests/expectations/monomorph-3.cpp @@ -1,43 +1,35 @@ #include <cstdint> #include <cstdlib> -extern "C" { - -struct Bar_Bar_f32; - -struct Bar_Foo_f32; +template<typename T> +struct Bar; -struct Bar_f32; - -union Foo_i32 { - const int32_t *data; +template<typename T> +union Foo { + const T *data; }; -union Foo_f32 { - const float *data; +template<typename T, typename E> +union Tuple { + const T *a; + const E *b; }; -union Foo_Bar_f32 { - const Bar_f32 *data; -}; - -union Tuple_Foo_f32_____f32 { - const Foo_f32 *a; +template<typename T> +union Indirection { + const T *a; const float *b; }; -union Indirection_f32 { - const float *a; - const float *b; -}; +extern "C" { -void root(Foo_i32 a, - Foo_f32 b, - Bar_f32 c, - Foo_Bar_f32 d, - Bar_Foo_f32 e, - Bar_Bar_f32 f, - Tuple_Foo_f32_____f32 g, - Indirection_f32 h); +void root(Foo<int32_t> a, + Foo<float> b, + Bar<float> c, + Foo<Bar<float>> d, + Bar<Foo<float>> e, + Bar<Bar<float>> f, + Tuple<Foo<float>, float> g, + Indirection<float> h); } // extern "C" diff --git a/tests/expectations/simplify-option-ptr.cpp b/tests/expectations/simplify-option-ptr.cpp index 926c56a..df57074 100644 --- a/tests/expectations/simplify-option-ptr.cpp +++ b/tests/expectations/simplify-option-ptr.cpp @@ -1,8 +1,6 @@ #include <cstdint> #include <cstdlib> -extern "C" { - struct Opaque; struct Foo { @@ -17,6 +15,8 @@ union Bar { void (*z)(); }; +extern "C" { + void root(const Opaque *a, Opaque *b, Foo c, Bar d); } // extern "C" diff --git a/tests/expectations/static.cpp b/tests/expectations/static.cpp index 9b92be9..3a3b7e0 100644 --- a/tests/expectations/static.cpp +++ b/tests/expectations/static.cpp @@ -1,14 +1,14 @@ #include <cstdint> #include <cstdlib> -extern "C" { - struct Bar; struct Foo { }; +extern "C" { + extern const Bar BAR; extern Foo FOO; diff --git a/tests/expectations/std_lib.cpp b/tests/expectations/std_lib.cpp index db4aae9..906b704 100644 --- a/tests/expectations/std_lib.cpp +++ b/tests/expectations/std_lib.cpp @@ -1,14 +1,19 @@ #include <cstdint> #include <cstdlib> -extern "C" { +template<typename T> +struct Option; + +template<typename T, typename E> +struct Result; -struct Option_i32; +struct String; -struct Result_i32__String; +template<typename T> +struct Vec; -struct Vec_String; +extern "C" { -void root(const Vec_String *a, const Option_i32 *b, const Result_i32__String *c); +void root(const Vec<String> *a, const Option<int32_t> *b, const Result<int32_t, String> *c); } // extern "C" diff --git a/tests/expectations/struct.cpp b/tests/expectations/struct.cpp index dfa6724..2013309 100644 --- a/tests/expectations/struct.cpp +++ b/tests/expectations/struct.cpp @@ -1,8 +1,6 @@ #include <cstdint> #include <cstdlib> -extern "C" { - struct Opaque; struct Normal { @@ -25,6 +23,8 @@ struct TupleNamed { float y; }; +extern "C" { + void root(Opaque *a, Normal b, NormalWithZST c, TupleRenamed d, TupleNamed e); } // extern "C" diff --git a/tests/expectations/typedef.cpp b/tests/expectations/typedef.cpp index ca4cc78..3e54bf7 100644 --- a/tests/expectations/typedef.cpp +++ b/tests/expectations/typedef.cpp @@ -1,21 +1,14 @@ #include <cstdint> #include <cstdlib> -extern "C" { - -struct IntFoo_i32 { +template<typename T> +struct IntFoo { int32_t x; - int32_t y; + T y; }; -void root(IntFoo_i32 a); - -} // extern "C" - -template<typename T> -struct IntFoo; +extern "C" { -template<> -struct IntFoo<int32_t> : public IntFoo_i32 { +void root(IntFoo<int32_t> a); -}; +} // extern "C" diff --git a/tests/expectations/union.cpp b/tests/expectations/union.cpp index bc80bf6..89b19d9 100644 --- a/tests/expectations/union.cpp +++ b/tests/expectations/union.cpp @@ -1,8 +1,6 @@ #include <cstdint> #include <cstdlib> -extern "C" { - struct Opaque; union Normal { @@ -15,6 +13,8 @@ union NormalWithZST { float y; }; +extern "C" { + void root(Opaque *a, Normal b, NormalWithZST c); } // extern "C" -- GitLab