diff --git a/engine/src/conversion/codegen_rs/mod.rs b/engine/src/conversion/codegen_rs/mod.rs index 5dd4cbb8c..938101de5 100644 --- a/engine/src/conversion/codegen_rs/mod.rs +++ b/engine/src/conversion/codegen_rs/mod.rs @@ -644,9 +644,7 @@ impl<'a> RsCodeGenerator<'a> { false, ) } - Api::ForwardDeclaration { .. } - | Api::ConcreteType { .. } - | Api::OpaqueTypedef { .. } => self.generate_type( + Api::ConcreteType { .. } => self.generate_type( &name, id, TypeKind::Abstract, @@ -657,6 +655,17 @@ impl<'a> RsCodeGenerator<'a> { None, false, ), + Api::ForwardDeclaration { .. } | Api::OpaqueTypedef { .. } => self.generate_type( + &name, + id, + TypeKind::Abstract, + false, // these types can't be kept in a Vector + false, // these types can't be put in a smart pointer + || None, + associated_methods, + None, + false, + ), Api::CType { .. } => RsCodegenResult { extern_c_mod_items: vec![ForeignItem::Verbatim(quote! { type #id = autocxx::#id; @@ -1042,6 +1051,7 @@ impl<'a> RsCodeGenerator<'a> { extern_c_mod_items: vec![ self.generate_cxxbridge_type(name, false, doc_attrs) ], + bridge_items: create_impl_items(&id, movable, destroyable, self.config), bindgen_mod_items, materializations, ..Default::default() diff --git a/integration-tests/tests/builder_modifiers.rs b/integration-tests/tests/builder_modifiers.rs index 0cf763e91..5fcc458fb 100644 --- a/integration-tests/tests/builder_modifiers.rs +++ b/integration-tests/tests/builder_modifiers.rs @@ -14,11 +14,19 @@ pub(crate) fn make_cpp17_adder() -> Option { make_clang_arg_adder(&["-std=c++17"]) } -struct ClangArgAdder(Vec); +struct ClangArgAdder(Vec, Vec); pub(crate) fn make_clang_arg_adder(args: &[&str]) -> Option { + make_clang_optional_arg_adder(args, &[]) +} + +pub(crate) fn make_clang_optional_arg_adder( + args: &[&str], + optional_args: &[&str], +) -> Option { let args: Vec<_> = args.iter().map(|a| a.to_string()).collect(); - Some(Box::new(ClangArgAdder(args))) + let optional_args: Vec<_> = optional_args.iter().map(|a| a.to_string()).collect(); + Some(Box::new(ClangArgAdder(args, optional_args))) } impl BuilderModifierFns for ClangArgAdder { @@ -34,6 +42,9 @@ impl BuilderModifierFns for ClangArgAdder { for f in &self.0 { builder = builder.flag(f); } + for f in &self.1 { + builder = builder.flag_if_supported(f); + } builder } } diff --git a/integration-tests/tests/integration_test.rs b/integration-tests/tests/integration_test.rs index 16c792b84..430edf322 100644 --- a/integration-tests/tests/integration_test.rs +++ b/integration-tests/tests/integration_test.rs @@ -8,7 +8,8 @@ use crate::{ builder_modifiers::{ - make_clang_arg_adder, make_cpp17_adder, EnableAutodiscover, SetSuppressSystemHeaders, + make_clang_arg_adder, make_clang_optional_arg_adder, make_cpp17_adder, EnableAutodiscover, + SetSuppressSystemHeaders, }, code_checkers::{ make_error_finder, make_rust_code_finder, make_string_finder, CppMatcher, @@ -5756,7 +5757,17 @@ fn test_issue_506() { } // namespace spanner "}; let rs = quote! {}; - run_test("", hdr, rs, &["spanner::Database", "spanner::Row"], &[]); + run_test_ex( + "", + hdr, + rs, + directives_from_lists(&["spanner::Database", "spanner::Row"], &[], None), + // This is normally a valid warning for generating bindings for this code, but we're doing + // it on purpose as a regression test on minimized code so we'll just ignore it. + make_clang_optional_arg_adder(&[], &["-Wno-delete-abstract-non-virtual-dtor"]), + None, + None, + ); } #[test] @@ -9429,6 +9440,43 @@ fn test_abstract_up() { run_test("", hdr, rs, &["A", "get_a"], &[]); } +#[test] +fn test_abstract_up_multiple_bridge() { + let hdr = indoc! {" + #include + class A { + public: + virtual void foo() const = 0; + virtual ~A() {} + }; + class B : public A { + public: + void foo() const {} + }; + inline std::unique_ptr get_a() { return std::make_unique(); } + "}; + let hexathorpe = Token![#](Span::call_site()); + let rs = quote! { + autocxx::include_cpp! { + #hexathorpe include "input.h" + safety!(unsafe_ffi) + generate!("A") + } + autocxx::include_cpp! { + #hexathorpe include "input.h" + safety!(unsafe_ffi) + name!(ffi2) + extern_cpp_type!("A", crate::ffi::A) + generate!("get_a") + } + fn main() { + let a = ffi2::get_a(); + a.foo(); + } + }; + do_run_test_manual("", hdr, rs, None, None).unwrap(); +} + #[test] fn test_abstract_private() { let hdr = indoc! {"