aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorbors[bot] <26634292+bors[bot]@users.noreply.github.com>2022-04-22 12:15:22 +0000
committerGitHub <noreply@github.com>2022-04-22 12:15:22 +0000
commit4337aea3be387921ee60520d2188906d8762367b (patch)
treeea9540ded2e2be710336c3ed7a0c0d4de72f1e99
parentb392376cc521230c8b254841ab036541317dc907 (diff)
parentbdd1b86ccb87d942a24dd60c01736e439ad57087 (diff)
downloadgcc-4337aea3be387921ee60520d2188906d8762367b.zip
gcc-4337aea3be387921ee60520d2188906d8762367b.tar.gz
gcc-4337aea3be387921ee60520d2188906d8762367b.tar.bz2
Merge #1155
1155: Add base for visibility resolving r=CohenArthur a=CohenArthur This adds a new visitor whose aim is to resolve the visibility of each VisItem in a crate. The crux of the implementation will be resolving `pub restricted` items, whose module needs to be resolved using name resolution/path resolution. On top of that, we will need to add a new visitor building a "tree" of modules, with a `accessible_from` or `is_child_of` method: All children of a module get to access its items whose visibility is inherited. Co-authored-by: Arthur Cohen <arthur.cohen@embecosm.com>
-rw-r--r--gcc/rust/Make-lang.in1
-rw-r--r--gcc/rust/hir/tree/rust-hir-item.h2
-rw-r--r--gcc/rust/privacy/rust-privacy-check.cc8
-rw-r--r--gcc/rust/privacy/rust-privacy-check.h1
-rw-r--r--gcc/rust/privacy/rust-privacy-common.h64
-rw-r--r--gcc/rust/privacy/rust-reachability.h2
-rw-r--r--gcc/rust/privacy/rust-visibility-resolver.cc163
-rw-r--r--gcc/rust/privacy/rust-visibility-resolver.h89
-rw-r--r--gcc/rust/util/rust-hir-map.cc17
-rw-r--r--gcc/rust/util/rust-hir-map.h7
10 files changed, 352 insertions, 2 deletions
diff --git a/gcc/rust/Make-lang.in b/gcc/rust/Make-lang.in
index 82a4d6b..d25f403 100644
--- a/gcc/rust/Make-lang.in
+++ b/gcc/rust/Make-lang.in
@@ -93,6 +93,7 @@ GRS_OBJS = \
rust/rust-privacy-check.o \
rust/rust-privacy-ctx.o \
rust/rust-reachability.o \
+ rust/rust-visibility-resolver.o \
rust/rust-tyty.o \
rust/rust-tyctx.o \
rust/rust-tyty-bounds.o \
diff --git a/gcc/rust/hir/tree/rust-hir-item.h b/gcc/rust/hir/tree/rust-hir-item.h
index 2f69630..2e28207 100644
--- a/gcc/rust/hir/tree/rust-hir-item.h
+++ b/gcc/rust/hir/tree/rust-hir-item.h
@@ -549,7 +549,7 @@ public:
const Analysis::NodeMapping &get_mappings () const { return mappings; }
};
-// Visibility of item - if the item has it, then it is some form of public
+// Visibility of an item
struct Visibility
{
public:
diff --git a/gcc/rust/privacy/rust-privacy-check.cc b/gcc/rust/privacy/rust-privacy-check.cc
index ccef318..ccfed2c 100644
--- a/gcc/rust/privacy/rust-privacy-check.cc
+++ b/gcc/rust/privacy/rust-privacy-check.cc
@@ -19,6 +19,8 @@
#include "rust-privacy-check.h"
#include "rust-reachability.h"
#include "rust-hir-type-check.h"
+#include "rust-hir-map.h"
+#include "rust-visibility-resolver.h"
extern bool
saw_errors (void);
@@ -29,10 +31,16 @@ void
Resolver::resolve (HIR::Crate &crate)
{
PrivacyContext ctx;
+ auto mappings = Analysis::Mappings::get ();
+
+ auto resolver = VisibilityResolver (*mappings);
+ resolver.go (crate);
+
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)
diff --git a/gcc/rust/privacy/rust-privacy-check.h b/gcc/rust/privacy/rust-privacy-check.h
index 47fe7df..290b5ea 100644
--- a/gcc/rust/privacy/rust-privacy-check.h
+++ b/gcc/rust/privacy/rust-privacy-check.h
@@ -19,7 +19,6 @@
#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"
diff --git a/gcc/rust/privacy/rust-privacy-common.h b/gcc/rust/privacy/rust-privacy-common.h
new file mode 100644
index 0000000..145eac7
--- /dev/null
+++ b/gcc/rust/privacy/rust-privacy-common.h
@@ -0,0 +1,64 @@
+// 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-mapping-common.h"
+
+namespace Rust {
+namespace Privacy {
+
+/**
+ * Visibility class related specifically to DefIds. This class allows defining
+ * the visibility of an item with regard to a specific module.
+ */
+class ModuleVisibility
+{
+public:
+ enum Type
+ {
+ Unknown,
+ Private,
+ Public,
+ Restricted,
+ };
+
+ ModuleVisibility () : kind (Unknown), module_id (UNKNOWN_DEFID) {}
+
+ static ModuleVisibility create_restricted (DefId module_id)
+ {
+ return ModuleVisibility (Type::Restricted, module_id);
+ }
+
+ static ModuleVisibility create_public ()
+ {
+ return ModuleVisibility (Type::Public, UNKNOWN_DEFID);
+ }
+
+ Type get_kind () const { return kind; }
+
+ const DefId &get_module_id () const { return module_id; }
+
+private:
+ ModuleVisibility (Type kind, DefId module_id)
+ : kind (kind), module_id (module_id)
+ {}
+
+ Type kind;
+ DefId module_id;
+};
+} // namespace Privacy
+} // namespace Rust
diff --git a/gcc/rust/privacy/rust-reachability.h b/gcc/rust/privacy/rust-reachability.h
index e61fbdf..e0bc4f5 100644
--- a/gcc/rust/privacy/rust-reachability.h
+++ b/gcc/rust/privacy/rust-reachability.h
@@ -46,6 +46,8 @@ public:
: current_level (ReachLevel::Reachable), ctx (ctx), ty_ctx (ty_ctx)
{}
+ // FIXME: Add `go` method which takes an `HIR::Crate &` as argument
+
/**
* Visit all the predicates of all the generic types of a given item, marking
* them as reachable or not.
diff --git a/gcc/rust/privacy/rust-visibility-resolver.cc b/gcc/rust/privacy/rust-visibility-resolver.cc
new file mode 100644
index 0000000..0b7a529
--- /dev/null
+++ b/gcc/rust/privacy/rust-visibility-resolver.cc
@@ -0,0 +1,163 @@
+// 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-visibility-resolver.h"
+#include "rust-ast.h"
+#include "rust-hir.h"
+#include "rust-hir-item.h"
+
+namespace Rust {
+namespace Privacy {
+
+VisibilityResolver::VisibilityResolver (Analysis::Mappings &mappings)
+ : mappings (mappings)
+{}
+
+void
+VisibilityResolver::go (HIR::Crate &crate)
+{
+ module_stack.push_back (crate.get_mappings ().get_defid ());
+ mappings.insert_visibility (crate.get_mappings ().get_defid (),
+ ModuleVisibility::create_public ());
+
+ for (auto &item : crate.items)
+ {
+ if (item->get_hir_kind () == HIR::Node::VIS_ITEM)
+ {
+ auto vis_item = static_cast<HIR::VisItem *> (item.get ());
+ vis_item->accept_vis (*this);
+ }
+ }
+}
+
+bool
+VisibilityResolver::resolve_visibility (const HIR::Visibility &visibility,
+ ModuleVisibility &to_resolve)
+{
+ switch (visibility.get_vis_type ())
+ {
+ case HIR::Visibility::PRIVATE:
+ to_resolve = ModuleVisibility::create_restricted (peek_module ());
+ return true;
+ case HIR::Visibility::PUBLIC:
+ // FIXME: We need to handle the restricted path here
+ // FIXME: We also need to handle 2015 vs 2018 edition conflicts
+ to_resolve = ModuleVisibility::create_public ();
+ return true;
+ default:
+ return false;
+ }
+}
+
+DefId
+VisibilityResolver::peek_module ()
+{
+ // We're always inserting a top module - the crate
+ // But we have to check otherwise `.back()` is UB
+ rust_assert (!module_stack.empty ());
+
+ return module_stack.back ();
+}
+
+void
+VisibilityResolver::visit (HIR::Module &mod)
+{
+ module_stack.push_back (mod.get_mappings ().get_defid ());
+
+ for (auto &item : mod.get_items ())
+ {
+ if (item->get_hir_kind () == HIR::Node::VIS_ITEM)
+ {
+ auto vis_item = static_cast<HIR::VisItem *> (item.get ());
+ vis_item->accept_vis (*this);
+ }
+ }
+
+ module_stack.pop_back ();
+}
+
+void
+VisibilityResolver::visit (HIR::ExternCrate &crate)
+{}
+
+void
+VisibilityResolver::visit (HIR::UseDeclaration &use_decl)
+{}
+
+void
+VisibilityResolver::visit (HIR::Function &func)
+{}
+
+void
+VisibilityResolver::visit (HIR::TypeAlias &type_alias)
+{}
+
+void
+VisibilityResolver::visit (HIR::StructStruct &struct_item)
+{}
+
+void
+VisibilityResolver::visit (HIR::TupleStruct &tuple_struct)
+{}
+
+void
+VisibilityResolver::visit (HIR::Enum &enum_item)
+{
+ ModuleVisibility vis;
+ if (!resolve_visibility (enum_item.get_visibility (), vis))
+ return;
+
+ mappings.insert_visibility (enum_item.get_mappings ().get_defid (), vis);
+ for (auto &variant : enum_item.get_variants ())
+ mappings.insert_visibility (variant->get_mappings ().get_defid (), vis);
+}
+
+void
+VisibilityResolver::visit (HIR::Union &union_item)
+{}
+
+void
+VisibilityResolver::visit (HIR::ConstantItem &const_item)
+{}
+
+void
+VisibilityResolver::visit (HIR::StaticItem &static_item)
+{}
+
+void
+VisibilityResolver::visit (HIR::Trait &trait)
+{
+ ModuleVisibility vis;
+ if (!resolve_visibility (trait.get_visibility (), vis))
+ return;
+
+ mappings.insert_visibility (trait.get_mappings ().get_defid (), vis);
+ for (auto &item : trait.get_trait_items ())
+ mappings.insert_visibility (item->get_mappings ().get_defid (), vis);
+}
+
+void
+VisibilityResolver::visit (HIR::ImplBlock &impl)
+{}
+
+void
+VisibilityResolver::visit (HIR::ExternBlock &block)
+{}
+
+} // namespace Privacy
+} // namespace Rust
diff --git a/gcc/rust/privacy/rust-visibility-resolver.h b/gcc/rust/privacy/rust-visibility-resolver.h
new file mode 100644
index 0000000..394c3d4
--- /dev/null
+++ b/gcc/rust/privacy/rust-visibility-resolver.h
@@ -0,0 +1,89 @@
+// 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_VISIBILITY_H
+#define RUST_VISIBILITY_H
+
+#include "rust-hir.h"
+#include "rust-hir-expr.h"
+#include "rust-hir-stmt.h"
+#include "rust-hir-item.h"
+#include "rust-hir-map.h"
+#include "rust-hir-visitor.h"
+
+namespace Rust {
+namespace Privacy {
+
+class VisibilityResolver : public HIR::HIRVisItemVisitor
+{
+public:
+ VisibilityResolver (Analysis::Mappings &mappings);
+
+ /**
+ * Perform visibility resolving on an entire crate
+ */
+ void go (HIR::Crate &crate);
+
+ /**
+ * Resolve the visibility of an item to its ModuleVisibility. This function
+ * emits errors if necessary. The contents of the to_resolve parameter will be
+ * overwritten on success.
+ *
+ * @param visibility Visibility of the item to resolve
+ * @param to_resolve ModuleVisibility reference to fill on success.
+ *
+ * @return false on error, true if the resolving was successful.
+ */
+ bool resolve_visibility (const HIR::Visibility &visibility,
+ ModuleVisibility &to_resolve);
+
+ /**
+ * Get the DefId of the parent module we are currently visiting.
+ *
+ * @return UNKNOWN_DEFID if the module stack is empty, a valid `DefId`
+ * otherwise
+ */
+ DefId peek_module ();
+
+ 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:
+ /* Mappings to insert visibilities into */
+ Analysis::Mappings &mappings;
+
+ /* Stack of modules visited by this visitor */
+ std::vector<DefId> module_stack;
+};
+
+} // namespace Privacy
+} // namespace Rust
+
+#endif // !RUST_VISIBILITY_H
diff --git a/gcc/rust/util/rust-hir-map.cc b/gcc/rust/util/rust-hir-map.cc
index b08258c..ac1cf70 100644
--- a/gcc/rust/util/rust-hir-map.cc
+++ b/gcc/rust/util/rust-hir-map.cc
@@ -781,5 +781,22 @@ Mappings::lookup_macro_def (NodeId id, AST::MacroRulesDefinition **def)
return true;
}
+void
+Mappings::insert_visibility (DefId id, Privacy::ModuleVisibility visibility)
+{
+ visibility_map.insert ({id, visibility});
+}
+
+bool
+Mappings::lookup_visibility (DefId id, Privacy::ModuleVisibility *def)
+{
+ auto it = visibility_map.find (id);
+ if (it == visibility_map.end ())
+ return false;
+
+ *def = it->second;
+ return true;
+}
+
} // namespace Analysis
} // namespace Rust
diff --git a/gcc/rust/util/rust-hir-map.h b/gcc/rust/util/rust-hir-map.h
index 9bac328..74fabdf 100644
--- a/gcc/rust/util/rust-hir-map.h
+++ b/gcc/rust/util/rust-hir-map.h
@@ -26,6 +26,7 @@
#include "rust-ast-full-decls.h"
#include "rust-hir-full-decls.h"
#include "rust-lang-item.h"
+#include "rust-privacy-common.h"
namespace Rust {
namespace Analysis {
@@ -295,6 +296,9 @@ public:
bool lookup_macro_def (NodeId id, AST::MacroRulesDefinition **def);
+ void insert_visibility (DefId id, Privacy::ModuleVisibility visibility);
+ bool lookup_visibility (DefId id, Privacy::ModuleVisibility *def);
+
private:
Mappings ();
@@ -353,6 +357,9 @@ private:
// crate names
std::map<CrateNum, std::string> crate_names;
+
+ // Low level visibility map for each DefId
+ std::map<DefId, Privacy::ModuleVisibility> visibility_map;
};
} // namespace Analysis