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
2 changes: 1 addition & 1 deletion cpp2rust/converter/converter.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2672,7 +2672,7 @@ bool Converter::VisitEnumDecl(clang::EnumDecl *decl) {
}
Mapper::AddRuleForUserDefinedType(decl);
StrCat("#[derive(Clone, Copy, PartialEq, Debug, Default)]");
StrCat(std::format("enum {}", Mapper::Map(ctx_.getCanonicalTagType(decl))));
StrCat(std::format("enum {}", GetRecordName(decl)));
StrCat("{");
bool first_enumerator = true;
for (auto e : decl->enumerators()) {
Expand Down
11 changes: 11 additions & 0 deletions cpp2rust/converter/mapper.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -724,6 +724,11 @@ std::string ToString(clang::QualType qual_type) {
}
}

if (auto *tag = qual_type->getAsTagDecl();
tag && !tag->getIdentifier() && !tag->getTypedefNameForAnonDecl()) {
return ToString(clang::cast<clang::NamedDecl>(tag));
}

std::string type;
llvm::raw_string_ostream os(type);
normalizeQualType(qual_type).print(os, getPrintPolicy());
Expand All @@ -736,6 +741,12 @@ std::string ToString(const clang::NamedDecl *decl) {
return synthesizeAnonRecordName(record);
}

if (auto *enum_decl = clang::dyn_cast<clang::EnumDecl>(decl);
enum_decl && !enum_decl->getIdentifier() &&
!enum_decl->getTypedefNameForAnonDecl()) {
return std::format("anon_enum_{}", GetLineNumber(enum_decl));
}

std::string out;
llvm::raw_string_ostream os(out);

Expand Down
52 changes: 52 additions & 0 deletions tests/unit/anonymous_enum.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
#include <assert.h>

enum {
FIRST_A,
FIRST_B,
};

struct S {
int a;

enum {
SECOND_A,
SECOND_B,
};
};

typedef enum {
TD_A,
TD_B,
} TdEnum;

struct WithAnonField {
int a;
enum {
FIELD_A,
FIELD_B,
} field;
};

int main() {
enum {
THIRD_A,
THIRD_B,
};

assert(FIRST_A != FIRST_B);
assert(S::SECOND_A != S::SECOND_B);
assert(THIRD_A != THIRD_B);

TdEnum td = TD_A;
assert(td == TD_A);
td = TD_B;
assert(td == TD_B);

WithAnonField w;
w.field = WithAnonField::FIELD_A;
assert(w.field == WithAnonField::FIELD_A);
w.field = WithAnonField::FIELD_B;
assert(w.field == WithAnonField::FIELD_B);

return 0;
};
52 changes: 52 additions & 0 deletions tests/unit/anonymous_enum_c.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
#include <assert.h>

enum {
FIRST_A,
FIRST_B,
};

struct S {
int a;

enum {
SECOND_A,
SECOND_B,
};
};

typedef enum {
TD_A,
TD_B,
} TdEnum;

struct WithAnonField {
int a;
enum {
FIELD_A,
FIELD_B,
} field;
};

int main() {
enum {
THIRD_A,
THIRD_B,
};

assert(FIRST_A != FIRST_B);
assert(SECOND_A != SECOND_B);
assert(THIRD_A != THIRD_B);

TdEnum td = TD_A;
assert(td == TD_A);
td = TD_B;
assert(td == TD_B);

struct WithAnonField w;
w.field = FIELD_A;
assert(w.field == FIELD_A);
w.field = FIELD_B;
assert(w.field == FIELD_B);

return 0;
};
84 changes: 84 additions & 0 deletions tests/unit/out/refcount/anonymous_enum.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,84 @@
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 anon_enum_3 {
#[default]
FIRST_A = 0,
FIRST_B = 1,
}
#[derive(Clone, Copy, PartialEq, Debug, Default)]
enum anon_enum_11 {
#[default]
SECOND_A = 0,
SECOND_B = 1,
}
#[derive(Default)]
pub struct S {
pub a: Value<i32>,
}
impl Clone for S {
fn clone(&self) -> Self {
let mut this = Self {
a: Rc::new(RefCell::new((*self.a.borrow()))),
};
this
}
}
impl ByteRepr for S {}
#[derive(Clone, Copy, PartialEq, Debug, Default)]
enum TdEnum {
#[default]
TD_A = 0,
TD_B = 1,
}
#[derive(Clone, Copy, PartialEq, Debug, Default)]
enum anon_enum_24 {
#[default]
FIELD_A = 0,
FIELD_B = 1,
}
#[derive(Default)]
pub struct WithAnonField {
pub a: Value<i32>,
pub field: Value<anon_enum_24>,
}
impl Clone for WithAnonField {
fn clone(&self) -> Self {
let mut this = Self {
a: Rc::new(RefCell::new((*self.a.borrow()))),
field: Rc::new(RefCell::new((*self.field.borrow()).clone())),
};
this
}
}
impl ByteRepr for WithAnonField {}
pub fn main() {
std::process::exit(main_0());
}
fn main_0() -> i32 {
#[derive(Clone, Copy, PartialEq, Debug, Default)]
enum anon_enum_31 {
#[default]
THIRD_A = 0,
THIRD_B = 1,
};
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)));
let td: Value<TdEnum> = Rc::new(RefCell::new(TdEnum::TD_A));
assert!((((*td.borrow()) as i32) == (TdEnum::TD_A as i32)));
(*td.borrow_mut()) = TdEnum::TD_B;
assert!((((*td.borrow()) as i32) == (TdEnum::TD_B as i32)));
let w: Value<WithAnonField> = Rc::new(RefCell::new(<WithAnonField>::default()));
(*(*w.borrow()).field.borrow_mut()) = anon_enum_24::FIELD_A;
assert!((((*(*w.borrow()).field.borrow()) as i32) == (anon_enum_24::FIELD_A as i32)));
(*(*w.borrow()).field.borrow_mut()) = anon_enum_24::FIELD_B;
assert!((((*(*w.borrow()).field.borrow()) as i32) == (anon_enum_24::FIELD_B as i32)));
return 0;
}
67 changes: 67 additions & 0 deletions tests/unit/out/refcount/anonymous_enum_c.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,67 @@
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 anon_enum_3 {
#[default]
FIRST_A = 0,
FIRST_B = 1,
}
#[derive(Clone, Copy, PartialEq, Debug, Default)]
enum anon_enum_11 {
#[default]
SECOND_A = 0,
SECOND_B = 1,
}
#[derive(Default)]
pub struct S {
pub a: Value<i32>,
}
impl ByteRepr for S {}
#[derive(Clone, Copy, PartialEq, Debug, Default)]
enum TdEnum {
#[default]
TD_A = 0,
TD_B = 1,
}
#[derive(Clone, Copy, PartialEq, Debug, Default)]
enum anon_enum_24 {
#[default]
FIELD_A = 0,
FIELD_B = 1,
}
#[derive(Default)]
pub struct WithAnonField {
pub a: Value<i32>,
pub field: Value<anon_enum_24>,
}
impl ByteRepr for WithAnonField {}
pub fn main() {
std::process::exit(main_0());
}
fn main_0() -> i32 {
#[derive(Clone, Copy, PartialEq, Debug, Default)]
enum anon_enum_31 {
#[default]
THIRD_A = 0,
THIRD_B = 1,
};
assert!((anon_enum_3::FIRST_A != anon_enum_3::FIRST_B));
assert!((anon_enum_11::SECOND_A != anon_enum_11::SECOND_B));
assert!((anon_enum_31::THIRD_A != anon_enum_31::THIRD_B));
let td: Value<TdEnum> = Rc::new(RefCell::new((TdEnum::TD_A as TdEnum)));
assert!((((*td.borrow()) as u32) == (TdEnum::TD_A as u32)));
(*td.borrow_mut()) = (TdEnum::TD_B as TdEnum);
assert!((((*td.borrow()) as u32) == (TdEnum::TD_B as u32)));
let w: Value<WithAnonField> = <Value<WithAnonField>>::default();
(*(*w.borrow()).field.borrow_mut()) = (anon_enum_24::FIELD_A as anon_enum_24);
assert!((((*(*w.borrow()).field.borrow()) as u32) == (anon_enum_24::FIELD_A as u32)));
(*(*w.borrow()).field.borrow_mut()) = (anon_enum_24::FIELD_B as anon_enum_24);
assert!((((*(*w.borrow()).field.borrow()) as u32) == (anon_enum_24::FIELD_B as u32)));
return 0;
}
69 changes: 69 additions & 0 deletions tests/unit/out/unsafe/anonymous_enum.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,69 @@
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 anon_enum_3 {
#[default]
FIRST_A = 0,
FIRST_B = 1,
}
#[derive(Clone, Copy, PartialEq, Debug, Default)]
enum anon_enum_11 {
#[default]
SECOND_A = 0,
SECOND_B = 1,
}
#[repr(C)]
#[derive(Copy, Clone, Default)]
pub struct S {
pub a: i32,
}
#[derive(Clone, Copy, PartialEq, Debug, Default)]
enum TdEnum {
#[default]
TD_A = 0,
TD_B = 1,
}
#[derive(Clone, Copy, PartialEq, Debug, Default)]
enum anon_enum_24 {
#[default]
FIELD_A = 0,
FIELD_B = 1,
}
#[repr(C)]
#[derive(Copy, Clone, Default)]
pub struct WithAnonField {
pub a: i32,
pub field: anon_enum_24,
}
pub fn main() {
unsafe {
std::process::exit(main_0() as i32);
}
}
unsafe fn main_0() -> i32 {
#[derive(Clone, Copy, PartialEq, Debug, Default)]
enum anon_enum_31 {
#[default]
THIRD_A = 0,
THIRD_B = 1,
};
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)));
let mut td: TdEnum = TdEnum::TD_A;
assert!(((td as i32) == (TdEnum::TD_A as i32)));
td = (TdEnum::TD_B).clone();
assert!(((td as i32) == (TdEnum::TD_B as i32)));
let mut w: WithAnonField = <WithAnonField>::default();
w.field = anon_enum_24::FIELD_A;
assert!(((w.field as i32) == (anon_enum_24::FIELD_A as i32)));
w.field = (anon_enum_24::FIELD_B).clone();
assert!(((w.field as i32) == (anon_enum_24::FIELD_B as i32)));
return 0;
}
Loading
Loading