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]>
---
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

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

base-commit: eef61cb13a49d1a2dbc6cd874b2ecc8906ee1da3
-- 
2.54.0

Reply via email to