Skip to content

Commit 2b1310c

Browse files
authored
Translate anonymous enums (#43)
1 parent b474ede commit 2b1310c

8 files changed

Lines changed: 405 additions & 1 deletion

File tree

cpp2rust/converter/converter.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2672,7 +2672,7 @@ bool Converter::VisitEnumDecl(clang::EnumDecl *decl) {
26722672
}
26732673
Mapper::AddRuleForUserDefinedType(decl);
26742674
StrCat("#[derive(Clone, Copy, PartialEq, Debug, Default)]");
2675-
StrCat(std::format("enum {}", Mapper::Map(ctx_.getCanonicalTagType(decl))));
2675+
StrCat(std::format("enum {}", GetRecordName(decl)));
26762676
StrCat("{");
26772677
bool first_enumerator = true;
26782678
for (auto e : decl->enumerators()) {

cpp2rust/converter/mapper.cpp

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -724,6 +724,11 @@ std::string ToString(clang::QualType qual_type) {
724724
}
725725
}
726726

727+
if (auto *tag = qual_type->getAsTagDecl();
728+
tag && !tag->getIdentifier() && !tag->getTypedefNameForAnonDecl()) {
729+
return ToString(clang::cast<clang::NamedDecl>(tag));
730+
}
731+
727732
std::string type;
728733
llvm::raw_string_ostream os(type);
729734
normalizeQualType(qual_type).print(os, getPrintPolicy());
@@ -736,6 +741,12 @@ std::string ToString(const clang::NamedDecl *decl) {
736741
return synthesizeAnonRecordName(record);
737742
}
738743

744+
if (auto *enum_decl = clang::dyn_cast<clang::EnumDecl>(decl);
745+
enum_decl && !enum_decl->getIdentifier() &&
746+
!enum_decl->getTypedefNameForAnonDecl()) {
747+
return std::format("anon_enum_{}", GetLineNumber(enum_decl));
748+
}
749+
739750
std::string out;
740751
llvm::raw_string_ostream os(out);
741752

tests/unit/anonymous_enum.cpp

Lines changed: 52 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,52 @@
1+
#include <assert.h>
2+
3+
enum {
4+
FIRST_A,
5+
FIRST_B,
6+
};
7+
8+
struct S {
9+
int a;
10+
11+
enum {
12+
SECOND_A,
13+
SECOND_B,
14+
};
15+
};
16+
17+
typedef enum {
18+
TD_A,
19+
TD_B,
20+
} TdEnum;
21+
22+
struct WithAnonField {
23+
int a;
24+
enum {
25+
FIELD_A,
26+
FIELD_B,
27+
} field;
28+
};
29+
30+
int main() {
31+
enum {
32+
THIRD_A,
33+
THIRD_B,
34+
};
35+
36+
assert(FIRST_A != FIRST_B);
37+
assert(S::SECOND_A != S::SECOND_B);
38+
assert(THIRD_A != THIRD_B);
39+
40+
TdEnum td = TD_A;
41+
assert(td == TD_A);
42+
td = TD_B;
43+
assert(td == TD_B);
44+
45+
WithAnonField w;
46+
w.field = WithAnonField::FIELD_A;
47+
assert(w.field == WithAnonField::FIELD_A);
48+
w.field = WithAnonField::FIELD_B;
49+
assert(w.field == WithAnonField::FIELD_B);
50+
51+
return 0;
52+
};

tests/unit/anonymous_enum_c.c

Lines changed: 52 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,52 @@
1+
#include <assert.h>
2+
3+
enum {
4+
FIRST_A,
5+
FIRST_B,
6+
};
7+
8+
struct S {
9+
int a;
10+
11+
enum {
12+
SECOND_A,
13+
SECOND_B,
14+
};
15+
};
16+
17+
typedef enum {
18+
TD_A,
19+
TD_B,
20+
} TdEnum;
21+
22+
struct WithAnonField {
23+
int a;
24+
enum {
25+
FIELD_A,
26+
FIELD_B,
27+
} field;
28+
};
29+
30+
int main() {
31+
enum {
32+
THIRD_A,
33+
THIRD_B,
34+
};
35+
36+
assert(FIRST_A != FIRST_B);
37+
assert(SECOND_A != SECOND_B);
38+
assert(THIRD_A != THIRD_B);
39+
40+
TdEnum td = TD_A;
41+
assert(td == TD_A);
42+
td = TD_B;
43+
assert(td == TD_B);
44+
45+
struct WithAnonField w;
46+
w.field = FIELD_A;
47+
assert(w.field == FIELD_A);
48+
w.field = FIELD_B;
49+
assert(w.field == FIELD_B);
50+
51+
return 0;
52+
};
Lines changed: 84 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,84 @@
1+
extern crate libcc2rs;
2+
use libcc2rs::*;
3+
use std::cell::RefCell;
4+
use std::collections::BTreeMap;
5+
use std::io::prelude::*;
6+
use std::io::{Read, Seek, Write};
7+
use std::os::fd::AsFd;
8+
use std::rc::{Rc, Weak};
9+
#[derive(Clone, Copy, PartialEq, Debug, Default)]
10+
enum anon_enum_3 {
11+
#[default]
12+
FIRST_A = 0,
13+
FIRST_B = 1,
14+
}
15+
#[derive(Clone, Copy, PartialEq, Debug, Default)]
16+
enum anon_enum_11 {
17+
#[default]
18+
SECOND_A = 0,
19+
SECOND_B = 1,
20+
}
21+
#[derive(Default)]
22+
pub struct S {
23+
pub a: Value<i32>,
24+
}
25+
impl Clone for S {
26+
fn clone(&self) -> Self {
27+
let mut this = Self {
28+
a: Rc::new(RefCell::new((*self.a.borrow()))),
29+
};
30+
this
31+
}
32+
}
33+
impl ByteRepr for S {}
34+
#[derive(Clone, Copy, PartialEq, Debug, Default)]
35+
enum TdEnum {
36+
#[default]
37+
TD_A = 0,
38+
TD_B = 1,
39+
}
40+
#[derive(Clone, Copy, PartialEq, Debug, Default)]
41+
enum anon_enum_24 {
42+
#[default]
43+
FIELD_A = 0,
44+
FIELD_B = 1,
45+
}
46+
#[derive(Default)]
47+
pub struct WithAnonField {
48+
pub a: Value<i32>,
49+
pub field: Value<anon_enum_24>,
50+
}
51+
impl Clone for WithAnonField {
52+
fn clone(&self) -> Self {
53+
let mut this = Self {
54+
a: Rc::new(RefCell::new((*self.a.borrow()))),
55+
field: Rc::new(RefCell::new((*self.field.borrow()).clone())),
56+
};
57+
this
58+
}
59+
}
60+
impl ByteRepr for WithAnonField {}
61+
pub fn main() {
62+
std::process::exit(main_0());
63+
}
64+
fn main_0() -> i32 {
65+
#[derive(Clone, Copy, PartialEq, Debug, Default)]
66+
enum anon_enum_31 {
67+
#[default]
68+
THIRD_A = 0,
69+
THIRD_B = 1,
70+
};
71+
assert!(((anon_enum_3::FIRST_A as i32) != (anon_enum_3::FIRST_B as i32)));
72+
assert!(((anon_enum_11::SECOND_A as i32) != (anon_enum_11::SECOND_B as i32)));
73+
assert!(((anon_enum_31::THIRD_A as i32) != (anon_enum_31::THIRD_B as i32)));
74+
let td: Value<TdEnum> = Rc::new(RefCell::new(TdEnum::TD_A));
75+
assert!((((*td.borrow()) as i32) == (TdEnum::TD_A as i32)));
76+
(*td.borrow_mut()) = TdEnum::TD_B;
77+
assert!((((*td.borrow()) as i32) == (TdEnum::TD_B as i32)));
78+
let w: Value<WithAnonField> = Rc::new(RefCell::new(<WithAnonField>::default()));
79+
(*(*w.borrow()).field.borrow_mut()) = anon_enum_24::FIELD_A;
80+
assert!((((*(*w.borrow()).field.borrow()) as i32) == (anon_enum_24::FIELD_A as i32)));
81+
(*(*w.borrow()).field.borrow_mut()) = anon_enum_24::FIELD_B;
82+
assert!((((*(*w.borrow()).field.borrow()) as i32) == (anon_enum_24::FIELD_B as i32)));
83+
return 0;
84+
}
Lines changed: 67 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,67 @@
1+
extern crate libcc2rs;
2+
use libcc2rs::*;
3+
use std::cell::RefCell;
4+
use std::collections::BTreeMap;
5+
use std::io::prelude::*;
6+
use std::io::{Read, Seek, Write};
7+
use std::os::fd::AsFd;
8+
use std::rc::{Rc, Weak};
9+
#[derive(Clone, Copy, PartialEq, Debug, Default)]
10+
enum anon_enum_3 {
11+
#[default]
12+
FIRST_A = 0,
13+
FIRST_B = 1,
14+
}
15+
#[derive(Clone, Copy, PartialEq, Debug, Default)]
16+
enum anon_enum_11 {
17+
#[default]
18+
SECOND_A = 0,
19+
SECOND_B = 1,
20+
}
21+
#[derive(Default)]
22+
pub struct S {
23+
pub a: Value<i32>,
24+
}
25+
impl ByteRepr for S {}
26+
#[derive(Clone, Copy, PartialEq, Debug, Default)]
27+
enum TdEnum {
28+
#[default]
29+
TD_A = 0,
30+
TD_B = 1,
31+
}
32+
#[derive(Clone, Copy, PartialEq, Debug, Default)]
33+
enum anon_enum_24 {
34+
#[default]
35+
FIELD_A = 0,
36+
FIELD_B = 1,
37+
}
38+
#[derive(Default)]
39+
pub struct WithAnonField {
40+
pub a: Value<i32>,
41+
pub field: Value<anon_enum_24>,
42+
}
43+
impl ByteRepr for WithAnonField {}
44+
pub fn main() {
45+
std::process::exit(main_0());
46+
}
47+
fn main_0() -> i32 {
48+
#[derive(Clone, Copy, PartialEq, Debug, Default)]
49+
enum anon_enum_31 {
50+
#[default]
51+
THIRD_A = 0,
52+
THIRD_B = 1,
53+
};
54+
assert!((anon_enum_3::FIRST_A != anon_enum_3::FIRST_B));
55+
assert!((anon_enum_11::SECOND_A != anon_enum_11::SECOND_B));
56+
assert!((anon_enum_31::THIRD_A != anon_enum_31::THIRD_B));
57+
let td: Value<TdEnum> = Rc::new(RefCell::new((TdEnum::TD_A as TdEnum)));
58+
assert!((((*td.borrow()) as u32) == (TdEnum::TD_A as u32)));
59+
(*td.borrow_mut()) = (TdEnum::TD_B as TdEnum);
60+
assert!((((*td.borrow()) as u32) == (TdEnum::TD_B as u32)));
61+
let w: Value<WithAnonField> = <Value<WithAnonField>>::default();
62+
(*(*w.borrow()).field.borrow_mut()) = (anon_enum_24::FIELD_A as anon_enum_24);
63+
assert!((((*(*w.borrow()).field.borrow()) as u32) == (anon_enum_24::FIELD_A as u32)));
64+
(*(*w.borrow()).field.borrow_mut()) = (anon_enum_24::FIELD_B as anon_enum_24);
65+
assert!((((*(*w.borrow()).field.borrow()) as u32) == (anon_enum_24::FIELD_B as u32)));
66+
return 0;
67+
}
Lines changed: 69 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,69 @@
1+
extern crate libc;
2+
use libc::*;
3+
extern crate libcc2rs;
4+
use libcc2rs::*;
5+
use std::collections::BTreeMap;
6+
use std::io::{Read, Seek, Write};
7+
use std::os::fd::{AsFd, FromRawFd, IntoRawFd};
8+
use std::rc::Rc;
9+
#[derive(Clone, Copy, PartialEq, Debug, Default)]
10+
enum anon_enum_3 {
11+
#[default]
12+
FIRST_A = 0,
13+
FIRST_B = 1,
14+
}
15+
#[derive(Clone, Copy, PartialEq, Debug, Default)]
16+
enum anon_enum_11 {
17+
#[default]
18+
SECOND_A = 0,
19+
SECOND_B = 1,
20+
}
21+
#[repr(C)]
22+
#[derive(Copy, Clone, Default)]
23+
pub struct S {
24+
pub a: i32,
25+
}
26+
#[derive(Clone, Copy, PartialEq, Debug, Default)]
27+
enum TdEnum {
28+
#[default]
29+
TD_A = 0,
30+
TD_B = 1,
31+
}
32+
#[derive(Clone, Copy, PartialEq, Debug, Default)]
33+
enum anon_enum_24 {
34+
#[default]
35+
FIELD_A = 0,
36+
FIELD_B = 1,
37+
}
38+
#[repr(C)]
39+
#[derive(Copy, Clone, Default)]
40+
pub struct WithAnonField {
41+
pub a: i32,
42+
pub field: anon_enum_24,
43+
}
44+
pub fn main() {
45+
unsafe {
46+
std::process::exit(main_0() as i32);
47+
}
48+
}
49+
unsafe fn main_0() -> i32 {
50+
#[derive(Clone, Copy, PartialEq, Debug, Default)]
51+
enum anon_enum_31 {
52+
#[default]
53+
THIRD_A = 0,
54+
THIRD_B = 1,
55+
};
56+
assert!(((anon_enum_3::FIRST_A as i32) != (anon_enum_3::FIRST_B as i32)));
57+
assert!(((anon_enum_11::SECOND_A as i32) != (anon_enum_11::SECOND_B as i32)));
58+
assert!(((anon_enum_31::THIRD_A as i32) != (anon_enum_31::THIRD_B as i32)));
59+
let mut td: TdEnum = TdEnum::TD_A;
60+
assert!(((td as i32) == (TdEnum::TD_A as i32)));
61+
td = (TdEnum::TD_B).clone();
62+
assert!(((td as i32) == (TdEnum::TD_B as i32)));
63+
let mut w: WithAnonField = <WithAnonField>::default();
64+
w.field = anon_enum_24::FIELD_A;
65+
assert!(((w.field as i32) == (anon_enum_24::FIELD_A as i32)));
66+
w.field = (anon_enum_24::FIELD_B).clone();
67+
assert!(((w.field as i32) == (anon_enum_24::FIELD_B as i32)));
68+
return 0;
69+
}

0 commit comments

Comments
 (0)