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