diff --git a/cpp2rust/converter/converter.cpp b/cpp2rust/converter/converter.cpp index 055db2e8ff..e54ef2a1a9 100644 --- a/cpp2rust/converter/converter.cpp +++ b/cpp2rust/converter/converter.cpp @@ -225,7 +225,12 @@ std::string Converter::ConvertFreshObject(clang::Expr *expr) { std::string Converter::ConvertPointerReceiver(clang::Expr *arg, std::string_view param_type) { - return std::format("({} as {})", ConvertFreshObject(arg), param_type); + auto *unwrapped = clang::IgnoreExprNodes( + arg, clang::IgnoreParensSingleStep, clang::IgnoreImplicitCastsSingleStep); + auto receiver = clang::isa(unwrapped) + ? ConvertTemporaryPointer(arg, std::nullopt) + : ConvertFreshObject(arg); + return std::format("({} as {})", receiver, param_type); } std::string Converter::ConvertTemporaryPointer( diff --git a/rules/string/tgt_refcount.rs b/rules/string/tgt_refcount.rs index 006d3c3219..f5bc952599 100644 --- a/rules/string/tgt_refcount.rs +++ b/rules/string/tgt_refcount.rs @@ -25,11 +25,16 @@ fn t7() -> i8 { 0_i8 } -fn f1(a0: Vec, a1: usize, a2: usize) -> Vec { - let mut __tmp1 = - a0[(a1) as usize..::std::cmp::min((a1 + a2) as usize, a0.len().saturating_sub(1))].to_vec(); - __tmp1.push(0); - __tmp1 +// Keep temporary receivers alive, but borrow only after evaluating the arguments. +fn f1(a0: Ptr>, a1: usize, a2: usize) -> Vec { + match (a0, a1, a2) { + (__source, __pos, __count) => __source.with(|__s: &Vec| { + let mut __tmp1 = + __s[__pos..::std::cmp::min(__pos + __count, __s.len().saturating_sub(1))].to_vec(); + __tmp1.push(0); + __tmp1 + }), + } } fn f3(a0: Vec, a1: Ptr) -> Vec { diff --git a/rules/string/tgt_unsafe.rs b/rules/string/tgt_unsafe.rs index 388fb3859f..79b7909311 100644 --- a/rules/string/tgt_unsafe.rs +++ b/rules/string/tgt_unsafe.rs @@ -27,10 +27,16 @@ fn t7() -> libc::c_char { 0 as libc::c_char } -unsafe fn f1(a0: Vec, a1: usize, a2: usize) -> Vec { - let mut __tmp1 = a0[(a1) as usize..::std::cmp::min((a1 + a2) as usize, a0.len() - 1)].to_vec(); - __tmp1.push(0); - __tmp1 +// Keep temporary receivers alive, but borrow only after evaluating the arguments. +unsafe fn f1(a0: *const Vec, a1: usize, a2: usize) -> Vec { + match (a0, a1, a2) { + (__source, __pos, __count) => { + let __s = &*__source; + let mut __tmp1 = __s[__pos..::std::cmp::min(__pos + __count, __s.len() - 1)].to_vec(); + __tmp1.push(0); + __tmp1 + } + } } unsafe fn f2(a0: Vec) -> usize { (a0.len() - 1) diff --git a/tests/unit/out/refcount/string.rs b/tests/unit/out/refcount/string.rs index b8116f7f97..dc8c142082 100644 --- a/tests/unit/out/refcount/string.rs +++ b/tests/unit/out/refcount/string.rs @@ -6,6 +6,14 @@ use std::io::prelude::*; use std::io::{Read, Seek, Write}; use std::os::fd::AsFd; use std::rc::{Rc, Weak}; +pub fn counted_string_0(calls: Ptr) -> Vec { + calls.with_mut(|__v| __v.prefix_inc()); + return { + let mut __bytes = Ptr::::from_string_literal(b"hello").to_c_bytes(); + __bytes.push(0); + __bytes + }; +} pub fn main() { __cpp2rust_init_globals(); std::process::exit(main_0()); @@ -73,15 +81,13 @@ fn main_0() -> i32 { ); i.prefix_inc(); } - let s3: Value> = Rc::new(RefCell::new({ - let mut __tmp1 = (*s2.borrow())[(2_usize) as usize - ..::std::cmp::min( - (2_usize + 5_usize) as usize, - (*s2.borrow()).len().saturating_sub(1), - )] - .to_vec(); - __tmp1.push(0); - __tmp1 + let s3: Value> = Rc::new(RefCell::new(match (s2.as_pointer(), 2_usize, 5_usize) { + (__source, __pos, __count) => __source.with(|__s: &Vec| { + let mut __tmp1 = + __s[__pos..::std::cmp::min(__pos + __count, __s.len().saturating_sub(1))].to_vec(); + __tmp1.push(0); + __tmp1 + }), })); assert!((((*s3.borrow()).len() - 1) == 5_usize)); assert!((((*s3.borrow()).len() - 1) == ((*s3.borrow()).len() - 1))); @@ -93,23 +99,27 @@ fn main_0() -> i32 { ); i.prefix_inc(); } - let s4: Value> = Rc::new(RefCell::new({ - let mut __tmp1 = (*s1.borrow())[(1_usize) as usize - ..::std::cmp::min( - (1_usize - + Ptr::::from_string_literal(b"l").with_c_str(|__lookup| { - (*s1.borrow()) - .iter() - .take((*s1.borrow()).len().saturating_sub(1)) - .rposition(|&x| __lookup.contains(&x)) - .unwrap_or(usize::MAX) - })) as usize, - (*s1.borrow()).len().saturating_sub(1), - )] - .to_vec(); - __tmp1.push(0); - __tmp1 - })); + let s4: Value> = Rc::new(RefCell::new( + match ( + s1.as_pointer(), + 1_usize, + Ptr::::from_string_literal(b"l").with_c_str(|__lookup| { + (*s1.borrow()) + .iter() + .take((*s1.borrow()).len().saturating_sub(1)) + .rposition(|&x| __lookup.contains(&x)) + .unwrap_or(usize::MAX) + }), + ) { + (__source, __pos, __count) => __source.with(|__s: &Vec| { + let mut __tmp1 = __s + [__pos..::std::cmp::min(__pos + __count, __s.len().saturating_sub(1))] + .to_vec(); + __tmp1.push(0); + __tmp1 + }), + }, + )); assert!((((*s4.borrow()).len() - 1) == 3_usize)); assert!((((*s4.borrow()).len() - 1) == ((*s4.borrow()).len() - 1))); let mut p4: Ptr = s4.decay(); @@ -201,39 +211,41 @@ fn main_0() -> i32 { assert!(((string[1_usize] as i32) == (('a' as i8) as i32))); assert!(((string[2_usize] as i32) == (('r' as i8) as i32))); assert!(((string[3_usize] as i32) == 0)); - let mut result: Vec = { + let result: Value> = Rc::new(RefCell::new({ let mut r = (string).clone(); r.pop(); Ptr::::from_string_literal(b" foo").with_c_str(|__s| r.extend_from_slice(__s)); r.push(0); r - }; - assert!(((result.len() - 1) == 8_usize)); - assert!(((result[0_usize] as i32) == (('b' as i8) as i32))); - assert!(((result[1_usize] as i32) == (('a' as i8) as i32))); - assert!(((result[2_usize] as i32) == (('r' as i8) as i32))); - assert!(((result[3_usize] as i32) == 0)); - assert!(((result[4_usize] as i32) == ((' ' as i8) as i32))); - assert!(((result[5_usize] as i32) == (('f' as i8) as i32))); - assert!(((result[6_usize] as i32) == (('o' as i8) as i32))); - assert!(((result[7_usize] as i32) == (('o' as i8) as i32))); - let mut substr_0: Vec = { - let mut __tmp1 = result[(5_usize) as usize - ..::std::cmp::min((5_usize + 3_usize) as usize, result.len().saturating_sub(1))] - .to_vec(); - __tmp1.push(0); - __tmp1 + })); + assert!((((*result.borrow()).len() - 1) == 8_usize)); + assert!((({ (*result.borrow())[0_usize] } as i32) == (('b' as i8) as i32))); + assert!((({ (*result.borrow())[1_usize] } as i32) == (('a' as i8) as i32))); + assert!((({ (*result.borrow())[2_usize] } as i32) == (('r' as i8) as i32))); + assert!((({ (*result.borrow())[3_usize] } as i32) == 0)); + assert!((({ (*result.borrow())[4_usize] } as i32) == ((' ' as i8) as i32))); + assert!((({ (*result.borrow())[5_usize] } as i32) == (('f' as i8) as i32))); + assert!((({ (*result.borrow())[6_usize] } as i32) == (('o' as i8) as i32))); + assert!((({ (*result.borrow())[7_usize] } as i32) == (('o' as i8) as i32))); + let mut substr_0: Vec = match (result.as_pointer(), 5_usize, 3_usize) { + (__source, __pos, __count) => __source.with(|__s: &Vec| { + let mut __tmp1 = + __s[__pos..::std::cmp::min(__pos + __count, __s.len().saturating_sub(1))].to_vec(); + __tmp1.push(0); + __tmp1 + }), }; assert!(((substr_0.len() - 1) == 3_usize)); assert!(((substr_0[0_usize] as i32) == (('f' as i8) as i32))); assert!(((substr_0[1_usize] as i32) == (('o' as i8) as i32))); assert!(((substr_0[2_usize] as i32) == (('o' as i8) as i32))); - let mut substr_1: Vec = { - let mut __tmp1 = result[(0_usize) as usize - ..::std::cmp::min((0_usize + 5_usize) as usize, result.len().saturating_sub(1))] - .to_vec(); - __tmp1.push(0); - __tmp1 + let mut substr_1: Vec = match (result.as_pointer(), 0_usize, 5_usize) { + (__source, __pos, __count) => __source.with(|__s: &Vec| { + let mut __tmp1 = + __s[__pos..::std::cmp::min(__pos + __count, __s.len().saturating_sub(1))].to_vec(); + __tmp1.push(0); + __tmp1 + }), }; assert!(((substr_1.len() - 1) == 5_usize)); assert!(((substr_1[0_usize] as i32) == (('b' as i8) as i32))); @@ -241,15 +253,13 @@ fn main_0() -> i32 { assert!(((substr_1[2_usize] as i32) == (('r' as i8) as i32))); assert!(((substr_1[3_usize] as i32) == 0)); assert!(((substr_1[4_usize] as i32) == ((' ' as i8) as i32))); - let mut substr_2: Vec = { - let mut __tmp1 = result[(0_usize) as usize - ..::std::cmp::min( - (0_usize + 15_usize) as usize, - result.len().saturating_sub(1), - )] - .to_vec(); - __tmp1.push(0); - __tmp1 + let mut substr_2: Vec = match (result.as_pointer(), 0_usize, 15_usize) { + (__source, __pos, __count) => __source.with(|__s: &Vec| { + let mut __tmp1 = + __s[__pos..::std::cmp::min(__pos + __count, __s.len().saturating_sub(1))].to_vec(); + __tmp1.push(0); + __tmp1 + }), }; assert!(((substr_2.len() - 1) == 8_usize)); assert!(((substr_2[0_usize] as i32) == (('b' as i8) as i32))); @@ -261,39 +271,39 @@ fn main_0() -> i32 { assert!(((substr_2[6_usize] as i32) == (('o' as i8) as i32))); assert!(((substr_2[7_usize] as i32) == (('o' as i8) as i32))); let mut pos: usize = Ptr::::from_string_literal(b"b").with_c_str(|__lookup| { - result + (*result.borrow()) .iter() - .take(result.len().saturating_sub(1)) + .take((*result.borrow()).len().saturating_sub(1)) .rposition(|&x| __lookup.contains(&x)) .unwrap_or(usize::MAX) }); assert!((pos == 0_usize)); pos = Ptr::::from_string_literal(b"f").with_c_str(|__lookup| { - result + (*result.borrow()) .iter() - .take(result.len().saturating_sub(1)) + .take((*result.borrow()).len().saturating_sub(1)) .rposition(|&x| __lookup.contains(&x)) .unwrap_or(usize::MAX) }); assert!((pos == 5_usize)); pos = Ptr::::from_string_literal(b"o").with_c_str(|__lookup| { - result + (*result.borrow()) .iter() - .take(result.len().saturating_sub(1)) + .take((*result.borrow()).len().saturating_sub(1)) .rposition(|&x| __lookup.contains(&x)) .unwrap_or(usize::MAX) }); assert!((pos == 7_usize)); pos = Ptr::::from_string_literal(b"x").with_c_str(|__lookup| { - result + (*result.borrow()) .iter() - .take(result.len().saturating_sub(1)) + .take((*result.borrow()).len().saturating_sub(1)) .rposition(|&x| __lookup.contains(&x)) .unwrap_or(usize::MAX) }); assert!((pos == ((-1_i64 as u64) as usize))); pos = { - let __hay = &result[..result.len().saturating_sub(1)]; + let __hay = &(*result.borrow())[..(*result.borrow()).len().saturating_sub(1)]; Ptr::::from_string_literal(b"f").with_c_str(|__needle| { (0_usize..=__hay.len().saturating_sub(__needle.len())) .find(|&__i| __hay[__i..].starts_with(__needle)) @@ -302,7 +312,7 @@ fn main_0() -> i32 { }; assert!((pos == 5_usize)); pos = { - let __hay = &result[..result.len().saturating_sub(1)]; + let __hay = &(*result.borrow())[..(*result.borrow()).len().saturating_sub(1)]; Ptr::::from_string_literal(b"oo").with_c_str(|__needle| { (0_usize..=__hay.len().saturating_sub(__needle.len())) .find(|&__i| __hay[__i..].starts_with(__needle)) @@ -311,7 +321,7 @@ fn main_0() -> i32 { }; assert!((pos == 6_usize)); pos = { - let __hay = &result[..result.len().saturating_sub(1)]; + let __hay = &(*result.borrow())[..(*result.borrow()).len().saturating_sub(1)]; Ptr::::from_string_literal(b"x").with_c_str(|__needle| { (0_usize..=__hay.len().saturating_sub(__needle.len())) .find(|&__i| __hay[__i..].starts_with(__needle)) @@ -334,6 +344,52 @@ fn main_0() -> i32 { assert!((diff < 0_i64)); diff += 6_i64; assert!((diff == 3_i64)); + let mut substr_pos: usize = 1_usize; + let once: Value> = Rc::new(RefCell::new( + match (s1.as_pointer(), substr_pos.postfix_inc(), 2_usize) { + (__source, __pos, __count) => __source.with(|__s: &Vec| { + let mut __tmp1 = __s + [__pos..::std::cmp::min(__pos + __count, __s.len().saturating_sub(1))] + .to_vec(); + __tmp1.push(0); + __tmp1 + }), + }, + )); + println!("position: {} {}", once.decay(), substr_pos); + let mut substr_count: usize = 2_usize; + once.as_pointer().write( + match (s1.as_pointer(), 1_usize, substr_count.postfix_inc()) { + (__source, __pos, __count) => __source.with(|__s: &Vec| { + let mut __tmp1 = __s + [__pos..::std::cmp::min(__pos + __count, __s.len().saturating_sub(1))] + .to_vec(); + __tmp1.push(0); + __tmp1 + }), + }, + ); + println!("count: {} {}", once.decay(), substr_count); + let receiver_calls: Value = Rc::new(RefCell::new(0)); + once.as_pointer().write( + match ( + Rc::new(RefCell::new( + ({ counted_string_0(receiver_calls.as_pointer()) }), + )) + .as_pointer(), + 1_usize, + 2_usize, + ) { + (__source, __pos, __count) => __source.with(|__s: &Vec| { + let mut __tmp1 = __s + [__pos..::std::cmp::min(__pos + __count, __s.len().saturating_sub(1))] + .to_vec(); + __tmp1.push(0); + __tmp1 + }), + }, + ); + println!("receiver: {} {}", once.decay(), (*receiver_calls.borrow())); let mut t0: usize = ((*s1.borrow()).len() - 1); let mut t1: usize = (t0).wrapping_add(((p1.read()) as usize)); let mut t2: usize = (t1).wrapping_add(((*s2.borrow()).len() - 1)); diff --git a/tests/unit/out/refcount/string_substr.rs b/tests/unit/out/refcount/string_substr.rs new file mode 100644 index 0000000000..6e0f1edd7b --- /dev/null +++ b/tests/unit/out/refcount/string_substr.rs @@ -0,0 +1,231 @@ +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(Clone, Record, ByteRepr, VaArg, FnPtrArg, Default)] +#[byte_size(8)] +pub struct Text { + #[offset(0)] + #[byte_size(8)] + pub value: Ptr>, +} +pub fn receiver_0(s: Ptr>, calls: Ptr) -> Ptr> { + calls.with_mut(|__v| __v.prefix_inc()); + return (s).clone(); +} +pub fn temporary_1(calls: Ptr) -> Vec { + calls.with_mut(|__v| __v.prefix_inc()); + return { + let mut __bytes = Ptr::::from_string_literal(b"hello").to_c_bytes(); + __bytes.push(0); + __bytes + }; +} +pub fn main() { + __cpp2rust_init_globals(); + std::process::exit(main_0()); +} +fn main_0() -> i32 { + let s: Value> = Rc::new(RefCell::new({ + let mut __bytes = Ptr::::from_string_literal(b"hello").to_c_bytes(); + __bytes.push(0); + __bytes + })); + let calls: Value = Rc::new(RefCell::new(0)); + let out: Value> = Rc::new(RefCell::new( + match ( + ({ receiver_0(s.as_pointer(), calls.as_pointer()) }), + ((*calls.borrow()) as usize), + 2_usize, + ) { + (__source, __pos, __count) => __source.with(|__s: &Vec| { + let mut __tmp1 = __s + [__pos..::std::cmp::min(__pos + __count, __s.len().saturating_sub(1))] + .to_vec(); + __tmp1.push(0); + __tmp1 + }), + }, + )); + println!("receiver: {} {}", out.decay(), (*calls.borrow())); + (*calls.borrow_mut()) = 0; + out.as_pointer().write( + match ( + Rc::new(RefCell::new(({ temporary_1(calls.as_pointer()) }))).as_pointer(), + 1_usize, + 2_usize, + ) { + (__source, __pos, __count) => __source.with(|__s: &Vec| { + let mut __tmp1 = __s + [__pos..::std::cmp::min(__pos + __count, __s.len().saturating_sub(1))] + .to_vec(); + __tmp1.push(0); + __tmp1 + }), + }, + ); + println!("temporary: {} {}", out.decay(), (*calls.borrow())); + out.as_pointer().write( + match ( + s.as_pointer(), + ({ + (*s.borrow_mut())[0_usize] = ('j' as i8); + 0 + } as usize), + 2_usize, + ) { + (__source, __pos, __count) => __source.with(|__s: &Vec| { + let mut __tmp1 = __s + [__pos..::std::cmp::min(__pos + __count, __s.len().saturating_sub(1))] + .to_vec(); + __tmp1.push(0); + __tmp1 + }), + }, + ); + println!("position mutation: {} {}", out.decay(), s.decay()); + out.as_pointer().write( + match ( + s.as_pointer(), + 0_usize, + ({ + (*s.borrow_mut())[1_usize] = ('a' as i8); + 2 + } as usize), + ) { + (__source, __pos, __count) => __source.with(|__s: &Vec| { + let mut __tmp1 = __s + [__pos..::std::cmp::min(__pos + __count, __s.len().saturating_sub(1))] + .to_vec(); + __tmp1.push(0); + __tmp1 + }), + }, + ); + println!("count mutation: {} {}", out.decay(), s.decay()); + (*out.borrow_mut())[0_usize] = ('X' as i8); + (*s.borrow_mut())[1_usize] = ('b' as i8); + println!("independent: {} {}", out.decay(), s.decay()); + let mut p: Ptr> = (s.as_pointer()); + out.as_pointer() + .write(match ((p).clone(), 1_usize, 2_usize) { + (__source, __pos, __count) => __source.with(|__s: &Vec| { + let mut __tmp1 = __s + [__pos..::std::cmp::min(__pos + __count, __s.len().saturating_sub(1))] + .to_vec(); + __tmp1.push(0); + __tmp1 + }), + }); + println!("pointer: {}", out.decay()); + out.as_pointer().write( + match ( + Rc::new(RefCell::new( + match ( + Rc::new(RefCell::new({ + let mut __bytes = Ptr::::from_string_literal(b"hello").to_c_bytes(); + __bytes.push(0); + __bytes + })) + .as_pointer(), + 1_usize, + 3_usize, + ) { + (__source, __pos, __count) => __source.with(|__s: &Vec| { + let mut __tmp1 = __s + [__pos..::std::cmp::min(__pos + __count, __s.len().saturating_sub(1))] + .to_vec(); + __tmp1.push(0); + __tmp1 + }), + }, + )) + .as_pointer(), + 1_usize, + 1_usize, + ) { + (__source, __pos, __count) => __source.with(|__s: &Vec| { + let mut __tmp1 = __s + [__pos..::std::cmp::min(__pos + __count, __s.len().saturating_sub(1))] + .to_vec(); + __tmp1.push(0); + __tmp1 + }), + }, + ); + println!("nested: {}", out.decay()); + out.as_pointer() + .write(match (s.as_pointer(), ((*s.borrow()).len() - 1), 0_usize) { + (__source, __pos, __count) => __source.with(|__s: &Vec| { + let mut __tmp1 = __s + [__pos..::std::cmp::min(__pos + __count, __s.len().saturating_sub(1))] + .to_vec(); + __tmp1.push(0); + __tmp1 + }), + }); + println!("empty: {}", ((*out.borrow()).len() - 1)); + let field: Value> = Rc::new(RefCell::new({ + let mut __bytes = Ptr::::from_string_literal(b"hello").to_c_bytes(); + __bytes.push(0); + __bytes + })); + let text: Value = Rc::new(RefCell::new(Text { + value: field.as_pointer(), + })); + out.as_pointer().write( + match ( + ({ (*text.borrow()).value.clone() }).clone(), + 1_usize, + 2_usize, + ) { + (__source, __pos, __count) => __source.with(|__s: &Vec| { + let mut __tmp1 = __s + [__pos..::std::cmp::min(__pos + __count, __s.len().saturating_sub(1))] + .to_vec(); + __tmp1.push(0); + __tmp1 + }), + }, + ); + println!( + "field: {} {}", + out.decay(), + { (*text.borrow()).value.clone() }.decay() + ); + let strings: Value>> = Rc::new(RefCell::new(Vec::from([ + { + let mut __bytes = Ptr::::from_string_literal(b"hello").to_c_bytes(); + __bytes.push(0); + __bytes + }, + { + let mut __bytes = Ptr::::from_string_literal(b"world").to_c_bytes(); + __bytes.push(0); + __bytes + }, + ]))); + let mut index: usize = 0_usize; + out.as_pointer().write( + match ( + strings.decay().offset(index.postfix_inc()), + 1_usize, + 2_usize, + ) { + (__source, __pos, __count) => __source.with(|__s: &Vec| { + let mut __tmp1 = __s + [__pos..::std::cmp::min(__pos + __count, __s.len().saturating_sub(1))] + .to_vec(); + __tmp1.push(0); + __tmp1 + }), + }, + ); + println!("element: {} {}", out.decay(), index); + return 0; +} +pub fn __cpp2rust_init_globals() {} diff --git a/tests/unit/out/unsafe/string.rs b/tests/unit/out/unsafe/string.rs index 5ab22b3acc..ae73493817 100644 --- a/tests/unit/out/unsafe/string.rs +++ b/tests/unit/out/unsafe/string.rs @@ -6,6 +6,13 @@ use std::collections::BTreeMap; use std::io::{Read, Seek, Write}; use std::os::fd::{AsFd, FromRawFd, IntoRawFd}; use std::rc::Rc; +pub unsafe fn counted_string_0(calls: *mut i32) -> Vec { + (*calls).prefix_inc(); + return { + let s = c"hello".as_ptr(); + std::slice::from_raw_parts(s, (0..).take_while(|&i| *s.add(i) != 0).count() + 1).to_vec() + }; +} pub fn main() { unsafe { __cpp2rust_init_globals(); @@ -81,12 +88,14 @@ unsafe fn main_0() -> i32 { ); i.prefix_inc(); } - let mut s3: Vec = { - let mut __tmp1 = s2 - [(2_usize) as usize..::std::cmp::min((2_usize + 5_usize) as usize, s2.len() - 1)] - .to_vec(); - __tmp1.push(0); - __tmp1 + let mut s3: Vec = match ((&mut s2 as *const Vec), 2_usize, 5_usize) + { + (__source, __pos, __count) => { + let __s = &*__source; + let mut __tmp1 = __s[__pos..::std::cmp::min(__pos + __count, __s.len() - 1)].to_vec(); + __tmp1.push(0); + __tmp1 + } }; assert!(((s3.len() - 1) == (5_usize))); assert!(((s3.len() - 1) == (s3.len() - 1))); @@ -96,24 +105,25 @@ unsafe fn main_0() -> i32 { assert!((((*p3.offset((i) as isize)) as i32) == (s3[(i as usize)] as i32))); i.prefix_inc(); } - let mut s4: Vec = { - let mut __tmp1 = s1[(1_usize) as usize - ..::std::cmp::min( - (1_usize - + match s1.iter().rposition(|&c| { - ::std::ffi::CStr::from_ptr(c"l".as_ptr()) - .to_str() - .unwrap() - .contains(c as u8 as char) - }) { - Some(idx) => idx, - None => usize::MAX, - }) as usize, - s1.len() - 1, - )] - .to_vec(); - __tmp1.push(0); - __tmp1 + let mut s4: Vec = match ( + (&mut s1 as *const Vec), + 1_usize, + match s1.iter().rposition(|&c| { + ::std::ffi::CStr::from_ptr(c"l".as_ptr()) + .to_str() + .unwrap() + .contains(c as u8 as char) + }) { + Some(idx) => idx, + None => usize::MAX, + }, + ) { + (__source, __pos, __count) => { + let __s = &*__source; + let mut __tmp1 = __s[__pos..::std::cmp::min(__pos + __count, __s.len() - 1)].to_vec(); + __tmp1.push(0); + __tmp1 + } }; assert!(((s4.len() - 1) == (3_usize))); assert!(((s4.len() - 1) == (s4.len() - 1))); @@ -232,37 +242,46 @@ unsafe fn main_0() -> i32 { assert!(((result[(5_usize)] as i32) == (('f' as libc::c_char) as i32))); assert!(((result[(6_usize)] as i32) == (('o' as libc::c_char) as i32))); assert!(((result[(7_usize)] as i32) == (('o' as libc::c_char) as i32))); - let mut substr_0: Vec = { - let mut __tmp1 = result - [(5_usize) as usize..::std::cmp::min((5_usize + 3_usize) as usize, result.len() - 1)] - .to_vec(); - __tmp1.push(0); - __tmp1 - }; + let mut substr_0: Vec = + match ((&mut result as *const Vec), 5_usize, 3_usize) { + (__source, __pos, __count) => { + let __s = &*__source; + let mut __tmp1 = + __s[__pos..::std::cmp::min(__pos + __count, __s.len() - 1)].to_vec(); + __tmp1.push(0); + __tmp1 + } + }; assert!(((substr_0.len() - 1) == (3_usize))); assert!(((substr_0[(0_usize)] as i32) == (('f' as libc::c_char) as i32))); assert!(((substr_0[(1_usize)] as i32) == (('o' as libc::c_char) as i32))); assert!(((substr_0[(2_usize)] as i32) == (('o' as libc::c_char) as i32))); - let mut substr_1: Vec = { - let mut __tmp1 = result - [(0_usize) as usize..::std::cmp::min((0_usize + 5_usize) as usize, result.len() - 1)] - .to_vec(); - __tmp1.push(0); - __tmp1 - }; + let mut substr_1: Vec = + match ((&mut result as *const Vec), 0_usize, 5_usize) { + (__source, __pos, __count) => { + let __s = &*__source; + let mut __tmp1 = + __s[__pos..::std::cmp::min(__pos + __count, __s.len() - 1)].to_vec(); + __tmp1.push(0); + __tmp1 + } + }; assert!(((substr_1.len() - 1) == (5_usize))); assert!(((substr_1[(0_usize)] as i32) == (('b' as libc::c_char) as i32))); assert!(((substr_1[(1_usize)] as i32) == (('a' as libc::c_char) as i32))); assert!(((substr_1[(2_usize)] as i32) == (('r' as libc::c_char) as i32))); assert!(((substr_1[(3_usize)] as i32) == (0))); assert!(((substr_1[(4_usize)] as i32) == ((' ' as libc::c_char) as i32))); - let mut substr_2: Vec = { - let mut __tmp1 = result - [(0_usize) as usize..::std::cmp::min((0_usize + 15_usize) as usize, result.len() - 1)] - .to_vec(); - __tmp1.push(0); - __tmp1 - }; + let mut substr_2: Vec = + match ((&mut result as *const Vec), 0_usize, 15_usize) { + (__source, __pos, __count) => { + let __s = &*__source; + let mut __tmp1 = + __s[__pos..::std::cmp::min(__pos + __count, __s.len() - 1)].to_vec(); + __tmp1.push(0); + __tmp1 + } + }; assert!(((substr_2.len() - 1) == (8_usize))); assert!(((substr_2[(0_usize)] as i32) == (('b' as libc::c_char) as i32))); assert!(((substr_2[(1_usize)] as i32) == (('a' as libc::c_char) as i32))); @@ -350,6 +369,66 @@ unsafe fn main_0() -> i32 { assert!(((diff) < (0_i64))); diff += 6_i64; assert!(((diff) == (3_i64))); + let mut substr_pos: usize = 1_usize; + let mut once: Vec = match ( + (&mut s1 as *const Vec), + substr_pos.postfix_inc(), + 2_usize, + ) { + (__source, __pos, __count) => { + let __s = &*__source; + let mut __tmp1 = __s[__pos..::std::cmp::min(__pos + __count, __s.len() - 1)].to_vec(); + __tmp1.push(0); + __tmp1 + } + }; + (unsafe { + libc::printf( + c"position: %s %zu\n".as_ptr() as *const libc::c_char, + (once.as_ptr()), + (substr_pos), + ) + }); + let mut substr_count: usize = 2_usize; + once = match ( + (&mut s1 as *const Vec), + 1_usize, + substr_count.postfix_inc(), + ) { + (__source, __pos, __count) => { + let __s = &*__source; + let mut __tmp1 = __s[__pos..::std::cmp::min(__pos + __count, __s.len() - 1)].to_vec(); + __tmp1.push(0); + __tmp1 + } + }; + (unsafe { + libc::printf( + c"count: %s %zu\n".as_ptr() as *const libc::c_char, + (once.as_ptr()), + (substr_count), + ) + }); + let mut receiver_calls: i32 = 0; + once = match ( + (&mut (unsafe { counted_string_0(&mut receiver_calls) }) as *const Vec), + 1_usize, + 2_usize, + ) { + (__source, __pos, __count) => { + let __s = &*__source; + let mut __tmp1 = __s[__pos..::std::cmp::min(__pos + __count, __s.len() - 1)].to_vec(); + __tmp1.push(0); + __tmp1 + } + }; + (unsafe { + libc::printf( + c"receiver: %s %d\n".as_ptr() as *const libc::c_char, + (once.as_ptr()), + (receiver_calls), + ) + }); let mut t0: usize = (s1.len() - 1); let mut t1: usize = (t0).wrapping_add(((*p1) as usize)); let mut t2: usize = (t1).wrapping_add((s2.len() - 1)); diff --git a/tests/unit/out/unsafe/string_substr.rs b/tests/unit/out/unsafe/string_substr.rs new file mode 100644 index 0000000000..0658739d77 --- /dev/null +++ b/tests/unit/out/unsafe/string_substr.rs @@ -0,0 +1,246 @@ +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, VaArg, FnPtrArg, Default)] +pub struct Text { + pub value: *mut Vec, +} +pub unsafe fn receiver_0(s: *mut Vec, calls: *mut i32) -> *mut Vec { + (*calls).prefix_inc(); + return s; +} +pub unsafe fn temporary_1(calls: *mut i32) -> Vec { + (*calls).prefix_inc(); + return { + let s = c"hello".as_ptr(); + std::slice::from_raw_parts(s, (0..).take_while(|&i| *s.add(i) != 0).count() + 1).to_vec() + }; +} +pub fn main() { + unsafe { + __cpp2rust_init_globals(); + std::process::exit(main_0() as i32); + } +} +unsafe fn main_0() -> i32 { + let mut s: Vec = { + let s = c"hello".as_ptr(); + std::slice::from_raw_parts(s, (0..).take_while(|&i| *s.add(i) != 0).count() + 1).to_vec() + }; + let mut calls: i32 = 0; + let mut out: Vec = match ( + ((unsafe { receiver_0(&mut s, &mut calls) }) as *const Vec), + (calls as usize), + 2_usize, + ) { + (__source, __pos, __count) => { + let __s = &*__source; + let mut __tmp1 = __s[__pos..::std::cmp::min(__pos + __count, __s.len() - 1)].to_vec(); + __tmp1.push(0); + __tmp1 + } + }; + (unsafe { + libc::printf( + c"receiver: %s %d\n".as_ptr() as *const libc::c_char, + (out.as_ptr()), + (calls), + ) + }); + calls = 0; + out = match ( + (&mut (unsafe { temporary_1(&mut calls) }) as *const Vec), + 1_usize, + 2_usize, + ) { + (__source, __pos, __count) => { + let __s = &*__source; + let mut __tmp1 = __s[__pos..::std::cmp::min(__pos + __count, __s.len() - 1)].to_vec(); + __tmp1.push(0); + __tmp1 + } + }; + (unsafe { + libc::printf( + c"temporary: %s %d\n".as_ptr() as *const libc::c_char, + (out.as_ptr()), + (calls), + ) + }); + out = match ( + (&mut s as *const Vec), + ({ + s[(0_usize)] = ('j' as libc::c_char); + 0 + } as usize), + 2_usize, + ) { + (__source, __pos, __count) => { + let __s = &*__source; + let mut __tmp1 = __s[__pos..::std::cmp::min(__pos + __count, __s.len() - 1)].to_vec(); + __tmp1.push(0); + __tmp1 + } + }; + (unsafe { + libc::printf( + c"position mutation: %s %s\n".as_ptr() as *const libc::c_char, + (out.as_ptr()), + (s.as_ptr()), + ) + }); + out = match ( + (&mut s as *const Vec), + 0_usize, + ({ + s[(1_usize)] = ('a' as libc::c_char); + 2 + } as usize), + ) { + (__source, __pos, __count) => { + let __s = &*__source; + let mut __tmp1 = __s[__pos..::std::cmp::min(__pos + __count, __s.len() - 1)].to_vec(); + __tmp1.push(0); + __tmp1 + } + }; + (unsafe { + libc::printf( + c"count mutation: %s %s\n".as_ptr() as *const libc::c_char, + (out.as_ptr()), + (s.as_ptr()), + ) + }); + out[(0_usize)] = ('X' as libc::c_char); + s[(1_usize)] = ('b' as libc::c_char); + (unsafe { + libc::printf( + c"independent: %s %s\n".as_ptr() as *const libc::c_char, + (out.as_ptr()), + (s.as_ptr()), + ) + }); + let mut p: *const Vec = (&mut s as *mut Vec).cast_const(); + out = match ((p as *const Vec), 1_usize, 2_usize) { + (__source, __pos, __count) => { + let __s = &*__source; + let mut __tmp1 = __s[__pos..::std::cmp::min(__pos + __count, __s.len() - 1)].to_vec(); + __tmp1.push(0); + __tmp1 + } + }; + (unsafe { + libc::printf( + c"pointer: %s\n".as_ptr() as *const libc::c_char, + (out.as_ptr()), + ) + }); + out = match ( + (&mut match ( + (&mut { + let s = c"hello".as_ptr(); + std::slice::from_raw_parts(s, (0..).take_while(|&i| *s.add(i) != 0).count() + 1) + .to_vec() + } as *const Vec), + 1_usize, + 3_usize, + ) { + (__source, __pos, __count) => { + let __s = &*__source; + let mut __tmp1 = + __s[__pos..::std::cmp::min(__pos + __count, __s.len() - 1)].to_vec(); + __tmp1.push(0); + __tmp1 + } + } as *const Vec), + 1_usize, + 1_usize, + ) { + (__source, __pos, __count) => { + let __s = &*__source; + let mut __tmp1 = __s[__pos..::std::cmp::min(__pos + __count, __s.len() - 1)].to_vec(); + __tmp1.push(0); + __tmp1 + } + }; + (unsafe { + libc::printf( + c"nested: %s\n".as_ptr() as *const libc::c_char, + (out.as_ptr()), + ) + }); + out = match ((&mut s as *const Vec), (s.len() - 1), 0_usize) { + (__source, __pos, __count) => { + let __s = &*__source; + let mut __tmp1 = __s[__pos..::std::cmp::min(__pos + __count, __s.len() - 1)].to_vec(); + __tmp1.push(0); + __tmp1 + } + }; + (unsafe { + libc::printf( + c"empty: %zu\n".as_ptr() as *const libc::c_char, + (out.len() - 1), + ) + }); + let mut field: Vec = { + let s = c"hello".as_ptr(); + std::slice::from_raw_parts(s, (0..).take_while(|&i| *s.add(i) != 0).count() + 1).to_vec() + }; + let mut text: Text = Text { value: &mut field }; + out = match ((text.value as *const Vec), 1_usize, 2_usize) { + (__source, __pos, __count) => { + let __s = &*__source; + let mut __tmp1 = __s[__pos..::std::cmp::min(__pos + __count, __s.len() - 1)].to_vec(); + __tmp1.push(0); + __tmp1 + } + }; + (unsafe { + libc::printf( + c"field: %s %s\n".as_ptr() as *const libc::c_char, + (out.as_ptr()), + ((*text.value).as_ptr()), + ) + }); + let mut strings: Vec> = Vec::from([ + { + let s = c"hello".as_ptr(); + std::slice::from_raw_parts(s, (0..).take_while(|&i| *s.add(i) != 0).count() + 1) + .to_vec() + }, + { + let s = c"world".as_ptr(); + std::slice::from_raw_parts(s, (0..).take_while(|&i| *s.add(i) != 0).count() + 1) + .to_vec() + }, + ]); + let mut index: usize = 0_usize; + out = match ( + (&mut strings[(index.postfix_inc())] as *const Vec), + 1_usize, + 2_usize, + ) { + (__source, __pos, __count) => { + let __s = &*__source; + let mut __tmp1 = __s[__pos..::std::cmp::min(__pos + __count, __s.len() - 1)].to_vec(); + __tmp1.push(0); + __tmp1 + } + }; + (unsafe { + libc::printf( + c"element: %s %zu\n".as_ptr() as *const libc::c_char, + (out.as_ptr()), + (index), + ) + }); + return 0; +} +pub unsafe fn __cpp2rust_init_globals() {} diff --git a/tests/unit/string.cpp b/tests/unit/string.cpp index 02e70149a6..c5bdd044ef 100644 --- a/tests/unit/string.cpp +++ b/tests/unit/string.cpp @@ -1,8 +1,14 @@ // ADDITIONAL_COMPILE_FLAGS: -std=c++17 #include #include +#include #include +std::string counted_string(int &calls) { + ++calls; + return "hello"; +} + int main() { std::string empty; assert(empty.length() == 0); @@ -143,6 +149,16 @@ int main() { diff += 6; assert(diff == 3); + std::size_t substr_pos = 1; + auto once = s1.substr(substr_pos++, 2); + printf("position: %s %zu\n", once.c_str(), substr_pos); + std::size_t substr_count = 2; + once = s1.substr(1, substr_count++); + printf("count: %s %zu\n", once.c_str(), substr_count); + int receiver_calls = 0; + once = counted_string(receiver_calls).substr(1, 2); + printf("receiver: %s %d\n", once.c_str(), receiver_calls); + // FIXME auto t0 = s1.length(); auto t1 = t0 + *p1; diff --git a/tests/unit/string_substr.cpp b/tests/unit/string_substr.cpp new file mode 100644 index 0000000000..fc5e7cbdbb --- /dev/null +++ b/tests/unit/string_substr.cpp @@ -0,0 +1,56 @@ +// ADDITIONAL_COMPILE_FLAGS: -std=c++17 +#include +#include +#include + +struct Text { + std::string &value; +}; + +std::string &receiver(std::string &s, int &calls) { + ++calls; + return s; +} + +std::string temporary(int &calls) { + ++calls; + return "hello"; +} + +int main() { + std::string s = "hello"; + int calls = 0; + auto out = receiver(s, calls).substr(calls, 2); + printf("receiver: %s %d\n", out.c_str(), calls); + + calls = 0; + out = temporary(calls).substr(1, 2); + printf("temporary: %s %d\n", out.c_str(), calls); + + out = s.substr((s[0] = 'j', 0), 2); + printf("position mutation: %s %s\n", out.c_str(), s.c_str()); + out = s.substr(0, (s[1] = 'a', 2)); + printf("count mutation: %s %s\n", out.c_str(), s.c_str()); + + out[0] = 'X'; + s[1] = 'b'; + printf("independent: %s %s\n", out.c_str(), s.c_str()); + + const std::string *p = &s; + out = p->substr(1, 2); + printf("pointer: %s\n", out.c_str()); + out = std::string("hello").substr(1, 3).substr(1, 1); + printf("nested: %s\n", out.c_str()); + out = s.substr(s.size(), 0); + printf("empty: %zu\n", out.size()); + + std::string field = "hello"; + Text text{field}; + out = text.value.substr(1, 2); + printf("field: %s %s\n", out.c_str(), text.value.c_str()); + std::vector strings = {"hello", "world"}; + std::size_t index = 0; + out = strings[index++].substr(1, 2); + printf("element: %s %zu\n", out.c_str(), index); + return 0; +}