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-rib.h"
20 : #include "rust-name-resolution-context.h"
21 :
22 : namespace Rust {
23 : namespace Resolver2_0 {
24 :
25 1536566 : Rib::Definition::Definition (NodeId id, Mode mode, bool enum_variant)
26 1536566 : : enum_variant (enum_variant)
27 : {
28 1536566 : switch (mode)
29 : {
30 49692 : case Mode::SHADOWABLE:
31 49692 : ids_shadowable.push_back (id);
32 49692 : return;
33 1486874 : case Mode::NON_SHADOWABLE:
34 1486874 : ids_non_shadowable.push_back (id);
35 1486874 : return;
36 0 : case Mode::GLOBBED:
37 0 : ids_globbed.push_back (id);
38 0 : return;
39 0 : default:
40 0 : gcc_unreachable ();
41 : }
42 : }
43 :
44 : bool
45 1597933 : Rib::Definition::is_ambiguous () const
46 : {
47 1597933 : if (!ids_shadowable.empty ())
48 : return false;
49 1447549 : else if (!ids_non_shadowable.empty ())
50 1292736 : return ids_non_shadowable.size () > 1;
51 : else
52 154813 : return ids_globbed.size () > 1;
53 : }
54 :
55 : bool
56 320550 : Rib::Definition::is_variant () const
57 : {
58 320550 : return enum_variant;
59 : }
60 :
61 : std::string
62 24 : Rib::Definition::to_string () const
63 : {
64 24 : std::stringstream out;
65 24 : const char *headers[3] = {"(S)[", "] (NS)[", "] (G)["};
66 24 : const std::vector<NodeId> *id_lists[3]
67 24 : = {&ids_shadowable, &ids_non_shadowable, &ids_globbed};
68 96 : for (int i = 0; i < 3; i++)
69 : {
70 72 : out << headers[i];
71 72 : std::string sep;
72 96 : for (auto id : *id_lists[i])
73 : {
74 48 : out << sep << id;
75 24 : sep = ",";
76 : }
77 72 : }
78 24 : out << "]";
79 24 : if (enum_variant)
80 0 : out << "(enum variant)";
81 24 : return out.str ();
82 24 : }
83 :
84 : Rib::Definition
85 49692 : Rib::Definition::Shadowable (NodeId id)
86 : {
87 49692 : return Definition (id, Mode::SHADOWABLE, false);
88 : }
89 :
90 : Rib::Definition
91 1486874 : Rib::Definition::NonShadowable (NodeId id, bool enum_variant)
92 : {
93 1486874 : return Definition (id, Mode::NON_SHADOWABLE, enum_variant);
94 : }
95 :
96 : Rib::Definition
97 0 : Rib::Definition::Globbed (NodeId id)
98 : {
99 0 : return Definition (id, Mode::GLOBBED, false);
100 : }
101 :
102 1229013 : DuplicateNameError::DuplicateNameError (std::string name, NodeId existing)
103 1229013 : : name (name), existing (existing)
104 1229013 : {}
105 :
106 125269040 : Rib::Rib (Kind kind) : kind (kind) {}
107 :
108 0 : Rib::Rib (Kind kind, std::string identifier, NodeId id)
109 0 : : Rib (kind, {{identifier, id}})
110 0 : {}
111 :
112 0 : Rib::Rib (Kind kind, std::unordered_map<std::string, NodeId> to_insert)
113 0 : : kind (kind)
114 : {
115 0 : for (auto &value : to_insert)
116 0 : values.insert ({value.first, Definition::NonShadowable (value.second)});
117 0 : }
118 :
119 : tl::expected<NodeId, DuplicateNameError>
120 1478981 : Rib::insert (std::string name, Definition def)
121 : {
122 1478981 : auto it = values.find (name);
123 1478981 : if (it == values.end ())
124 : {
125 : /* No old value */
126 249469 : values[name] = def;
127 : }
128 1229512 : else if (it->second.ids_non_shadowable.empty ()
129 1229512 : || def.ids_non_shadowable.empty ())
130 : { /* No non-shadowable conflict */
131 2543 : auto ¤t = values[name];
132 2634 : for (auto id : def.ids_non_shadowable)
133 : {
134 182 : if (std::find (current.ids_non_shadowable.cbegin (),
135 : current.ids_non_shadowable.cend (), id)
136 182 : == current.ids_non_shadowable.cend ())
137 91 : current.ids_non_shadowable.push_back (id);
138 : else
139 : // TODO: should this produce an error?
140 0 : return tl::make_unexpected (DuplicateNameError (name, id));
141 : }
142 2951 : for (auto id : def.ids_shadowable)
143 : {
144 4904 : if (std::find (current.ids_shadowable.cbegin (),
145 : current.ids_shadowable.cend (), id)
146 4904 : == current.ids_shadowable.cend ())
147 408 : current.ids_shadowable.push_back (id);
148 : else
149 : // TODO: should this produce an error?
150 4088 : return tl::make_unexpected (DuplicateNameError (name, id));
151 : }
152 499 : for (auto id : def.ids_globbed)
153 : {
154 0 : if (std::find (current.ids_globbed.cbegin (),
155 : current.ids_globbed.cend (), id)
156 0 : == current.ids_globbed.cend ())
157 0 : current.ids_globbed.push_back (id);
158 : else
159 : // TODO: should this produce an error?
160 0 : return tl::make_unexpected (DuplicateNameError (name, id));
161 : }
162 : }
163 : else /* Multiple non-shadowable */
164 : {
165 3680907 : return tl::make_unexpected (
166 4907876 : DuplicateNameError (name, it->second.ids_non_shadowable.back ()));
167 : }
168 :
169 249968 : if (!def.ids_shadowable.empty ())
170 47648 : return def.ids_shadowable.back ();
171 202320 : else if (!def.ids_non_shadowable.empty ())
172 202320 : return def.ids_non_shadowable.back ();
173 0 : rust_assert (!def.ids_globbed.empty ());
174 0 : return def.ids_globbed.back ();
175 : }
176 :
177 : bool
178 4899901 : Rib::insert_globbed (std::string name, const Definition &def)
179 : {
180 4899901 : bool dirty = false;
181 :
182 4899901 : const std::vector<NodeId> *ids_src;
183 :
184 4899901 : if (!def.ids_shadowable.empty ())
185 317336 : ids_src = &def.ids_shadowable;
186 4582565 : else if (!def.ids_non_shadowable.empty ())
187 506158 : ids_src = &def.ids_non_shadowable;
188 : else
189 4076407 : ids_src = &def.ids_globbed;
190 :
191 4899901 : auto it = values.find (name);
192 4899901 : if (it == values.end ())
193 : {
194 79775 : values[name].ids_globbed = *ids_src;
195 79775 : return true;
196 : }
197 :
198 9716766 : for (NodeId id : *ids_src)
199 : {
200 4896640 : auto &ids_dst = it->second.ids_globbed;
201 9793280 : if (std::find (ids_dst.cbegin (), ids_dst.cend (), id) == ids_dst.cend ())
202 : {
203 3144 : dirty = true;
204 3144 : ids_dst.push_back (id);
205 : }
206 : }
207 :
208 4820126 : return dirty;
209 : }
210 :
211 : tl::optional<Rib::Definition>
212 3571081 : Rib::get (const std::string &name)
213 : {
214 3571081 : auto it = values.find (name);
215 :
216 3571081 : if (it == values.end ())
217 3152466 : return tl::nullopt;
218 :
219 418615 : return it->second;
220 : }
221 :
222 : const std::unordered_map<std::string, Rib::Definition> &
223 62694369 : Rib::get_values () const
224 : {
225 62694369 : return values;
226 : }
227 :
228 : } // namespace Resolver2_0
229 : } // namespace Rust
|