https://gcc.gnu.org/g:3a54974005c60391c13aa44f97f03bf188c1e08c
commit r17-3085-g3a54974005c60391c13aa44f97f03bf188c1e08c Author: Yap Zhi Heng <[email protected]> Date: Sat Jun 27 17:42:04 2026 +0800 gccrs: Add support for #[repr(transparent)] attribute gcc/rust/ChangeLog: * typecheck/rust-tyty.h (TyTy::ADTType::ReprKind): Add TRANSPARENT variant. * typecheck/rust-hir-type-check-base.cc (TypeCheckBase::parse_repr_options): Add parsing of transparent repr, throw error for invalid repr. * typecheck/rust-hir-type-check-item.cc (TypeCheckItem::visit (StructStruct)): Throw error if #[repr(transparent)] struct/enum has more than 1 field. Signed-Off-By: Yap Zhi Heng <[email protected]> Diff: --- gcc/rust/typecheck/rust-hir-type-check-base.cc | 22 +++++++++++++++++++--- gcc/rust/typecheck/rust-hir-type-check-item.cc | 18 +++++++++++++----- gcc/rust/typecheck/rust-tyty.h | 2 +- gcc/testsuite/rust/compile/invalid_repr_hint.rs | 12 ++++++++++++ .../rust/compile/repr_transparent_fields.rs | 16 ++++++++++++++++ 5 files changed, 61 insertions(+), 9 deletions(-) diff --git a/gcc/rust/typecheck/rust-hir-type-check-base.cc b/gcc/rust/typecheck/rust-hir-type-check-base.cc index 8b6b4d6f5431..7ff37c92434c 100644 --- a/gcc/rust/typecheck/rust-hir-type-check-base.cc +++ b/gcc/rust/typecheck/rust-hir-type-check-base.cc @@ -517,12 +517,12 @@ TypeCheckBase::parse_repr_options (const AST::AttrVec &attrs, location_t locus) bool is_align = false; bool is_c = false; bool is_integer = false; + bool is_transparent = false; unsigned char value = 1; if (oparen == std::string::npos) { is_pack = inline_option.compare ("packed") == 0; - is_align = inline_option.compare ("align") == 0; is_c = inline_option.compare ("C") == 0; is_integer = (inline_option.compare ("isize") == 0 || inline_option.compare ("i8") == 0 @@ -536,6 +536,7 @@ TypeCheckBase::parse_repr_options (const AST::AttrVec &attrs, location_t locus) || inline_option.compare ("u32") == 0 || inline_option.compare ("u64") == 0 || inline_option.compare ("u128") == 0); + is_transparent = inline_option.compare ("transparent") == 0; } else @@ -554,7 +555,16 @@ TypeCheckBase::parse_repr_options (const AST::AttrVec &attrs, location_t locus) value = strtoul (value_str.c_str () + 1, NULL, 10); } - if (is_pack) + if (is_transparent) + { + if (is_pack || is_align || is_c || is_integer) + rust_error_at ( + locus, ErrorCode::E0692, + "transparent struct cannot have other repr hints"); + + repr.repr_kind = TyTy::ADTType::ReprKind::TRANSPARENT; + } + else if (is_pack) { repr.repr_kind = TyTy::ADTType::ReprKind::PACKED; repr.pack = value; @@ -574,9 +584,15 @@ TypeCheckBase::parse_repr_options (const AST::AttrVec &attrs, location_t locus) bool ok = context->lookup_builtin (inline_option, &repr.repr); if (!ok) { - rust_error_at (attr.get_locus (), "Invalid repr type"); + rust_error_at (attr.get_locus (), ErrorCode::E0552, + "unrecognized representation hint"); } } + else + { + rust_error_at (attr.get_locus (), ErrorCode::E0552, + "unrecognized representation hint"); + } delete meta_items; diff --git a/gcc/rust/typecheck/rust-hir-type-check-item.cc b/gcc/rust/typecheck/rust-hir-type-check-item.cc index 065615a23b0a..ac0eeaf277e0 100644 --- a/gcc/rust/typecheck/rust-hir-type-check-item.cc +++ b/gcc/rust/typecheck/rust-hir-type-check-item.cc @@ -339,6 +339,19 @@ TypeCheckItem::visit (HIR::StructStruct &struct_decl) ResolveWhereClauseItem::Resolve (*where_clause_item, region_constraints); } + // Process #[repr(X)] attribute, if any + const AST::AttrVec &attrs = struct_decl.get_outer_attrs (); + TyTy::ADTType::ReprOptions repr + = parse_repr_options (attrs, struct_decl.get_locus ()); + if (repr.repr_kind == TyTy::ADTType::ReprKind::TRANSPARENT + && struct_decl.get_fields ().size () > 1) + { + rust_error_at (struct_decl.get_locus (), ErrorCode::E0690, + "transparent struct needs at most one field with " + "non-trivial size or alignment, but has %lu", + (unsigned long) struct_decl.get_fields ().size ()); + } + std::vector<TyTy::StructFieldType *> fields; for (auto &field : struct_decl.get_fields ()) { @@ -379,11 +392,6 @@ TypeCheckItem::visit (HIR::StructStruct &struct_decl) struct_decl.get_identifier ().as_string (), ident, variant_type, tl::nullopt, std::move (fields))); - // Process #[repr(X)] attribute, if any - const AST::AttrVec &attrs = struct_decl.get_outer_attrs (); - TyTy::ADTType::ReprOptions repr - = parse_repr_options (attrs, struct_decl.get_locus ()); - auto *type = new TyTy::ADTType ( struct_decl.get_mappings ().get_defid (), struct_decl.get_mappings ().get_hirid (), diff --git a/gcc/rust/typecheck/rust-tyty.h b/gcc/rust/typecheck/rust-tyty.h index b5e5f02c6782..f645f673f86b 100644 --- a/gcc/rust/typecheck/rust-tyty.h +++ b/gcc/rust/typecheck/rust-tyty.h @@ -910,7 +910,7 @@ public: INT, ALIGN, PACKED, - // TRANSPARENT, + TRANSPARENT, // SIMD, // ... }; diff --git a/gcc/testsuite/rust/compile/invalid_repr_hint.rs b/gcc/testsuite/rust/compile/invalid_repr_hint.rs new file mode 100644 index 000000000000..7ac48a921d4d --- /dev/null +++ b/gcc/testsuite/rust/compile/invalid_repr_hint.rs @@ -0,0 +1,12 @@ +#![feature(no_core)] +#![no_core] + +#[repr(InvalidRepr)] // { dg-error "unrecognized representation hint" } +struct Foo { + x: i32, +} + +#[repr(align)] // { dg-error "unrecognized representation hint" } +struct Bar { + x: i32, +} diff --git a/gcc/testsuite/rust/compile/repr_transparent_fields.rs b/gcc/testsuite/rust/compile/repr_transparent_fields.rs new file mode 100644 index 000000000000..19002138696a --- /dev/null +++ b/gcc/testsuite/rust/compile/repr_transparent_fields.rs @@ -0,0 +1,16 @@ +#![feature(no_core)] +#![no_core] + +#[repr(transparent)] +struct Foo { // { dg-error "transparent struct needs at most one field with non-trivial size or alignment, but has 2" } + foo: i32, + bar: i32 +} + +#[repr(transparent)] +struct Bar {} + +#[repr(transparent)] +struct Baz { + foo: i32 +}
