From 4558e895c31f938baaff6da22051bfa024a87214 Mon Sep 17 00:00:00 2001 From: Lucian Popescu Date: Tue, 26 May 2026 13:17:58 +0100 Subject: [PATCH 1/2] Add Inc and Dec traits for enums --- cpp2rust/converter/converter.cpp | 5 ++ cpp2rust/converter/converter.h | 2 + libcc2rs/src/inc.rs | 32 +++++++++++ tests/ub/enum_out_of_range_increment.c | 9 ++++ .../ub/out/refcount/enum_out_of_range_cast.rs | 1 + .../refcount/enum_out_of_range_increment.rs | 38 +++++++++++++ tests/ub/out/unsafe/enum_out_of_range_cast.rs | 1 + .../out/unsafe/enum_out_of_range_increment.rs | 40 ++++++++++++++ tests/unit/enum_increment.c | 18 +++++++ tests/unit/out/refcount/anonymous_enum.rs | 7 ++- tests/unit/out/refcount/anonymous_enum_c.rs | 7 ++- .../unit/out/refcount/bool_condition_enum.rs | 1 + .../out/refcount/bool_condition_enum_c.rs | 1 + .../out/refcount/bool_condition_logical.rs | 1 + .../out/refcount/bool_condition_logical_c.rs | 1 + tests/unit/out/refcount/c_struct.rs | 1 + tests/unit/out/refcount/enum_increment.rs | 54 +++++++++++++++++++ tests/unit/out/refcount/enum_int_interop.rs | 3 ++ tests/unit/out/refcount/enum_int_interop_c.rs | 3 ++ tests/unit/out/refcount/switch_char.rs | 1 + tests/unit/out/refcount/switch_enum.rs | 1 + .../out/refcount/va_arg_non_primitive_ptrs.rs | 1 + tests/unit/out/unsafe/anonymous_enum.rs | 7 ++- tests/unit/out/unsafe/anonymous_enum_c.rs | 7 ++- tests/unit/out/unsafe/bool_condition_enum.rs | 1 + .../unit/out/unsafe/bool_condition_enum_c.rs | 1 + .../unit/out/unsafe/bool_condition_logical.rs | 1 + .../out/unsafe/bool_condition_logical_c.rs | 1 + tests/unit/out/unsafe/c_struct.rs | 1 + tests/unit/out/unsafe/enum_increment.rs | 48 +++++++++++++++++ tests/unit/out/unsafe/enum_int_interop.rs | 3 ++ tests/unit/out/unsafe/enum_int_interop_c.rs | 3 ++ tests/unit/out/unsafe/switch_char.rs | 1 + tests/unit/out/unsafe/switch_enum.rs | 1 + .../unit/out/unsafe/union_tagged_many_arms.rs | 1 + tests/unit/out/unsafe/union_tagged_simple.rs | 1 + .../out/unsafe/union_tagged_struct_arms.rs | 1 + .../out/unsafe/union_void_ptr_sized_deref.rs | 1 + .../out/unsafe/va_arg_non_primitive_ptrs.rs | 1 + 39 files changed, 304 insertions(+), 4 deletions(-) create mode 100644 tests/ub/enum_out_of_range_increment.c create mode 100644 tests/ub/out/refcount/enum_out_of_range_increment.rs create mode 100644 tests/ub/out/unsafe/enum_out_of_range_increment.rs create mode 100644 tests/unit/enum_increment.c create mode 100644 tests/unit/out/refcount/enum_increment.rs create mode 100644 tests/unit/out/unsafe/enum_increment.rs diff --git a/cpp2rust/converter/converter.cpp b/cpp2rust/converter/converter.cpp index c291b81b..780bd7d8 100644 --- a/cpp2rust/converter/converter.cpp +++ b/cpp2rust/converter/converter.cpp @@ -2892,6 +2892,7 @@ bool Converter::VisitEnumDecl(clang::EnumDecl *decl) { StrCat("}"); AddFromImpl(decl); + AddIncDecImpls(decl); return false; } @@ -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_); diff --git a/cpp2rust/converter/converter.h b/cpp2rust/converter/converter.h index 8743067d..8d192aa7 100644 --- a/cpp2rust/converter/converter.h +++ b/cpp2rust/converter/converter.h @@ -315,6 +315,8 @@ class Converter : public clang::RecursiveASTVisitor { virtual void AddFromImpl(clang::EnumDecl *decl); + virtual void AddIncDecImpls(clang::EnumDecl *decl); + virtual bool VisitCXXDefaultArgExpr(clang::CXXDefaultArgExpr *expr); virtual bool VisitLambdaExpr(clang::LambdaExpr *expr); diff --git a/libcc2rs/src/inc.rs b/libcc2rs/src/inc.rs index b64887c5..29d3cede 100644 --- a/libcc2rs/src/inc.rs +++ b/libcc2rs/src/inc.rs @@ -124,6 +124,38 @@ impl 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::*; diff --git a/tests/ub/enum_out_of_range_increment.c b/tests/ub/enum_out_of_range_increment.c new file mode 100644 index 00000000..fe8b0adc --- /dev/null +++ b/tests/ub/enum_out_of_range_increment.c @@ -0,0 +1,9 @@ +// panic + +enum color { RED, GREEN, BLUE }; + +int main() { + enum color c = BLUE; + c++; + return c == RED ? 0 : 1; +} diff --git a/tests/ub/out/refcount/enum_out_of_range_cast.rs b/tests/ub/out/refcount/enum_out_of_range_cast.rs index 2ee58dc0..60538ac8 100644 --- a/tests/ub/out/refcount/enum_out_of_range_cast.rs +++ b/tests/ub/out/refcount/enum_out_of_range_cast.rs @@ -23,6 +23,7 @@ impl From for Color { } } } +libcc2rs::impl_enum_inc_dec!(Color); pub fn main() { std::process::exit(main_0()); } diff --git a/tests/ub/out/refcount/enum_out_of_range_increment.rs b/tests/ub/out/refcount/enum_out_of_range_increment.rs new file mode 100644 index 00000000..4809fa73 --- /dev/null +++ b/tests/ub/out/refcount/enum_out_of_range_increment.rs @@ -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 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 = 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 + }; +} diff --git a/tests/ub/out/unsafe/enum_out_of_range_cast.rs b/tests/ub/out/unsafe/enum_out_of_range_cast.rs index 8f0a5ac5..79ef0be6 100644 --- a/tests/ub/out/unsafe/enum_out_of_range_cast.rs +++ b/tests/ub/out/unsafe/enum_out_of_range_cast.rs @@ -23,6 +23,7 @@ impl From for Color { } } } +libcc2rs::impl_enum_inc_dec!(Color); pub fn main() { unsafe { std::process::exit(main_0() as i32); diff --git a/tests/ub/out/unsafe/enum_out_of_range_increment.rs b/tests/ub/out/unsafe/enum_out_of_range_increment.rs new file mode 100644 index 00000000..ce87da65 --- /dev/null +++ b/tests/ub/out/unsafe/enum_out_of_range_increment.rs @@ -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 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 + }; +} diff --git a/tests/unit/enum_increment.c b/tests/unit/enum_increment.c new file mode 100644 index 00000000..20852cdc --- /dev/null +++ b/tests/unit/enum_increment.c @@ -0,0 +1,18 @@ +#include + +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; +} diff --git a/tests/unit/out/refcount/anonymous_enum.rs b/tests/unit/out/refcount/anonymous_enum.rs index 405402d6..fb540cf7 100644 --- a/tests/unit/out/refcount/anonymous_enum.rs +++ b/tests/unit/out/refcount/anonymous_enum.rs @@ -21,6 +21,7 @@ impl From for anon_enum_3 { } } } +libcc2rs::impl_enum_inc_dec!(anon_enum_3); #[derive(Clone, Copy, PartialEq, Debug, Default)] enum anon_enum_11 { #[default] @@ -36,6 +37,7 @@ impl From for anon_enum_11 { } } } +libcc2rs::impl_enum_inc_dec!(anon_enum_11); #[derive(Default)] pub struct S { pub a: Value, @@ -73,6 +75,7 @@ impl From for TdEnum { } } } +libcc2rs::impl_enum_inc_dec!(TdEnum); #[derive(Clone, Copy, PartialEq, Debug, Default)] enum anon_enum_24 { #[default] @@ -88,6 +91,7 @@ impl From for anon_enum_24 { } } } +libcc2rs::impl_enum_inc_dec!(anon_enum_24); #[derive(Default)] pub struct WithAnonField { pub a: Value, @@ -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))); diff --git a/tests/unit/out/refcount/anonymous_enum_c.rs b/tests/unit/out/refcount/anonymous_enum_c.rs index e28c7981..66829762 100644 --- a/tests/unit/out/refcount/anonymous_enum_c.rs +++ b/tests/unit/out/refcount/anonymous_enum_c.rs @@ -21,6 +21,7 @@ impl From for anon_enum_3 { } } } +libcc2rs::impl_enum_inc_dec!(anon_enum_3); #[derive(Clone, Copy, PartialEq, Debug, Default)] enum anon_enum_11 { #[default] @@ -36,6 +37,7 @@ impl From for anon_enum_11 { } } } +libcc2rs::impl_enum_inc_dec!(anon_enum_11); #[derive(Default)] pub struct S { pub a: Value, @@ -65,6 +67,7 @@ impl From for TdEnum { } } } +libcc2rs::impl_enum_inc_dec!(TdEnum); #[derive(Clone, Copy, PartialEq, Debug, Default)] enum anon_enum_24 { #[default] @@ -80,6 +83,7 @@ impl From for anon_enum_24 { } } } +libcc2rs::impl_enum_inc_dec!(anon_enum_24); #[derive(Default)] pub struct WithAnonField { pub a: Value, @@ -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)); diff --git a/tests/unit/out/refcount/bool_condition_enum.rs b/tests/unit/out/refcount/bool_condition_enum.rs index 312017ae..1d7dc853 100644 --- a/tests/unit/out/refcount/bool_condition_enum.rs +++ b/tests/unit/out/refcount/bool_condition_enum.rs @@ -23,6 +23,7 @@ impl From for Code { } } } +libcc2rs::impl_enum_inc_dec!(Code); pub fn main() { std::process::exit(main_0()); } diff --git a/tests/unit/out/refcount/bool_condition_enum_c.rs b/tests/unit/out/refcount/bool_condition_enum_c.rs index f3720089..f84c1a88 100644 --- a/tests/unit/out/refcount/bool_condition_enum_c.rs +++ b/tests/unit/out/refcount/bool_condition_enum_c.rs @@ -23,6 +23,7 @@ impl From for Code { } } } +libcc2rs::impl_enum_inc_dec!(Code); pub fn main() { std::process::exit(main_0()); } diff --git a/tests/unit/out/refcount/bool_condition_logical.rs b/tests/unit/out/refcount/bool_condition_logical.rs index 7101b5d0..31425290 100644 --- a/tests/unit/out/refcount/bool_condition_logical.rs +++ b/tests/unit/out/refcount/bool_condition_logical.rs @@ -23,6 +23,7 @@ impl From for Code { } } } +libcc2rs::impl_enum_inc_dec!(Code); thread_local!( pub static side_effect: Value = Rc::new(RefCell::new(0)); ); diff --git a/tests/unit/out/refcount/bool_condition_logical_c.rs b/tests/unit/out/refcount/bool_condition_logical_c.rs index de5a8563..31e3d7fd 100644 --- a/tests/unit/out/refcount/bool_condition_logical_c.rs +++ b/tests/unit/out/refcount/bool_condition_logical_c.rs @@ -23,6 +23,7 @@ impl From for Code { } } } +libcc2rs::impl_enum_inc_dec!(Code); thread_local!( pub static side_effect: Value = Rc::new(RefCell::new(0)); ); diff --git a/tests/unit/out/refcount/c_struct.rs b/tests/unit/out/refcount/c_struct.rs index 3379e833..0549baab 100644 --- a/tests/unit/out/refcount/c_struct.rs +++ b/tests/unit/out/refcount/c_struct.rs @@ -52,6 +52,7 @@ impl From for Color { } } } +libcc2rs::impl_enum_inc_dec!(Color); #[derive(Default)] pub struct Inner { pub a: Value, diff --git a/tests/unit/out/refcount/enum_increment.rs b/tests/unit/out/refcount/enum_increment.rs new file mode 100644 index 00000000..25a24a2f --- /dev/null +++ b/tests/unit/out/refcount/enum_increment.rs @@ -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 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 = Rc::new(RefCell::new(0)); + let c: Value = 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 = 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; +} diff --git a/tests/unit/out/refcount/enum_int_interop.rs b/tests/unit/out/refcount/enum_int_interop.rs index 0346281d..4426a475 100644 --- a/tests/unit/out/refcount/enum_int_interop.rs +++ b/tests/unit/out/refcount/enum_int_interop.rs @@ -23,6 +23,7 @@ impl From for Color { } } } +libcc2rs::impl_enum_inc_dec!(Color); #[derive(Clone, Copy, PartialEq, Debug, Default)] enum Option { #[default] @@ -42,6 +43,7 @@ impl From for Option { } } } +libcc2rs::impl_enum_inc_dec!(Option); #[derive(Clone, Copy, PartialEq, Debug, Default)] enum Tag { #[default] @@ -59,6 +61,7 @@ impl From for Tag { } } } +libcc2rs::impl_enum_inc_dec!(Tag); #[derive(Default)] pub struct Entry { pub name: Value>, diff --git a/tests/unit/out/refcount/enum_int_interop_c.rs b/tests/unit/out/refcount/enum_int_interop_c.rs index 97609ceb..609243a7 100644 --- a/tests/unit/out/refcount/enum_int_interop_c.rs +++ b/tests/unit/out/refcount/enum_int_interop_c.rs @@ -23,6 +23,7 @@ impl From for Color { } } } +libcc2rs::impl_enum_inc_dec!(Color); #[derive(Clone, Copy, PartialEq, Debug, Default)] enum Option { #[default] @@ -42,6 +43,7 @@ impl From for Option { } } } +libcc2rs::impl_enum_inc_dec!(Option); #[derive(Clone, Copy, PartialEq, Debug, Default)] enum Tag { #[default] @@ -59,6 +61,7 @@ impl From for Tag { } } } +libcc2rs::impl_enum_inc_dec!(Tag); #[derive(Default)] pub struct Entry { pub name: Value>, diff --git a/tests/unit/out/refcount/switch_char.rs b/tests/unit/out/refcount/switch_char.rs index 4c756a76..9a9fd82b 100644 --- a/tests/unit/out/refcount/switch_char.rs +++ b/tests/unit/out/refcount/switch_char.rs @@ -47,6 +47,7 @@ impl From for Color { } } } +libcc2rs::impl_enum_inc_dec!(Color); pub fn main() { std::process::exit(main_0()); } diff --git a/tests/unit/out/refcount/switch_enum.rs b/tests/unit/out/refcount/switch_enum.rs index 03c48ef1..fcdb6d4e 100644 --- a/tests/unit/out/refcount/switch_enum.rs +++ b/tests/unit/out/refcount/switch_enum.rs @@ -23,6 +23,7 @@ impl From for Color { } } } +libcc2rs::impl_enum_inc_dec!(Color); pub fn switch_enum_0(c: Color) -> i32 { let c: Value = Rc::new(RefCell::new(c)); 'switch: { diff --git a/tests/unit/out/refcount/va_arg_non_primitive_ptrs.rs b/tests/unit/out/refcount/va_arg_non_primitive_ptrs.rs index e090ef0d..50935667 100644 --- a/tests/unit/out/refcount/va_arg_non_primitive_ptrs.rs +++ b/tests/unit/out/refcount/va_arg_non_primitive_ptrs.rs @@ -31,6 +31,7 @@ impl From for opt { } } } +libcc2rs::impl_enum_inc_dec!(opt); pub fn dispatch_0(option: i32, __args: &[VaArg]) -> i32 { let option: Value = Rc::new(RefCell::new(option)); let ap: Value = Rc::new(RefCell::new(VaList::default())); diff --git a/tests/unit/out/unsafe/anonymous_enum.rs b/tests/unit/out/unsafe/anonymous_enum.rs index a16f0d6e..55f89d26 100644 --- a/tests/unit/out/unsafe/anonymous_enum.rs +++ b/tests/unit/out/unsafe/anonymous_enum.rs @@ -21,6 +21,7 @@ impl From for anon_enum_3 { } } } +libcc2rs::impl_enum_inc_dec!(anon_enum_3); #[derive(Clone, Copy, PartialEq, Debug, Default)] enum anon_enum_11 { #[default] @@ -36,6 +37,7 @@ impl From for anon_enum_11 { } } } +libcc2rs::impl_enum_inc_dec!(anon_enum_11); #[repr(C)] #[derive(Copy, Clone, Default)] pub struct S { @@ -56,6 +58,7 @@ impl From for TdEnum { } } } +libcc2rs::impl_enum_inc_dec!(TdEnum); #[derive(Clone, Copy, PartialEq, Debug, Default)] enum anon_enum_24 { #[default] @@ -71,6 +74,7 @@ impl From for anon_enum_24 { } } } +libcc2rs::impl_enum_inc_dec!(anon_enum_24); #[repr(C)] #[derive(Copy, Clone, Default)] pub struct WithAnonField { @@ -97,7 +101,8 @@ unsafe 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))); diff --git a/tests/unit/out/unsafe/anonymous_enum_c.rs b/tests/unit/out/unsafe/anonymous_enum_c.rs index 8b1d3b84..b245af7d 100644 --- a/tests/unit/out/unsafe/anonymous_enum_c.rs +++ b/tests/unit/out/unsafe/anonymous_enum_c.rs @@ -21,6 +21,7 @@ impl From for anon_enum_3 { } } } +libcc2rs::impl_enum_inc_dec!(anon_enum_3); #[derive(Clone, Copy, PartialEq, Debug, Default)] enum anon_enum_11 { #[default] @@ -36,6 +37,7 @@ impl From for anon_enum_11 { } } } +libcc2rs::impl_enum_inc_dec!(anon_enum_11); #[repr(C)] #[derive(Copy, Clone, Default)] pub struct S { @@ -56,6 +58,7 @@ impl From for TdEnum { } } } +libcc2rs::impl_enum_inc_dec!(TdEnum); #[derive(Clone, Copy, PartialEq, Debug, Default)] enum anon_enum_24 { #[default] @@ -71,6 +74,7 @@ impl From for anon_enum_24 { } } } +libcc2rs::impl_enum_inc_dec!(anon_enum_24); #[repr(C)] #[derive(Copy, Clone, Default)] pub struct WithAnonField { @@ -97,7 +101,8 @@ unsafe 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)); diff --git a/tests/unit/out/unsafe/bool_condition_enum.rs b/tests/unit/out/unsafe/bool_condition_enum.rs index da7dae3e..fbfa85eb 100644 --- a/tests/unit/out/unsafe/bool_condition_enum.rs +++ b/tests/unit/out/unsafe/bool_condition_enum.rs @@ -23,6 +23,7 @@ impl From for Code { } } } +libcc2rs::impl_enum_inc_dec!(Code); pub fn main() { unsafe { std::process::exit(main_0() as i32); diff --git a/tests/unit/out/unsafe/bool_condition_enum_c.rs b/tests/unit/out/unsafe/bool_condition_enum_c.rs index c744e452..898b67a6 100644 --- a/tests/unit/out/unsafe/bool_condition_enum_c.rs +++ b/tests/unit/out/unsafe/bool_condition_enum_c.rs @@ -23,6 +23,7 @@ impl From for Code { } } } +libcc2rs::impl_enum_inc_dec!(Code); pub fn main() { unsafe { std::process::exit(main_0() as i32); diff --git a/tests/unit/out/unsafe/bool_condition_logical.rs b/tests/unit/out/unsafe/bool_condition_logical.rs index 8f0a8cfe..59e37030 100644 --- a/tests/unit/out/unsafe/bool_condition_logical.rs +++ b/tests/unit/out/unsafe/bool_condition_logical.rs @@ -23,6 +23,7 @@ impl From for Code { } } } +libcc2rs::impl_enum_inc_dec!(Code); pub static mut side_effect: i32 = unsafe { 0 }; pub unsafe fn observe_0(mut v: i32) -> i32 { side_effect.prefix_inc(); diff --git a/tests/unit/out/unsafe/bool_condition_logical_c.rs b/tests/unit/out/unsafe/bool_condition_logical_c.rs index 38326f50..0c55e31b 100644 --- a/tests/unit/out/unsafe/bool_condition_logical_c.rs +++ b/tests/unit/out/unsafe/bool_condition_logical_c.rs @@ -23,6 +23,7 @@ impl From for Code { } } } +libcc2rs::impl_enum_inc_dec!(Code); pub static mut side_effect: i32 = unsafe { 0 }; pub unsafe fn observe_0(mut v: i32) -> i32 { side_effect.prefix_inc(); diff --git a/tests/unit/out/unsafe/c_struct.rs b/tests/unit/out/unsafe/c_struct.rs index 02e3df2b..5157a6f3 100644 --- a/tests/unit/out/unsafe/c_struct.rs +++ b/tests/unit/out/unsafe/c_struct.rs @@ -41,6 +41,7 @@ impl From for Color { } } } +libcc2rs::impl_enum_inc_dec!(Color); #[repr(C)] #[derive(Copy, Clone, Default)] pub struct Inner { diff --git a/tests/unit/out/unsafe/enum_increment.rs b/tests/unit/out/unsafe/enum_increment.rs new file mode 100644 index 00000000..16552a7b --- /dev/null +++ b/tests/unit/out/unsafe/enum_increment.rs @@ -0,0 +1,48 @@ +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, + COLOR_LAST = 3, +} +impl From 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() { + unsafe { + std::process::exit(main_0() as i32); + } +} +unsafe fn main_0() -> i32 { + let mut count: i32 = 0; + let mut c: color = color::RED; + 'loop_: while ((((c as u32) < ((color::COLOR_LAST as i32) as u32)) as i32) != 0) { + count.postfix_inc(); + c.postfix_inc(); + } + assert!(((((count) == (3)) as i32) != 0)); + let mut c: color = color::RED; + assert!(((((c.postfix_inc() as u32) == ((color::RED as i32) as u32)) as i32) != 0)); + assert!(((((c.prefix_inc() as u32) == ((color::BLUE as i32) as u32)) as i32) != 0)); + assert!(((((c.postfix_dec() as u32) == ((color::BLUE as i32) as u32)) as i32) != 0)); + assert!(((((c.prefix_dec() as u32) == ((color::RED as i32) as u32)) as i32) != 0)); + return 0; +} diff --git a/tests/unit/out/unsafe/enum_int_interop.rs b/tests/unit/out/unsafe/enum_int_interop.rs index 756eef9c..f3883690 100644 --- a/tests/unit/out/unsafe/enum_int_interop.rs +++ b/tests/unit/out/unsafe/enum_int_interop.rs @@ -23,6 +23,7 @@ impl From for Color { } } } +libcc2rs::impl_enum_inc_dec!(Color); #[derive(Clone, Copy, PartialEq, Debug, Default)] enum Option { #[default] @@ -42,6 +43,7 @@ impl From for Option { } } } +libcc2rs::impl_enum_inc_dec!(Option); #[derive(Clone, Copy, PartialEq, Debug, Default)] enum Tag { #[default] @@ -59,6 +61,7 @@ impl From for Tag { } } } +libcc2rs::impl_enum_inc_dec!(Tag); #[repr(C)] #[derive(Copy, Clone, Default)] pub struct Entry { diff --git a/tests/unit/out/unsafe/enum_int_interop_c.rs b/tests/unit/out/unsafe/enum_int_interop_c.rs index 3f4fcbae..8a5562fc 100644 --- a/tests/unit/out/unsafe/enum_int_interop_c.rs +++ b/tests/unit/out/unsafe/enum_int_interop_c.rs @@ -23,6 +23,7 @@ impl From for Color { } } } +libcc2rs::impl_enum_inc_dec!(Color); #[derive(Clone, Copy, PartialEq, Debug, Default)] enum Option { #[default] @@ -42,6 +43,7 @@ impl From for Option { } } } +libcc2rs::impl_enum_inc_dec!(Option); #[derive(Clone, Copy, PartialEq, Debug, Default)] enum Tag { #[default] @@ -59,6 +61,7 @@ impl From for Tag { } } } +libcc2rs::impl_enum_inc_dec!(Tag); #[repr(C)] #[derive(Copy, Clone, Default)] pub struct Entry { diff --git a/tests/unit/out/unsafe/switch_char.rs b/tests/unit/out/unsafe/switch_char.rs index e32ee055..d1962a73 100644 --- a/tests/unit/out/unsafe/switch_char.rs +++ b/tests/unit/out/unsafe/switch_char.rs @@ -46,6 +46,7 @@ impl From for Color { } } } +libcc2rs::impl_enum_inc_dec!(Color); pub fn main() { unsafe { std::process::exit(main_0() as i32); diff --git a/tests/unit/out/unsafe/switch_enum.rs b/tests/unit/out/unsafe/switch_enum.rs index e75e4a28..583326da 100644 --- a/tests/unit/out/unsafe/switch_enum.rs +++ b/tests/unit/out/unsafe/switch_enum.rs @@ -23,6 +23,7 @@ impl From for Color { } } } +libcc2rs::impl_enum_inc_dec!(Color); pub unsafe fn switch_enum_0(mut c: Color) -> i32 { 'switch: { let __match_cond = (c as i32); diff --git a/tests/unit/out/unsafe/union_tagged_many_arms.rs b/tests/unit/out/unsafe/union_tagged_many_arms.rs index a46a2fcd..b1ac0bda 100644 --- a/tests/unit/out/unsafe/union_tagged_many_arms.rs +++ b/tests/unit/out/unsafe/union_tagged_many_arms.rs @@ -27,6 +27,7 @@ impl From for Tag { } } } +libcc2rs::impl_enum_inc_dec!(Tag); #[repr(C)] #[derive(Copy, Clone)] pub union Slot_anon_0 { diff --git a/tests/unit/out/unsafe/union_tagged_simple.rs b/tests/unit/out/unsafe/union_tagged_simple.rs index a2548f7c..834c22fe 100644 --- a/tests/unit/out/unsafe/union_tagged_simple.rs +++ b/tests/unit/out/unsafe/union_tagged_simple.rs @@ -21,6 +21,7 @@ impl From for Kind { } } } +libcc2rs::impl_enum_inc_dec!(Kind); #[repr(C)] #[derive(Copy, Clone)] pub union Event_anon_0 { diff --git a/tests/unit/out/unsafe/union_tagged_struct_arms.rs b/tests/unit/out/unsafe/union_tagged_struct_arms.rs index 681020f1..52ec1c70 100644 --- a/tests/unit/out/unsafe/union_tagged_struct_arms.rs +++ b/tests/unit/out/unsafe/union_tagged_struct_arms.rs @@ -23,6 +23,7 @@ impl From for Choice { } } } +libcc2rs::impl_enum_inc_dec!(Choice); #[repr(C)] #[derive(Copy, Clone, Default)] pub struct Branch_anon_0_anon_0 { diff --git a/tests/unit/out/unsafe/union_void_ptr_sized_deref.rs b/tests/unit/out/unsafe/union_void_ptr_sized_deref.rs index 83977a80..3391a818 100644 --- a/tests/unit/out/unsafe/union_void_ptr_sized_deref.rs +++ b/tests/unit/out/unsafe/union_void_ptr_sized_deref.rs @@ -23,6 +23,7 @@ impl From for Width { } } } +libcc2rs::impl_enum_inc_dec!(Width); #[repr(C)] #[derive(Copy, Clone)] pub union Sink_anon_0 { diff --git a/tests/unit/out/unsafe/va_arg_non_primitive_ptrs.rs b/tests/unit/out/unsafe/va_arg_non_primitive_ptrs.rs index e8e2c8c6..df278617 100644 --- a/tests/unit/out/unsafe/va_arg_non_primitive_ptrs.rs +++ b/tests/unit/out/unsafe/va_arg_non_primitive_ptrs.rs @@ -31,6 +31,7 @@ impl From for opt { } } } +libcc2rs::impl_enum_inc_dec!(opt); pub unsafe fn dispatch_0(mut option: i32, __args: &[VaArg]) -> i32 { let mut ap: VaList = VaList::default(); ap = VaList::new(__args); From 3257a3a4a3f667dc3d9d2dbdf2029eadc18af148 Mon Sep 17 00:00:00 2001 From: Lucian Popescu Date: Tue, 26 May 2026 20:18:22 +0100 Subject: [PATCH 2/2] Trigger CI