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-visibility-resolver.h"
20 : : #include "rust-ast.h"
21 : : #include "rust-hir.h"
22 : : #include "rust-hir-item.h"
23 : :
24 : : namespace Rust {
25 : : namespace Privacy {
26 : :
27 : 3359 : VisibilityResolver::VisibilityResolver (Analysis::Mappings &mappings,
28 : 3359 : Resolver::Resolver &resolver)
29 : 3359 : : mappings (mappings), resolver (resolver)
30 : 3359 : {}
31 : :
32 : : void
33 : 3359 : VisibilityResolver::go (HIR::Crate &crate)
34 : : {
35 : 3359 : mappings.insert_visibility (crate.get_mappings ().get_nodeid (),
36 : : ModuleVisibility::create_public ());
37 : :
38 : 3359 : current_module = crate.get_mappings ().get_defid ();
39 : :
40 : 16235 : for (auto &item : crate.get_items ())
41 : : {
42 : 12876 : if (item->get_hir_kind () == HIR::Node::VIS_ITEM)
43 : : {
44 : 12876 : auto vis_item = static_cast<HIR::VisItem *> (item.get ());
45 : 12876 : vis_item->accept_vis (*this);
46 : : }
47 : : }
48 : 3359 : }
49 : :
50 : : bool
51 : 8 : VisibilityResolver::resolve_module_path (const HIR::SimplePath &restriction,
52 : : DefId &id)
53 : : {
54 : : // We need, from the restriction, to figure out the actual Module it
55 : : // belongs to.
56 : :
57 : 8 : NodeId ast_node_id = restriction.get_mappings ().get_nodeid ();
58 : :
59 : 8 : auto invalid_path
60 : : = Error (restriction.get_locus (),
61 : 8 : "cannot use non-module path as privacy restrictor");
62 : :
63 : 8 : NodeId ref_node_id = UNKNOWN_NODEID;
64 : 8 : if (!resolver.lookup_resolved_name (ast_node_id, &ref_node_id))
65 : : {
66 : 0 : invalid_path.emit ();
67 : 0 : return false;
68 : : }
69 : : // FIXME: Add a hint here if we can find the path in another scope, such as
70 : : // a type or something else
71 : : // TODO: For the hint, can we point to the original item's definition if
72 : : // present?
73 : :
74 : 8 : HirId ref;
75 : 8 : rust_assert (mappings.lookup_node_to_hir (ref_node_id, &ref));
76 : :
77 : 8 : auto crate = mappings.get_ast_crate (mappings.get_current_crate ());
78 : :
79 : : // we may be dealing with pub(crate)
80 : 8 : if (ref_node_id == crate.get_node_id ())
81 : : // FIXME: What do we do here? There isn't a DefId for the Crate, so can we
82 : : // actually do anything?
83 : : // We basically want to return true always but just when exporting export
84 : : // these items as private?
85 : : return true;
86 : :
87 : 7 : auto module = mappings.lookup_module (ref);
88 : 7 : if (!module)
89 : : {
90 : 0 : invalid_path.emit ();
91 : 0 : return false;
92 : : }
93 : :
94 : : // Fill in the resolved `DefId`
95 : 7 : id = module->get_mappings ().get_defid ();
96 : :
97 : 7 : return true;
98 : 8 : }
99 : :
100 : : bool
101 : 12993 : VisibilityResolver::resolve_visibility (const HIR::Visibility &visibility,
102 : : ModuleVisibility &to_resolve)
103 : : {
104 : 12993 : switch (visibility.get_vis_type ())
105 : : {
106 : 9425 : case HIR::Visibility::PRIVATE:
107 : 9425 : to_resolve = ModuleVisibility::create_restricted (current_module);
108 : 9425 : return true;
109 : 3560 : case HIR::Visibility::PUBLIC:
110 : 3560 : to_resolve = ModuleVisibility::create_public ();
111 : 3560 : return true;
112 : 8 : case HIR::Visibility::RESTRICTED: {
113 : : // FIXME: We also need to handle 2015 vs 2018 edition conflicts
114 : 8 : auto id = UNKNOWN_DEFID;
115 : 8 : auto result = resolve_module_path (visibility.get_path (), id);
116 : 8 : to_resolve = ModuleVisibility::create_restricted (id);
117 : 8 : return result;
118 : : }
119 : 0 : default:
120 : 0 : rust_unreachable ();
121 : : return false;
122 : : }
123 : : }
124 : :
125 : : void
126 : 10832 : VisibilityResolver::resolve_and_update (const HIR::VisItem *item)
127 : : {
128 : 10832 : ModuleVisibility module_vis;
129 : 10832 : if (!resolve_visibility (item->get_visibility (), module_vis))
130 : 0 : return; // we will already have emitted errors
131 : :
132 : 10832 : mappings.insert_visibility (item->get_mappings ().get_nodeid (), module_vis);
133 : : }
134 : :
135 : : void
136 : 432 : VisibilityResolver::visit (HIR::Module &mod)
137 : : {
138 : 432 : auto old_module = current_module;
139 : 432 : current_module = mod.get_mappings ().get_defid ();
140 : :
141 : 980 : for (auto &item : mod.get_items ())
142 : : {
143 : 548 : if (item->get_hir_kind () == HIR::Node::VIS_ITEM)
144 : : {
145 : 548 : auto vis_item = static_cast<HIR::VisItem *> (item.get ());
146 : 548 : vis_item->accept_vis (*this);
147 : : }
148 : : }
149 : :
150 : 432 : current_module = old_module;
151 : 432 : }
152 : :
153 : : void
154 : 0 : VisibilityResolver::visit (HIR::ExternCrate &)
155 : 0 : {}
156 : :
157 : : void
158 : 0 : VisibilityResolver::visit (HIR::UseDeclaration &)
159 : 0 : {}
160 : :
161 : : void
162 : 8158 : VisibilityResolver::visit (HIR::Function &func)
163 : : {
164 : 8158 : resolve_and_update (&func);
165 : 8158 : }
166 : :
167 : : void
168 : 740 : VisibilityResolver::visit (HIR::TypeAlias &type_alias)
169 : : {
170 : 740 : resolve_and_update (&type_alias);
171 : 740 : }
172 : :
173 : : void
174 : 830 : VisibilityResolver::visit (HIR::StructStruct &struct_item)
175 : : {
176 : 830 : resolve_and_update (&struct_item);
177 : 830 : }
178 : :
179 : : void
180 : 655 : VisibilityResolver::visit (HIR::TupleStruct &tuple_struct)
181 : : {
182 : 655 : resolve_and_update (&tuple_struct);
183 : 655 : }
184 : :
185 : : void
186 : 157 : VisibilityResolver::visit (HIR::Enum &enum_item)
187 : : {
188 : 157 : ModuleVisibility vis;
189 : 157 : if (!resolve_visibility (enum_item.get_visibility (), vis))
190 : 0 : return;
191 : :
192 : 157 : mappings.insert_visibility (enum_item.get_mappings ().get_nodeid (), vis);
193 : 538 : for (auto &variant : enum_item.get_variants ())
194 : 381 : mappings.insert_visibility (variant->get_mappings ().get_nodeid (), vis);
195 : : }
196 : :
197 : : void
198 : 89 : VisibilityResolver::visit (HIR::Union &)
199 : 89 : {}
200 : :
201 : : void
202 : 409 : VisibilityResolver::visit (HIR::ConstantItem &const_item)
203 : : {
204 : 409 : resolve_and_update (&const_item);
205 : 409 : }
206 : :
207 : : void
208 : 40 : VisibilityResolver::visit (HIR::StaticItem &static_item)
209 : : {
210 : 40 : resolve_and_update (&static_item);
211 : 40 : }
212 : :
213 : : void
214 : 2004 : VisibilityResolver::visit (HIR::Trait &trait)
215 : : {
216 : 2004 : ModuleVisibility vis;
217 : 2004 : if (!resolve_visibility (trait.get_visibility (), vis))
218 : 0 : return;
219 : :
220 : 2004 : mappings.insert_visibility (trait.get_mappings ().get_nodeid (), vis);
221 : 3476 : for (auto &item : trait.get_trait_items ())
222 : 1472 : mappings.insert_visibility (item->get_mappings ().get_nodeid (), vis);
223 : : }
224 : :
225 : : void
226 : 2974 : VisibilityResolver::visit (HIR::ImplBlock &impl)
227 : : {
228 : 7043 : for (auto &item : impl.get_impl_items ())
229 : : {
230 : 4069 : HIR::VisItem *vis_item;
231 : 4069 : switch (item->get_impl_item_type ())
232 : : {
233 : 3323 : case HIR::ImplItem::FUNCTION:
234 : 3323 : vis_item = static_cast<HIR::Function *> (item.get ());
235 : : break;
236 : 708 : case HIR::ImplItem::TYPE_ALIAS:
237 : 708 : vis_item = static_cast<HIR::TypeAlias *> (item.get ());
238 : : break;
239 : 38 : case HIR::ImplItem::CONSTANT:
240 : 38 : vis_item = static_cast<HIR::ConstantItem *> (item.get ());
241 : : break;
242 : 0 : default:
243 : 0 : rust_unreachable ();
244 : 4069 : return;
245 : : }
246 : 4069 : vis_item->accept_vis (*this);
247 : : }
248 : 2974 : }
249 : :
250 : : void
251 : 1005 : VisibilityResolver::visit (HIR::ExternBlock &)
252 : 1005 : {}
253 : :
254 : : } // namespace Privacy
255 : : } // namespace Rust
|