Subversion Repositories tendra.SVN

Rev

Go to most recent revision | Details | Last modification | View Log | RSS feed

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