Subversion Repositories tendra.SVN

Rev

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

Rev Author Line No. Line
2 7u83 1
/*
7 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
7 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:-
7 7u83 42
 
2 7u83 43
        (1) Its Recipients shall ensure that this Notice is
44
        reproduced upon any copies or amended versions of it;
7 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;
7 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;
7 7u83 53
 
2 7u83 54
        (4) DERA gives no warranty or assurance as to its
55
        quality or suitability for any purpose and DERA accepts
56
        no liability whatsoever in relation to any use to which
57
        it may be put.
58
*/
59
 
60
 
61
#include "config.h"
62
#include "c_types.h"
63
#include "ctype_ops.h"
64
#include "graph_ops.h"
65
#include "hashid_ops.h"
66
#include "id_ops.h"
67
#include "type_ops.h"
68
#include "virt_ops.h"
69
#include "error.h"
70
#include "catalog.h"
71
#include "option.h"
72
#include "access.h"
73
#include "capsule.h"
74
#include "check.h"
75
#include "chktype.h"
76
#include "derive.h"
77
#include "dump.h"
78
#include "exception.h"
79
#include "function.h"
80
#include "namespace.h"
81
#include "overload.h"
82
#include "syntax.h"
83
#include "template.h"
84
#include "virtual.h"
85
 
86
 
87
/*
88
    COMBINE TWO INHERITED VIRTUAL FUNCTIONS
89
 
90
    This routine is called when the same virtual function is inherited
91
    via both vp and vq.  It combine the two virtual function table entries
92
    and returns the result.  Note that one or other may be selected using
93
    the dominance rule in certain cases.
94
*/
95
 
7 7u83 96
static VIRTUAL
97
inherit_duplicate(VIRTUAL vp, VIRTUAL vq)
2 7u83 98
{
7 7u83 99
	GRAPH gr;
100
	IDENTIFIER fn;
101
	IDENTIFIER gn;
102
	unsigned long n;
103
	if (IS_virt_inherit(vq)) {
104
		DESTROY_virt_inherit(destroy, fn, n, gr, vq, vq);
105
		UNUSED(fn);
106
		UNUSED(n);
107
		UNUSED(gr);
108
		UNUSED(vq);
109
		return (vp);
110
	}
111
	if (IS_virt_inherit(vp)) {
112
		DESTROY_virt_inherit(destroy, fn, n, gr, vp, vp);
113
		UNUSED(fn);
114
		UNUSED(n);
115
		UNUSED(gr);
116
		UNUSED(vp);
117
		return (vq);
118
	}
119
	fn = DEREF_id(virt_func(vp));
120
	gn = DEREF_id(virt_func(vq));
121
	if (EQ_id(fn, gn)) {
122
		return (vp);
123
	}
124
	COPY_virt(virt_next(vq), vp);
125
	return (vq);
2 7u83 126
}
127
 
128
 
129
/*
130
    INHERIT A VIRTUAL FUNCTION
131
 
132
    This routine inherits the virtual function vq from the direct base
133
    class gs.  p gives the list of functions already inherited.
134
*/
135
 
7 7u83 136
static VIRTUAL
137
inherit_virtual(VIRTUAL vq, GRAPH gs, LIST(VIRTUAL) p)
2 7u83 138
{
7 7u83 139
	VIRTUAL vp = NULL_virt;
140
	CLASS_TYPE cs = DEREF_ctype(graph_head(gs));
141
	CLASS_INFO ci = DEREF_cinfo(ctype_info(cs));
142
	GRAPH gt = DEREF_graph(ctype_base(cs));
143
	IDENTIFIER fn = DEREF_id(virt_func(vq));
144
	switch (TAG_virt(vq)) {
145
	case virt_simple_tag:
146
		/* Simple inheritance */
147
		MAKE_virt_inherit(fn, 0, gs, vp);
148
		return (vp);
149
	case virt_override_tag: {
150
		/* Override inheritance */
151
		IDENTIFIER bn = DEREF_id(virt_override_orig(vq));
152
		GRAPH rq = DEREF_graph(virt_override_ret(vq));
153
		GRAPH sq = DEREF_graph(virt_override_src(vq));
154
		GRAPH sp = find_subgraph(gs, gt, sq);
155
		MAKE_virt_complex(fn, 0, gs, rq, bn, sp, vp);
156
		fn = bn;
157
		gs = sp;
158
		break;
2 7u83 159
	}
7 7u83 160
	case virt_inherit_tag: {
161
		/* Nested inheritance */
162
		GRAPH gq = DEREF_graph(virt_base(vq));
163
		GRAPH gp = find_subgraph(gs, gt, gq);
164
		MAKE_virt_inherit(fn, 0, gp, vp);
165
		gs = gp;
166
		break;
2 7u83 167
	}
7 7u83 168
	case virt_complex_tag: {
169
		/* Complex inheritance */
170
		IDENTIFIER bn = DEREF_id(virt_complex_orig(vq));
171
		GRAPH rq = DEREF_graph(virt_complex_ret(vq));
172
		GRAPH sq = DEREF_graph(virt_complex_src(vq));
173
		GRAPH sp = find_subgraph(gs, gt, sq);
174
		GRAPH gq = DEREF_graph(virt_base(vq));
175
		GRAPH gp = find_subgraph(gs, gt, gq);
176
		MAKE_virt_complex(fn, 0, gp, rq, bn, sp, vp);
177
		fn = bn;
178
		gs = sp;
179
		break;
2 7u83 180
	}
7 7u83 181
	case virt_link_tag: {
182
		/* Symbolic link */
183
		PTR(VIRTUAL)pv = DEREF_ptr(virt_link_to(vq));
184
		vq = DEREF_virt(pv);
185
		vp = inherit_virtual(vq, gs, p);
186
		return (vp);
2 7u83 187
	}
7 7u83 188
	default:
189
		/* Shouldn't occur */
190
		return (vp);
2 7u83 191
	}
192
 
7 7u83 193
	/* Check previous cases */
194
	if (ci & cinfo_virtual_base) {
195
		while (!IS_NULL_list(p)) {
196
			VIRTUAL vr = DEREF_virt(HEAD_list(p));
197
			switch (TAG_virt(vr)) {
198
			case virt_inherit_tag: {
199
				/* Previous simple inheritance */
200
				IDENTIFIER bn = DEREF_id(virt_func(vr));
201
				GRAPH gr = DEREF_graph(virt_base(vr));
202
				if (EQ_id(bn, fn) && eq_graph(gr, gs)) {
203
					unsigned long n =
204
					    DEREF_ulong(virt_no(vr));
205
					vp = inherit_duplicate(vr, vp);
206
					COPY_ulong(virt_no(vr), n);
207
					COPY_virt(HEAD_list(p), vp);
208
					MAKE_virt_link(bn, n, gr, HEAD_list(p),
209
						       vp);
210
					return (vp);
211
				}
212
				break;
213
			}
214
			case virt_complex_tag: {
215
				/* Previous complex inheritance */
216
				IDENTIFIER bn = DEREF_id(virt_complex_orig(vr));
217
				GRAPH gr = DEREF_graph(virt_complex_src(vr));
218
				if (EQ_id(bn, fn) && eq_graph(gr, gs)) {
219
					unsigned long n =
220
					    DEREF_ulong(virt_no(vr));
221
					vp = inherit_duplicate(vr, vp);
222
					COPY_ulong(virt_no(vr), n);
223
					COPY_virt(HEAD_list(p), vp);
224
					MAKE_virt_link(bn, n, gr, HEAD_list(p),
225
						       vp);
226
					return (vp);
227
				}
228
				break;
229
			}
230
			}
231
			p = TAIL_list(p);
2 7u83 232
		}
233
	}
7 7u83 234
	return (vp);
2 7u83 235
}
236
 
237
 
238
/*
239
    INHERIT A VIRTUAL FUNCTION TABLE
240
 
241
    This routine inherits the virtual function table vs to the class
242
    corresponding to the graph gt.  vt gives any previous virtual function
243
    tables.
244
*/
245
 
7 7u83 246
static VIRTUAL
247
inherit_table(VIRTUAL vs, VIRTUAL vt, GRAPH gt)
2 7u83 248
{
7 7u83 249
	if (!IS_NULL_virt(vs)) {
250
		OFFSET off;
251
		VIRTUAL vp;
252
		IDENTIFIER id = DEREF_id(virt_func(vs));
253
		GRAPH gr = DEREF_graph(virt_base(vs));
254
		GRAPH gs = DEREF_graph(graph_top(gr));
255
		VIRTUAL vr = DEREF_virt(virt_next(vs));
256
		vr = inherit_table(vr, vt, gt);
257
		gr = find_subgraph(gt, gs, gr);
258
		off = DEREF_off(graph_off(gr));
259
		vp = vr;
260
		while (!IS_NULL_virt(vp)) {
261
			/* Check for previous use of this base */
262
			GRAPH gp = DEREF_graph(virt_base(vp));
263
			if (eq_graph(gp, gr)) {
264
				COPY_off(virt_table_off(vp), off);
265
				COPY_graph(virt_base(vp), gr);
266
				return (vt);
267
			}
268
			vp = DEREF_virt(virt_next(vp));
269
		}
270
		MAKE_virt_table(id, 0, gr, off, vt);
271
		COPY_virt(virt_next(vt), vr);
2 7u83 272
	}
7 7u83 273
	return (vt);
2 7u83 274
}
275
 
276
 
277
/*
278
    INHERIT VIRTUAL FUNCTION TABLES
279
 
280
    This routine inherits the virtual function tables from the list of
281
    base classes br.
282
*/
283
 
7 7u83 284
static VIRTUAL
285
inherit_base_tables(LIST(GRAPH) br)
2 7u83 286
{
7 7u83 287
	if (!IS_NULL_list(br)) {
288
		VIRTUAL vt = inherit_base_tables(TAIL_list(br));
289
		GRAPH gs = DEREF_graph(HEAD_list(br));
290
		CLASS_TYPE cs = DEREF_ctype(graph_head(gs));
291
		VIRTUAL vs = DEREF_virt(ctype_virt(cs));
292
		vt = inherit_table(vs, vt, gs);
293
		return (vt);
294
	}
295
	return (NULL_virt);
2 7u83 296
}
297
 
298
 
299
/*
300
    CREATE A VIRTUAL FUNCTION TABLES
301
 
302
    This routine creates the virtual function tables for the class ct.
303
    If code generation is not enabled then this is just a simple table
304
    corresponding to ct.  Otherwise it may be necessary to create a
305
    number of tables, corresponding to the base classes of ct.  If the
306
    first base class is not virtual then its inherited table is used
307
    for ct, otherwise a new table needs to be created.  If bases is
308
    false then a single table is created.
309
*/
310
 
7 7u83 311
static VIRTUAL
312
make_virt_table(CLASS_TYPE ct, CLASS_INFO cj, int bases)
2 7u83 313
{
7 7u83 314
	VIRTUAL vt = NULL_virt;
315
	VIRTUAL vs = NULL_virt;
316
	GRAPH gr = DEREF_graph(ctype_base(ct));
317
	CLASS_INFO ci = DEREF_cinfo(ctype_info(ct));
2 7u83 318
 
7 7u83 319
	/* Inherit tables from base classes */
320
	if (bases) {
321
		LIST(GRAPH) br = DEREF_list(graph_tails(gr));
322
		vs = inherit_base_tables(br);
323
		if (!IS_NULL_virt(vs)) {
324
			OFFSET off = DEREF_off(virt_table_off(vs));
325
			if (is_zero_offset(off)) {
326
				/* Use inherited virtual function table */
327
				vt = vs;
328
			}
329
		}
2 7u83 330
	}
331
 
7 7u83 332
	/* Create new virtual function table */
333
	if (IS_NULL_virt(vt)) {
334
		IDENTIFIER id = DEREF_id(ctype_name(ct));
335
		MAKE_virt_table(id, 0, gr, NULL_off, vt);
336
		COPY_virt(virt_next(vt), vs);
337
	}
338
	COPY_virt(ctype_virt(ct), vt);
339
	COPY_cinfo(ctype_info(ct), (ci | cj));
340
	return (vt);
2 7u83 341
}
342
 
343
 
344
/*
345
    INITIALISE A VIRTUAL FUNCTION TABLE
346
 
347
    This routine initialises the virtual function table for the class
348
    type ct.
349
*/
350
 
7 7u83 351
void
352
begin_virtual(CLASS_TYPE ct)
2 7u83 353
{
7 7u83 354
	unsigned long n = 0;
355
	LIST(VIRTUAL) p = NULL_list(VIRTUAL);
356
	GRAPH gr = DEREF_graph(ctype_base(ct));
357
	LIST(GRAPH) br = DEREF_list(graph_tails(gr));
2 7u83 358
 
7 7u83 359
	/* Scan through direct base classes */
360
	while (!IS_NULL_list(br)) {
361
		GRAPH gs = DEREF_graph(HEAD_list(br));
362
		CLASS_TYPE cs = DEREF_ctype(graph_head(gs));
363
		VIRTUAL vs = DEREF_virt(ctype_virt(cs));
364
		if (!IS_NULL_virt(vs)) {
365
			LIST(VIRTUAL)q = DEREF_list(virt_table_entries(vs));
366
			while (!IS_NULL_list(q)) {
367
				VIRTUAL vq = DEREF_virt(HEAD_list(q));
368
				VIRTUAL vp = inherit_virtual(vq, gs, p);
369
				if (!IS_NULL_virt(vp)) {
370
					/* Add inherited function to list */
371
					CONS_virt(vp, p, p);
372
					COPY_ulong(virt_no(vp), n);
373
					n++;
374
				}
375
				q = TAIL_list(q);
376
			}
2 7u83 377
		}
7 7u83 378
		br = TAIL_list(br);
2 7u83 379
	}
380
 
7 7u83 381
	/* Construct the virtual function table */
382
	if (!IS_NULL_list(p)) {
383
		CLASS_INFO ci = (cinfo_polymorphic | cinfo_poly_base);
384
		VIRTUAL vt = make_virt_table(ct, ci, output_capsule);
385
		p = REVERSE_list(p);
386
		COPY_list(virt_table_entries(vt), p);
387
		COPY_ulong(virt_no(vt), n);
388
	}
389
	return;
2 7u83 390
}
391
 
392
 
393
/*
394
    COMPLETE A VIRTUAL FUNCTION TABLE
395
 
396
    This routine is called at the end of a class definition to complete
397
    the construction of the virtual function table.  It checks for
398
    inherited pure virtual functions and for final overriding functions.
399
    Also if any overriding virtual function involves a non-trivial base
400
    class conversion then an inherited virtual function table cannot be
401
    used as the main virtual function table for ct.
402
*/
403
 
7 7u83 404
void
405
end_virtual(CLASS_TYPE ct)
2 7u83 406
{
7 7u83 407
	VIRTUAL vt = DEREF_virt(ctype_virt(ct));
408
	if (!IS_NULL_virt(vt)) {
409
		int destr = 0;
410
		int trivial = 1;
411
		OFFSET off = DEREF_off(virt_table_off(vt));
412
		CLASS_INFO ci = DEREF_cinfo(ctype_info(ct));
413
		LIST(VIRTUAL) p = DEREF_list(virt_table_entries(vt));
414
		LIST(VIRTUAL) q = p;
415
		unsigned long n = DEREF_ulong(virt_no(vt));
416
		IGNORE check_value(OPT_VAL_virtual_funcs, n);
417
		while (!IS_NULL_list(q)) {
418
			VIRTUAL vf = DEREF_virt(HEAD_list(q));
419
			IDENTIFIER id = DEREF_id(virt_func(vf));
420
			HASHID nm = DEREF_hashid(id_name(id));
421
			DECL_SPEC ds = DEREF_dspec(id_storage(id));
422
			if (ds & dspec_pure) {
423
				ci |= cinfo_abstract;
424
			}
425
			if (IS_hashid_destr(nm)) {
426
				destr = 1;
427
			}
428
			if (IS_virt_override(vf)) {
429
				/* Check for non-trivial return conversions */
430
				GRAPH gr = DEREF_graph(virt_override_ret(vf));
431
				if (!IS_NULL_graph(gr)) {
432
					DECL_SPEC acc =
433
					    DEREF_dspec(graph_access(gr));
434
					if (!(acc & dspec_ignore)) {
435
						trivial = 0;
436
					}
437
				}
438
			} else if (IS_virt_complex(vf)) {
439
				/* Check for final overrider */
440
				GRAPH gr = DEREF_graph(virt_complex_ret(vf));
441
				VIRTUAL vn = DEREF_virt(virt_next(vf));
442
				if (!IS_NULL_virt(vn)) {
443
					id = DEREF_id(virt_complex_orig(vf));
444
					report(crt_loc,
445
					       ERR_class_virtual_final(id, ct));
446
				}
447
				if (!IS_NULL_graph(gr)) {
448
					DECL_SPEC acc =
449
					    DEREF_dspec(graph_access(gr));
450
					if (!(acc & dspec_ignore)) {
451
						trivial = 0;
452
					}
453
				}
454
			}
455
			q = TAIL_list(q);
2 7u83 456
		}
7 7u83 457
		if (!IS_NULL_off(off) && !trivial && output_capsule) {
458
			/* Can't use inherited virtual function table */
459
			VIRTUAL vs = make_virt_table(ct, cinfo_none, 0);
460
			COPY_virt(virt_next(vs), vt);
461
			COPY_ulong(virt_no(vs), n);
462
			COPY_list(virt_table_entries(vs), p);
2 7u83 463
		}
7 7u83 464
		if (!destr) {
465
			/* Warn about non-virtual destructors */
466
			report(crt_loc, ERR_class_virtual_destr(ct));
2 7u83 467
		}
7 7u83 468
		ci |= cinfo_polymorphic;
469
		COPY_cinfo(ctype_info(ct), ci);
2 7u83 470
	}
7 7u83 471
	return;
2 7u83 472
}
473
 
474
 
475
/*
476
    CHECK VIRTUAL FUNCTION RETURN TYPES
477
 
478
    This routine checks whether the return type of the function type s is
479
    valid for a virtual function which overrides a function of type t.
480
    If the return types differ by a base class conversion then the
481
    corresponding base class graph is returned via pgr.
482
*/
483
 
7 7u83 484
static int
485
virtual_return(TYPE s, TYPE t, GRAPH *pgr)
2 7u83 486
{
7 7u83 487
    if (IS_type_func(s) && IS_type_func(t)) {
488
	TYPE p = DEREF_type(type_func_ret(s));
489
	TYPE q = DEREF_type(type_func_ret(t));
490
	unsigned np = TAG_type(p);
491
	unsigned nq = TAG_type(q);
492
	if (np == nq) {
493
	    if (eq_type(p, q)) {
494
		    return (1);
495
	    }
496
	    if (np == type_ptr_tag || nq == type_ref_tag) {
497
		p = DEREF_type(type_ptr_etc_sub(p));
498
		np = TAG_type(p);
499
		if (np == type_compound_tag) {
500
		    q = DEREF_type(type_ptr_etc_sub(q));
501
		    nq = TAG_type(q);
502
		    if (nq == type_compound_tag) {
2 7u83 503
			/* Both pointer or reference to class */
7 7u83 504
			GRAPH gr;
505
			CLASS_TYPE cp, cq;
506
			cp = DEREF_ctype(type_compound_defn(p));
507
			cq = DEREF_ctype(type_compound_defn(q));
508
			gr = find_base_class(cp, cq, 1);
509
			if (!IS_NULL_graph(gr)) {
2 7u83 510
			    /* Base class conversion */
7 7u83 511
			    CV_SPEC cv = cv_compare(q, p);
512
			    if (cv == cv_none) {
2 7u83 513
				/* Qualification conversion */
7 7u83 514
				*pgr = gr;
515
				return (1);
2 7u83 516
			    }
517
			}
518
		    }
519
		}
520
	    }
521
	}
522
 
523
	/* Allow for template types */
7 7u83 524
	if (np == type_token_tag && is_templ_type(p)) {
525
		return (1);
526
	}
527
	if (nq == type_token_tag && is_templ_type(q)) {
528
		return (1);
529
	}
530
	if (np == type_error_tag || nq == type_error_tag) {
531
		return (1);
532
	}
2 7u83 533
    }
7 7u83 534
    return (0);
2 7u83 535
}
536
 
537
 
538
/*
539
    DOES A FUNCTION OVERRIDE A VIRTUAL FUNCTION?
540
 
541
    This routine checks whether a member function nm of type t overrides
542
    a virtual function in some base class of ct.  It returns a list of
543
    all such functions.  The function return types are not checked at
544
    this stage.  If the function is not an overriding virtual function
545
    but has the same name as a virtual function then this is returned
546
    via pid.
547
*/
548
 
7 7u83 549
LIST(VIRTUAL)
550
overrides_virtual(CLASS_TYPE ct, HASHID nm, TYPE t, IDENTIFIER *pid)
2 7u83 551
{
7 7u83 552
	LIST(VIRTUAL) res = NULL_list(VIRTUAL);
553
	VIRTUAL vt = DEREF_virt(ctype_virt(ct));
554
	if (!IS_NULL_virt(vt)) {
555
		unsigned nt = TAG_hashid(nm);
556
		LIST(VIRTUAL) p = DEREF_list(virt_table_entries(vt));
557
		while (!IS_NULL_list(p)) {
558
			VIRTUAL vf = DEREF_virt(HEAD_list(p));
559
			switch (TAG_virt(vf)) {
560
			case virt_inherit_tag:
561
			case virt_complex_tag: {
562
				/* Only check inherited functions */
563
				IDENTIFIER fid = DEREF_id(virt_func(vf));
564
				HASHID fnm = DEREF_hashid(id_name(fid));
565
				if (EQ_hashid(fnm, nm)) {
566
					/* Names match */
567
					TYPE s;
568
					s = DEREF_type(id_function_etc_type(fid));
569
					if (eq_func_type(t, s, 1, 0)) {
570
						/* Types basically match */
571
						CONS_virt(vf, res, res);
572
					} else {
573
						*pid = fid;
574
					}
575
				} else if (nt == hashid_destr_tag) {
576
					/* Check for virtual destructors */
577
					if (IS_hashid_destr(fnm)) {
578
						CONS_virt(vf, res, res);
579
					}
580
				}
581
				break;
2 7u83 582
			}
583
			}
7 7u83 584
			p = TAIL_list(p);
2 7u83 585
		}
7 7u83 586
		res = REVERSE_list(res);
2 7u83 587
	}
7 7u83 588
	return (res);
2 7u83 589
}
590
 
591
 
592
/*
593
    FIND AN OVERRIDING VIRTUAL FUNCTION
594
 
595
    This routine finds an overriding virtual function for the virtual
596
    function id inherited from the base class gr of ct.  If the return
597
    types do not match then the base class conversion is assigned to pgr.
598
*/
599
 
7 7u83 600
VIRTUAL
601
find_overrider(CLASS_TYPE ct, IDENTIFIER id, GRAPH gr, GRAPH *pgr)
2 7u83 602
{
7 7u83 603
	HASHID nm = DEREF_hashid(id_name(id));
604
	unsigned nt = TAG_hashid(nm);
605
	TYPE t = DEREF_type(id_function_etc_type(id));
2 7u83 606
 
7 7u83 607
	/* Scan through virtual functions */
608
	VIRTUAL vs = DEREF_virt(ctype_virt(ct));
609
	if (!IS_NULL_virt(vs)) {
610
		LIST(VIRTUAL) p = DEREF_list(virt_table_entries(vs));
611
		while (!IS_NULL_list(p)) {
612
			VIRTUAL vf = DEREF_virt(HEAD_list(p));
613
			if (!IS_virt_link(vf)) {
614
				GRAPH gs = DEREF_graph(virt_base(vf));
615
				if (is_subgraph(gs, gr)) {
616
					HASHID fnm;
617
					IDENTIFIER fid =
618
					    DEREF_id(virt_func(vf));
619
					if (EQ_id(fid, id)) {
620
						/* Identical functions */
621
						return (vf);
622
					}
623
					fnm = DEREF_hashid(id_name(fid));
624
					if (EQ_hashid(fnm, nm)) {
625
						/* Names match */
626
						TYPE s;
627
						s = DEREF_type(id_function_etc_type(fid));
628
						if (eq_func_type(s, t, 1, 0)) {
629
							/* Types basically
630
							 * match */
631
							IGNORE virtual_return(s, t, pgr);
632
							return (vf);
633
						}
634
					} else if (nt == hashid_destr_tag) {
635
						/* Check for virtual
636
						 * destructors */
637
						if (IS_hashid_destr(fnm)) {
638
							return (vf);
639
						}
640
					}
641
				}
2 7u83 642
			}
7 7u83 643
			p = TAIL_list(p);
2 7u83 644
		}
645
	}
7 7u83 646
	return (NULL_virt);
2 7u83 647
}
648
 
649
 
650
/*
651
    FIND THE START OF A VIRTUAL FUNCTION TABLE SECTION
652
 
653
    This routine finds the offset within the main virtual function table
654
    for a class of those functions inherited from the base class gr.
655
*/
656
 
7 7u83 657
unsigned long
658
virtual_start(GRAPH gr)
2 7u83 659
{
7 7u83 660
	DECL_SPEC acc = DEREF_dspec(graph_access(gr));
661
	if (!(acc & dspec_ignore)) {
662
		GRAPH gu = DEREF_graph(graph_up(gr));
663
		if (!IS_NULL_graph(gu)) {
664
			unsigned long n = virtual_start(gu);
665
			LIST(GRAPH) br = DEREF_list(graph_tails(gu));
666
			while (!IS_NULL_list(br)) {
667
				VIRTUAL vs;
668
				CLASS_TYPE cs;
669
				GRAPH gs = DEREF_graph(HEAD_list(br));
670
				if (eq_graph(gs, gr)) {
671
					return (n);
672
				}
673
				cs = DEREF_ctype(graph_head(gs));
674
				vs = DEREF_virt(ctype_virt(cs));
675
				if (!IS_NULL_virt(vs)) {
676
					/* Add virtual functions from cs */
677
					unsigned long m =
678
					    DEREF_ulong(virt_no(vs));
679
					n += m;
680
				}
681
				br = TAIL_list(br);
682
			}
683
			return (n);
2 7u83 684
		}
685
	}
7 7u83 686
	return (0);
2 7u83 687
}
688
 
689
 
690
/*
691
    CREATE AN OVERRIDING VIRTUAL FUNCTION
692
 
693
    This routine creates an overriding virtual function id for vq.  gs gives
694
    the base class graph of the underlying type.
695
*/
696
 
7 7u83 697
static VIRTUAL
698
override_virtual(IDENTIFIER id, VIRTUAL vq, GRAPH gs)
2 7u83 699
{
7 7u83 700
	GRAPH gt;
701
	VIRTUAL vp;
702
	GRAPH gr = NULL_graph;
703
	IDENTIFIER fn = DEREF_id(virt_func(vq));
704
	unsigned long n = DEREF_ulong(virt_no(vq));
2 7u83 705
 
7 7u83 706
	/* Check function return types */
707
	TYPE t = DEREF_type(id_function_etc_type(id));
708
	TYPE s = DEREF_type(id_function_etc_type(fn));
709
	if (virtual_return(t, s, &gr)) {
710
		if (!IS_NULL_graph(gr)) {
711
			ERROR err = check_ambig_base(gr);
712
			if (!IS_NULL_err(err)) {
713
				/* Can't be ambiguous */
714
				ERROR err2 = ERR_class_virtual_ambig(id, fn);
715
				err = concat_error(err, err2);
716
				report(crt_loc, err);
717
			}
718
			check_base_access(gr);
719
		}
720
		if (!eq_except(t, s)) {
721
			/* Check exception specifiers */
722
			PTR(LOCATION)loc = id_loc(fn);
723
			report(crt_loc, ERR_except_spec_virtual(id, fn, loc));
724
		}
725
	} else {
726
		PTR(LOCATION)loc = id_loc(fn);
727
		report(crt_loc, ERR_class_virtual_ret(id, fn, loc));
2 7u83 728
	}
729
 
7 7u83 730
	/* Find the result components */
731
	switch (TAG_virt(vq)) {
732
	case virt_override_tag:
733
		fn = DEREF_id(virt_override_orig(vq));
734
		gs = DEREF_graph(virt_override_src(vq));
735
		break;
736
	case virt_inherit_tag:
737
		gs = DEREF_graph(virt_base(vq));
738
		break;
739
	case virt_complex_tag:
740
		fn = DEREF_id(virt_complex_orig(vq));
741
		gs = DEREF_graph(virt_complex_src(vq));
742
		break;
2 7u83 743
	}
7 7u83 744
	gt = DEREF_graph(graph_top(gs));
745
	MAKE_virt_override(id, n, gt, gr, fn, gs, vp);
746
	if (do_dump) {
747
		dump_override(id, fn);
2 7u83 748
	}
7 7u83 749
	return (vp);
2 7u83 750
}
751
 
752
 
753
/*
754
    ADD A VIRTUAL FUNCTION
755
 
756
    This routine adds the virtual function id to the virtual function
757
    table for the class ct.  r is the result of a call to overrides_virtual
758
    on id.
759
*/
760
 
7 7u83 761
void
762
add_virtual(CLASS_TYPE ct, IDENTIFIER id, LIST(VIRTUAL) r)
2 7u83 763
{
7 7u83 764
	VIRTUAL vf;
765
	unsigned long n;
766
	LIST(VIRTUAL)p, q;
767
	GRAPH gr = DEREF_graph(ctype_base(ct));
2 7u83 768
 
7 7u83 769
	/* Create the virtual function table if necessary */
770
	VIRTUAL vt = DEREF_virt(ctype_virt(ct));
771
	if (IS_NULL_virt(vt)) {
772
		vt = make_virt_table(ct, cinfo_polymorphic, output_capsule);
773
		p = NULL_list(VIRTUAL);
774
		n = 0;
775
	} else {
776
		p = DEREF_list(virt_table_entries(vt));
777
		n = DEREF_ulong(virt_no(vt));
778
	}
2 7u83 779
 
7 7u83 780
	/* Create the table entry */
781
	if (IS_NULL_list(r)) {
782
		/* New virtual function */
783
		MAKE_virt_simple(id, n, gr, vf);
784
		CONS_virt(vf, NULL_list(VIRTUAL), q);
785
		p = APPEND_list(p, q);
786
		COPY_list(virt_table_entries(vt), p);
787
		COPY_ulong(virt_no(vt), n + 1);
788
	} else {
789
		/* Overriding virtual function */
790
		q = r;
791
		while (!IS_NULL_list(q)) {
792
			VIRTUAL vq = DEREF_virt(HEAD_list(q));
793
			for (;;) {
794
				VIRTUAL vp = DEREF_virt(HEAD_list(p));
795
				if (EQ_virt(vp, vq)) {
796
					break;
797
				}
798
				p = TAIL_list(p);
799
			}
800
			vf = override_virtual(id, vq, gr);
801
			COPY_virt(HEAD_list(p), vf);
802
			p = TAIL_list(p);
803
			q = TAIL_list(q);
804
		}
805
		DESTROY_list(r, SIZE_virt);
2 7u83 806
	}
7 7u83 807
	return;
2 7u83 808
}
809
 
810
 
811
/*
812
    FIND A PURE VIRTUAL FUNCTION OF A CLASS
813
 
814
    This routine returns a pure virtual function of the class ct if such
815
    exists.  Otherwise the null identifier is returned.
816
*/
817
 
7 7u83 818
IDENTIFIER
819
find_pure_function(CLASS_TYPE ct)
2 7u83 820
{
7 7u83 821
	VIRTUAL vt = DEREF_virt(ctype_virt(ct));
822
	if (!IS_NULL_virt(vt)) {
823
		LIST(VIRTUAL) p = DEREF_list(virt_table_entries(vt));
824
		while (!IS_NULL_list(p)) {
825
			VIRTUAL vf = DEREF_virt(HEAD_list(p));
826
			IDENTIFIER id = DEREF_id(virt_func(vf));
827
			DECL_SPEC ds = DEREF_dspec(id_storage(id));
828
			if (ds & dspec_pure) {
829
				return (id);
830
			}
831
			p = TAIL_list(p);
832
		}
2 7u83 833
	}
7 7u83 834
	return (NULL_id);
2 7u83 835
}