Skip to content

Commit

Permalink
Handle the const struct * and struct * patterns (#2304)
Browse files Browse the repository at this point in the history
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.
  • Loading branch information
pvdrz committed Nov 10, 2022
1 parent ed3aa90 commit db4ea32
Show file tree
Hide file tree
Showing 3 changed files with 201 additions and 3 deletions.
153 changes: 153 additions & 0 deletions bindgen-tests/tests/expectations/tests/typedef-pointer-overlap.rs

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

30 changes: 30 additions & 0 deletions bindgen-tests/tests/headers/typedef-pointer-overlap.h
@@ -0,0 +1,30 @@
typedef const struct foo {
char inner;
} *foo;

typedef struct bar {
char inner;
} *bar;

typedef struct baz *baz;

typedef union cat {
int standard_issue;
} *cat;

typedef enum mad { scientist } *mad;

void takes_foo_ptr(foo);
void takes_foo_struct(struct foo);

void takes_bar_ptr(bar);
void takes_bar_struct(struct bar);

void takes_baz_ptr(baz);
void takes_baz_struct(struct baz);

void takes_cat_ptr(cat);
void takes_cat_union(union cat);

void takes_mad_ptr(mad);
void takes_mad_enum(enum mad);
21 changes: 18 additions & 3 deletions bindgen/ir/ty.rs
Expand Up @@ -1094,17 +1094,32 @@ impl Type {
}
CXType_Typedef => {
let inner = cursor.typedef_type().expect("Not valid Type?");
let inner =
let inner_id =
Item::from_ty_or_ref(inner, location, None, ctx);
if inner == potential_id {
if inner_id == potential_id {
warn!(
"Generating oqaque type instead of self-referential \
typedef");
// This can happen if we bail out of recursive situations
// within the clang parsing.
TypeKind::Opaque
} else {
TypeKind::Alias(inner)
// Check if this type definition is an alias to a pointer of a `struct` /
// `union` / `enum` with the same name and add the `_ptr` suffix to it to
// avoid name collisions.
if let Some(ref mut name) = name {
if inner.kind() == CXType_Pointer &&
!ctx.options().c_naming
{
let pointee = inner.pointee_type().unwrap();
if pointee.kind() == CXType_Elaborated &&
pointee.declaration().spelling() == *name
{
*name += "_ptr";
}
}
}
TypeKind::Alias(inner_id)
}
}
CXType_Enum => {
Expand Down

0 comments on commit db4ea32

Please sign in to comment.