1  // Copyright (C) 2020-2023 Free Software Foundation, Inc.
       2  
       3  // This file is part of GCC.
       4  
       5  // GCC is free software; you can redistribute it and/or modify it under
       6  // the terms of the GNU General Public License as published by the Free
       7  // Software Foundation; either version 3, or (at your option) any later
       8  // version.
       9  
      10  // GCC is distributed in the hope that it will be useful, but WITHOUT ANY
      11  // WARRANTY; without even the implied warranty of MERCHANTABILITY or
      12  // FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
      13  // for more details.
      14  
      15  // You should have received a copy of the GNU General Public License
      16  // along with GCC; see the file COPYING3.  If not see
      17  // <http://www.gnu.org/licenses/>.
      18  
      19  #ifndef RUST_PUB_RESTRICTED_VISITOR_H
      20  #define RUST_PUB_RESTRICTED_VISITOR_H
      21  
      22  #include "rust-hir-visitor.h"
      23  #include "rust-hir.h"
      24  #include "rust-hir-expr.h"
      25  #include "rust-hir-stmt.h"
      26  #include "rust-hir-item.h"
      27  #include "rust-hir-map.h"
      28  
      29  namespace Rust {
      30  namespace Privacy {
      31  
      32  /**
      33   * This visitor takes care of reporting `pub(restricted)` violations:
      34   * A `pub(restricted)` violation is defined as the usage of a path restriction
      35   * on an item which does not restrict the item's visibility to one of its parent
      36   * modules. What this means is that an user is allowed to specify that an item
      37   * should be public for any of its parent modules, going all the way to the
      38   * `crate` module, but not for any of its children module.
      39   *
      40   * ```rust
      41   * mod a {
      42   * 	mod b {
      43   * 		pub (in a) struct A0;
      44   *
      45   * 		mod c {
      46   * 			mod d {
      47   * 				pub (in a) struct A1;
      48   * 			}
      49   * 		}
      50   *
      51   * 		pub (in c::d) struct A2;
      52   * 	}
      53   * }
      54   * ```
      55   *
      56   * The above `A0`'s visibility is valid: It is restricted to a path, `a`,
      57   * which is a parent of the current module, `b`.
      58   * Likewise, `A1` is also defined properly: `a` is a parent of `d`, albeit
      59   * a great-great-great-grandparant of it.
      60   *
      61   * `A2` visibility, however, is invalid: Where the struct is defined, the
      62   * current module is `b`. `c::d` (which refers to the `d` module) is a child of
      63   * `b`, and not one of its ancestors.
      64   *
      65   * Note that these resolution rules are also the ones of the 2015 rust edition:
      66   * All the `pub(restricted)` visibilities above would be invalid in the 2018
      67   * edition, as the paths there must be absolute and not relative (`c::d` would
      68   * become `crate::a::b::c::d` etc). Nonetheless, the logic stays the same.
      69   */
      70  class PubRestrictedVisitor : public HIR::HIRVisItemVisitor
      71  {
      72  public:
      73    PubRestrictedVisitor (Analysis::Mappings &mappings);
      74  
      75    void go (HIR::Crate &crate);
      76  
      77    /**
      78     * Check if an item's restricted visibility (`pub (crate)`, `pub (self)`,
      79     * `pub(super)`, `pub (in <path>)`) is valid in the current context.
      80     * `pub restricted` visibilities are only allowed when the restriction path
      81     * is a parent module of the item being visited.
      82     *
      83     * In case of error, this function will emit the errors and return.
      84     *
      85     * @param item_id NodeId of the item to check the restriction of
      86     * @param locus Location of the item being checked
      87     *
      88     * @return true if the visibility restriction is valid, false otherwise.
      89     */
      90    bool is_restriction_valid (NodeId item_id, const Location &locus);
      91  
      92    virtual void visit (HIR::Module &mod);
      93    virtual void visit (HIR::ExternCrate &crate);
      94    virtual void visit (HIR::UseDeclaration &use_decl);
      95    virtual void visit (HIR::Function &func);
      96    virtual void visit (HIR::TypeAlias &type_alias);
      97    virtual void visit (HIR::StructStruct &struct_item);
      98    virtual void visit (HIR::TupleStruct &tuple_struct);
      99    virtual void visit (HIR::Enum &enum_item);
     100    virtual void visit (HIR::Union &union_item);
     101    virtual void visit (HIR::ConstantItem &const_item);
     102    virtual void visit (HIR::StaticItem &static_item);
     103    virtual void visit (HIR::Trait &trait);
     104    virtual void visit (HIR::ImplBlock &impl);
     105    virtual void visit (HIR::ExternBlock &block);
     106  
     107  private:
     108    /* Stack of ancestor modules visited by this visitor */
     109    std::vector<DefId> module_stack;
     110  
     111    // FIXME: Do we have to handle `self` and `super` as part of the name
     112    // resolution pass?
     113  
     114    Analysis::Mappings &mappings;
     115  };
     116  
     117  } // namespace Privacy
     118  } // namespace Rust
     119  
     120  #endif // !RUST_PUB_RESTRICTED_VISITOR_H