Skip to content

Commit 6a9066f

Browse files
Evan Shawemilio
authored andcommitted
Add enum_class option
This option allows specifying that a C++ enum should be emitted with plain `enum` rather than `enum class`. It's true that `enum class` should generally be preferred, but sometimes there's existing code which is already using plain `enum`, and porting that code to Rust becomes easier when `cbindgen` can emit plain `enum`. This option can be overridden on a per-enum basis using a `cbindgen:` annotation. It defaults to true for two reasons: * Backward compatibility. * `enum class` is probably actually what you want, in general.
1 parent 16fe3ec commit 6a9066f

File tree

12 files changed

+272
-12
lines changed

12 files changed

+272
-12
lines changed

docs.md

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -269,6 +269,7 @@ The rest are just local overrides for the same options found in the cbindgen.tom
269269
* derive-mut-casts
270270
* derive-tagged-enum-destructor
271271
* derive-tagged-enum-copy-constructor
272+
* enum-class
272273
* prefix-with-name
273274
* private-default-tagged-enum-constructor
274275

@@ -672,6 +673,10 @@ add_sentinel = false
672673
# default: false
673674
prefix_with_name = false
674675

676+
# Whether to emit enums using "enum class" when targeting C++.
677+
# default: true
678+
enum_class = true
679+
675680
# Whether to generate static `::MyVariant(..)` constructors and `bool IsMyVariant()`
676681
# methods for enums with fields.
677682
#

src/bindgen/config.rs

Lines changed: 30 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -391,7 +391,7 @@ impl StructConfig {
391391
}
392392

393393
/// Settings to apply to generated enums.
394-
#[derive(Debug, Clone, Default, Deserialize)]
394+
#[derive(Debug, Clone, Deserialize)]
395395
#[serde(rename_all = "snake_case")]
396396
#[serde(deny_unknown_fields)]
397397
#[serde(default)]
@@ -425,11 +425,34 @@ pub struct EnumConfig {
425425
/// This is only generated if a copy constructor for the same tagged enum is
426426
/// generated as well.
427427
pub derive_tagged_enum_copy_assignment: bool,
428+
/// Declare the enum as an enum class.
429+
/// Only relevant when targeting C++.
430+
pub enum_class: bool,
428431
/// Whether to generate empty, private default-constructors for tagged
429432
/// enums.
430433
pub private_default_tagged_enum_constructor: bool,
431434
}
432435

436+
impl Default for EnumConfig {
437+
fn default() -> EnumConfig {
438+
EnumConfig {
439+
rename_variants: None,
440+
add_sentinel: false,
441+
prefix_with_name: false,
442+
derive_helper_methods: false,
443+
derive_const_casts: false,
444+
derive_mut_casts: false,
445+
cast_assert_name: None,
446+
must_use: None,
447+
derive_tagged_enum_destructor: false,
448+
derive_tagged_enum_copy_constructor: false,
449+
derive_tagged_enum_copy_assignment: false,
450+
enum_class: true,
451+
private_default_tagged_enum_constructor: false,
452+
}
453+
}
454+
}
455+
433456
impl EnumConfig {
434457
pub(crate) fn add_sentinel(&self, annotations: &AnnotationSet) -> bool {
435458
if let Some(x) = annotations.bool("add-sentinel") {
@@ -473,6 +496,12 @@ impl EnumConfig {
473496
}
474497
self.derive_tagged_enum_copy_assignment
475498
}
499+
pub(crate) fn enum_class(&self, annotations: &AnnotationSet) -> bool {
500+
if let Some(x) = annotations.bool("enum-class") {
501+
return x;
502+
}
503+
self.enum_class
504+
}
476505
pub(crate) fn private_default_tagged_enum_constructor(
477506
&self,
478507
annotations: &AnnotationSet,

src/bindgen/ir/enumeration.rs

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -559,7 +559,11 @@ impl Source for Enum {
559559
}
560560
}
561561
} else {
562-
out.write("enum class");
562+
if config.enumeration.enum_class(&self.annotations) {
563+
out.write("enum class");
564+
} else {
565+
out.write("enum");
566+
}
563567

564568
if self.annotations.must_use {
565569
if let Some(ref anno) = config.enumeration.must_use {

template.toml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -103,6 +103,7 @@ derive_mut_casts = false
103103
# cast_assert_name = "ASSERT"
104104
derive_tagged_enum_destructor = false
105105
derive_tagged_enum_copy_constructor = false
106+
enum_class = true
106107
private_default_tagged_enum_constructor = false
107108

108109

tests/expectations/both/enum.c

Lines changed: 31 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -65,6 +65,21 @@ enum M {
6565
};
6666
typedef int8_t M;
6767

68+
typedef enum N {
69+
n1,
70+
n2,
71+
n3,
72+
n4,
73+
} N;
74+
75+
enum O {
76+
o1,
77+
o2,
78+
o3,
79+
o4,
80+
};
81+
typedef int8_t O;
82+
6883
typedef struct J J;
6984

7085
typedef struct K K;
@@ -142,4 +157,19 @@ typedef struct I {
142157
};
143158
} I;
144159

145-
void root(Opaque *o, A a, B b, C c, D d, E e, F f, G g, H h, I i, J j, K k, L l, M m);
160+
void root(Opaque *opaque,
161+
A a,
162+
B b,
163+
C c,
164+
D d,
165+
E e,
166+
F f,
167+
G g,
168+
H h,
169+
I i,
170+
J j,
171+
K k,
172+
L l,
173+
M m,
174+
N n,
175+
O o);

tests/expectations/both/enum.compat.c

Lines changed: 37 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -107,6 +107,27 @@ enum M
107107
typedef int8_t M;
108108
#endif // __cplusplus
109109

110+
typedef enum N {
111+
n1,
112+
n2,
113+
n3,
114+
n4,
115+
} N;
116+
117+
enum O
118+
#ifdef __cplusplus
119+
: int8_t
120+
#endif // __cplusplus
121+
{
122+
o1,
123+
o2,
124+
o3,
125+
o4,
126+
};
127+
#ifndef __cplusplus
128+
typedef int8_t O;
129+
#endif // __cplusplus
130+
110131
typedef struct J J;
111132

112133
typedef struct K K;
@@ -200,7 +221,22 @@ typedef struct I {
200221
extern "C" {
201222
#endif // __cplusplus
202223

203-
void root(Opaque *o, A a, B b, C c, D d, E e, F f, G g, H h, I i, J j, K k, L l, M m);
224+
void root(Opaque *opaque,
225+
A a,
226+
B b,
227+
C c,
228+
D d,
229+
E e,
230+
F f,
231+
G g,
232+
H h,
233+
I i,
234+
J j,
235+
K k,
236+
L l,
237+
M m,
238+
N n,
239+
O o);
204240

205241
#ifdef __cplusplus
206242
} // extern "C"

tests/expectations/enum.c

Lines changed: 31 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -65,6 +65,21 @@ enum M {
6565
};
6666
typedef int8_t M;
6767

68+
typedef enum {
69+
n1,
70+
n2,
71+
n3,
72+
n4,
73+
} N;
74+
75+
enum O {
76+
o1,
77+
o2,
78+
o3,
79+
o4,
80+
};
81+
typedef int8_t O;
82+
6883
typedef struct J J;
6984

7085
typedef struct K K;
@@ -142,4 +157,19 @@ typedef struct {
142157
};
143158
} I;
144159

145-
void root(Opaque *o, A a, B b, C c, D d, E e, F f, G g, H h, I i, J j, K k, L l, M m);
160+
void root(Opaque *opaque,
161+
A a,
162+
B b,
163+
C c,
164+
D d,
165+
E e,
166+
F f,
167+
G g,
168+
H h,
169+
I i,
170+
J j,
171+
K k,
172+
L l,
173+
M m,
174+
N n,
175+
O o);

tests/expectations/enum.compat.c

Lines changed: 37 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -107,6 +107,27 @@ enum M
107107
typedef int8_t M;
108108
#endif // __cplusplus
109109

110+
typedef enum {
111+
n1,
112+
n2,
113+
n3,
114+
n4,
115+
} N;
116+
117+
enum O
118+
#ifdef __cplusplus
119+
: int8_t
120+
#endif // __cplusplus
121+
{
122+
o1,
123+
o2,
124+
o3,
125+
o4,
126+
};
127+
#ifndef __cplusplus
128+
typedef int8_t O;
129+
#endif // __cplusplus
130+
110131
typedef struct J J;
111132

112133
typedef struct K K;
@@ -200,7 +221,22 @@ typedef struct {
200221
extern "C" {
201222
#endif // __cplusplus
202223

203-
void root(Opaque *o, A a, B b, C c, D d, E e, F f, G g, H h, I i, J j, K k, L l, M m);
224+
void root(Opaque *opaque,
225+
A a,
226+
B b,
227+
C c,
228+
D d,
229+
E e,
230+
F f,
231+
G g,
232+
H h,
233+
I i,
234+
J j,
235+
K k,
236+
L l,
237+
M m,
238+
N n,
239+
O o);
204240

205241
#ifdef __cplusplus
206242
} // extern "C"

tests/expectations/enum.cpp

Lines changed: 30 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -58,6 +58,20 @@ enum class M : int8_t {
5858
m3 = 1,
5959
};
6060

61+
enum N {
62+
n1,
63+
n2,
64+
n3,
65+
n4,
66+
};
67+
68+
enum O : int8_t {
69+
o1,
70+
o2,
71+
o3,
72+
o4,
73+
};
74+
6175
struct J;
6276

6377
struct K;
@@ -137,6 +151,21 @@ struct I {
137151

138152
extern "C" {
139153

140-
void root(Opaque *o, A a, B b, C c, D d, E e, F f, G g, H h, I i, J j, K k, L l, M m);
154+
void root(Opaque *opaque,
155+
A a,
156+
B b,
157+
C c,
158+
D d,
159+
E e,
160+
F f,
161+
G g,
162+
H h,
163+
I i,
164+
J j,
165+
K k,
166+
L l,
167+
M m,
168+
N n,
169+
O o);
141170

142171
} // extern "C"

tests/expectations/tag/enum.c

Lines changed: 19 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -65,6 +65,21 @@ enum M {
6565
};
6666
typedef int8_t M;
6767

68+
enum N {
69+
n1,
70+
n2,
71+
n3,
72+
n4,
73+
};
74+
75+
enum O {
76+
o1,
77+
o2,
78+
o3,
79+
o4,
80+
};
81+
typedef int8_t O;
82+
6883
struct J;
6984

7085
struct K;
@@ -142,7 +157,7 @@ struct I {
142157
};
143158
};
144159

145-
void root(struct Opaque *o,
160+
void root(struct Opaque *opaque,
146161
A a,
147162
B b,
148163
C c,
@@ -155,4 +170,6 @@ void root(struct Opaque *o,
155170
struct J j,
156171
struct K k,
157172
enum L l,
158-
M m);
173+
M m,
174+
enum N n,
175+
O o);

0 commit comments

Comments
 (0)