Subversion Repositories tendra.SVN

Rev

Rev 5 | Details | Compare with Previous | Last modification | View Log | RSS feed

Rev Author Line No. Line
2 7u83 1
/*
6 7u83 2
 * Copyright (c) 2002-2006 The TenDRA Project <http://www.tendra.org/>.
3
 * All rights reserved.
4
 *
5
 * Redistribution and use in source and binary forms, with or without
6
 * modification, are permitted provided that the following conditions are met:
7
 *
8
 * 1. Redistributions of source code must retain the above copyright notice,
9
 *    this list of conditions and the following disclaimer.
10
 * 2. Redistributions in binary form must reproduce the above copyright notice,
11
 *    this list of conditions and the following disclaimer in the documentation
12
 *    and/or other materials provided with the distribution.
13
 * 3. Neither the name of The TenDRA Project nor the names of its contributors
14
 *    may be used to endorse or promote products derived from this software
15
 *    without specific, prior written permission.
16
 *
17
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ``AS
18
 * IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
19
 * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
20
 * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT HOLDERS OR
21
 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
22
 * EXEMPLARY OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
23
 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
24
 * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
25
 * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
26
 * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
27
 * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
28
 *
29
 * $Id$
30
 */
31
/*
2 7u83 32
    		 Crown Copyright (c) 1997, 1998
6 7u83 33
 
2 7u83 34
    This TenDRA(r) Computer Program is subject to Copyright
35
    owned by the United Kingdom Secretary of State for Defence
36
    acting through the Defence Evaluation and Research Agency
37
    (DERA).  It is made available to Recipients with a
38
    royalty-free licence for its use, reproduction, transfer
39
    to other parties and amendment for any purpose not excluding
40
    product development provided that any such use et cetera
41
    shall be deemed to be acceptance of the following conditions:-
6 7u83 42
 
2 7u83 43
        (1) Its Recipients shall ensure that this Notice is
44
        reproduced upon any copies or amended versions of it;
6 7u83 45
 
2 7u83 46
        (2) Any amended version of it shall be clearly marked to
47
        show both the nature of and the organisation responsible
48
        for the relevant amendment or amendments;
6 7u83 49
 
2 7u83 50
        (3) Its onward transfer from a recipient to another
51
        party shall be deemed to be that party's acceptance of
52
        these conditions;
6 7u83 53
 
2 7u83 54
        (4) DERA gives no warranty or assurance as to its
55
        quality or suitability for any purpose and DERA accepts
56
        no liability whatsoever in relation to any use to which
57
        it may be put.
58
*/
59
 
60
 
61
#include "config.h"
62
#include "c_types.h"
63
#include "ctype_ops.h"
64
#include "graph_ops.h"
65
#include "hashid_ops.h"
66
#include "id_ops.h"
67
#include "member_ops.h"
68
#include "nspace_ops.h"
69
#include "type_ops.h"
70
#include "error.h"
71
#include "catalog.h"
72
#include "option.h"
73
#include "access.h"
74
#include "class.h"
75
#include "declare.h"
76
#include "derive.h"
77
#include "dump.h"
78
#include "hash.h"
79
#include "identifier.h"
80
#include "instance.h"
81
#include "label.h"
82
#include "namespace.h"
83
#include "parse.h"
84
#include "predict.h"
85
#include "print.h"
86
#include "redeclare.h"
87
#include "syntax.h"
88
#include "tokdef.h"
89
#include "ustring.h"
90
#include "variable.h"
91
 
92
 
93
/*
94
    CURRENT NAMESPACE LISTS
95
 
96
    These variables give the current namespace (the one which is currently
97
    being defined) and the stack of all enclosing namespaces.  Another stack
98
    of namespaces, which will be a superset of the first, gives the list
99
    of locations to be searched during name look-up.
100
*/
101
 
6 7u83 102
NAMESPACE crt_namespace = NULL_nspace;
103
NAMESPACE last_namespace = NULL_nspace;
104
NAMESPACE qual_namespace = NULL_nspace;
105
STACK(NAMESPACE) namespace_stack = NULL_stack(NAMESPACE);
106
STACK(NAMESPACE) crt_nspace_stack = NULL_stack(NAMESPACE);
107
STACK(NAMESPACE) local_nspace_stack = NULL_stack(NAMESPACE);
2 7u83 108
 
109
 
110
/*
111
    STANDARD NAMESPACES
112
 
113
    These variables give the various standard namespaces, including the
114
    global namespace and the external token namespace.  In addition a
115
    dynamic record of the smallest named namespace enclosing the current
116
    namespace and the smallest named or block namespace (or, if the
117
    proto_scope option is true, function prototype namespace) enclosing
118
    the current namespace are maintained in nonblock_namespace and
119
    nonclass_namespace respectively.
120
*/
121
 
6 7u83 122
NAMESPACE global_namespace = NULL_nspace;
123
NAMESPACE token_namespace = NULL_nspace;
124
NAMESPACE c_namespace = NULL_nspace;
125
NAMESPACE nonblock_namespace = NULL_nspace;
126
NAMESPACE nonclass_namespace = NULL_nspace;
127
static NAMESPACE scope_namespace = NULL_nspace;
2 7u83 128
 
129
 
130
/*
131
    STANDARD NAMESPACE IDENTIFIERS
132
 
133
    The identifier local_namespace_id is used as the name for all unnamed
134
    namespaces defined within the current translation unit.
135
*/
136
 
6 7u83 137
static IDENTIFIER local_namespace_id = NULL_id;
2 7u83 138
 
139
 
140
/*
141
    NAME LOOK-UP CACHE FLAG
142
 
143
    This flag is set to indicate that name look-up should be cached
144
    whenever possible.  It is switched off temporarily in field selectors
145
    as an optimisation.
146
*/
147
 
6 7u83 148
int cache_lookup = 1;
149
int old_cache_lookup = 1;
2 7u83 150
 
151
 
152
/*
153
    CREATE A STANDARD NAMESPACE
154
 
155
    This routine creates a global namespace of size sz with a dummy name
156
    given by s.
157
*/
158
 
6 7u83 159
NAMESPACE
160
make_global_nspace(CONST char *s, int sz)
2 7u83 161
{
6 7u83 162
	IDENTIFIER id;
163
	string u = ustrlit(s);
164
	NAMESPACE ns = NULL_nspace;
165
	DECL_SPEC ds = (dspec_defn | dspec_extern);
166
	HASHID nm = lookup_name(u, hash(u), 1, lex_identifier);
167
	MAKE_id_nspace_name(nm, ds, NULL_nspace, crt_loc, ns, id);
168
	ns = make_namespace(id, nspace_global_tag, sz);
169
	COPY_nspace(id_nspace_name_defn(id), ns);
170
	return (ns);
2 7u83 171
}
172
 
173
 
174
/*
175
    INITIALISE STANDARD NAMESPACES
176
 
177
    This routine initialises the standard namespaces above.
178
*/
179
 
6 7u83 180
void
181
init_namespace(void)
2 7u83 182
{
6 7u83 183
	string s = ustrlit("<local>");
184
	HASHID nm = lookup_name(s, hash(s), 1, lex_identifier);
185
	local_namespace_id = DEREF_id(hashid_id(nm));
186
	global_namespace = make_global_nspace("<global>", 50);
2 7u83 187
#if LANGUAGE_CPP
6 7u83 188
	c_namespace = make_global_nspace("<c>", 50);
2 7u83 189
#endif
6 7u83 190
	token_namespace = make_global_nspace("<token>", 50);
191
	scope_namespace = make_global_nspace("<scope>", 50);
192
	last_namespace = global_namespace;
193
	old_cache_lookup = cache_lookup;
194
	return;
2 7u83 195
}
196
 
197
 
198
/*
199
    DOES ONE NAMESPACE CONTAIN ANOTHER?
200
 
201
    This routine checks whether the namespace ns contains the definition
202
    of the namespace pns.
203
*/
204
 
6 7u83 205
int
206
is_subnspace(NAMESPACE ns, NAMESPACE pns)
2 7u83 207
{
6 7u83 208
	if (EQ_nspace(ns, pns)) {
209
		return (1);
210
	}
211
	while (!IS_NULL_nspace(pns)) {
212
		pns = DEREF_nspace(nspace_parent(pns));
213
		if (EQ_nspace(ns, pns)) {
214
			return (1);
215
		}
216
	}
217
	return (0);
2 7u83 218
}
219
 
220
 
221
/*
222
    FIND THE JOIN OF TWO NAMESPACES
223
 
224
    This routine finds the join of the namespaces ns and nt, that is to
225
    say the smallest namespace which contains both ns and nt.  A using
226
    directive for nt in ns causes the members of nt to be treated as
227
    members of the join namespace for the purposes of unqualified name
228
    look-up.
229
*/
230
 
6 7u83 231
static NAMESPACE
232
join_namespace(NAMESPACE ns, NAMESPACE nt)
2 7u83 233
{
6 7u83 234
	while (!EQ_nspace(ns, nt)) {
235
		if (IS_NULL_nspace(ns)) {
236
			return (NULL_nspace);
237
		}
238
		if (IS_NULL_nspace(nt)) {
239
			return (NULL_nspace);
240
		}
241
		if (is_subnspace(ns, nt)) {
242
			return (ns);
243
		}
244
		if (is_subnspace(nt, ns)) {
245
			return (nt);
246
		}
247
		ns = DEREF_nspace(nspace_parent(ns));
248
		nt = DEREF_nspace(nspace_parent(nt));
249
	}
250
	return (ns);
2 7u83 251
}
252
 
253
 
254
/*
255
    UNCACHE A NAMESPACE
256
 
257
    This routine clears the cached name look-ups for all the names
258
    accessible from the namespace ns.
259
*/
260
 
6 7u83 261
void
262
uncache_namespace(NAMESPACE ns, int add)
2 7u83 263
{
6 7u83 264
	if (!IS_NULL_nspace(ns) && cache_lookup) {
265
		MEMBER mem;
266
		LIST(NAMESPACE) uns;
2 7u83 267
 
6 7u83 268
		/* Clear cache fields for all members */
269
		if (IS_nspace_named_etc(ns)) {
270
			mem = DEREF_member(nspace_named_etc_first(ns));
271
		} else {
272
			mem = DEREF_member(nspace_last(ns));
273
		}
274
		while (!IS_NULL_member(mem)) {
275
			IDENTIFIER id = DEREF_id(member_id(mem));
276
			if (!IS_NULL_id(id)) {
277
				HASHID nm = DEREF_hashid(id_name(id));
278
				if (!add) {
279
					id = NULL_id;
280
				}
281
				COPY_id(hashid_cache(nm), id);
282
			}
283
			mem = DEREF_member(member_next(mem));
284
		}
2 7u83 285
 
6 7u83 286
		/* Recursively clear all used namespaces */
287
		uns = DEREF_list(nspace_use(ns));
288
		if (!IS_NULL_list(uns)) {
289
			LIST(NAMESPACE) lns = uns;
290
			COPY_list(nspace_use(ns), NULL_list(NAMESPACE));
291
			while (!IS_NULL_list(lns)) {
292
				NAMESPACE pns = DEREF_nspace(HEAD_list(lns));
293
				uncache_namespace(pns, 0);
294
				lns = TAIL_list(lns);
295
			}
296
			COPY_list(nspace_use(ns), uns);
297
		}
2 7u83 298
	}
6 7u83 299
	return;
2 7u83 300
}
301
 
302
 
303
/*
304
    ADD A NAMESPACE TO THE LOOK-UP LIST
305
 
306
    This routine adds the namespace ns to the look-up namespace list.  Note
307
    that this is automatically called by push_namespace.
308
*/
309
 
6 7u83 310
void
311
add_namespace(NAMESPACE ns)
2 7u83 312
{
6 7u83 313
	PUSH_nspace(ns, namespace_stack);
314
	uncache_namespace(ns, 1);
315
	return;
2 7u83 316
}
317
 
318
 
319
/*
320
    REMOVE A NAMESPACE FROM THE LOOK-UP LIST
321
 
322
    This routine removes the top namespace from the look-up namespace list.
323
    Note that this is automatically called by pop_namespace.
324
*/
325
 
6 7u83 326
void
327
remove_namespace(void)
2 7u83 328
{
6 7u83 329
	NAMESPACE ns;
330
	POP_nspace(ns, namespace_stack);
331
	uncache_namespace(ns, 0);
332
	return;
2 7u83 333
}
334
 
335
 
336
/*
337
    PUSH A NAMESPACE
338
 
339
    This routine pushes the namespace ns onto the namespace stack.
340
*/
341
 
6 7u83 342
void
343
store_namespace(NAMESPACE ns)
2 7u83 344
{
6 7u83 345
	NAMESPACE cns = crt_namespace;
346
	switch (TAG_nspace(ns)) {
347
	case nspace_named_tag:
348
	case nspace_unnamed_tag:
349
	case nspace_global_tag:
350
		/* Record named namespaces */
351
		nonblock_namespace = ns;
352
		nonclass_namespace = ns;
353
		break;
354
	case nspace_param_tag:
355
		/* Deal with function prototype scopes */
356
		if (option(OPT_proto_scope)) {
357
			nonclass_namespace = ns;
358
		}
359
		break;
360
	case nspace_block_tag:
361
		/* A block is a non-class namespace */
362
		nonclass_namespace = ns;
363
		break;
2 7u83 364
	}
6 7u83 365
	COPY_nspace(nspace_parent(ns), cns);
366
	PUSH_nspace(cns, crt_nspace_stack);
367
	crt_namespace = ns;
368
	return;
2 7u83 369
}
370
 
371
 
372
/*
373
    POP A NAMESPACE
374
 
375
    This routine removes a namespace from the namespace stack.
376
*/
377
 
6 7u83 378
NAMESPACE
379
restore_namespace(void)
2 7u83 380
{
6 7u83 381
	NAMESPACE ns = crt_namespace;
382
	int fb = EQ_nspace(ns, nonblock_namespace);
383
	int fc = EQ_nspace(ns, nonclass_namespace);
384
	int fa = (fb || fc);
385
	if (fa) {
386
		/* Check for enclosing namespaces */
387
		LIST(NAMESPACE) lns = LIST_stack(crt_nspace_stack);
388
		while (fa && !IS_NULL_list(lns)) {
389
			NAMESPACE pns = DEREF_nspace(HEAD_list(lns));
390
			switch (TAG_nspace(pns)) {
391
			case nspace_named_tag:
392
			case nspace_unnamed_tag:
393
			case nspace_global_tag:
394
				if (fb) {
395
					/* Non-block namespace found */
396
					nonblock_namespace = pns;
397
					fa = fc;
398
					fb = 0;
399
				}
400
				goto nonclass_namespace_lab;
401
			case nspace_param_tag:
402
				/* Deal with function prototype scopes */
403
				if (!option(OPT_proto_scope)) {
404
					break;
405
				}
406
				goto nonclass_namespace_lab;
407
			case nspace_block_tag:
408
nonclass_namespace_lab:
409
				if (fc) {
410
					/* Non-class namespace found */
411
					nonclass_namespace = pns;
412
					fa = fb;
413
					fc = 0;
414
				}
415
				break;
416
			}
417
			lns = TAIL_list(lns);
2 7u83 418
		}
419
	}
6 7u83 420
	POP_nspace(crt_namespace, crt_nspace_stack);
421
	return (ns);
2 7u83 422
}
423
 
424
 
425
/*
426
    SET CURRENT NAMESPACE
427
 
428
    This routine makes the namespace ns into the current namespace, pushing
429
    the previous namespace onto the stack.
430
*/
431
 
6 7u83 432
void
433
push_namespace(NAMESPACE ns)
2 7u83 434
{
6 7u83 435
	store_namespace(ns);
436
	add_namespace(ns);
437
	return;
2 7u83 438
}
439
 
440
 
441
/*
442
    RESTORE PREVIOUS NAMESPACE
443
 
444
    This routine restores the current namespace to its previous value by
445
    popping it from the stack.  It returns the removed namespace.
446
*/
447
 
6 7u83 448
NAMESPACE
449
pop_namespace(void)
2 7u83 450
{
6 7u83 451
	NAMESPACE ns = restore_namespace();
452
	remove_namespace();
453
	return (ns);
2 7u83 454
}
455
 
456
 
457
/*
458
    RECALCULATE NAMESPACES
459
 
460
    This routine forces the recalculation of nonblock_namespace and
461
    nonclass_namespace by pushing and immediately popping the global
462
    namespace.
463
*/
464
 
6 7u83 465
void
466
update_namespace(void)
2 7u83 467
{
6 7u83 468
	NAMESPACE ns = global_namespace;
469
	if (!IS_NULL_nspace(ns)) {
470
		store_namespace(ns);
471
		IGNORE restore_namespace();
472
	}
473
	return;
2 7u83 474
}
475
 
476
 
477
/*
478
    CREATE A NAMESPACE
479
 
480
    This routine creates a namespace named id of type tag.  If tag is
481
    indicates a small namespace then sz will be zero.  Otherwise sz gives
482
    the size of hash table to be created.
483
*/
484
 
6 7u83 485
NAMESPACE
486
make_namespace(IDENTIFIER id, unsigned tag, int sz)
2 7u83 487
{
6 7u83 488
	NAMESPACE ns;
489
	NAMESPACE pns;
490
	if (!IS_NULL_id(id)) {
491
		pns = DEREF_nspace(id_parent(id));
492
	} else {
493
		pns = crt_namespace;
494
	}
495
	if (sz == 0) {
496
		/* Small namespace */
497
		MAKE_nspace_block_etc(tag, id, pns, ns);
498
	} else {
499
		/* Large namespace */
500
		PTR(MEMBER) ptr;
501
		SIZE(MEMBER) psz;
502
		unsigned long i, n = (unsigned long)sz;
2 7u83 503
 
6 7u83 504
		/* Allocate namespace hash table */
505
		psz = SCALE(SIZE_member, n);
506
		ptr = MAKE_ptr(psz);
507
		MAKE_nspace_named_etc(tag, id, pns, n, ptr, ns);
2 7u83 508
 
6 7u83 509
		/* Initialise hash table entries */
510
		for (i = 0; i < n; i++) {
511
			COPY_member(ptr, NULL_member);
512
			ptr = STEP_ptr(ptr, SIZE_member);
513
		}
2 7u83 514
	}
6 7u83 515
	return (ns);
2 7u83 516
}
517
 
518
 
519
/*
520
    USE A NAMESPACE
521
 
522
    This routine creates a using directive for the namespace ns in
523
    the namespace cns.  nt gives the join of cns and ns.  The routine
524
    returns zero to indicate that ns has already been used from cns.
525
*/
526
 
6 7u83 527
int
528
use_namespace(NAMESPACE ns, NAMESPACE cns, NAMESPACE nt)
2 7u83 529
{
6 7u83 530
	if (!EQ_nspace(cns, ns)) {
531
		LIST(NAMESPACE) p = DEREF_list(nspace_use(cns));
532
		LIST(NAMESPACE) r = DEREF_list(nspace_join(cns));
533
		LIST(NAMESPACE) q = p;
534
		while (!IS_NULL_list(q)) {
535
			NAMESPACE qns = DEREF_nspace(HEAD_list(q));
536
			if (EQ_nspace(qns, ns)) {
537
				return (0);
538
			}
539
			q = TAIL_list(q);
540
		}
541
		CONS_nspace(nt, r, r);
542
		COPY_list(nspace_join(cns), r);
543
		CONS_nspace(ns, p, p);
544
		COPY_list(nspace_use(cns), p);
545
		return (1);
2 7u83 546
	}
6 7u83 547
	return (0);
2 7u83 548
}
549
 
550
 
551
/*
552
    LIST OF JOIN NAMESPACES
553
 
554
    During unqualified name look-up any using-directives are treated as
555
    injecting the names from the used namespace into the join on the
556
    used and the using namespaces.  This is implemented by injecting a
557
    dummy using-directive into the join namespace.  This list is used
558
    to keep track of all the join namespaces which have using-directives
559
    injected in this way.
560
*/
561
 
6 7u83 562
static LIST(NAMESPACE) join_nspaces = NULL_list(NAMESPACE);
2 7u83 563
 
564
 
565
/*
566
    CLEAR LIST OF JOIN NAMESPACES
567
 
568
    This routine removes any dummy using-directives from the list of join
569
    namespaces above.
570
*/
571
 
6 7u83 572
static void
573
clear_join_nspaces(void)
2 7u83 574
{
6 7u83 575
	LIST(NAMESPACE) lns = join_nspaces;
576
	while (!IS_NULL_list(lns)) {
577
		NAMESPACE ns;
578
		NAMESPACE dns;
579
		LIST(NAMESPACE) p;
580
		DESTROY_CONS_nspace(destroy, ns, lns, lns);
581
		p = DEREF_list(nspace_use(ns));
582
		if (!IS_NULL_list(p)) {
583
			DESTROY_CONS_nspace(destroy, dns, p, p);
584
			UNUSED(dns);
585
			COPY_list(nspace_use(ns), p);
586
		}
587
		p = DEREF_list(nspace_join(ns));
588
		if (!IS_NULL_list(p)) {
589
			DESTROY_CONS_nspace(destroy, dns, p, p);
590
			UNUSED(dns);
591
			COPY_list(nspace_join(ns), p);
592
		}
2 7u83 593
	}
6 7u83 594
	join_nspaces = NULL_list(NAMESPACE);
595
	return;
2 7u83 596
}
597
 
598
 
599
/*
600
    BEGIN A NAMESPACE DEFINITION
601
 
602
    This routine begins the definition of a namespace named id (or an
603
    anonymous namespace if anon is true).  Note that there may be multiple
604
    definitions of a namespace, the effect of the later definitions being
605
    to add elements to the existing namespace.  Only original namespace
606
    names, and not namespace aliases, can be used in these namespace
607
    extensions.
608
*/
609
 
6 7u83 610
void
611
begin_namespace(IDENTIFIER id, int anon)
2 7u83 612
{
6 7u83 613
	HASHID nm;
614
	MEMBER mem;
615
	IDENTIFIER old_id;
616
	NAMESPACE ns = NULL_nspace;
617
	NAMESPACE cns = crt_namespace;
618
	unsigned tag = nspace_named_tag;
2 7u83 619
 
6 7u83 620
	/* Find name for anonymous namespaces */
621
	if (anon) {
622
		id = local_namespace_id;
623
		tag = nspace_unnamed_tag;
624
	}
625
	nm = DEREF_hashid(id_name(id));
2 7u83 626
 
6 7u83 627
	/* Can only occur in namespace scope */
628
	if (in_function_defn || in_class_defn) {
629
		report(crt_loc, ERR_dcl_nspace_scope());
630
	}
2 7u83 631
 
6 7u83 632
	/* Look up namespace name */
633
	mem = search_member(cns, nm, 1);
634
	old_id = DEREF_id(member_id(mem));
635
	if (!IS_NULL_id(old_id)) {
636
		/* Check for redeclarations */
637
		old_id = redecl_inherit(old_id, qual_none, in_class_defn, 2);
638
		switch (TAG_id(old_id)) {
639
		case id_nspace_name_tag:
640
			/* Previously defined namespace */
641
			ns = DEREF_nspace(id_nspace_name_defn(old_id));
642
			break;
643
		case id_nspace_alias_tag: {
644
			/* Previously defined namespace alias */
645
			IDENTIFIER ns_id;
646
			ns = DEREF_nspace(id_nspace_alias_defn(old_id));
647
			ns_id = DEREF_id(nspace_name(ns));
648
			if (!IS_id_nspace_name(ns_id)) {
649
				/* Alias for class namespace */
650
				ns = NULL_nspace;
651
				goto default_lab;
652
			}
653
			report(crt_loc, ERR_dcl_nspace_def_orig(ns_id, old_id));
654
			break;
2 7u83 655
		}
6 7u83 656
		default:
657
default_lab: {
658
		     /* Other previously defined identifier */
659
		     PTR(LOCATION) loc = id_loc(old_id);
660
		     report(crt_loc, ERR_basic_odr_decl(old_id, loc));
661
		     break;
662
	     }
663
		}
2 7u83 664
	}
665
 
6 7u83 666
	/* Construct the namespace if necessary */
667
	if (IS_NULL_nspace(ns)) {
668
		DECL_SPEC ds = (dspec_defn | dspec_extern);
669
		MAKE_id_nspace_name(nm, ds, cns, decl_loc, ns, id);
670
		ns = make_namespace(id, tag, 50);
671
		COPY_nspace(id_nspace_name_defn(id), ns);
672
		set_member(mem, id);
673
		if (anon) {
674
			/* Anonymous namespaces are implicitly used */
675
			IGNORE use_namespace(ns, cns, cns);
676
			if (do_dump) {
677
				dump_using(ns, cns, &decl_loc);
678
			}
679
		}
2 7u83 680
	}
681
 
6 7u83 682
	/* Adjust the current namespace */
683
	if (do_dump) {
684
		dump_declare(id, &decl_loc, 1);
685
	}
686
	push_namespace(ns);
687
	cns = DEREF_nspace(id_parent(id));
688
	COPY_nspace(nspace_parent(ns), cns);
689
	return;
2 7u83 690
}
691
 
692
 
693
/*
694
    END A NAMESPACE DEFINITION
695
 
696
    This routine ends the definition of the current namespace.
697
*/
698
 
6 7u83 699
void
700
end_namespace(int anon)
2 7u83 701
{
6 7u83 702
	NAMESPACE ns;
703
	clear_decl_blocks();
704
	ns = pop_namespace();
705
	if (do_dump) {
706
		IDENTIFIER id = DEREF_id(nspace_name(ns));
707
		dump_undefine(id, &crt_loc, 0);
708
	}
709
	UNUSED(anon);
710
	return;
2 7u83 711
}
712
 
713
 
714
/*
715
    PROCESS A TARGET DEPENDENT DECLARATION SEQUENCE
716
 
717
    This routine is called in the processing of target dependent
718
    preprocessing directives within declaration sequences.  The directive
719
    involved is given by dir, while c gives the associated condition for
720
    '#if' and '#elif'.
721
*/
722
 
6 7u83 723
void
724
target_decl(int dir, EXP c)
2 7u83 725
{
6 7u83 726
	if (!IS_NULL_exp(c)) {
727
		report(crt_loc, ERR_cpp_cond_if_ti_decl(dir));
728
	}
729
	return;
2 7u83 730
}
731
 
732
 
733
/*
734
    BEGIN A DECLARATION BLOCK
735
 
736
    A declaration block is a technique for partitioning the external
737
    declarations into subsets.  These subsets have no significance within
738
    the language, but are useful for indicating, for example, those
739
    identifiers which form part of a certain API.  This routine starts
740
    a declaration block named id.
741
*/
742
 
6 7u83 743
void
744
begin_decl_block(IDENTIFIER id)
2 7u83 745
{
6 7u83 746
	NAMESPACE cns = nonblock_namespace;
747
	NAMESPACE sns = scope_namespace;
748
	HASHID nm = DEREF_hashid(id_name(id));
749
	MEMBER mem = search_member(sns, nm, 1);
750
	id = DEREF_id(member_id(mem));
751
	if (IS_NULL_id(id)) {
752
		/* Create dummy namespace identifier */
753
		NAMESPACE bns = NULL_nspace;
754
		DECL_SPEC ds = (dspec_defn | dspec_extern);
755
		MAKE_id_nspace_name(nm, ds, cns, crt_loc, bns, id);
756
		bns = make_namespace(id, nspace_block_tag, 0);
757
		COPY_nspace(id_nspace_name_defn(id), bns);
758
		COPY_id(member_id(mem), id);
759
	}
760
	if (do_dump) {
761
		/* Output scope to dump file */
762
		NAMESPACE bns = DEREF_nspace(id_nspace_name_defn(id));
763
		dump_begin_scope(id, bns, cns, &crt_loc);
764
	}
765
	if (!IS_NULL_nspace(cns)) {
766
		/* Add to current namespace */
767
		STACK(IDENTIFIER)pids = DEREF_stack(nspace_set(cns));
768
		PUSH_id(id, pids);
769
		COPY_stack(nspace_set(cns), pids);
770
	}
771
	return;
2 7u83 772
}
773
 
774
 
775
/*
776
    END A DECLARATION BLOCK
777
 
778
    This routine ends a declaration block named id or the current
779
    declaration block if id is the null identifier.  If there is no
780
    current declaration block and force is true then an error is
781
    raised.  The routine returns true if a declaration block is ended.
782
*/
783
 
6 7u83 784
int
785
end_decl_block(IDENTIFIER id, int force)
2 7u83 786
{
6 7u83 787
	int res = 0;
788
	NAMESPACE cns = nonblock_namespace;
789
	if (!IS_NULL_nspace(cns)) {
790
		/* Add to current namespace */
791
		STACK(IDENTIFIER) pids = DEREF_stack(nspace_set(cns));
792
		if (IS_NULL_stack(pids)) {
793
			if (force) {
794
				/* Stack shouldn't be empty */
795
				report(crt_loc, ERR_pragma_dblock_end());
796
			}
797
		} else {
798
			IDENTIFIER pid;
799
			POP_id(pid, pids);
800
			COPY_stack(nspace_set(cns), pids);
801
			if (!IS_NULL_id(id)) {
802
				/* Check block name if given */
803
				HASHID nm = DEREF_hashid(id_name(id));
804
				HASHID pnm = DEREF_hashid(id_name(pid));
805
				if (!EQ_hashid(nm, pnm)) {
806
					report(crt_loc,
807
					       ERR_pragma_dblock_name(pnm));
808
				}
809
			}
810
			if (do_dump) {
811
				/* Output scope to dump file */
812
				NAMESPACE bns =
813
				    DEREF_nspace(id_nspace_name_defn(pid));
814
				dump_end_scope(pid, bns, &crt_loc);
815
			}
816
			res = 1;
2 7u83 817
		}
818
	}
6 7u83 819
	return (res);
2 7u83 820
}
821
 
822
 
823
/*
824
    END ALL DECLARATION BLOCKS
825
 
826
    This routine ends all the declaration blocks associated with the
827
    current namespace.  This is called at the end of a namespace definition
828
    and at the end of the input file.
829
*/
830
 
6 7u83 831
void
832
clear_decl_blocks(void)
2 7u83 833
{
6 7u83 834
	while (end_decl_block(NULL_id, 0));
835
	return;
2 7u83 836
}
837
 
838
 
839
/*
840
    FIND A NAMESPACE
841
 
842
    This routine finds the namespace corresponding to the identifier id,
843
    returning the null namespace if id does not represent a class or a
844
    namespace.
845
*/
846
 
6 7u83 847
NAMESPACE
848
find_namespace(IDENTIFIER id)
2 7u83 849
{
6 7u83 850
	NAMESPACE ns = NULL_nspace;
851
	if (!IS_NULL_id(id)) {
852
		switch (TAG_id(id)) {
853
		case id_nspace_name_tag:
854
		case id_nspace_alias_tag:
855
			/* Explicitly named namespaces */
856
			ns = DEREF_nspace(id_nspace_name_etc_defn(id));
857
			break;
858
		case id_class_name_tag:
859
		case id_class_alias_tag: {
860
			/* Class namespaces */
861
			TYPE t = DEREF_type(id_class_name_etc_defn(id));
862
			if (IS_type_compound(t)) {
863
				CLASS_TYPE ct =
864
				    DEREF_ctype(type_compound_defn(t));
865
				complete_class(ct, 1);
866
				ns = DEREF_nspace(ctype_member(ct));
867
			} else {
868
				CLASS_TYPE ct = find_class(id);
869
				if (!IS_NULL_ctype(ct)) {
870
					complete_class(ct, 1);
871
					ns = DEREF_nspace(ctype_member(ct));
872
				}
873
			}
874
			break;
2 7u83 875
		}
6 7u83 876
		}
2 7u83 877
	}
6 7u83 878
	return (ns);
2 7u83 879
}
880
 
881
 
882
/*
883
    LOOK UP A NAMESPACE NAME
884
 
885
    This routine looks up the identifier id as a namespace name in a
886
    namespace alias or namespace directive.
887
*/
888
 
6 7u83 889
NAMESPACE
890
find_nspace_id(IDENTIFIER id)
2 7u83 891
{
6 7u83 892
	NAMESPACE ns;
893
	if (IS_id_nspace_name_etc(id)) {
894
		ns = DEREF_nspace(id_nspace_name_etc_defn(id));
895
	} else {
896
		if (crt_templ_qualifier == 0) {
897
			HASHID nm = DEREF_hashid(id_name(id));
898
			if (crt_id_qualifier == qual_none) {
899
				IDENTIFIER nid = find_type_id(nm, 2);
900
				if (!IS_NULL_id(nid)) {
901
					id = nid;
902
				}
903
			} else {
904
				NAMESPACE pns = DEREF_nspace(id_parent(id));
905
				IDENTIFIER nid = find_qual_id(pns, nm, 0, 2);
906
				if (!IS_NULL_id(nid)) {
907
					id = nid;
908
				}
909
			}
910
		}
911
		ns = find_namespace(id);
912
		if (IS_NULL_nspace(ns)) {
913
			/* Invalid namespace identifier */
914
			report(crt_loc, ERR_dcl_nspace_undef(id));
915
			return (NULL_nspace);
916
		}
2 7u83 917
	}
6 7u83 918
	use_id(id, 0);
919
	return (ns);
2 7u83 920
}
921
 
922
 
923
/*
924
    CONSTRUCT A NAMESPACE ALIAS
925
 
926
    This routine sets up id as an alias for the namespace ns.  A namespace
927
    alias may be consistently redefined any number of times.
928
*/
929
 
6 7u83 930
void
931
alias_namespace(IDENTIFIER id, NAMESPACE ns)
2 7u83 932
{
6 7u83 933
	MEMBER mem;
934
	IDENTIFIER old_id;
935
	NAMESPACE cns = crt_namespace;
936
	HASHID nm = DEREF_hashid(id_name(id));
937
	DECL_SPEC ds = (dspec_defn | dspec_extern);
938
	if (IS_NULL_nspace(ns)) {
939
		/* Invalid namespace identifier */
940
		begin_namespace(id, 0);
941
		end_namespace(0);
942
		return;
943
	}
944
	if (IS_nspace_ctype(ns)) {
945
		/* Can't have a class namespace */
946
		report(crt_loc, ERR_dcl_nspace_alias_class(ns));
947
	}
2 7u83 948
 
6 7u83 949
	/* Look up namespace alias name */
950
	mem = search_member(cns, nm, 1);
951
	old_id = DEREF_id(member_id(mem));
2 7u83 952
 
6 7u83 953
	/* Check for redeclarations */
954
	if (!IS_NULL_id(old_id)) {
955
		old_id = redecl_inherit(old_id, qual_none, in_class_defn, 2);
956
		switch (TAG_id(old_id)) {
957
		case id_nspace_name_tag: {
958
			/* Previously defined namespace name */
959
			ERROR err;
960
			NAMESPACE old_ns;
961
			PTR(LOCATION) loc = id_loc(old_id);
962
			old_ns = DEREF_nspace(id_nspace_name_defn(old_id));
963
			report(crt_loc, ERR_dcl_nspace_alias_bad(old_id, loc));
964
			if (EQ_nspace(ns, old_ns)) {
965
				/* No further action if consistent */
966
				return;
967
			}
968
			/* Hide namespace name with namespace alias */
969
			err = ERR_dcl_nspace_alias_redef(old_id, loc);
970
			report(crt_loc, err);
971
			break;
2 7u83 972
		}
6 7u83 973
		case id_nspace_alias_tag: {
974
			/* Previously defined namespace alias */
975
			NAMESPACE old_ns;
976
			old_ns = DEREF_nspace(id_nspace_alias_defn(old_id));
977
			if (!EQ_nspace(ns, old_ns)) {
978
				/* Inconsistent alias redefinition */
979
				ERROR err;
980
				PTR(LOCATION) loc = id_loc(old_id);
981
				err = ERR_dcl_nspace_alias_redef(old_id, loc);
982
				report(crt_loc, err);
983
				COPY_nspace(id_nspace_alias_defn(old_id), ns);
984
			}
985
			return;
2 7u83 986
		}
6 7u83 987
		default: {
988
			/* Other previously defined identifier */
989
			PTR(LOCATION) loc = id_loc(old_id);
990
			report(crt_loc, ERR_basic_odr_decl(old_id, loc));
991
			break;
992
		}
993
		}
2 7u83 994
	}
995
 
6 7u83 996
	/* Set up the namespace alias */
997
	MAKE_id_nspace_alias(nm, ds, cns, decl_loc, ns, id);
998
	set_member(mem, id);
999
	return;
2 7u83 1000
}
1001
 
1002
 
1003
/*
1004
    PROCESS A USING NAMESPACE DIRECTIVE
1005
 
1006
    This routine processes a using namespace directive for the namespace ns.
1007
*/
1008
 
6 7u83 1009
void
1010
using_namespace(NAMESPACE ns)
2 7u83 1011
{
6 7u83 1012
	if (!IS_NULL_nspace(ns)) {
1013
		if (IS_nspace_ctype(ns)) {
1014
			/* Namespace designates a class */
1015
			report(crt_loc, ERR_dcl_nspace_udir_class(ns));
1016
		} else {
1017
			NAMESPACE cns = crt_namespace;
1018
			NAMESPACE jns = join_namespace(ns, cns);
1019
			if (IS_NULL_nspace(jns)) {
1020
				jns = global_namespace;
1021
			}
1022
			if (!use_namespace(ns, cns, jns)) {
1023
				/* Namespace already used */
1024
				report(crt_loc, ERR_dcl_nspace_udir_dup(ns));
1025
			}
1026
			uncache_namespace(ns, 0);
1027
			if (do_dump) {
1028
				dump_using(ns, cns, &crt_loc);
1029
			}
1030
		}
2 7u83 1031
	}
6 7u83 1032
	return;
2 7u83 1033
}
1034
 
1035
 
1036
/*
1037
    ADD A NESTED NAMESPACE
1038
 
1039
    This routine adds the namespace ns to the look-up stack.  If ns is
1040
    a nested namespace then the enclosing namespaces are also added.
1041
    It returns true if the stack is changed.
1042
*/
1043
 
6 7u83 1044
int
1045
add_nested_nspace(NAMESPACE ns)
2 7u83 1046
{
6 7u83 1047
	int res = 0;
1048
	if (!IS_NULL_nspace(ns) && !EQ_nspace(ns, crt_namespace)) {
1049
		switch (TAG_nspace(ns)) {
1050
		case nspace_named_tag:
1051
		case nspace_unnamed_tag:
1052
		case nspace_ctype_tag: {
1053
			IDENTIFIER id = DEREF_id(nspace_name(ns));
1054
			if (!IS_NULL_id(id)) {
1055
				NAMESPACE pns = DEREF_nspace(id_parent(id));
1056
				IGNORE add_nested_nspace(pns);
1057
			}
1058
			add_namespace(ns);
1059
			res = 1;
1060
			break;
2 7u83 1061
		}
6 7u83 1062
		}
2 7u83 1063
	}
6 7u83 1064
	return (res);
2 7u83 1065
}
1066
 
1067
 
1068
/*
1069
    REMOVE A NESTED NAMESPACE
1070
 
1071
    This routine removes the namespace ns from the look-up stack.  If
1072
    ns is a namespace class then the enclosing namespaces are also
1073
    removed.  It returns true if the stack is changed.
1074
*/
1075
 
6 7u83 1076
int
1077
remove_nested_nspace(NAMESPACE ns)
2 7u83 1078
{
6 7u83 1079
	int res = 0;
1080
	if (!IS_NULL_nspace(ns) && !EQ_nspace(ns, crt_namespace)) {
1081
		switch (TAG_nspace(ns)) {
1082
		case nspace_named_tag:
1083
		case nspace_unnamed_tag:
1084
		case nspace_ctype_tag: {
1085
			IDENTIFIER id;
1086
			remove_namespace();
1087
			id = DEREF_id(nspace_name(ns));
1088
			if (!IS_NULL_id(id)) {
1089
				NAMESPACE pns = DEREF_nspace(id_parent(id));
1090
				IGNORE remove_nested_nspace(pns);
1091
			}
1092
			res = 1;
1093
			break;
2 7u83 1094
		}
6 7u83 1095
		}
2 7u83 1096
	}
6 7u83 1097
	return (res);
2 7u83 1098
}
1099
 
1100
 
1101
/*
1102
    BEGIN THE LOOK-UP SCOPE FOR A DECLARATOR
1103
 
1104
    This routine is called immediately after the declarator id given with
1105
    identifier qualifiers idtype and qns to set the name look-up
1106
    appropriately.  Thus for example, in 'int C::a = b ;', b is looked up
1107
    in the scope of C.
1108
*/
1109
 
6 7u83 1110
void
1111
begin_declarator(IDENTIFIER id, QUALIFIER idtype, NAMESPACE qns, int scan)
2 7u83 1112
{
6 7u83 1113
	NAMESPACE ns = NULL_nspace;
1114
	if (idtype != qual_none) {
1115
		ns = DEREF_nspace(id_parent(id));
1116
		if (!IS_NULL_nspace(ns) && !IS_nspace_ctype(ns)) {
1117
			if (!IS_NULL_nspace(qns) && !EQ_nspace(qns, ns)) {
1118
				/* Should have an immediate member */
1119
				report(crt_loc, ERR_lookup_qual_decl(id, qns));
1120
				ns = qns;
1121
			}
1122
		}
1123
		if (add_nested_nspace(ns) && scan) {
1124
			/* Rescan identifier if stack has changed */
1125
			RESCAN_LEXER;
1126
		}
2 7u83 1127
	}
6 7u83 1128
	PUSH_nspace(ns, local_nspace_stack);
1129
	if (crt_state_depth == 0) {
1130
		id = underlying_id(id);
1131
		DEREF_loc(id_loc(id), decl_loc);
1132
	} else {
1133
		decl_loc = crt_loc;
2 7u83 1134
	}
6 7u83 1135
	return;
2 7u83 1136
}
1137
 
1138
 
1139
/*
1140
    END THE LOOK-UP SCOPE FOR A DECLARATOR
1141
 
1142
    This routine is called at the end of the initialiser or definition
1143
    of the declarator id to reset the name look-up.
1144
*/
1145
 
6 7u83 1146
void
1147
end_declarator(IDENTIFIER id, int scan)
2 7u83 1148
{
6 7u83 1149
	NAMESPACE ns;
1150
	POP_nspace(ns, local_nspace_stack);
1151
	if (IS_NULL_nspace(ns)) {
1152
		if (!IS_NULL_id(id)) {
1153
			HASHID nm = DEREF_hashid(id_name(id));
1154
			IDENTIFIER cid = DEREF_id(hashid_cache(nm));
1155
			if (!EQ_id(id, cid)) {
1156
				/* Look-up may have changed */
1157
				COPY_id(hashid_cache(nm), NULL_id);
1158
				if (scan) {
1159
					/* Rescan identifier if look-up has
1160
					 * changed */
1161
					RESCAN_LEXER;
1162
				}
1163
			}
2 7u83 1164
		}
6 7u83 1165
	} else {
1166
		if (remove_nested_nspace(ns) && scan) {
1167
			/* Rescan identifier if stack has changed */
1168
			RESCAN_LEXER;
1169
		}
2 7u83 1170
	}
6 7u83 1171
	return;
2 7u83 1172
}
1173
 
1174
 
1175
/*
1176
    SET A NAMESPACE MEMBER
1177
 
1178
    This routine sets the identifier id to be a namespace member as
1179
    indicated by mem.  It also sets the look-up cache to id if appropriate.
1180
*/
1181
 
6 7u83 1182
void
1183
set_member(MEMBER mem, IDENTIFIER id)
2 7u83 1184
{
6 7u83 1185
	if (!IS_NULL_member(mem)) {
1186
		HASHID nm;
1187
		IDENTIFIER cid;
1188
		LIST(NAMESPACE) lns;
2 7u83 1189
 
6 7u83 1190
		/* Check any previous definition */
1191
		IDENTIFIER pid = DEREF_id(member_id(mem));
1192
		if (!IS_NULL_id(pid)) {
1193
			if (IS_id_token(pid)) {
1194
				IGNORE unify_id(pid, id, 1);
1195
			} else if (IS_id_token(id)) {
1196
				if (unify_id(id, pid, 0)) {
1197
					return;
1198
				}
1199
			}
1200
		}
2 7u83 1201
 
6 7u83 1202
		/* Check look-up cache */
1203
		cid = NULL_id;
1204
		nm = DEREF_hashid(id_name(id));
1205
		lns = LIST_stack(namespace_stack);
1206
		if (!IS_NULL_list(lns)) {
1207
			/* Check for current namespace */
1208
			NAMESPACE ns = DEREF_nspace(id_parent(id));
1209
			NAMESPACE pns = DEREF_nspace(HEAD_list(lns));
1210
			if (EQ_nspace(ns, pns)) {
1211
				/* Check for unambiguous look-up */
1212
				lns = DEREF_list(nspace_use(ns));
1213
				if (IS_NULL_list(lns)) {
1214
					cid = id;
1215
				}
1216
			}
1217
		}
1218
		COPY_id(hashid_cache(nm), cid);
1219
 
1220
		/* Set member identifier */
1221
		COPY_id(member_id(mem), id);
2 7u83 1222
	}
6 7u83 1223
	return;
2 7u83 1224
}
1225
 
1226
 
1227
/*
1228
    SET A NAMESPACE TYPE MEMBER
1229
 
1230
    This routine sets the type identifier id to be a namespace member
1231
    as indicated by mem.  Note that in C this just sets the alt field
1232
    of mem, whereas in C++ it may also set the id field.
1233
*/
1234
 
6 7u83 1235
void
1236
set_type_member(MEMBER mem, IDENTIFIER id)
2 7u83 1237
{
6 7u83 1238
	if (!IS_NULL_member(mem)) {
2 7u83 1239
#if LANGUAGE_CPP
6 7u83 1240
		IDENTIFIER mid = DEREF_id(member_id(mem));
1241
		if (IS_NULL_id(mid)) {
1242
			/* No object of the same name */
1243
			set_member(mem, id);
1244
		} else {
1245
			/* Hidden by object of the same name */
1246
			HASHID nm = DEREF_hashid(id_name(id));
1247
			DECL_SPEC ds = DEREF_dspec(id_storage(mid));
1248
			if ((ds & dspec_inherit) && !(ds & dspec_alias)) {
1249
				ds = DEREF_dspec(id_storage(id));
1250
				if (!(ds & dspec_inherit)) {
1251
					/* An uninherited type overrrides an
1252
					 * inherited object */
1253
					COPY_id(member_id(mem), id);
1254
				}
1255
			}
1256
			COPY_id(hashid_cache(nm), NULL_id);
2 7u83 1257
		}
6 7u83 1258
#endif
1259
		COPY_id(member_alt(mem), id);
2 7u83 1260
	}
6 7u83 1261
	return;
2 7u83 1262
}
1263
 
1264
 
1265
/*
1266
    CLEAR A NAMESPACE MEMBER
1267
 
1268
    This routine clears all meanings of the member nm of the namespace ns.
1269
*/
1270
 
6 7u83 1271
void
1272
clear_member(NAMESPACE ns, HASHID nm)
2 7u83 1273
{
6 7u83 1274
	MEMBER mem = search_member(ns, nm, 0);
1275
	if (!IS_NULL_member(mem)) {
1276
		COPY_id(member_id(mem), NULL_id);
1277
		COPY_id(member_alt(mem), NULL_id);
1278
	}
1279
	COPY_id(hashid_cache(nm), NULL_id);
1280
	return;
2 7u83 1281
}
1282
 
1283
 
1284
/*
1285
    FIND A MEMBER OF A NAMESPACE
1286
 
1287
    This routine searches the namespace ns for a member named nm.  This
1288
    is returned if found.  Otherwise if create is true then an empty
1289
    member is created and returned.  Otherwise the null member is returned.
1290
*/
1291
 
6 7u83 1292
MEMBER
1293
search_member(NAMESPACE ns, HASHID nm, int create)
2 7u83 1294
{
6 7u83 1295
	MEMBER mem;
2 7u83 1296
 
6 7u83 1297
	if (IS_NULL_nspace(ns)) {
1298
		/* Null namespace */
1299
		if (create) {
1300
			MAKE_member_small(NULL_member, mem);
1301
		} else {
1302
			mem = NULL_member;
1303
		}
2 7u83 1304
 
6 7u83 1305
	} else if (IS_nspace_block_etc(ns)) {
1306
		/* Small namespaces */
1307
		MEMBER last = DEREF_member(nspace_last(ns));
2 7u83 1308
 
6 7u83 1309
		/* Search through members */
1310
		mem = last;
1311
		while (!IS_NULL_member(mem)) {
1312
			IDENTIFIER mid = DEREF_id(member_id(mem));
1313
			if (!IS_NULL_id(mid)) {
1314
				HASHID mnm = DEREF_hashid(id_name(mid));
1315
				if (EQ_hashid(nm, mnm)) {
1316
					return (mem);
1317
				}
2 7u83 1318
#if LANGUAGE_C
6 7u83 1319
			} else {
1320
			/* ... continues */
1321
				/* Need to also check tag namespace in C */
1322
				mid = DEREF_id(member_alt(mem));
1323
				if (!IS_NULL_id(mid)) {
1324
					HASHID mnm = DEREF_hashid(id_name(mid));
1325
					if (EQ_hashid(nm, mnm)) {
1326
						return (mem);
1327
					}
1328
				}
1329
#endif
1330
			}
1331
			mem = DEREF_member(member_next(mem));
2 7u83 1332
		}
1333
 
6 7u83 1334
		/* Create new member if necessary */
1335
		if (create) {
1336
			MAKE_member_small(last, mem);
1337
			COPY_member(nspace_last(ns), mem);
1338
		}
1339
	} else {
1340
		/* Large namespaces */
1341
		PTR(MEMBER) ptr = DEREF_ptr(nspace_named_etc_table(ns));
1342
		unsigned long sz = DEREF_ulong(nspace_named_etc_size(ns));
1343
		unsigned long h = DEREF_ulong(hashid_hash(nm));
1344
		SIZE(MEMBER) psz = SCALE(SIZE_member,(h % sz));
2 7u83 1345
 
6 7u83 1346
		/* Search through members */
1347
		ptr = STEP_ptr(ptr, psz);
1348
		mem = DEREF_member(ptr);
1349
		while (!IS_NULL_member(mem)) {
1350
			IDENTIFIER mid = DEREF_id(member_id(mem));
1351
			if (!IS_NULL_id(mid)) {
1352
				HASHID mnm = DEREF_hashid(id_name(mid));
1353
				if (EQ_hashid(nm, mnm)) {
1354
					return (mem);
1355
				}
2 7u83 1356
#if LANGUAGE_C
6 7u83 1357
			} else {
1358
			/* ... continues */
1359
				/* Need to also check tag namespace in C */
1360
				mid = DEREF_id(member_alt(mem));
1361
				if (!IS_NULL_id(mid)) {
1362
					HASHID mnm = DEREF_hashid(id_name(mid));
1363
					if (EQ_hashid(nm, mnm)) {
1364
						return (mem);
1365
					}
1366
				}
1367
#endif
1368
			}
1369
			mem = DEREF_member(member_large_tnext(mem));
2 7u83 1370
		}
1371
 
6 7u83 1372
		/* Create new member if necessary */
1373
		if (create) {
1374
			MEMBER last;
1375
			mem = DEREF_member(ptr);
1376
			MAKE_member_large(NULL_member, mem, mem);
1377
			COPY_member(ptr, mem);
1378
			last = DEREF_member(nspace_last(ns));
1379
			if (IS_NULL_member(last)) {
1380
				COPY_member(nspace_named_etc_first(ns), mem);
1381
			} else {
1382
				COPY_member(member_next(last), mem);
1383
			}
1384
			COPY_member(nspace_last(ns), mem);
1385
		}
2 7u83 1386
	}
6 7u83 1387
	return (mem);
2 7u83 1388
}
1389
 
1390
 
1391
/*
1392
    UPDATE A NAMESPACE MEMBER
1393
 
1394
    This routine copies the member mem of the namespace ns to the end of
1395
    the list of all members.  In block namespaces this is to force the
1396
    member to be re-examined in make_decl_stmt.  In class namespaces this
1397
    is to preserve the order of the data members.
1398
*/
1399
 
6 7u83 1400
MEMBER
1401
update_member(NAMESPACE ns, MEMBER mem)
2 7u83 1402
{
6 7u83 1403
	IDENTIFIER id = DEREF_id(member_id(mem));
1404
	IDENTIFIER alt = DEREF_id(member_alt(mem));
1405
	COPY_id(member_id(mem), NULL_id);
1406
	COPY_id(member_alt(mem), NULL_id);
1407
	if (IS_member_small(mem)) {
1408
		/* Create new small member */
1409
		MEMBER last = DEREF_member(nspace_last(ns));
1410
		MAKE_member_small(last, mem);
1411
		COPY_member(nspace_last(ns), mem);
1412
	} else {
1413
		/* Create new large member */
1414
		if (!IS_NULL_id(id)) {
1415
			HASHID nm = DEREF_hashid(id_name(id));
1416
			mem = search_member(ns, nm, 1);
1417
		} else if (!IS_NULL_id(alt)) {
1418
			HASHID nm = DEREF_hashid(id_name(alt));
1419
			mem = search_member(ns, nm, 1);
1420
		}
2 7u83 1421
	}
6 7u83 1422
	COPY_id(member_id(mem), id);
1423
	COPY_id(member_alt(mem), alt);
1424
	return (mem);
2 7u83 1425
}
1426
 
1427
 
1428
/*
1429
    FIND A TYPE IDENTIFIER
1430
 
1431
    This routine checks whether the identifier id is a type name (if bit 0
1432
    of type is true) or a namespace name (if bit 1 of type is true).  In
1433
    C only struct, union and enum tags are allowed.
1434
*/
1435
 
6 7u83 1436
static IDENTIFIER
1437
select_type_id(IDENTIFIER id, int type)
2 7u83 1438
{
6 7u83 1439
	if (!IS_NULL_id(id)) {
1440
		switch (TAG_id(id)) {
1441
		case id_class_name_tag:
1442
		case id_enum_name_tag:
1443
			if (type & 1) {
1444
				return (id);
1445
			}
1446
			break;
2 7u83 1447
#if LANGUAGE_CPP
6 7u83 1448
		case id_class_alias_tag:
1449
		case id_enum_alias_tag:
1450
		case id_type_alias_tag:
1451
			if (type & 1) {
1452
				return (id);
1453
			}
1454
			break;
1455
		case id_nspace_name_tag:
1456
		case id_nspace_alias_tag:
1457
			if (type & 2) {
1458
				return (id);
1459
			}
1460
			break;
2 7u83 1461
#endif
6 7u83 1462
		}
2 7u83 1463
	}
6 7u83 1464
	return (NULL_id);
2 7u83 1465
}
1466
 
1467
 
1468
/*
1469
    FIND A TYPE MEMBER
1470
 
1471
    This routine returns the type or namespace name associated with the
1472
    member mem, or the null identifier if this does not exist.  The
1473
    type argument is as above.  In C++ it is necessary to check both
1474
    the id and the alt fields of mem, whereas in C only the alt field
1475
    needs to be examined.
1476
*/
1477
 
6 7u83 1478
IDENTIFIER
1479
type_member(MEMBER mem, int type)
2 7u83 1480
{
6 7u83 1481
	IDENTIFIER id = NULL_id;
1482
	if (!IS_NULL_member(mem)) {
2 7u83 1483
#if LANGUAGE_CPP
6 7u83 1484
		id = DEREF_id(member_id(mem));
1485
		id = select_type_id(id, type);
1486
		if (IS_NULL_id(id)) {
1487
			id = DEREF_id(member_alt(mem));
1488
			id = select_type_id(id, type);
1489
		}
2 7u83 1490
#else
6 7u83 1491
		id = DEREF_id(member_alt(mem));
1492
		id = select_type_id(id, type);
2 7u83 1493
#endif
6 7u83 1494
	}
1495
	return (id);
2 7u83 1496
}
1497
 
1498
 
1499
/*
1500
    IS AN IDENTIFIER IN A LIST?
1501
 
1502
    This routine checks whether the identifier id is in the list of
1503
    ambiguous meanings given by pid and pids.  Functions are excluded
1504
    because of the complications introduced by using-declarations and
1505
    overloading.  Overload resolution will eliminate duplicate entries
1506
    in this case.
1507
*/
1508
 
6 7u83 1509
static int
1510
already_found_id(IDENTIFIER id, IDENTIFIER pid, LIST(IDENTIFIER) pids)
2 7u83 1511
{
6 7u83 1512
	if (IS_id_function_etc(id)) {
1513
		/* Exclude functions */
1514
		return (0);
2 7u83 1515
	}
6 7u83 1516
	if (!IS_NULL_id(pid)) {
1517
		if (IS_id_ambig(pid)) {
1518
			/* Check ambiguous identifiers */
1519
			LIST(IDENTIFIER) qids = DEREF_list(id_ambig_ids(pid));
1520
			if (already_found_id(id, NULL_id, qids)) {
1521
				return (1);
1522
			}
1523
		} else {
1524
			/* Check simple identifiers */
1525
			if (!IS_id_function_etc(pid)) {
1526
				id = DEREF_id(id_alias(id));
1527
				pid = DEREF_id(id_alias(pid));
1528
				if (EQ_id(id, pid)) {
1529
					return (1);
1530
				}
1531
			}
1532
		}
1533
	}
1534
	if (!IS_NULL_list(pids)) {
1535
		/* Check identifier lists */
1536
		IDENTIFIER qid = DEREF_id(HEAD_list(pids));
1537
		pids = TAIL_list(pids);
1538
		return (already_found_id(id, qid, pids));
1539
	}
1540
	return (0);
2 7u83 1541
}
1542
 
1543
 
1544
/*
1545
    LOOK UP AN IDENTIFIER IN A NAMESPACE
1546
 
1547
    This routine looks up the identifier nm in the namespace ns.
1548
*/
1549
 
6 7u83 1550
IDENTIFIER
1551
search_id(NAMESPACE ns, HASHID nm, int create, int type)
2 7u83 1552
{
6 7u83 1553
	IDENTIFIER id;
1554
	MEMBER mem = search_member(ns, nm, create);
1555
	if (!IS_NULL_member(mem)) {
1556
		if (type) {
1557
			id = type_member(mem, type);
1558
		} else {
1559
			id = DEREF_id(member_id(mem));
1560
		}
2 7u83 1561
	} else {
6 7u83 1562
		id = NULL_id;
2 7u83 1563
	}
6 7u83 1564
	return (id);
2 7u83 1565
}
1566
 
1567
 
1568
/*
1569
    SEARCH A NAMESPACE FOR AN IDENTIFIER
1570
 
1571
    This routine searches the namespace ns and used namespaces for an
1572
    identifier named nm, which is returned if found.  Otherwise if create
1573
    is true then a dummy identifier is created and returned.  Otherwise
1574
    the null identifier is returned.  qual is true for qualified look-ups.
1575
    If type is nonzero then only type and namespace names are considered.
1576
    rns gives the original value of ns for use when recursively searching
1577
    used namespaces.
1578
*/
1579
 
6 7u83 1580
static IDENTIFIER
1581
search_nspace(NAMESPACE ns, HASHID nm, NAMESPACE rns, int qual, int create,
1582
	      int type)
2 7u83 1583
{
6 7u83 1584
	IDENTIFIER id;
1585
	LIST(NAMESPACE) uns;
2 7u83 1586
 
6 7u83 1587
	/* Allow for class namespaces */
1588
	if (IS_nspace_ctype(ns)) {
1589
		id = search_field(ns, nm, create, type);
1590
		return (id);
1591
	}
2 7u83 1592
 
6 7u83 1593
	/* Search main namespace */
1594
	id = search_id(ns, nm, create, type);
1595
	if (!IS_NULL_id(id) && qual) {
1596
		/* Return found identifier */
1597
		return (id);
1598
	}
2 7u83 1599
 
6 7u83 1600
	/* Search used namespaces */
1601
	uns = DEREF_list(nspace_use(ns));
1602
	if (!IS_NULL_list(uns)) {
1603
		LIST(NAMESPACE) vns = DEREF_list(nspace_join(ns));
1604
		LIST(NAMESPACE) uns_orig = uns;
1605
		LIST(NAMESPACE) vns_orig = vns;
1606
		LIST(IDENTIFIER) ambig = NULL_list(IDENTIFIER);
1607
		COPY_list(nspace_use(ns), NULL_list(NAMESPACE));
1608
		COPY_list(nspace_join(ns), NULL_list(NAMESPACE));
1609
		while (!IS_NULL_list(uns)) {
1610
			NAMESPACE pns = DEREF_nspace(HEAD_list(uns));
1611
			NAMESPACE jns = DEREF_nspace(HEAD_list(vns));
1612
			if (qual || is_subnspace(rns, jns)) {
1613
				/* Look-up identifier in used namespace */
1614
				IDENTIFIER pid;
1615
				pid = search_nspace(pns, nm, rns, qual, 0,
1616
						    type);
1617
				if (!IS_NULL_id(pid)) {
1618
					/* Add found identifier to list */
1619
					if (IS_NULL_id(id)) {
1620
						id = pid;
1621
					} else if (!already_found_id(pid, id,
1622
								     ambig)) {
1623
						CONS_id(pid, ambig, ambig);
1624
					}
1625
				}
1626
			} else {
1627
				/* Postpone look-up until join namespace */
1628
				if (use_namespace(pns, jns, jns)) {
1629
					CONS_nspace(jns, join_nspaces,
1630
						    join_nspaces);
1631
				}
1632
			}
1633
			vns = TAIL_list(vns);
1634
			uns = TAIL_list(uns);
2 7u83 1635
		}
6 7u83 1636
		if (!IS_NULL_list(ambig)) {
1637
			/* Ambiguous resolution */
1638
			DECL_SPEC ds;
1639
			CONS_id(id, ambig, ambig);
1640
			ds = find_ambig_dspec(ambig);
1641
			MAKE_id_ambig(nm, ds, rns, crt_loc, ambig, 1, id);
2 7u83 1642
		}
6 7u83 1643
		COPY_list(nspace_use(ns), uns_orig);
1644
		COPY_list(nspace_join(ns), vns_orig);
2 7u83 1645
	}
6 7u83 1646
 
1647
	/* Create dummy identifier if necessary */
1648
	if (IS_NULL_id(id) && create) {
1649
		MAKE_id_undef(nm, dspec_none, ns, crt_loc, id);
2 7u83 1650
	}
6 7u83 1651
	return (id);
2 7u83 1652
}
1653
 
1654
 
1655
/*
1656
    EXTERNAL NAME LOOK-UP
1657
 
1658
    This routine searches all the namespaces in the current namespace stack
1659
    which are contained within pns for the identifier pns.  If type is
1660
    nonzero then only type and namespace names are considered.
1661
*/
1662
 
6 7u83 1663
IDENTIFIER
1664
find_extern_id(HASHID nm, NAMESPACE pns, int type)
2 7u83 1665
{
6 7u83 1666
	IDENTIFIER id = NULL_id;
1667
	LIST(NAMESPACE) lns = LIST_stack(namespace_stack);
1668
	while (!IS_NULL_list(lns)) {
1669
		NAMESPACE ns = DEREF_nspace(HEAD_list(lns));
1670
		if (!IS_NULL_nspace(ns)) {
1671
			id = search_nspace(ns, nm, ns, 0, 0, type);
1672
			if (!IS_NULL_id(id)) {
1673
				break;
1674
			}
1675
			if (EQ_nspace(ns, pns)) {
1676
				break;
1677
			}
1678
		}
1679
		lns = TAIL_list(lns);
2 7u83 1680
	}
6 7u83 1681
	if (!IS_NULL_list(join_nspaces)) {
1682
		clear_join_nspaces();
1683
	}
1684
	return (id);
2 7u83 1685
}
1686
 
1687
 
1688
/*
1689
    UNQUALIFIED NAME LOOK-UP
1690
 
1691
    This routine (aka who the feck is fred?) looks up the name nm in the
1692
    current scope, returning the corresponding identifier.  Note that
1693
    there is always a meaning for nm even if it is the underlying dummy
1694
    identifier.
1695
*/
1696
 
6 7u83 1697
IDENTIFIER
1698
find_id(HASHID nm)
2 7u83 1699
{
6 7u83 1700
	IDENTIFIER id;
1701
	if (cache_lookup) {
1702
		id = DEREF_id(hashid_cache(nm));
1703
		if (IS_NULL_id(id)) {
1704
			id = find_extern_id(nm, NULL_nspace, 0);
1705
			if (IS_NULL_id(id)) {
1706
				/* Use underlying meaning if not found */
1707
				id = DEREF_id(hashid_id(nm));
1708
			}
1709
			COPY_id(hashid_cache(nm), id);
1710
		}
1711
	} else {
1712
		id = find_extern_id(nm, NULL_nspace, 0);
1713
		if (IS_NULL_id(id)) {
1714
			/* Use underlying meaning if not found */
1715
			id = DEREF_id(hashid_id(nm));
1716
		}
2 7u83 1717
	}
6 7u83 1718
	return (id);
2 7u83 1719
}
1720
 
1721
 
1722
/*
1723
    QUALIFIED NAME LOOK-UP
1724
 
1725
    This routine (aka who the feck is fred::bloggs?) looks up the name nm
1726
    in the namespace ns.  Only type names are considered when type is
1727
    nonzero.  When ns is the null namespace this reduces to an unqualified
1728
    name look-up.
1729
*/
1730
 
6 7u83 1731
IDENTIFIER
1732
find_qual_id(NAMESPACE ns, HASHID nm, int create, int type)
2 7u83 1733
{
6 7u83 1734
	IDENTIFIER id;
1735
	if (IS_NULL_nspace(ns)) {
1736
		/* Unqualified name look-up */
1737
		if (type == 0) {
1738
			id = find_id(nm);
1739
		} else {
1740
			id = find_type_id(nm, type);
1741
		}
2 7u83 1742
	} else {
6 7u83 1743
		/* Qualified name look-up */
1744
		id = search_nspace(ns, nm, ns, 1, create, type);
2 7u83 1745
	}
6 7u83 1746
	return (id);
2 7u83 1747
}
1748
 
1749
 
1750
/*
1751
    SIMPLE TYPE NAME LOOK-UP
1752
 
1753
    This routine looks up the name nm as a type in the current scope,
1754
    returning the corresponding identifier.  If there is no type named
1755
    nm then the null identifier is returned.
1756
*/
1757
 
6 7u83 1758
IDENTIFIER
1759
find_type_id(HASHID nm, int type)
2 7u83 1760
{
6 7u83 1761
	IDENTIFIER id;
1762
	if (cache_lookup) {
1763
		/* Check whether cached value is a type */
1764
		id = DEREF_id(hashid_cache(nm));
1765
		id = select_type_id(id, type);
1766
		if (!IS_NULL_id(id)) {
1767
			return (id);
1768
		}
1769
	}
1770
	id = find_extern_id(nm, NULL_nspace, type);
1771
	return (id);
2 7u83 1772
}
1773
 
1774
 
1775
/*
1776
    OPERATOR FUNCTION NAME LOOK-UP
1777
 
1778
    This routine is identical to find_id except that it ignores all class
1779
    namespaces.  This is used when looking up operator functions in C++
1780
    and is the default look-up rule in C.
1781
*/
1782
 
6 7u83 1783
IDENTIFIER
1784
find_op_id(HASHID nm)
2 7u83 1785
{
6 7u83 1786
	IDENTIFIER id;
1787
	LIST(NAMESPACE) lns;
1788
	int cache = cache_lookup;
1789
	if (cache) {
1790
		/* Check cached look-up */
1791
		id = DEREF_id(hashid_cache(nm));
1792
		if (!IS_NULL_id(id)) {
1793
			NAMESPACE ns = DEREF_nspace(id_parent(id));
1794
			if (IS_NULL_nspace(ns) || !IS_nspace_ctype(ns)) {
1795
				return (id);
1796
			}
1797
			cache = 0;
1798
		}
2 7u83 1799
	}
1800
 
6 7u83 1801
	/* Scan through namespace stack */
1802
	lns = LIST_stack(namespace_stack);
1803
	while (!IS_NULL_list(lns)) {
1804
		NAMESPACE ns = DEREF_nspace(HEAD_list(lns));
1805
		if (!IS_NULL_nspace(ns) && !IS_nspace_ctype(ns)) {
1806
			id = search_nspace(ns, nm, ns, 0, 0, 0);
1807
			if (!IS_NULL_id(id)) {
1808
				if (!IS_NULL_list(join_nspaces)) {
1809
					clear_join_nspaces();
1810
				}
1811
				if (cache) {
1812
					COPY_id(hashid_cache(nm), id);
1813
				}
1814
				return (id);
1815
			}
1816
		} else {
1817
			cache = 0;
1818
		}
1819
		lns = TAIL_list(lns);
2 7u83 1820
	}
6 7u83 1821
	if (!IS_NULL_list(join_nspaces)) {
1822
		clear_join_nspaces();
1823
	}
1824
	id = DEREF_id(hashid_id(nm));
1825
	if (cache) {
1826
		COPY_id(hashid_cache(nm), id);
1827
	}
1828
	return (id);
2 7u83 1829
}
1830
 
1831
 
1832
/*
1833
    FINAL NAME LOOK-UP CHECK
1834
 
1835
    This routine gives a final check in the name look-up.  In most cases
1836
    id will already be a valid identifier for the namespace ns - the couple
1837
    of exceptions - undeclared members and non-simple identifier names
1838
    are handled by this routine.
1839
*/
1840
 
6 7u83 1841
IDENTIFIER
1842
check_id(NAMESPACE ns, IDENTIFIER id, int templ)
2 7u83 1843
{
6 7u83 1844
	if (!IS_NULL_id(id)) {
1845
		unsigned tag = TAG_id(id);
1846
		if (tag == id_dummy_tag) {
1847
			/* Re-scan dummy identifiers */
1848
			HASHID nm = DEREF_hashid(id_name(id));
1849
			id = find_qual_id(ns, nm, 1, 0);
1850
			tag = TAG_id(id);
1851
		}
1852
		if (tag == id_token_tag && crt_id_qualifier != qual_none) {
1853
			/* Can't qualify token names */
1854
			report(crt_loc, ERR_token_qual(id));
1855
		}
1856
		UNUSED(templ);
2 7u83 1857
	}
6 7u83 1858
	return (id);
2 7u83 1859
}
1860
 
1861
 
1862
/*
1863
    REMOVE AN ELEMENT OF A SET OF OVERLOADED FUNCTIONS
1864
 
1865
    This routine removes the function id from the set of overloaded
1866
    functions fid.
1867
*/
1868
 
6 7u83 1869
static IDENTIFIER
1870
remove_func(IDENTIFIER fid, IDENTIFIER id)
2 7u83 1871
{
6 7u83 1872
	if (!IS_NULL_id(fid)) {
1873
		IDENTIFIER pid = DEREF_id(id_function_etc_over(fid));
1874
		if (EQ_id(fid, id)) {
1875
			fid = pid;
1876
			COPY_id(id_function_etc_over(id), NULL_id);
1877
		} else {
1878
			pid = remove_func(pid, id);
1879
			COPY_id(id_function_etc_over(fid), pid);
1880
		}
2 7u83 1881
	}
6 7u83 1882
	return (fid);
2 7u83 1883
}
1884
 
1885
 
1886
/*
1887
    REMOVE AN IDENTIFIER FROM A NAMESPACE
1888
 
1889
    This routine removes the identifier id its parent namespace.
1890
*/
1891
 
6 7u83 1892
void
1893
remove_id(IDENTIFIER id)
2 7u83 1894
{
6 7u83 1895
	HASHID nm = DEREF_hashid(id_name(id));
1896
	NAMESPACE ns = DEREF_nspace(id_parent(id));
1897
	MEMBER mem = search_member(ns, nm, 0);
1898
	if (!IS_NULL_member(mem)) {
1899
		IDENTIFIER mid = DEREF_id(member_id(mem));
1900
		IDENTIFIER tid = DEREF_id(member_alt(mem));
1901
		if (IS_id_function_etc(id)) {
1902
			mid = remove_func(mid, id);
1903
		} else {
1904
			if (EQ_id(id, mid)) {
1905
				mid = NULL_id;
1906
			}
1907
			if (EQ_id(id, tid)) {
1908
				tid = NULL_id;
1909
			}
1910
		}
1911
		if (IS_NULL_id(mid)) {
1912
			mid = tid;
1913
		}
1914
		COPY_id(member_id(mem), mid);
1915
		COPY_id(member_alt(mem), tid);
1916
		COPY_id(hashid_cache(nm), NULL_id);
1917
		IGNORE check_identifier(id, ns, NULL_exp, ANON_NONE, 1);
2 7u83 1918
	}
6 7u83 1919
	return;
2 7u83 1920
}
1921
 
1922
 
1923
/*
1924
    DOES AN IDENTIFIER HAVE AN EXTERNAL LINKAGE NAME?
1925
 
1926
    This routine checks whether the identifier id has an external linkage
1927
    name.  It cannot be a member of a block, an unnamed class or an
1928
    anonymous namespace.
1929
*/
1930
 
6 7u83 1931
int
1932
has_linkage(IDENTIFIER id)
2 7u83 1933
{
6 7u83 1934
	while (!IS_NULL_id(id)) {
1935
		HASHID nm = DEREF_hashid(id_name(id));
1936
		NAMESPACE ns = DEREF_nspace(id_parent(id));
1937
		DECL_SPEC ds = DEREF_dspec(id_storage(id));
1938
		if (IS_hashid_anon(nm)) {
1939
			return (0);
1940
		}
1941
		if (!(ds & dspec_extern)) {
1942
			return (0);
1943
		}
1944
		if ((ds & dspec_c) && !anon_c_linkage) {
1945
			return (1);
1946
		}
1947
		if (IS_NULL_nspace(ns)) {
1948
			return (0);
1949
		}
1950
		switch (TAG_nspace(ns)) {
1951
		case nspace_named_tag:
1952
			break;
1953
		case nspace_ctype_tag:
1954
			break;
1955
		case nspace_global_tag:
1956
			return (1);
1957
		default:
1958
			return (0);
1959
		}
1960
		id = DEREF_id(nspace_name(ns));
2 7u83 1961
	}
6 7u83 1962
	return (0);
2 7u83 1963
}
1964
 
1965
 
1966
/*
1967
    CHECK HIDING OF LOCAL VARIABLES
1968
 
1969
    This routine is used to report on variables, parameters and functions
1970
    hidden by id.  Note that only the first instance is reported, and that
1971
    the hiding of one declaration by a subsequent incompatible redeclaration
1972
    is excluded.
1973
*/
1974
 
6 7u83 1975
void
1976
check_hiding(IDENTIFIER id)
2 7u83 1977
{
6 7u83 1978
    if (crt_id_qualifier == qual_none) {
2 7u83 1979
	/* Check through all look-up namespaces */
6 7u83 1980
	HASHID nm = DEREF_hashid(id_name(id));
1981
	LIST(NAMESPACE) lns = LIST_stack(namespace_stack);
1982
	while (!IS_NULL_list(lns)) {
1983
	    NAMESPACE ns = DEREF_nspace(HEAD_list(lns));
1984
	    if (!IS_NULL_nspace(ns)) {
1985
		IDENTIFIER mid = search_nspace(ns, nm, ns, 0, 0, 0);
1986
		if (!IS_NULL_id(mid) && !EQ_id(mid, id)) {
1987
		    ERROR err = NULL_err;
1988
		    switch (TAG_id(mid)) {
1989
			case id_variable_tag:
1990
			case id_parameter_tag:
1991
			case id_function_tag: {
2 7u83 1992
			    /* Report hiding of these objects */
6 7u83 1993
			    PTR(LOCATION) mloc = id_loc(mid);
1994
			    err = ERR_basic_scope_hide(nm, mloc);
1995
			    break;
2 7u83 1996
			}
6 7u83 1997
			case id_stat_member_tag:
1998
			case id_mem_func_tag:
1999
			case id_stat_mem_func_tag:
2000
			case id_member_tag:
2 7u83 2001
			    /* Report hiding of members */
6 7u83 2002
			    err = ERR_basic_scope_hide_mem(nm, mid);
2003
			    break;
2 7u83 2004
		    }
6 7u83 2005
		    if (!IS_NULL_err(err)) {
2 7u83 2006
			/* Print error */
6 7u83 2007
			LOCATION loc;
2008
			DEREF_loc(id_loc(id), loc);
2009
			report(crt_loc, err);
2 7u83 2010
		    }
6 7u83 2011
		    break;
2 7u83 2012
		}
2013
	    }
6 7u83 2014
	    lns = TAIL_list(lns);
2 7u83 2015
	}
6 7u83 2016
	if (!IS_NULL_list(join_nspaces)) {
2017
		clear_join_nspaces();
2018
	}
2 7u83 2019
    }
6 7u83 2020
    return;
2 7u83 2021
}