Skip to content

Commit 20c9e80

Browse files
committed
Fix generic enum variant body collisions
1 parent 4acf942 commit 20c9e80

14 files changed

Lines changed: 491 additions & 28 deletions

src/bindgen/ir/enumeration.rs

Lines changed: 30 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -164,33 +164,35 @@ impl EnumVariant {
164164
let body = match variant.fields {
165165
syn::Fields::Unit => VariantBody::Empty(annotations),
166166
syn::Fields::Named(ref fields) => {
167-
let path = Path::new(format!("{}_Body", variant.ident));
167+
let path = Path::new(format!("{}_{}_Body", self_path.name(), variant.ident));
168168
let name = body_rule
169169
.apply(
170170
&variant.ident.unraw().to_string(),
171171
IdentifierType::StructMember,
172172
)
173173
.into_owned();
174+
let mut body = Struct::new(
175+
path,
176+
generic_params,
177+
parse_fields(inline_tag_field, &fields.named, self_path, None)?,
178+
inline_tag_field,
179+
true,
180+
None,
181+
false,
182+
None,
183+
annotations,
184+
Documentation::none(),
185+
);
186+
body.export_name = format!("{}_Body", variant.ident);
174187
VariantBody::Body {
175-
body: Struct::new(
176-
path,
177-
generic_params,
178-
parse_fields(inline_tag_field, &fields.named, self_path, None)?,
179-
inline_tag_field,
180-
true,
181-
None,
182-
false,
183-
None,
184-
annotations,
185-
Documentation::none(),
186-
),
188+
body,
187189
name,
188190
inline: false,
189191
inline_casts: false,
190192
}
191193
}
192194
syn::Fields::Unnamed(ref fields) => {
193-
let path = Path::new(format!("{}_Body", variant.ident));
195+
let path = Path::new(format!("{}_{}_Body", self_path.name(), variant.ident));
194196
let name = body_rule
195197
.apply(
196198
&variant.ident.unraw().to_string(),
@@ -205,19 +207,21 @@ impl EnumVariant {
205207
// As a result we don't currently inline variant definitions in C++ mode at all.
206208
let inline = inline_casts && config.language != Language::Cxx;
207209
let inline_name = if inline { Some(&*name) } else { None };
210+
let mut body = Struct::new(
211+
path,
212+
generic_params,
213+
parse_fields(inline_tag_field, &fields.unnamed, self_path, inline_name)?,
214+
inline_tag_field,
215+
true,
216+
None,
217+
false,
218+
None,
219+
annotations,
220+
Documentation::none(),
221+
);
222+
body.export_name = format!("{}_Body", variant.ident);
208223
VariantBody::Body {
209-
body: Struct::new(
210-
path,
211-
generic_params,
212-
parse_fields(inline_tag_field, &fields.unnamed, self_path, inline_name)?,
213-
inline_tag_field,
214-
true,
215-
None,
216-
false,
217-
None,
218-
annotations,
219-
Documentation::none(),
220-
),
224+
body,
221225
name,
222226
inline,
223227
inline_casts,

src/bindgen/ir/structure.rs

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -199,7 +199,9 @@ impl Struct {
199199
config: &Config,
200200
) -> Self {
201201
let mangled_path = mangle::mangle_path(&self.path, generic_values, &config.export.mangle);
202-
Struct::new(
202+
let mangled_export_name =
203+
mangle::mangle_name(&self.export_name, generic_values, &config.export.mangle);
204+
let mut specialized = Struct::new(
203205
mangled_path,
204206
GenericParams::default(),
205207
self.fields
@@ -219,7 +221,9 @@ impl Struct {
219221
self.cfg.clone(),
220222
self.annotations.clone(),
221223
self.documentation.clone(),
222-
)
224+
);
225+
specialized.export_name = mangled_export_name;
226+
specialized
223227
}
224228

225229
pub(crate) fn emit_bitflags_binop<F: Write>(
Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
{
2+
use_a;
3+
use_b;
4+
};
Lines changed: 46 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,46 @@
1+
#include <stdarg.h>
2+
#include <stdbool.h>
3+
#include <stdint.h>
4+
#include <stdlib.h>
5+
6+
typedef struct {
7+
int32_t x;
8+
} Payload;
9+
10+
typedef enum {
11+
ResultA_Payload_Ok_Payload,
12+
ResultA_Payload_Err_Payload,
13+
} ResultA_Payload_Tag;
14+
15+
typedef struct {
16+
ResultA_Payload_Tag tag;
17+
union {
18+
struct {
19+
Payload ok;
20+
};
21+
struct {
22+
void *err;
23+
};
24+
};
25+
} ResultA_Payload;
26+
27+
typedef enum {
28+
ResultB_Payload_Ok_Payload,
29+
ResultB_Payload_Err_Payload,
30+
} ResultB_Payload_Tag;
31+
32+
typedef struct {
33+
ResultB_Payload_Tag tag;
34+
union {
35+
struct {
36+
Payload ok;
37+
};
38+
struct {
39+
void *err;
40+
};
41+
};
42+
} ResultB_Payload;
43+
44+
void use_a(ResultA_Payload _a);
45+
46+
void use_b(ResultB_Payload _b);
Lines changed: 54 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,54 @@
1+
#include <stdarg.h>
2+
#include <stdbool.h>
3+
#include <stdint.h>
4+
#include <stdlib.h>
5+
6+
typedef struct {
7+
int32_t x;
8+
} Payload;
9+
10+
typedef enum {
11+
ResultA_Payload_Ok_Payload,
12+
ResultA_Payload_Err_Payload,
13+
} ResultA_Payload_Tag;
14+
15+
typedef struct {
16+
ResultA_Payload_Tag tag;
17+
union {
18+
struct {
19+
Payload ok;
20+
};
21+
struct {
22+
void *err;
23+
};
24+
};
25+
} ResultA_Payload;
26+
27+
typedef enum {
28+
ResultB_Payload_Ok_Payload,
29+
ResultB_Payload_Err_Payload,
30+
} ResultB_Payload_Tag;
31+
32+
typedef struct {
33+
ResultB_Payload_Tag tag;
34+
union {
35+
struct {
36+
Payload ok;
37+
};
38+
struct {
39+
void *err;
40+
};
41+
};
42+
} ResultB_Payload;
43+
44+
#ifdef __cplusplus
45+
extern "C" {
46+
#endif // __cplusplus
47+
48+
void use_a(ResultA_Payload _a);
49+
50+
void use_b(ResultB_Payload _b);
51+
52+
#ifdef __cplusplus
53+
} // extern "C"
54+
#endif // __cplusplus
Lines changed: 61 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,61 @@
1+
#include <cstdarg>
2+
#include <cstdint>
3+
#include <cstdlib>
4+
#include <ostream>
5+
#include <new>
6+
7+
struct Payload {
8+
int32_t x;
9+
};
10+
11+
template<typename T>
12+
struct ResultA {
13+
enum class Tag {
14+
ResultA_Ok,
15+
ResultA_Err,
16+
};
17+
18+
struct ResultA_Ok_Body {
19+
T _0;
20+
};
21+
22+
struct ResultA_Err_Body {
23+
void *_0;
24+
};
25+
26+
Tag tag;
27+
union {
28+
ResultA_Ok_Body ok;
29+
ResultA_Err_Body err;
30+
};
31+
};
32+
33+
template<typename T>
34+
struct ResultB {
35+
enum class Tag {
36+
ResultB_Ok,
37+
ResultB_Err,
38+
};
39+
40+
struct ResultB_Ok_Body {
41+
T _0;
42+
};
43+
44+
struct ResultB_Err_Body {
45+
void *_0;
46+
};
47+
48+
Tag tag;
49+
union {
50+
ResultB_Ok_Body ok;
51+
ResultB_Err_Body err;
52+
};
53+
};
54+
55+
extern "C" {
56+
57+
void use_a(ResultA<Payload> _a);
58+
59+
void use_b(ResultB<Payload> _b);
60+
61+
} // extern "C"
Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,32 @@
1+
from libc.stdint cimport int8_t, int16_t, int32_t, int64_t, intptr_t
2+
from libc.stdint cimport uint8_t, uint16_t, uint32_t, uint64_t, uintptr_t
3+
cdef extern from *:
4+
ctypedef bint bool
5+
ctypedef struct va_list
6+
7+
cdef extern from *:
8+
9+
ctypedef struct Payload:
10+
int32_t x;
11+
12+
ctypedef enum ResultA_Payload_Tag:
13+
ResultA_Payload_Ok_Payload,
14+
ResultA_Payload_Err_Payload,
15+
16+
ctypedef struct ResultA_Payload:
17+
ResultA_Payload_Tag tag;
18+
Payload ok;
19+
void *err;
20+
21+
ctypedef enum ResultB_Payload_Tag:
22+
ResultB_Payload_Ok_Payload,
23+
ResultB_Payload_Err_Payload,
24+
25+
ctypedef struct ResultB_Payload:
26+
ResultB_Payload_Tag tag;
27+
Payload ok;
28+
void *err;
29+
30+
void use_a(ResultA_Payload _a);
31+
32+
void use_b(ResultB_Payload _b);
Lines changed: 46 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,46 @@
1+
#include <stdarg.h>
2+
#include <stdbool.h>
3+
#include <stdint.h>
4+
#include <stdlib.h>
5+
6+
typedef struct Payload {
7+
int32_t x;
8+
} Payload;
9+
10+
typedef enum ResultA_Payload_Tag {
11+
ResultA_Payload_Ok_Payload,
12+
ResultA_Payload_Err_Payload,
13+
} ResultA_Payload_Tag;
14+
15+
typedef struct ResultA_Payload {
16+
ResultA_Payload_Tag tag;
17+
union {
18+
struct {
19+
struct Payload ok;
20+
};
21+
struct {
22+
void *err;
23+
};
24+
};
25+
} ResultA_Payload;
26+
27+
typedef enum ResultB_Payload_Tag {
28+
ResultB_Payload_Ok_Payload,
29+
ResultB_Payload_Err_Payload,
30+
} ResultB_Payload_Tag;
31+
32+
typedef struct ResultB_Payload {
33+
ResultB_Payload_Tag tag;
34+
union {
35+
struct {
36+
struct Payload ok;
37+
};
38+
struct {
39+
void *err;
40+
};
41+
};
42+
} ResultB_Payload;
43+
44+
void use_a(struct ResultA_Payload _a);
45+
46+
void use_b(struct ResultB_Payload _b);

0 commit comments

Comments
 (0)