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
48 changes: 48 additions & 0 deletions cpp2rust/converter/converter.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@

#include <clang/AST/APValue.h>
#include <clang/AST/ParentMapContext.h>
#include <clang/Basic/LangOptions.h>
#include <clang/Basic/SourceManager.h>
#include <llvm/ADT/DenseMap.h>
#include <llvm/Support/ConvertUTF.h>
Expand Down Expand Up @@ -3421,8 +3422,42 @@ void Converter::ConvertPointerOffset(clang::Expr *base, clang::Expr *idx,
computed_expr_type_ = ComputedExprType::FreshPointer;
}

static bool IsFlexibleArrayMemberAccess(clang::ASTContext &ctx,
clang::Expr *array) {
return array->isFlexibleArrayMemberLike(
ctx, clang::LangOptions::StrictFlexArraysLevelKind::OneZeroOrIncomplete,
/*IgnoreTemplateOrMacroSubstitution=*/true);
}

void Converter::EmitFlexibleArrayElementPtr(clang::Expr *array,
clang::Expr *idx, bool is_mut) {
{
PushExplicitAutoref no_autoref(*this, std::nullopt);
Convert(array);
}
StrCat(is_mut ? ".as_mut_ptr()" : ".as_ptr()", ".add");
{
PushParen call(*this);
{
PushParen paren(*this);
Convert(idx);
}
StrCat(keyword::kAs, "usize");
}
}

void Converter::ConvertArraySubscript(clang::Expr *base, clang::Expr *idx,
clang::QualType type) {
if (auto inner = base->IgnoreImplicit()) {
if (inner->getType()->isArrayType() &&
IsFlexibleArrayMemberAccess(ctx_, inner)) {
PushParen outer(*this);
StrCat(token::kStar);
EmitFlexibleArrayElementPtr(inner, idx,
!inner->getType().isConstQualified());
return;
}
}
if (IsUniquePtr(base->getType())) {
PushExplicitAutoref no_autoref(*this, std::nullopt);
Convert(base->IgnoreImplicit());
Expand Down Expand Up @@ -3725,6 +3760,19 @@ void Converter::ConvertUnsignedArithBinaryOperator(clang::BinaryOperator *op,

void Converter::ConvertAddrOf(clang::Expr *expr, clang::QualType pointer_type) {
assert(pointer_type->isPointerType());
if (auto ase =
clang::dyn_cast<clang::ArraySubscriptExpr>(expr->IgnoreParens())) {
auto base = ase->getBase();
auto inner = base->IgnoreImplicit();
if (base->IgnoreCasts()->getType()->isArrayType() &&
IsFlexibleArrayMemberAccess(ctx_, inner)) {
EmitFlexibleArrayElementPtr(
inner, ase->getIdx(),
!pointer_type->getPointeeType().isConstQualified());
computed_expr_type_ = ComputedExprType::FreshPointer;
return;
}
}
if (IsReferenceType(expr) || pointer_type->isFunctionPointerType()) {
PushExprKind push(*this, ExprKind::AddrOf);
Convert(expr);
Expand Down
3 changes: 3 additions & 0 deletions cpp2rust/converter/converter.h
Original file line number Diff line number Diff line change
Expand Up @@ -443,6 +443,9 @@ class Converter : public clang::RecursiveASTVisitor<Converter> {
virtual void ConvertArraySubscript(clang::Expr *base, clang::Expr *idx,
clang::QualType type);

void EmitFlexibleArrayElementPtr(clang::Expr *array, clang::Expr *idx,
bool is_mut);

virtual void ConvertAssignment(clang::Expr *lhs, clang::Expr *rhs,
std::string_view assign_operator);

Expand Down
4 changes: 2 additions & 2 deletions tests/unit/out/unsafe/union_field_alignment.rs
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@ pub fn main() {
unsafe fn main_0() -> i32 {
let mut n: node = <node>::default();
n.next = std::ptr::null_mut();
n.x.bytes[(0) as usize] = 171_u8;
assert!(((((n.x.bytes[(0) as usize] as i32) == (171)) as i32) != 0));
(*n.x.bytes.as_mut_ptr().add((0) as usize)) = 171_u8;
assert!((((((*n.x.bytes.as_mut_ptr().add((0) as usize)) as i32) == (171)) as i32) != 0));
return 0;
}
63 changes: 63 additions & 0 deletions tests/unit/out/unsafe/union_flex_array_member.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,63 @@
extern crate libc;
use libc::*;
extern crate libcc2rs;
use libcc2rs::*;
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)]
pub union anon_0 {
pub bytes: [u8; 1],
pub aligner: *mut ::libc::c_void,
}
impl Default for anon_0 {
fn default() -> Self {
unsafe { std::mem::zeroed() }
}
}
#[repr(C)]
#[derive(Copy, Clone, Default)]
pub struct node {
pub len: u64,
pub pos: u64,
pub x: anon_0,
}
pub fn main() {
unsafe {
std::process::exit(main_0() as i32);
}
}
unsafe fn main_0() -> i32 {
let mut tail_size: u64 = 32_u64;
let mut n: *mut node = (libcc2rs::malloc_unsafe(
(::std::mem::size_of::<node>() as u64 as u64).wrapping_add(tail_size),
) as *mut node);
(*n).len = tail_size;
let mut i: u64 = 0_u64;
'loop_: while ((((i) < (tail_size)) as i32) != 0) {
(*(*n).x.bytes.as_mut_ptr().add((i) as usize)) = (((i) & (255_u64)) as u8);
i.postfix_inc();
}
let mut i: u64 = 0_u64;
'loop_: while ((((i) < (tail_size)) as i32) != 0) {
assert!(
(((((*(*n).x.bytes.as_mut_ptr().add((i) as usize)) as i32)
== ((((i) & (255_u64)) as u8) as i32)) as i32)
!= 0)
);
i.postfix_inc();
}
let mut p: *mut u8 = ((*n).x.bytes.as_mut_ptr().add((10) as usize));
assert!((((((*p) as i32) == (10)) as i32) != 0));
(*p) = 170_u8;
assert!((((((*(*n).x.bytes.as_mut_ptr().add((10) as usize)) as i32) == (170)) as i32) != 0));
(*n).pos = 20_u64;
let mut q: *mut u8 = ((*n).x.bytes.as_mut_ptr().add(((*n).pos) as usize));
assert!((((((*q) as i32) == (20)) as i32) != 0));
(*q) = 187_u8;
assert!((((((*q) as i32) == (187)) as i32) != 0));
libcc2rs::free_unsafe((n as *mut node as *mut ::libc::c_void));
return 0;
}
9 changes: 8 additions & 1 deletion tests/unit/union_flex_array_member.c
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
// no-compile
// no-compile: refcount
#include <assert.h>
#include <stddef.h>
#include <stdint.h>
Expand All @@ -7,6 +7,7 @@

struct node {
size_t len;
size_t pos;
union {
uint8_t bytes[1];
void *aligner;
Expand All @@ -30,6 +31,12 @@ int main(void) {
*p = 0xAA;
assert(n->x.bytes[10] == 0xAA);

n->pos = 20;
uint8_t *q = &n->x.bytes[n->pos];
assert(*q == 20);
*q = 0xBB;
assert(*q == 0xBB);

free(n);
return 0;
}
Loading