Skip to content

Commit b16c1d2

Browse files
garrisonemilio
authored andcommitted
Use C++ fixed-type enumeration syntax under C23 (or higher) as well
C23 [has introduced support for enumerations with fixed underlying type](https://open-std.org/JTC1/SC22/WG14/www/docs/n3030.htm), matching the existing C++ syntax for this functionality. This PR modifies cbindgen to output a header that enables this syntax if either `__cplusplus` is defined (as before) or if the compilation is according to C23 or later (added in this PR). My motivation for this change is that my toolchain complained that some names were defined twice, both as an enum and a typedef. I [fixed the error](https://github.com/Qiskit/Qiskit.jl/blob/73bfbb9440168dc76685632f9fb3d00d3a17bd79/gen/generator.jl#L16-L18) by defining `__cplusplus` even thought the compiler is compiling in C mode. This change will allow me to remove that workaround, as long as C23 or later is set as the C standard. Closes #1156
1 parent b68b027 commit b16c1d2

125 files changed

Lines changed: 2588 additions & 521 deletions

File tree

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

src/bindgen/ir/enumeration.rs

Lines changed: 38 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -680,15 +680,20 @@ impl Enum {
680680
}
681681
write!(out, " {tag_name}");
682682

683-
if config.cpp_compatible_c() {
684-
out.new_line();
685-
out.write("#ifdef __cplusplus");
686-
out.new_line();
687-
write!(out, " : {prim}");
688-
out.new_line();
689-
out.write("#endif // __cplusplus");
690-
out.new_line();
691-
}
683+
// Emit typed enum syntax (valid in C23 or later or C++)
684+
let cond = if config.cpp_compatible_c() {
685+
"defined(__cplusplus) || __STDC_VERSION__ >= 202311L"
686+
} else {
687+
"__STDC_VERSION__ >= 202311L"
688+
};
689+
690+
out.new_line();
691+
write!(out, "#if {cond}");
692+
out.new_line();
693+
write!(out, " : {prim}");
694+
out.new_line();
695+
write!(out, "#endif // {cond}");
696+
out.new_line();
692697
} else {
693698
if config.style.generate_typedef() {
694699
out.write("typedef ");
@@ -759,17 +764,39 @@ impl Enum {
759764
}
760765

761766
// Emit typedef specifying the tag enum's size if necessary.
762-
// In C++ enums can "inherit" from numeric types (`enum E: uint8_t { ... }`),
763-
// but in C `typedef uint8_t E` is the only way to give a fixed size to `E`.
767+
// In C++ or C23 enums can "inherit" from numeric types (`enum E: uint8_t { ... }`),
768+
// but in older versions of C `typedef uint8_t E` is the only way to give a fixed size to `E`.
764769
if let Some(prim) = size {
765770
if config.cpp_compatible_c() {
766771
out.new_line_if_not_start();
767772
out.write("#ifndef __cplusplus");
768773
}
769774

770775
if config.language != Language::Cxx {
776+
if config.language == Language::C {
777+
out.new_line();
778+
out.write("#if __STDC_VERSION__ >= 202311L");
779+
780+
out.new_line();
781+
write!(
782+
out,
783+
"{} enum {} {};",
784+
config.language.typedef(),
785+
tag_name,
786+
tag_name
787+
);
788+
789+
out.new_line();
790+
out.write("#else");
791+
}
792+
771793
out.new_line();
772794
write!(out, "{} {} {};", config.language.typedef(), prim, tag_name);
795+
796+
if config.language == Language::C {
797+
out.new_line();
798+
out.write("#endif // __STDC_VERSION__ >= 202311L");
799+
}
773800
}
774801

775802
if config.cpp_compatible_c() {

tests/expectations/alias.c

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,11 +3,19 @@
33
#include <stdint.h>
44
#include <stdlib.h>
55

6-
enum Status {
6+
enum Status
7+
#if __STDC_VERSION__ >= 202311L
8+
: uint32_t
9+
#endif // __STDC_VERSION__ >= 202311L
10+
{
711
Ok,
812
Err,
913
};
14+
#if __STDC_VERSION__ >= 202311L
15+
typedef enum Status Status;
16+
#else
1017
typedef uint32_t Status;
18+
#endif // __STDC_VERSION__ >= 202311L
1119

1220
typedef struct {
1321
int32_t a;

tests/expectations/alias.compat.c

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4,15 +4,19 @@
44
#include <stdlib.h>
55

66
enum Status
7-
#ifdef __cplusplus
7+
#if defined(__cplusplus) || __STDC_VERSION__ >= 202311L
88
: uint32_t
9-
#endif // __cplusplus
9+
#endif // defined(__cplusplus) || __STDC_VERSION__ >= 202311L
1010
{
1111
Ok,
1212
Err,
1313
};
1414
#ifndef __cplusplus
15+
#if __STDC_VERSION__ >= 202311L
16+
typedef enum Status Status;
17+
#else
1518
typedef uint32_t Status;
19+
#endif // __STDC_VERSION__ >= 202311L
1620
#endif // __cplusplus
1721

1822
typedef struct {

tests/expectations/alias_both.c

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,11 +3,19 @@
33
#include <stdint.h>
44
#include <stdlib.h>
55

6-
enum Status {
6+
enum Status
7+
#if __STDC_VERSION__ >= 202311L
8+
: uint32_t
9+
#endif // __STDC_VERSION__ >= 202311L
10+
{
711
Ok,
812
Err,
913
};
14+
#if __STDC_VERSION__ >= 202311L
15+
typedef enum Status Status;
16+
#else
1017
typedef uint32_t Status;
18+
#endif // __STDC_VERSION__ >= 202311L
1119

1220
typedef struct Dep {
1321
int32_t a;

tests/expectations/alias_both.compat.c

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4,15 +4,19 @@
44
#include <stdlib.h>
55

66
enum Status
7-
#ifdef __cplusplus
7+
#if defined(__cplusplus) || __STDC_VERSION__ >= 202311L
88
: uint32_t
9-
#endif // __cplusplus
9+
#endif // defined(__cplusplus) || __STDC_VERSION__ >= 202311L
1010
{
1111
Ok,
1212
Err,
1313
};
1414
#ifndef __cplusplus
15+
#if __STDC_VERSION__ >= 202311L
16+
typedef enum Status Status;
17+
#else
1518
typedef uint32_t Status;
19+
#endif // __STDC_VERSION__ >= 202311L
1620
#endif // __cplusplus
1721

1822
typedef struct Dep {

tests/expectations/alias_tag.c

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,11 +3,19 @@
33
#include <stdint.h>
44
#include <stdlib.h>
55

6-
enum Status {
6+
enum Status
7+
#if __STDC_VERSION__ >= 202311L
8+
: uint32_t
9+
#endif // __STDC_VERSION__ >= 202311L
10+
{
711
Ok,
812
Err,
913
};
14+
#if __STDC_VERSION__ >= 202311L
15+
typedef enum Status Status;
16+
#else
1017
typedef uint32_t Status;
18+
#endif // __STDC_VERSION__ >= 202311L
1119

1220
struct Dep {
1321
int32_t a;

tests/expectations/alias_tag.compat.c

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4,15 +4,19 @@
44
#include <stdlib.h>
55

66
enum Status
7-
#ifdef __cplusplus
7+
#if defined(__cplusplus) || __STDC_VERSION__ >= 202311L
88
: uint32_t
9-
#endif // __cplusplus
9+
#endif // defined(__cplusplus) || __STDC_VERSION__ >= 202311L
1010
{
1111
Ok,
1212
Err,
1313
};
1414
#ifndef __cplusplus
15+
#if __STDC_VERSION__ >= 202311L
16+
typedef enum Status Status;
17+
#else
1518
typedef uint32_t Status;
19+
#endif // __STDC_VERSION__ >= 202311L
1620
#endif // __cplusplus
1721

1822
struct Dep {

tests/expectations/annotation.c

Lines changed: 27 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -3,11 +3,19 @@
33
#include <stdint.h>
44
#include <stdlib.h>
55

6-
enum C {
6+
enum C
7+
#if __STDC_VERSION__ >= 202311L
8+
: uint32_t
9+
#endif // __STDC_VERSION__ >= 202311L
10+
{
711
X = 2,
812
Y,
913
};
14+
#if __STDC_VERSION__ >= 202311L
15+
typedef enum C C;
16+
#else
1017
typedef uint32_t C;
18+
#endif // __STDC_VERSION__ >= 202311L
1119

1220
typedef struct {
1321
int32_t m0;
@@ -18,12 +26,20 @@ typedef struct {
1826
float y;
1927
} B;
2028

21-
enum F_Tag {
29+
enum F_Tag
30+
#if __STDC_VERSION__ >= 202311L
31+
: uint8_t
32+
#endif // __STDC_VERSION__ >= 202311L
33+
{
2234
Foo,
2335
Bar,
2436
Baz,
2537
};
38+
#if __STDC_VERSION__ >= 202311L
39+
typedef enum F_Tag F_Tag;
40+
#else
2641
typedef uint8_t F_Tag;
42+
#endif // __STDC_VERSION__ >= 202311L
2743

2844
typedef struct {
2945
F_Tag tag;
@@ -40,12 +56,20 @@ typedef union {
4056
Bar_Body bar;
4157
} F;
4258

43-
enum H_Tag {
59+
enum H_Tag
60+
#if __STDC_VERSION__ >= 202311L
61+
: uint8_t
62+
#endif // __STDC_VERSION__ >= 202311L
63+
{
4464
Hello,
4565
There,
4666
Everyone,
4767
};
68+
#if __STDC_VERSION__ >= 202311L
69+
typedef enum H_Tag H_Tag;
70+
#else
4871
typedef uint8_t H_Tag;
72+
#endif // __STDC_VERSION__ >= 202311L
4973

5074
typedef struct {
5175
uint8_t x;

tests/expectations/annotation.compat.c

Lines changed: 18 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -4,15 +4,19 @@
44
#include <stdlib.h>
55

66
enum C
7-
#ifdef __cplusplus
7+
#if defined(__cplusplus) || __STDC_VERSION__ >= 202311L
88
: uint32_t
9-
#endif // __cplusplus
9+
#endif // defined(__cplusplus) || __STDC_VERSION__ >= 202311L
1010
{
1111
X = 2,
1212
Y,
1313
};
1414
#ifndef __cplusplus
15+
#if __STDC_VERSION__ >= 202311L
16+
typedef enum C C;
17+
#else
1518
typedef uint32_t C;
19+
#endif // __STDC_VERSION__ >= 202311L
1620
#endif // __cplusplus
1721

1822
typedef struct {
@@ -25,16 +29,20 @@ typedef struct {
2529
} B;
2630

2731
enum F_Tag
28-
#ifdef __cplusplus
32+
#if defined(__cplusplus) || __STDC_VERSION__ >= 202311L
2933
: uint8_t
30-
#endif // __cplusplus
34+
#endif // defined(__cplusplus) || __STDC_VERSION__ >= 202311L
3135
{
3236
Foo,
3337
Bar,
3438
Baz,
3539
};
3640
#ifndef __cplusplus
41+
#if __STDC_VERSION__ >= 202311L
42+
typedef enum F_Tag F_Tag;
43+
#else
3744
typedef uint8_t F_Tag;
45+
#endif // __STDC_VERSION__ >= 202311L
3846
#endif // __cplusplus
3947

4048
typedef struct {
@@ -53,16 +61,20 @@ typedef union {
5361
} F;
5462

5563
enum H_Tag
56-
#ifdef __cplusplus
64+
#if defined(__cplusplus) || __STDC_VERSION__ >= 202311L
5765
: uint8_t
58-
#endif // __cplusplus
66+
#endif // defined(__cplusplus) || __STDC_VERSION__ >= 202311L
5967
{
6068
Hello,
6169
There,
6270
Everyone,
6371
};
6472
#ifndef __cplusplus
73+
#if __STDC_VERSION__ >= 202311L
74+
typedef enum H_Tag H_Tag;
75+
#else
6576
typedef uint8_t H_Tag;
77+
#endif // __STDC_VERSION__ >= 202311L
6678
#endif // __cplusplus
6779

6880
typedef struct {

tests/expectations/annotation_both.c

Lines changed: 27 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -3,11 +3,19 @@
33
#include <stdint.h>
44
#include <stdlib.h>
55

6-
enum C {
6+
enum C
7+
#if __STDC_VERSION__ >= 202311L
8+
: uint32_t
9+
#endif // __STDC_VERSION__ >= 202311L
10+
{
711
X = 2,
812
Y,
913
};
14+
#if __STDC_VERSION__ >= 202311L
15+
typedef enum C C;
16+
#else
1017
typedef uint32_t C;
18+
#endif // __STDC_VERSION__ >= 202311L
1119

1220
typedef struct A {
1321
int32_t m0;
@@ -18,12 +26,20 @@ typedef struct B {
1826
float y;
1927
} B;
2028

21-
enum F_Tag {
29+
enum F_Tag
30+
#if __STDC_VERSION__ >= 202311L
31+
: uint8_t
32+
#endif // __STDC_VERSION__ >= 202311L
33+
{
2234
Foo,
2335
Bar,
2436
Baz,
2537
};
38+
#if __STDC_VERSION__ >= 202311L
39+
typedef enum F_Tag F_Tag;
40+
#else
2641
typedef uint8_t F_Tag;
42+
#endif // __STDC_VERSION__ >= 202311L
2743

2844
typedef struct Bar_Body {
2945
F_Tag tag;
@@ -40,12 +56,20 @@ typedef union F {
4056
Bar_Body bar;
4157
} F;
4258

43-
enum H_Tag {
59+
enum H_Tag
60+
#if __STDC_VERSION__ >= 202311L
61+
: uint8_t
62+
#endif // __STDC_VERSION__ >= 202311L
63+
{
4464
Hello,
4565
There,
4666
Everyone,
4767
};
68+
#if __STDC_VERSION__ >= 202311L
69+
typedef enum H_Tag H_Tag;
70+
#else
4871
typedef uint8_t H_Tag;
72+
#endif // __STDC_VERSION__ >= 202311L
4973

5074
typedef struct There_Body {
5175
uint8_t x;

0 commit comments

Comments
 (0)