diff --git a/gcc/rust/ast/rust-ast.cc b/gcc/rust/ast/rust-ast.cc index 9c0b1bf82452..27e62a923a5c 100644 --- a/gcc/rust/ast/rust-ast.cc +++ b/gcc/rust/ast/rust-ast.cc @@ -311,7 +311,8 @@ Attribute::get_traits_to_derive () // Copy constructor must deep copy attr_input as unique pointer Attribute::Attribute (Attribute const &other) - : path (other.path), locus (other.locus) + : path (other.path), locus (other.locus), + inner_attribute (other.inner_attribute) { // guard to protect from null pointer dereference if (other.attr_input != nullptr) @@ -324,6 +325,7 @@ Attribute::operator= (Attribute const &other) { path = other.path; locus = other.locus; + inner_attribute = other.inner_attribute; // guard to protect from null pointer dereference if (other.attr_input != nullptr) attr_input = other.attr_input->clone_attr_input (); diff --git a/gcc/rust/checks/errors/rust-unsafe-checker.cc b/gcc/rust/checks/errors/rust-unsafe-checker.cc index ff307ae21134..af3cd80245d1 100644 --- a/gcc/rust/checks/errors/rust-unsafe-checker.cc +++ b/gcc/rust/checks/errors/rust-unsafe-checker.cc @@ -784,7 +784,23 @@ UnsafeChecker::visit (Trait &trait) void UnsafeChecker::visit (ImplBlock &impl) { - // FIXME: Handle unsafe impls + bool safe = !impl.is_unsafe (); + // Check for unsafe-only attributes on generics and lifetimes + if (safe) + for (auto &parm : impl.get_generic_params ()) + { + for (auto o_attr : parm->get_outer_attrs ()) + { + rust_assert (!o_attr.is_inner_attribute ()); + + Rust::AST::SimplePath path = o_attr.get_path (); + if (path == Values::Attributes::MAY_DANGLE) + rust_error_at ( + o_attr.get_locus (), ErrorCode::E0569, + "use of % is unsafe and requires unsafe impl"); + } + } + for (auto &item : impl.get_impl_items ()) item->accept_vis (*this); } diff --git a/gcc/rust/hir/rust-ast-lower-item.cc b/gcc/rust/hir/rust-ast-lower-item.cc index f6a73cb7121f..f3ad72c72374 100644 --- a/gcc/rust/hir/rust-ast-lower-item.cc +++ b/gcc/rust/hir/rust-ast-lower-item.cc @@ -542,7 +542,7 @@ ASTLoweringItem::visit (AST::InherentImpl &impl_block) mapping, std::move (impl_items), std::move (generic_params), std::unique_ptr (impl_type), nullptr, where_clause, polarity, vis, impl_block.get_inner_attrs (), impl_block.get_outer_attrs (), - impl_block.get_locus ()); + impl_block.get_locus (), false); translated = hir_impl_block; mappings.insert_hir_impl_block (hir_impl_block); @@ -623,6 +623,7 @@ void ASTLoweringItem::visit (AST::TraitImpl &impl_block) { std::vector> where_clause_items; + bool unsafe = impl_block.is_unsafe (); for (auto &item : impl_block.get_where_clause ().get_items ()) { HIR::WhereClauseItem *i = ASTLowerWhereClauseItem::translate (*item); @@ -696,7 +697,7 @@ ASTLoweringItem::visit (AST::TraitImpl &impl_block) std::unique_ptr (impl_type), std::unique_ptr (trait_ref), where_clause, polarity, vis, impl_block.get_inner_attrs (), impl_block.get_outer_attrs (), - impl_block.get_locus ()); + impl_block.get_locus (), unsafe); translated = hir_impl_block; mappings.insert_hir_impl_block (hir_impl_block); diff --git a/gcc/rust/hir/rust-ast-lower-type.cc b/gcc/rust/hir/rust-ast-lower-type.cc index 091fa031ab5f..ad93526644e7 100644 --- a/gcc/rust/hir/rust-ast-lower-type.cc +++ b/gcc/rust/hir/rust-ast-lower-type.cc @@ -17,6 +17,7 @@ // . #include "rust-ast-lower-type.h" +#include "rust-attribute-values.h" namespace Rust { namespace HIR { @@ -446,16 +447,17 @@ void ASTLowerGenericParam::visit (AST::LifetimeParam ¶m) { auto crate_num = mappings.get_current_crate (); + AST::Lifetime lifetime = param.get_lifetime (); Analysis::NodeMapping mapping (crate_num, param.get_node_id (), mappings.get_next_hir_id (crate_num), mappings.get_next_localdef_id (crate_num)); - HIR::Lifetime lt (mapping, param.get_lifetime ().get_lifetime_type (), - param.get_lifetime ().get_lifetime_name (), - param.get_lifetime ().get_locus ()); + HIR::Lifetime lt (mapping, lifetime.get_lifetime_type (), + lifetime.get_lifetime_name (), lifetime.get_locus ()); translated = new HIR::LifetimeParam (mapping, lt, param.get_locus (), - std::vector ()); + std::vector (), + param.get_outer_attrs ()); } void @@ -482,7 +484,6 @@ ASTLowerGenericParam::visit (AST::ConstGenericParam ¶m) void ASTLowerGenericParam::visit (AST::TypeParam ¶m) { - AST::Attribute outer_attr = AST::Attribute::create_empty (); std::vector> type_param_bounds; if (param.has_type_param_bounds ()) { @@ -506,7 +507,8 @@ ASTLowerGenericParam::visit (AST::TypeParam ¶m) translated = new HIR::TypeParam (mapping, param.get_type_representation (), param.get_locus (), std::move (type_param_bounds), - std::unique_ptr (type), std::move (outer_attr)); + std::unique_ptr (type), + param.get_outer_attrs ()); } HIR::TypeParamBound * diff --git a/gcc/rust/hir/rust-hir-dump.cc b/gcc/rust/hir/rust-hir-dump.cc index 57500e4169fc..d9e02f5d2416 100644 --- a/gcc/rust/hir/rust-hir-dump.cc +++ b/gcc/rust/hir/rust-hir-dump.cc @@ -1508,7 +1508,8 @@ void Dump::visit (TypeParam &e) { begin ("TypeParam"); - put_field ("outer_attr", e.get_outer_attribute ().as_string ()); + auto &outer_attrs = e.get_outer_attrs (); + do_outer_attrs (outer_attrs); put_field ("type_representation", e.get_type_representation ().as_string ()); diff --git a/gcc/rust/hir/tree/rust-hir-item.h b/gcc/rust/hir/tree/rust-hir-item.h index 7e0c8c6ffca9..86fdabd74b33 100644 --- a/gcc/rust/hir/tree/rust-hir-item.h +++ b/gcc/rust/hir/tree/rust-hir-item.h @@ -35,9 +35,7 @@ class TypePath; // A type generic parameter (as opposed to a lifetime generic parameter) class TypeParam : public GenericParam { - // bool has_outer_attribute; - // std::unique_ptr outer_attr; - AST::Attribute outer_attr; + AST::AttrVec outer_attrs; Identifier type_representation; @@ -59,16 +57,16 @@ class TypeParam : public GenericParam bool has_type_param_bounds () const { return !type_param_bounds.empty (); } // Returns whether the type param has an outer attribute. - bool has_outer_attribute () const { return !outer_attr.is_empty (); } - AST::Attribute &get_outer_attribute () { return outer_attr; } + bool has_outer_attribute () const override { return outer_attrs.size () > 0; } + AST::AttrVec &get_outer_attrs () override { return outer_attrs; } TypeParam (Analysis::NodeMapping mappings, Identifier type_representation, location_t locus = UNDEF_LOCATION, std::vector> type_param_bounds = std::vector> (), std::unique_ptr type = nullptr, - AST::Attribute outer_attr = AST::Attribute::create_empty ()) - : GenericParam (mappings), outer_attr (std::move (outer_attr)), + AST::AttrVec outer_attrs = std::vector ()) + : GenericParam (mappings), outer_attrs (std::move (outer_attrs)), type_representation (std::move (type_representation)), type_param_bounds (std::move (type_param_bounds)), type (std::move (type)), locus (locus) @@ -76,7 +74,7 @@ class TypeParam : public GenericParam // Copy constructor uses clone TypeParam (TypeParam const &other) - : GenericParam (other.mappings), outer_attr (other.outer_attr), + : GenericParam (other.mappings), outer_attrs (other.outer_attrs), type_representation (other.type_representation), locus (other.locus) { // guard to prevent null pointer dereference @@ -92,7 +90,7 @@ class TypeParam : public GenericParam TypeParam &operator= (TypeParam const &other) { type_representation = other.type_representation; - outer_attr = other.outer_attr; + outer_attrs = other.outer_attrs; locus = other.locus; mappings = other.mappings; @@ -2741,6 +2739,7 @@ class ImplBlock : public VisItem, public WithInnerAttrs BoundPolarity polarity; location_t locus; std::vector> impl_items; + bool unsafe; public: ImplBlock (Analysis::NodeMapping mappings, @@ -2749,20 +2748,20 @@ class ImplBlock : public VisItem, public WithInnerAttrs std::unique_ptr impl_type, std::unique_ptr trait_ref, WhereClause where_clause, BoundPolarity polarity, Visibility vis, AST::AttrVec inner_attrs, - AST::AttrVec outer_attrs, location_t locus) + AST::AttrVec outer_attrs, location_t locus, bool unsafe = false) : VisItem (std::move (mappings), std::move (vis), std::move (outer_attrs)), WithInnerAttrs (std::move (inner_attrs)), generic_params (std::move (generic_params)), impl_type (std::move (impl_type)), trait_ref (std::move (trait_ref)), where_clause (std::move (where_clause)), polarity (polarity), - locus (locus), impl_items (std::move (impl_items)) + locus (locus), impl_items (std::move (impl_items)), unsafe (unsafe) {} ImplBlock (ImplBlock const &other) : VisItem (other), WithInnerAttrs (other.inner_attrs), impl_type (other.impl_type->clone_type ()), where_clause (other.where_clause), polarity (other.polarity), - locus (other.locus) + locus (other.locus), unsafe (other.unsafe) { generic_params.reserve (other.generic_params.size ()); for (const auto &e : other.generic_params) @@ -2781,6 +2780,7 @@ class ImplBlock : public VisItem, public WithInnerAttrs polarity = other.polarity; inner_attrs = other.inner_attrs; locus = other.locus; + unsafe = other.unsafe; generic_params.reserve (other.generic_params.size ()); for (const auto &e : other.generic_params) @@ -2801,6 +2801,8 @@ class ImplBlock : public VisItem, public WithInnerAttrs // Returns whether inherent impl block has inherent impl items. bool has_impl_items () const { return !impl_items.empty (); } + bool is_unsafe () const { return unsafe; } + void accept_vis (HIRFullVisitor &vis) override; void accept_vis (HIRStmtVisitor &vis) override; void accept_vis (HIRVisItemVisitor &vis) override; diff --git a/gcc/rust/hir/tree/rust-hir.cc b/gcc/rust/hir/tree/rust-hir.cc index 80878fe18a1b..35aa5851f69d 100644 --- a/gcc/rust/hir/tree/rust-hir.cc +++ b/gcc/rust/hir/tree/rust-hir.cc @@ -2017,14 +2017,19 @@ LifetimeParam::as_string () const { std::string str ("LifetimeParam: "); - str += "\n Outer attribute: "; - if (!has_outer_attribute ()) + str += "\n Outer attributes: "; + if (outer_attrs.empty ()) { str += "none"; } else { - str += outer_attr.as_string (); + /* note that this does not print them with "outer attribute" syntax - + * just the body */ + for (const auto &attr : outer_attrs) + { + str += "\n " + attr.as_string (); + } } str += "\n Lifetime: " + lifetime.as_string (); @@ -2106,14 +2111,19 @@ TypeParam::as_string () const { std::string str ("TypeParam: "); - str += "\n Outer attribute: "; - if (!has_outer_attribute ()) + str += "\n Outer attributes: "; + if (outer_attrs.empty ()) { str += "none"; } else { - str += outer_attr.as_string (); + /* note that this does not print them with "outer attribute" syntax - + * just the body */ + for (const auto &attr : outer_attrs) + { + str += "\n " + attr.as_string (); + } } str += "\n Identifier: " + type_representation.as_string (); diff --git a/gcc/rust/hir/tree/rust-hir.h b/gcc/rust/hir/tree/rust-hir.h index b427f1d204dc..3fb97b2f1218 100644 --- a/gcc/rust/hir/tree/rust-hir.h +++ b/gcc/rust/hir/tree/rust-hir.h @@ -617,6 +617,9 @@ class GenericParam : public FullVisitable CONST, }; + virtual AST::AttrVec &get_outer_attrs () = 0; + virtual bool has_outer_attribute () const = 0; + // Unique pointer custom clone function std::unique_ptr clone_generic_param () const { @@ -654,9 +657,7 @@ class LifetimeParam : public GenericParam // LifetimeBounds lifetime_bounds; std::vector lifetime_bounds; // inlined LifetimeBounds - // bool has_outer_attribute; - // std::unique_ptr outer_attr; - AST::Attribute outer_attr; + AST::AttrVec outer_attrs; location_t locus; @@ -669,7 +670,9 @@ class LifetimeParam : public GenericParam std::vector &get_lifetime_bounds () { return lifetime_bounds; } // Returns whether the lifetime param has an outer attribute. - bool has_outer_attribute () const { return !outer_attr.is_empty (); } + bool has_outer_attribute () const override { return outer_attrs.size () > 1; } + + AST::AttrVec &get_outer_attrs () { return outer_attrs; } // Returns whether the lifetime param is in an error state. bool is_error () const { return lifetime.is_error (); } @@ -679,11 +682,11 @@ class LifetimeParam : public GenericParam location_t locus = UNDEF_LOCATION, std::vector lifetime_bounds = std::vector (), - AST::Attribute outer_attr = AST::Attribute::create_empty ()) + AST::AttrVec outer_attrs = std::vector ()) : GenericParam (mappings, GenericKind::LIFETIME), lifetime (std::move (lifetime)), lifetime_bounds (std::move (lifetime_bounds)), - outer_attr (std::move (outer_attr)), locus (locus) + outer_attrs (std::move (outer_attrs)), locus (locus) {} // TODO: remove copy and assignment operator definitions - not required @@ -692,7 +695,7 @@ class LifetimeParam : public GenericParam LifetimeParam (LifetimeParam const &other) : GenericParam (other.mappings, GenericKind::LIFETIME), lifetime (other.lifetime), lifetime_bounds (other.lifetime_bounds), - outer_attr (other.outer_attr), locus (other.locus) + outer_attrs (other.outer_attrs), locus (other.locus) {} // Overloaded assignment operator to clone attribute @@ -700,7 +703,7 @@ class LifetimeParam : public GenericParam { lifetime = other.lifetime; lifetime_bounds = other.lifetime_bounds; - outer_attr = other.outer_attr; + outer_attrs = other.outer_attrs; locus = other.locus; mappings = other.mappings; @@ -748,6 +751,10 @@ class ConstGenericParam : public GenericParam default_expression = other.default_expression->clone_expr (); } + bool has_outer_attribute () const override { return false; } + + AST::AttrVec &get_outer_attrs () override { return outer_attrs; } + std::string as_string () const override final; void accept_vis (HIRFullVisitor &vis) override final; @@ -775,6 +782,9 @@ class ConstGenericParam : public GenericParam std::string name; std::unique_ptr type; + /* const params have no outer attrs, should be empty */ + AST::AttrVec outer_attrs = std::vector (); + /* Optional - can be a null pointer if there is no default expression */ std::unique_ptr default_expression; diff --git a/gcc/testsuite/rust/compile/issue-3045-1.rs b/gcc/testsuite/rust/compile/issue-3045-1.rs new file mode 100644 index 000000000000..a1328f22d0cd --- /dev/null +++ b/gcc/testsuite/rust/compile/issue-3045-1.rs @@ -0,0 +1,21 @@ +#![feature(dropck_eyepatch)] +#[allow(dead_code)] + +#[lang = "sized"] +trait Sized {} + +struct Test { + _inner: T, +} + +struct Test2 { + _inner: T, +} + +trait Action {} + +impl<#[may_dangle] T> Action for Test {} // { dg-error "use of 'may_dangle' is unsafe and requires unsafe impl" "" { target *-*-* } 0 } + +unsafe impl<#[may_dangle] T> Action for Test2 {} + +fn main() {} diff --git a/gcc/testsuite/rust/compile/issue-3045-2.rs b/gcc/testsuite/rust/compile/issue-3045-2.rs new file mode 100644 index 000000000000..177707fb4750 --- /dev/null +++ b/gcc/testsuite/rust/compile/issue-3045-2.rs @@ -0,0 +1,20 @@ +#![feature(dropck_eyepatch)] +#[allow(dead_code)] + +#[lang = "sized"] +trait Sized {} + + +trait Action {} + +struct Inspector<'a>(&'a u8); +struct Inspector2<'a>(&'a u8); + +impl<#[may_dangle] 'a> Action for Inspector<'a> {} // { dg-error "use of 'may_dangle' is unsafe and requires unsafe impl" "" { target *-*-* } 0 } + +unsafe impl<#[may_dangle] 'a> Action for Inspector2<'a> {} + + +fn main() { + +}