Skip to content

Commit

Permalink
Merge pull request #1021 from dtolnay/carray
Browse files Browse the repository at this point in the history
Recognize C array of relocatable element type in struct as relocatable
  • Loading branch information
dtolnay committed Mar 8, 2022
2 parents c53e4bc + 033294e commit a6e1cd1
Show file tree
Hide file tree
Showing 5 changed files with 57 additions and 3 deletions.
17 changes: 17 additions & 0 deletions gen/src/builtin.rs
Expand Up @@ -28,6 +28,7 @@ pub struct Builtins<'a> {
pub rust_slice_repr: bool,
pub exception: bool,
pub relocatable: bool,
pub relocatable_or_array: bool,
pub friend_impl: bool,
pub is_complete: bool,
pub destroy: bool,
Expand Down Expand Up @@ -113,6 +114,11 @@ pub(super) fn write(out: &mut OutFile) {
include.sys_types = true;
}

if builtin.relocatable_or_array {
include.cstddef = true;
builtin.relocatable = true;
}

if builtin.relocatable {
include.type_traits = true;
}
Expand Down Expand Up @@ -357,6 +363,17 @@ pub(super) fn write(out: &mut OutFile) {
writeln!(out, "}};");
}

if builtin.relocatable_or_array {
out.next_section();
writeln!(out, "template <typename T>");
writeln!(out, "struct IsRelocatableOrArray : IsRelocatable<T> {{}};");
writeln!(out, "template <typename T, ::std::size_t N>");
writeln!(
out,
"struct IsRelocatableOrArray<T[N]> : IsRelocatableOrArray<T> {{}};",
);
}

out.end_block(Block::AnonymousNamespace);
out.end_block(Block::InlineNamespace("cxxbridge1"));

Expand Down
20 changes: 19 additions & 1 deletion gen/src/write.rs
Expand Up @@ -470,7 +470,25 @@ fn check_trivial_extern_type(out: &mut OutFile, alias: &TypeAlias, reasons: &[Tr
let id = alias.name.to_fully_qualified();
out.builtin.relocatable = true;
writeln!(out, "static_assert(");
writeln!(out, " ::rust::IsRelocatable<{}>::value,", id);
if reasons
.iter()
.all(|r| matches!(r, TrivialReason::StructField(_)))
{
// If the type is only used as a struct field and not as by-value
// function argument or any other use, then C array of trivially
// relocatable type is also permissible.
//
// --- means something sane:
// struct T { char buf[N]; };
//
// --- means something totally different:
// void f(char buf[N]);
//
out.builtin.relocatable_or_array = true;
writeln!(out, " ::rust::IsRelocatableOrArray<{}>::value,", id);
} else {
writeln!(out, " ::rust::IsRelocatable<{}>::value,", id);
}
writeln!(
out,
" \"type {} should be trivially move constructible and trivially destructible in C++ to be used as {} in Rust\");",
Expand Down
16 changes: 15 additions & 1 deletion tests/ffi/lib.rs
Expand Up @@ -15,7 +15,7 @@
pub mod cast;
pub mod module;

use cxx::{CxxString, CxxVector, SharedPtr, UniquePtr};
use cxx::{type_id, CxxString, CxxVector, ExternType, SharedPtr, UniquePtr};
use std::fmt::{self, Display};
use std::mem::MaybeUninit;
use std::os::raw::c_char;
Expand Down Expand Up @@ -80,6 +80,7 @@ pub mod ffi {

pub struct Array {
a: [i32; 4],
b: Buffer,
}

#[derive(Copy, Clone, Debug, Default, Eq, Hash, Ord, PartialEq, PartialOrd)]
Expand Down Expand Up @@ -248,6 +249,10 @@ pub mod ffi {
CVal2,
}

extern "C++" {
type Buffer = crate::Buffer;
}

extern "Rust" {
type R;

Expand Down Expand Up @@ -412,6 +417,15 @@ impl ffi::Array {
}
}

#[derive(Default)]
#[repr(C)]
pub struct Buffer([c_char; 12]);

unsafe impl ExternType for Buffer {
type Id = type_id!("tests::Buffer");
type Kind = cxx::kind::Trivial;
}

#[derive(Debug)]
struct Error;

Expand Down
2 changes: 2 additions & 0 deletions tests/ffi/tests.h
Expand Up @@ -84,6 +84,8 @@ struct Borrow {
const std::string &s;
};

typedef char Buffer[12];

size_t c_return_primitive();
Shared c_return_shared();
::A::AShared c_return_ns_shared();
Expand Down
5 changes: 4 additions & 1 deletion tests/test.rs
Expand Up @@ -261,7 +261,10 @@ fn test_c_method_calls() {
assert_eq!(2023, *ffi::Shared { z: 2023 }.c_method_mut_on_shared());

let val = 42;
let mut array = ffi::Array { a: [0, 0, 0, 0] };
let mut array = ffi::Array {
a: [0, 0, 0, 0],
b: ffi::Buffer::default(),
};
array.c_set_array(val);
assert_eq!(array.a.len() as i32 * val, array.r_get_array_sum());
}
Expand Down

0 comments on commit a6e1cd1

Please sign in to comment.