Branch data Line data Source code
1 : : // Copyright (C) 2020-2024 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 : : #include "rust-reachability.h"
20 : : #include "rust-tyty.h"
21 : :
22 : : namespace Rust {
23 : : namespace Privacy {
24 : :
25 : : static HIR::VisItem *
26 : 548 : maybe_get_vis_item (std::unique_ptr<HIR::Item> &item)
27 : : {
28 : 548 : if (item->get_hir_kind () != HIR::Node::VIS_ITEM)
29 : : return nullptr;
30 : :
31 : 548 : return static_cast<HIR::VisItem *> (item.get ());
32 : : }
33 : :
34 : : ReachLevel
35 : 11764 : ReachabilityVisitor::get_reachability_level (
36 : : const HIR::Visibility &item_visibility)
37 : : {
38 : 11764 : return item_visibility.is_public () ? current_level : ReachLevel::Unreachable;
39 : : }
40 : :
41 : : void
42 : 10921 : ReachabilityVisitor::visit_generic_predicates (
43 : : const std::vector<std::unique_ptr<HIR::GenericParam>> &generics,
44 : : ReachLevel item_reach)
45 : : {
46 : 10921 : if (item_reach == ReachLevel::Unreachable)
47 : : return;
48 : :
49 : 4536 : for (const auto &generic : generics)
50 : : {
51 : 2079 : if (generic->get_kind () == HIR::GenericParam::GenericKind::TYPE)
52 : : {
53 : 2057 : TyTy::BaseType *generic_ty = nullptr;
54 : 2057 : auto ok = ty_ctx.lookup_type (generic->get_mappings ().get_hirid (),
55 : : &generic_ty);
56 : 2057 : rust_assert (ok);
57 : 2057 : rust_assert (generic_ty->get_kind () == TyTy::PARAM);
58 : :
59 : 2057 : auto generic_param = static_cast<TyTy::ParamType *> (generic_ty);
60 : 4250 : for (const auto &bound : generic_param->get_specified_bounds ())
61 : : {
62 : 2193 : const auto trait = bound.get ()->get_hir_trait_ref ();
63 : 2193 : ctx.update_reachability (trait->get_mappings (), item_reach);
64 : : }
65 : : }
66 : : }
67 : : }
68 : :
69 : : void
70 : 432 : ReachabilityVisitor::visit (HIR::Module &mod)
71 : : {
72 : 432 : auto reach = get_reachability_level (mod.get_visibility ());
73 : 432 : reach = ctx.update_reachability (mod.get_mappings (), reach);
74 : :
75 : 980 : for (auto &item : mod.get_items ())
76 : : {
77 : : // FIXME: Is that what we want to do? Yes? Only visit the items with
78 : : // visibility?
79 : : //
80 : : // Imagine if we had `maybe_get_vis_item(item)?->accept_vis(*this)` ;)
81 : 548 : auto vis_item = maybe_get_vis_item (item);
82 : 548 : if (vis_item)
83 : 548 : vis_item->accept_vis (*this);
84 : : }
85 : 432 : }
86 : :
87 : : void
88 : 0 : ReachabilityVisitor::visit (HIR::ExternCrate &crate)
89 : : {
90 : 0 : auto reach = get_reachability_level (crate.get_visibility ());
91 : 0 : reach = ctx.update_reachability (crate.get_mappings (), reach);
92 : 0 : }
93 : :
94 : : void
95 : 0 : ReachabilityVisitor::visit (HIR::UseDeclaration &use_decl)
96 : : {
97 : 0 : auto reach = get_reachability_level (use_decl.get_visibility ());
98 : 0 : reach = ctx.update_reachability (use_decl.get_mappings (), reach);
99 : 0 : }
100 : :
101 : : void
102 : 4835 : ReachabilityVisitor::visit (HIR::Function &func)
103 : : {
104 : 4835 : auto fn_reach = get_reachability_level (func.get_visibility ());
105 : :
106 : 4835 : fn_reach = ctx.update_reachability (func.get_mappings (), fn_reach);
107 : 4835 : visit_generic_predicates (func.get_generic_params (), fn_reach);
108 : 4835 : }
109 : :
110 : : void
111 : 32 : ReachabilityVisitor::visit (HIR::TypeAlias &type_alias)
112 : : {
113 : 32 : auto type_reach = get_reachability_level (type_alias.get_visibility ());
114 : :
115 : 32 : visit_generic_predicates (type_alias.get_generic_params (), type_reach);
116 : 32 : }
117 : :
118 : : void
119 : 830 : ReachabilityVisitor::visit (HIR::StructStruct &struct_item)
120 : : {
121 : 830 : auto struct_reach = get_reachability_level (struct_item.get_visibility ());
122 : :
123 : 830 : struct_reach
124 : 830 : = ctx.update_reachability (struct_item.get_mappings (), struct_reach);
125 : :
126 : 830 : auto old_level = current_level;
127 : 830 : current_level = struct_reach;
128 : :
129 : 830 : visit_generic_predicates (struct_item.get_generic_params (), struct_reach);
130 : :
131 : 830 : if (struct_reach != ReachLevel::Unreachable)
132 : : {
133 : 351 : for (auto &field : struct_item.get_fields ())
134 : 199 : if (field.get_visibility ().is_public ())
135 : 162 : ctx.update_reachability (field.get_field_type ()->get_mappings (),
136 : : struct_reach);
137 : : }
138 : :
139 : 830 : current_level = old_level;
140 : 830 : }
141 : :
142 : : void
143 : 655 : ReachabilityVisitor::visit (HIR::TupleStruct &)
144 : 655 : {}
145 : :
146 : : void
147 : 157 : ReachabilityVisitor::visit (HIR::Enum &enum_item)
148 : : {
149 : 157 : auto enum_reach = get_reachability_level (enum_item.get_visibility ());
150 : :
151 : 157 : enum_reach = ctx.update_reachability (enum_item.get_mappings (), enum_reach);
152 : 157 : visit_generic_predicates (enum_item.get_generic_params (), enum_reach);
153 : :
154 : 538 : for (const auto &variant : enum_item.get_variants ())
155 : : {
156 : 381 : auto variant_reach
157 : 381 : = ctx.update_reachability (variant->get_mappings (), enum_reach);
158 : :
159 : 381 : switch (variant->get_enum_item_kind ())
160 : : {
161 : 166 : case HIR::EnumItem::Tuple: {
162 : : // Should we update the fields only if they are public? Similarly to
163 : : // what we do in the ReachabilityVisitor for HIR::TupleStruct?
164 : 166 : auto tuple_variant
165 : 166 : = static_cast<HIR::EnumItemTuple *> (variant.get ());
166 : 332 : for (const auto &field : tuple_variant->get_tuple_fields ())
167 : 166 : ctx.update_reachability (field.get_mappings (), variant_reach);
168 : : break;
169 : : }
170 : 36 : case HIR::EnumItem::Struct: {
171 : : // Should we update the fields only if they are public? Similarly to
172 : : // what we do in the ReachabilityVisitor for HIR::StructStruct?
173 : 36 : auto struct_variant
174 : 36 : = static_cast<HIR::EnumItemStruct *> (variant.get ());
175 : 107 : for (const auto &field : struct_variant->get_struct_fields ())
176 : 71 : ctx.update_reachability (field.get_mappings (), variant_reach);
177 : : break;
178 : : }
179 : : // Nothing nested to visit in that case
180 : : case HIR::EnumItem::Named:
181 : : case HIR::EnumItem::Discriminant:
182 : : break;
183 : : }
184 : : }
185 : 157 : }
186 : :
187 : : void
188 : 89 : ReachabilityVisitor::visit (HIR::Union &union_item)
189 : : {
190 : 89 : auto union_reach = get_reachability_level (union_item.get_visibility ());
191 : :
192 : 89 : union_reach
193 : 89 : = ctx.update_reachability (union_item.get_mappings (), union_reach);
194 : 89 : visit_generic_predicates (union_item.get_generic_params (), union_reach);
195 : 89 : }
196 : :
197 : : void
198 : 371 : ReachabilityVisitor::visit (HIR::ConstantItem &const_item)
199 : : {
200 : 371 : auto reach = get_reachability_level (const_item.get_visibility ());
201 : 371 : reach = ctx.update_reachability (const_item.get_mappings (), reach);
202 : 371 : }
203 : :
204 : : void
205 : 40 : ReachabilityVisitor::visit (HIR::StaticItem &static_item)
206 : : {
207 : 40 : auto reach = get_reachability_level (static_item.get_visibility ());
208 : 40 : reach = ctx.update_reachability (static_item.get_mappings (), reach);
209 : 40 : }
210 : :
211 : : void
212 : 2004 : ReachabilityVisitor::visit (HIR::Trait &trait)
213 : : {
214 : 2004 : auto trait_reach = get_reachability_level (trait.get_visibility ());
215 : :
216 : 2004 : trait_reach = ctx.update_reachability (trait.get_mappings (), trait_reach);
217 : 2004 : visit_generic_predicates (trait.get_generic_params (), trait_reach);
218 : 2004 : }
219 : :
220 : : void
221 : 2974 : ReachabilityVisitor::visit (HIR::ImplBlock &impl)
222 : : {
223 : 2974 : auto impl_reach = get_reachability_level (impl.get_visibility ());
224 : :
225 : 2974 : impl_reach = ctx.update_reachability (impl.get_mappings (), impl_reach);
226 : 2974 : visit_generic_predicates (impl.get_generic_params (), impl_reach);
227 : 2974 : }
228 : :
229 : : void
230 : 1005 : ReachabilityVisitor::visit (HIR::ExternBlock &)
231 : 1005 : {}
232 : :
233 : : // FIXME: How can we visit Blocks in the current configuration? Have a full
234 : : // visitor?
235 : : } // namespace Privacy
236 : : } // namespace Rust
|