[COMMITTED 27/77] gccrs: Add support for #[repr(transparent)] attribute

[email protected]
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
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.