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
+}

Reply via email to