Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
29 commits
Select commit Hold shift + click to select a range
5b56999
Codegen for safe union
lucic71 Jun 23, 2026
2427859
Add UnionStore
lucic71 Jun 23, 2026
6da60bd
pod -> reinterpret and UnionStore -> UnionStorage
lucic71 Jun 23, 2026
34627ea
Codegen for union accessors
lucic71 Jun 23, 2026
e85659f
Update tests
lucic71 Jun 23, 2026
5058455
Add ByteRepr for arrays
lucic71 Jun 23, 2026
d0957ad
Access fields of struct arm in union
lucic71 Jun 23, 2026
e4d60b8
Add ByteRepr for arrays
lucic71 Jun 23, 2026
9f40efb
Update tests
lucic71 Jun 23, 2026
b57892a
Add ByteRepr for unions
lucic71 Jun 23, 2026
aa51805
Memcpy a poitner to a struct through ErasedPtr
lucic71 Jun 23, 2026
88e4868
Fix arrays in unions
lucic71 Jun 24, 2026
4cae8e2
Use C size when size_of diverges between C and Rust
lucic71 Jun 24, 2026
7cd4161
Add byte_size in ByteRepr to capture C size
lucic71 Jun 24, 2026
f59af63
Update tests
lucic71 Jun 24, 2026
83a9dcc
Update tests
lucic71 Jun 24, 2026
25cf021
Reinterpret cast on aliasing pointers
lucic71 Jun 24, 2026
74532a7
Update tests
lucic71 Jun 24, 2026
1018203
Create fresh pointer from union member
lucic71 Jun 24, 2026
78a6361
Add reinterpret_cast on addrof array
lucic71 Jun 24, 2026
ebcfc6a
Panic on default byte_size implementation
lucic71 Jun 24, 2026
039b9d0
Add ReinterpretedView::byte_size to encode constant size of arrays
lucic71 Jun 24, 2026
32194b1
Add name of struct that does not implement ByteRepr
lucic71 Jun 24, 2026
f6b7344
Add ByteRepr for enums
lucic71 Jun 24, 2026
abd39cd
Update tests
lucic71 Jun 24, 2026
9a247bd
Use reinterpret_cast to do a -> void * -> b
lucic71 Jun 24, 2026
96ab050
Avoid trips through reinterpret_cast on same type
lucic71 Jun 24, 2026
97841b8
Add ByteRepr for pointers
lucic71 Jun 25, 2026
afd4402
Update tests
lucic71 Jun 25, 2026
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
41 changes: 38 additions & 3 deletions cpp2rust/converter/converter.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -55,12 +55,15 @@ use std::rc::Rc;
)");
}

std::string Converter::EmitOpaqueRecords() {
std::string Converter::EmitOpaqueRecords(bool emit_byte_repr) {
std::string out;
record_decls_.ForEachUndefined([&](const std::string &name) {
out += "pub struct ";
out += name;
out += ";\n";
if (emit_byte_repr) {
out += "impl ByteRepr for " + name + " {}\n";
}
});
return out;
}
Expand Down Expand Up @@ -753,6 +756,11 @@ void Converter::EmitRustStructOrUnion(clang::RecordDecl *decl) {
}
}

if (decl->isUnion()) {
EmitRustUnion(decl);
return;
}

// Derived traits
if (EmitsReprCForRecords()) {
StrCat("#[repr(C)]");
Expand All @@ -770,8 +778,7 @@ void Converter::EmitRustStructOrUnion(clang::RecordDecl *decl) {
auto access = clang::dyn_cast<clang::CXXRecordDecl>(decl)
? AccessSpecifierAsString(decl->getAccess())
: keyword::kPub;
StrCat(access, decl->isUnion() ? keyword::kUnion : keyword::kStruct,
GetRecordName(decl));
StrCat(access, keyword::kStruct, GetRecordName(decl));
{
PushBrace brace(*this);
for (auto *field : decl->fields()) {
Expand Down Expand Up @@ -817,6 +824,31 @@ void Converter::EmitRustStructOrUnion(clang::RecordDecl *decl) {
AddByteReprTrait(decl);
}

void Converter::EmitRustUnion(clang::RecordDecl *decl) {
if (EmitsReprCForRecords()) {
StrCat("#[repr(C)]");
}
auto attrs = GetStructAttributes(decl);
Mapper::SetDerives(ctx_.getCanonicalTagType(decl),
std::vector<std::string>(attrs.begin(), attrs.end()));
StrCat("#[derive(");
for (auto *attr : attrs) {
StrCat(attr, ',');
}
StrCat(")]");

StrCat(keyword::kPub, keyword::kUnion, GetRecordName(decl));
{
PushBrace brace(*this);
for (auto *field : decl->fields()) {
VisitFieldDecl(field);
}
}

AddDefaultTrait(decl);
AddByteReprTrait(decl);
}

bool Converter::VisitCXXRecordDecl(clang::CXXRecordDecl *decl) {
if (clang::isa<clang::ClassTemplateSpecializationDecl>(decl)) {
materializeTemplateSpecialization(decl);
Expand Down Expand Up @@ -3136,6 +3168,7 @@ bool Converter::VisitEnumDecl(clang::EnumDecl *decl) {

AddFromImpl(decl);
AddIncDecImpls(decl);
AddByteReprTrait(decl);
return false;
}

Expand Down Expand Up @@ -3918,6 +3951,8 @@ void Converter::EmitDefaultStructLiteral(const clang::RecordDecl *decl) {

void Converter::AddByteReprTrait(const clang::RecordDecl *decl) {}

void Converter::AddByteReprTrait(const clang::EnumDecl *decl) {}

void Converter::ConvertUnsignedArithBinaryOperator(clang::BinaryOperator *op,
clang::Expr *expr) {
StrCat(token::kDot);
Expand Down
6 changes: 5 additions & 1 deletion cpp2rust/converter/converter.h
Original file line number Diff line number Diff line change
Expand Up @@ -50,7 +50,7 @@ class Converter : public clang::RecursiveASTVisitor<Converter> {

virtual void EmitFilePreamble();

static std::string EmitOpaqueRecords();
static std::string EmitOpaqueRecords(bool emit_byte_repr);

virtual bool VisitBuiltinType(clang::BuiltinType *type);

Expand Down Expand Up @@ -112,6 +112,8 @@ class Converter : public clang::RecursiveASTVisitor<Converter> {

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

virtual void EmitRustUnion(clang::RecordDecl *decl);

virtual bool EmitsReprCForRecords() const { return true; }

virtual bool VisitCXXMethodDecl(clang::CXXMethodDecl *decl);
Expand Down Expand Up @@ -539,6 +541,8 @@ class Converter : public clang::RecursiveASTVisitor<Converter> {

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

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

virtual void
ConvertUnsignedArithBinaryOperator(clang::BinaryOperator *binary_operator,
clang::Expr *expr);
Expand Down
36 changes: 36 additions & 0 deletions cpp2rust/converter/converter_lib.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -199,6 +199,42 @@ bool IsMut(clang::QualType qual_type) {
qual_type->getPointeeType().isConstQualified());
}

bool TypeImplementsByteRepr(clang::QualType qt) {
if (qt->isIntegerType() || qt->isFloatingType()) {
return true;
}
if (qt->isPointerType()) {
return true;
}
if (const auto *arr = qt->getAsArrayTypeUnsafe()) {
return TypeImplementsByteRepr(arr->getElementType());
}
if (const auto *rd = qt->getAsRecordDecl()) {
if (rd->isUnion()) {
return true;
}
for (const auto *field : rd->fields()) {
if (!TypeImplementsByteRepr(field->getType())) {
return false;
}
}
return true;
}
return false;
}

bool RustSizeDivergesFromC(clang::QualType qt) {
qt = qt.getCanonicalType();
// Records have Rc<RefCell<>> fields that diverge from the C size
if (qt->isRecordType()) {
return true;
}
if (auto *arr = qt->getAsArrayTypeUnsafe()) {
return RustSizeDivergesFromC(arr->getElementType());
}
return false;
}

bool IsMutatingCall(const clang::CallExpr *expr) {
if (auto *callee = expr->getDirectCallee()) {
if (auto *method = clang::dyn_cast<clang::CXXMethodDecl>(callee)) {
Expand Down
4 changes: 4 additions & 0 deletions cpp2rust/converter/converter_lib.h
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,10 @@ bool IsUnsignedArithOp(const clang::BinaryOperator *expr);

bool IsMut(clang::QualType qual_type);

bool TypeImplementsByteRepr(clang::QualType qt);

bool RustSizeDivergesFromC(clang::QualType qt);

bool IsMutatingCall(const clang::CallExpr *expr);

bool IsOverloadedFunction(const clang::FunctionDecl *decl);
Expand Down
Loading