Branch data Line data Source code
1 : : // Copyright (C) 2020-2025 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 : 3863 : maybe_get_vis_item (std::unique_ptr<HIR::Item> &item)
27 : : {
28 : 3863 : if (item->get_hir_kind () != HIR::Node::VIS_ITEM)
29 : : return nullptr;
30 : :
31 : 3863 : return static_cast<HIR::VisItem *> (item.get ());
32 : : }
33 : :
34 : : ReachLevel
35 : 18264 : ReachabilityVisitor::get_reachability_level (
36 : : const HIR::Visibility &item_visibility)
37 : : {
38 : 18264 : return item_visibility.is_public () ? current_level : ReachLevel::Unreachable;
39 : : }
40 : :
41 : : void
42 : 16662 : ReachabilityVisitor::visit_generic_predicates (
43 : : const std::vector<std::unique_ptr<HIR::GenericParam>> &generics,
44 : : ReachLevel item_reach)
45 : : {
46 : 16662 : if (item_reach == ReachLevel::Unreachable)
47 : : return;
48 : :
49 : 7841 : for (const auto &generic : generics)
50 : : {
51 : 3758 : if (generic->get_kind () == HIR::GenericParam::GenericKind::TYPE)
52 : : {
53 : 3732 : TyTy::BaseType *generic_ty = nullptr;
54 : 3732 : auto ok = ty_ctx.lookup_type (generic->get_mappings ().get_hirid (),
55 : : &generic_ty);
56 : 3732 : rust_assert (ok);
57 : 3732 : rust_assert (generic_ty->get_kind () == TyTy::PARAM);
58 : :
59 : 3732 : auto generic_param = static_cast<TyTy::ParamType *> (generic_ty);
60 : 7772 : for (const auto &bound : generic_param->get_specified_bounds ())
61 : : {
62 : 4040 : const auto trait = bound.get ()->get_hir_trait_ref ();
63 : 4040 : ctx.update_reachability (trait->get_mappings (), item_reach);
64 : : }
65 : : }
66 : : }
67 : : }
68 : :
69 : : void
70 : 1164 : ReachabilityVisitor::visit (HIR::Module &mod)
71 : : {
72 : 1164 : auto reach = get_reachability_level (mod.get_visibility ());
73 : 1164 : reach = ctx.update_reachability (mod.get_mappings (), reach);
74 : :
75 : 5027 : 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 : 3863 : auto vis_item = maybe_get_vis_item (item);
82 : 3863 : if (vis_item)
83 : 3863 : vis_item->accept_vis (*this);
84 : : }
85 : 1164 : }
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 : 5853 : ReachabilityVisitor::visit (HIR::Function &func)
103 : : {
104 : 5853 : auto fn_reach = get_reachability_level (func.get_visibility ());
105 : :
106 : 5853 : fn_reach = ctx.update_reachability (func.get_mappings (), fn_reach);
107 : 5853 : visit_generic_predicates (func.get_generic_params (), fn_reach);
108 : 5853 : }
109 : :
110 : : void
111 : 33 : ReachabilityVisitor::visit (HIR::TypeAlias &type_alias)
112 : : {
113 : 33 : auto type_reach = get_reachability_level (type_alias.get_visibility ());
114 : :
115 : 33 : visit_generic_predicates (type_alias.get_generic_params (), type_reach);
116 : 33 : }
117 : :
118 : : void
119 : 1274 : ReachabilityVisitor::visit (HIR::StructStruct &struct_item)
120 : : {
121 : 1274 : auto struct_reach = get_reachability_level (struct_item.get_visibility ());
122 : :
123 : 1274 : struct_reach
124 : 1274 : = ctx.update_reachability (struct_item.get_mappings (), struct_reach);
125 : :
126 : 1274 : auto old_level = current_level;
127 : 1274 : current_level = struct_reach;
128 : :
129 : 1274 : visit_generic_predicates (struct_item.get_generic_params (), struct_reach);
130 : :
131 : 1274 : if (struct_reach != ReachLevel::Unreachable)
132 : : {
133 : 544 : for (auto &field : struct_item.get_fields ())
134 : 265 : if (field.get_visibility ().is_public ())
135 : 208 : ctx.update_reachability (field.get_field_type ().get_mappings (),
136 : : struct_reach);
137 : : }
138 : :
139 : 1274 : current_level = old_level;
140 : 1274 : }
141 : :
142 : : void
143 : 783 : ReachabilityVisitor::visit (HIR::TupleStruct &)
144 : 783 : {}
145 : :
146 : : void
147 : 472 : ReachabilityVisitor::visit (HIR::Enum &enum_item)
148 : : {
149 : 472 : auto enum_reach = get_reachability_level (enum_item.get_visibility ());
150 : :
151 : 472 : enum_reach = ctx.update_reachability (enum_item.get_mappings (), enum_reach);
152 : 472 : visit_generic_predicates (enum_item.get_generic_params (), enum_reach);
153 : :
154 : 1596 : for (const auto &variant : enum_item.get_variants ())
155 : : {
156 : 1124 : auto variant_reach
157 : 1124 : = ctx.update_reachability (variant->get_mappings (), enum_reach);
158 : :
159 : 1124 : switch (variant->get_enum_item_kind ())
160 : : {
161 : 382 : case HIR::EnumItem::Tuple:
162 : 382 : {
163 : : // Should we update the fields only if they are public? Similarly to
164 : : // what we do in the ReachabilityVisitor for HIR::TupleStruct?
165 : 382 : auto tuple_variant
166 : 382 : = static_cast<HIR::EnumItemTuple *> (variant.get ());
167 : 789 : for (const auto &field : tuple_variant->get_tuple_fields ())
168 : 407 : ctx.update_reachability (field.get_mappings (), variant_reach);
169 : : break;
170 : : }
171 : 76 : case HIR::EnumItem::Struct:
172 : 76 : {
173 : : // Should we update the fields only if they are public? Similarly to
174 : : // what we do in the ReachabilityVisitor for HIR::StructStruct?
175 : 76 : auto struct_variant
176 : 76 : = static_cast<HIR::EnumItemStruct *> (variant.get ());
177 : 204 : for (const auto &field : struct_variant->get_struct_fields ())
178 : 128 : ctx.update_reachability (field.get_mappings (), variant_reach);
179 : : break;
180 : : }
181 : : // Nothing nested to visit in that case
182 : : case HIR::EnumItem::Named:
183 : : case HIR::EnumItem::Discriminant:
184 : : break;
185 : : }
186 : : }
187 : 472 : }
188 : :
189 : : void
190 : 97 : ReachabilityVisitor::visit (HIR::Union &union_item)
191 : : {
192 : 97 : auto union_reach = get_reachability_level (union_item.get_visibility ());
193 : :
194 : 97 : union_reach
195 : 97 : = ctx.update_reachability (union_item.get_mappings (), union_reach);
196 : 97 : visit_generic_predicates (union_item.get_generic_params (), union_reach);
197 : 97 : }
198 : :
199 : : void
200 : 389 : ReachabilityVisitor::visit (HIR::ConstantItem &const_item)
201 : : {
202 : 389 : auto reach = get_reachability_level (const_item.get_visibility ());
203 : 389 : reach = ctx.update_reachability (const_item.get_mappings (), reach);
204 : 389 : }
205 : :
206 : : void
207 : 49 : ReachabilityVisitor::visit (HIR::StaticItem &static_item)
208 : : {
209 : 49 : auto reach = get_reachability_level (static_item.get_visibility ());
210 : 49 : reach = ctx.update_reachability (static_item.get_mappings (), reach);
211 : 49 : }
212 : :
213 : : void
214 : 3452 : ReachabilityVisitor::visit (HIR::Trait &trait)
215 : : {
216 : 3452 : auto trait_reach = get_reachability_level (trait.get_visibility ());
217 : :
218 : 3452 : trait_reach = ctx.update_reachability (trait.get_mappings (), trait_reach);
219 : 3452 : visit_generic_predicates (trait.get_generic_params (), trait_reach);
220 : 3452 : }
221 : :
222 : : void
223 : 5481 : ReachabilityVisitor::visit (HIR::ImplBlock &impl)
224 : : {
225 : 5481 : auto impl_reach = get_reachability_level (impl.get_visibility ());
226 : :
227 : 5481 : impl_reach = ctx.update_reachability (impl.get_mappings (), impl_reach);
228 : 5481 : visit_generic_predicates (impl.get_generic_params (), impl_reach);
229 : 5481 : }
230 : :
231 : : void
232 : 1398 : ReachabilityVisitor::visit (HIR::ExternBlock &)
233 : 1398 : {}
234 : :
235 : : // FIXME: How can we visit Blocks in the current configuration? Have a full
236 : : // visitor?
237 : : } // namespace Privacy
238 : : } // namespace Rust
|