Skip to content

Commit

Permalink
Add enum_class option
Browse files Browse the repository at this point in the history
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.
  • Loading branch information
edsrzf authored and emilio committed Dec 29, 2019
1 parent 16fe3ec commit 6a9066f
Show file tree
Hide file tree
Showing 12 changed files with 272 additions and 12 deletions.
5 changes: 5 additions & 0 deletions docs.md
Original file line number Diff line number Diff line change
Expand Up @@ -269,6 +269,7 @@ The rest are just local overrides for the same options found in the cbindgen.tom
* derive-mut-casts
* derive-tagged-enum-destructor
* derive-tagged-enum-copy-constructor
* enum-class
* prefix-with-name
* private-default-tagged-enum-constructor

Expand Down Expand Up @@ -672,6 +673,10 @@ add_sentinel = false
# default: false
prefix_with_name = false

# Whether to emit enums using "enum class" when targeting C++.
# default: true
enum_class = true

# Whether to generate static `::MyVariant(..)` constructors and `bool IsMyVariant()`
# methods for enums with fields.
#
Expand Down
31 changes: 30 additions & 1 deletion src/bindgen/config.rs
Original file line number Diff line number Diff line change
Expand Up @@ -391,7 +391,7 @@ impl StructConfig {
}

/// Settings to apply to generated enums.
#[derive(Debug, Clone, Default, Deserialize)]
#[derive(Debug, Clone, Deserialize)]
#[serde(rename_all = "snake_case")]
#[serde(deny_unknown_fields)]
#[serde(default)]
Expand Down Expand Up @@ -425,11 +425,34 @@ pub struct EnumConfig {
/// This is only generated if a copy constructor for the same tagged enum is
/// generated as well.
pub derive_tagged_enum_copy_assignment: bool,
/// Declare the enum as an enum class.
/// Only relevant when targeting C++.
pub enum_class: bool,
/// Whether to generate empty, private default-constructors for tagged
/// enums.
pub private_default_tagged_enum_constructor: bool,
}

impl Default for EnumConfig {
fn default() -> EnumConfig {
EnumConfig {
rename_variants: None,
add_sentinel: false,
prefix_with_name: false,
derive_helper_methods: false,
derive_const_casts: false,
derive_mut_casts: false,
cast_assert_name: None,
must_use: None,
derive_tagged_enum_destructor: false,
derive_tagged_enum_copy_constructor: false,
derive_tagged_enum_copy_assignment: false,
enum_class: true,
private_default_tagged_enum_constructor: false,
}
}
}

impl EnumConfig {
pub(crate) fn add_sentinel(&self, annotations: &AnnotationSet) -> bool {
if let Some(x) = annotations.bool("add-sentinel") {
Expand Down Expand Up @@ -473,6 +496,12 @@ impl EnumConfig {
}
self.derive_tagged_enum_copy_assignment
}
pub(crate) fn enum_class(&self, annotations: &AnnotationSet) -> bool {
if let Some(x) = annotations.bool("enum-class") {
return x;
}
self.enum_class
}
pub(crate) fn private_default_tagged_enum_constructor(
&self,
annotations: &AnnotationSet,
Expand Down
6 changes: 5 additions & 1 deletion src/bindgen/ir/enumeration.rs
Original file line number Diff line number Diff line change
Expand Up @@ -559,7 +559,11 @@ impl Source for Enum {
}
}
} else {
out.write("enum class");
if config.enumeration.enum_class(&self.annotations) {
out.write("enum class");
} else {
out.write("enum");
}

if self.annotations.must_use {
if let Some(ref anno) = config.enumeration.must_use {
Expand Down
1 change: 1 addition & 0 deletions template.toml
Original file line number Diff line number Diff line change
Expand Up @@ -103,6 +103,7 @@ derive_mut_casts = false
# cast_assert_name = "ASSERT"
derive_tagged_enum_destructor = false
derive_tagged_enum_copy_constructor = false
enum_class = true
private_default_tagged_enum_constructor = false


Expand Down
32 changes: 31 additions & 1 deletion tests/expectations/both/enum.c
Original file line number Diff line number Diff line change
Expand Up @@ -65,6 +65,21 @@ enum M {
};
typedef int8_t M;

typedef enum N {
n1,
n2,
n3,
n4,
} N;

enum O {
o1,
o2,
o3,
o4,
};
typedef int8_t O;

typedef struct J J;

typedef struct K K;
Expand Down Expand Up @@ -142,4 +157,19 @@ typedef struct I {
};
} I;

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);
void root(Opaque *opaque,
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,
N n,
O o);
38 changes: 37 additions & 1 deletion tests/expectations/both/enum.compat.c
Original file line number Diff line number Diff line change
Expand Up @@ -107,6 +107,27 @@ enum M
typedef int8_t M;
#endif // __cplusplus

typedef enum N {
n1,
n2,
n3,
n4,
} N;

enum O
#ifdef __cplusplus
: int8_t
#endif // __cplusplus
{
o1,
o2,
o3,
o4,
};
#ifndef __cplusplus
typedef int8_t O;
#endif // __cplusplus

typedef struct J J;

typedef struct K K;
Expand Down Expand Up @@ -200,7 +221,22 @@ typedef struct I {
extern "C" {
#endif // __cplusplus

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);
void root(Opaque *opaque,
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,
N n,
O o);

#ifdef __cplusplus
} // extern "C"
Expand Down
32 changes: 31 additions & 1 deletion tests/expectations/enum.c
Original file line number Diff line number Diff line change
Expand Up @@ -65,6 +65,21 @@ enum M {
};
typedef int8_t M;

typedef enum {
n1,
n2,
n3,
n4,
} N;

enum O {
o1,
o2,
o3,
o4,
};
typedef int8_t O;

typedef struct J J;

typedef struct K K;
Expand Down Expand Up @@ -142,4 +157,19 @@ typedef struct {
};
} I;

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);
void root(Opaque *opaque,
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,
N n,
O o);
38 changes: 37 additions & 1 deletion tests/expectations/enum.compat.c
Original file line number Diff line number Diff line change
Expand Up @@ -107,6 +107,27 @@ enum M
typedef int8_t M;
#endif // __cplusplus

typedef enum {
n1,
n2,
n3,
n4,
} N;

enum O
#ifdef __cplusplus
: int8_t
#endif // __cplusplus
{
o1,
o2,
o3,
o4,
};
#ifndef __cplusplus
typedef int8_t O;
#endif // __cplusplus

typedef struct J J;

typedef struct K K;
Expand Down Expand Up @@ -200,7 +221,22 @@ typedef struct {
extern "C" {
#endif // __cplusplus

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);
void root(Opaque *opaque,
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,
N n,
O o);

#ifdef __cplusplus
} // extern "C"
Expand Down
31 changes: 30 additions & 1 deletion tests/expectations/enum.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -58,6 +58,20 @@ enum class M : int8_t {
m3 = 1,
};

enum N {
n1,
n2,
n3,
n4,
};

enum O : int8_t {
o1,
o2,
o3,
o4,
};

struct J;

struct K;
Expand Down Expand Up @@ -137,6 +151,21 @@ struct I {

extern "C" {

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);
void root(Opaque *opaque,
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,
N n,
O o);

} // extern "C"
21 changes: 19 additions & 2 deletions tests/expectations/tag/enum.c
Original file line number Diff line number Diff line change
Expand Up @@ -65,6 +65,21 @@ enum M {
};
typedef int8_t M;

enum N {
n1,
n2,
n3,
n4,
};

enum O {
o1,
o2,
o3,
o4,
};
typedef int8_t O;

struct J;

struct K;
Expand Down Expand Up @@ -142,7 +157,7 @@ struct I {
};
};

void root(struct Opaque *o,
void root(struct Opaque *opaque,
A a,
B b,
C c,
Expand All @@ -155,4 +170,6 @@ void root(struct Opaque *o,
struct J j,
struct K k,
enum L l,
M m);
M m,
enum N n,
O o);
Loading

0 comments on commit 6a9066f

Please sign in to comment.