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 1490665 : Rib::Definition::Definition (NodeId id, Mode mode, bool enum_variant)
26 1490665 : : enum_variant (enum_variant)
27 : {
28 1490665 : switch (mode)
29 : {
30 47931 : case Mode::SHADOWABLE:
31 47931 : ids_shadowable.push_back (id);
32 47931 : return;
33 1442734 : case Mode::NON_SHADOWABLE:
34 1442734 : ids_non_shadowable.push_back (id);
35 1442734 : 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 1543177 : Rib::Definition::is_ambiguous () const
46 : {
47 1543177 : if (!ids_shadowable.empty ())
48 : return false;
49 1394717 : else if (!ids_non_shadowable.empty ())
50 1246941 : return ids_non_shadowable.size () > 1;
51 : else
52 147776 : return ids_globbed.size () > 1;
53 : }
54 :
55 : bool
56 314825 : Rib::Definition::is_variant () const
57 : {
58 314825 : return enum_variant;
59 : }
60 :
61 : std::string
62 590155775 : Rib::Definition::to_string () const
63 : {
64 590155775 : std::stringstream out;
65 590155775 : const char *headers[3] = {"(S)[", "] (NS)[", "] (G)["};
66 590155775 : const std::vector<NodeId> *id_lists[3]
67 590155775 : = {&ids_shadowable, &ids_non_shadowable, &ids_globbed};
68 2360623100 : for (int i = 0; i < 3; i++)
69 : {
70 1770467325 : out << headers[i];
71 1770467325 : std::string sep;
72 2479459197 : for (auto id : *id_lists[i])
73 : {
74 1417983744 : out << sep << id;
75 708991872 : sep = ",";
76 : }
77 1770467325 : }
78 590155775 : out << "]";
79 590155775 : if (enum_variant)
80 39670 : out << "(enum variant)";
81 590155775 : return out.str ();
82 590155775 : }
83 :
84 : Rib::Definition
85 47931 : Rib::Definition::Shadowable (NodeId id)
86 : {
87 47931 : return Definition (id, Mode::SHADOWABLE, false);
88 : }
89 :
90 : Rib::Definition
91 1442734 : Rib::Definition::NonShadowable (NodeId id, bool enum_variant)
92 : {
93 1442734 : 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 1196938 : DuplicateNameError::DuplicateNameError (std::string name, NodeId existing)
103 1196938 : : name (name), existing (existing)
104 1196938 : {}
105 :
106 123043376 : 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 1433273 : Rib::insert (std::string name, Definition def)
121 : {
122 1433273 : auto it = values.find (name);
123 1433273 : if (it == values.end ())
124 : {
125 : /* No old value */
126 235890 : values[name] = def;
127 : }
128 1197383 : else if (it->second.ids_non_shadowable.empty ()
129 1197383 : || def.ids_non_shadowable.empty ())
130 : { /* No non-shadowable conflict */
131 2381 : auto ¤t = values[name];
132 2447 : for (auto id : def.ids_non_shadowable)
133 : {
134 132 : if (std::find (current.ids_non_shadowable.cbegin (),
135 : current.ids_non_shadowable.cend (), id)
136 132 : == current.ids_non_shadowable.cend ())
137 66 : 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 2760 : for (auto id : def.ids_shadowable)
143 : {
144 4630 : if (std::find (current.ids_shadowable.cbegin (),
145 : current.ids_shadowable.cend (), id)
146 4630 : == current.ids_shadowable.cend ())
147 379 : current.ids_shadowable.push_back (id);
148 : else
149 : // TODO: should this produce an error?
150 3872 : return tl::make_unexpected (DuplicateNameError (name, id));
151 : }
152 445 : 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 3585006 : return tl::make_unexpected (
166 4780008 : DuplicateNameError (name, it->second.ids_non_shadowable.back ()));
167 : }
168 :
169 236335 : if (!def.ids_shadowable.empty ())
170 45995 : return def.ids_shadowable.back ();
171 190340 : else if (!def.ids_non_shadowable.empty ())
172 190340 : 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 4891470 : Rib::insert_globbed (std::string name, const Definition &def)
179 : {
180 4891470 : bool dirty = false;
181 :
182 4891470 : const std::vector<NodeId> *ids_src;
183 :
184 4891470 : if (!def.ids_shadowable.empty ())
185 315031 : ids_src = &def.ids_shadowable;
186 4576439 : else if (!def.ids_non_shadowable.empty ())
187 500540 : ids_src = &def.ids_non_shadowable;
188 : else
189 4075899 : ids_src = &def.ids_globbed;
190 :
191 4891470 : auto it = values.find (name);
192 4891470 : if (it == values.end ())
193 : {
194 77691 : values[name].ids_globbed = *ids_src;
195 77691 : return true;
196 : }
197 :
198 9704066 : for (NodeId id : *ids_src)
199 : {
200 4890287 : auto &ids_dst = it->second.ids_globbed;
201 9780574 : if (std::find (ids_dst.cbegin (), ids_dst.cend (), id) == ids_dst.cend ())
202 : {
203 3116 : dirty = true;
204 3116 : ids_dst.push_back (id);
205 : }
206 : }
207 :
208 4813779 : return dirty;
209 : }
210 :
211 : tl::optional<Rib::Definition>
212 3484112 : Rib::get (const std::string &name)
213 : {
214 3484112 : auto it = values.find (name);
215 :
216 3484112 : if (it == values.end ())
217 3077547 : return tl::nullopt;
218 :
219 406565 : return it->second;
220 : }
221 :
222 : const std::unordered_map<std::string, Rib::Definition> &
223 61580584 : Rib::get_values () const
224 : {
225 61580584 : return values;
226 : }
227 :
228 : } // namespace Resolver2_0
229 : } // namespace Rust
|