[COMMITTED 27/77] gccrs: Add support for #[repr(transparent)] attribute
[email protected] Fri, 7 Aug 2026 14:39:18 +0200
Newsgroups
gmane.comp.gcc.rust,gmane.comp.gcc.patches
Message-ID
<[email protected] >
From: Yap Zhi Heng <[email protected] >
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] >
---
.../typecheck/rust-hir-type-check-base.cc | 22 ++++++++++++++++---
.../typecheck/rust-hir-type-check-item.cc | 18 ++++++++++-----
gcc/rust/typecheck/rust-tyty.h | 2 +-
.../rust/compile/invalid_repr_hint.rs | 12 ++++++++++
.../rust/compile/repr_transparent_fields.rs | 16 ++++++++++++++
5 files changed, 61 insertions(+), 9 deletions(-)
create mode 100644 gcc/testsuite/rust/compile/invalid_repr_hint.rs
create mode 100644 gcc/testsuite/rust/compile/repr_transparent_fields.rs
diff --git a/gcc/rust/typecheck/rust-hir-type-check-base.cc b/gcc/rust/typecheck/rust-hir-type-check-base.cc
index 8b6b4d6f543..7ff37c92434 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 065615a23b0..ac0eeaf277e 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 b5e5f02c678..f645f673f86 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 00000000000..7ac48a921d4
--- /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 00000000000..19002138696
--- /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
+}
--
2.50.1