Skip to content

Commit edf2c9b

Browse files
Copilotnunoplopes
andauthored
Insert missing pointer-type cast for call arguments when Clang omits an implicit cast node
Co-authored-by: nunoplopes <2998477+nunoplopes@users.noreply.github.com>
1 parent 8f5512f commit edf2c9b

6 files changed

Lines changed: 50 additions & 3 deletions

File tree

‎cpp2rust/converter/converter.cpp‎

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1875,6 +1875,29 @@ void Converter::ConvertParamTy(clang::QualType param_type, clang::Expr *expr) {
18751875
} else {
18761876
ConvertVarInit(param_type, expr);
18771877
}
1878+
ConvertParamTyPointerCastIfNeeded(param_type, expr);
1879+
}
1880+
1881+
void Converter::ConvertParamTyPointerCastIfNeeded(clang::QualType param_type,
1882+
clang::Expr *expr) {
1883+
if (!param_type->isPointerType() || !expr->getType()->isPointerType() ||
1884+
IsVaListType(param_type) || IsVaListType(expr->getType())) {
1885+
return;
1886+
}
1887+
switch (GetConstCastType(param_type->getPointeeType(),
1888+
expr->getType()->getPointeeType())) {
1889+
case ConstCastType::MutableToConst:
1890+
StrCat(".cast_const()");
1891+
return;
1892+
case ConstCastType::ConstToMutable:
1893+
StrCat(".cast_mut()");
1894+
return;
1895+
default:
1896+
break;
1897+
}
1898+
if (!IsCastRedundantInRust(expr, param_type)) {
1899+
ConvertCast(param_type);
1900+
}
18781901
}
18791902

18801903
void Converter::EmitHoistedArgs(CallInfo &info) {

‎cpp2rust/converter/converter.h‎

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -282,6 +282,15 @@ class Converter : public clang::RecursiveASTVisitor<Converter> {
282282

283283
void ConvertParamTy(clang::QualType param_type, clang::Expr *expr);
284284

285+
// Emits a pointer-type adjustment (const/mut fixup or reinterpret cast)
286+
// after `expr` has been converted, for cases where the argument's Rust
287+
// pointee type differs from the parameter's Rust pointee type even though
288+
// Clang did not insert an implicit cast node for the call argument (e.g.
289+
// when two C types are canonically identical, such as `size_t` and
290+
// `unsigned long`, but map to different Rust types).
291+
virtual void ConvertParamTyPointerCastIfNeeded(clang::QualType param_type,
292+
clang::Expr *expr);
293+
285294
void EmitHoistedArgs(CallInfo &info);
286295

287296
void EmitArgList(const CallInfo &info);

‎cpp2rust/converter/models/converter_refcount.cpp‎

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2596,6 +2596,18 @@ std::string ConverterRefCount::ConvertPointeeType(clang::QualType ptr_type) {
25962596
return std::string(Trim(str));
25972597
}
25982598

2599+
void ConverterRefCount::ConvertParamTyPointerCastIfNeeded(
2600+
clang::QualType param_type, clang::Expr *expr) {
2601+
if (!param_type->isPointerType() || !expr->getType()->isPointerType() ||
2602+
IsVaListType(param_type) || IsVaListType(expr->getType())) {
2603+
return;
2604+
}
2605+
auto dest_type = ConvertPointeeType(param_type);
2606+
if (dest_type != ConvertPointeeType(expr->getType())) {
2607+
StrCat(std::format(".reinterpret_cast::<{}>()", dest_type));
2608+
}
2609+
}
2610+
25992611
bool ConverterRefCount::ShouldConvertMethod(const clang::CXXMethodDecl *decl) {
26002612
if (clang::isa<clang::CXXDestructorDecl>(decl)) {
26012613
return IsMethodOnPtr(decl);

‎cpp2rust/converter/models/converter_refcount.h‎

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -263,6 +263,9 @@ class ConverterRefCount final : public Converter {
263263
std::string ConvertPtrType(clang::QualType type);
264264
std::string ConvertPointeeType(clang::QualType ptr_type) override;
265265

266+
void ConvertParamTyPointerCastIfNeeded(clang::QualType param_type,
267+
clang::Expr *expr) override;
268+
266269
std::string ConvertSubscriptIndex(clang::Expr *idx);
267270

268271
std::string GetSafeTypeAsString(clang::QualType qual_type) const;

‎tests/unit/out/refcount/implicit_ptr_cast.rs‎

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@ pub fn main() {
1515
}
1616
fn main_0() -> i32 {
1717
let x: Value<usize> = Rc::new(RefCell::new(0_usize));
18-
({ write_ulong_0((x.as_pointer().reinterpret_cast::<u64>())) });
18+
({ write_ulong_0((x.as_pointer()).reinterpret_cast::<u64>()) });
1919
assert!(((((*x.borrow()) == 42_usize) as i32) != 0));
2020
return 0;
2121
}

‎tests/unit/out/unsafe/implicit_ptr_cast.rs‎

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@ use std::collections::BTreeMap;
66
use std::io::{Read, Seek, Write};
77
use std::os::fd::{AsFd, FromRawFd, IntoRawFd};
88
use std::rc::Rc;
9-
pub unsafe fn write_ulong_0(p: *mut u64) {
9+
pub unsafe fn write_ulong_0(mut p: *mut u64) {
1010
(*p) = 42_u64;
1111
}
1212
pub fn main() {
@@ -16,7 +16,7 @@ pub fn main() {
1616
}
1717
unsafe fn main_0() -> i32 {
1818
let mut x: usize = 0_usize;
19-
(unsafe { write_ulong_0((&mut x as *mut usize as *mut u64)) });
19+
(unsafe { write_ulong_0((&mut x as *mut usize) as *mut u64) });
2020
assert!(((((x) == (42_usize)) as i32) != 0));
2121
return 0;
2222
}

0 commit comments

Comments
 (0)