Skip to content

ir: Skip phantom anonymous members from inside attribute expressions#3361

Closed
barry3406 wants to merge 1 commit intorust-lang:mainfrom
barry3406:fix/3295-aligned-struct-with-alignof
Closed

ir: Skip phantom anonymous members from inside attribute expressions#3361
barry3406 wants to merge 1 commit intorust-lang:mainfrom
barry3406:fix/3295-aligned-struct-with-alignof

Conversation

@barry3406
Copy link
Copy Markdown

Clang exposes anonymous structs declared inside the parent struct's attribute expressions (e.g. __alignof__(struct{int aaa;}) inside __attribute__((aligned(...)))) as child cursors of the surrounding struct, with the surrounding struct as both their lexical and semantic parent. The existing is_anonymous() && kind != EnumDecl check in CompInfo::from_ty happily promoted them to anonymous members, so the surrounding struct ended up with an extra phantom field. That doubled the surrounding struct's size, which then made the size assertions in the generated bindings fail to compile (["Size of base_t__bindgen_ty_1"][size_of::<...>() - 4usize] evaluates to an out-of-bounds index).

Tell those apart from real anonymous members by comparing source ranges: a real anonymous member's source range is contained inside the parent struct's body, while a phantom child from inside an attribute expression sits past the parent's closing }. Added a new Cursor::extent_contains helper for the check, and gated the anonymous-member promotion on it.

Verified against the reproducer from #3295 — the regenerated bindings now have a single aaa: c_int field on base_t__bindgen_ty_1, and the size/offset assertions evaluate cleanly. Added a regression test in bindgen-tests/tests/{headers,expectations/tests} covering exactly the snippet from the issue.

Fixes #3295

Clang exposes anonymous structs declared inside the parent struct's
attribute expressions (e.g. `__alignof__(struct{int aaa;})` inside
`__attribute__((aligned(...)))`) as child cursors of the surrounding
struct, with the surrounding struct as both their lexical and semantic
parent. The existing `is_anonymous() && kind != EnumDecl` check in
`CompInfo::from_ty` happily promoted them to anonymous members, doubling
the surrounding struct's layout and producing failing size assertions
in the generated bindings.

Tell those apart from real anonymous members by comparing source
ranges: a real anonymous member's source range is contained within the
parent struct's source range, while a phantom child from inside an
attribute expression sits past the parent's closing `}`.

Fixes rust-lang#3295
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

__attribute__((aligned(__alignof__(struct {...})))) will trigger size check error

1 participant