Skip to content

Commit db4ea32

Browse files
authored
Handle the const struct * and struct * patterns (#2304)
Given that C keeps a different namespace for `struct`/`enum`/`union` and `typedef` aliases. The following patterns ```c typedef const struct foo { void *inner; } *foo; typedef struct bar { void *inner; } *bar; ``` are valid C code and produces both a `struct` and a pointer called `foo` and `bar` in different namespaces. Given that Rust does not make this distinction, we add the `_ptr` prefix to the pointer type aliases to avoid any name collisions.
1 parent ed3aa90 commit db4ea32

File tree

3 files changed

+201
-3
lines changed

3 files changed

+201
-3
lines changed

bindgen-tests/tests/expectations/tests/typedef-pointer-overlap.rs

+153
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
typedef const struct foo {
2+
char inner;
3+
} *foo;
4+
5+
typedef struct bar {
6+
char inner;
7+
} *bar;
8+
9+
typedef struct baz *baz;
10+
11+
typedef union cat {
12+
int standard_issue;
13+
} *cat;
14+
15+
typedef enum mad { scientist } *mad;
16+
17+
void takes_foo_ptr(foo);
18+
void takes_foo_struct(struct foo);
19+
20+
void takes_bar_ptr(bar);
21+
void takes_bar_struct(struct bar);
22+
23+
void takes_baz_ptr(baz);
24+
void takes_baz_struct(struct baz);
25+
26+
void takes_cat_ptr(cat);
27+
void takes_cat_union(union cat);
28+
29+
void takes_mad_ptr(mad);
30+
void takes_mad_enum(enum mad);

bindgen/ir/ty.rs

+18-3
Original file line numberDiff line numberDiff line change
@@ -1094,17 +1094,32 @@ impl Type {
10941094
}
10951095
CXType_Typedef => {
10961096
let inner = cursor.typedef_type().expect("Not valid Type?");
1097-
let inner =
1097+
let inner_id =
10981098
Item::from_ty_or_ref(inner, location, None, ctx);
1099-
if inner == potential_id {
1099+
if inner_id == potential_id {
11001100
warn!(
11011101
"Generating oqaque type instead of self-referential \
11021102
typedef");
11031103
// This can happen if we bail out of recursive situations
11041104
// within the clang parsing.
11051105
TypeKind::Opaque
11061106
} else {
1107-
TypeKind::Alias(inner)
1107+
// Check if this type definition is an alias to a pointer of a `struct` /
1108+
// `union` / `enum` with the same name and add the `_ptr` suffix to it to
1109+
// avoid name collisions.
1110+
if let Some(ref mut name) = name {
1111+
if inner.kind() == CXType_Pointer &&
1112+
!ctx.options().c_naming
1113+
{
1114+
let pointee = inner.pointee_type().unwrap();
1115+
if pointee.kind() == CXType_Elaborated &&
1116+
pointee.declaration().spelling() == *name
1117+
{
1118+
*name += "_ptr";
1119+
}
1120+
}
1121+
}
1122+
TypeKind::Alias(inner_id)
11081123
}
11091124
}
11101125
CXType_Enum => {

0 commit comments

Comments
 (0)