Skip to content

Commit 29e8abe

Browse files
committed
Add align attribute in unsafe
1 parent 9490952 commit 29e8abe

6 files changed

Lines changed: 157 additions & 2 deletions

File tree

‎cpp2rust/converter/converter.cpp‎

Lines changed: 11 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -790,7 +790,7 @@ void Converter::EmitRustStructOrUnion(clang::RecordDecl *decl) {
790790

791791
// Derived traits
792792
if (EmitsReprCForRecords()) {
793-
StrCat("#[repr(C)]");
793+
EmitReprC(decl);
794794
}
795795
auto attrs = GetStructAttributes(decl);
796796
Mapper::SetDerives(ctx_.getCanonicalTagType(decl),
@@ -892,8 +892,17 @@ std::string Converter::DestroyMembers(const clang::CXXRecordDecl *decl) {
892892
return out;
893893
}
894894

895-
void Converter::EmitRustUnion(clang::RecordDecl *decl) {
895+
void Converter::EmitReprC(clang::RecordDecl *decl) {
896+
if (decl->hasAttr<clang::AlignedAttr>()) {
897+
StrCat(std::format("#[repr(C, align({}))]",
898+
ctx_.getTypeAlign(ctx_.getCanonicalTagType(decl)) / 8));
899+
return;
900+
}
896901
StrCat("#[repr(C)]");
902+
}
903+
904+
void Converter::EmitRustUnion(clang::RecordDecl *decl) {
905+
EmitReprC(decl);
897906
auto attrs = GetStructAttributes(decl);
898907
Mapper::SetDerives(ctx_.getCanonicalTagType(decl),
899908
std::vector<std::string>(attrs.begin(), attrs.end()));

‎cpp2rust/converter/converter.h‎

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -120,6 +120,7 @@ class Converter : public clang::RecursiveASTVisitor<Converter> {
120120

121121
virtual void EmitRustStructOrUnion(clang::RecordDecl *decl);
122122

123+
void EmitReprC(clang::RecordDecl *decl);
123124
virtual void EmitRustUnion(clang::RecordDecl *decl);
124125

125126
virtual bool EmitsReprCForRecords() const { return true; }

‎cpp2rust/converter/models/converter_refcount.cpp‎

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1406,6 +1406,7 @@ bool ConverterRefCount::VisitUnaryExprOrTypeTraitExpr(
14061406
: expr->getArgumentExpr()->getType();
14071407
switch (expr->getKind()) {
14081408
case clang::UnaryExprOrTypeTrait::UETT_SizeOf:
1409+
// Once Values are dropped from fields, precomputation should be gone
14091410
if (RustSizeDivergesFromC(arg_type)) {
14101411
StrCat(std::format("{}usize", ctx_.getTypeSize(arg_type) / 8));
14111412
computed_expr_type_ = ComputedExprType::FreshValue;
@@ -1414,6 +1415,7 @@ bool ConverterRefCount::VisitUnaryExprOrTypeTraitExpr(
14141415
break;
14151416
case clang::UnaryExprOrTypeTrait::UETT_AlignOf:
14161417
case clang::UnaryExprOrTypeTrait::UETT_PreferredAlignOf:
1418+
// Once Values are dropped from fields, precomputation should be gone
14171419
if (RustSizeDivergesFromC(arg_type)) {
14181420
StrCat(std::format("{}usize", ctx_.getTypeAlign(arg_type) / 8));
14191421
computed_expr_type_ = ComputedExprType::FreshValue;
Lines changed: 71 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,71 @@
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(Default)]
10+
pub struct S {
11+
pub c: Value<u8>,
12+
pub x: Value<i64>,
13+
}
14+
impl Clone for S {
15+
fn clone(&self) -> Self {
16+
let __this: Value<S> = Rc::new(RefCell::new(Self {
17+
c: Rc::new(RefCell::new((*self.c.borrow()))),
18+
x: Rc::new(RefCell::new((*self.x.borrow()))),
19+
}));
20+
let this: Ptr<S> = __this.as_pointer();
21+
Rc::try_unwrap(__this).ok().unwrap().into_inner()
22+
}
23+
}
24+
impl ByteRepr for S {
25+
fn byte_size() -> usize {
26+
16
27+
}
28+
fn to_bytes(&self, buf: &mut [u8]) {
29+
(*self.c.borrow()).to_bytes(&mut buf[0..1]);
30+
(*self.x.borrow()).to_bytes(&mut buf[8..16]);
31+
}
32+
fn from_bytes(buf: &[u8]) -> Self {
33+
Self {
34+
c: Rc::new(RefCell::new(<u8>::from_bytes(&buf[0..1]))),
35+
x: Rc::new(RefCell::new(<i64>::from_bytes(&buf[8..16]))),
36+
}
37+
}
38+
}
39+
pub fn pack_size_0() -> u64 {
40+
return ((0 as usize).wrapping_add((0 as usize)) as u64);
41+
}
42+
pub fn pack_size_1(args_0: i32, args_1: f64) -> u64 {
43+
let args_0: Value<i32> = Rc::new(RefCell::new(args_0));
44+
let args_1: Value<f64> = Rc::new(RefCell::new(args_1));
45+
return ((2 as usize).wrapping_add((2 as usize)) as u64);
46+
}
47+
pub fn main() {
48+
std::process::exit(main_0());
49+
}
50+
fn main_0() -> i32 {
51+
let arr: Value<Box<[i64]>> = Rc::new(RefCell::new(Box::new([
52+
<i64>::default(),
53+
<i64>::default(),
54+
<i64>::default(),
55+
<i64>::default(),
56+
])));
57+
let s: Value<S> = Rc::new(RefCell::new(S {
58+
c: Rc::new(RefCell::new(<u8>::default())),
59+
x: Rc::new(RefCell::new(<i64>::default())),
60+
}));
61+
assert!((::std::mem::size_of::<i32>() == 4_usize));
62+
assert!((::std::mem::size_of::<[i64; 4]>() == 32_usize));
63+
assert!((16usize == 16_usize));
64+
assert!((::std::mem::align_of::<i32>() == 4_usize));
65+
assert!((16usize == 16_usize));
66+
assert!((::std::mem::align_of::<[i64; 4]>() == 8_usize));
67+
assert!((16usize == 16_usize));
68+
assert!((({ pack_size_0() }) == 0_u64));
69+
assert!((({ pack_size_1(1, 2.0E+0,) }) == 4_u64));
70+
return 0;
71+
}
Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,42 @@
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, align(16))]
10+
#[derive(Copy, Clone, Default)]
11+
pub struct S {
12+
pub c: libc::c_char,
13+
pub x: i64,
14+
}
15+
pub unsafe fn pack_size_0() -> u64 {
16+
return ((0 as usize).wrapping_add((0 as usize)) as u64);
17+
}
18+
pub unsafe fn pack_size_1(mut args_0: i32, mut args_1: f64) -> u64 {
19+
return ((2 as usize).wrapping_add((2 as usize)) as u64);
20+
}
21+
pub fn main() {
22+
unsafe {
23+
std::process::exit(main_0() as i32);
24+
}
25+
}
26+
unsafe fn main_0() -> i32 {
27+
let mut arr: [i64; 4] = [0_i64, 0_i64, 0_i64, 0_i64];
28+
let mut s: S = S {
29+
c: (0 as libc::c_char),
30+
x: 0_i64,
31+
};
32+
assert!(((::std::mem::size_of::<i32>()) == (4_usize)));
33+
assert!(((::std::mem::size_of::<[i64; 4]>()) == (32_usize)));
34+
assert!(((::std::mem::size_of::<S>()) == (16_usize)));
35+
assert!(((::std::mem::align_of::<i32>()) == (4_usize)));
36+
assert!(((::std::mem::align_of::<S>()) == (16_usize)));
37+
assert!(((::std::mem::align_of::<[i64; 4]>()) == (8_usize)));
38+
assert!(((::std::mem::align_of::<S>()) == (16_usize)));
39+
assert!(((unsafe { pack_size_0() }) == (0_u64)));
40+
assert!(((unsafe { pack_size_1(1, 2.0E+0,) }) == (4_u64)));
41+
return 0;
42+
}
Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
#include <cassert>
2+
#include <cstdint>
3+
4+
struct alignas(16) S {
5+
char c;
6+
int64_t x;
7+
};
8+
9+
template <typename... Args> unsigned long pack_size(Args... args) {
10+
return sizeof...(args) + sizeof...(Args);
11+
}
12+
13+
int main() {
14+
int64_t arr[4] = {};
15+
S s{};
16+
17+
assert(sizeof(int32_t) == 4);
18+
assert(sizeof(arr) == 32);
19+
assert(sizeof(s) == 16);
20+
21+
assert(alignof(int32_t) == 4);
22+
assert(alignof(S) == 16);
23+
24+
assert(__alignof(arr) == 8);
25+
assert(__alignof(s) == 16);
26+
27+
assert(pack_size() == 0);
28+
assert(pack_size(1, 2.0) == 4);
29+
return 0;
30+
}

0 commit comments

Comments
 (0)