[gccrs,COMMIT,1/3] gccrs: Add support for #[repr(transparent)] attribute

Message ID 20260708091609.3108-1-gerris.rs@gmail.com
State New
Headers
Series [gccrs,COMMIT,1/3] gccrs: Add support for #[repr(transparent)] attribute |

Commit Message

gerris.rs@gmail.com July 8, 2026, 9:16 a.m. UTC
  From: Yap Zhi Heng <yapzhhg@gmail.com>

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 <yapzhhg@gmail.com>
---
This change was merged into the gccrs repository and is posted here for
upstream visibility and potential drive-by review, as requested by GCC
release managers.
Each commit email contains a link to its details on github from where you can
find the Pull-Request and associated discussions.


Commit on github: https://github.com/Rust-GCC/gccrs/commit/ca4f17810c0dcb5974bdb0a50e1c4620ddf961de

The commit has NOT been mentioned in any issue.

The commit has been mentioned in the following pull-request(s):
 - https://github.com/Rust-GCC/gccrs/pull/4650

 .../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


base-commit: eef61cb13a49d1a2dbc6cd874b2ecc8906ee1da3
  

Patch

diff --git a/gcc/rust/typecheck/rust-hir-type-check-base.cc b/gcc/rust/typecheck/rust-hir-type-check-base.cc
index 8b6b4d6f5..7ff37c924 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 065615a23..ac0eeaf27 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 b5e5f02c6..f645f673f 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 000000000..7ac48a921
--- /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 000000000..190021386
--- /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
+}