[gcc r17-3085] gccrs: Add support for #[repr(transparent)] attribute

Arthur Cohen via Gcc-cvs <[email protected]>
Newsgroups gmane.comp.gcc.cvs
Message-ID <[email protected]>
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
+}
lmpx.com only provides a reader for public news (NNTP) servers. It is not affiliated with the servers or forums shown here and is not responsible for the content of articles, which is written by their respective authors.