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
5 changes: 5 additions & 0 deletions cpp2rust/converter/converter.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2892,6 +2892,7 @@ bool Converter::VisitEnumDecl(clang::EnumDecl *decl) {
StrCat("}");

AddFromImpl(decl);
AddIncDecImpls(decl);
return false;
}

Expand All @@ -2913,6 +2914,10 @@ void Converter::AddFromImpl(clang::EnumDecl *decl) {
StrCat(std::format("_ => panic!(\"invalid {} value: {{}}\", n),", name));
}

void Converter::AddIncDecImpls(clang::EnumDecl *decl) {
StrCat(std::format("libcc2rs::impl_enum_inc_dec!({});", GetRecordName(decl)));
}

bool Converter::VisitCXXDefaultArgExpr(clang::CXXDefaultArgExpr *expr) {
if (expr->getType()->isPointerType()) {
StrCat(keyword_default_);
Expand Down
2 changes: 2 additions & 0 deletions cpp2rust/converter/converter.h
Original file line number Diff line number Diff line change
Expand Up @@ -315,6 +315,8 @@ class Converter : public clang::RecursiveASTVisitor<Converter> {

virtual void AddFromImpl(clang::EnumDecl *decl);

virtual void AddIncDecImpls(clang::EnumDecl *decl);

virtual bool VisitCXXDefaultArgExpr(clang::CXXDefaultArgExpr *expr);

virtual bool VisitLambdaExpr(clang::LambdaExpr *expr);
Expand Down
32 changes: 32 additions & 0 deletions libcc2rs/src/inc.rs
Original file line number Diff line number Diff line change
Expand Up @@ -124,6 +124,38 @@ impl<T> UnsafePrefixInc for *mut T {
}
}

#[macro_export]
macro_rules! impl_enum_inc_dec {
($t:ty) => {
impl PostfixInc for $t {
fn postfix_inc(&mut self) -> Self {
let copy = *self;
*self = <$t>::from(*self as i32 + 1);
copy
}
}
impl PrefixInc for $t {
fn prefix_inc(&mut self) -> Self {
*self = <$t>::from(*self as i32 + 1);
*self
}
}
impl PostfixDec for $t {
fn postfix_dec(&mut self) -> Self {
let copy = *self;
*self = <$t>::from(*self as i32 - 1);
copy
}
}
impl PrefixDec for $t {
fn prefix_dec(&mut self) -> Self {
*self = <$t>::from(*self as i32 - 1);
*self
}
}
};
}

#[cfg(test)]
mod tests {
use super::*;
Expand Down
9 changes: 9 additions & 0 deletions tests/ub/enum_out_of_range_increment.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
// panic

enum color { RED, GREEN, BLUE };

int main() {
enum color c = BLUE;
c++;
return c == RED ? 0 : 1;
}
1 change: 1 addition & 0 deletions tests/ub/out/refcount/enum_out_of_range_cast.rs
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@ impl From<i32> for Color {
}
}
}
libcc2rs::impl_enum_inc_dec!(Color);
pub fn main() {
std::process::exit(main_0());
}
Expand Down
38 changes: 38 additions & 0 deletions tests/ub/out/refcount/enum_out_of_range_increment.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
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, Copy, PartialEq, Debug, Default)]
enum color {
#[default]
RED = 0,
GREEN = 1,
BLUE = 2,
}
impl From<i32> for color {
fn from(n: i32) -> color {
match n {
0 => color::RED,
1 => color::GREEN,
2 => color::BLUE,
_ => panic!("invalid color value: {}", n),
}
}
}
libcc2rs::impl_enum_inc_dec!(color);
pub fn main() {
std::process::exit(main_0());
}
fn main_0() -> i32 {
let c: Value<color> = Rc::new(RefCell::new(color::BLUE));
(*c.borrow_mut()).postfix_inc();
return if (((((*c.borrow()) as u32) == ((color::RED as i32) as u32)) as i32) != 0) {
0
} else {
1
};
}
1 change: 1 addition & 0 deletions tests/ub/out/unsafe/enum_out_of_range_cast.rs
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@ impl From<i32> for Color {
}
}
}
libcc2rs::impl_enum_inc_dec!(Color);
pub fn main() {
unsafe {
std::process::exit(main_0() as i32);
Expand Down
40 changes: 40 additions & 0 deletions tests/ub/out/unsafe/enum_out_of_range_increment.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
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;
#[derive(Clone, Copy, PartialEq, Debug, Default)]
enum color {
#[default]
RED = 0,
GREEN = 1,
BLUE = 2,
}
impl From<i32> for color {
fn from(n: i32) -> color {
match n {
0 => color::RED,
1 => color::GREEN,
2 => color::BLUE,
_ => panic!("invalid color value: {}", n),
}
}
}
libcc2rs::impl_enum_inc_dec!(color);
pub fn main() {
unsafe {
std::process::exit(main_0() as i32);
}
}
unsafe fn main_0() -> i32 {
let mut c: color = color::BLUE;
c.postfix_inc();
return if ((((c as u32) == ((color::RED as i32) as u32)) as i32) != 0) {
0
} else {
1
};
}
18 changes: 18 additions & 0 deletions tests/unit/enum_increment.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
#include <assert.h>

enum color { RED, GREEN, BLUE, COLOR_LAST };

int main() {
int count = 0;
for (enum color c = RED; c < COLOR_LAST; c++) {
count++;
}
assert(count == 3);

enum color c = RED;
assert(c++ == RED);
assert(++c == BLUE);
assert(c-- == BLUE);
assert(--c == RED);
return 0;
}
7 changes: 6 additions & 1 deletion tests/unit/out/refcount/anonymous_enum.rs
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ impl From<i32> for anon_enum_3 {
}
}
}
libcc2rs::impl_enum_inc_dec!(anon_enum_3);
#[derive(Clone, Copy, PartialEq, Debug, Default)]
enum anon_enum_11 {
#[default]
Expand All @@ -36,6 +37,7 @@ impl From<i32> for anon_enum_11 {
}
}
}
libcc2rs::impl_enum_inc_dec!(anon_enum_11);
#[derive(Default)]
pub struct S {
pub a: Value<i32>,
Expand Down Expand Up @@ -73,6 +75,7 @@ impl From<i32> for TdEnum {
}
}
}
libcc2rs::impl_enum_inc_dec!(TdEnum);
#[derive(Clone, Copy, PartialEq, Debug, Default)]
enum anon_enum_24 {
#[default]
Expand All @@ -88,6 +91,7 @@ impl From<i32> for anon_enum_24 {
}
}
}
libcc2rs::impl_enum_inc_dec!(anon_enum_24);
#[derive(Default)]
pub struct WithAnonField {
pub a: Value<i32>,
Expand Down Expand Up @@ -121,7 +125,8 @@ fn main_0() -> i32 {
_ => panic!("invalid anon_enum_31 value: {}", n),
}
}
};
}
libcc2rs::impl_enum_inc_dec!(anon_enum_31);
assert!(((anon_enum_3::FIRST_A as i32) != (anon_enum_3::FIRST_B as i32)));
assert!(((anon_enum_11::SECOND_A as i32) != (anon_enum_11::SECOND_B as i32)));
assert!(((anon_enum_31::THIRD_A as i32) != (anon_enum_31::THIRD_B as i32)));
Expand Down
7 changes: 6 additions & 1 deletion tests/unit/out/refcount/anonymous_enum_c.rs
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ impl From<i32> for anon_enum_3 {
}
}
}
libcc2rs::impl_enum_inc_dec!(anon_enum_3);
#[derive(Clone, Copy, PartialEq, Debug, Default)]
enum anon_enum_11 {
#[default]
Expand All @@ -36,6 +37,7 @@ impl From<i32> for anon_enum_11 {
}
}
}
libcc2rs::impl_enum_inc_dec!(anon_enum_11);
#[derive(Default)]
pub struct S {
pub a: Value<i32>,
Expand Down Expand Up @@ -65,6 +67,7 @@ impl From<i32> for TdEnum {
}
}
}
libcc2rs::impl_enum_inc_dec!(TdEnum);
#[derive(Clone, Copy, PartialEq, Debug, Default)]
enum anon_enum_24 {
#[default]
Expand All @@ -80,6 +83,7 @@ impl From<i32> for anon_enum_24 {
}
}
}
libcc2rs::impl_enum_inc_dec!(anon_enum_24);
#[derive(Default)]
pub struct WithAnonField {
pub a: Value<i32>,
Expand All @@ -104,7 +108,8 @@ fn main_0() -> i32 {
_ => panic!("invalid anon_enum_31 value: {}", n),
}
}
};
}
libcc2rs::impl_enum_inc_dec!(anon_enum_31);
assert!(((((anon_enum_3::FIRST_A as i32) != (anon_enum_3::FIRST_B as i32)) as i32) != 0));
assert!(((((anon_enum_11::SECOND_A as i32) != (anon_enum_11::SECOND_B as i32)) as i32) != 0));
assert!(((((anon_enum_31::THIRD_A as i32) != (anon_enum_31::THIRD_B as i32)) as i32) != 0));
Expand Down
1 change: 1 addition & 0 deletions tests/unit/out/refcount/bool_condition_enum.rs
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@ impl From<i32> for Code {
}
}
}
libcc2rs::impl_enum_inc_dec!(Code);
pub fn main() {
std::process::exit(main_0());
}
Expand Down
1 change: 1 addition & 0 deletions tests/unit/out/refcount/bool_condition_enum_c.rs
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@ impl From<i32> for Code {
}
}
}
libcc2rs::impl_enum_inc_dec!(Code);
pub fn main() {
std::process::exit(main_0());
}
Expand Down
1 change: 1 addition & 0 deletions tests/unit/out/refcount/bool_condition_logical.rs
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@ impl From<i32> for Code {
}
}
}
libcc2rs::impl_enum_inc_dec!(Code);
thread_local!(
pub static side_effect: Value<i32> = Rc::new(RefCell::new(0));
);
Expand Down
1 change: 1 addition & 0 deletions tests/unit/out/refcount/bool_condition_logical_c.rs
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@ impl From<i32> for Code {
}
}
}
libcc2rs::impl_enum_inc_dec!(Code);
thread_local!(
pub static side_effect: Value<i32> = Rc::new(RefCell::new(0));
);
Expand Down
1 change: 1 addition & 0 deletions tests/unit/out/refcount/c_struct.rs
Original file line number Diff line number Diff line change
Expand Up @@ -52,6 +52,7 @@ impl From<i32> for Color {
}
}
}
libcc2rs::impl_enum_inc_dec!(Color);
#[derive(Default)]
pub struct Inner {
pub a: Value<i32>,
Expand Down
54 changes: 54 additions & 0 deletions tests/unit/out/refcount/enum_increment.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
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, Copy, PartialEq, Debug, Default)]
enum color {
#[default]
RED = 0,
GREEN = 1,
BLUE = 2,
COLOR_LAST = 3,
}
impl From<i32> for color {
fn from(n: i32) -> color {
match n {
0 => color::RED,
1 => color::GREEN,
2 => color::BLUE,
3 => color::COLOR_LAST,
_ => panic!("invalid color value: {}", n),
}
}
}
libcc2rs::impl_enum_inc_dec!(color);
pub fn main() {
std::process::exit(main_0());
}
fn main_0() -> i32 {
let count: Value<i32> = Rc::new(RefCell::new(0));
let c: Value<color> = Rc::new(RefCell::new(color::RED));
'loop_: while (((((*c.borrow()) as u32) < ((color::COLOR_LAST as i32) as u32)) as i32) != 0) {
(*count.borrow_mut()).postfix_inc();
(*c.borrow_mut()).postfix_inc();
}
assert!(((((*count.borrow()) == 3) as i32) != 0));
let c: Value<color> = Rc::new(RefCell::new(color::RED));
assert!(
(((((*c.borrow_mut()).postfix_inc() as u32) == ((color::RED as i32) as u32)) as i32) != 0)
);
assert!(
(((((*c.borrow_mut()).prefix_inc() as u32) == ((color::BLUE as i32) as u32)) as i32) != 0)
);
assert!(
(((((*c.borrow_mut()).postfix_dec() as u32) == ((color::BLUE as i32) as u32)) as i32) != 0)
);
assert!(
(((((*c.borrow_mut()).prefix_dec() as u32) == ((color::RED as i32) as u32)) as i32) != 0)
);
return 0;
}
3 changes: 3 additions & 0 deletions tests/unit/out/refcount/enum_int_interop.rs
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@ impl From<i32> for Color {
}
}
}
libcc2rs::impl_enum_inc_dec!(Color);
#[derive(Clone, Copy, PartialEq, Debug, Default)]
enum Option {
#[default]
Expand All @@ -42,6 +43,7 @@ impl From<i32> for Option {
}
}
}
libcc2rs::impl_enum_inc_dec!(Option);
#[derive(Clone, Copy, PartialEq, Debug, Default)]
enum Tag {
#[default]
Expand All @@ -59,6 +61,7 @@ impl From<i32> for Tag {
}
}
}
libcc2rs::impl_enum_inc_dec!(Tag);
#[derive(Default)]
pub struct Entry {
pub name: Value<Ptr<u8>>,
Expand Down
Loading
Loading