Subversion Repositories tendra.SVN

Rev

Rev 2 | Show entire file | Ignore whitespace | Details | Blame | Last modification | View Log | RSS feed

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