Line data Source code
1 : // Copyright (C) 2020-2026 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 3910 : maybe_get_vis_item (std::unique_ptr<HIR::Item> &item)
27 : {
28 3910 : if (item->get_hir_kind () != HIR::Node::VIS_ITEM)
29 : return nullptr;
30 :
31 3910 : return static_cast<HIR::VisItem *> (item.get ());
32 : }
33 :
34 : ReachLevel
35 18694 : ReachabilityVisitor::get_reachability_level (
36 : const HIR::Visibility &item_visibility)
37 : {
38 18694 : return item_visibility.is_public () ? current_level : ReachLevel::Unreachable;
39 : }
40 :
41 : void
42 17061 : ReachabilityVisitor::visit_generic_predicates (
43 : const std::vector<std::unique_ptr<HIR::GenericParam>> &generics,
44 : ReachLevel item_reach)
45 : {
46 17061 : if (item_reach == ReachLevel::Unreachable)
47 : return;
48 :
49 7962 : for (const auto &generic : generics)
50 : {
51 3800 : if (generic->get_kind () == HIR::GenericParam::GenericKind::TYPE)
52 : {
53 3771 : TyTy::BaseType *generic_ty = nullptr;
54 3771 : auto ok = ty_ctx.lookup_type (generic->get_mappings ().get_hirid (),
55 : &generic_ty);
56 3771 : rust_assert (ok);
57 3771 : rust_assert (generic_ty->get_kind () == TyTy::PARAM);
58 :
59 3771 : auto generic_param = static_cast<TyTy::ParamType *> (generic_ty);
60 7847 : for (const auto &bound : generic_param->get_specified_bounds ())
61 : {
62 4076 : const auto trait = bound.get ()->get_hir_trait_ref ();
63 4076 : ctx.update_reachability (trait->get_mappings (), item_reach);
64 : }
65 : }
66 : }
67 : }
68 :
69 : void
70 1189 : ReachabilityVisitor::visit (HIR::Module &mod)
71 : {
72 1189 : auto reach = get_reachability_level (mod.get_visibility ());
73 1189 : reach = ctx.update_reachability (mod.get_mappings (), reach);
74 :
75 5099 : 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 3910 : auto vis_item = maybe_get_vis_item (item);
82 3910 : if (vis_item)
83 3910 : vis_item->accept_vis (*this);
84 : }
85 1189 : }
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 6048 : ReachabilityVisitor::visit (HIR::Function &func)
103 : {
104 6048 : auto fn_reach = get_reachability_level (func.get_visibility ());
105 :
106 6048 : fn_reach = ctx.update_reachability (func.get_mappings (), fn_reach);
107 6048 : visit_generic_predicates (func.get_generic_params (), fn_reach);
108 6048 : }
109 :
110 : void
111 42 : ReachabilityVisitor::visit (HIR::TypeAlias &type_alias)
112 : {
113 42 : auto type_reach = get_reachability_level (type_alias.get_visibility ());
114 :
115 42 : visit_generic_predicates (type_alias.get_generic_params (), type_reach);
116 42 : }
117 :
118 : void
119 1322 : ReachabilityVisitor::visit (HIR::StructStruct &struct_item)
120 : {
121 1322 : auto struct_reach = get_reachability_level (struct_item.get_visibility ());
122 :
123 1322 : struct_reach
124 1322 : = ctx.update_reachability (struct_item.get_mappings (), struct_reach);
125 :
126 1322 : auto old_level = current_level;
127 1322 : current_level = struct_reach;
128 :
129 1322 : visit_generic_predicates (struct_item.get_generic_params (), struct_reach);
130 :
131 1322 : if (struct_reach != ReachLevel::Unreachable)
132 : {
133 558 : 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 1322 : current_level = old_level;
140 1322 : }
141 :
142 : void
143 794 : ReachabilityVisitor::visit (HIR::TupleStruct &)
144 794 : {}
145 :
146 : void
147 478 : ReachabilityVisitor::visit (HIR::Enum &enum_item)
148 : {
149 478 : auto enum_reach = get_reachability_level (enum_item.get_visibility ());
150 :
151 478 : enum_reach = ctx.update_reachability (enum_item.get_mappings (), enum_reach);
152 478 : visit_generic_predicates (enum_item.get_generic_params (), enum_reach);
153 :
154 1614 : for (const auto &variant : enum_item.get_variants ())
155 : {
156 1136 : auto variant_reach
157 1136 : = ctx.update_reachability (variant->get_mappings (), enum_reach);
158 :
159 1136 : switch (variant->get_enum_item_kind ())
160 : {
161 386 : case HIR::EnumItem::Tuple:
162 386 : {
163 : // Should we update the fields only if they are public? Similarly to
164 : // what we do in the ReachabilityVisitor for HIR::TupleStruct?
165 386 : auto tuple_variant
166 386 : = static_cast<HIR::EnumItemTuple *> (variant.get ());
167 795 : for (const auto &field : tuple_variant->get_tuple_fields ())
168 409 : ctx.update_reachability (field.get_mappings (), variant_reach);
169 : break;
170 : }
171 79 : case HIR::EnumItem::Struct:
172 79 : {
173 : // Should we update the fields only if they are public? Similarly to
174 : // what we do in the ReachabilityVisitor for HIR::StructStruct?
175 79 : auto struct_variant
176 79 : = static_cast<HIR::EnumItemStruct *> (variant.get ());
177 209 : for (const auto &field : struct_variant->get_struct_fields ())
178 130 : 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 478 : }
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 393 : ReachabilityVisitor::visit (HIR::ConstantItem &const_item)
201 : {
202 393 : auto reach = get_reachability_level (const_item.get_visibility ());
203 393 : reach = ctx.update_reachability (const_item.get_mappings (), reach);
204 393 : }
205 :
206 : void
207 51 : ReachabilityVisitor::visit (HIR::StaticItem &static_item)
208 : {
209 51 : auto reach = get_reachability_level (static_item.get_visibility ());
210 51 : reach = ctx.update_reachability (static_item.get_mappings (), reach);
211 51 : }
212 :
213 : void
214 3536 : ReachabilityVisitor::visit (HIR::Trait &trait)
215 : {
216 3536 : auto trait_reach = get_reachability_level (trait.get_visibility ());
217 :
218 3536 : trait_reach = ctx.update_reachability (trait.get_mappings (), trait_reach);
219 3536 : visit_generic_predicates (trait.get_generic_params (), trait_reach);
220 3536 : }
221 :
222 : void
223 5538 : ReachabilityVisitor::visit (HIR::ImplBlock &impl)
224 : {
225 5538 : auto impl_reach = get_reachability_level (impl.get_visibility ());
226 :
227 5538 : impl_reach = ctx.update_reachability (impl.get_mappings (), impl_reach);
228 5538 : visit_generic_predicates (impl.get_generic_params (), impl_reach);
229 5538 : }
230 :
231 : void
232 1442 : ReachabilityVisitor::visit (HIR::ExternBlock &)
233 1442 : {}
234 :
235 : // FIXME: How can we visit Blocks in the current configuration? Have a full
236 : // visitor?
237 : } // namespace Privacy
238 : } // namespace Rust
|