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
1 change: 1 addition & 0 deletions cpp2rust/compat/platform_flags.h
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ static inline std::vector<std::string> getPlatformClangFlags() {
std::vector<std::string> flags = {
"-resource-dir=" CLANG_RESOURCE_DIR,
"-I" COMPAT_INCLUDE_DIR,
"-D_FORTIFY_SOURCE=0",
};
#ifdef MACOS_SDK_PATH
flags.push_back("-isysroot" MACOS_SDK_PATH);
Expand Down
70 changes: 49 additions & 21 deletions cpp2rust/converter/converter.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -599,12 +599,12 @@ bool Converter::VisitRecordDecl(clang::RecordDecl *decl) {
}

Mapper::AddRuleForUserDefinedType(decl);
EmitRustStruct(decl);
EmitRustStructOrUnion(decl);

return false;
}

void Converter::EmitRustStruct(clang::RecordDecl *decl) {
void Converter::EmitRustStructOrUnion(clang::RecordDecl *decl) {
// Enums and static variables. In rust they live outside the record
for (auto *d : decl->decls()) {
if (auto *enum_decl = llvm::dyn_cast<clang::EnumDecl>(d)) {
Expand All @@ -630,6 +630,9 @@ void Converter::EmitRustStruct(clang::RecordDecl *decl) {
}

// Derived traits
if (EmitsReprCForRecords()) {
StrCat("#[repr(C)]");
}
StrCat("#[derive(");
for (auto *attr : GetStructAttributes(decl)) {
StrCat(attr, ",");
Expand All @@ -640,7 +643,8 @@ void Converter::EmitRustStruct(clang::RecordDecl *decl) {
auto access = clang::dyn_cast<clang::CXXRecordDecl>(decl)
? AccessSpecifierAsString(decl->getAccess())
: keyword::kPub;
StrCat(access, keyword::kStruct, GetRecordName(decl));
StrCat(access, decl->isUnion() ? keyword::kUnion : keyword::kStruct,
GetRecordName(decl));
{
PushBrace brace(*this);
for (auto *field : decl->fields()) {
Expand Down Expand Up @@ -681,8 +685,8 @@ void Converter::EmitRustStruct(clang::RecordDecl *decl) {
AddOrdTrait(cxx);
AddCloneTrait(cxx);
AddDropTrait(cxx);
AddDefaultTrait(cxx);
}
AddDefaultTrait(decl);
AddByteReprTrait(decl);
}

Expand Down Expand Up @@ -728,10 +732,10 @@ bool Converter::VisitCXXRecordDecl(clang::CXXRecordDecl *decl) {
}
}

EmitRustStruct(decl);
EmitRustStructOrUnion(decl);
} else {
// FIXME: improve error handling
assert(0 && "unsupported union");
assert(0 && "unsupported record kind");
}

return false;
Expand Down Expand Up @@ -2883,6 +2887,10 @@ std::string Converter::GetRecordName(const clang::NamedDecl *decl) const {

std::vector<const char *>
Converter::GetStructAttributes(const clang::RecordDecl *decl) {
if (decl->isUnion()) {
return {"Copy", "Clone"};
}

std::vector<const char *> struct_attrs = {};

if (recordDerivesCopy(decl)) {
Expand Down Expand Up @@ -3202,7 +3210,21 @@ void Converter::AddCloneTrait(const clang::CXXRecordDecl *decl) {}

void Converter::AddDropTrait(const clang::CXXRecordDecl *decl) {}

void Converter::AddDefaultTrait(const clang::CXXRecordDecl *decl) {
void Converter::AddDefaultTraitForUnion(const clang::RecordDecl *decl) {
StrCat(std::format("impl Default for {}", GetRecordName(decl)));
PushBrace impl_brace(*this);
StrCat("fn default() -> Self");
PushBrace fn_brace(*this);
StrCat("unsafe");
PushBrace unsafe_brace(*this);
StrCat("std::mem::zeroed()");
}

void Converter::AddDefaultTrait(const clang::RecordDecl *decl) {
if (decl->isUnion()) {
AddDefaultTraitForUnion(decl);
return;
}
if (RecordDerivesDefault(decl)) {
return;
}
Expand All @@ -3211,20 +3233,26 @@ void Converter::AddDefaultTrait(const clang::CXXRecordDecl *decl) {
PushBrace impl_brace(*this);
StrCat("fn default() -> Self");
PushBrace fn_brace(*this);
if (auto *default_ctor = GetUserDefinedDefaultConstructor(decl)) {
StrCat(keyword_unsafe_);
PushBrace unsafe_brace(*this);
Convert(clang::CXXConstructExpr::Create(
ctx_, ctx_.getCanonicalTagType(decl), clang::SourceLocation(),
default_ctor,
/*Elidable=*/false, llvm::ArrayRef<clang::Expr *>(),
/*HadMultipleCandidates=*/false,
/*ListInitialization=*/false,
/*StdInitListInitialization=*/false,
/*ZeroInitialization=*/false, clang::CXXConstructionKind::Complete,
clang::SourceRange()));
} else {
StrCat(struct_name);

if (auto *cxx = clang::dyn_cast<clang::CXXRecordDecl>(decl)) {
if (auto *default_ctor = GetUserDefinedDefaultConstructor(cxx)) {
StrCat(keyword_unsafe_);
PushBrace unsafe_brace(*this);
Convert(clang::CXXConstructExpr::Create(
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

won't this leak memory?

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It's created inside the allocator of ASTContext, the node is automatically freed when ASTContext is destroyed

ctx_, ctx_.getCanonicalTagType(decl), clang::SourceLocation(),
default_ctor,
/*Elidable=*/false, llvm::ArrayRef<clang::Expr *>(),
/*HadMultipleCandidates=*/false,
/*ListInitialization=*/false,
/*StdInitListInitialization=*/false,
/*ZeroInitialization=*/false, clang::CXXConstructionKind::Complete,
clang::SourceRange()));
return;
}
}

StrCat(struct_name);
{
PushBrace struct_brace(*this);
for (auto *field : decl->fields()) {
StrCat(GetNamedDeclAsString(field), token::kColon,
Expand Down
8 changes: 6 additions & 2 deletions cpp2rust/converter/converter.h
Original file line number Diff line number Diff line change
Expand Up @@ -99,7 +99,9 @@ class Converter : public clang::RecursiveASTVisitor<Converter> {

virtual bool VisitCXXRecordDecl(clang::CXXRecordDecl *decl);

void EmitRustStruct(clang::RecordDecl *decl);
virtual void EmitRustStructOrUnion(clang::RecordDecl *decl);

virtual bool EmitsReprCForRecords() const { return true; }

virtual bool VisitCXXMethodDecl(clang::CXXMethodDecl *decl);
virtual std::string GetSelfMaybeWithMut(const clang::CXXMethodDecl *decl);
Expand Down Expand Up @@ -441,7 +443,9 @@ class Converter : public clang::RecursiveASTVisitor<Converter> {

virtual void AddDropTrait(const clang::CXXRecordDecl *decl);

virtual void AddDefaultTrait(const clang::CXXRecordDecl *decl);
virtual void AddDefaultTrait(const clang::RecordDecl *decl);

virtual void AddDefaultTraitForUnion(const clang::RecordDecl *decl);

virtual void AddByteReprTrait(const clang::RecordDecl *decl);

Expand Down
1 change: 1 addition & 0 deletions cpp2rust/converter/lex.h
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,7 @@ inline constexpr const char *kReturn = "return";
inline constexpr const char *kSelfValue = "self";
inline constexpr const char *kStatic = "static";
inline constexpr const char *kStruct = "struct";
inline constexpr const char *kUnion = "union";
inline constexpr const char *kTrue = "true";
inline constexpr const char *kWhile = "while";
inline constexpr const char *kFor = "for";
Expand Down
5 changes: 4 additions & 1 deletion cpp2rust/converter/models/converter_refcount.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -460,11 +460,14 @@ void ConverterRefCount::AddCloneTrait(const clang::CXXRecordDecl *decl) {
StrCat("}");
}

void ConverterRefCount::AddDefaultTrait(const clang::CXXRecordDecl *decl) {
void ConverterRefCount::AddDefaultTrait(const clang::RecordDecl *decl) {
PushConversionKind push(*this, ConversionKind::FullRefCount);
Converter::AddDefaultTrait(decl);
}

void ConverterRefCount::AddDefaultTraitForUnion(const clang::RecordDecl *decl) {
}

void ConverterRefCount::AddDropTrait(const clang::CXXRecordDecl *decl) {
if (!decl->hasUserDeclaredDestructor()) {
return;
Expand Down
6 changes: 5 additions & 1 deletion cpp2rust/converter/models/converter_refcount.h
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,8 @@ class ConverterRefCount final : public Converter {

bool VisitCXXRecordDecl(clang::CXXRecordDecl *decl) override;

bool EmitsReprCForRecords() const override { return false; }

void ConvertOrdAndPartialOrdTraits(const clang::CXXRecordDecl *decl,
const clang::FunctionDecl *op) override;

Expand All @@ -37,7 +39,9 @@ class ConverterRefCount final : public Converter {

void AddByteReprTrait(const clang::RecordDecl *decl) override;

void AddDefaultTrait(const clang::CXXRecordDecl *decl) override;
void AddDefaultTrait(const clang::RecordDecl *decl) override;

void AddDefaultTraitForUnion(const clang::RecordDecl *decl) override;

std::string GetSelfMaybeWithMut(const clang::CXXMethodDecl *decl) override;

Expand Down
3 changes: 3 additions & 0 deletions tests/benchmarks/out/unsafe/bfs.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ use std::collections::BTreeMap;
use std::io::{Read, Seek, Write};
use std::os::fd::{AsFd, FromRawFd, IntoRawFd};
use std::rc::Rc;
#[repr(C)]
#[derive(Copy, Clone, Default)]
pub struct Queue {
pub elems: *mut u32,
Expand Down Expand Up @@ -35,11 +36,13 @@ impl Queue {
return ((self.back) == (0_u64));
}
}
#[repr(C)]
#[derive(Copy, Clone, Default)]
pub struct GraphNode {
pub vertex: u32,
pub next: *mut GraphNode,
}
#[repr(C)]
#[derive(Copy, Clone, Default)]
pub struct Graph {
pub V: u32,
Expand Down
1 change: 1 addition & 0 deletions tests/benchmarks/out/unsafe/bst.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ use std::collections::BTreeMap;
use std::io::{Read, Seek, Write};
use std::os::fd::{AsFd, FromRawFd, IntoRawFd};
use std::rc::Rc;
#[repr(C)]
#[derive(Copy, Clone, Default)]
pub struct node_t {
pub left: *mut node_t,
Expand Down
1 change: 1 addition & 0 deletions tests/ub/out/unsafe/ub6.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ use std::collections::BTreeMap;
use std::io::{Read, Seek, Write};
use std::os::fd::{AsFd, FromRawFd, IntoRawFd};
use std::rc::Rc;
#[repr(C)]
#[derive(Copy, Clone, Default)]
pub struct Pair {
pub x1: *mut i32,
Expand Down
118 changes: 118 additions & 0 deletions tests/unit/out/refcount/union_addrof_external.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,118 @@
extern crate libcc2rs;
use libcc2rs::*;
use std::cell::RefCell;
use std::collections::BTreeMap;
use std::io::prelude::*;
use std::io::{Read, Seek, Write};
use std::os::fd::AsFd;
use std::rc::{Rc, Weak};
#[repr(C)]
#[derive()]
pub struct record {
pub code: Value<u16>,
pub lo: Value<u16>,
pub hi: Value<u32>,
pub pad: Value<Box<[u8]>>,
}
impl ByteRepr for record {}
#[repr(C)]
#[derive(Copy, Clone)]
pub union Container_anon_15_3 {
pub h: Value<record>,
pub raw_: Value<Box<[u8]>>,
}
impl Default for Container_anon_15_3 {
fn default() -> Self {
unsafe { std::mem::zeroed() }
}
}
#[repr(C)]
#[derive(Default)]
pub struct Container {
pub view: Value<Container_anon_15_3>,
}
impl ByteRepr for Container {}
pub fn fill_0(out: AnyPtr, cap: u64) {
let out: Value<AnyPtr> = Rc::new(RefCell::new(out));
let cap: Value<u64> = Rc::new(RefCell::new(cap));
let src: Value<Box<[u8]>> = Rc::new(RefCell::new(Box::new([
0_u8,
<u8>::default(),
<u8>::default(),
<u8>::default(),
<u8>::default(),
<u8>::default(),
<u8>::default(),
<u8>::default(),
<u8>::default(),
<u8>::default(),
<u8>::default(),
<u8>::default(),
<u8>::default(),
<u8>::default(),
<u8>::default(),
<u8>::default(),
])));
(*src.borrow_mut())[(0) as usize] = 2_u8;
(*src.borrow_mut())[(1) as usize] = 0_u8;
(*src.borrow_mut())[(2) as usize] = 0_u8;
(*src.borrow_mut())[(3) as usize] = 80_u8;
(*src.borrow_mut())[(4) as usize] = 127_u8;
(*src.borrow_mut())[(5) as usize] = 0_u8;
(*src.borrow_mut())[(6) as usize] = 0_u8;
(*src.borrow_mut())[(7) as usize] = 1_u8;
let n: Value<u64> = Rc::new(RefCell::new(
if ((::std::mem::size_of::<[u8; 16]>() as u64) < (*cap.borrow())) {
::std::mem::size_of::<[u8; 16]>() as u64
} else {
(*cap.borrow())
},
));
{
(*out.borrow()).memcpy(
&((src.as_pointer() as Ptr<u8>) as Ptr<u8>).to_any(),
(*n.borrow()) as usize,
);
(*out.borrow()).clone()
};
}
pub fn main() {
std::process::exit(main_0());
}
fn main_0() -> i32 {
let c: Value<Container> = <Value<Container>>::default();
{
((c.as_pointer()) as Ptr<Container>).to_any().memset(
(0) as u8,
::std::mem::size_of::<Container>() as u64 as usize,
);
((c.as_pointer()) as Ptr<Container>).to_any().clone()
};
({
let _out: AnyPtr = (((*c.borrow()).view.as_pointer()).to_strong().as_pointer() as AnyPtr);
let _cap: u64 = ::std::mem::size_of::<Container_anon_15_3>() as u64;
fill_0(_out, _cap)
});
assert!((((*(*(*(*c.borrow()).view.borrow()).h.borrow()).code.borrow()) as i32) == (2)));
assert!(
((((((*(*(*c.borrow()).view.borrow()).h.borrow()).lo.as_pointer())
.to_strong()
.as_pointer() as Ptr::<u8>)
.offset((0) as isize)
.read()) as i32)
== (0))
);
assert!(
((((((*(*(*c.borrow()).view.borrow()).h.borrow()).lo.as_pointer())
.to_strong()
.as_pointer() as Ptr::<u8>)
.offset((1) as isize)
.read()) as i32)
== (80))
);
assert!((((*(*(*c.borrow()).view.borrow()).raw_.borrow())[(0) as usize] as i32) == (2)));
assert!(
((((*(*(*c.borrow()).view.borrow()).raw_.borrow())[(3) as usize] as u8) as i32) == (80))
);
return 0;
}
25 changes: 0 additions & 25 deletions tests/unit/out/refcount/union_basic.rs

This file was deleted.

Loading
Loading