Skip to content

Commit 8a9145e

Browse files
committed
Add isize conversion for enum values used as subscript
1 parent 5907a12 commit 8a9145e

5 files changed

Lines changed: 90 additions & 3 deletions

File tree

cpp2rust/converter/models/converter_refcount.cpp

Lines changed: 11 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -2154,7 +2154,7 @@ bool ConverterRefCount::ConvertCXXOperatorCallExpr(
21542154
pending_deref_.set(std::format("({} as {}).offset({})",
21552155
ConvertObject(expr->getArg(0)),
21562156
ConvertPtrType(expr->getArg(0)->getType()),
2157-
ConvertRValue(expr->getArg(1))),
2157+
ConvertSubscriptIndex(expr->getArg(1))),
21582158
expr);
21592159
break;
21602160
}
@@ -2174,7 +2174,7 @@ bool ConverterRefCount::ConvertCXXOperatorCallExpr(
21742174
StrCat(std::format("({} as {}).offset({})",
21752175
ConvertObject(expr->getArg(0)),
21762176
ConvertPtrType(expr->getArg(0)->getType()),
2177-
ConvertRValue(expr->getArg(1))));
2177+
ConvertSubscriptIndex(expr->getArg(1))));
21782178

21792179
if (is_inner_boxed) {
21802180
StrCat(GetPointerDerefSuffix(expr->getType()), ".as_pointer()");
@@ -2209,6 +2209,14 @@ void ConverterRefCount::ConvertFunctionParameters(clang::FunctionDecl *decl) {
22092209
}
22102210
}
22112211

2212+
std::string ConverterRefCount::ConvertSubscriptIndex(clang::Expr *idx) {
2213+
auto str = ConvertRValue(idx);
2214+
if (idx->getType()->isEnumeralType()) {
2215+
return std::format("({}) as isize", str);
2216+
}
2217+
return str;
2218+
}
2219+
22122220
void ConverterRefCount::ConvertArraySubscript(clang::Expr *base,
22132221
clang::Expr *idx,
22142222
clang::QualType type) {
@@ -2225,7 +2233,7 @@ void ConverterRefCount::ConvertArraySubscript(clang::Expr *base,
22252233
StrCat(std::format("({} as {}).offset({})",
22262234
ToString(base->IgnoreImplicit()),
22272235
ConvertPtrType(base->IgnoreImplicit()->getType()),
2228-
ConvertRValue(idx)));
2236+
ConvertSubscriptIndex(idx)));
22292237

22302238
if (is_inner_boxed) {
22312239
StrCat(GetPointerDerefSuffix(type), ".as_pointer()");

cpp2rust/converter/models/converter_refcount.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -242,6 +242,8 @@ class ConverterRefCount final : public Converter {
242242
std::string ConvertPtrType(clang::QualType type);
243243
std::string ConvertPointeeType(clang::QualType ptr_type) override;
244244

245+
std::string ConvertSubscriptIndex(clang::Expr *idx);
246+
245247
std::string GetSafeTypeAsString(clang::QualType qual_type) const;
246248

247249
/// The kind of conversion that should be performed.

tests/unit/enum_int_interop_c.c

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -140,5 +140,16 @@ int main() {
140140
assert(entries[2].color == BLUE);
141141
assert(entries[2].opt == OPT_C);
142142

143+
const char *names[] = {"red", "green", "blue"};
144+
enum Color idx = GREEN;
145+
assert(names[idx][0] == 'g');
146+
assert(entries[idx].opt == OPT_A);
147+
assert(names[global_tag][0] == 'b');
148+
149+
const char **pp = &names[idx];
150+
assert((*pp)[0] == 'g');
151+
struct Entry *pe = &entries[idx];
152+
assert(pe->opt == OPT_A);
153+
143154
return 0;
144155
}

tests/unit/out/refcount/enum_int_interop_c.rs

Lines changed: 45 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -319,5 +319,50 @@ fn main_0() -> i32 {
319319
== ((Option::OPT_C as i32) as u32)) as i32)
320320
!= 0)
321321
);
322+
let names: Value<Box<[Ptr<u8>]>> = Rc::new(RefCell::new(Box::new([
323+
Ptr::from_string_literal(b"red"),
324+
Ptr::from_string_literal(b"green"),
325+
Ptr::from_string_literal(b"blue"),
326+
])));
327+
let idx: Value<Color> = Rc::new(RefCell::new(Color::GREEN));
328+
assert!(
329+
((((((*names.borrow())[(*idx.borrow()) as usize]
330+
.offset((0) as isize)
331+
.read()) as i32)
332+
== ('g' as i32)) as i32)
333+
!= 0)
334+
);
335+
assert!(
336+
(((((*(*entries_3.with(Value::clone).borrow())[(*idx.borrow()) as usize]
337+
.opt
338+
.borrow()) as u32)
339+
== ((Option::OPT_A as i32) as u32)) as i32)
340+
!= 0)
341+
);
342+
assert!(
343+
((((((*names.borrow())[(*global_tag_2.with(Value::clone).borrow()) as usize]
344+
.offset((0) as isize)
345+
.read()) as i32)
346+
== ('b' as i32)) as i32)
347+
!= 0)
348+
);
349+
let pp: Value<Ptr<Ptr<u8>>> = Rc::new(RefCell::new(
350+
((names.as_pointer() as Ptr<Ptr<u8>>).offset((*idx.borrow()) as isize)),
351+
));
352+
assert!(
353+
(((((((*pp.borrow()).read()).offset((0) as isize).read()) as i32) == ('g' as i32)) as i32)
354+
!= 0)
355+
);
356+
let pe: Value<Ptr<Entry>> = Rc::new(RefCell::new(
357+
((entries_3.with(Value::clone).as_pointer() as Ptr<Entry>)
358+
.offset((*idx.borrow()) as isize)),
359+
));
360+
assert!(
361+
((({
362+
let _lhs = ((*(*(*pe.borrow()).upgrade().deref()).opt.borrow()) as u32).clone();
363+
_lhs == ((Option::OPT_A as i32) as u32)
364+
}) as i32)
365+
!= 0)
366+
);
322367
return 0;
323368
}

tests/unit/out/unsafe/enum_int_interop_c.rs

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -220,5 +220,26 @@ unsafe fn main_0() -> i32 {
220220
assert!(
221221
((((entries_3[(2) as usize].opt as u32) == ((Option::OPT_C as i32) as u32)) as i32) != 0)
222222
);
223+
let mut names: [*const libc::c_char; 3] = [
224+
(c"red".as_ptr().cast_mut()).cast_const(),
225+
(c"green".as_ptr().cast_mut()).cast_const(),
226+
(c"blue".as_ptr().cast_mut()).cast_const(),
227+
];
228+
let mut idx: Color = Color::GREEN;
229+
assert!(
230+
(((((*names[(idx) as usize].offset((0) as isize)) as i32) == ('g' as i32)) as i32) != 0)
231+
);
232+
assert!(
233+
((((entries_3[(idx) as usize].opt as u32) == ((Option::OPT_A as i32) as u32)) as i32) != 0)
234+
);
235+
assert!(
236+
(((((*names[(global_tag_2) as usize].offset((0) as isize)) as i32) == ('b' as i32))
237+
as i32)
238+
!= 0)
239+
);
240+
let mut pp: *mut *const libc::c_char = (&mut names[(idx) as usize] as *mut *const libc::c_char);
241+
assert!((((((*(*pp).offset((0) as isize)) as i32) == ('g' as i32)) as i32) != 0));
242+
let mut pe: *mut Entry = (&mut entries_3[(idx) as usize] as *mut Entry);
243+
assert!((((((*pe).opt as u32) == ((Option::OPT_A as i32) as u32)) as i32) != 0));
223244
return 0;
224245
}

0 commit comments

Comments
 (0)