Skip to content

Commit 521db4b

Browse files
authored
Translate C99 flexible array member (#473)
1 parent a18bb1a commit 521db4b

5 files changed

Lines changed: 209 additions & 5 deletions

File tree

‎cpp2rust/converter/converter.cpp‎

Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -268,7 +268,7 @@ bool Converter::VisitConstantArrayType(clang::ConstantArrayType *type) {
268268
bool Converter::VisitIncompleteArrayType(clang::IncompleteArrayType *type) {
269269
StrCat('[');
270270
Convert(type->getElementType());
271-
StrCat(']');
271+
StrCat("; 0]");
272272
return false;
273273
}
274274

@@ -4129,9 +4129,8 @@ std::string Converter::GetArrayDefaultAsString(clang::QualType qual_type) {
41294129
return std::format("[{}; {}]", element_type_as_string,
41304130
size_as_string.c_str());
41314131
}
4132-
if (auto *array_type =
4133-
clang::dyn_cast<clang::IncompleteArrayType>(qual_type)) {
4134-
return GetDefaultAsString(array_type->getElementType());
4132+
if (clang::isa<clang::IncompleteArrayType>(qual_type)) {
4133+
return "[]";
41354134
}
41364135
if (Printer::ToString(ctx_, qual_type).contains("std::array")) {
41374136
assert(GetTemplateArgs(qual_type).has_value());

‎cpp2rust/converter/models/converter_refcount.cpp‎

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -75,7 +75,8 @@ static bool NeedsMutAccess(clang::ASTContext &ctx,
7575
static bool IsValueField(clang::ASTContext &ctx,
7676
const clang::FieldDecl *field) {
7777
auto type = field->getType();
78-
return type->isConstantArrayType() || IsBoxedType(ctx, type);
78+
return type->isConstantArrayType() || type->isIncompleteArrayType() ||
79+
IsBoxedType(ctx, type);
7980
}
8081

8182
// Whether `expr` is an array field whose elements are accessed through
@@ -2449,6 +2450,12 @@ bool ConverterRefCount::VisitCXXDefaultArgExpr(clang::CXXDefaultArgExpr *expr) {
24492450

24502451
std::string
24512452
ConverterRefCount::GetArrayDefaultAsString(clang::QualType qual_type) {
2453+
if (auto *array_type =
2454+
clang::dyn_cast<clang::IncompleteArrayType>(qual_type)) {
2455+
PushConversionKind push(*this, ConversionKind::Unboxed);
2456+
return std::format("Box::<[{}]>::default()",
2457+
ToString(array_type->getElementType()));
2458+
}
24522459
if (auto *array_type = clang::dyn_cast<clang::ConstantArrayType>(qual_type)) {
24532460
const auto &size = array_type->getSize();
24542461
auto size_as_string = GetNumAsString(size);
Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
#include <assert.h>
2+
#include <stdlib.h>
3+
#include <string.h>
4+
5+
struct F {
6+
int n;
7+
char tail[];
8+
};
9+
10+
int main(void) {
11+
assert(sizeof(struct F) == sizeof(int));
12+
struct F *f = malloc(sizeof(struct F) + 4);
13+
assert(f != NULL);
14+
f->n = 4;
15+
memcpy(f->tail, "xyz", 4);
16+
assert(f->n == 4);
17+
assert(strcmp(f->tail, "xyz") == 0);
18+
assert(f->tail[1] == 'y');
19+
free(f);
20+
struct F *g = malloc(sizeof(struct F) + 8);
21+
assert(g != NULL);
22+
g->n = 8;
23+
memcpy(g->tail, "abcdefg", 8);
24+
assert(g->tail[6] == 'g');
25+
assert(g->tail[7] == '\0');
26+
free(g);
27+
return 0;
28+
}
Lines changed: 95 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,95 @@
1+
extern crate libcc2rs;
2+
use libcc2rs::*;
3+
use std::cell::RefCell;
4+
use std::collections::BTreeMap;
5+
use std::io::prelude::*;
6+
use std::io::{Read, Seek, Write};
7+
use std::os::fd::AsFd;
8+
use std::rc::{Rc, Weak};
9+
#[derive(DeepClone, Record, ByteRepr, VaArg, FnPtrArg)]
10+
#[byte_size(4)]
11+
pub struct F {
12+
#[offset(0)]
13+
pub n: i32,
14+
#[offset(4)]
15+
#[byte_size(0)]
16+
pub tail: Value<Box<[i8]>>,
17+
}
18+
impl Default for F {
19+
fn default() -> Self {
20+
F {
21+
n: 0_i32,
22+
tail: Rc::new(RefCell::new(Box::<[i8]>::default())),
23+
}
24+
}
25+
}
26+
pub fn main() {
27+
__cpp2rust_init_globals();
28+
std::process::exit(main_0());
29+
}
30+
fn main_0() -> i32 {
31+
assert!((((4usize == ::std::mem::size_of::<i32>()) as i32) != 0));
32+
let mut f: Ptr<F> =
33+
libcc2rs::malloc_refcount((4usize as usize).wrapping_add(4_usize)).reinterpret_cast::<F>();
34+
assert!((((!((f).is_null())) as i32) != 0));
35+
field!(f, n).write(4);
36+
{
37+
((array_field_ptr!(f, tail) as Ptr<i8>) as Ptr<i8>)
38+
.to_any()
39+
.memcpy(
40+
&Ptr::<i8>::from_string_literal(b"xyz").to_any(),
41+
4_usize as usize,
42+
);
43+
((array_field_ptr!(f, tail) as Ptr<i8>) as Ptr<i8>).to_any()
44+
};
45+
assert!((((f.with(|__s| __s.n) == 4) as i32) != 0));
46+
assert!(
47+
((({
48+
let mut __it1 = (array_field_ptr!(f, tail) as Ptr<i8>).to_c_string_iterator();
49+
let mut __it2 = Ptr::<i8>::from_string_literal(b"xyz").to_c_string_iterator();
50+
loop {
51+
let __c1 = __it1.next();
52+
let __c2 = __it2.next();
53+
if __c1 != __c2 {
54+
break (__c1.unwrap_or(0) as u8 as i32) - (__c2.unwrap_or(0) as u8 as i32);
55+
}
56+
if __c1.is_none() {
57+
break 0;
58+
}
59+
}
60+
} == 0) as i32)
61+
!= 0)
62+
);
63+
assert!(
64+
(((((elem!((array_field_ptr!(f, tail) as Ptr::<i8>), 1).read()) as i32) == ('y' as i32))
65+
as i32)
66+
!= 0)
67+
);
68+
libcc2rs::free_refcount((f).to_any());
69+
let mut g: Ptr<F> =
70+
libcc2rs::malloc_refcount((4usize as usize).wrapping_add(8_usize)).reinterpret_cast::<F>();
71+
assert!((((!((g).is_null())) as i32) != 0));
72+
field!(g, n).write(8);
73+
{
74+
((array_field_ptr!(g, tail) as Ptr<i8>) as Ptr<i8>)
75+
.to_any()
76+
.memcpy(
77+
&Ptr::<i8>::from_string_literal(b"abcdefg").to_any(),
78+
8_usize as usize,
79+
);
80+
((array_field_ptr!(g, tail) as Ptr<i8>) as Ptr<i8>).to_any()
81+
};
82+
assert!(
83+
(((((elem!((array_field_ptr!(g, tail) as Ptr::<i8>), 6).read()) as i32) == ('g' as i32))
84+
as i32)
85+
!= 0)
86+
);
87+
assert!(
88+
(((((elem!((array_field_ptr!(g, tail) as Ptr::<i8>), 7).read()) as i32) == ('\0' as i32))
89+
as i32)
90+
!= 0)
91+
);
92+
libcc2rs::free_refcount((g).to_any());
93+
return 0;
94+
}
95+
pub fn __cpp2rust_init_globals() {}
Lines changed: 75 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,75 @@
1+
extern crate libc;
2+
use libc::*;
3+
extern crate libcc2rs;
4+
use libcc2rs::*;
5+
use std::collections::BTreeMap;
6+
use std::io::{Read, Seek, Write};
7+
use std::os::fd::{AsFd, FromRawFd, IntoRawFd};
8+
use std::rc::Rc;
9+
#[repr(C)]
10+
#[derive(Copy, Clone, VaArg, FnPtrArg)]
11+
pub struct F {
12+
pub n: i32,
13+
pub tail: [libc::c_char; 0],
14+
}
15+
impl Default for F {
16+
fn default() -> Self {
17+
F { n: 0_i32, tail: [] }
18+
}
19+
}
20+
pub fn main() {
21+
unsafe {
22+
__cpp2rust_init_globals();
23+
std::process::exit(main_0() as i32);
24+
}
25+
}
26+
unsafe fn main_0() -> i32 {
27+
assert!(((((::std::mem::size_of::<F>()) == (::std::mem::size_of::<i32>())) as i32) != 0));
28+
let mut f: *mut F =
29+
(libcc2rs::malloc_unsafe((::std::mem::size_of::<F>() as usize).wrapping_add(4_usize))
30+
as *mut F);
31+
assert!((((!((f).is_null())) as i32) != 0));
32+
(*f).n = 4;
33+
{
34+
if 4_usize != 0 {
35+
::std::ptr::copy_nonoverlapping(
36+
(c"xyz".as_ptr().cast_mut() as *const ::libc::c_void),
37+
((*f).tail.as_mut_ptr() as *mut ::libc::c_void),
38+
4_usize as usize,
39+
)
40+
}
41+
((*f).tail.as_mut_ptr() as *mut ::libc::c_void)
42+
};
43+
assert!((((((*f).n) == (4)) as i32) != 0));
44+
assert!(
45+
((((libc::strcmp(
46+
((*f).tail.as_mut_ptr()).cast_const(),
47+
(c"xyz".as_ptr().cast_mut()).cast_const()
48+
)) == (0)) as i32)
49+
!= 0)
50+
);
51+
assert!((((((*(*f).tail.as_mut_ptr().add((1) as usize)) as i32) == ('y' as i32)) as i32) != 0));
52+
libcc2rs::free_unsafe((f as *mut ::libc::c_void));
53+
let mut g: *mut F =
54+
(libcc2rs::malloc_unsafe((::std::mem::size_of::<F>() as usize).wrapping_add(8_usize))
55+
as *mut F);
56+
assert!((((!((g).is_null())) as i32) != 0));
57+
(*g).n = 8;
58+
{
59+
if 8_usize != 0 {
60+
::std::ptr::copy_nonoverlapping(
61+
(c"abcdefg".as_ptr().cast_mut() as *const ::libc::c_void),
62+
((*g).tail.as_mut_ptr() as *mut ::libc::c_void),
63+
8_usize as usize,
64+
)
65+
}
66+
((*g).tail.as_mut_ptr() as *mut ::libc::c_void)
67+
};
68+
assert!((((((*(*g).tail.as_mut_ptr().add((6) as usize)) as i32) == ('g' as i32)) as i32) != 0));
69+
assert!(
70+
(((((*(*g).tail.as_mut_ptr().add((7) as usize)) as i32) == ('\0' as i32)) as i32) != 0)
71+
);
72+
libcc2rs::free_unsafe((g as *mut ::libc::c_void));
73+
return 0;
74+
}
75+
pub unsafe fn __cpp2rust_init_globals() {}

0 commit comments

Comments
 (0)