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