]> gcc.gnu.org Git - gcc.git/blame - gcc/cp/name-lookup.c
decl.c (register_dtor_fn): Mark cleanup as used.
[gcc.git] / gcc / cp / name-lookup.c
CommitLineData
aed81407
GDR
1/* Definitions for C++ name lookup routines.
2 Copyright (C) 2003 Free Software Foundation, Inc.
3 Contributed by Gabriel Dos Reis <gdr@integrable-solutions.net>
4
ed3cf953 5This file is part of GCC.
aed81407 6
ed3cf953 7GCC is free software; you can redistribute it and/or modify
aed81407
GDR
8it under the terms of the GNU General Public License as published by
9the Free Software Foundation; either version 2, or (at your option)
10any later version.
11
ed3cf953 12GCC is distributed in the hope that it will be useful,
aed81407
GDR
13but WITHOUT ANY WARRANTY; without even the implied warranty of
14MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15GNU General Public License for more details.
16
17You should have received a copy of the GNU General Public License
ed3cf953 18along with GCC; see the file COPYING. If not, write to
aed81407
GDR
19the Free Software Foundation, 59 Temple Place - Suite 330,
20Boston, MA 02111-1307, USA. */
21
22#include "config.h"
23#include "system.h"
24#include "coretypes.h"
25#include "tm.h"
26#include "tree.h"
27#include "cp-tree.h"
28#include "name-lookup.h"
ed3cf953 29#include "timevar.h"
aed81407 30
5e0c54e5
GDR
31/* Compute the chain index of a binding_entry given the HASH value of its
32 name and the total COUNT of chains. COUNT is assumed to be a power
33 of 2. */
34#define ENTRY_INDEX(HASH, COUNT) (((HASH) >> 3) & ((COUNT) - 1))
35
36/* A free list of "binding_entry"s awaiting for re-use. */
7e8f3096 37static GTY((deletable(""))) binding_entry free_binding_entry = NULL;
5e0c54e5
GDR
38
39/* Create a binding_entry object for (NAME, TYPE). */
40static inline binding_entry
41binding_entry_make (tree name, tree type)
42{
43 binding_entry entry;
44
45 if (free_binding_entry)
46 {
47 entry = free_binding_entry;
48 free_binding_entry = entry->chain;
49 }
50 else
51 entry = ggc_alloc (sizeof (struct binding_entry_s));
52
53 entry->name = name;
54 entry->type = type;
7e8f3096 55 entry->chain = NULL;
5e0c54e5
GDR
56
57 return entry;
58}
59
60/* Put ENTRY back on the free list. */
61static inline void
62binding_entry_free (binding_entry entry)
63{
64 entry->chain = free_binding_entry;
65 free_binding_entry = entry;
66}
67
68/* The datatype used to implement the mapping from names to types at
69 a given scope. */
70struct binding_table_s GTY(())
71{
72 /* Array of chains of "binding_entry"s */
73 binding_entry * GTY((length ("%h.chain_count"))) chain;
74
75 /* The number of chains in this table. This is the length of the
7e8f3096 76 the member "chain" considered as an array. */
5e0c54e5
GDR
77 size_t chain_count;
78
79 /* Number of "binding_entry"s in this table. */
80 size_t entry_count;
81};
82
83/* Construct TABLE with an initial CHAIN_COUNT. */
84static inline void
85binding_table_construct (binding_table table, size_t chain_count)
86{
87 table->chain_count = chain_count;
88 table->entry_count = 0;
89 table->chain = ggc_alloc_cleared
90 (table->chain_count * sizeof (binding_entry));
91}
92
93/* Free TABLE by making its entries ready for reuse. */
94void
95binding_table_free (binding_table table)
96{
97 size_t i;
98 if (table == NULL)
99 return;
100
101 for (i = 0; i < table->chain_count; ++i)
102 {
7e8f3096
AP
103 binding_entry temp = table->chain[i];
104 while (temp != NULL)
5e0c54e5 105 {
7e8f3096
AP
106 binding_entry entry = temp;
107 temp = entry->chain;
a1447166 108 entry->chain = NULL;
5e0c54e5
GDR
109 binding_entry_free (entry);
110 }
7e8f3096 111 table->chain[i] = temp;
5e0c54e5
GDR
112 }
113 table->entry_count = 0;
114}
115
116/* Allocate a table with CHAIN_COUNT, assumed to be a power of two. */
117binding_table
118binding_table_new (size_t chain_count)
119{
120 binding_table table = ggc_alloc (sizeof (struct binding_table_s));
7e8f3096 121 table->chain = NULL;
5e0c54e5
GDR
122 binding_table_construct (table, chain_count);
123 return table;
124}
125
126/* Expand TABLE to twice its current chain_count. */
127static void
128binding_table_expand (binding_table table)
129{
130 const size_t old_chain_count = table->chain_count;
131 const size_t old_entry_count = table->entry_count;
132 const size_t new_chain_count = 2 * old_chain_count;
133 binding_entry *old_chains = table->chain;
134 size_t i;
135
136 binding_table_construct (table, new_chain_count);
137 for (i = 0; i < old_chain_count; ++i)
138 {
139 binding_entry entry = old_chains[i];
140 for (; entry != NULL; entry = old_chains[i])
141 {
142 const unsigned int hash = IDENTIFIER_HASH_VALUE (entry->name);
143 const size_t j = ENTRY_INDEX (hash, new_chain_count);
144
145 old_chains[i] = entry->chain;
146 entry->chain = table->chain[j];
147 table->chain[j] = entry;
148 }
149 }
150 table->entry_count = old_entry_count;
151}
152
153/* Insert a binding for NAME to TYPe into TABLE. */
154void
155binding_table_insert (binding_table table, tree name, tree type)
156{
157 const unsigned int hash = IDENTIFIER_HASH_VALUE (name);
158 const size_t i = ENTRY_INDEX (hash, table->chain_count);
159 binding_entry entry = binding_entry_make (name, type);
160
161 entry->chain = table->chain[i];
162 table->chain[i] = entry;
163 ++table->entry_count;
164
165 if (3 * table->chain_count < 5 * table->entry_count)
166 binding_table_expand (table);
167}
168
169/* Return the binding_entry, if any, that maps NAME. */
170binding_entry
171binding_table_find (binding_table table, tree name)
172{
173 const unsigned int hash = IDENTIFIER_HASH_VALUE (name);
174 binding_entry entry = table->chain[ENTRY_INDEX (hash, table->chain_count)];
175
176 while (entry != NULL && entry->name != name)
177 entry = entry->chain;
178
179 return entry;
180}
181
182/* Return the binding_entry, if any, that maps name to an anonymous type. */
183tree
184binding_table_find_anon_type (binding_table table, tree name)
185{
186 const unsigned int hash = IDENTIFIER_HASH_VALUE (name);
187 binding_entry entry = table->chain[ENTRY_INDEX (hash, table->chain_count)];
188
189 while (entry != NULL && TYPE_IDENTIFIER (entry->type) != name)
190 entry = entry->chain;
191
192 return entry ? entry->type : NULL;
193}
194
195/* Return the binding_entry, if any, that has TYPE as target. If NAME
196 is non-null, then set the domain and rehash that entry. */
197binding_entry
198binding_table_reverse_maybe_remap (binding_table table, tree type, tree name)
199{
200 const size_t chain_count = table->chain_count;
201 binding_entry entry = NULL;
202 binding_entry *p = NULL;
203 size_t i;
204
205 for (i = 0; i < chain_count && entry == NULL; ++i)
206 {
207 p = &table->chain[i];
208 while (*p != NULL && entry == NULL)
209 if ((*p)->type == type)
210 entry = *p;
211 else
212 p = &(*p)->chain;
213 }
214
215 if (entry != NULL && name != NULL && entry->name != name)
216 {
217 /* Remove the bucket from the previous chain. */
218 *p = (*p)->chain;
219
220 /* Remap the name type to type. */
221 i = ENTRY_INDEX (IDENTIFIER_HASH_VALUE (name), chain_count);
222 entry->chain = table->chain[i];
223 entry->name = name;
224 table->chain[i] = entry;
225 }
226
227 return entry;
228}
229
230/* Remove from TABLE all entries that map to anonymous enums or
231 class-types. */
232void
233binding_table_remove_anonymous_types (binding_table table)
234{
235 const size_t chain_count = table->chain_count;
236 size_t i;
237
238 for (i = 0; i < chain_count; ++i)
239 {
240 binding_entry *p = &table->chain[i];
241
242 while (*p != NULL)
243 if (ANON_AGGRNAME_P ((*p)->name))
244 {
245 binding_entry e = *p;
246 *p = (*p)->chain;
247 --table->entry_count;
248 binding_entry_free (e);
249 }
250 else
251 p = &(*p)->chain;
252 }
253}
254
255/* Apply PROC -- with DATA -- to all entries in TABLE. */
256void
257binding_table_foreach (binding_table table, bt_foreach_proc proc, void *data)
258{
259 const size_t chain_count = table->chain_count;
260 size_t i;
261
262 for (i = 0; i < chain_count; ++i)
263 {
264 binding_entry entry = table->chain[i];
265 for (; entry != NULL; entry = entry->chain)
266 proc (entry, data);
267 }
268}
269\f
270
aed81407
GDR
271/* A free list of "cxx_binding"s, connected by their PREVIOUS. */
272static GTY((deletable (""))) cxx_binding *free_bindings;
273
274/* (GC)-allocate a binding object with VALUE and TYPE member initialized. */
275cxx_binding *
276cxx_binding_make (tree value, tree type)
277{
278 cxx_binding *binding;
279 if (free_bindings)
280 {
281 binding = free_bindings;
282 free_bindings = binding->previous;
283 }
284 else
7e8f3096 285 binding = ggc_alloc (sizeof (cxx_binding));
aed81407
GDR
286
287 binding->value = value;
288 binding->type = type;
7e8f3096 289 binding->previous = NULL;
aed81407
GDR
290
291 return binding;
292}
293
294/* Put BINDING back on the free list. */
295void
296cxx_binding_free (cxx_binding *binding)
297{
298 binding->previous = free_bindings;
299 free_bindings = binding;
300}
ed3cf953
GDR
301\f
302/* Return (from the stack of) the BINDING, if any, establihsed at SCOPE. */
303
304static inline cxx_binding *
305find_binding (cxx_scope *scope, cxx_binding *binding)
306{
307 timevar_push (TV_NAME_LOOKUP);
308
309 for (; binding != NULL; binding = binding->previous)
310 if (BINDING_SCOPE (binding) == scope)
311 POP_TIMEVAR_AND_RETURN (TV_NAME_LOOKUP, binding);
312
da247ccc 313 POP_TIMEVAR_AND_RETURN (TV_NAME_LOOKUP, (cxx_binding *)0);
ed3cf953
GDR
314}
315
316/* Return the binding for NAME in SCOPE, if any. Otherwise, return NULL. */
317cxx_binding *
318cxx_scope_find_binding_for_name (cxx_scope *scope, tree name)
319{
320 cxx_binding *b = IDENTIFIER_NAMESPACE_BINDINGS (name);
321 if (b)
322 {
323 /* Fold-in case where NAME is used only once. */
324 if (scope == BINDING_SCOPE (b) && b->previous == NULL)
325 return b;
326 return find_binding (scope, b);
327 }
328 return NULL;
329}
330
331/* Always returns a binding for name in scope. If no binding is
332 found, make a new one. */
333
334cxx_binding *
335binding_for_name (cxx_scope *scope, tree name)
336{
337 cxx_binding *result;
338
339 result = cxx_scope_find_binding_for_name (scope, name);
340 if (result)
341 return result;
342 /* Not found, make a new one. */
343 result = cxx_binding_make (NULL, NULL);
344 result->previous = IDENTIFIER_NAMESPACE_BINDINGS (name);
345 BINDING_SCOPE (result) = scope;
346 result->is_local = false;
347 result->value_is_inherited = false;
348 IDENTIFIER_NAMESPACE_BINDINGS (name) = result;
349 return result;
350}
351\f
352/* Namespace-scope manipulation routines. */
353
354/* Return the binding value for name in scope. */
355
356tree
357namespace_binding (tree name, tree scope)
358{
359 cxx_binding *binding;
360
361 if (scope == NULL)
362 scope = global_namespace;
363 scope = ORIGINAL_NAMESPACE (scope);
364 binding = cxx_scope_find_binding_for_name (NAMESPACE_LEVEL (scope), name);
365
366 return binding ? binding->value : NULL_TREE;
367}
368
369/* Set the binding value for name in scope. */
370
371void
372set_namespace_binding (tree name, tree scope, tree val)
373{
374 cxx_binding *b;
375
376 timevar_push (TV_NAME_LOOKUP);
377 if (scope == NULL_TREE)
378 scope = global_namespace;
379 b = binding_for_name (NAMESPACE_LEVEL (scope), name);
380 BINDING_VALUE (b) = val;
381 timevar_pop (TV_NAME_LOOKUP);
382}
383
28ea4c88 384#include "gt-cp-name-lookup.h"
This page took 0.154471 seconds and 5 git commands to generate.