Skip to content

Commit e35f62a

Browse files
authored
Fix name clash between anon enums across TU (#171)
`return std::format("anon_enum_{}", GetLineNumber(enum_decl));` results in name clashes between enums declared in different files at the same line, I replaced that with `return GetNamedDeclAsString(enum_decl);`
1 parent 3995dc6 commit e35f62a

11 files changed

Lines changed: 287 additions & 149 deletions

File tree

cpp2rust/converter/converter_lib.cpp

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -416,9 +416,10 @@ std::string GetNamedDeclAsString(const clang::NamedDecl *decl) {
416416
auto name = decl->getDeclName().isIdentifier() ? decl->getName().str()
417417
: decl->getNameAsString();
418418

419-
// Anonymous record
419+
// Anonymous record or enum
420420
if (name.empty() && (clang::isa<clang::RecordDecl>(decl) ||
421-
clang::isa<clang::FieldDecl>(decl))) {
421+
clang::isa<clang::FieldDecl>(decl) ||
422+
clang::isa<clang::EnumDecl>(decl))) {
422423
const clang::NamedDecl *target = decl;
423424
if (auto *field = clang::dyn_cast<clang::FieldDecl>(decl)) {
424425
if (auto *record = field->getType()->getAsRecordDecl();

cpp2rust/converter/mapper.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -765,7 +765,7 @@ std::string ToString(const clang::NamedDecl *decl) {
765765
}
766766
if (!enum_decl->getIdentifier() &&
767767
!enum_decl->getTypedefNameForAnonDecl()) {
768-
return std::format("anon_enum_{}", GetLineNumber(enum_decl));
768+
return GetNamedDeclAsString(enum_decl);
769769
}
770770
}
771771

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
cmake_minimum_required(VERSION 3.16)
2+
project(cross_tu_anon_enum_collision LANGUAGES C)
3+
add_executable(app a.c b.c)
Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
#include <assert.h>
2+
// anon enum below shares the same declaration line as b.c:enum { BETA = 9 }
3+
enum { ALPHA = 7 };
4+
5+
int b_value(void);
6+
7+
int a_value(void) {
8+
int x = 0;
9+
x |= ALPHA;
10+
return x;
11+
}
12+
13+
int main(void) {
14+
assert(a_value() == 7);
15+
assert(b_value() == 9);
16+
return 0;
17+
}
Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
// anon enum below shares the same declaration line as b.c:enum { ALPHA = 7 }
2+
3+
enum { BETA = 9 };
4+
5+
int b_value(void) {
6+
int x = 0;
7+
x |= BETA;
8+
return x;
9+
}
Lines changed: 54 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,54 @@
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_0 {
11+
#[default]
12+
ALPHA = 7,
13+
}
14+
impl From<i32> for anon_0 {
15+
fn from(n: i32) -> anon_0 {
16+
match n {
17+
7 => anon_0::ALPHA,
18+
_ => panic!("invalid anon_0 value: {}", n),
19+
}
20+
}
21+
}
22+
libcc2rs::impl_enum_inc_dec!(anon_0);
23+
pub fn a_value_1() -> i32 {
24+
let x: Value<i32> = Rc::new(RefCell::new(0));
25+
(*x.borrow_mut()) |= (anon_0::ALPHA as i32);
26+
return (*x.borrow());
27+
}
28+
pub fn main() {
29+
std::process::exit(main_0());
30+
}
31+
fn main_0() -> i32 {
32+
assert!((((({ a_value_1() }) == 7) as i32) != 0));
33+
assert!((((({ b_value_2() }) == 9) as i32) != 0));
34+
return 0;
35+
}
36+
#[derive(Clone, Copy, PartialEq, Debug, Default)]
37+
enum anon_3 {
38+
#[default]
39+
BETA = 9,
40+
}
41+
impl From<i32> for anon_3 {
42+
fn from(n: i32) -> anon_3 {
43+
match n {
44+
9 => anon_3::BETA,
45+
_ => panic!("invalid anon_3 value: {}", n),
46+
}
47+
}
48+
}
49+
libcc2rs::impl_enum_inc_dec!(anon_3);
50+
pub fn b_value_2() -> i32 {
51+
let x: Value<i32> = Rc::new(RefCell::new(0));
52+
(*x.borrow_mut()) |= (anon_3::BETA as i32);
53+
return (*x.borrow());
54+
}
Lines changed: 56 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,56 @@
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_0 {
11+
#[default]
12+
ALPHA = 7,
13+
}
14+
impl From<i32> for anon_0 {
15+
fn from(n: i32) -> anon_0 {
16+
match n {
17+
7 => anon_0::ALPHA,
18+
_ => panic!("invalid anon_0 value: {}", n),
19+
}
20+
}
21+
}
22+
libcc2rs::impl_enum_inc_dec!(anon_0);
23+
pub unsafe fn a_value_1() -> i32 {
24+
let mut x: i32 = 0;
25+
x |= (anon_0::ALPHA as i32);
26+
return x;
27+
}
28+
pub fn main() {
29+
unsafe {
30+
std::process::exit(main_0() as i32);
31+
}
32+
}
33+
unsafe fn main_0() -> i32 {
34+
assert!(((((unsafe { a_value_1() }) == (7)) as i32) != 0));
35+
assert!(((((unsafe { b_value_2() }) == (9)) as i32) != 0));
36+
return 0;
37+
}
38+
#[derive(Clone, Copy, PartialEq, Debug, Default)]
39+
enum anon_3 {
40+
#[default]
41+
BETA = 9,
42+
}
43+
impl From<i32> for anon_3 {
44+
fn from(n: i32) -> anon_3 {
45+
match n {
46+
9 => anon_3::BETA,
47+
_ => panic!("invalid anon_3 value: {}", n),
48+
}
49+
}
50+
}
51+
libcc2rs::impl_enum_inc_dec!(anon_3);
52+
pub unsafe fn b_value_2() -> i32 {
53+
let mut x: i32 = 0;
54+
x |= (anon_3::BETA as i32);
55+
return x;
56+
}

tests/unit/out/refcount/anonymous_enum.rs

Lines changed: 36 additions & 36 deletions
Original file line numberDiff line numberDiff line change
@@ -7,37 +7,37 @@ use std::io::{Read, Seek, Write};
77
use std::os::fd::AsFd;
88
use std::rc::{Rc, Weak};
99
#[derive(Clone, Copy, PartialEq, Debug, Default)]
10-
enum anon_enum_3 {
10+
enum anon_0 {
1111
#[default]
1212
FIRST_A = 0,
1313
FIRST_B = 1,
1414
}
15-
impl From<i32> for anon_enum_3 {
16-
fn from(n: i32) -> anon_enum_3 {
15+
impl From<i32> for anon_0 {
16+
fn from(n: i32) -> anon_0 {
1717
match n {
18-
0 => anon_enum_3::FIRST_A,
19-
1 => anon_enum_3::FIRST_B,
20-
_ => panic!("invalid anon_enum_3 value: {}", n),
18+
0 => anon_0::FIRST_A,
19+
1 => anon_0::FIRST_B,
20+
_ => panic!("invalid anon_0 value: {}", n),
2121
}
2222
}
2323
}
24-
libcc2rs::impl_enum_inc_dec!(anon_enum_3);
24+
libcc2rs::impl_enum_inc_dec!(anon_0);
2525
#[derive(Clone, Copy, PartialEq, Debug, Default)]
26-
enum anon_enum_11 {
26+
enum anon_1 {
2727
#[default]
2828
SECOND_A = 0,
2929
SECOND_B = 1,
3030
}
31-
impl From<i32> for anon_enum_11 {
32-
fn from(n: i32) -> anon_enum_11 {
31+
impl From<i32> for anon_1 {
32+
fn from(n: i32) -> anon_1 {
3333
match n {
34-
0 => anon_enum_11::SECOND_A,
35-
1 => anon_enum_11::SECOND_B,
36-
_ => panic!("invalid anon_enum_11 value: {}", n),
34+
0 => anon_1::SECOND_A,
35+
1 => anon_1::SECOND_B,
36+
_ => panic!("invalid anon_1 value: {}", n),
3737
}
3838
}
3939
}
40-
libcc2rs::impl_enum_inc_dec!(anon_enum_11);
40+
libcc2rs::impl_enum_inc_dec!(anon_1);
4141
#[derive(Default)]
4242
pub struct S {
4343
pub a: Value<i32>,
@@ -77,25 +77,25 @@ impl From<i32> for TdEnum {
7777
}
7878
libcc2rs::impl_enum_inc_dec!(TdEnum);
7979
#[derive(Clone, Copy, PartialEq, Debug, Default)]
80-
enum anon_enum_24 {
80+
enum anon_2 {
8181
#[default]
8282
FIELD_A = 0,
8383
FIELD_B = 1,
8484
}
85-
impl From<i32> for anon_enum_24 {
86-
fn from(n: i32) -> anon_enum_24 {
85+
impl From<i32> for anon_2 {
86+
fn from(n: i32) -> anon_2 {
8787
match n {
88-
0 => anon_enum_24::FIELD_A,
89-
1 => anon_enum_24::FIELD_B,
90-
_ => panic!("invalid anon_enum_24 value: {}", n),
88+
0 => anon_2::FIELD_A,
89+
1 => anon_2::FIELD_B,
90+
_ => panic!("invalid anon_2 value: {}", n),
9191
}
9292
}
9393
}
94-
libcc2rs::impl_enum_inc_dec!(anon_enum_24);
94+
libcc2rs::impl_enum_inc_dec!(anon_2);
9595
#[derive(Default)]
9696
pub struct WithAnonField {
9797
pub a: Value<i32>,
98-
pub field: Value<anon_enum_24>,
98+
pub field: Value<anon_2>,
9999
}
100100
impl Clone for WithAnonField {
101101
fn clone(&self) -> Self {
@@ -112,32 +112,32 @@ pub fn main() {
112112
}
113113
fn main_0() -> i32 {
114114
#[derive(Clone, Copy, PartialEq, Debug, Default)]
115-
enum anon_enum_31 {
115+
enum anon_3 {
116116
#[default]
117117
THIRD_A = 0,
118118
THIRD_B = 1,
119119
}
120-
impl From<i32> for anon_enum_31 {
121-
fn from(n: i32) -> anon_enum_31 {
120+
impl From<i32> for anon_3 {
121+
fn from(n: i32) -> anon_3 {
122122
match n {
123-
0 => anon_enum_31::THIRD_A,
124-
1 => anon_enum_31::THIRD_B,
125-
_ => panic!("invalid anon_enum_31 value: {}", n),
123+
0 => anon_3::THIRD_A,
124+
1 => anon_3::THIRD_B,
125+
_ => panic!("invalid anon_3 value: {}", n),
126126
}
127127
}
128128
}
129-
libcc2rs::impl_enum_inc_dec!(anon_enum_31);
130-
assert!(((anon_enum_3::FIRST_A as i32) != (anon_enum_3::FIRST_B as i32)));
131-
assert!(((anon_enum_11::SECOND_A as i32) != (anon_enum_11::SECOND_B as i32)));
132-
assert!(((anon_enum_31::THIRD_A as i32) != (anon_enum_31::THIRD_B as i32)));
129+
libcc2rs::impl_enum_inc_dec!(anon_3);
130+
assert!(((anon_0::FIRST_A as i32) != (anon_0::FIRST_B as i32)));
131+
assert!(((anon_1::SECOND_A as i32) != (anon_1::SECOND_B as i32)));
132+
assert!(((anon_3::THIRD_A as i32) != (anon_3::THIRD_B as i32)));
133133
let td: Value<TdEnum> = Rc::new(RefCell::new(TdEnum::TD_A));
134134
assert!((((*td.borrow()) as i32) == (TdEnum::TD_A as i32)));
135135
(*td.borrow_mut()) = TdEnum::TD_B;
136136
assert!((((*td.borrow()) as i32) == (TdEnum::TD_B as i32)));
137137
let w: Value<WithAnonField> = Rc::new(RefCell::new(<WithAnonField>::default()));
138-
(*(*w.borrow()).field.borrow_mut()) = anon_enum_24::FIELD_A;
139-
assert!((((*(*w.borrow()).field.borrow()) as i32) == (anon_enum_24::FIELD_A as i32)));
140-
(*(*w.borrow()).field.borrow_mut()) = anon_enum_24::FIELD_B;
141-
assert!((((*(*w.borrow()).field.borrow()) as i32) == (anon_enum_24::FIELD_B as i32)));
138+
(*(*w.borrow()).field.borrow_mut()) = anon_2::FIELD_A;
139+
assert!((((*(*w.borrow()).field.borrow()) as i32) == (anon_2::FIELD_A as i32)));
140+
(*(*w.borrow()).field.borrow_mut()) = anon_2::FIELD_B;
141+
assert!((((*(*w.borrow()).field.borrow()) as i32) == (anon_2::FIELD_B as i32)));
142142
return 0;
143143
}

0 commit comments

Comments
 (0)