Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions cpp2rust/converter/converter_lib.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -286,6 +286,9 @@ bool TypeImplementsByteRepr(clang::QualType qt) {
if (rd->isUnion()) {
return true;
}
if (!qt.isTriviallyCopyableType(rd->getASTContext())) {
return false;
}
for (const auto *field : rd->fields()) {
if (!TypeImplementsByteRepr(field->getType())) {
return false;
Expand Down
15 changes: 14 additions & 1 deletion libcc2rs/src/reinterpret.rs
Original file line number Diff line number Diff line change
Expand Up @@ -92,7 +92,20 @@ impl<T: ByteRepr> ByteRepr for Vec<T> {}
impl<T: ByteRepr> ByteRepr for Option<T> {}
impl<T: ByteRepr> ByteRepr for std::rc::Rc<T> {}
impl<T: ByteRepr> ByteRepr for std::cell::RefCell<T> {}
impl<T: ByteRepr> ByteRepr for Box<[T]> {}
impl<T: ByteRepr> ByteRepr for Box<[T]> {
fn to_bytes(&self, buf: &mut [u8]) {
let elem_size = T::byte_size();
for (i, elem) in self.iter().enumerate() {
elem.to_bytes(&mut buf[i * elem_size..(i + 1) * elem_size]);
}
}

fn from_bytes(buf: &[u8]) -> Self {
let elem_size = T::byte_size();
assert_eq!(buf.len() % elem_size, 0, "ub: partial array element");
buf.chunks(elem_size).map(T::from_bytes).collect()
}
}
impl<T: ByteRepr> ByteRepr for Box<T> {}
impl<T: 'static> ByteRepr for *const T {}
impl<T: 'static> ByteRepr for *mut T {}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -45,21 +45,7 @@ impl Default for S {
}
}
}
impl ByteRepr for S {
fn byte_size() -> usize {
32
}
fn to_bytes(&self, buf: &mut [u8]) {
(*self.v.borrow()).to_bytes(&mut buf[0..24]);
(*self.n.borrow()).to_bytes(&mut buf[24..32]);
}
fn from_bytes(buf: &[u8]) -> Self {
Self {
v: Rc::new(RefCell::new(<Vec<i32>>::from_bytes(&buf[0..24]))),
n: Rc::new(RefCell::new(<Box<[i32]>>::from_bytes(&buf[24..32]))),
}
}
}
impl ByteRepr for S {}
pub fn sum_0(s: Ptr<S>) -> i32 {
return {
let _lhs = {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -20,19 +20,7 @@ impl Clone for S {
Rc::try_unwrap(__this).ok().unwrap().into_inner()
}
}
impl ByteRepr for S {
fn byte_size() -> usize {
4
}
fn to_bytes(&self, buf: &mut [u8]) {
(*self.v.borrow()).to_bytes(&mut buf[0..4]);
}
fn from_bytes(buf: &[u8]) -> Self {
Self {
v: Rc::new(RefCell::new(<i32>::from_bytes(&buf[0..4]))),
}
}
}
impl ByteRepr for S {}
pub trait Base {
fn apply(&self, x: i32) -> i32;
}
Expand All @@ -50,19 +38,7 @@ impl Clone for Derived {
Rc::try_unwrap(__this).ok().unwrap().into_inner()
}
}
impl ByteRepr for Derived {
fn byte_size() -> usize {
16
}
fn to_bytes(&self, buf: &mut [u8]) {
(*self.factor.borrow()).to_bytes(&mut buf[8..12]);
}
fn from_bytes(buf: &[u8]) -> Self {
Self {
factor: Rc::new(RefCell::new(<i32>::from_bytes(&buf[8..12]))),
}
}
}
impl ByteRepr for Derived {}
pub fn main() {
__cpp2rust_init_globals();
std::process::exit(main_0());
Expand Down
25 changes: 25 additions & 0 deletions tests/unit/array_field_addr.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
// no-compile: refcount
#include <assert.h>
#include <stdlib.h>
#include <string.h>

struct S {
int before;
unsigned char mask[4];
int after;
};

int main(void) {
struct S *s = malloc(sizeof(struct S));
assert(s != NULL);
s->before = 1;
memset(s->mask, 5, sizeof(s->mask));
s->after = 2;
*(unsigned char *)&s->mask = 7;
unsigned char out[4];
memcpy(out, &s->mask, sizeof(s->mask));
assert(out[0] == 7 && out[3] == 5);
assert(s->before == 1 && s->after == 2);
free(s);
return 0;
}
43 changes: 43 additions & 0 deletions tests/unit/container_field_addr.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
// panic: refcount
#include <cassert>
#include <map>
#include <string>
#include <vector>

struct S {
int tag;
std::vector<int> v;
std::string s;
std::map<int, int> m;
};

static void add(std::vector<int> *v, int k) { v->push_back(k); }

static void append(std::string *s, const char *t, std::size_t n) {
s->append(t, n);
}

static void put(std::map<int, int> *m, int k, int v) { (*m)[k] = v; }

static void run(S *h) {
add(&h->v, h->tag);
append(&h->s, "ab", 2);
put(&h->m, h->tag, 2);
std::vector<int> *pv = &h->v;
pv->push_back((int)pv->size());
assert(h->v.size() == 2 && h->v[0] == 7 && h->v[1] == 1);
assert(h->s == "ab");
assert(h->m[7] == 2);
assert(h->tag == 7);
}

int main() {
S local;
local.tag = 7;
run(&local);
S *heap = new S();
heap->tag = 7;
run(heap);
delete heap;
return 0;
}
45 changes: 45 additions & 0 deletions tests/unit/field_aliasing.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
// panic: refcount
#include <assert.h>
#include <stdlib.h>

struct In {
int x;
int y;
};

struct S {
struct In in;
int total;
int n;
int arr[4];
};

struct Node {
int x;
struct Node *self;
};

int main(void) {
struct S *p = calloc(1, sizeof(struct S));
assert(p != NULL);
struct S *q = p;
p->in.x = 1;
p->in.y = 2;
p->total = q->in.x + q->in.y;
assert(q->total == 3);
struct In *ip = &p->in;
ip->x = p->total + 1;
assert(q->in.x == 4 && q->in.y == 2);
p->arr[p->n] = p->total;
p->n += 1;
p->arr[p->n] = q->in.x;
assert(q->arr[0] == 3 && q->arr[1] == 4 && q->n == 1);
free(p);

struct Node s;
s.x = 1;
s.self = &s;
s.self->x = s.x + 1;
assert(s.x == 2);
return 0;
}
51 changes: 51 additions & 0 deletions tests/unit/field_method_receiver.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
#include <cassert>
#include <vector>

struct Counter {
int n;
int get() const { return n; }
void add(int k) { n += k; }
Counter *self() { return this; }
void take(Counter *other) {
n += other->n;
other->n = 0;
}
};

struct S {
int tag;
Counter c;
Counter arr[2];
std::vector<int> v;
void bump() { c.add(tag); }
};

static void run(S *o) {
o->c.add(2);
assert(o->c.get() == 2);
o->arr[1].add(5);
assert(o->arr[1].get() == 5);
o->c.self()->add(1);
assert(o->c.get() == 3);
assert(o->c.self() == &o->c);
o->arr[0].take(&o->arr[1]);
assert(o->arr[0].get() == 5 && o->arr[1].get() == 0);
o->c.take(&o->c);
assert(o->c.get() == 0);
o->bump();
assert(o->c.get() == 1);
o->v.push_back(o->c.get());
assert(o->v.size() == 1 && o->v[0] == 1);
assert(o->tag == 1);
}

int main() {
S local{};
local.tag = 1;
run(&local);
S *heap = new S{};
heap->tag = 1;
run(heap);
delete heap;
return 0;
}
43 changes: 43 additions & 0 deletions tests/unit/field_pointers_malloced_struct.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
// panic: refcount
#include <cassert>
#include <cstdlib>

struct S {
int a;
int b;
int c;
};

static int bump(S *s) {
s->b += 10;
return s->b;
}

int main() {
S *s = static_cast<S *>(calloc(1, sizeof(S)));
assert(s != nullptr);
s->b = 1;
s->a = bump(s);
assert(s->a == 11);
assert(s->b == 11);
s->a = 1;
s->b = 2;
s->c = 0;
if (s->a < s->b && s->c++ == 0) {
s->a = 5;
}
assert(s->a == 5 && s->c == 1);
if (s->a < s->b && s->c++ == 0) {
s->a = 6;
}
assert(s->a == 5 && s->c == 1);
int x = s->a + (s->b = 3);
assert(x == 8 && s->b == 3);
int y = 0;
s->c = (y = 99);
assert(s->c == 99 && y == 99);
s->a += bump(s);
assert(s->a == 18 && s->b == 13 && s->c == 99);
free(s);
return 0;
}
33 changes: 33 additions & 0 deletions tests/unit/first_field_ptr_covers_struct.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
// panic: refcount
#include <assert.h>
#include <stdlib.h>
#include <string.h>

struct In {
short a;
short b;
};

struct S {
int x;
struct In in;
int z;
};

int main(void) {
struct S src = {1, {2, 3}, 4};
struct S *p = malloc(sizeof(struct S));
assert(p != NULL);
memcpy(&p->x, &src, sizeof(*p));
assert(p->x == 1 && p->in.a == 2 && p->in.b == 3 && p->z == 4);
struct In n = {5, 6};
memcpy(&p->in, &n, sizeof(n));
assert(p->x == 1 && p->in.a == 5 && p->in.b == 6 && p->z == 4);
unsigned char *bz = (unsigned char *)&p->z;
for (int i = 0; i < 4; i++) {
bz[i] = 1;
}
assert(p->z == 0x01010101 && p->in.b == 6);
free(p);
return 0;
}
30 changes: 30 additions & 0 deletions tests/unit/first_member_downcast.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
// panic: refcount
#include <assert.h>
#include <stdlib.h>

typedef struct base {
int kind;
} base;

typedef struct derived {
base head;
size_t value;
} derived;

int main(void) {
derived *d = malloc(sizeof(*d));
assert(d != NULL);
d->head.kind = 3;
d->value = 7;
base *b = &d->head;
derived *back = (derived *)b;
assert(back == d);
assert(back->value == 7);
assert(back->head.kind == 3);
back->value = 8;
assert(d->value == 8);
b->kind = 4;
assert(d->head.kind == 4);
free(back);
return 0;
}
Loading
Loading