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
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 <limits.h>
63
#include "c_types.h"
64
#include "ctype_ops.h"
65
#include "etype_ops.h"
66
#include "exp_ops.h"
67
#include "graph_ops.h"
68
#include "hashid_ops.h"
69
#include "id_ops.h"
70
#include "member_ops.h"
71
#include "nspace_ops.h"
72
#include "off_ops.h"
73
#include "tok_ops.h"
74
#include "type_ops.h"
75
#include "error.h"
76
#include "catalog.h"
77
#include "option.h"
78
#include "access.h"
79
#include "check.h"
80
#include "chktype.h"
81
#include "class.h"
82
#include "derive.h"
83
#include "dump.h"
84
#include "identifier.h"
85
#include "instance.h"
86
#include "namespace.h"
87
#include "redeclare.h"
88
#include "syntax.h"
89
#include "template.h"
90
#include "token.h"
91
#include "virtual.h"
92
 
93
 
94
/*
95
    ARE TWO GRAPHS EQUAL?
96
 
97
    This routine checks whether the graphs gr and gs are equal.  Allowance
98
    is made for the equivalence of virtual bases.
99
*/
100
 
6 7u83 101
int
102
eq_graph(GRAPH gr, GRAPH gs)
2 7u83 103
{
6 7u83 104
	GRAPH hr = gr;
105
	GRAPH hs = gs;
106
	while (!IS_NULL_graph(gr)) {
107
		/* Calculate canonical form for virtual bases */
108
		hr = gr;
109
		gr = DEREF_graph(graph_equal(gr));
110
	}
111
	while (!IS_NULL_graph(gs)) {
112
		/* Calculate canonical form for virtual bases */
113
		hs = gs;
114
		gs = DEREF_graph(graph_equal(gs));
115
	}
116
	return (EQ_graph(hr, hs));
2 7u83 117
}
118
 
119
 
120
/*
121
    SEARCH A GRAPH FOR A BASE
122
 
123
    This routine searches the graph gr for the base class ct.  It returns
124
    the first node encountered which matches ct, or the null graph if no
125
    such match is found.  Note that the search algorithm is based on a
126
    depth-first left-to-right traversal of the graph.
127
*/
128
 
6 7u83 129
static GRAPH
130
search_graph(GRAPH gr, CLASS_TYPE ct)
2 7u83 131
{
6 7u83 132
	DECL_SPEC acc;
2 7u83 133
 
6 7u83 134
	/* Check the head of gr */
135
	CLASS_TYPE cr = DEREF_ctype(graph_head(gr));
136
	if (eq_ctype(cr, ct)) {
137
		return (gr);
138
	}
2 7u83 139
 
6 7u83 140
	/* Only search first instance */
141
	acc = DEREF_dspec(graph_access(gr));
142
	if (acc & dspec_defn) {
143
		/* Search the branches of gr */
144
		LIST(GRAPH)br = DEREF_list(graph_tails(gr));
145
		while (!IS_NULL_list(br)) {
146
			GRAPH gs = DEREF_graph(HEAD_list(br));
147
			gs = search_graph(gs, ct);
148
			if (!IS_NULL_graph(gs)) {
149
				return (gs);
150
			}
151
			br = TAIL_list(br);
152
		}
2 7u83 153
	}
6 7u83 154
	return (NULL_graph);
2 7u83 155
}
156
 
157
 
158
/*
159
    IS ONE GRAPH A SUBGRAPH OF ANOTHER?
160
 
161
    This routine checks whether the graph gs is a subgraph of gr (allowing
162
    for the identification of virtual bases).
163
*/
164
 
6 7u83 165
int
166
is_subgraph(GRAPH gr, GRAPH gs)
2 7u83 167
{
6 7u83 168
	unsigned nt, ns;
169
	CLASS_TYPE ct, cs;
170
	if (EQ_graph(gr, gs)) {
171
		return (1);
2 7u83 172
	}
6 7u83 173
	ct = DEREF_ctype(graph_head(gr));
174
	cs = DEREF_ctype(graph_head(gs));
175
	nt = DEREF_unsigned(ctype_no_bases(ct));
176
	ns = DEREF_unsigned(ctype_no_bases(cs));
177
	if (nt == ns) {
178
		/* Graphs are the same size */
179
		return (eq_graph(gr, gs));
180
	}
181
	if (nt > ns) {
182
		/* gr is bigger than gs */
183
		LIST(GRAPH)br = DEREF_list(graph_tails(gr));
184
		while (!IS_NULL_list(br)) {
185
			GRAPH gt = DEREF_graph(HEAD_list(br));
186
			if (is_subgraph(gt, gs)) {
187
				return (1);
188
			}
189
			br = TAIL_list(br);
190
		}
191
	}
192
	return (0);
2 7u83 193
}
194
 
195
 
196
/*
197
    COPY A GRAPH
198
 
199
    This routine recursively copies the graph gr into the base class graph
200
    of the current class, with access specifiers adjusted by acc and virtual
201
    specifier virt.  indir is true if the graph is a subgraph of a virtual
202
    base and templ is true if the graph represents a template parameter.
203
*/
204
 
6 7u83 205
static GRAPH
206
copy_graph(GRAPH gr, OFFSET off, DECL_SPEC acc, int virt, int indir, int templ)
2 7u83 207
{
6 7u83 208
	OFFSET offa;
209
	DECL_SPEC as;
210
	GRAPH gc, gp, gs;
211
	LIST(GRAPH)bs;
2 7u83 212
 
6 7u83 213
	/* Decompose head of graph */
214
	CLASS_TYPE ct = DEREF_ctype(graph_head(gr));
215
	LIST(GRAPH)bt = DEREF_list(graph_tails(gr));
2 7u83 216
 
6 7u83 217
	/* Adjust access specifiers */
218
	DECL_SPEC at = DEREF_dspec(graph_access(gr));
219
	as = join_access(at, acc);
220
	as |= shadow_access(at);
221
	if (at & dspec_virtual) {
222
		virt = 1;
223
	}
224
	if (virt) {
225
		/* Mark virtual bases */
226
		as |= dspec_virtual;
227
		indir = 1;
228
	}
229
	if (indir) {
230
		/* Mark indirect bases */
231
		as |= dspec_mutable;
232
	}
233
	if (templ) {
234
		/* Mark template parameter bases */
235
		as |= dspec_template;
236
	}
237
	as |= dspec_inherit;
238
	as &= ~dspec_done;
2 7u83 239
 
6 7u83 240
	/* Search existing graph for ct */
241
	gc = DEREF_graph(ctype_base(crt_class));
242
	gp = search_graph(gc, ct);
243
	if (IS_NULL_graph(gp)) {
244
		as |= dspec_defn;
245
	}
2 7u83 246
 
6 7u83 247
	/* Copy components */
248
	bs = NULL_list(GRAPH);
249
	while (!IS_NULL_list(bt)) {
250
		GRAPH gt = DEREF_graph(HEAD_list(bt));
251
		gt = copy_graph(gt, off, as, 0, indir, templ);
252
		CONS_graph(gt, bs, bs);
253
		bt = TAIL_list(bt);
254
	}
255
	bs = REVERSE_list(bs);
2 7u83 256
 
6 7u83 257
	/* Create new graph */
258
	MAKE_graph_basic(ct, as, gs);
259
	COPY_list(graph_tails(gs), bs);
260
	COPY_graph(graph_top(gs), gc);
2 7u83 261
 
6 7u83 262
	/* Set base offset */
263
	offa = DEREF_off(graph_off(gr));
264
	if (!IS_NULL_off(offa)) {
265
		MAKE_off_deriv(gs, off, offa, off);
266
	}
267
	COPY_off(graph_off(gs), off);
2 7u83 268
 
6 7u83 269
	/* Set up-field of bases */
270
	while (!IS_NULL_list(bs)) {
271
		GRAPH gt = DEREF_graph(HEAD_list(bs));
272
		COPY_graph(graph_up(gt), gs);
273
		bs = TAIL_list(bs);
274
	}
275
	return (gs);
2 7u83 276
}
277
 
278
 
279
/*
280
    FIND A COPY OF A SUBGRAPH
281
 
282
    Given a graph gs, a subgraph hs of gs, and a copy gr of gs (produced
283
    by copy_graph above), this routine returns the subgraph of gr which is
284
    the image of hs under this copy operation, i.e. it is the subgraph
285
    hr which makes the following diagram commutative:
286
 
287
				copy
288
			    gr ------ gs
289
			     |        |
290
			incl |        | incl
291
			     |        |
292
			    hr ------ hs
293
				copy
294
*/
295
 
6 7u83 296
GRAPH
297
find_subgraph(GRAPH gr, GRAPH gs, GRAPH hs)
2 7u83 298
{
6 7u83 299
	if (EQ_graph(gs, hs)) {
300
		return (gr);
2 7u83 301
	}
6 7u83 302
	if (!IS_NULL_graph(gr)) {
303
		LIST(GRAPH)br = DEREF_list(graph_tails(gr));
304
		LIST(GRAPH)bs = DEREF_list(graph_tails(gs));
305
		while (!IS_NULL_list(br)) {
306
			GRAPH ar = DEREF_graph(HEAD_list(br));
307
			GRAPH as = DEREF_graph(HEAD_list(bs));
308
			GRAPH hr = find_subgraph(ar, as, hs);
309
			if (!IS_NULL_graph(hr)) {
310
				return (hr);
311
			}
312
			br = TAIL_list(br);
313
			bs = TAIL_list(bs);
314
		}
315
	}
316
	return (NULL_graph);
2 7u83 317
}
318
 
319
 
320
/*
321
    IDENTIFY TWO GRAPHS
322
 
323
    This routine identifies the graph gs with the graph gr by linking
324
    them by means of their equal fields.
325
*/
326
 
6 7u83 327
static void
328
identify_graph(GRAPH gr, GRAPH gs)
2 7u83 329
{
6 7u83 330
	DECL_SPEC acc;
331
	LIST(GRAPH)br, bs;
332
	GRAPH gu = DEREF_graph(graph_equal(gs));
333
	while (!IS_NULL_graph(gu)) {
334
		gs = gu;
335
		gu = DEREF_graph(graph_equal(gs));
336
	}
337
	br = DEREF_list(graph_tails(gr));
338
	bs = DEREF_list(graph_tails(gs));
339
	while (!IS_NULL_list(br)) {
340
		GRAPH hr = DEREF_graph(HEAD_list(br));
341
		GRAPH hs = DEREF_graph(HEAD_list(bs));
342
		identify_graph(hr, hs);
343
		br = TAIL_list(br);
344
		bs = TAIL_list(bs);
345
	}
346
	COPY_graph(graph_equal(gs), gr);
347
	acc = DEREF_dspec(graph_access(gr));
348
	acc |= dspec_done;
349
	COPY_dspec(graph_access(gr), acc);
350
	return;
2 7u83 351
}
352
 
353
 
354
/*
355
    BASE CLASS INFORMATION
356
 
357
    The variable base_info holds information about the graph being analysed
358
    by fold_graph, for example, does it have a virtual or an ambiguous base
359
    class?
360
*/
361
 
6 7u83 362
static CLASS_INFO base_info = cinfo_none;
363
static LIST(GRAPH) virtual_bases = NULL_list(GRAPH);
2 7u83 364
 
365
 
366
/*
367
    FOLD A GRAPH
368
 
369
    This routine folds the graph gr by identifying all of its equal virtual
370
    bases.  It also defines values representing the offset of each base
371
    from the start of its class.  It returns a list of all the base classes
372
    in gr (allowing for virtual bases).  All bases added to the list are
373
    marked as explicit bases.
374
*/
375
 
6 7u83 376
static LIST(GRAPH)
377
fold_graph(GRAPH gr, LIST(GRAPH)br)
2 7u83 378
{
6 7u83 379
	CLASS_TYPE ct = DEREF_ctype(graph_head(gr));
380
	DECL_SPEC acc = DEREF_dspec(graph_access(gr));
2 7u83 381
 
6 7u83 382
	/* Scan for previous uses of this base */
383
	LIST(GRAPH)bs = br;
384
	while (!IS_NULL_list(bs)) {
385
		GRAPH gs = DEREF_graph(HEAD_list(bs));
386
		CLASS_TYPE cs = DEREF_ctype(graph_head(gs));
387
		if (eq_ctype(cs, ct)) {
388
			/* Duplicate base found */
389
			DECL_SPEC acs = DEREF_dspec(graph_access(gs));
390
			if ((acs & dspec_virtual) && (acc & dspec_virtual)) {
391
				/* Both bases are virtual */
392
				if (!eq_graph(gr, gs)) {
393
					/* Identify graphs if not already
394
					 * done */
395
					identify_graph(gr, gs);
396
				}
397
				/* Propagate ambiguous bases */
398
				if (acs & dspec_alias) {
399
					acc |= dspec_alias;
400
				} else if (acc & dspec_alias) {
401
					while (!IS_NULL_graph(gs)) {
402
						acs = DEREF_dspec(graph_access(gs));
403
						acs |= dspec_alias;
404
						COPY_dspec(graph_access(gs),
405
							   acs);
406
						gs = DEREF_graph(graph_equal(gs));
407
					}
408
				}
409
				acc |= dspec_done;
410
				COPY_dspec(graph_access(gr), acc);
411
				return (br);
412
			}
413
			/* Ambiguous base */
414
			base_info |= cinfo_ambiguous;
415
			acc |= dspec_alias;
416
			acs |= dspec_alias;
417
			COPY_dspec(graph_access(gs), acs);
2 7u83 418
		}
6 7u83 419
		bs = TAIL_list(bs);
2 7u83 420
	}
421
 
6 7u83 422
	/* Add base class to list */
423
	acc |= (dspec_main | dspec_done);
424
	COPY_dspec(graph_access(gr), acc);
425
	CONS_graph(gr, br, br);
2 7u83 426
 
6 7u83 427
	/* Fold subgraphs */
428
	bs = DEREF_list(graph_tails(gr));
429
	while (!IS_NULL_list(bs)) {
430
		GRAPH gs = DEREF_graph(HEAD_list(bs));
431
		br = fold_graph(gs, br);
432
		bs = TAIL_list(bs);
433
	}
2 7u83 434
 
6 7u83 435
	/* Build list of virtual classes */
436
	if (acc & dspec_virtual) {
437
		base_info |= cinfo_virtual_base;
438
		CONS_graph(gr, virtual_bases, virtual_bases);
439
	}
440
	return (br);
2 7u83 441
}
442
 
443
 
444
/*
445
    FIND A SINGLE INHERITANCE BASE CLASS
446
 
447
    This routine returns the single inheritance base class of gr or the
448
    null graph if there is no such base.  The single inheritance base
449
    is the first direct base, provided this is not virtual.  Derived
450
    classes are laid out so that their single inheritance base classes
451
    are at zero offset from the start of the class, thereby minimising
452
    the cost of a base class conversion.
453
*/
454
 
6 7u83 455
static GRAPH
456
find_first_base(GRAPH gr)
2 7u83 457
{
6 7u83 458
	LIST(GRAPH)br = DEREF_list(graph_tails(gr));
459
	if (!IS_NULL_list(br)) {
460
		GRAPH gs = DEREF_graph(HEAD_list(br));
461
		DECL_SPEC acc = DEREF_dspec(graph_access(gs));
462
		if (!(acc & dspec_virtual)) {
463
			return (gs);
464
		}
2 7u83 465
	}
6 7u83 466
	return (NULL_graph);
2 7u83 467
}
468
 
469
 
470
/*
471
    END BASE CLASS DEFINITIONS
472
 
473
    This routine is called after all the base classes of a class have been
474
    processed.  ok is false for an empty base class list.  The routine
475
    folds the base class graph of the current class and records the total
476
    number of bases.  It also initialises the virtual function table.
477
*/
478
 
6 7u83 479
void
480
end_base_class(CLASS_TYPE ct, int ok)
2 7u83 481
{
6 7u83 482
	if (!IS_NULL_ctype(ct)) {
483
		/* Scan for virtual bases */
484
		CLASS_INFO ci = DEREF_cinfo(ctype_info(ct));
485
		GRAPH gr = DEREF_graph(ctype_base(ct));
486
		LIST(GRAPH)bs = DEREF_list(graph_tails(gr));
487
		unsigned nd = LENGTH_list(bs);
488
		LIST(GRAPH)br = fold_graph(gr, NULL_list(GRAPH));
489
		unsigned nb = LENGTH_list(br);
490
		IGNORE check_value(OPT_VAL_base_classes,(ulong)(nb - 1));
491
		IGNORE check_value(OPT_VAL_direct_bases,(ulong)nd);
492
		COPY_unsigned(ctype_no_bases(ct), nb);
493
		while (!IS_NULL_list(br)) {
494
			GRAPH gs;
495
			nb--;
496
			DESTROY_CONS_graph(destroy, gs, br, br);
497
			do {
498
				COPY_unsigned(graph_no(gs), nb);
499
				gs = DEREF_graph(graph_equal(gs));
500
			} while (!IS_NULL_graph(gs));
501
		}
502
		br = REVERSE_list(virtual_bases);
503
		COPY_list(ctype_vbase(ct), br);
504
		nd = LENGTH_list(br);
505
		IGNORE check_value(OPT_VAL_virtual_bases,(ulong)nd);
506
		virtual_bases = NULL_list(GRAPH);
2 7u83 507
 
6 7u83 508
		/* Mark single inheritance bases */
509
		do {
510
			DECL_SPEC acc = DEREF_dspec(graph_access(gr));
511
			acc |= dspec_ignore;
512
			COPY_dspec(graph_access(gr), acc);
513
			gr = find_first_base(gr);
514
		} while (!IS_NULL_graph(gr));
2 7u83 515
 
6 7u83 516
		/* Set up base class namespaces */
517
		while (!IS_NULL_list(bs)) {
518
			GRAPH gs = DEREF_graph(HEAD_list(bs));
519
			CLASS_TYPE cs = DEREF_ctype(graph_head(gs));
520
			NAMESPACE ns = DEREF_nspace(ctype_member(cs));
521
			NAMESPACE nt = DEREF_nspace(ctype_member(ct));
522
			IGNORE use_namespace(ns, nt, nt);
523
			uncache_namespace(ns, 0);
524
			bs = TAIL_list(bs);
525
		}
2 7u83 526
 
6 7u83 527
		/* Record class information */
528
		if (!ok) {
529
			report(crt_loc, ERR_class_derived_empty(ct));
530
		}
531
		ci |= base_info;
532
		COPY_cinfo(ctype_info(ct), ci);
533
		base_info = cinfo_none;
534
		if (do_dump) {
535
			dump_base(ct);
536
		}
2 7u83 537
 
6 7u83 538
		/* Set up virtual function table */
539
		begin_virtual(ct);
540
	}
541
	return;
2 7u83 542
}
543
 
544
 
545
/*
546
    ADD A BASE CLASS TO A CLASS DEFINITION
547
 
548
    This routine adds a base class bid with access specifier acc to the
549
    current class.  virt is true to indicate a virtual base class.
550
*/
551
 
6 7u83 552
void
553
add_base_class(IDENTIFIER bid, DECL_SPEC acc, int virt)
2 7u83 554
{
6 7u83 555
	GRAPH gt;
556
	int ok = 1;
557
	CLASS_INFO cj;
558
	int templ = 0;
559
	LIST(GRAPH)bt;
560
	TYPE s = NULL_type;
561
	CLASS_TYPE cs = NULL_ctype;
2 7u83 562
 
6 7u83 563
	/* Examine the derived class */
564
	CLASS_TYPE ct = crt_class;
565
	CLASS_INFO ci = DEREF_cinfo(ctype_info(ct));
566
	if (ci & cinfo_union) {
567
		/* Derived class can't be a union */
568
		report(crt_loc, ERR_class_union_deriv(ct));
569
		ok = 0;
570
	}
2 7u83 571
 
6 7u83 572
	/* Examine the base class */
573
	if (IS_id_class_name_etc(bid)) {
574
		s = DEREF_type(id_class_name_etc_defn(bid));
2 7u83 575
	} else {
6 7u83 576
		IDENTIFIER tid;
577
		HASHID bnm = DEREF_hashid(id_name(bid));
578
		if (crt_id_qualifier == qual_none) {
579
			tid = find_type_id(bnm, 1);
580
		} else {
581
			NAMESPACE bns = DEREF_nspace(id_parent(bid));
582
			tid = find_qual_id(bns, bnm, 0, 1);
583
			if (IS_NULL_id(tid)) {
584
				/* Allow for implicit typename */
585
				s = check_typename(bns, bid, btype_class);
586
			}
587
		}
588
		if (!IS_NULL_id(tid)) {
589
			if (IS_id_ambig(tid)) {
590
				tid = report_ambiguous(tid, 0, 1, 1);
591
			}
592
			if (IS_id_class_name_etc(tid)) {
593
				s = DEREF_type(id_class_name_etc_defn(tid));
594
				bid = tid;
595
			}
596
		}
2 7u83 597
	}
6 7u83 598
	if (!IS_NULL_type(s)) {
599
		/* Declared base type */
600
		s = expand_type(s, 2);
601
		if (IS_type_compound(s)) {
602
			cs = DEREF_ctype(type_compound_defn(s));
603
		} else if (IS_type_token(s)) {
604
			/* Allow for template parameters */
605
			IDENTIFIER pid = DEREF_id(type_token_tok(s));
606
			cs = find_class(pid);
607
			templ = 1;
608
		}
609
		if (IS_NULL_ctype(cs)) {
610
			/* Inappropriate base class type */
611
			if (!IS_type_error(s)) {
612
				report(crt_loc, ERR_class_derived_class(s));
613
			}
614
			ok = 0;
615
		} else {
616
			/* Examine base class type */
617
			bid = DEREF_id(ctype_name(cs));
618
			cj = DEREF_cinfo(ctype_info(cs));
619
			if (cj & cinfo_union) {
620
				/* Base class can't be a union */
621
				report(crt_loc, ERR_class_union_base(cs));
622
				ok = 0;
623
			} else {
624
				/* Base class must be complete */
625
				ERROR err = check_incomplete(s);
626
				if (!IS_NULL_err(err)) {
627
					ERROR err2 =
628
					    ERR_class_derived_incompl();
629
					err = concat_error(err, err2);
630
					report(crt_loc, err);
631
					ok = 0;
632
				}
633
			}
634
		}
2 7u83 635
	} else {
6 7u83 636
		/* Undeclared base type */
637
		report(crt_loc, ERR_dcl_type_simple_undef(bid));
638
		ok = 0;
2 7u83 639
	}
640
 
6 7u83 641
	/* Check the access specifier */
642
	if (acc == dspec_none) {
643
		/* No access specifier given */
644
		acc = crt_access;
645
		if (acc != prev_access) {
646
			/* Warn about 'class C : public A, B' */
647
			report(crt_loc, ERR_class_access_base_acc(bid, acc));
648
		}
2 7u83 649
	}
6 7u83 650
	prev_access = acc;
651
	if (virt) {
652
		prev_access |= dspec_virtual;
2 7u83 653
	}
654
 
6 7u83 655
	/* Check for duplicate base classes */
656
	gt = DEREF_graph(ctype_base(ct));
657
	if (ok) {
658
		bt = DEREF_list(graph_tails(gt));
659
		while (!IS_NULL_list(bt)) {
660
			GRAPH gu = DEREF_graph(HEAD_list(bt));
661
			CLASS_TYPE cu = DEREF_ctype(graph_head(gu));
662
			if (eq_ctype(cs, cu)) {
663
				report(crt_loc, ERR_class_mi_dup(ct, cs));
664
				ok = 0;
665
				break;
666
			}
667
			bt = TAIL_list(bt);
668
		}
2 7u83 669
	}
670
 
6 7u83 671
	/* Add base class to graph */
672
	if (ok) {
673
		OFFSET off;
674
		LIST(GRAPH)bs = NULL_list(GRAPH);
675
		GRAPH gs = DEREF_graph(ctype_base(cs));
676
		MAKE_off_base(gs, off);
677
		gs = copy_graph(gs, off, acc, virt, virt, templ);
678
		COPY_graph(off_base_graph(off), gs);
679
		COPY_graph(graph_up(gs), gt);
680
		CONS_graph(gs, bs, bs);
681
		bt = DEREF_list(graph_tails(gt));
682
		if (!IS_NULL_list(bt)) {
683
			/* Mark multiple inheritance */
684
			ci |= cinfo_multiple_base;
685
		}
686
		bt = APPEND_list(bt, bs);
687
		COPY_list(graph_tails(gt), bt);
2 7u83 688
 
6 7u83 689
		/* Adjust class information */
690
		cj = DEREF_cinfo(ctype_info(cs));
691
		ci = check_class_info(ci, cj, 1, acc);
692
		COPY_cinfo(ctype_info(ct), ci);
693
 
694
		/* Use class name */
695
		use_id(bid, 0);
696
	}
697
	return;
2 7u83 698
}
699
 
700
 
701
/*
702
    FIND A BASE CLASS
703
 
704
    This routine finds whether cs is a base class of ct, returning the
705
    corresponding node of the base class graph, or the null graph.  The
706
    first guess is based on the fact that if cs is a base class of ct
707
    then ct has at least as many base classes as cs.   The way to remember
708
    which way round the arguments go is that 'find_base_class ( ct, cs )'
709
    checks for 'class ct : public cs {}'.  If ct is a template class
710
    then def indicates whether this operation implies that ct should
711
    be defined (not properly implemented yet).
712
*/
713
 
6 7u83 714
GRAPH
715
find_base_class(CLASS_TYPE ct, CLASS_TYPE cs, int def)
2 7u83 716
{
6 7u83 717
	unsigned nt, ns;
718
	complete_class(ct, 1);
719
	nt = DEREF_unsigned(ctype_no_bases(ct));
720
	ns = DEREF_unsigned(ctype_no_bases(cs));
721
	if (nt >= ns) {
722
		/* ct is bigger than cs */
723
		GRAPH gr = DEREF_graph(ctype_base(ct));
724
		return (search_graph(gr, cs));
725
	}
726
	UNUSED(def);
727
	return (NULL_graph);
2 7u83 728
}
729
 
730
 
731
/*
732
    COMPARE TWO CLASSES
733
 
734
    This routine finds whether cs is a base class of ct, or ct is a base
735
    class of cs.  It returns whichever class is the base class, or the null
736
    class if the two classes are not so related.  The first guess is based
737
    on the relative numbers of base classes of each type.  def is as in
738
    find_base_class.
739
*/
740
 
6 7u83 741
CLASS_TYPE
742
compare_base_class(CLASS_TYPE ct, CLASS_TYPE cs, int def)
2 7u83 743
{
6 7u83 744
	unsigned nt, ns;
745
	complete_class(ct, 1);
746
	complete_class(cs, 1);
747
	nt = DEREF_unsigned(ctype_no_bases(ct));
748
	ns = DEREF_unsigned(ctype_no_bases(cs));
749
	if (nt >= ns) {
750
		/* ct is bigger than cs */
751
		GRAPH gr = DEREF_graph(ctype_base(ct));
752
		gr = search_graph(gr, cs);
753
		if (!IS_NULL_graph(gr)) {
754
			return (cs);
755
		}
756
	} else {
757
		/* ct is smaller than cs */
758
		GRAPH gr = DEREF_graph(ctype_base(cs));
759
		gr = search_graph(gr, ct);
760
		if (!IS_NULL_graph(gr)) {
761
			return (ct);
762
		}
763
	}
764
	UNUSED(def);
765
	return (NULL_ctype);
2 7u83 766
}
767
 
768
 
769
/*
770
    CHECK AN AMBIGUOUS BASE CLASS
771
 
772
    This routine checks whether the base class corresponding to the node
773
    gr is ambiguous.  It returns a suitable error message.
774
*/
775
 
6 7u83 776
ERROR
777
check_ambig_base(GRAPH gr)
2 7u83 778
{
6 7u83 779
    if (!IS_NULL_graph(gr)) {
780
	DECL_SPEC acc = DEREF_dspec(graph_access(gr));
781
	if (acc & dspec_alias) {
2 7u83 782
	    /* Ambiguous base class */
6 7u83 783
	    GRAPH gt = DEREF_graph(graph_top(gr));
784
	    CLASS_TYPE ct = DEREF_ctype(graph_head(gt));
785
	    CLASS_TYPE cs = DEREF_ctype(graph_head(gr));
786
	    ERROR err = ERR_class_member_lookup_ambig(cs, ct);
787
	    return (err);
2 7u83 788
	}
789
    }
6 7u83 790
    return (NULL_err);
2 7u83 791
}
792
 
793
 
794
/*
795
    CHECK A VIRTUAL BASE CLASS
796
 
797
    This routine checks whether the base class corresponding to the node
798
    gr is a virtual base of a base class of a virtual base.  It returns a
799
    suitable error message.
800
*/
801
 
6 7u83 802
ERROR
803
check_virt_base(GRAPH gr)
2 7u83 804
{
6 7u83 805
	if (!IS_NULL_graph(gr)) {
806
		DECL_SPEC acc = DEREF_dspec(graph_access(gr));
807
		if (acc & dspec_mutable) {
808
			/* Virtual base class */
809
			GRAPH gt = DEREF_graph(graph_top(gr));
810
			CLASS_TYPE ct = DEREF_ctype(graph_head(gt));
811
			CLASS_TYPE cs = DEREF_ctype(graph_head(gr));
812
			ERROR err = ERR_class_derived_virt(cs, ct);
813
			return (err);
814
		}
2 7u83 815
	}
6 7u83 816
	return (NULL_err);
2 7u83 817
}
818
 
819
 
820
/*
821
    FIND A UNIQUE BASE CLASS
822
 
823
    This routine returns the graph representing the unique direct base
824
    class of ct if this exists.  Otherwise it adds an error to err and
825
    returns the null graph.
826
*/
827
 
6 7u83 828
GRAPH
829
uniq_base_class(CLASS_TYPE ct, ERROR *err)
2 7u83 830
{
6 7u83 831
	GRAPH gr = DEREF_graph(ctype_base(ct));
832
	LIST(GRAPH)br = DEREF_list(graph_tails(gr));
833
	if (LENGTH_list(br) == 1) {
834
		GRAPH gs = DEREF_graph(HEAD_list(br));
835
		return (gs);
836
	}
837
	add_error(err, ERR_class_base_init_uniq(ct));
838
	return (NULL_graph);
2 7u83 839
}
840
 
841
 
842
/*
843
    FIND THE SHORTEST ROUTE TO A BASE CLASS
844
 
845
    There may be several path for accessing a virtual base class.  This
846
    routine finds the shortest such path in terms of virtual base
847
    indirections for reaching the base gr.
848
*/
849
 
6 7u83 850
GRAPH
851
min_base_class(GRAPH gr)
2 7u83 852
{
6 7u83 853
	GRAPH gs = gr;
854
	unsigned n = (unsigned)UINT_MAX;
855
	while (!IS_NULL_graph(gs)) {
856
		GRAPH gt = gs;
857
		unsigned m = 0;
858
		while (!IS_NULL_graph(gt)) {
859
			/* Find base class depth */
860
			DECL_SPEC acc = DEREF_dspec(graph_access(gt));
861
			if (acc & dspec_virtual) {
862
				m++;
863
			}
864
			gt = DEREF_graph(graph_up(gt));
865
		}
866
		if (m < n) {
867
			/* Shortest path so far */
868
			gr = gs;
869
			n = m;
870
		}
871
		gs = DEREF_graph(graph_equal(gs));
2 7u83 872
	}
6 7u83 873
	return (gr);
2 7u83 874
}
875
 
876
 
877
/*
878
    FIND A DIRECT OR VIRTUAL BASE CLASS
879
 
880
    This routine checks whether the class cs denotes a direct or a virtual
881
    base class of ct.  If so it returns the corresponding graph.  If it is
882
    both then an error is added to err and the direct base is returned.
883
    Otherwise an error is added to err and the null graph is returned.
884
*/
885
 
6 7u83 886
GRAPH
887
direct_base_class(CLASS_TYPE ct, CLASS_TYPE cs, ERROR *err)
2 7u83 888
{
6 7u83 889
	GRAPH gt = NULL_graph;
890
	GRAPH gr = DEREF_graph(ctype_base(ct));
891
	LIST(GRAPH)bd = DEREF_list(graph_tails(gr));
892
	LIST(GRAPH)bv = DEREF_list(ctype_vbase(ct));
2 7u83 893
 
6 7u83 894
	/* Scan through direct base classes */
895
	while (!IS_NULL_list(bd)) {
896
		GRAPH gs = DEREF_graph(HEAD_list(bd));
897
		CLASS_TYPE cr = DEREF_ctype(graph_head(gs));
898
		if (eq_ctype(cr, cs)) {
899
			gt = gs;
900
			break;
901
		}
902
		bd = TAIL_list(bd);
2 7u83 903
	}
904
 
6 7u83 905
	/* Scan through virtual base classes */
906
	while (!IS_NULL_list(bv)) {
907
		GRAPH gs = DEREF_graph(HEAD_list(bv));
908
		CLASS_TYPE cr = DEREF_ctype(graph_head(gs));
909
		if (eq_ctype(cr, cs)) {
910
			if (IS_NULL_graph(gt)) {
911
				gt = gs;
912
			} else if (!eq_graph(gt, gs)) {
913
				/* Both a direct and a virtual base */
914
				add_error(err, ERR_class_base_init_ambig(cs));
915
			}
916
			break;
917
		}
918
		bv = TAIL_list(bv);
2 7u83 919
	}
920
 
6 7u83 921
	/* Return result */
922
	if (IS_NULL_graph(gt)) {
923
		/* Neither a direct nor a virtual base */
924
		add_error(err, ERR_class_base_init_base(cs));
925
	}
926
	return (gt);
2 7u83 927
}
928
 
929
 
930
/*
931
    FIND AN AMBIGUOUS BASE CLASS
932
 
933
    This routine searches the graph gr for any ambiguous base class,
934
    returning the corresponding node if it is found, or the null graph
935
    otherwise.
936
*/
937
 
6 7u83 938
GRAPH
939
find_ambig_base(GRAPH gr)
2 7u83 940
{
6 7u83 941
	DECL_SPEC acc = DEREF_dspec(graph_access(gr));
942
	if (acc & dspec_alias) {
943
		/* Ambiguous classes are marked */
944
		return (gr);
2 7u83 945
	}
6 7u83 946
	if (acc & dspec_defn) {
947
		/* Only search the first occurrence of each class */
948
		LIST(GRAPH)br = DEREF_list(graph_tails(gr));
949
		while (!IS_NULL_list(br)) {
950
			GRAPH gs = DEREF_graph(HEAD_list(br));
951
			gs = find_ambig_base(gs);
952
			if (!IS_NULL_graph(gs)) {
953
				return (gs);
954
			}
955
			br = TAIL_list(br);
956
		}
957
	}
958
	return (NULL_graph);
2 7u83 959
}
960
 
961
 
962
/*
963
    EXPAND A BASE CLASS GRAPH
964
 
965
    This routine expands any token definitions in the base class graph
966
    gr.  The null graph is returned if the result is not a valid base
967
    class.
968
*/
969
 
6 7u83 970
GRAPH
971
expand_graph(GRAPH gr, int rec)
2 7u83 972
{
6 7u83 973
	if (!IS_NULL_graph(gr)) {
974
		TYPE t = NULL_type;
975
		GRAPH gt = DEREF_graph(graph_top(gr));
976
		CLASS_TYPE ct = DEREF_ctype(graph_head(gt));
977
		CLASS_TYPE cs = DEREF_ctype(graph_head(gr));
978
		ct = expand_ctype(ct, rec, &t);
979
		if (IS_NULL_ctype(ct)) {
980
			return (NULL_graph);
981
		}
982
		cs = expand_ctype(cs, rec, &t);
983
		if (IS_NULL_ctype(cs)) {
984
			return (NULL_graph);
985
		}
986
		gr = find_base_class(ct, cs, 1);
987
	}
988
	return (gr);
2 7u83 989
}
990
 
991
 
992
/*
993
    CONSTRUCT AN INHERITED IDENTIFIER
994
 
995
    This routine constructs an identifier representing the inherited value
996
    of id in the namespace ns.  gr and off give the corresponding base class
997
    if appropriate.
998
*/
999
 
6 7u83 1000
static IDENTIFIER
1001
inherit_id(NAMESPACE ns, GRAPH gr, OFFSET off, IDENTIFIER id, int prev)
2 7u83 1002
{
6 7u83 1003
	HASHID nm;
1004
	DECL_SPEC ds;
1005
	unsigned tag;
1006
	NAMESPACE pns;
1007
	IDENTIFIER cid;
1008
	LIST(IDENTIFIER)p = NULL_list(IDENTIFIER);
2 7u83 1009
 
6 7u83 1010
	/* Check for trivial inheritance */
1011
	if (IS_NULL_id(id)) {
1012
		return (NULL_id);
1013
	}
1014
	pns = DEREF_nspace(id_parent(id));
1015
	if (EQ_nspace(pns, ns)) {
1016
		return (id);
1017
	}
2 7u83 1018
 
6 7u83 1019
	/* Check for previous declarations */
1020
	tag = TAG_id(id);
1021
	nm = DEREF_hashid(id_name(id));
1022
	if (!IS_NULL_graph(gr) && !prev) {
1023
		LIST(IDENTIFIER)q;
1024
		p = DEREF_list(graph_member(gr));
1025
		q = p;
1026
		while (!IS_NULL_list(q)) {
1027
			IDENTIFIER qid = DEREF_id(HEAD_list(q));
1028
			HASHID qnm = DEREF_hashid(id_name(qid));
1029
			if (EQ_hashid(qnm, nm) && tag == TAG_id(qid)) {
1030
				/* Already have inherited member */
1031
				return (qid);
1032
			}
1033
			q = TAIL_list(q);
1034
		}
2 7u83 1035
	}
1036
 
6 7u83 1037
	/* Calculate inherited access */
1038
	ds = DEREF_dspec(id_storage(id));
1039
	if (!IS_NULL_graph(gr)) {
1040
		int adjust = 1;
1041
		if (tag == id_class_name_tag) {
1042
			CLASS_TYPE cs = DEREF_ctype(graph_head(gr));
1043
			TYPE t = DEREF_type(id_class_name_defn(id));
1044
			if (IS_type_compound(t)) {
1045
				CLASS_TYPE ct =
1046
				    DEREF_ctype(type_compound_defn(t));
1047
				if (eq_ctype(cs, ct)) {
1048
					/* This is an injected base class
1049
					 * name */
1050
					adjust = 0;
1051
				}
1052
			}
2 7u83 1053
		}
6 7u83 1054
		if (adjust) {
1055
			DECL_SPEC acc = DEREF_dspec(graph_access(gr));
1056
			DECL_SPEC acc2 = unshadow_access(acc);
1057
			acc = join_access(ds, acc);
1058
			acc2 = join_access(ds, acc2);
1059
			ds &= ~(dspec_access | dspec_access2);
1060
			ds |= acc;
1061
			ds |= shadow_access(acc2);
1062
		}
2 7u83 1063
	}
6 7u83 1064
	ds |= dspec_inherit;
1065
	ds &= ~dspec_alias;
2 7u83 1066
 
6 7u83 1067
	/* Copy the identifier */
1068
	cid = copy_id(id, 0);
1069
	if (!EQ_id(cid, id)) {
1070
		switch (tag) {
1071
		case id_function_tag:
1072
		case id_mem_func_tag:
1073
		case id_stat_mem_func_tag: {
1074
			/* Functions */
1075
			IDENTIFIER over;
1076
			over = DEREF_id(id_function_etc_over(cid));
1077
			if (!IS_NULL_id(over)) {
1078
				/* Overloaded functions */
1079
				over = inherit_id(ns, gr, off, over, 1);
1080
				COPY_id(id_function_etc_over(cid), over);
1081
			}
1082
			break;
2 7u83 1083
		}
6 7u83 1084
		case id_member_tag: {
1085
			/* Members */
1086
			if (!IS_NULL_graph(gr)) {
1087
				/* Add base class offset */
1088
				OFFSET off1 = DEREF_off(id_member_off(cid));
1089
				MAKE_off_plus(off, off1, off1);
1090
				COPY_off(id_member_off(cid), off1);
1091
				COPY_graph(id_member_base(cid), gr);
1092
			}
1093
			break;
2 7u83 1094
		}
6 7u83 1095
		}
1096
		COPY_nspace(id_parent(cid), ns);
1097
		COPY_dspec(id_storage(cid), ds);
2 7u83 1098
	}
1099
 
6 7u83 1100
	/* Add to list of inherited members */
1101
	if (!IS_NULL_graph(gr) && !prev) {
1102
		CONS_id(cid, p, p);
1103
		COPY_list(graph_member(gr), p);
1104
	}
1105
	return (cid);
2 7u83 1106
}
1107
 
1108
 
1109
/*
1110
    TYPE REPRESENTING A SET OF MEMBER LOOK-UPS
1111
 
1112
    This structure is used to represent a list of class member look-ups.
1113
    Each look-up consists of a member identifier plus a base class graph
1114
    indicating from which base class it is inherited.
1115
*/
1116
 
1117
typedef struct {
6 7u83 1118
	LIST(IDENTIFIER) ids;
1119
	LIST(GRAPH) bases;
1120
} MEMBER_LOOKUP;
2 7u83 1121
 
1122
 
1123
/*
1124
    RESOLVE AMBIGUOUS MEMBER LOOK-UP
1125
 
1126
    This routine resolves the potentially ambiguous member look-up for the
1127
    member named nm in the namespace ns given by mems.  If form is not
1128
    the null type then it gives a list of template arguments to be
1129
    applied to nm.  The routine also destroys mems.
1130
*/
1131
 
6 7u83 1132
static IDENTIFIER
1133
resolve_member(NAMESPACE ns, HASHID nm, MEMBER_LOOKUP *mems, TYPE form,
1134
	       int dominate)
2 7u83 1135
{
6 7u83 1136
	IDENTIFIER id = NULL_id;
1137
	LIST(IDENTIFIER)ambig = NULL_list(IDENTIFIER);
1138
	LIST(IDENTIFIER)pids = mems->ids;
1139
	LIST(GRAPH)grs = mems->bases;
2 7u83 1140
 
6 7u83 1141
	/* Check for empty lists */
1142
	if (IS_NULL_list(pids)) {
1143
		return (NULL_id);
1144
	}
2 7u83 1145
 
6 7u83 1146
	/* Scan through various look-ups */
1147
	while (!IS_NULL_list(pids)) {
1148
		IDENTIFIER pid = DEREF_id(HEAD_list(pids));
1149
		GRAPH gp = DEREF_graph(HEAD_list(grs));
1150
		if (!IS_NULL_id(pid)) {
1151
			int ok = 1;
1152
			int dep = IS_id_member(pid);
1153
			IDENTIFIER pal = DEREF_id(id_alias(pid));
1154
			DECL_SPEC pds = DEREF_dspec(id_storage(pid));
1155
			DECL_SPEC gds = DEREF_dspec(graph_access(gp));
1156
			DECL_SPEC acc = join_access(pds, gds);
1157
			OFFSET off = DEREF_off(graph_off(gp));
2 7u83 1158
 
6 7u83 1159
			/* Mark equivalent look-ups */
1160
			LIST(IDENTIFIER)qids = TAIL_list(pids);
1161
			LIST(GRAPH)hrs = TAIL_list(grs);
1162
			while (!IS_NULL_list(qids)) {
1163
				IDENTIFIER qid = DEREF_id(HEAD_list(qids));
1164
				IDENTIFIER qal = DEREF_id(id_alias(qid));
1165
				GRAPH hp = DEREF_graph(HEAD_list(hrs));
1166
				if (EQ_id(pal, qal)) {
1167
					if (!dep || eq_graph(gp, hp)) {
1168
						/* This represents the same
1169
						 * member */
1170
						DECL_SPEC acc2;
1171
						COPY_id(HEAD_list(qids),
1172
							NULL_id);
1173
						pds = DEREF_dspec(id_storage(qid));
1174
						gds = DEREF_dspec(graph_access(hp));
1175
						acc2 = join_access(pds, gds);
1176
						if (acc2 < acc) {
1177
							/* More accessible by
1178
							 * this route */
1179
							gp = hp;
1180
							acc = acc2;
1181
						}
1182
					}
1183
				} else {
1184
					/* Check for dominating bases */
1185
					if (is_subgraph(gp, hp)) {
1186
						if (dominate) {
1187
							COPY_id(HEAD_list(qids),
1188
								NULL_id);
1189
						}
1190
					} else if (is_subgraph(hp, gp)) {
1191
						ok = 0;
1192
						break;
1193
					}
1194
				}
1195
				qids = TAIL_list(qids);
1196
				hrs = TAIL_list(hrs);
2 7u83 1197
			}
6 7u83 1198
 
1199
			/* Record look-up */
1200
			if (ok) {
1201
				int prev = 0;
1202
				if (!IS_NULL_type(form) &&
1203
				    IS_type_token(form)) {
1204
					/* Allow for templates */
1205
					LIST(TOKEN)args;
1206
					args =
1207
					    DEREF_list(type_token_args(form));
1208
					pid = apply_template(pid, args, 0, 0);
1209
					prev = 1;
1210
				}
1211
				pid = inherit_id(ns, gp, off, pid, prev);
1212
				if (IS_NULL_id(id)) {
1213
					id = pid;
1214
				} else {
1215
					CONS_id(pid, ambig, ambig);
1216
				}
2 7u83 1217
			}
1218
		}
6 7u83 1219
		pids = TAIL_list(pids);
1220
		grs = TAIL_list(grs);
1221
	}
2 7u83 1222
 
6 7u83 1223
	/* Construct the result */
1224
	if (!IS_NULL_list(ambig)) {
1225
		DECL_SPEC ds;
1226
		CONS_id(id, ambig, ambig);
1227
		ds = find_ambig_dspec(ambig);
1228
		ds |= dspec_inherit;
1229
		MAKE_id_ambig(nm, ds, ns, crt_loc, ambig, 1, id);
2 7u83 1230
	}
1231
 
6 7u83 1232
	/* Destroy lists */
1233
	DESTROY_list(mems->ids, SIZE_id);
1234
	DESTROY_list(mems->bases, SIZE_graph);
1235
	return (id);
2 7u83 1236
}
1237
 
1238
 
1239
/*
1240
    SEARCH A BASE CLASS GRAPH FOR AN IDENTIFIER
1241
 
1242
    This routine searches the graph gr for all visible members named nm,
1243
    storing the result in mems.  If cs is not the null class then only
1244
    base classes lying below such a class are searched.  If type is nonzero
1245
    then only type members are found.  depth gives a depth count and is
1246
    used because the top level is searched elsewhere.
1247
*/
1248
 
6 7u83 1249
static void
1250
search_base(GRAPH gr, HASHID nm, MEMBER_LOOKUP *mems, CLASS_TYPE cs, int type,
1251
	    int depth)
2 7u83 1252
{
6 7u83 1253
	LIST(GRAPH)br;
1254
	LIST(GRAPH)gres = NULL_list(GRAPH);
1255
	LIST(IDENTIFIER)res = NULL_list(IDENTIFIER);
1256
	DECL_SPEC acc = DEREF_dspec(graph_access(gr));
1257
	if (!(acc & dspec_done)) {
1258
		/* Not yet in scope */
1259
		mems->ids = res;
1260
		mems->bases = gres;
1261
		return;
1262
	}
2 7u83 1263
 
6 7u83 1264
	/* Search derived class */
1265
	if (depth) {
1266
		CLASS_TYPE ct = DEREF_ctype(graph_head(gr));
1267
		if (IS_NULL_ctype(cs) || eq_ctype(ct, cs)) {
1268
			NAMESPACE ns = DEREF_nspace(ctype_member(ct));
1269
			IDENTIFIER id = search_id(ns, nm, 0, type);
1270
			if (!IS_NULL_id(id)) {
1271
				DECL_SPEC ds = DEREF_dspec(id_storage(id));
1272
				if ((ds & dspec_inherit) &&
1273
				    !(ds & dspec_alias)) {
1274
					/* Ignore inherited members */
1275
					/* EMPTY */
1276
				} else {
1277
					CONS_id(id, res, res);
1278
					CONS_graph(gr, gres, gres);
1279
					mems->ids = res;
1280
					mems->bases = gres;
1281
					return;
1282
				}
1283
			}
1284
			cs = NULL_ctype;
2 7u83 1285
		}
1286
	}
1287
 
6 7u83 1288
	/* Search base classes */
1289
	br = DEREF_list(graph_tails(gr));
1290
	while (!IS_NULL_list(br)) {
1291
		MEMBER_LOOKUP bmems;
1292
		GRAPH gs = DEREF_graph(HEAD_list(br));
1293
		search_base(gs, nm, &bmems, cs, type, depth + 1);
1294
		if (!IS_NULL_list(bmems.ids)) {
1295
			res = APPEND_list(res, bmems.ids);
1296
			gres = APPEND_list(gres, bmems.bases);
1297
		}
1298
		br = TAIL_list(br);
2 7u83 1299
	}
6 7u83 1300
	mems->ids = res;
1301
	mems->bases = gres;
1302
	return;
2 7u83 1303
}
1304
 
1305
 
1306
/*
1307
    SEARCH BASE CLASSES FOR A CLASS MEMBER
1308
 
1309
    This routine searches the base classes of the class namespace ns
1310
    for a member named nm.
1311
*/
1312
 
6 7u83 1313
IDENTIFIER
1314
search_base_field(NAMESPACE ns, HASHID nm, int type, int dominate)
2 7u83 1315
{
6 7u83 1316
	GRAPH gr;
1317
	IDENTIFIER id;
1318
	CLASS_TYPE ct;
1319
	MEMBER_LOOKUP mems;
1320
	IDENTIFIER cid = DEREF_id(nspace_name(ns));
1321
	TYPE t = DEREF_type(id_class_name_etc_defn(cid));
1322
	while (IS_type_templ(t)) {
1323
		t = DEREF_type(type_templ_defn(t));
1324
	}
1325
	ct = DEREF_ctype(type_compound_defn(t));
1326
	gr = DEREF_graph(ctype_base(ct));
1327
	search_base(gr, nm, &mems, NULL_ctype, type, 0);
1328
	id = resolve_member(ns, nm, &mems, NULL_type, dominate);
1329
	return (id);
2 7u83 1330
}
1331
 
1332
 
1333
/*
1334
    SEARCH FOR A CLASS MEMBER
1335
 
1336
    This routine searches the class namespace ns and its base classes
1337
    for a member named nm, which is returned if found.  Otherwise if
1338
    create is true then a dummy identifier is created and returned.
1339
    Otherwise the null identifier is returned.  If type is true then only
1340
    type and namespace names are considered.
1341
*/
1342
 
6 7u83 1343
IDENTIFIER
1344
search_field(NAMESPACE ns, HASHID nm, int create, int type)
2 7u83 1345
{
6 7u83 1346
	/* Search main class */
1347
	IDENTIFIER id;
1348
	MEMBER mem = search_member(ns, nm, 1);
1349
	if (type) {
1350
		id = type_member(mem, type);
1351
	} else {
1352
		id = DEREF_id(member_id(mem));
1353
	}
2 7u83 1354
 
6 7u83 1355
	/* Search base classes */
1356
	if (IS_NULL_id(id)) {
1357
		id = search_base_field(ns, nm, type, 1);
1358
		if (!IS_NULL_id(id)) {
1359
			if (type) {
1360
				set_type_member(mem, id);
1361
			} else {
1362
				set_member(mem, id);
1363
			}
1364
			if (IS_hashid_destr(nm)) {
1365
				/* Check destructor names */
1366
				report(crt_loc, ERR_class_dtor_inherit(nm, ns));
1367
			}
1368
		} else {
1369
			if (create) {
1370
				/* Create dummy identifier if necessary */
1371
				MAKE_id_undef(nm, dspec_none, ns, crt_loc, id);
1372
			}
1373
			if (IS_hashid_destr(nm)) {
1374
				/* Check destructor names */
1375
				TYPE s = DEREF_type(hashid_destr_type(nm));
1376
				IDENTIFIER tid = DEREF_id(nspace_name(ns));
1377
				TYPE t =
1378
				    DEREF_type(id_class_name_etc_defn(tid));
1379
				if (!eq_type(s, t)) {
1380
					report(crt_loc,
1381
					       ERR_expr_pseudo_type(t, s));
1382
				}
1383
			}
2 7u83 1384
		}
1385
	}
6 7u83 1386
	return (id);
2 7u83 1387
}
1388
 
1389
 
1390
/*
1391
    IS AN IDENTIFIER A MEMBER OF A CLASS?
1392
 
1393
    This routine checks whether the identifier id is a member of the class
1394
    namespace ns or any base class of ns.  It returns the corresponding
1395
    base class graph, or the null graph if id is not such a member.
1396
*/
1397
 
6 7u83 1398
GRAPH
1399
is_subfield(NAMESPACE ns, IDENTIFIER id)
2 7u83 1400
{
6 7u83 1401
	CLASS_TYPE ct = namespace_class(ns);
1402
	if (!IS_NULL_ctype(ct)) {
1403
		NAMESPACE cns = DEREF_nspace(id_parent(id));
1404
		if (!IS_NULL_nspace(cns) && IS_nspace_ctype(cns)) {
1405
			CLASS_TYPE cs = namespace_class(cns);
1406
			GRAPH gr = find_base_class(ct, cs, 0);
1407
			return (gr);
1408
		}
2 7u83 1409
	}
6 7u83 1410
	return (NULL_graph);
2 7u83 1411
}
1412
 
1413
 
1414
/*
1415
    SEARCH FOR A SUBFIELD
1416
 
1417
    This routine finds the member of a class corresponding to the member
1418
    id of the base class of ns indicated by gr.
1419
*/
1420
 
6 7u83 1421
IDENTIFIER
1422
search_subfield(NAMESPACE ns, GRAPH gr, IDENTIFIER id)
2 7u83 1423
{
6 7u83 1424
	GRAPH gt = DEREF_graph(graph_top(gr));
1425
	if (!EQ_graph(gr, gt)) {
1426
		int def = 0;
1427
		IDENTIFIER pid;
1428
		MEMBER_LOOKUP mems;
1429
		TYPE form = find_form(id, &def);
1430
		HASHID nm = DEREF_hashid(id_name(id));
1431
		DECL_SPEC acc = DEREF_dspec(graph_access(gr));
1432
		if (acc & dspec_alias) {
1433
			/* Ambiguous base class */
1434
			CLASS_TYPE cs = DEREF_ctype(graph_head(gr));
1435
			search_base(gt, nm, &mems, cs, 0, 1);
1436
		} else {
1437
			/* Unambiguous base class */
1438
			search_base(gr, nm, &mems, NULL_ctype, 0, 1);
1439
		}
1440
		pid = resolve_member(ns, nm, &mems, form, 1);
1441
		if (!IS_NULL_id(pid)) {
1442
			id = pid;
1443
		}
2 7u83 1444
	}
6 7u83 1445
	return (id);
2 7u83 1446
}
1447
 
1448
 
1449
/*
1450
    PROCESS INHERITANCE FOR A CLASS
1451
 
1452
    This routine is called at the end of a class definition to handle
1453
    any inheritance issues.  At present an inherited member is only
1454
    recorded as it is looked up.  However the lists of all virtual
1455
    functions and conversion functions on the class need to take account
1456
    of inheritance immediately.
1457
*/
1458
 
6 7u83 1459
void
1460
inherit_class(void)
2 7u83 1461
{
6 7u83 1462
	CLASS_TYPE ct = crt_class;
1463
	NAMESPACE ns = crt_namespace;
1464
	GRAPH gr = DEREF_graph(ctype_base(ct));
1465
	LIST(GRAPH)bases = DEREF_list(graph_tails(gr));
1466
	LIST(IDENTIFIER)pc = DEREF_list(ctype_conv(ct));
2 7u83 1467
 
6 7u83 1468
	/* Scan through base classes */
1469
	while (!IS_NULL_list(bases)) {
1470
		GRAPH gs = DEREF_graph(HEAD_list(bases));
1471
		CLASS_TYPE cs = DEREF_ctype(graph_head(gs));
2 7u83 1472
 
6 7u83 1473
		/* Deal with conversion functions */
1474
		LIST(IDENTIFIER)qc = DEREF_list(ctype_conv(cs));
1475
		while (!IS_NULL_list(qc)) {
1476
			/* Deal with each inherited conversion */
1477
			IDENTIFIER qid = DEREF_id(HEAD_list(qc));
1478
			HASHID qnm = DEREF_hashid(id_name(qid));
1479
			LIST(IDENTIFIER)r = pc;
1480
			while (!IS_NULL_list(r)) {
1481
				/* Check whether already declared */
1482
				IDENTIFIER rid = DEREF_id(HEAD_list(r));
1483
				HASHID rnm = DEREF_hashid(id_name(rid));
1484
				if (EQ_hashid(rnm, qnm)) {
1485
					break;
1486
				}
1487
				r = TAIL_list(r);
2 7u83 1488
			}
6 7u83 1489
			if (IS_NULL_list(r)) {
1490
				/* Construct inherited member */
1491
				qid = search_field(ns, qnm, 0, 0);
1492
				if (!IS_NULL_id(qid)) {
1493
					if (IS_id_ambig(qid)) {
1494
						LIST(IDENTIFIER)qids;
1495
						qids = DEREF_list(id_ambig_ids(qid));
1496
						while (!IS_NULL_list(qids)) {
1497
							qid = DEREF_id(HEAD_list(qids));
1498
							CONS_id(qid, pc, pc);
1499
							qids = TAIL_list(qids);
1500
						}
1501
					} else {
1502
						CONS_id(qid, pc, pc);
1503
					}
1504
				}
1505
			}
1506
			qc = TAIL_list(qc);
2 7u83 1507
		}
6 7u83 1508
 
1509
		/* Process next base class */
1510
		bases = TAIL_list(bases);
2 7u83 1511
	}
1512
 
6 7u83 1513
	/* Record modified information */
1514
	COPY_list(ctype_conv(ct), pc);
2 7u83 1515
 
6 7u83 1516
	/* Deal with virtual functions */
1517
	end_virtual(ct);
1518
	return;
2 7u83 1519
}