diff options
author | bors[bot] <26634292+bors[bot]@users.noreply.github.com> | 2022-05-17 10:11:04 +0000 |
---|---|---|
committer | GitHub <noreply@github.com> | 2022-05-17 10:11:04 +0000 |
commit | 8cad07cfd2244ad9a40027a4306b81b4553a4797 (patch) | |
tree | ce267318444308626518420adf10b563c2bad96c /gcc | |
parent | e4213b9568ae8cb8a4e31326e0e78c79db0a99cc (diff) | |
parent | 48fc2df91b07709f41ab80499a661ac9f12f3be3 (diff) | |
download | gcc-8cad07cfd2244ad9a40027a4306b81b4553a4797.zip gcc-8cad07cfd2244ad9a40027a4306b81b4553a4797.tar.gz gcc-8cad07cfd2244ad9a40027a4306b81b4553a4797.tar.bz2 |
Merge #1246
1246: Report simple privacy violations r=CohenArthur a=CohenArthur
This adds a base visitor for reporting basic privacy violations. For now, only function calls are implemented.
Co-authored-by: Arthur Cohen <arthur.cohen@embecosm.com>
Diffstat (limited to 'gcc')
-rw-r--r-- | gcc/rust/Make-lang.in | 2 | ||||
-rw-r--r-- | gcc/rust/privacy/rust-privacy-check.cc | 2 | ||||
-rw-r--r-- | gcc/rust/privacy/rust-privacy-common.h | 4 | ||||
-rw-r--r-- | gcc/rust/privacy/rust-privacy-reporter.cc | 645 | ||||
-rw-r--r-- | gcc/rust/privacy/rust-privacy-reporter.h | 201 | ||||
-rw-r--r-- | gcc/rust/privacy/rust-pub-restricted-visitor.cc | 36 | ||||
-rw-r--r-- | gcc/rust/privacy/rust-pub-restricted-visitor.h | 4 | ||||
-rw-r--r-- | gcc/rust/privacy/rust-visibility-resolver.cc | 32 | ||||
-rw-r--r-- | gcc/rust/privacy/rust-visibility-resolver.h | 1 | ||||
-rw-r--r-- | gcc/rust/resolve/rust-ast-resolve-base.h | 6 | ||||
-rw-r--r-- | gcc/rust/resolve/rust-ast-resolve-item.cc | 5 | ||||
-rw-r--r-- | gcc/rust/resolve/rust-ast-resolve-toplevel.h | 14 | ||||
-rw-r--r-- | gcc/rust/resolve/rust-ast-resolve.cc | 2 | ||||
-rw-r--r-- | gcc/rust/util/rust-hir-map.cc | 26 | ||||
-rw-r--r-- | gcc/rust/util/rust-hir-map.h | 15 | ||||
-rw-r--r-- | gcc/rust/util/rust-optional-test.cc | 104 | ||||
-rw-r--r-- | gcc/rust/util/rust-optional.h | 141 | ||||
-rw-r--r-- | gcc/testsuite/rust/compile/privacy1.rs | 11 | ||||
-rw-r--r-- | gcc/testsuite/rust/compile/pub_restricted_3.rs | 11 |
19 files changed, 1164 insertions, 98 deletions
diff --git a/gcc/rust/Make-lang.in b/gcc/rust/Make-lang.in index 738cfdf..f87ad54 100644 --- a/gcc/rust/Make-lang.in +++ b/gcc/rust/Make-lang.in @@ -100,6 +100,7 @@ GRS_OBJS = \ rust/rust-reachability.o \ rust/rust-visibility-resolver.o \ rust/rust-pub-restricted-visitor.o \ + rust/rust-privacy-reporter.o \ rust/rust-tyty.o \ rust/rust-tyctx.o \ rust/rust-tyty-bounds.o \ @@ -120,6 +121,7 @@ GRS_OBJS = \ rust/rust-compile-pattern.o \ rust/rust-compile-fnparam.o \ rust/rust-base62.o \ + rust/rust-optional-test.o \ rust/rust-compile-item.o \ rust/rust-compile-implitem.o \ rust/rust-compile-expr.o \ diff --git a/gcc/rust/privacy/rust-privacy-check.cc b/gcc/rust/privacy/rust-privacy-check.cc index b2e33c0..dca5235 100644 --- a/gcc/rust/privacy/rust-privacy-check.cc +++ b/gcc/rust/privacy/rust-privacy-check.cc @@ -23,6 +23,7 @@ #include "rust-name-resolver.h" #include "rust-visibility-resolver.h" #include "rust-pub-restricted-visitor.h" +#include "rust-privacy-reporter.h" extern bool saw_errors (void); @@ -40,6 +41,7 @@ Resolver::resolve (HIR::Crate &crate) VisibilityResolver (*mappings, *resolver).go (crate); PubRestrictedVisitor (*mappings).go (crate); + PrivacyReporter (*mappings, *resolver).go (crate); auto visitor = ReachabilityVisitor (ctx, *ty_ctx); diff --git a/gcc/rust/privacy/rust-privacy-common.h b/gcc/rust/privacy/rust-privacy-common.h index a47992f..ceafe91 100644 --- a/gcc/rust/privacy/rust-privacy-common.h +++ b/gcc/rust/privacy/rust-privacy-common.h @@ -24,6 +24,9 @@ namespace Privacy { /** * Visibility class related specifically to DefIds. This class allows defining * the visibility of an item with regard to a specific module. + * + * Items are either public throughout a crate, or restricted to a specific + * module. Private items are simply restricted to the current module. */ class ModuleVisibility { @@ -31,7 +34,6 @@ public: enum Type { Unknown, - Private, Public, Restricted, }; diff --git a/gcc/rust/privacy/rust-privacy-reporter.cc b/gcc/rust/privacy/rust-privacy-reporter.cc new file mode 100644 index 0000000..4c18adb --- /dev/null +++ b/gcc/rust/privacy/rust-privacy-reporter.cc @@ -0,0 +1,645 @@ +#include "rust-privacy-reporter.h" +#include "rust-hir-expr.h" +#include "rust-hir-stmt.h" +#include "rust-hir-item.h" + +namespace Rust { +namespace Privacy { + +PrivacyReporter::PrivacyReporter (Analysis::Mappings &mappings, + Resolver::Resolver &resolver) + : mappings (mappings), resolver (resolver), + current_module (Optional<NodeId>::none ()) +{} + +void +PrivacyReporter::go (HIR::Crate &crate) +{ + for (auto &item : crate.items) + item->accept_vis (*this); +} + +static bool +is_child_module (NodeId current_module, + Optional<std::vector<NodeId> &> children) +{ + if (!children) + return false; + + // FIXME: This checks for one step - we need to go deeper + for (auto &child : *children) + if (child == current_module) + return true; + + return false; +} + +// FIXME: This function needs a lot of refactoring +void +PrivacyReporter::check_for_privacy_violation (const NodeId &use_id, + const Location &locus) +{ + NodeId ref_node_id; + + // FIXME: Don't assert here - we might be dealing with a type + rust_assert (resolver.lookup_resolved_name (use_id, &ref_node_id)); + + ModuleVisibility vis; + + // FIXME: Can we really return here if the item has no visibility? + if (!mappings.lookup_visibility (ref_node_id, vis)) + return; + + auto valid = true; + + switch (vis.get_kind ()) + { + case ModuleVisibility::Public: + break; + case ModuleVisibility::Restricted: { + // If we are in the crate, everything is restricted correctly, but we + // can't get a module for it + if (current_module.is_none ()) + return; + + auto module = mappings.lookup_defid (vis.get_module_id ()); + rust_assert (module != nullptr); + + auto mod_node_id = module->get_mappings ().get_nodeid (); + + // We are in the module referenced by the pub(restricted) visibility. + // This is valid + if (mod_node_id == current_module.get ()) + break; + + auto children = mappings.lookup_module_children (mod_node_id); + + // FIXME: This needs a LOT of TLC: hinting about the definition, a + // string to say if it's a module, function, type, etc... + if (!is_child_module (current_module.get (), children)) + valid = false; + } + break; + case ModuleVisibility::Unknown: + rust_unreachable (); + break; + } + + if (!valid) + rust_error_at (locus, "definition is private in this context"); +} + +void +PrivacyReporter::visit (HIR::IdentifierExpr &ident_expr) +{} + +void +PrivacyReporter::visit (HIR::Lifetime &lifetime) +{} + +void +PrivacyReporter::visit (HIR::LifetimeParam &lifetime_param) +{} + +void +PrivacyReporter::visit (HIR::PathInExpression &path) +{ + check_for_privacy_violation (path.get_mappings ().get_nodeid (), + path.get_locus ()); +} + +void +PrivacyReporter::visit (HIR::TypePathSegment &segment) +{} + +void +PrivacyReporter::visit (HIR::TypePathSegmentGeneric &segment) +{} + +void +PrivacyReporter::visit (HIR::TypePathSegmentFunction &segment) +{} + +void +PrivacyReporter::visit (HIR::TypePath &path) +{} + +void +PrivacyReporter::visit (HIR::QualifiedPathInExpression &path) +{} + +void +PrivacyReporter::visit (HIR::QualifiedPathInType &path) +{} + +void +PrivacyReporter::visit (HIR::LiteralExpr &expr) +{} + +void +PrivacyReporter::visit (HIR::BorrowExpr &expr) +{} + +void +PrivacyReporter::visit (HIR::DereferenceExpr &expr) +{} + +void +PrivacyReporter::visit (HIR::ErrorPropagationExpr &expr) +{} + +void +PrivacyReporter::visit (HIR::NegationExpr &expr) +{} + +void +PrivacyReporter::visit (HIR::ArithmeticOrLogicalExpr &expr) +{} + +void +PrivacyReporter::visit (HIR::ComparisonExpr &expr) +{} + +void +PrivacyReporter::visit (HIR::LazyBooleanExpr &expr) +{} + +void +PrivacyReporter::visit (HIR::TypeCastExpr &expr) +{} + +void +PrivacyReporter::visit (HIR::AssignmentExpr &expr) +{} + +void +PrivacyReporter::visit (HIR::CompoundAssignmentExpr &expr) +{} + +void +PrivacyReporter::visit (HIR::GroupedExpr &expr) +{} + +void +PrivacyReporter::visit (HIR::ArrayElemsValues &elems) +{} + +void +PrivacyReporter::visit (HIR::ArrayElemsCopied &elems) +{} + +void +PrivacyReporter::visit (HIR::ArrayExpr &expr) +{} + +void +PrivacyReporter::visit (HIR::ArrayIndexExpr &expr) +{} + +void +PrivacyReporter::visit (HIR::TupleExpr &expr) +{} + +void +PrivacyReporter::visit (HIR::TupleIndexExpr &expr) +{} + +void +PrivacyReporter::visit (HIR::StructExprStruct &expr) +{} + +void +PrivacyReporter::visit (HIR::StructExprFieldIdentifier &field) +{} + +void +PrivacyReporter::visit (HIR::StructExprFieldIdentifierValue &field) +{} + +void +PrivacyReporter::visit (HIR::StructExprFieldIndexValue &field) +{} + +void +PrivacyReporter::visit (HIR::StructExprStructFields &expr) +{} + +void +PrivacyReporter::visit (HIR::StructExprStructBase &expr) +{} + +void +PrivacyReporter::visit (HIR::CallExpr &expr) +{ + expr.get_fnexpr ()->accept_vis (*this); + + // rust_assert (mappings.lookup_visibility (definition_id, def_vis)); + // check_for_privacy_violation (def_vis, expr.get_locus ()); +} + +void +PrivacyReporter::visit (HIR::MethodCallExpr &expr) +{} + +void +PrivacyReporter::visit (HIR::FieldAccessExpr &expr) +{} + +void +PrivacyReporter::visit (HIR::ClosureExprInner &expr) +{} + +void +PrivacyReporter::visit (HIR::BlockExpr &expr) +{ + for (auto &stmt : expr.get_statements ()) + stmt->accept_vis (*this); + + auto &last_expr = expr.get_final_expr (); + if (last_expr) + last_expr->accept_vis (*this); +} + +void +PrivacyReporter::visit (HIR::ClosureExprInnerTyped &expr) +{} + +void +PrivacyReporter::visit (HIR::ContinueExpr &expr) +{} + +void +PrivacyReporter::visit (HIR::BreakExpr &expr) +{} + +void +PrivacyReporter::visit (HIR::RangeFromToExpr &expr) +{} + +void +PrivacyReporter::visit (HIR::RangeFromExpr &expr) +{} + +void +PrivacyReporter::visit (HIR::RangeToExpr &expr) +{} + +void +PrivacyReporter::visit (HIR::RangeFullExpr &expr) +{} + +void +PrivacyReporter::visit (HIR::RangeFromToInclExpr &expr) +{} + +void +PrivacyReporter::visit (HIR::RangeToInclExpr &expr) +{} + +void +PrivacyReporter::visit (HIR::ReturnExpr &expr) +{} + +void +PrivacyReporter::visit (HIR::UnsafeBlockExpr &expr) +{} + +void +PrivacyReporter::visit (HIR::LoopExpr &expr) +{} + +void +PrivacyReporter::visit (HIR::WhileLoopExpr &expr) +{} + +void +PrivacyReporter::visit (HIR::WhileLetLoopExpr &expr) +{} + +void +PrivacyReporter::visit (HIR::ForLoopExpr &expr) +{} + +void +PrivacyReporter::visit (HIR::IfExpr &expr) +{} + +void +PrivacyReporter::visit (HIR::IfExprConseqElse &expr) +{} + +void +PrivacyReporter::visit (HIR::IfExprConseqIf &expr) +{} + +void +PrivacyReporter::visit (HIR::IfExprConseqIfLet &expr) +{} + +void +PrivacyReporter::visit (HIR::IfLetExpr &expr) +{} + +void +PrivacyReporter::visit (HIR::IfLetExprConseqElse &expr) +{} + +void +PrivacyReporter::visit (HIR::IfLetExprConseqIf &expr) +{} + +void +PrivacyReporter::visit (HIR::IfLetExprConseqIfLet &expr) +{} + +void +PrivacyReporter::visit (HIR::MatchExpr &expr) +{} + +void +PrivacyReporter::visit (HIR::AwaitExpr &expr) +{} + +void +PrivacyReporter::visit (HIR::AsyncBlockExpr &expr) +{} + +void +PrivacyReporter::visit (HIR::TypeParam ¶m) +{} + +void +PrivacyReporter::visit (HIR::LifetimeWhereClauseItem &item) +{} + +void +PrivacyReporter::visit (HIR::TypeBoundWhereClauseItem &item) +{} + +void +PrivacyReporter::visit (HIR::Module &module) +{ + auto old_module = current_module; + current_module + = Optional<NodeId>::some (module.get_mappings ().get_nodeid ()); + + for (auto &item : module.get_items ()) + item->accept_vis (*this); + + current_module = old_module; +} + +void +PrivacyReporter::visit (HIR::ExternCrate &crate) +{} + +void +PrivacyReporter::visit (HIR::UseTreeGlob &use_tree) +{} + +void +PrivacyReporter::visit (HIR::UseTreeList &use_tree) +{} + +void +PrivacyReporter::visit (HIR::UseTreeRebind &use_tree) +{} + +void +PrivacyReporter::visit (HIR::UseDeclaration &use_decl) +{} + +void +PrivacyReporter::visit (HIR::Function &function) +{ + function.get_definition ()->accept_vis (*this); +} + +void +PrivacyReporter::visit (HIR::TypeAlias &type_alias) +{} + +void +PrivacyReporter::visit (HIR::StructStruct &struct_item) +{} + +void +PrivacyReporter::visit (HIR::TupleStruct &tuple_struct) +{} + +void +PrivacyReporter::visit (HIR::EnumItem &item) +{} + +void +PrivacyReporter::visit (HIR::EnumItemTuple &item) +{} + +void +PrivacyReporter::visit (HIR::EnumItemStruct &item) +{} + +void +PrivacyReporter::visit (HIR::EnumItemDiscriminant &item) +{} + +void +PrivacyReporter::visit (HIR::Enum &enum_item) +{} + +void +PrivacyReporter::visit (HIR::Union &union_item) +{} + +void +PrivacyReporter::visit (HIR::ConstantItem &const_item) +{} + +void +PrivacyReporter::visit (HIR::StaticItem &static_item) +{} + +void +PrivacyReporter::visit (HIR::TraitItemFunc &item) +{} + +void +PrivacyReporter::visit (HIR::TraitItemConst &item) +{} + +void +PrivacyReporter::visit (HIR::TraitItemType &item) +{} + +void +PrivacyReporter::visit (HIR::Trait &trait) +{} + +void +PrivacyReporter::visit (HIR::ImplBlock &impl) +{} + +void +PrivacyReporter::visit (HIR::ExternalStaticItem &item) +{} + +void +PrivacyReporter::visit (HIR::ExternalFunctionItem &item) +{} + +void +PrivacyReporter::visit (HIR::ExternBlock &block) +{} + +void +PrivacyReporter::visit (HIR::LiteralPattern &pattern) +{} + +void +PrivacyReporter::visit (HIR::IdentifierPattern &pattern) +{} + +void +PrivacyReporter::visit (HIR::WildcardPattern &pattern) +{} + +void +PrivacyReporter::visit (HIR::RangePatternBoundLiteral &bound) +{} + +void +PrivacyReporter::visit (HIR::RangePatternBoundPath &bound) +{} + +void +PrivacyReporter::visit (HIR::RangePatternBoundQualPath &bound) +{} + +void +PrivacyReporter::visit (HIR::RangePattern &pattern) +{} + +void +PrivacyReporter::visit (HIR::ReferencePattern &pattern) +{} + +void +PrivacyReporter::visit (HIR::StructPatternFieldTuplePat &field) +{} + +void +PrivacyReporter::visit (HIR::StructPatternFieldIdentPat &field) +{} + +void +PrivacyReporter::visit (HIR::StructPatternFieldIdent &field) +{} + +void +PrivacyReporter::visit (HIR::StructPattern &pattern) +{} + +void +PrivacyReporter::visit (HIR::TupleStructItemsNoRange &tuple_items) +{} + +void +PrivacyReporter::visit (HIR::TupleStructItemsRange &tuple_items) +{} + +void +PrivacyReporter::visit (HIR::TupleStructPattern &pattern) +{} + +void +PrivacyReporter::visit (HIR::TuplePatternItemsMultiple &tuple_items) +{} + +void +PrivacyReporter::visit (HIR::TuplePatternItemsRanged &tuple_items) +{} + +void +PrivacyReporter::visit (HIR::TuplePattern &pattern) +{} + +void +PrivacyReporter::visit (HIR::GroupedPattern &pattern) +{} + +void +PrivacyReporter::visit (HIR::SlicePattern &pattern) +{} + +void +PrivacyReporter::visit (HIR::EmptyStmt &stmt) +{} + +void +PrivacyReporter::visit (HIR::LetStmt &stmt) +{} + +void +PrivacyReporter::visit (HIR::ExprStmtWithoutBlock &stmt) +{ + stmt.get_expr ()->accept_vis (*this); +} + +void +PrivacyReporter::visit (HIR::ExprStmtWithBlock &stmt) +{} + +void +PrivacyReporter::visit (HIR::TraitBound &bound) +{} + +void +PrivacyReporter::visit (HIR::ImplTraitType &type) +{} + +void +PrivacyReporter::visit (HIR::TraitObjectType &type) +{} + +void +PrivacyReporter::visit (HIR::ParenthesisedType &type) +{} + +void +PrivacyReporter::visit (HIR::ImplTraitTypeOneBound &type) +{} + +void +PrivacyReporter::visit (HIR::TupleType &type) +{} + +void +PrivacyReporter::visit (HIR::NeverType &type) +{} + +void +PrivacyReporter::visit (HIR::RawPointerType &type) +{} + +void +PrivacyReporter::visit (HIR::ReferenceType &type) +{} + +void +PrivacyReporter::visit (HIR::ArrayType &type) +{} + +void +PrivacyReporter::visit (HIR::SliceType &type) +{} + +void +PrivacyReporter::visit (HIR::InferredType &type) +{} + +void +PrivacyReporter::visit (HIR::BareFunctionType &type) +{} + +} // namespace Privacy +} // namespace Rust diff --git a/gcc/rust/privacy/rust-privacy-reporter.h b/gcc/rust/privacy/rust-privacy-reporter.h new file mode 100644 index 0000000..fafcec1 --- /dev/null +++ b/gcc/rust/privacy/rust-privacy-reporter.h @@ -0,0 +1,201 @@ +// 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_REPORTER_H +#define RUST_PRIVACY_REPORTER_H + +#include "rust-hir-map.h" +#include "rust-hir-visitor.h" +#include "rust-mapping-common.h" +#include "rust-name-resolver.h" + +namespace Rust { +namespace Privacy { + +/** + * This visitor visits all items and expressions of a crate and reports privacy + * violations. It should be started after using the `VisibilityResolver` visitor + * which resolves the visibilities of all items of a crate. + */ +class PrivacyReporter : public HIR::HIRFullVisitor +{ +public: + PrivacyReporter (Analysis::Mappings &mappings, + Rust::Resolver::Resolver &resolver); + + /** + * Perform privacy error reporting on an entire crate + */ + void go (HIR::Crate &crate); + +private: + /** + * Check if a given item's visibility is accessible from the current module. + * + * This function reports the errors it finds. + * + * @param use_id NodeId of the expression/statement referencing an item with + * a visibility + * @param locus Location of said expression/statement + */ + void check_for_privacy_violation (const NodeId &use_id, + const Location &locus); + + virtual void visit (HIR::IdentifierExpr &ident_expr); + virtual void visit (HIR::Lifetime &lifetime); + virtual void visit (HIR::LifetimeParam &lifetime_param); + virtual void visit (HIR::PathInExpression &path); + virtual void visit (HIR::TypePathSegment &segment); + virtual void visit (HIR::TypePathSegmentGeneric &segment); + virtual void visit (HIR::TypePathSegmentFunction &segment); + virtual void visit (HIR::TypePath &path); + virtual void visit (HIR::QualifiedPathInExpression &path); + virtual void visit (HIR::QualifiedPathInType &path); + virtual void visit (HIR::LiteralExpr &expr); + virtual void visit (HIR::BorrowExpr &expr); + virtual void visit (HIR::DereferenceExpr &expr); + virtual void visit (HIR::ErrorPropagationExpr &expr); + virtual void visit (HIR::NegationExpr &expr); + virtual void visit (HIR::ArithmeticOrLogicalExpr &expr); + virtual void visit (HIR::ComparisonExpr &expr); + virtual void visit (HIR::LazyBooleanExpr &expr); + virtual void visit (HIR::TypeCastExpr &expr); + virtual void visit (HIR::AssignmentExpr &expr); + virtual void visit (HIR::CompoundAssignmentExpr &expr); + virtual void visit (HIR::GroupedExpr &expr); + virtual void visit (HIR::ArrayElemsValues &elems); + virtual void visit (HIR::ArrayElemsCopied &elems); + virtual void visit (HIR::ArrayExpr &expr); + virtual void visit (HIR::ArrayIndexExpr &expr); + virtual void visit (HIR::TupleExpr &expr); + virtual void visit (HIR::TupleIndexExpr &expr); + virtual void visit (HIR::StructExprStruct &expr); + virtual void visit (HIR::StructExprFieldIdentifier &field); + virtual void visit (HIR::StructExprFieldIdentifierValue &field); + virtual void visit (HIR::StructExprFieldIndexValue &field); + virtual void visit (HIR::StructExprStructFields &expr); + virtual void visit (HIR::StructExprStructBase &expr); + virtual void visit (HIR::CallExpr &expr); + virtual void visit (HIR::MethodCallExpr &expr); + virtual void visit (HIR::FieldAccessExpr &expr); + virtual void visit (HIR::ClosureExprInner &expr); + virtual void visit (HIR::BlockExpr &expr); + virtual void visit (HIR::ClosureExprInnerTyped &expr); + virtual void visit (HIR::ContinueExpr &expr); + virtual void visit (HIR::BreakExpr &expr); + virtual void visit (HIR::RangeFromToExpr &expr); + virtual void visit (HIR::RangeFromExpr &expr); + virtual void visit (HIR::RangeToExpr &expr); + virtual void visit (HIR::RangeFullExpr &expr); + virtual void visit (HIR::RangeFromToInclExpr &expr); + virtual void visit (HIR::RangeToInclExpr &expr); + virtual void visit (HIR::ReturnExpr &expr); + virtual void visit (HIR::UnsafeBlockExpr &expr); + virtual void visit (HIR::LoopExpr &expr); + virtual void visit (HIR::WhileLoopExpr &expr); + virtual void visit (HIR::WhileLetLoopExpr &expr); + virtual void visit (HIR::ForLoopExpr &expr); + virtual void visit (HIR::IfExpr &expr); + virtual void visit (HIR::IfExprConseqElse &expr); + virtual void visit (HIR::IfExprConseqIf &expr); + virtual void visit (HIR::IfExprConseqIfLet &expr); + virtual void visit (HIR::IfLetExpr &expr); + virtual void visit (HIR::IfLetExprConseqElse &expr); + virtual void visit (HIR::IfLetExprConseqIf &expr); + virtual void visit (HIR::IfLetExprConseqIfLet &expr); + virtual void visit (HIR::MatchExpr &expr); + virtual void visit (HIR::AwaitExpr &expr); + virtual void visit (HIR::AsyncBlockExpr &expr); + virtual void visit (HIR::TypeParam ¶m); + virtual void visit (HIR::LifetimeWhereClauseItem &item); + virtual void visit (HIR::TypeBoundWhereClauseItem &item); + virtual void visit (HIR::Module &module); + virtual void visit (HIR::ExternCrate &crate); + virtual void visit (HIR::UseTreeGlob &use_tree); + virtual void visit (HIR::UseTreeList &use_tree); + virtual void visit (HIR::UseTreeRebind &use_tree); + virtual void visit (HIR::UseDeclaration &use_decl); + virtual void visit (HIR::Function &function); + 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::EnumItem &item); + virtual void visit (HIR::EnumItemTuple &item); + virtual void visit (HIR::EnumItemStruct &item); + virtual void visit (HIR::EnumItemDiscriminant &item); + 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::TraitItemFunc &item); + virtual void visit (HIR::TraitItemConst &item); + virtual void visit (HIR::TraitItemType &item); + virtual void visit (HIR::Trait &trait); + virtual void visit (HIR::ImplBlock &impl); + virtual void visit (HIR::ExternalStaticItem &item); + virtual void visit (HIR::ExternalFunctionItem &item); + virtual void visit (HIR::ExternBlock &block); + virtual void visit (HIR::LiteralPattern &pattern); + virtual void visit (HIR::IdentifierPattern &pattern); + virtual void visit (HIR::WildcardPattern &pattern); + virtual void visit (HIR::RangePatternBoundLiteral &bound); + virtual void visit (HIR::RangePatternBoundPath &bound); + virtual void visit (HIR::RangePatternBoundQualPath &bound); + virtual void visit (HIR::RangePattern &pattern); + virtual void visit (HIR::ReferencePattern &pattern); + virtual void visit (HIR::StructPatternFieldTuplePat &field); + virtual void visit (HIR::StructPatternFieldIdentPat &field); + virtual void visit (HIR::StructPatternFieldIdent &field); + virtual void visit (HIR::StructPattern &pattern); + virtual void visit (HIR::TupleStructItemsNoRange &tuple_items); + virtual void visit (HIR::TupleStructItemsRange &tuple_items); + virtual void visit (HIR::TupleStructPattern &pattern); + virtual void visit (HIR::TuplePatternItemsMultiple &tuple_items); + virtual void visit (HIR::TuplePatternItemsRanged &tuple_items); + virtual void visit (HIR::TuplePattern &pattern); + virtual void visit (HIR::GroupedPattern &pattern); + virtual void visit (HIR::SlicePattern &pattern); + virtual void visit (HIR::EmptyStmt &stmt); + virtual void visit (HIR::LetStmt &stmt); + virtual void visit (HIR::ExprStmtWithoutBlock &stmt); + virtual void visit (HIR::ExprStmtWithBlock &stmt); + virtual void visit (HIR::TraitBound &bound); + virtual void visit (HIR::ImplTraitType &type); + virtual void visit (HIR::TraitObjectType &type); + virtual void visit (HIR::ParenthesisedType &type); + virtual void visit (HIR::ImplTraitTypeOneBound &type); + virtual void visit (HIR::TupleType &type); + virtual void visit (HIR::NeverType &type); + virtual void visit (HIR::RawPointerType &type); + virtual void visit (HIR::ReferenceType &type); + virtual void visit (HIR::ArrayType &type); + virtual void visit (HIR::SliceType &type); + virtual void visit (HIR::InferredType &type); + virtual void visit (HIR::BareFunctionType &type); + + Analysis::Mappings &mappings; + Rust::Resolver::Resolver &resolver; + + // `None` means we're in the root module - the crate + Optional<NodeId> current_module; +}; + +} // namespace Privacy +} // namespace Rust + +#endif // !RUST_PRIVACY_REPORTER_H diff --git a/gcc/rust/privacy/rust-pub-restricted-visitor.cc b/gcc/rust/privacy/rust-pub-restricted-visitor.cc index ca50fe3..e391653 100644 --- a/gcc/rust/privacy/rust-pub-restricted-visitor.cc +++ b/gcc/rust/privacy/rust-pub-restricted-visitor.cc @@ -24,14 +24,15 @@ namespace Rust { namespace Privacy { bool -PubRestrictedVisitor::is_restriction_valid (DefId item_id, +PubRestrictedVisitor::is_restriction_valid (NodeId item_id, const Location &locus) { ModuleVisibility visibility; // If there is no visibility in the mappings, then the item is private and // does not contain any restriction - if (!mappings.lookup_visibility (item_id, &visibility)) + // FIXME: Is that correct? + if (!mappings.lookup_visibility (item_id, visibility)) return true; for (auto mod = module_stack.rbegin (); mod != module_stack.rend (); mod++) @@ -72,7 +73,7 @@ PubRestrictedVisitor::visit (HIR::Module &mod) // FIXME: We need to update `super` and `self` here module_stack.push_back (mod.get_mappings ().get_defid ()); - is_restriction_valid (mod.get_mappings ().get_defid (), mod.get_locus ()); + is_restriction_valid (mod.get_mappings ().get_nodeid (), mod.get_locus ()); for (auto &item : mod.get_items ()) { @@ -89,33 +90,34 @@ PubRestrictedVisitor::visit (HIR::Module &mod) void PubRestrictedVisitor::visit (HIR::ExternCrate &crate) { - is_restriction_valid (crate.get_mappings ().get_defid (), crate.get_locus ()); + is_restriction_valid (crate.get_mappings ().get_nodeid (), + crate.get_locus ()); } void PubRestrictedVisitor::visit (HIR::UseDeclaration &use_decl) { - is_restriction_valid (use_decl.get_mappings ().get_defid (), + is_restriction_valid (use_decl.get_mappings ().get_nodeid (), use_decl.get_locus ()); } void PubRestrictedVisitor::visit (HIR::Function &func) { - is_restriction_valid (func.get_mappings ().get_defid (), func.get_locus ()); + is_restriction_valid (func.get_mappings ().get_nodeid (), func.get_locus ()); } void PubRestrictedVisitor::visit (HIR::TypeAlias &type_alias) { - is_restriction_valid (type_alias.get_mappings ().get_defid (), + is_restriction_valid (type_alias.get_mappings ().get_nodeid (), type_alias.get_locus ()); } void PubRestrictedVisitor::visit (HIR::StructStruct &struct_item) { - is_restriction_valid (struct_item.get_mappings ().get_defid (), + is_restriction_valid (struct_item.get_mappings ().get_nodeid (), struct_item.get_locus ()); // FIXME: Check fields here as well } @@ -123,7 +125,7 @@ PubRestrictedVisitor::visit (HIR::StructStruct &struct_item) void PubRestrictedVisitor::visit (HIR::TupleStruct &tuple_struct) { - is_restriction_valid (tuple_struct.get_mappings ().get_defid (), + is_restriction_valid (tuple_struct.get_mappings ().get_nodeid (), tuple_struct.get_locus ()); // FIXME: Check fields here as well } @@ -131,47 +133,49 @@ PubRestrictedVisitor::visit (HIR::TupleStruct &tuple_struct) void PubRestrictedVisitor::visit (HIR::Enum &enum_item) { - is_restriction_valid (enum_item.get_mappings ().get_defid (), + is_restriction_valid (enum_item.get_mappings ().get_nodeid (), enum_item.get_locus ()); } void PubRestrictedVisitor::visit (HIR::Union &union_item) { - is_restriction_valid (union_item.get_mappings ().get_defid (), + is_restriction_valid (union_item.get_mappings ().get_nodeid (), union_item.get_locus ()); } void PubRestrictedVisitor::visit (HIR::ConstantItem &const_item) { - is_restriction_valid (const_item.get_mappings ().get_defid (), + is_restriction_valid (const_item.get_mappings ().get_nodeid (), const_item.get_locus ()); } void PubRestrictedVisitor::visit (HIR::StaticItem &static_item) { - is_restriction_valid (static_item.get_mappings ().get_defid (), + is_restriction_valid (static_item.get_mappings ().get_nodeid (), static_item.get_locus ()); } void PubRestrictedVisitor::visit (HIR::Trait &trait) { - is_restriction_valid (trait.get_mappings ().get_defid (), trait.get_locus ()); + is_restriction_valid (trait.get_mappings ().get_nodeid (), + trait.get_locus ()); } void PubRestrictedVisitor::visit (HIR::ImplBlock &impl) { - is_restriction_valid (impl.get_mappings ().get_defid (), impl.get_locus ()); + is_restriction_valid (impl.get_mappings ().get_nodeid (), impl.get_locus ()); } void PubRestrictedVisitor::visit (HIR::ExternBlock &block) { - is_restriction_valid (block.get_mappings ().get_defid (), block.get_locus ()); + is_restriction_valid (block.get_mappings ().get_nodeid (), + block.get_locus ()); } } // namespace Privacy diff --git a/gcc/rust/privacy/rust-pub-restricted-visitor.h b/gcc/rust/privacy/rust-pub-restricted-visitor.h index dc725e1..2685f3d 100644 --- a/gcc/rust/privacy/rust-pub-restricted-visitor.h +++ b/gcc/rust/privacy/rust-pub-restricted-visitor.h @@ -82,12 +82,12 @@ public: * * In case of error, this function will emit the errors and return. * - * @param item_id DefId of the item to check the restriction of + * @param item_id NodeId of the item to check the restriction of * @param locus Location of the item being checked * * @return true if the visibility restriction is valid, false otherwise. */ - bool is_restriction_valid (DefId item_id, const Location &locus); + bool is_restriction_valid (NodeId item_id, const Location &locus); virtual void visit (HIR::Module &mod); virtual void visit (HIR::ExternCrate &crate); diff --git a/gcc/rust/privacy/rust-visibility-resolver.cc b/gcc/rust/privacy/rust-visibility-resolver.cc index 38d6403..421dff0 100644 --- a/gcc/rust/privacy/rust-visibility-resolver.cc +++ b/gcc/rust/privacy/rust-visibility-resolver.cc @@ -32,9 +32,11 @@ VisibilityResolver::VisibilityResolver (Analysis::Mappings &mappings, void VisibilityResolver::go (HIR::Crate &crate) { - mappings.insert_visibility (crate.get_mappings ().get_defid (), + mappings.insert_visibility (crate.get_mappings ().get_nodeid (), ModuleVisibility::create_public ()); + current_module = crate.get_mappings ().get_defid (); + for (auto &item : crate.items) { if (item->get_hir_kind () == HIR::Node::VIS_ITEM) @@ -103,15 +105,18 @@ VisibilityResolver::resolve_visibility (const HIR::Visibility &visibility, switch (visibility.get_vis_type ()) { case HIR::Visibility::PRIVATE: + to_resolve = ModuleVisibility::create_restricted (current_module); return true; case HIR::Visibility::PUBLIC: to_resolve = ModuleVisibility::create_public (); return true; - case HIR::Visibility::RESTRICTED: - // FIXME: We also need to handle 2015 vs 2018 edition conflicts - to_resolve = ModuleVisibility::create_public (); - return resolve_module_path (visibility.get_path (), - to_resolve.get_module_id ()); + case HIR::Visibility::RESTRICTED: { + // FIXME: We also need to handle 2015 vs 2018 edition conflicts + auto id = UNKNOWN_DEFID; + auto result = resolve_module_path (visibility.get_path (), id); + to_resolve = ModuleVisibility::create_restricted (id); + return result; + } default: gcc_unreachable (); return false; @@ -125,12 +130,15 @@ VisibilityResolver::resolve_and_update (const HIR::VisItem *item) if (!resolve_visibility (item->get_visibility (), module_vis)) return; // we will already have emitted errors - mappings.insert_visibility (item->get_mappings ().get_defid (), module_vis); + mappings.insert_visibility (item->get_mappings ().get_nodeid (), module_vis); } void VisibilityResolver::visit (HIR::Module &mod) { + auto old_module = current_module; + current_module = mod.get_mappings ().get_defid (); + for (auto &item : mod.get_items ()) { if (item->get_hir_kind () == HIR::Node::VIS_ITEM) @@ -139,6 +147,8 @@ VisibilityResolver::visit (HIR::Module &mod) vis_item->accept_vis (*this); } } + + current_module = old_module; } void @@ -180,9 +190,9 @@ VisibilityResolver::visit (HIR::Enum &enum_item) if (!resolve_visibility (enum_item.get_visibility (), vis)) return; - mappings.insert_visibility (enum_item.get_mappings ().get_defid (), vis); + mappings.insert_visibility (enum_item.get_mappings ().get_nodeid (), vis); for (auto &variant : enum_item.get_variants ()) - mappings.insert_visibility (variant->get_mappings ().get_defid (), vis); + mappings.insert_visibility (variant->get_mappings ().get_nodeid (), vis); } void @@ -208,9 +218,9 @@ VisibilityResolver::visit (HIR::Trait &trait) if (!resolve_visibility (trait.get_visibility (), vis)) return; - mappings.insert_visibility (trait.get_mappings ().get_defid (), vis); + mappings.insert_visibility (trait.get_mappings ().get_nodeid (), vis); for (auto &item : trait.get_trait_items ()) - mappings.insert_visibility (item->get_mappings ().get_defid (), vis); + mappings.insert_visibility (item->get_mappings ().get_nodeid (), vis); } void diff --git a/gcc/rust/privacy/rust-visibility-resolver.h b/gcc/rust/privacy/rust-visibility-resolver.h index c57d518..20a581c 100644 --- a/gcc/rust/privacy/rust-visibility-resolver.h +++ b/gcc/rust/privacy/rust-visibility-resolver.h @@ -94,6 +94,7 @@ public: private: Analysis::Mappings &mappings; Rust::Resolver::Resolver &resolver; + DefId current_module; }; } // namespace Privacy diff --git a/gcc/rust/resolve/rust-ast-resolve-base.h b/gcc/rust/resolve/rust-ast-resolve-base.h index 17d05c3..9c1f0a1 100644 --- a/gcc/rust/resolve/rust-ast-resolve-base.h +++ b/gcc/rust/resolve/rust-ast-resolve-base.h @@ -199,9 +199,10 @@ public: void visit (AST::BareFunctionType &); protected: - ResolverBase (NodeId parent) + ResolverBase (NodeId parent, NodeId current_module = UNKNOWN_NODEID) : resolver (Resolver::get ()), mappings (Analysis::Mappings::get ()), - resolved_node (UNKNOWN_NODEID), parent (parent), locus (Location ()) + resolved_node (UNKNOWN_NODEID), parent (parent), + current_module (current_module), locus (Location ()) {} bool resolved () const { return resolved_node != UNKNOWN_NODEID; } @@ -215,6 +216,7 @@ protected: Analysis::Mappings *mappings; NodeId resolved_node; NodeId parent; + NodeId current_module; Location locus; }; diff --git a/gcc/rust/resolve/rust-ast-resolve-item.cc b/gcc/rust/resolve/rust-ast-resolve-item.cc index 93eca1b..38e7713 100644 --- a/gcc/rust/resolve/rust-ast-resolve-item.cc +++ b/gcc/rust/resolve/rust-ast-resolve-item.cc @@ -250,8 +250,11 @@ ResolveItem::visit (AST::Module &module) resolver->push_new_type_rib (resolver->get_type_scope ().peek ()); resolver->push_new_label_rib (resolver->get_type_scope ().peek ()); + // FIXME: Should we reinsert a child here? Any reason we ResolveTopLevel::go + // in ResolveTopLevel::visit (AST::Module) as well as here? for (auto &item : module.get_items ()) - ResolveTopLevel::go (item.get (), CanonicalPath::create_empty (), cpath); + ResolveTopLevel::go (item.get (), CanonicalPath::create_empty (), cpath, + module.get_node_id ()); for (auto &item : module.get_items ()) ResolveItem::go (item.get (), path, cpath); diff --git a/gcc/rust/resolve/rust-ast-resolve-toplevel.h b/gcc/rust/resolve/rust-ast-resolve-toplevel.h index 7aba67f..7cfaa72 100644 --- a/gcc/rust/resolve/rust-ast-resolve-toplevel.h +++ b/gcc/rust/resolve/rust-ast-resolve-toplevel.h @@ -34,12 +34,12 @@ class ResolveTopLevel : public ResolverBase public: static void go (AST::Item *item, const CanonicalPath &prefix, - const CanonicalPath &canonical_prefix) + const CanonicalPath &canonical_prefix, NodeId current_module) { if (item->is_marked_for_strip ()) return; - ResolveTopLevel resolver (prefix, canonical_prefix); + ResolveTopLevel resolver (prefix, canonical_prefix, current_module); item->accept_vis (resolver); }; @@ -62,8 +62,10 @@ public: Definition{module.get_node_id (), module.get_node_id ()}); + mappings->insert_module_child (current_module, module.get_node_id ()); + for (auto &item : module.get_items ()) - ResolveTopLevel::go (item.get (), path, cpath); + ResolveTopLevel::go (item.get (), path, cpath, module.get_node_id ()); mappings->insert_canonical_path (mappings->get_current_crate (), module.get_node_id (), cpath); @@ -123,7 +125,7 @@ public: }); for (auto &variant : enum_decl.get_variants ()) - ResolveTopLevel::go (variant.get (), path, cpath); + ResolveTopLevel::go (variant.get (), path, cpath, current_module); mappings->insert_canonical_path (mappings->get_current_crate (), enum_decl.get_node_id (), cpath); @@ -403,8 +405,8 @@ public: private: ResolveTopLevel (const CanonicalPath &prefix, - const CanonicalPath &canonical_prefix) - : ResolverBase (UNKNOWN_NODEID), prefix (prefix), + const CanonicalPath &canonical_prefix, NodeId current_module) + : ResolverBase (UNKNOWN_NODEID, current_module), prefix (prefix), canonical_prefix (canonical_prefix) {} diff --git a/gcc/rust/resolve/rust-ast-resolve.cc b/gcc/rust/resolve/rust-ast-resolve.cc index 6da5609..945ff28 100644 --- a/gcc/rust/resolve/rust-ast-resolve.cc +++ b/gcc/rust/resolve/rust-ast-resolve.cc @@ -86,7 +86,7 @@ NameResolution::go (AST::Crate &crate) // a Self type Foo which is defined after the impl block for example. for (auto it = crate.items.begin (); it != crate.items.end (); it++) ResolveTopLevel::go (it->get (), CanonicalPath::create_empty (), - crate_prefix); + crate_prefix, scope_node_id); // FIXME remove this if (saw_errors ()) diff --git a/gcc/rust/util/rust-hir-map.cc b/gcc/rust/util/rust-hir-map.cc index 66d3e41..934331b 100644 --- a/gcc/rust/util/rust-hir-map.cc +++ b/gcc/rust/util/rust-hir-map.cc @@ -832,21 +832,41 @@ Mappings::lookup_macro_def (NodeId id, AST::MacroRulesDefinition **def) } void -Mappings::insert_visibility (DefId id, Privacy::ModuleVisibility visibility) +Mappings::insert_visibility (NodeId id, Privacy::ModuleVisibility visibility) { visibility_map.insert ({id, visibility}); } bool -Mappings::lookup_visibility (DefId id, Privacy::ModuleVisibility *def) +Mappings::lookup_visibility (NodeId id, Privacy::ModuleVisibility &def) { auto it = visibility_map.find (id); if (it == visibility_map.end ()) return false; - *def = it->second; + def = it->second; return true; } +void +Mappings::insert_module_child (NodeId module, NodeId child) +{ + auto it = module_child_map.find (module); + if (it == module_child_map.end ()) + module_child_map.insert ({module, {child}}); + else + it->second.emplace_back (child); +} + +Optional<std::vector<NodeId> &> +Mappings::lookup_module_children (NodeId module) +{ + auto it = module_child_map.find (module); + if (it == module_child_map.end ()) + return Optional<std::vector<NodeId> &>::none (); + + return Optional<std::vector<NodeId> &>::some (it->second); +} + } // namespace Analysis } // namespace Rust diff --git a/gcc/rust/util/rust-hir-map.h b/gcc/rust/util/rust-hir-map.h index 0bb870b..03bfd5f 100644 --- a/gcc/rust/util/rust-hir-map.h +++ b/gcc/rust/util/rust-hir-map.h @@ -19,6 +19,7 @@ #ifndef RUST_HIR_MAP_H #define RUST_HIR_MAP_H +#include "rust-optional.h" #include "rust-system.h" #include "rust-location.h" #include "rust-mapping-common.h" @@ -318,8 +319,11 @@ 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); + void insert_visibility (NodeId id, Privacy::ModuleVisibility visibility); + bool lookup_visibility (NodeId id, Privacy::ModuleVisibility &def); + + void insert_module_child (NodeId module, NodeId child); + Optional<std::vector<NodeId> &> lookup_module_children (NodeId module); private: Mappings (); @@ -385,7 +389,12 @@ private: std::map<CrateNum, std::string> crate_names; // Low level visibility map for each DefId - std::map<DefId, Privacy::ModuleVisibility> visibility_map; + std::map<NodeId, Privacy::ModuleVisibility> visibility_map; + + // Module tree maps + + // Maps each module's node id to a list of its children + std::map<NodeId, std::vector<NodeId>> module_child_map; }; } // namespace Analysis diff --git a/gcc/rust/util/rust-optional-test.cc b/gcc/rust/util/rust-optional-test.cc new file mode 100644 index 0000000..9045ac3 --- /dev/null +++ b/gcc/rust/util/rust-optional-test.cc @@ -0,0 +1,104 @@ +// 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-optional.h" + +#include "config.h" +#include "selftest.h" + +static void +rust_optional_create () +{ + auto opt = Rust::Optional<int>::some (15); + + ASSERT_TRUE (opt.is_some ()); + ASSERT_EQ (opt.get (), 15); + + Rust::Optional<int> const_opt = Rust::Optional<int>::some (15); + const int &value = const_opt.get (); + + ASSERT_EQ (value, 15); +} + +static void +rust_optional_operators () +{ + auto opt = Rust::Optional<int>::some (15); + + // as bool + ASSERT_TRUE (opt); + + // deref + ASSERT_EQ (*opt, 15); + + class Methodable + { + public: + int method () { return 15; } + }; + + auto m_opt = Rust::Optional<Methodable>::some (Methodable ()); + ASSERT_EQ (m_opt->method (), 15); +} + +static void +rust_optional_take () +{ + auto opt = Rust::Optional<int>::some (15); + auto value = opt.take (); + + ASSERT_EQ (value, 15); + ASSERT_TRUE (opt.is_none ()); +} + +static void +rust_optional_map () +{ + auto opt = Rust::Optional<int>::some (15); + auto twice = opt.map<int> ([] (int value) { return value * 2; }); + + ASSERT_FALSE (opt); + ASSERT_TRUE (twice); + ASSERT_EQ (*twice, 30); +} + +static void +rust_optional_reference () +{ + auto value = std::vector<std::string> (); + value.emplace_back ("rust"); + value.emplace_back ("+"); + value.emplace_back ("gcc"); + value.emplace_back ("="); + value.emplace_back ("<3"); + + auto opt = Rust::Optional<std::vector<std::string> &>::some (value); + + ASSERT_EQ (opt->at (0), "rust"); + ASSERT_EQ (opt->at (2), "gcc"); +} + +void +rust_optional_test () +{ + rust_optional_create (); + rust_optional_operators (); + rust_optional_take (); + rust_optional_map (); + rust_optional_reference (); +} diff --git a/gcc/rust/util/rust-optional.h b/gcc/rust/util/rust-optional.h index c1b547a..5646540 100644 --- a/gcc/rust/util/rust-optional.h +++ b/gcc/rust/util/rust-optional.h @@ -96,6 +96,7 @@ private: public: Optional (const Optional &other) = default; + Optional &operator= (const Optional &other) = default; Optional (Optional &&other) = default; static Optional<T> some (T value) @@ -167,74 +168,110 @@ public: } }; -} // namespace Rust +template <typename T> class Optional<T &> +{ +private: + struct Empty + { + }; -#ifdef CHECKING_P + enum Kind + { + Some, + None + } kind; -static void -rust_optional_create () -{ - auto opt = Rust::Optional<int>::some (15); + union Content + { + Empty empty; + T *value; - ASSERT_TRUE (opt.is_some ()); - ASSERT_EQ (opt.get (), 15); + Content () = default; + } content; - Rust::Optional<int> const_opt = Rust::Optional<int>::some (15); - const int &value = const_opt.get (); + Optional<T &> (Kind kind, Content content) : kind (kind), content (content) {} - ASSERT_EQ (value, 15); -} +public: + Optional (const Optional &other) = default; + Optional (Optional &&other) = default; -static void -rust_optional_operators () -{ - auto opt = Rust::Optional<int>::some (15); + static Optional<T &> some (T &value) + { + Content content; + content.value = &value; + + return Optional (Kind::Some, content); + } + + static Optional<T &> none () + { + Content content; + content.empty = Empty (); + + return Optional (Kind::None, content); + } + + bool is_some () const { return kind == Kind::Some; } + bool is_none () const { return !is_some (); } + + // FIXME: Can we factor this in a single class? + + /** + * Enable boolean-like comparisons. + */ + operator bool () { return is_some (); } - // as bool - ASSERT_TRUE (opt); + /** + * Enables dereferencing to access the contained value + */ + T &operator* () { return get (); } + const T &operator* () const { return get (); } + T *operator-> () { return &get (); } + const T *operator-> () const { return &get (); } - // deref - ASSERT_EQ (*opt, 15); + const T &get () const + { + rust_assert (is_some ()); + + return *content.value; + } - class Methodable + T &get () { - public: - int method () { return 15; } - }; + rust_assert (is_some ()); - auto m_opt = Rust::Optional<Methodable>::some (Methodable ()); - ASSERT_EQ (m_opt->method (), 15); -} + return *content.value; + } -static void -rust_optional_take () -{ - auto opt = Rust::Optional<int>::some (15); - auto value = opt.take (); + T &take () + { + rust_assert (is_some ()); - ASSERT_EQ (value, 15); - ASSERT_TRUE (opt.is_none ()); -} + auto to_return = std::move (content.value); -static void -rust_optional_map () -{ - auto opt = Rust::Optional<int>::some (15); - auto twice = opt.map<int> ([] (int value) { return value * 2; }); + content.empty = Empty (); + kind = Kind::None; + + return *to_return; + } - ASSERT_FALSE (opt); - ASSERT_TRUE (twice); - ASSERT_EQ (*twice, 30); -} + template <typename U> Optional<U &> map (std::function<U &(T &)> functor) + { + if (is_none ()) + return Optional::none (); -static void -rust_optional_test () -{ - rust_optional_create (); - rust_optional_operators (); - rust_optional_take (); - rust_optional_map (); -} + auto value = functor (take ()); + + return Optional::some (value); + } +}; + +} // namespace Rust + +#ifdef CHECKING_P + +void +rust_optional_test (); #endif // !CHECKING_P diff --git a/gcc/testsuite/rust/compile/privacy1.rs b/gcc/testsuite/rust/compile/privacy1.rs new file mode 100644 index 0000000..1cc83c0 --- /dev/null +++ b/gcc/testsuite/rust/compile/privacy1.rs @@ -0,0 +1,11 @@ +mod orange { + mod green { + fn sain() {} + pub fn doux() {} + } + + fn brown() { + green::sain(); // { dg-error "definition is private in this context" } + green::doux(); + } +} diff --git a/gcc/testsuite/rust/compile/pub_restricted_3.rs b/gcc/testsuite/rust/compile/pub_restricted_3.rs new file mode 100644 index 0000000..d477385 --- /dev/null +++ b/gcc/testsuite/rust/compile/pub_restricted_3.rs @@ -0,0 +1,11 @@ +// { dg-additional-options "-w" } + +mod foo { + mod bar { + pub(in foo) fn baz() {} + } + + fn baz() { + bar::baz(); // no error, foo::bar::baz is public in foo + } +} |