Skip to content

Commit a218b03

Browse files
liamnaddellP-E-P
authored andcommitted
[#3045] #[may_dangle] in safe impl
gcc/rust/ChangeLog: * ast/rust-ast.cc: Fix Attribute constructors to copy inner_attribute * checks/errors/rust-unsafe-checker.cc: Add pass for #[may_dangle] in safe impl's * hir/rust-ast-lower-item.cc: Add support for unsafe impl's * hir/rust-ast-lower-type.cc: Lower attributes in impl's from AST to HIR * hir/rust-hir-dump.cc: Change single attribute to AttrVec * hir/tree/rust-hir-item.h: Add unsafe support to Impl blocks in HIR * hir/tree/rust-hir.cc: Change single attribute to AttrVec * hir/tree/rust-hir.h: Add has/get_outer_attribute to GenericParam gcc/testsuite/ChangeLog: * rust/compile/issue-3045-1.rs: Add test for #[may_dangle] Generic Type triggering error * rust/compile/issue-3045-2.rs: Add test for #[may_dangle] Lifetime triggering error Signed-off-by: Liam Naddell <liam.naddell@mail.utoronto.ca>
1 parent 47c947c commit a218b03

10 files changed

+122
-37
lines changed

gcc/rust/ast/rust-ast.cc

+3-1
Original file line numberDiff line numberDiff line change
@@ -311,7 +311,8 @@ Attribute::get_traits_to_derive ()
311311

312312
// Copy constructor must deep copy attr_input as unique pointer
313313
Attribute::Attribute (Attribute const &other)
314-
: path (other.path), locus (other.locus)
314+
: path (other.path), locus (other.locus),
315+
inner_attribute (other.inner_attribute)
315316
{
316317
// guard to protect from null pointer dereference
317318
if (other.attr_input != nullptr)
@@ -324,6 +325,7 @@ Attribute::operator= (Attribute const &other)
324325
{
325326
path = other.path;
326327
locus = other.locus;
328+
inner_attribute = other.inner_attribute;
327329
// guard to protect from null pointer dereference
328330
if (other.attr_input != nullptr)
329331
attr_input = other.attr_input->clone_attr_input ();

gcc/rust/checks/errors/rust-unsafe-checker.cc

+17-1
Original file line numberDiff line numberDiff line change
@@ -784,7 +784,23 @@ UnsafeChecker::visit (Trait &trait)
784784
void
785785
UnsafeChecker::visit (ImplBlock &impl)
786786
{
787-
// FIXME: Handle unsafe impls
787+
bool safe = !impl.is_unsafe ();
788+
// Check for unsafe-only attributes on generics and lifetimes
789+
if (safe)
790+
for (auto &parm : impl.get_generic_params ())
791+
{
792+
for (auto o_attr : parm->get_outer_attrs ())
793+
{
794+
rust_assert (!o_attr.is_inner_attribute ());
795+
796+
Rust::AST::SimplePath path = o_attr.get_path ();
797+
if (path == Values::Attributes::MAY_DANGLE)
798+
rust_error_at (
799+
o_attr.get_locus (), ErrorCode::E0569,
800+
"use of %<may_dangle%> is unsafe and requires unsafe impl");
801+
}
802+
}
803+
788804
for (auto &item : impl.get_impl_items ())
789805
item->accept_vis (*this);
790806
}

gcc/rust/hir/rust-ast-lower-item.cc

+3-2
Original file line numberDiff line numberDiff line change
@@ -542,7 +542,7 @@ ASTLoweringItem::visit (AST::InherentImpl &impl_block)
542542
mapping, std::move (impl_items), std::move (generic_params),
543543
std::unique_ptr<HIR::Type> (impl_type), nullptr, where_clause, polarity,
544544
vis, impl_block.get_inner_attrs (), impl_block.get_outer_attrs (),
545-
impl_block.get_locus ());
545+
impl_block.get_locus (), false);
546546
translated = hir_impl_block;
547547

548548
mappings.insert_hir_impl_block (hir_impl_block);
@@ -623,6 +623,7 @@ void
623623
ASTLoweringItem::visit (AST::TraitImpl &impl_block)
624624
{
625625
std::vector<std::unique_ptr<HIR::WhereClauseItem>> where_clause_items;
626+
bool unsafe = impl_block.is_unsafe ();
626627
for (auto &item : impl_block.get_where_clause ().get_items ())
627628
{
628629
HIR::WhereClauseItem *i = ASTLowerWhereClauseItem::translate (*item);
@@ -696,7 +697,7 @@ ASTLoweringItem::visit (AST::TraitImpl &impl_block)
696697
std::unique_ptr<HIR::Type> (impl_type),
697698
std::unique_ptr<HIR::TypePath> (trait_ref), where_clause, polarity, vis,
698699
impl_block.get_inner_attrs (), impl_block.get_outer_attrs (),
699-
impl_block.get_locus ());
700+
impl_block.get_locus (), unsafe);
700701
translated = hir_impl_block;
701702

702703
mappings.insert_hir_impl_block (hir_impl_block);

gcc/rust/hir/rust-ast-lower-type.cc

+8-6
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@
1717
// <http://www.gnu.org/licenses/>.
1818

1919
#include "rust-ast-lower-type.h"
20+
#include "rust-attribute-values.h"
2021

2122
namespace Rust {
2223
namespace HIR {
@@ -446,16 +447,17 @@ void
446447
ASTLowerGenericParam::visit (AST::LifetimeParam &param)
447448
{
448449
auto crate_num = mappings.get_current_crate ();
450+
AST::Lifetime lifetime = param.get_lifetime ();
449451
Analysis::NodeMapping mapping (crate_num, param.get_node_id (),
450452
mappings.get_next_hir_id (crate_num),
451453
mappings.get_next_localdef_id (crate_num));
452454

453-
HIR::Lifetime lt (mapping, param.get_lifetime ().get_lifetime_type (),
454-
param.get_lifetime ().get_lifetime_name (),
455-
param.get_lifetime ().get_locus ());
455+
HIR::Lifetime lt (mapping, lifetime.get_lifetime_type (),
456+
lifetime.get_lifetime_name (), lifetime.get_locus ());
456457

457458
translated = new HIR::LifetimeParam (mapping, lt, param.get_locus (),
458-
std::vector<Lifetime> ());
459+
std::vector<Lifetime> (),
460+
param.get_outer_attrs ());
459461
}
460462

461463
void
@@ -482,7 +484,6 @@ ASTLowerGenericParam::visit (AST::ConstGenericParam &param)
482484
void
483485
ASTLowerGenericParam::visit (AST::TypeParam &param)
484486
{
485-
AST::Attribute outer_attr = AST::Attribute::create_empty ();
486487
std::vector<std::unique_ptr<HIR::TypeParamBound>> type_param_bounds;
487488
if (param.has_type_param_bounds ())
488489
{
@@ -506,7 +507,8 @@ ASTLowerGenericParam::visit (AST::TypeParam &param)
506507
translated
507508
= new HIR::TypeParam (mapping, param.get_type_representation (),
508509
param.get_locus (), std::move (type_param_bounds),
509-
std::unique_ptr<Type> (type), std::move (outer_attr));
510+
std::unique_ptr<Type> (type),
511+
param.get_outer_attrs ());
510512
}
511513

512514
HIR::TypeParamBound *

gcc/rust/hir/rust-hir-dump.cc

+2-1
Original file line numberDiff line numberDiff line change
@@ -1508,7 +1508,8 @@ void
15081508
Dump::visit (TypeParam &e)
15091509
{
15101510
begin ("TypeParam");
1511-
put_field ("outer_attr", e.get_outer_attribute ().as_string ());
1511+
auto &outer_attrs = e.get_outer_attrs ();
1512+
do_outer_attrs (outer_attrs);
15121513

15131514
put_field ("type_representation", e.get_type_representation ().as_string ());
15141515

gcc/rust/hir/tree/rust-hir-item.h

+14-12
Original file line numberDiff line numberDiff line change
@@ -35,9 +35,7 @@ class TypePath;
3535
// A type generic parameter (as opposed to a lifetime generic parameter)
3636
class TypeParam : public GenericParam
3737
{
38-
// bool has_outer_attribute;
39-
// std::unique_ptr<Attribute> outer_attr;
40-
AST::Attribute outer_attr;
38+
AST::AttrVec outer_attrs;
4139

4240
Identifier type_representation;
4341

@@ -59,24 +57,24 @@ class TypeParam : public GenericParam
5957
bool has_type_param_bounds () const { return !type_param_bounds.empty (); }
6058

6159
// Returns whether the type param has an outer attribute.
62-
bool has_outer_attribute () const { return !outer_attr.is_empty (); }
63-
AST::Attribute &get_outer_attribute () { return outer_attr; }
60+
bool has_outer_attribute () const override { return outer_attrs.size () > 0; }
61+
AST::AttrVec &get_outer_attrs () override { return outer_attrs; }
6462

6563
TypeParam (Analysis::NodeMapping mappings, Identifier type_representation,
6664
location_t locus = UNDEF_LOCATION,
6765
std::vector<std::unique_ptr<TypeParamBound>> type_param_bounds
6866
= std::vector<std::unique_ptr<TypeParamBound>> (),
6967
std::unique_ptr<Type> type = nullptr,
70-
AST::Attribute outer_attr = AST::Attribute::create_empty ())
71-
: GenericParam (mappings), outer_attr (std::move (outer_attr)),
68+
AST::AttrVec outer_attrs = std::vector<AST::Attribute> ())
69+
: GenericParam (mappings), outer_attrs (std::move (outer_attrs)),
7270
type_representation (std::move (type_representation)),
7371
type_param_bounds (std::move (type_param_bounds)),
7472
type (std::move (type)), locus (locus)
7573
{}
7674

7775
// Copy constructor uses clone
7876
TypeParam (TypeParam const &other)
79-
: GenericParam (other.mappings), outer_attr (other.outer_attr),
77+
: GenericParam (other.mappings), outer_attrs (other.outer_attrs),
8078
type_representation (other.type_representation), locus (other.locus)
8179
{
8280
// guard to prevent null pointer dereference
@@ -92,7 +90,7 @@ class TypeParam : public GenericParam
9290
TypeParam &operator= (TypeParam const &other)
9391
{
9492
type_representation = other.type_representation;
95-
outer_attr = other.outer_attr;
93+
outer_attrs = other.outer_attrs;
9694
locus = other.locus;
9795
mappings = other.mappings;
9896

@@ -2741,6 +2739,7 @@ class ImplBlock : public VisItem, public WithInnerAttrs
27412739
BoundPolarity polarity;
27422740
location_t locus;
27432741
std::vector<std::unique_ptr<ImplItem>> impl_items;
2742+
bool unsafe;
27442743

27452744
public:
27462745
ImplBlock (Analysis::NodeMapping mappings,
@@ -2749,20 +2748,20 @@ class ImplBlock : public VisItem, public WithInnerAttrs
27492748
std::unique_ptr<Type> impl_type,
27502749
std::unique_ptr<TypePath> trait_ref, WhereClause where_clause,
27512750
BoundPolarity polarity, Visibility vis, AST::AttrVec inner_attrs,
2752-
AST::AttrVec outer_attrs, location_t locus)
2751+
AST::AttrVec outer_attrs, location_t locus, bool unsafe = false)
27532752
: VisItem (std::move (mappings), std::move (vis), std::move (outer_attrs)),
27542753
WithInnerAttrs (std::move (inner_attrs)),
27552754
generic_params (std::move (generic_params)),
27562755
impl_type (std::move (impl_type)), trait_ref (std::move (trait_ref)),
27572756
where_clause (std::move (where_clause)), polarity (polarity),
2758-
locus (locus), impl_items (std::move (impl_items))
2757+
locus (locus), impl_items (std::move (impl_items)), unsafe (unsafe)
27592758
{}
27602759

27612760
ImplBlock (ImplBlock const &other)
27622761
: VisItem (other), WithInnerAttrs (other.inner_attrs),
27632762
impl_type (other.impl_type->clone_type ()),
27642763
where_clause (other.where_clause), polarity (other.polarity),
2765-
locus (other.locus)
2764+
locus (other.locus), unsafe (other.unsafe)
27662765
{
27672766
generic_params.reserve (other.generic_params.size ());
27682767
for (const auto &e : other.generic_params)
@@ -2781,6 +2780,7 @@ class ImplBlock : public VisItem, public WithInnerAttrs
27812780
polarity = other.polarity;
27822781
inner_attrs = other.inner_attrs;
27832782
locus = other.locus;
2783+
unsafe = other.unsafe;
27842784

27852785
generic_params.reserve (other.generic_params.size ());
27862786
for (const auto &e : other.generic_params)
@@ -2801,6 +2801,8 @@ class ImplBlock : public VisItem, public WithInnerAttrs
28012801
// Returns whether inherent impl block has inherent impl items.
28022802
bool has_impl_items () const { return !impl_items.empty (); }
28032803

2804+
bool is_unsafe () const { return unsafe; }
2805+
28042806
void accept_vis (HIRFullVisitor &vis) override;
28052807
void accept_vis (HIRStmtVisitor &vis) override;
28062808
void accept_vis (HIRVisItemVisitor &vis) override;

gcc/rust/hir/tree/rust-hir.cc

+16-6
Original file line numberDiff line numberDiff line change
@@ -2017,14 +2017,19 @@ LifetimeParam::as_string () const
20172017
{
20182018
std::string str ("LifetimeParam: ");
20192019

2020-
str += "\n Outer attribute: ";
2021-
if (!has_outer_attribute ())
2020+
str += "\n Outer attributes: ";
2021+
if (outer_attrs.empty ())
20222022
{
20232023
str += "none";
20242024
}
20252025
else
20262026
{
2027-
str += outer_attr.as_string ();
2027+
/* note that this does not print them with "outer attribute" syntax -
2028+
* just the body */
2029+
for (const auto &attr : outer_attrs)
2030+
{
2031+
str += "\n " + attr.as_string ();
2032+
}
20282033
}
20292034

20302035
str += "\n Lifetime: " + lifetime.as_string ();
@@ -2106,14 +2111,19 @@ TypeParam::as_string () const
21062111
{
21072112
std::string str ("TypeParam: ");
21082113

2109-
str += "\n Outer attribute: ";
2110-
if (!has_outer_attribute ())
2114+
str += "\n Outer attributes: ";
2115+
if (outer_attrs.empty ())
21112116
{
21122117
str += "none";
21132118
}
21142119
else
21152120
{
2116-
str += outer_attr.as_string ();
2121+
/* note that this does not print them with "outer attribute" syntax -
2122+
* just the body */
2123+
for (const auto &attr : outer_attrs)
2124+
{
2125+
str += "\n " + attr.as_string ();
2126+
}
21172127
}
21182128

21192129
str += "\n Identifier: " + type_representation.as_string ();

gcc/rust/hir/tree/rust-hir.h

+18-8
Original file line numberDiff line numberDiff line change
@@ -617,6 +617,9 @@ class GenericParam : public FullVisitable
617617
CONST,
618618
};
619619

620+
virtual AST::AttrVec &get_outer_attrs () = 0;
621+
virtual bool has_outer_attribute () const = 0;
622+
620623
// Unique pointer custom clone function
621624
std::unique_ptr<GenericParam> clone_generic_param () const
622625
{
@@ -654,9 +657,7 @@ class LifetimeParam : public GenericParam
654657
// LifetimeBounds lifetime_bounds;
655658
std::vector<Lifetime> lifetime_bounds; // inlined LifetimeBounds
656659

657-
// bool has_outer_attribute;
658-
// std::unique_ptr<Attribute> outer_attr;
659-
AST::Attribute outer_attr;
660+
AST::AttrVec outer_attrs;
660661

661662
location_t locus;
662663

@@ -669,7 +670,9 @@ class LifetimeParam : public GenericParam
669670
std::vector<Lifetime> &get_lifetime_bounds () { return lifetime_bounds; }
670671

671672
// Returns whether the lifetime param has an outer attribute.
672-
bool has_outer_attribute () const { return !outer_attr.is_empty (); }
673+
bool has_outer_attribute () const override { return outer_attrs.size () > 1; }
674+
675+
AST::AttrVec &get_outer_attrs () { return outer_attrs; }
673676

674677
// Returns whether the lifetime param is in an error state.
675678
bool is_error () const { return lifetime.is_error (); }
@@ -679,11 +682,11 @@ class LifetimeParam : public GenericParam
679682
location_t locus = UNDEF_LOCATION,
680683
std::vector<Lifetime> lifetime_bounds
681684
= std::vector<Lifetime> (),
682-
AST::Attribute outer_attr = AST::Attribute::create_empty ())
685+
AST::AttrVec outer_attrs = std::vector<AST::Attribute> ())
683686
: GenericParam (mappings, GenericKind::LIFETIME),
684687
lifetime (std::move (lifetime)),
685688
lifetime_bounds (std::move (lifetime_bounds)),
686-
outer_attr (std::move (outer_attr)), locus (locus)
689+
outer_attrs (std::move (outer_attrs)), locus (locus)
687690
{}
688691

689692
// TODO: remove copy and assignment operator definitions - not required
@@ -692,15 +695,15 @@ class LifetimeParam : public GenericParam
692695
LifetimeParam (LifetimeParam const &other)
693696
: GenericParam (other.mappings, GenericKind::LIFETIME),
694697
lifetime (other.lifetime), lifetime_bounds (other.lifetime_bounds),
695-
outer_attr (other.outer_attr), locus (other.locus)
698+
outer_attrs (other.outer_attrs), locus (other.locus)
696699
{}
697700

698701
// Overloaded assignment operator to clone attribute
699702
LifetimeParam &operator= (LifetimeParam const &other)
700703
{
701704
lifetime = other.lifetime;
702705
lifetime_bounds = other.lifetime_bounds;
703-
outer_attr = other.outer_attr;
706+
outer_attrs = other.outer_attrs;
704707
locus = other.locus;
705708
mappings = other.mappings;
706709

@@ -748,6 +751,10 @@ class ConstGenericParam : public GenericParam
748751
default_expression = other.default_expression->clone_expr ();
749752
}
750753

754+
bool has_outer_attribute () const override { return false; }
755+
756+
AST::AttrVec &get_outer_attrs () override { return outer_attrs; }
757+
751758
std::string as_string () const override final;
752759

753760
void accept_vis (HIRFullVisitor &vis) override final;
@@ -775,6 +782,9 @@ class ConstGenericParam : public GenericParam
775782
std::string name;
776783
std::unique_ptr<Type> type;
777784

785+
/* const params have no outer attrs, should be empty */
786+
AST::AttrVec outer_attrs = std::vector<AST::Attribute> ();
787+
778788
/* Optional - can be a null pointer if there is no default expression */
779789
std::unique_ptr<Expr> default_expression;
780790

+21
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
#![feature(dropck_eyepatch)]
2+
#[allow(dead_code)]
3+
4+
#[lang = "sized"]
5+
trait Sized {}
6+
7+
struct Test<T> {
8+
_inner: T,
9+
}
10+
11+
struct Test2<T> {
12+
_inner: T,
13+
}
14+
15+
trait Action {}
16+
17+
impl<#[may_dangle] T> Action for Test<T> {} // { dg-error "use of 'may_dangle' is unsafe and requires unsafe impl" "" { target *-*-* } 0 }
18+
19+
unsafe impl<#[may_dangle] T> Action for Test2<T> {}
20+
21+
fn main() {}
+20
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
#![feature(dropck_eyepatch)]
2+
#[allow(dead_code)]
3+
4+
#[lang = "sized"]
5+
trait Sized {}
6+
7+
8+
trait Action {}
9+
10+
struct Inspector<'a>(&'a u8);
11+
struct Inspector2<'a>(&'a u8);
12+
13+
impl<#[may_dangle] 'a> Action for Inspector<'a> {} // { dg-error "use of 'may_dangle' is unsafe and requires unsafe impl" "" { target *-*-* } 0 }
14+
15+
unsafe impl<#[may_dangle] 'a> Action for Inspector2<'a> {}
16+
17+
18+
fn main() {
19+
20+
}

0 commit comments

Comments
 (0)