diff options
author | bors[bot] <26634292+bors[bot]@users.noreply.github.com> | 2022-04-12 14:32:53 +0000 |
---|---|---|
committer | GitHub <noreply@github.com> | 2022-04-12 14:32:53 +0000 |
commit | 7430791e0f71f1882a0f856c496071b76c61a6bc (patch) | |
tree | 4c285160c182b314feafef54912e80b2e7e9750f | |
parent | 2076e69bf92fae8efb0ee11a205a69ad8b4854a8 (diff) | |
parent | 1e5126022d8db1adaa925a810dbe0f8f0a13d1fa (diff) | |
download | gcc-7430791e0f71f1882a0f856c496071b76c61a6bc.zip gcc-7430791e0f71f1882a0f856c496071b76c61a6bc.tar.gz gcc-7430791e0f71f1882a0f856c496071b76c61a6bc.tar.bz2 |
Merge #1082
1082: Add base for privacy visitor r=CohenArthur a=CohenArthur
This PR is extremely early and implements some building blocks for privacy visitors. I'd like to get some feedback on the architecture and, if satisfactory, merge this first "visitor" which only takes care of visiting HIR struct definitions, to make reviewing easier. We could also merge it to a different branch for now, in order to not add an incomplete pass to the compiler.
Thanks!
Co-authored-by: Arthur Cohen <arthur.cohen@embecosm.com>
-rw-r--r-- | gcc/rust/Make-lang.in | 9 | ||||
-rw-r--r-- | gcc/rust/hir/tree/rust-hir-item.h | 11 | ||||
-rw-r--r-- | gcc/rust/hir/tree/rust-hir.h | 61 | ||||
-rw-r--r-- | gcc/rust/privacy/rust-privacy-check.cc | 49 | ||||
-rw-r--r-- | gcc/rust/privacy/rust-privacy-check.h | 45 | ||||
-rw-r--r-- | gcc/rust/privacy/rust-privacy-ctx.cc | 93 | ||||
-rw-r--r-- | gcc/rust/privacy/rust-privacy-ctx.h | 79 | ||||
-rw-r--r-- | gcc/rust/privacy/rust-reachability.cc | 157 | ||||
-rw-r--r-- | gcc/rust/privacy/rust-reachability.h | 72 | ||||
-rw-r--r-- | gcc/rust/rust-lang.cc | 3 | ||||
-rw-r--r-- | gcc/rust/rust-session-manager.cc | 4 | ||||
-rw-r--r-- | gcc/rust/typecheck/rust-hir-type-check.h | 2 | ||||
-rw-r--r-- | gcc/rust/typecheck/rust-tyctx.cc | 2 | ||||
-rw-r--r-- | gcc/rust/util/rust-mapping-common.h | 13 |
14 files changed, 591 insertions, 9 deletions
diff --git a/gcc/rust/Make-lang.in b/gcc/rust/Make-lang.in index 6240011..840a245 100644 --- a/gcc/rust/Make-lang.in +++ b/gcc/rust/Make-lang.in @@ -89,6 +89,9 @@ GRS_OBJS = \ rust/rust-ast-resolve-expr.o \ rust/rust-ast-resolve-type.o \ rust/rust-hir-type-check.o \ + rust/rust-privacy-check.o \ + rust/rust-privacy-ctx.o \ + rust/rust-reachability.o \ rust/rust-tyty.o \ rust/rust-tyctx.o \ rust/rust-tyty-bounds.o \ @@ -278,6 +281,7 @@ RUST_INCLUDES = -I $(srcdir)/rust \ -I $(srcdir)/rust/resolve \ -I $(srcdir)/rust/util \ -I $(srcdir)/rust/typecheck \ + -I $(srcdir)/rust/privacy \ -I $(srcdir)/rust/lint # add files that require cross-folder includes - currently rust-lang.o, rust-lex.o @@ -339,6 +343,11 @@ rust/%.o: rust/typecheck/%.cc $(COMPILE) $(RUST_CXXFLAGS) $(RUST_INCLUDES) $< $(POSTCOMPILE) +# build rust/privacy files in rust folder +rust/%.o: rust/privacy/%.cc + $(COMPILE) $(RUST_CXXFLAGS) $(RUST_INCLUDES) $< + $(POSTCOMPILE) + # build rust/lint files in rust folder rust/%.o: rust/lint/%.cc $(COMPILE) $(RUST_CXXFLAGS) $(RUST_INCLUDES) $< diff --git a/gcc/rust/hir/tree/rust-hir-item.h b/gcc/rust/hir/tree/rust-hir-item.h index 0c361e0..bc26725 100644 --- a/gcc/rust/hir/tree/rust-hir-item.h +++ b/gcc/rust/hir/tree/rust-hir-item.h @@ -576,6 +576,9 @@ public: // Returns whether visibility is in an error state. bool is_error () const { return vis_type == ERROR; } + // Does the current visibility refer to a simple `pub <item>` entirely public + bool is_public () const { return vis_type == PUBLIC; } + // Creates an error visibility. static Visibility create_error () { @@ -621,6 +624,8 @@ protected: public: using HIR::Stmt::accept_vis; + BaseKind get_hir_kind () override final { return VIS_ITEM; } + /* Does the item have some kind of public visibility (non-default * visibility)? */ bool has_visibility () const { return !visibility.is_error (); } @@ -1458,6 +1463,8 @@ public: Analysis::NodeMapping get_mappings () const { return mappings; } Location get_locus () { return locus; } + + Visibility &get_visibility () { return visibility; } }; // Rust struct declaration with true struct type HIR node @@ -2744,7 +2751,7 @@ protected: }; // Abstract base class for an item used inside an extern block -class ExternalItem +class ExternalItem : public Node { Analysis::NodeMapping mappings; AST::AttrVec outer_attrs; @@ -2755,6 +2762,8 @@ class ExternalItem public: virtual ~ExternalItem () {} + BaseKind get_hir_kind () override final { return EXTERNAL; } + // Returns whether item has outer attributes. bool has_outer_attrs () const { return !outer_attrs.empty (); } diff --git a/gcc/rust/hir/tree/rust-hir.h b/gcc/rust/hir/tree/rust-hir.h index fda7e1d..67cfb3a 100644 --- a/gcc/rust/hir/tree/rust-hir.h +++ b/gcc/rust/hir/tree/rust-hir.h @@ -45,6 +45,41 @@ class HIRTypeVisitor; // forward decl for use in token tree method class Token; +class Node +{ +public: + // Kind for downcasting various HIR nodes to other base classes when visiting + // them + enum BaseKind + { + /* class ExternalItem */ + EXTERNAL, + /* class TraitItem */ + TRAIT_ITEM, + /* class VisItem */ + VIS_ITEM, + /* class Item */ + ITEM, + /* class ImplItem */ + IMPL, + /* class Type */ + TYPE, + /* class Stmt */ + STMT, + /* class Expr */ + EXPR, + /* class Pattern */ + PATTERN, + }; + + /** + * Get the kind of HIR node we are dealing with. This is useful for + * downcasting to more precise types when necessary, i.e going from an `Item*` + * to a `VisItem*` + */ + virtual BaseKind get_hir_kind () = 0; +}; + // A literal - value with a type. Used in LiteralExpr and LiteralPattern. struct Literal { @@ -91,7 +126,7 @@ public: /* Base statement abstract class. Note that most "statements" are not allowed in * top-level module scope - only a subclass of statements called "items" are. */ -class Stmt +class Stmt : public Node { public: // Unique pointer custom clone function @@ -100,6 +135,8 @@ public: return std::unique_ptr<Stmt> (clone_stmt_impl ()); } + BaseKind get_hir_kind () override { return STMT; } + virtual ~Stmt () {} virtual std::string as_string () const = 0; @@ -138,6 +175,8 @@ public: return std::unique_ptr<Item> (clone_item_impl ()); } + BaseKind get_hir_kind () override { return ITEM; } + std::string as_string () const override; /* Adds crate names to the vector passed by reference, if it can @@ -171,7 +210,7 @@ protected: class ExprWithoutBlock; // Base expression HIR node - abstract -class Expr +class Expr : public Node { AST::AttrVec outer_attrs; Analysis::NodeMapping mappings; @@ -213,6 +252,8 @@ public: Path, }; + BaseKind get_hir_kind () override final { return EXPR; } + const AST::AttrVec &get_outer_attrs () const { return outer_attrs; } // Unique pointer custom clone function @@ -358,7 +399,7 @@ protected: }; // Pattern base HIR node -class Pattern +class Pattern : public Node { public: enum PatternType @@ -376,6 +417,8 @@ public: SLICE, }; + BaseKind get_hir_kind () override final { return PATTERN; } + // Unique pointer custom clone function std::unique_ptr<Pattern> clone_pattern () const { @@ -406,7 +449,7 @@ protected: class TraitBound; // Base class for types as represented in HIR - abstract -class Type +class Type : public Node { public: // Unique pointer custom clone function @@ -418,6 +461,8 @@ public: // virtual destructor virtual ~Type () {} + BaseKind get_hir_kind () override final { return TYPE; } + virtual std::string as_string () const = 0; /* HACK: convert to trait bound. Virtual method overriden by classes that @@ -686,7 +731,7 @@ protected: }; // Item used in trait declarations - abstract base class -class TraitItem +class TraitItem : public Node { public: enum TraitItemKind @@ -696,6 +741,8 @@ public: TYPE }; + BaseKind get_hir_kind () override final { return TRAIT_ITEM; } + protected: // Constructor TraitItem (Analysis::NodeMapping mappings) : mappings (mappings) {} @@ -728,7 +775,7 @@ public: virtual const AST::AttrVec &get_outer_attrs () const = 0; }; -class ImplItem +class ImplItem : public Node { public: enum ImplItemType @@ -740,6 +787,8 @@ public: virtual ~ImplItem () {} + BaseKind get_hir_kind () override final { return IMPL; } + // Unique pointer custom clone function std::unique_ptr<ImplItem> clone_inherent_impl_item () const { diff --git a/gcc/rust/privacy/rust-privacy-check.cc b/gcc/rust/privacy/rust-privacy-check.cc new file mode 100644 index 0000000..ccef318 --- /dev/null +++ b/gcc/rust/privacy/rust-privacy-check.cc @@ -0,0 +1,49 @@ +// Copyright (C) 2020-2022 Free Software Foundation, Inc. + +// This file is part of GCC. + +// GCC is free software; you can redistribute it and/or modify it under +// the terms of the GNU General Public License as published by the Free +// Software Foundation; either version 3, or (at your option) any later +// version. + +// GCC is distributed in the hope that it will be useful, but WITHOUT ANY +// WARRANTY; without even the implied warranty of MERCHANTABILITY or +// FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License +// for more details. + +// You should have received a copy of the GNU General Public License +// along with GCC; see the file COPYING3. If not see +// <http://www.gnu.org/licenses/>. + +#include "rust-privacy-check.h" +#include "rust-reachability.h" +#include "rust-hir-type-check.h" + +extern bool +saw_errors (void); + +namespace Rust { +namespace Privacy { +void +Resolver::resolve (HIR::Crate &crate) +{ + PrivacyContext ctx; + auto ty_ctx = ::Rust::Resolver::TypeCheckContext::get (); + auto visitor = ReachabilityVisitor (ctx, *ty_ctx); + + const auto &items = crate.items; + for (auto &item : items) + { + if (item->get_hir_kind () == HIR::Node::VIS_ITEM) + { + auto vis_item = static_cast<HIR::VisItem *> (item.get ()); + vis_item->accept_vis (visitor); + } + } + + if (saw_errors ()) + return; +} +} // namespace Privacy +} // namespace Rust diff --git a/gcc/rust/privacy/rust-privacy-check.h b/gcc/rust/privacy/rust-privacy-check.h new file mode 100644 index 0000000..47fe7df --- /dev/null +++ b/gcc/rust/privacy/rust-privacy-check.h @@ -0,0 +1,45 @@ +// Copyright (C) 2020-2022 Free Software Foundation, Inc. + +// This file is part of GCC. + +// GCC is free software; you can redistribute it and/or modify it under +// the terms of the GNU General Public License as published by the Free +// Software Foundation; either version 3, or (at your option) any later +// version. + +// GCC is distributed in the hope that it will be useful, but WITHOUT ANY +// WARRANTY; without even the implied warranty of MERCHANTABILITY or +// FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License +// for more details. + +// You should have received a copy of the GNU General Public License +// along with GCC; see the file COPYING3. If not see +// <http://www.gnu.org/licenses/>. + +#ifndef RUST_PRIVACY_CHECK_H +#define RUST_PRIVACY_CHECK_H + +#include "rust-hir-map.h" +#include "rust-hir.h" +#include "rust-hir-expr.h" +#include "rust-hir-stmt.h" +#include "rust-hir-item.h" +#include "rust-hir-type-check.h" + +namespace Rust { +namespace Privacy { +class Resolver +{ +public: + /** + * Perform the full privacy resolving pass on a crate. + * + * This resolver first computes the reachability of all items in a crate, + * before checking for privacy violations. + */ + static void resolve (HIR::Crate &crate); +}; +} // namespace Privacy +} // namespace Rust + +#endif // !RUST_PRIVACY_CHECK_H diff --git a/gcc/rust/privacy/rust-privacy-ctx.cc b/gcc/rust/privacy/rust-privacy-ctx.cc new file mode 100644 index 0000000..9ebc869 --- /dev/null +++ b/gcc/rust/privacy/rust-privacy-ctx.cc @@ -0,0 +1,93 @@ +// Copyright (C) 2020-2022 Free Software Foundation, Inc. + +// This file is part of GCC. + +// GCC is free software; you can redistribute it and/or modify it under +// the terms of the GNU General Public License as published by the Free +// Software Foundation; either version 3, or (at your option) any later +// version. + +// GCC is distributed in the hope that it will be useful, but WITHOUT ANY +// WARRANTY; without even the implied warranty of MERCHANTABILITY or +// FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License +// for more details. + +// You should have received a copy of the GNU General Public License +// along with GCC; see the file COPYING3. If not see +// <http://www.gnu.org/licenses/>. + +#include "rust-privacy-ctx.h" +#include "selftest.h" + +namespace Rust { +namespace Privacy { + +static ReachLevel +insert_if_higher (ReachLevel new_level, + std::unordered_map<DefId, ReachLevel>::iterator &existing) +{ + if (new_level > existing->second) + existing->second = new_level; + + return existing->second; +} + +ReachLevel +PrivacyContext::update_reachability (const Analysis::NodeMapping &mapping, + ReachLevel reach) +{ + auto def_id = mapping.get_defid (); + auto existing_reach = reachability_map.find (def_id); + if (existing_reach != reachability_map.end ()) + return insert_if_higher (reach, existing_reach); + + reachability_map.insert ({def_id, reach}); + return reach; +} + +const ReachLevel * +PrivacyContext::lookup_reachability (const Analysis::NodeMapping &mapping) +{ + auto existing_reach = reachability_map.find (mapping.get_defid ()); + if (existing_reach == reachability_map.end ()) + return nullptr; + + return &existing_reach->second; +} +} // namespace Privacy +} // namespace Rust + +#if CHECKING_P +namespace selftest { +static void +update_reachability_test (void) +{ + auto ctx = Rust::Privacy::PrivacyContext (); + // Bogus values for the mappings + auto mapping = Rust::Analysis::NodeMapping (15, 15, 15, 15); + + auto new_level + = ctx.update_reachability (mapping, Rust::Privacy::ReachLevel::Unreachable); + + ASSERT_EQ (new_level, Rust::Privacy::ReachLevel::Unreachable); + + ASSERT_TRUE (ctx.lookup_reachability (mapping)); + ASSERT_EQ (*ctx.lookup_reachability (mapping), + Rust::Privacy::ReachLevel::Unreachable); + + new_level + = ctx.update_reachability (mapping, Rust::Privacy::ReachLevel::Reachable); + + ASSERT_EQ (new_level, Rust::Privacy::ReachLevel::Reachable); + ASSERT_TRUE (ctx.lookup_reachability (mapping)); + ASSERT_EQ (*ctx.lookup_reachability (mapping), + Rust::Privacy::ReachLevel::Reachable); +} + +void +rust_privacy_ctx_test (void) +{ + update_reachability_test (); +} +} // namespace selftest +#endif // !CHECKING_P diff --git a/gcc/rust/privacy/rust-privacy-ctx.h b/gcc/rust/privacy/rust-privacy-ctx.h new file mode 100644 index 0000000..52d790e --- /dev/null +++ b/gcc/rust/privacy/rust-privacy-ctx.h @@ -0,0 +1,79 @@ +// Copyright (C) 2020-2022 Free Software Foundation, Inc. + +// This file is part of GCC. + +// GCC is free software; you can redistribute it and/or modify it under +// the terms of the GNU General Public License as published by the Free +// Software Foundation; either version 3, or (at your option) any later +// version. + +// GCC is distributed in the hope that it will be useful, but WITHOUT ANY +// WARRANTY; without even the implied warranty of MERCHANTABILITY or +// FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License +// for more details. + +// You should have received a copy of the GNU General Public License +// along with GCC; see the file COPYING3. If not see +// <http://www.gnu.org/licenses/>. + +#ifndef RUST_PRIVACY_CTX_H +#define RUST_PRIVACY_CTX_H + +#include "rust-hir-map.h" +#include "rust-privacy-check.h" + +namespace Rust { +namespace Privacy { + +/** + * Reachability levels of HIR nodes. These levels are computed through the + * `ReachabilityVisitor` visitor. + */ +enum ReachLevel +{ + Unreachable, + Reachable, +}; + +class PrivacyContext +{ +public: + /** + * Insert a new resolved visibility for a given node. If the node is already + * present in the reachability map, then its visibility will only be updated + * if the given visibility is higher. + * + * @param mappings Mappings of the node to store the reach level for + * @param reach Level of reachability for the given node + * + * @return The new reachability level for this node. If this was the first + * time inserting this node, then return `reach`. Otherwise, return `reach` or + * the existing reach level if it was higher. + */ + ReachLevel update_reachability (const Analysis::NodeMapping &mapping, + ReachLevel reach); + + /** + * Lookup the visibility of an already declared Node + * + * @param mapping Mappings of the node to fetch the reach level of + * + * @return `nullptr` if the reach level for the current node has not been + * added, a valid pointer otherwise + */ + const ReachLevel *lookup_reachability (const Analysis::NodeMapping &mapping); + +private: + std::unordered_map<DefId, ReachLevel> reachability_map; +}; +} // namespace Privacy +} // namespace Rust + +#if CHECKING_P +namespace selftest { +void +rust_privacy_ctx_test (void); +} +#endif // !CHECKING_P + +#endif // !RUST_PRIVACY_CTX_H diff --git a/gcc/rust/privacy/rust-reachability.cc b/gcc/rust/privacy/rust-reachability.cc new file mode 100644 index 0000000..82a4827 --- /dev/null +++ b/gcc/rust/privacy/rust-reachability.cc @@ -0,0 +1,157 @@ +// Copyright (C) 2020-2022 Free Software Foundation, Inc. + +// This file is part of GCC. + +// GCC is free software; you can redistribute it and/or modify it under +// the terms of the GNU General Public License as published by the Free +// Software Foundation; either version 3, or (at your option) any later +// version. + +// GCC is distributed in the hope that it will be useful, but WITHOUT ANY +// WARRANTY; without even the implied warranty of MERCHANTABILITY or +// FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License +// for more details. + +// You should have received a copy of the GNU General Public License +// along with GCC; see the file COPYING3. If not see +// <http://www.gnu.org/licenses/>. + +#include "rust-reachability.h" +#include "rust-tyty.h" + +namespace Rust { +namespace Privacy { + +static HIR::VisItem * +maybe_get_vis_item (std::unique_ptr<HIR::Item> &item) +{ + if (item->get_hir_kind () != HIR::Node::VIS_ITEM) + return nullptr; + + return static_cast<HIR::VisItem *> (item.get ()); +} + +void +ReachabilityVisitor::visit (HIR::Module &mod) +{ + for (auto &item : mod.get_items ()) + { + // FIXME: Is that what we want to do? Yes? Only visit the items with + // visibility? + // + // Imagine if we had `maybe_get_vis_item(item)?->accept_vis(*this)` ;) + auto vis_item = maybe_get_vis_item (item); + if (vis_item) + vis_item->accept_vis (*this); + } +} + +void +ReachabilityVisitor::visit (HIR::ExternCrate &crate) +{} + +void +ReachabilityVisitor::visit (HIR::UseDeclaration &use_decl) +{} + +void +ReachabilityVisitor::visit (HIR::Function &func) +{} + +void +ReachabilityVisitor::visit (HIR::TypeAlias &type_alias) +{} + +void +ReachabilityVisitor::visit (HIR::StructStruct &struct_item) +{ + auto struct_reach = ReachLevel::Unreachable; + if (struct_item.get_visibility ().is_public ()) + struct_reach = current_level; + + struct_reach + = ctx.update_reachability (struct_item.get_mappings (), struct_reach); + + auto old_level = current_level; + current_level = struct_reach; + + if (struct_reach != ReachLevel::Unreachable) + { + for (auto &field : struct_item.get_fields ()) + if (field.get_visibility ().is_public ()) + ctx.update_reachability (field.get_mappings (), struct_reach); + + for (auto &generic : struct_item.get_generic_params ()) + { + switch (generic->get_kind ()) + { + case HIR::GenericParam::LIFETIME: + break; + case HIR::GenericParam::TYPE: + TyTy::BaseType *generic_ty = nullptr; + rust_assert ( + ty_ctx.lookup_type (generic->get_mappings ().get_hirid (), + &generic_ty)); + + if (generic_ty->get_kind () == TyTy::PARAM) + { + auto generic_param + = static_cast<TyTy::ParamType *> (generic_ty); + for (const auto &bound : + generic_param->get_specified_bounds ()) + { + const auto trait = bound.get ()->get_hir_trait_ref (); + ctx.update_reachability (trait->get_mappings (), + struct_reach); + } + } + + break; + } + } + + for (auto &field : struct_item.get_fields ()) + if (field.get_visibility ().is_public ()) + ctx.update_reachability (field.get_field_type ()->get_mappings (), + struct_reach); + } + + current_level = old_level; +} + +void +ReachabilityVisitor::visit (HIR::TupleStruct &tuple_struct) +{} + +void +ReachabilityVisitor::visit (HIR::Enum &enum_item) +{} + +void +ReachabilityVisitor::visit (HIR::Union &union_item) +{} + +void +ReachabilityVisitor::visit (HIR::ConstantItem &const_item) +{} + +void +ReachabilityVisitor::visit (HIR::StaticItem &static_item) +{} + +void +ReachabilityVisitor::visit (HIR::Trait &trait) +{} + +void +ReachabilityVisitor::visit (HIR::ImplBlock &impl) +{} + +void +ReachabilityVisitor::visit (HIR::ExternBlock &block) +{} + +// FIXME: How can we visit Blocks in the current configuration? Have a full +// visitor? +} // namespace Privacy +} // namespace Rust diff --git a/gcc/rust/privacy/rust-reachability.h b/gcc/rust/privacy/rust-reachability.h new file mode 100644 index 0000000..75ed269 --- /dev/null +++ b/gcc/rust/privacy/rust-reachability.h @@ -0,0 +1,72 @@ +// Copyright (C) 2020-2022 Free Software Foundation, Inc. + +// This file is part of GCC. + +// GCC is free software; you can redistribute it and/or modify it under +// the terms of the GNU General Public License as published by the Free +// Software Foundation; either version 3, or (at your option) any later +// version. + +// GCC is distributed in the hope that it will be useful, but WITHOUT ANY +// WARRANTY; without even the implied warranty of MERCHANTABILITY or +// FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License +// for more details. + +// You should have received a copy of the GNU General Public License +// along with GCC; see the file COPYING3. If not see +// <http://www.gnu.org/licenses/>. + +#ifndef RUST_REACHABILITY_H +#define RUST_REACHABILITY_H + +#include "rust-privacy-ctx.h" +#include "rust-hir-visitor.h" +#include "rust-hir.h" +#include "rust-hir-expr.h" +#include "rust-hir-stmt.h" +#include "rust-hir-item.h" +#include "rust-hir-type-check.h" + +namespace Rust { +namespace Privacy { + +// FIXME: The EmbargoVisitor from rustc is a fixed-point visitor which tries +// to reach more and more nodes until nothing has changed anymore. +// Do we need to reproduce this behavior? How long does it take to do this? + +/** + * The ReachabilityVisitor tries to reach all items possible in the crate, + * according to their privacy level. + */ +class ReachabilityVisitor : public HIR::HIRVisItemVisitor +{ +public: + ReachabilityVisitor (PrivacyContext &ctx, + const ::Rust::Resolver::TypeCheckContext &ty_ctx) + : current_level (ReachLevel::Reachable), ctx (ctx), ty_ctx (ty_ctx) + {} + + virtual void visit (HIR::Module &mod); + virtual void visit (HIR::ExternCrate &crate); + virtual void visit (HIR::UseDeclaration &use_decl); + virtual void visit (HIR::Function &func); + virtual void visit (HIR::TypeAlias &type_alias); + virtual void visit (HIR::StructStruct &struct_item); + virtual void visit (HIR::TupleStruct &tuple_struct); + virtual void visit (HIR::Enum &enum_item); + virtual void visit (HIR::Union &union_item); + virtual void visit (HIR::ConstantItem &const_item); + virtual void visit (HIR::StaticItem &static_item); + virtual void visit (HIR::Trait &trait); + virtual void visit (HIR::ImplBlock &impl); + virtual void visit (HIR::ExternBlock &block); + +private: + ReachLevel current_level; + PrivacyContext &ctx; + const ::Rust::Resolver::TypeCheckContext &ty_ctx; +}; +} // namespace Privacy +} // namespace Rust + +#endif // !RUST_REACHABILITY_H diff --git a/gcc/rust/rust-lang.cc b/gcc/rust/rust-lang.cc index 5ecd79b..c746941 100644 --- a/gcc/rust/rust-lang.cc +++ b/gcc/rust/rust-lang.cc @@ -32,8 +32,10 @@ #include "convert.h" #include "langhooks.h" #include "langhooks-def.h" + #include "selftest.h" #include "rust-cfg-parser.h" +#include "rust-privacy-ctx.h" #include <mpfr.h> // note: header files must be in this order or else forward declarations don't @@ -455,6 +457,7 @@ run_rust_tests () // Call tests for the rust frontend here simple_assert (); rust_cfg_parser_test (); + rust_privacy_ctx_test (); } } // namespace selftest diff --git a/gcc/rust/rust-session-manager.cc b/gcc/rust/rust-session-manager.cc index 6b1d030..ec99be7 100644 --- a/gcc/rust/rust-session-manager.cc +++ b/gcc/rust/rust-session-manager.cc @@ -25,6 +25,7 @@ #include "rust-ast-resolve.h" #include "rust-ast-lower.h" #include "rust-hir-type-check.h" +#include "rust-privacy-check.h" #include "rust-tycheck-dump.h" #include "rust-compile.h" #include "rust-cfg-parser.h" @@ -609,6 +610,9 @@ Session::parse_file (const char *filename) if (saw_errors ()) return; + // privacy pass + Privacy::Resolver::resolve (hir); + // do compile to gcc generic Compile::Context ctx (backend); Compile::CompileCrate::Compile (hir, &ctx); diff --git a/gcc/rust/typecheck/rust-hir-type-check.h b/gcc/rust/typecheck/rust-hir-type-check.h index e63ef9f..e63f8ad 100644 --- a/gcc/rust/typecheck/rust-hir-type-check.h +++ b/gcc/rust/typecheck/rust-hir-type-check.h @@ -104,7 +104,7 @@ public: void insert_type (const Analysis::NodeMapping &mappings, TyTy::BaseType *type); void insert_implicit_type (TyTy::BaseType *type); - bool lookup_type (HirId id, TyTy::BaseType **type); + bool lookup_type (HirId id, TyTy::BaseType **type) const; void insert_implicit_type (HirId id, TyTy::BaseType *type); diff --git a/gcc/rust/typecheck/rust-tyctx.cc b/gcc/rust/typecheck/rust-tyctx.cc index 434809c..d8a49e8 100644 --- a/gcc/rust/typecheck/rust-tyctx.cc +++ b/gcc/rust/typecheck/rust-tyctx.cc @@ -98,7 +98,7 @@ TypeCheckContext::insert_implicit_type (HirId id, TyTy::BaseType *type) } bool -TypeCheckContext::lookup_type (HirId id, TyTy::BaseType **type) +TypeCheckContext::lookup_type (HirId id, TyTy::BaseType **type) const { auto it = resolved.find (id); if (it == resolved.end ()) diff --git a/gcc/rust/util/rust-mapping-common.h b/gcc/rust/util/rust-mapping-common.h index 27faa7f..c440ae9 100644 --- a/gcc/rust/util/rust-mapping-common.h +++ b/gcc/rust/util/rust-mapping-common.h @@ -69,4 +69,17 @@ struct DefId } // namespace Rust +namespace std { +template <> struct hash<Rust::DefId> +{ + size_t operator() (const Rust::DefId &id) const noexcept + { + // TODO: Check if we can improve performance by having a better hash + // algorithm for `DefId`s + return hash<uint32_t> () (hash<uint32_t> () (id.crateNum) + + hash<uint32_t> () (id.localDefId)); + } +}; +} // namespace std + #endif // RUST_MAPPING_COMMON |