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
33 changes: 23 additions & 10 deletions cpp2rust/converter/converter.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1816,6 +1816,20 @@ void Converter::ConvertFunctionToFunctionPointer(
computed_expr_type_ = ComputedExprType::FreshPointer;
}

std::string Converter::ConvertFnPtrCallee(clang::Expr *arg) {
PushExprKind push(*this, ExprKind::Callee);
Buffer buf(*this);
Convert(arg);
return std::move(buf).str();
}

std::string Converter::ConvertFnPtrPlaceholder(clang::Expr *arg) {
auto proto =
arg->getType()->getPointeeType()->getAs<clang::FunctionProtoType>();
return std::format("({} as {} {})", ConvertFnPtrCallee(arg), keyword_unsafe_,
ConvertFunctionPointerType(proto));
}

Converter::CallInfo Converter::CollectCallInfo(clang::CallExpr *expr) {
using Kind = CallArg::Kind;

Expand Down Expand Up @@ -4607,22 +4621,20 @@ void Converter::PlaceholderCtx::dump() const {
<< ", declared_in_rule_as_rust_ptr: "
<< declared_in_rule_as_rust_ptr
<< ", access: " << static_cast<int>(access)
<< ", param_type: " << param_type
<< ", arg_idx: " << arg_idx
<< ", materialize_idx: " << materialize_idx << '\n';
}

std::string Converter::ConvertPlaceholder(clang::Expr *expr, clang::Expr *arg,
const PlaceholderCtx &ph_ctx) {
if (arg->getType()->isFunctionPointerType()) {
PushExprKind push(*this, ExprKind::Callee);
Buffer buf(*this);
Convert(arg);
return std::move(buf).str();
return ConvertFnPtrPlaceholder(arg);
}

if (ph_ctx.declared_in_rule_as_rust_ptr && arg->getType()->isArrayType()) {
return std::format("({} as {})", ConvertFreshPointer(arg),
ph_ctx.param_type);
return std::format(
"({} as {})", ConvertFreshPointer(arg),
Mapper::GetParamType(GetCalleeOrExpr(expr), ph_ctx.arg_idx));
}

if (ph_ctx.needs_materialization()) {
Expand All @@ -4637,8 +4649,9 @@ std::string Converter::ConvertPlaceholder(clang::Expr *expr, clang::Expr *arg,
}

if (ph_ctx.needs_pointer_receiver()) {
return std::format("({} as {})", ConvertFreshObject(arg),
ph_ctx.param_type);
return std::format(
"({} as {})", ConvertFreshObject(arg),
Mapper::GetParamType(GetCalleeOrExpr(expr), ph_ctx.arg_idx));
}

if (ph_ctx.needs_object_receiver()) {
Expand Down Expand Up @@ -4717,7 +4730,7 @@ std::string Converter::ConvertIRFragment(
bool is_receiver = HasReceiver(expr) && arg_idx == 0;

PlaceholderCtx ph_ctx{
.param_type = Mapper::GetParamType(GetCalleeOrExpr(expr), arg_idx),
.arg_idx = arg_idx,
.implicit_convert_to = GetParamImplicitConvertTarget(expr, arg_idx),
.materialize_ctx = ctx,
.materialize_idx =
Expand Down
5 changes: 4 additions & 1 deletion cpp2rust/converter/converter.h
Original file line number Diff line number Diff line change
Expand Up @@ -221,7 +221,7 @@ class Converter : public clang::RecursiveASTVisitor<Converter> {
};

struct PlaceholderCtx {
std::string param_type;
unsigned arg_idx;
std::optional<clang::QualType> implicit_convert_to;
TempMaterializationCtx *materialize_ctx;
int materialize_idx; // <0 = no idx, >=0 idx valid
Expand Down Expand Up @@ -309,6 +309,9 @@ class Converter : public clang::RecursiveASTVisitor<Converter> {
virtual void
ConvertFunctionToFunctionPointer(const clang::FunctionDecl *fn_decl);

std::string ConvertFnPtrCallee(clang::Expr *arg);
virtual std::string ConvertFnPtrPlaceholder(clang::Expr *arg);

// Option<fn> implements Copy
virtual bool FunctionPointerImplementsCopy() const { return true; }

Expand Down
7 changes: 3 additions & 4 deletions cpp2rust/converter/mapper.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -682,10 +682,9 @@ std::string InstantiateTemplate(const clang::Expr *expr, unsigned n) {
if (!rule) {
return text;
}
for (auto &ty : subs) {
if (ty) {
ty = mapTypeStringRecursive(*ty);
}
auto &ty = subs.at(n - 1);
if (ty) {
ty = mapTypeStringRecursive(*ty);
}
return instantiateTgt(subs, text);
}
Expand Down
4 changes: 4 additions & 0 deletions cpp2rust/converter/models/converter_refcount.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1287,6 +1287,10 @@ void ConverterRefCount::ConvertFunctionToFunctionPointer(
computed_expr_type_ = ComputedExprType::FreshPointer;
}

std::string ConverterRefCount::ConvertFnPtrPlaceholder(clang::Expr *arg) {
return ConvertFnPtrCallee(arg);
}

void ConverterRefCount::ConvertEqualsNullPtr(clang::Expr *expr) {
StrCat('(');
Convert(expr);
Expand Down
2 changes: 2 additions & 0 deletions cpp2rust/converter/models/converter_refcount.h
Original file line number Diff line number Diff line change
Expand Up @@ -103,6 +103,8 @@ class ConverterRefCount final : public Converter {
void
ConvertFunctionToFunctionPointer(const clang::FunctionDecl *fn_decl) override;

std::string ConvertFnPtrPlaceholder(clang::Expr *arg) override;

// FnPtr does not implement Copy
bool FunctionPointerImplementsCopy() const override { return false; }

Expand Down
32 changes: 32 additions & 0 deletions libcc2rs/src/callable.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
// Copyright (c) 2022-present INESC-ID.
// Distributed under the MIT license that can be found in the LICENSE file.

macro_rules! callable {
($name:ident; $($a:ident: $A:ident),*) => {
pub trait $name<$($A,)* R> {
fn call(&self, $($a: $A),*) -> R;
}

impl<F, $($A,)* R> $name<$($A,)* R> for F
where
F: Fn($($A),*) -> R,
{
#[inline]
fn call(&self, $($a: $A),*) -> R {
self($($a),*)
}
}

impl<$($A,)* R> $name<$($A,)* R> for unsafe fn($($A),*) -> R {
#[inline]
fn call(&self, $($a: $A),*) -> R {
unsafe { self($($a),*) }
}
}
};
}

callable!(Callable0;);
callable!(Callable1; a1: A1);
callable!(Callable2; a1: A1, a2: A2);
callable!(Callable3; a1: A1, a2: A2, a3: A3);
3 changes: 3 additions & 0 deletions libcc2rs/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,9 @@ pub use libc_shims::*;
mod fn_ptr;
pub use fn_ptr::FnPtr;

mod callable;
pub use callable::*;

mod inc;
pub use inc::*;

Expand Down
19 changes: 3 additions & 16 deletions rules/algorithm/src.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@

struct T2 {
friend bool operator<(T2 a, T2 b) { return false; }
bool operator()(const T2 &, const T2 &) const;
};

struct T1 {
Expand Down Expand Up @@ -91,14 +92,7 @@ template <class T1, class T2> T1 f3(T1 first, T1 last, const T2 &value) {
return std::find(first, last, value);
}

// TODO
auto lambda = [](const T2 &a, const T2 &b) { return false; };
void f6(T1 first, T1 last, decltype(lambda) comp) {
return std::stable_sort(first, last, comp);
}

template <typename T1, typename T2>
void f7(T1 first, T1 last, bool (*comp)(const T2 &, const T2 &)) {
void f6(T1 first, T1 last, T2 comp) {
return std::stable_sort(first, last, comp);
}

Expand Down Expand Up @@ -126,14 +120,7 @@ std::ostream_iterator<char> f13(std::string::iterator a0,
return std::copy(a0, a1, a2);
}

// TODO
auto lambda_nref = [](T2 a, T2 b) { return false; };
void f14(T1 *first, T1 *last, decltype(lambda_nref) comp) {
return std::stable_sort(first, last, comp);
}

template <typename T1, typename T2>
void f15(T1 *first, T1 *last, bool (*comp)(T2, T2)) {
void f14(T1 *first, T1 *last, T2 comp) {
return std::stable_sort(first, last, comp);
}

Expand Down
23 changes: 4 additions & 19 deletions rules/algorithm/tgt_refcount.rs
Original file line number Diff line number Diff line change
Expand Up @@ -38,16 +38,9 @@ fn f3<T1: PartialEq + Clone + ByteRepr>(a0: Ptr<T1>, a1: Ptr<T1>, a2: T1) -> Ptr

fn f6<T1: Ord + Clone, T2>(a0: Ptr<T1>, a1: Ptr<T1>, a2: T2)
where
T2: FnMut(Ptr<T1>, Ptr<T1>) -> bool,
T2: Callable2<Ptr<T1>, Ptr<T1>, bool>,
{
a0.sort_with_cmp(a1.get_offset(), a2)
}

fn f7<T1: Ord + Clone, T2>(a0: Ptr<T1>, a1: Ptr<T1>, a2: T2)
where
T2: FnMut(Ptr<T1>, Ptr<T1>) -> bool,
{
a0.sort_with_cmp(a1.get_offset(), a2)
a0.sort_with_cmp(a1.get_offset(), |x, y| a2.call(x, y))
}

fn f8<T1: PartialOrd + Clone + ByteRepr>(a0: Ptr<T1>, a1: Ptr<T1>) -> Ptr<T1> {
Expand Down Expand Up @@ -109,17 +102,9 @@ fn f13(a0: Ptr<u8>, a1: Ptr<u8>, a2: &mut ::std::fs::File) -> ::std::fs::File {

fn f14<T1: Ord + Clone + ByteRepr, T2>(a0: Ptr<T1>, a1: Ptr<T1>, a2: T2)
where
T2: Fn(T1, T1) -> bool,
{
let fun = |x: Ptr<T1>, y: Ptr<T1>| a2((x.read()).clone(), (y.read()).clone());
a0.sort_with_cmp(a1.get_offset(), fun)
}

fn f15<T1: Ord + Clone + ByteRepr, T2>(a0: Ptr<T1>, a1: Ptr<T1>, a2: T2)
where
T2: Fn(T1, T1) -> bool,
T2: Callable2<T1, T1, bool>,
{
let fun = |x: Ptr<T1>, y: Ptr<T1>| a2((x.read()).clone(), (y.read()).clone());
let fun = |x: Ptr<T1>, y: Ptr<T1>| a2.call((x.read()).clone(), (y.read()).clone());
a0.sort_with_cmp(a1.get_offset(), fun)
}

Expand Down
49 changes: 9 additions & 40 deletions rules/algorithm/tgt_unsafe.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
// Copyright (c) 2022-present INESC-ID.
// Distributed under the MIT license that can be found in the LICENSE file.

use libcc2rs::*;
use std::io::{Seek, Write};

unsafe fn f1<T1: Ord>(a0: *mut T1, a1: *mut T1) {
Expand All @@ -27,31 +28,15 @@ unsafe fn f3<T1: PartialEq>(a0: *mut T1, a1: *mut T1, a2: T1) -> *mut T1 {
it
}

unsafe fn f6<T1: Ord, T2>(a0: *mut T1, a1: *mut T1, a2: &mut T2)
unsafe fn f6<T1: Ord, T2>(a0: *mut T1, a1: *mut T1, a2: T2)
where
T2: FnMut(&T1, &T1) -> bool,
T2: Callable2<*const T1, *const T1, bool>,
{
let len = a1.offset_from(a0) as usize;
::std::slice::from_raw_parts_mut(a0, len).sort_by(|x, y| {
if (a2)(x, y) {
if a2.call(x as *const _, y as *const _) {
std::cmp::Ordering::Less
} else if (a2)(y, x) {
std::cmp::Ordering::Greater
} else {
std::cmp::Ordering::Equal
}
})
}

unsafe fn f7<T1: Ord, T2>(a0: *mut T1, a1: *mut T1, a2: &mut T2)
where
T2: FnMut(&T1, &T1) -> bool,
{
let len = a1.offset_from(a0) as usize;
::std::slice::from_raw_parts_mut(a0, len).sort_by(|x, y| {
if (a2)(x, y) {
std::cmp::Ordering::Less
} else if (a2)(y, x) {
} else if a2.call(y as *const _, x as *const _) {
std::cmp::Ordering::Greater
} else {
std::cmp::Ordering::Equal
Expand Down Expand Up @@ -113,31 +98,15 @@ unsafe fn f13(
a2.try_clone().unwrap()
}

unsafe fn f14<T1: Ord + Copy, T2>(a0: *mut T1, a1: *mut T1, a2: &mut T2)
where
T2: FnMut(T1, T1) -> bool,
{
let len = a1.offset_from(a0) as usize;
::std::slice::from_raw_parts_mut(a0, len).sort_by(|x, y| {
if (a2)(*x, *y) {
std::cmp::Ordering::Less
} else if (a2)(*y, *x) {
std::cmp::Ordering::Greater
} else {
std::cmp::Ordering::Equal
}
})
}

unsafe fn f15<T1: Ord + Copy, T2>(a0: *mut T1, a1: *mut T1, a2: &mut T2)
unsafe fn f14<T1: Ord + Copy, T2>(a0: *mut T1, a1: *mut T1, a2: T2)
where
T2: FnMut(T1, T1) -> bool,
T2: Callable2<T1, T1, bool>,
{
let len = a1.offset_from(a0) as usize;
::std::slice::from_raw_parts_mut(a0, len).sort_by(|x, y| {
if (a2)(*x, *y) {
if a2.call(*x, *y) {
std::cmp::Ordering::Less
} else if (a2)(*y, *x) {
} else if a2.call(*y, *x) {
std::cmp::Ordering::Greater
} else {
std::cmp::Ordering::Equal
Expand Down
2 changes: 1 addition & 1 deletion tests/unit/out/refcount/fn_ptr_stable_sort.rs
Original file line number Diff line number Diff line change
Expand Up @@ -61,7 +61,7 @@ fn main_0() -> i32 {
});
(v.as_pointer() as Ptr<Item>).sort_with_cmp(
(v.as_pointer() as Ptr<Item>).to_end().get_offset(),
Compare_0,
|x, y| Compare_0.call(x, y),
);
assert!(
((*(*(v.as_pointer() as Ptr<Item>)
Expand Down
3 changes: 2 additions & 1 deletion tests/unit/out/refcount/stable_sort.rs
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,8 @@ fn main_0() -> i32 {
let x: Value<i32> = Rc::new(RefCell::new(x));
let y: Value<i32> = Rc::new(RefCell::new(y));
return ((*x.borrow()) < (*y.borrow()));
})((x.read()).clone(), (y.read()).clone())
})
.call((x.read()).clone(), (y.read()).clone())
};
(arr1.as_pointer() as Ptr<i32>).sort_with_cmp(
(arr1.as_pointer() as Ptr<i32>)
Expand Down
8 changes: 6 additions & 2 deletions tests/unit/out/unsafe/fn_ptr_stable_sort.rs
Original file line number Diff line number Diff line change
Expand Up @@ -28,9 +28,13 @@ unsafe fn main_0() -> i32 {
{
let len = v.as_mut_ptr().add(v.len()).offset_from(v.as_mut_ptr()) as usize;
::std::slice::from_raw_parts_mut(v.as_mut_ptr(), len).sort_by(|x, y| {
if (Compare_0)(x, y) {
if (Compare_0 as unsafe fn(*const Item, *const Item) -> bool)
.call(x as *const _, y as *const _)
{
std::cmp::Ordering::Less
} else if (Compare_0)(y, x) {
} else if (Compare_0 as unsafe fn(*const Item, *const Item) -> bool)
.call(y as *const _, x as *const _)
{
std::cmp::Ordering::Greater
} else {
std::cmp::Ordering::Equal
Expand Down
15 changes: 12 additions & 3 deletions tests/unit/out/unsafe/qsort_bsearch.rs
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,10 @@ unsafe fn main_0() -> i32 {
Some(std::mem::transmute::<
*const (),
unsafe extern "C" fn(*const ::libc::c_void, *const ::libc::c_void) -> i32,
>(cmp_int_0 as *const ())),
>(
(cmp_int_0 as unsafe fn(*const ::libc::c_void, *const ::libc::c_void) -> i32)
as *const (),
)),
);
let mut i: i32 = 0;
'loop_: while ((((i) < (7)) as i32) != 0) {
Expand All @@ -41,7 +44,10 @@ unsafe fn main_0() -> i32 {
Some(std::mem::transmute::<
*const (),
unsafe extern "C" fn(*const ::libc::c_void, *const ::libc::c_void) -> i32,
>(cmp_int_0 as *const ())),
>(
(cmp_int_0 as unsafe fn(*const ::libc::c_void, *const ::libc::c_void) -> i32)
as *const (),
)),
) as *mut i32);
assert!((((!((hit).is_null())) as i32) != 0));
assert!(((((*hit) == (7)) as i32) != 0));
Expand All @@ -54,7 +60,10 @@ unsafe fn main_0() -> i32 {
Some(std::mem::transmute::<
*const (),
unsafe extern "C" fn(*const ::libc::c_void, *const ::libc::c_void) -> i32,
>(cmp_int_0 as *const ())),
>(
(cmp_int_0 as unsafe fn(*const ::libc::c_void, *const ::libc::c_void) -> i32)
as *const (),
)),
) as *mut i32);
assert!(((((miss).is_null()) as i32) != 0));
return 0;
Expand Down
Loading
Loading