Fix remaining "C-linkage specified, but returns UDT" warnings on macOS
diff --git a/gen/src/builtin.rs b/gen/src/builtin.rs
index 65cd703..5248a20 100644
--- a/gen/src/builtin.rs
+++ b/gen/src/builtin.rs
@@ -21,6 +21,10 @@
pub trycatch: bool,
pub ptr_len: bool,
pub repr_fat: bool,
+ pub rust_str_new_unchecked: bool,
+ pub rust_str_repr: bool,
+ pub rust_slice_new: bool,
+ pub rust_slice_repr: bool,
pub exception: bool,
pub relocatable: bool,
pub friend_impl: bool,
@@ -162,6 +166,20 @@
ifndef::write(out, builtin.layout, "CXXBRIDGE1_LAYOUT");
ifndef::write(out, builtin.relocatable, "CXXBRIDGE1_RELOCATABLE");
+ if builtin.rust_str_new_unchecked {
+ out.next_section();
+ writeln!(out, "class Str::uninit {{}};");
+ writeln!(out, "inline Str::Str(uninit) noexcept {{}}");
+ }
+
+ if builtin.rust_slice_new {
+ out.next_section();
+ writeln!(out, "template <typename T>");
+ writeln!(out, "class Slice<T>::uninit {{}};");
+ writeln!(out, "template <typename T>");
+ writeln!(out, "inline Slice<T>::Slice(uninit) noexcept {{}}");
+ }
+
out.begin_block(Block::Namespace("detail"));
if builtin.maybe_uninit {
@@ -221,8 +239,18 @@
out.begin_block(Block::AnonymousNamespace);
+ if builtin.repr_fat {
+ include.array = true;
+ include.cstdint = true;
+ out.next_section();
+ out.begin_block(Block::Namespace("repr"));
+ writeln!(out, "using Fat = ::std::array<::std::uintptr_t, 2>;");
+ out.end_block(Block::Namespace("repr"));
+ }
+
if builtin.ptr_len {
include.cstddef = true;
+ out.next_section();
out.begin_block(Block::Namespace("repr"));
writeln!(out, "struct PtrLen final {{");
writeln!(out, " void *ptr;");
@@ -231,15 +259,47 @@
out.end_block(Block::Namespace("repr"));
}
- if builtin.repr_fat {
- include.array = true;
- include.cstdint = true;
- out.begin_block(Block::Namespace("repr"));
- writeln!(out, "template <typename T>");
- writeln!(out, "struct Fat final {{");
- writeln!(out, " T repr;");
+ if builtin.rust_str_new_unchecked || builtin.rust_str_repr {
+ out.next_section();
+ writeln!(out, "template <>");
+ writeln!(out, "class impl<Str> final {{");
+ writeln!(out, "public:");
+ if builtin.rust_str_new_unchecked {
+ writeln!(
+ out,
+ " static Str new_unchecked(repr::Fat repr) noexcept {{",
+ );
+ writeln!(out, " Str str = Str::uninit{{}};");
+ writeln!(out, " str.repr = repr;");
+ writeln!(out, " return str;");
+ writeln!(out, " }}");
+ }
+ if builtin.rust_str_repr {
+ writeln!(out, " static repr::Fat repr(Str str) noexcept {{");
+ writeln!(out, " return str.repr;");
+ writeln!(out, " }}");
+ }
writeln!(out, "}};");
- out.end_block(Block::Namespace("repr"));
+ }
+
+ if builtin.rust_slice_new || builtin.rust_slice_repr {
+ out.next_section();
+ writeln!(out, "template <typename T>");
+ writeln!(out, "class impl<Slice<T>> final {{");
+ writeln!(out, "public:");
+ if builtin.rust_slice_new {
+ writeln!(out, " static Slice<T> slice(repr::Fat repr) noexcept {{");
+ writeln!(out, " Slice<T> slice = typename Slice<T>::uninit{{}};");
+ writeln!(out, " slice.repr = repr;");
+ writeln!(out, " return slice;");
+ writeln!(out, " }}");
+ }
+ if builtin.rust_slice_repr {
+ writeln!(out, " static repr::Fat repr(Slice<T> slice) noexcept {{");
+ writeln!(out, " return slice.repr;");
+ writeln!(out, " }}");
+ }
+ writeln!(out, "}};");
}
if builtin.rust_error {
diff --git a/gen/src/write.rs b/gen/src/write.rs
index c6331f4..2404f9c 100644
--- a/gen/src/write.rs
+++ b/gen/src/write.rs
@@ -5,7 +5,7 @@
use crate::syntax::atom::Atom::{self, *};
use crate::syntax::instantiate::ImplKey;
use crate::syntax::map::UnorderedMap as Map;
-use crate::syntax::set::{OrderedSet, UnorderedSet};
+use crate::syntax::set::UnorderedSet;
use crate::syntax::symbol::Symbol;
use crate::syntax::trivial::{self, TrivialReason};
use crate::syntax::{
@@ -125,25 +125,6 @@
out.set_namespace(Default::default());
- // MSVC workaround for "C linkage function cannot return C++ class" error.
- // Apparently the compiler fails to perform implicit instantiations as part
- // of an extern declaration return type. Instead we instantiate explicitly.
- // See https://stackoverflow.com/a/57429504/6086311.
- out.next_section();
- let mut slice_in_return_position = OrderedSet::new();
- for api in apis {
- if let Api::CxxFunction(efn) | Api::RustFunction(efn) = api {
- if let Some(ty @ Type::Str(_)) | Some(ty @ Type::SliceRef(_)) = &efn.ret {
- slice_in_return_position.insert(ty);
- }
- }
- }
- for ty in &slice_in_return_position {
- write!(out, "template class ::rust::repr::Fat<");
- write_type(out, ty);
- writeln!(out, ">;");
- }
-
out.next_section();
for api in apis {
if let Api::TypeAlias(ety) = api {
@@ -757,7 +738,16 @@
}
match &efn.ret {
Some(Type::Ref(_)) => write!(out, "&"),
- Some(Type::Str(_)) | Some(Type::SliceRef(_)) if !indirect_return => write!(out, "{{"),
+ Some(Type::Str(_)) if !indirect_return => {
+ out.builtin.rust_str_repr = true;
+ write!(out, "::rust::impl<::rust::Str>::repr(");
+ }
+ Some(ty @ Type::SliceRef(_)) if !indirect_return => {
+ out.builtin.rust_slice_repr = true;
+ write!(out, "::rust::impl<");
+ write_type(out, ty);
+ write!(out, ">::repr(");
+ }
_ => {}
}
match &efn.receiver {
@@ -796,7 +786,7 @@
match &efn.ret {
Some(Type::RustBox(_)) => write!(out, ".into_raw()"),
Some(Type::UniquePtr(_)) => write!(out, ".release()"),
- Some(Type::Str(_)) | Some(Type::SliceRef(_)) if !indirect_return => write!(out, "}}"),
+ Some(Type::Str(_)) | Some(Type::SliceRef(_)) if !indirect_return => write!(out, ")"),
_ => {}
}
if indirect_return {
@@ -995,6 +985,16 @@
write!(out, "(");
}
Type::Ref(_) => write!(out, "*"),
+ Type::Str(_) => {
+ out.builtin.rust_str_new_unchecked = true;
+ write!(out, "::rust::impl<::rust::Str>::new_unchecked(");
+ }
+ Type::SliceRef(_) => {
+ out.builtin.rust_slice_new = true;
+ write!(out, "::rust::impl<");
+ write_type(out, ret);
+ write!(out, ">::slice(");
+ }
_ => {}
}
}
@@ -1040,10 +1040,8 @@
write!(out, ")");
if !indirect_return {
if let Some(ret) = &sig.ret {
- match ret {
- Type::RustBox(_) | Type::UniquePtr(_) => write!(out, ")"),
- Type::Str(_) | Type::SliceRef(_) => write!(out, ".repr"),
- _ => {}
+ if let Type::RustBox(_) | Type::UniquePtr(_) | Type::Str(_) | Type::SliceRef(_) = ret {
+ write!(out, ")");
}
}
}
@@ -1113,11 +1111,9 @@
write_type(out, &ty.inner);
write!(out, " *");
}
- Some(ty @ Type::Str(_)) | Some(ty @ Type::SliceRef(_)) => {
+ Some(Type::Str(_)) | Some(Type::SliceRef(_)) => {
out.builtin.repr_fat = true;
- write!(out, "::rust::repr::Fat<");
- write_type(out, ty);
- write!(out, "> ");
+ write!(out, "::rust::repr::Fat ");
}
Some(ty) if out.types.needs_indirect_abi(ty) => write!(out, "void "),
_ => write_return_type(out, ty),