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
3 changes: 1 addition & 2 deletions cpp2rust/converter/converter.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2084,8 +2084,7 @@ bool Converter::VisitImplicitCastExpr(clang::ImplicitCastExpr *expr) {
bool dest_pointee_const =
expr->getType()->getPointeeType().isConstQualified();
Convert(sub_expr);
if (clang::isa<clang::StringLiteral>(sub_expr) ||
clang::isa<clang::PredefinedExpr>(sub_expr)) {
if (IsStringLiteralExpr(sub_expr)) {
StrCat(".as_ptr()");
if (!dest_pointee_const) {
StrCat(".cast_mut()");
Expand Down
6 changes: 6 additions & 0 deletions cpp2rust/converter/converter_lib.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -140,6 +140,12 @@ bool IsUnionArrayMember(const clang::Expr *base) {
return false;
}

bool IsStringLiteralExpr(const clang::Expr *expr) {
const auto *stripped = expr->IgnoreParens()->IgnoreImplicit();
return clang::isa<clang::StringLiteral>(stripped) ||
clang::isa<clang::PredefinedExpr>(stripped);
}

bool IsUserDefinedDecl(const clang::Decl *decl) {
const auto &ctx = decl->getASTContext();
const auto &src_mgr = ctx.getSourceManager();
Expand Down
2 changes: 2 additions & 0 deletions cpp2rust/converter/converter_lib.h
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,8 @@ bool IsInMainFile(const clang::Decl *decl);

bool IsUnionArrayMember(const clang::Expr *base);

bool IsStringLiteralExpr(const clang::Expr *expr);

bool IsUserDefinedDecl(const clang::Decl *decl);

bool RefersToUserDefinedDecl(const clang::Expr *expr);
Expand Down
22 changes: 15 additions & 7 deletions cpp2rust/converter/models/converter_refcount.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1170,6 +1170,8 @@ bool ConverterRefCount::VisitImplicitCastExpr(clang::ImplicitCastExpr *expr) {
->getPointeeType()
->getAsArrayTypeUnsafe()
->getElementType())));
} else if (IsStringLiteralExpr(sub_expr)) {
StrCat(std::format("{}.to_any()", ConvertFreshPointer(sub_expr)));
} else {
StrCat(std::format("({} as {}).to_any()", ConvertFreshPointer(sub_expr),
ToString(sub_expr->getType())));
Expand Down Expand Up @@ -1209,9 +1211,9 @@ bool ConverterRefCount::VisitImplicitCastExpr(clang::ImplicitCastExpr *expr) {
Convert(sub_expr);
return false;
}
if (clang::isa<clang::StringLiteral>(sub_expr) ||
clang::isa<clang::PredefinedExpr>(sub_expr)) {
StrCat(std::format("Ptr::from_string_literal({})", ToString(sub_expr)));
if (IsStringLiteralExpr(sub_expr)) {
StrCat(std::format("Ptr::from_string_literal({})",
ToString(sub_expr->IgnoreParens())));
return false;
} else {
// we need to write (var.as_pointer as Ptr<T>) because Rust isn't
Expand Down Expand Up @@ -2222,10 +2224,16 @@ void ConverterRefCount::ConvertArraySubscript(clang::Expr *base,

{
PushParen paren(*this, is_inner_boxed);
StrCat(std::format("({} as {}).offset({})",
ToString(base->IgnoreImplicit()),
ConvertPtrType(base->IgnoreImplicit()->getType()),
ConvertRValue(idx)));
if (IsStringLiteralExpr(base)) {
StrCat(std::format("Ptr::from_string_literal({}).offset({})",
ToString(base->IgnoreParens()->IgnoreImplicit()),
ConvertRValue(idx)));
} else {
StrCat(std::format("({} as {}).offset({})",
ToString(base->IgnoreImplicit()),
ConvertPtrType(base->IgnoreImplicit()->getType()),
ConvertRValue(idx)));
}

if (is_inner_boxed) {
StrCat(GetPointerDerefSuffix(type), ".as_pointer()");
Expand Down
173 changes: 173 additions & 0 deletions tests/unit/out/refcount/string_literal_ptr_init.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,173 @@
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};
#[derive()]
pub struct label {
pub name: Value<Ptr<u8>>,
pub probe: Value<FnPtr<fn() -> i32>>,
pub mask: Value<i32>,
}
impl Clone for label {
fn clone(&self) -> Self {
Self {
name: Rc::new(RefCell::new((*self.name.borrow()).clone())),
probe: Rc::new(RefCell::new((*self.probe.borrow()).clone())),
mask: Rc::new(RefCell::new((*self.mask.borrow()).clone())),
}
}
}
impl Default for label {
fn default() -> Self {
label {
name: Rc::new(RefCell::new(Ptr::<u8>::null())),
probe: Rc::new(RefCell::new(FnPtr::null())),
mask: <Value<i32>>::default(),
}
}
}
impl ByteRepr for label {
fn byte_size() -> usize {
24
}
fn to_bytes(&self, buf: &mut [u8]) {
(*self.name.borrow()).to_bytes(&mut buf[0..8]);
(*self.probe.borrow()).to_bytes(&mut buf[8..16]);
(*self.mask.borrow()).to_bytes(&mut buf[16..20]);
}
fn from_bytes(buf: &[u8]) -> Self {
Self {
name: Rc::new(RefCell::new(<Ptr<u8>>::from_bytes(&buf[0..8]))),
probe: Rc::new(RefCell::new(<FnPtr<fn() -> i32>>::from_bytes(&buf[8..16]))),
mask: Rc::new(RefCell::new(<i32>::from_bytes(&buf[16..20]))),
}
}
}
pub fn probe_two_0() -> i32 {
return 1;
}
thread_local!(
pub static table_1: Value<Box<[label]>> = Rc::new(RefCell::new(Box::new([
label {
name: Rc::new(RefCell::new(Ptr::from_string_literal(b"first"))),
probe: Rc::new(RefCell::new(FnPtr::null())),
mask: Rc::new(RefCell::new((1 << 4))),
},
label {
name: Rc::new(RefCell::new(Ptr::from_string_literal(b"second"))),
probe: Rc::new(RefCell::new((FnPtr::<fn() -> i32>::new(probe_two_0)))),
mask: Rc::new(RefCell::new((1 << 5))),
},
])));
);
pub fn main() {
std::process::exit(main_0());
}
fn main_0() -> i32 {
assert!(
((((((*(*table_1.with(Value::clone).borrow())[(0) as usize]
.name
.borrow())
.offset((0) as isize)
.read()) as i32)
== ('f' as i32)) as i32)
!= 0)
);
assert!(
((((((*(*table_1.with(Value::clone).borrow())[(0) as usize]
.name
.borrow())
.offset((4) as isize)
.read()) as i32)
== ('t' as i32)) as i32)
!= 0)
);
assert!(
((((*(*table_1.with(Value::clone).borrow())[(0) as usize]
.probe
.borrow())
.is_null()) as i32)
!= 0)
);
assert!(
((((*(*table_1.with(Value::clone).borrow())[(0) as usize]
.mask
.borrow())
== 16) as i32)
!= 0)
);
assert!(
((((((*(*table_1.with(Value::clone).borrow())[(1) as usize]
.name
.borrow())
.offset((0) as isize)
.read()) as i32)
== ('s' as i32)) as i32)
!= 0)
);
assert!(
(((({
(*(*(*table_1.with(Value::clone).borrow())[(1) as usize]
.probe
.borrow()))()
}) == 1) as i32)
!= 0)
);
assert!(
((((*(*table_1.with(Value::clone).borrow())[(1) as usize]
.mask
.borrow())
== 32) as i32)
!= 0)
);
let tail: Value<Ptr<u8>> =
Rc::new(RefCell::new((Ptr::from_string_literal(b"ab.cd").offset(2))));
assert!(
((((((*tail.borrow()).offset((0) as isize).read()) as i32) == ('.' as i32)) as i32) != 0)
);
assert!(
((((((*tail.borrow()).offset((1) as isize).read()) as i32) == ('c' as i32)) as i32) != 0)
);
assert!(
((((((*tail.borrow()).offset((2) as isize).read()) as i32) == ('d' as i32)) as i32) != 0)
);
let have: Value<i32> = Rc::new(RefCell::new(0));
let p: Value<AnyPtr> = Rc::new(RefCell::new(if ((*have.borrow()) != 0) {
(*(*table_1.with(Value::clone).borrow())[(0) as usize]
.name
.borrow())
.clone()
.to_any()
} else {
Ptr::from_string_literal(b"").to_any()
}));
assert!(
(((((((*p.borrow()).reinterpret_cast::<u8>())
.offset((0) as isize)
.read()) as i32)
== ('\0' as i32)) as i32)
!= 0)
);
(*have.borrow_mut()) = 1;
(*p.borrow_mut()) = if ((*have.borrow()) != 0) {
(*(*table_1.with(Value::clone).borrow())[(0) as usize]
.name
.borrow())
.clone()
.to_any()
} else {
Ptr::from_string_literal(b"").to_any()
};
assert!(
(((((((*p.borrow()).reinterpret_cast::<u8>())
.offset((0) as isize)
.read()) as i32)
== ('f' as i32)) as i32)
!= 0)
);
return 0;
}
91 changes: 91 additions & 0 deletions tests/unit/out/unsafe/string_literal_ptr_init.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,91 @@
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 struct label {
pub name: *const libc::c_char,
pub probe: Option<unsafe fn() -> i32>,
pub mask: i32,
}
impl Default for label {
fn default() -> Self {
label {
name: std::ptr::null(),
probe: None,
mask: 0_i32,
}
}
}
pub unsafe fn probe_two_0() -> i32 {
return 1;
}
pub static mut table_1: [label; 2] = unsafe {
[
label {
name: ((c"first").as_ptr().cast_mut()).cast_const(),
probe: None,
mask: ((1) << (4)),
},
label {
name: ((c"second").as_ptr().cast_mut()).cast_const(),
probe: (Some(probe_two_0)),
mask: ((1) << (5)),
},
]
};
pub fn main() {
unsafe {
std::process::exit(main_0() as i32);
}
}
unsafe fn main_0() -> i32 {
assert!(
(((((*table_1[(0) as usize].name.offset((0) as isize)) as i32) == ('f' as i32)) as i32)
!= 0)
);
assert!(
(((((*table_1[(0) as usize].name.offset((4) as isize)) as i32) == ('t' as i32)) as i32)
!= 0)
);
assert!(((((table_1[(0) as usize].probe).is_none()) as i32) != 0));
assert!(((((table_1[(0) as usize].mask) == (16)) as i32) != 0));
assert!(
(((((*table_1[(1) as usize].name.offset((0) as isize)) as i32) == ('s' as i32)) as i32)
!= 0)
);
assert!(((((unsafe { (table_1[(1) as usize].probe).unwrap()() }) == (1)) as i32) != 0));
assert!(((((table_1[(1) as usize].mask) == (32)) as i32) != 0));
let mut tail: *const libc::c_char = (&mut (*c"ab.cd".as_ptr().cast_mut().offset((2) as isize))
as *mut libc::c_char)
.cast_const();
assert!((((((*tail.offset((0) as isize)) as i32) == ('.' as i32)) as i32) != 0));
assert!((((((*tail.offset((1) as isize)) as i32) == ('c' as i32)) as i32) != 0));
assert!((((((*tail.offset((2) as isize)) as i32) == ('d' as i32)) as i32) != 0));
let mut have: i32 = 0;
let mut p: *mut ::libc::c_void = if (have != 0) {
(table_1[(0) as usize].name as *mut ::libc::c_void)
} else {
(c"".as_ptr().cast_mut() as *mut libc::c_char as *mut ::libc::c_void)
};
assert!(
(((((*(p as *const libc::c_char).offset((0) as isize)) as i32) == ('\0' as i32)) as i32)
!= 0)
);
have = 1;
p = if (have != 0) {
(table_1[(0) as usize].name as *mut ::libc::c_void)
} else {
(c"".as_ptr().cast_mut() as *mut libc::c_char as *mut ::libc::c_void)
};
assert!(
(((((*(p as *const libc::c_char).offset((0) as isize)) as i32) == ('f' as i32)) as i32)
!= 0)
);
return 0;
}
41 changes: 41 additions & 0 deletions tests/unit/string_literal_ptr_init.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
#include <assert.h>

#define END_MARK "ab.cd"

struct label {
const char *name;
int (*probe)(void);
int mask;
};

static int probe_two(void) { return 1; }

#define ENTRY(name, probe, mask) {(name), (probe), (mask)}

static const struct label table[] = {
ENTRY("first", 0, 1 << 4),
ENTRY("second", probe_two, 1 << 5),
};

int main() {
assert(table[0].name[0] == 'f');
assert(table[0].name[4] == 't');
assert(table[0].probe == 0);
assert(table[0].mask == 16);
assert(table[1].name[0] == 's');
assert(table[1].probe() == 1);
assert(table[1].mask == 32);

const char *tail = &END_MARK[2];
assert(tail[0] == '.');
assert(tail[1] == 'c');
assert(tail[2] == 'd');

int have = 0;
void *p = have ? (void *)table[0].name : "";
assert(((const char *)p)[0] == '\0');
have = 1;
p = have ? (void *)table[0].name : "";
assert(((const char *)p)[0] == 'f');
return 0;
}
Loading