Subversion Repositories tendra.SVN

Rev

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

Rev 5 Rev 6
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 54... Line 84...
54
 
84
 
55
    The flag do_access_checks may be set to false to suppress access
85
    The flag do_access_checks may be set to false to suppress access
56
    checking.
86
    checking.
57
*/
87
*/
58
 
88
 
59
int do_access_checks = 1 ;
89
int do_access_checks = 1;
60
 
90
 
61
 
91
 
62
/*
92
/*
63
    CURRENT CLASS MEMBER ACCESS
93
    CURRENT CLASS MEMBER ACCESS
64
 
94
 
65
    The variable crt_access is used to hold the current access specifier
95
    The variable crt_access is used to hold the current access specifier
66
    during a class definition.  prev_access is used to check for dubious
96
    during a class definition.  prev_access is used to check for dubious
67
    base class access specifiers.
97
    base class access specifiers.
68
*/
98
*/
69
 
99
 
70
DECL_SPEC crt_access = dspec_public ;
100
DECL_SPEC crt_access = dspec_public;
71
DECL_SPEC prev_access = dspec_public ;
101
DECL_SPEC prev_access = dspec_public;
72
 
102
 
73
 
103
 
74
/*
104
/*
75
    FIND THE COMPOSITE OF TWO ACCESSES
105
    FIND THE COMPOSITE OF TWO ACCESSES
76
 
106
 
Line 82... Line 112...
82
	    dspec_public < dspec_protected < dspec_private
112
	    dspec_public < dspec_protected < dspec_private
83
 
113
 
84
    the composite is just the maximum of the access components of a and b.
114
    the composite is just the maximum of the access components of a and b.
85
*/
115
*/
86
 
116
 
87
DECL_SPEC join_access
117
DECL_SPEC
88
    PROTO_N ( ( a, b ) )
-
 
89
    PROTO_T ( DECL_SPEC a X DECL_SPEC b )
118
join_access(DECL_SPEC a, DECL_SPEC b)
90
{
119
{
91
    DECL_SPEC p = ( a & dspec_access ) ;
120
	DECL_SPEC p = (a & dspec_access);
92
    DECL_SPEC q = ( b & dspec_access ) ;
121
	DECL_SPEC q = (b & dspec_access);
93
    if ( p >= q ) return ( p ) ;
122
	if (p >= q) {
-
 
123
		return (p);
-
 
124
	}
94
    return ( q ) ;
125
	return (q);
95
}
126
}
96
 
127
 
97
 
128
 
98
/*
129
/*
99
    ADJUST THE ACCESS FOR AN IDENTIFIER
130
    ADJUST THE ACCESS FOR AN IDENTIFIER
Line 101... Line 132...
101
    This routine adjusts the access to the identifier id to the access
132
    This routine adjusts the access to the identifier id to the access
102
    level acc.  expl is true for explicit using and access declarations
133
    level acc.  expl is true for explicit using and access declarations
103
    and false for simple redeclarations.
134
    and false for simple redeclarations.
104
*/
135
*/
105
 
136
 
106
void adjust_access
137
void
107
    PROTO_N ( ( id, acc, expl ) )
-
 
108
    PROTO_T ( IDENTIFIER id X DECL_SPEC acc X int expl )
138
adjust_access(IDENTIFIER id, DECL_SPEC acc, int expl)
109
{
139
{
110
    DECL_SPEC ds = DEREF_dspec ( id_storage ( id ) ) ;
140
    DECL_SPEC ds = DEREF_dspec(id_storage(id));
111
    DECL_SPEC pacc = ( ds & dspec_access ) ;
141
    DECL_SPEC pacc = (ds & dspec_access);
112
    if ( pacc && acc != pacc ) {
142
    if (pacc && acc != pacc) {
113
	if ( !expl ) {
143
	if (!expl) {
114
	    /* Access changed by redeclaration */
144
	    /* Access changed by redeclaration */
115
	    PTR ( LOCATION ) loc = id_loc ( id ) ;
145
	    PTR(LOCATION)loc = id_loc(id);
116
	    report ( crt_loc, ERR_class_access_spec_change ( id, loc ) ) ;
146
	    report(crt_loc, ERR_class_access_spec_change(id, loc));
117
	}
147
	}
118
	if ( acc > pacc ) {
148
	if (acc > pacc) {
119
	    if ( expl ) {
149
	    if (expl) {
120
		/* Access reduced by using declaration */
150
		/* Access reduced by using declaration */
121
		PTR ( LOCATION ) loc = id_loc ( id ) ;
151
		PTR(LOCATION)loc = id_loc(id);
122
		report ( crt_loc, ERR_dcl_nspace_udecl_acc ( id, loc ) ) ;
152
		report(crt_loc, ERR_dcl_nspace_udecl_acc(id, loc));
123
	    }
153
	    }
124
	    acc = pacc ;
154
	    acc = pacc;
125
	}
155
	}
126
	ds = ( ( ds & ~dspec_access ) | acc ) ;
156
	ds = ((ds & ~dspec_access) | acc);
127
	COPY_dspec ( id_storage ( id ), ds ) ;
157
	COPY_dspec(id_storage(id), ds);
128
    }
158
    }
129
    if ( IS_id_function_etc ( id ) && expl ) {
159
    if (IS_id_function_etc(id) && expl) {
130
	/* Deal with overloaded functions */
160
	/* Deal with overloaded functions */
131
	id = DEREF_id ( id_function_etc_over ( id ) ) ;
161
	id = DEREF_id(id_function_etc_over(id));
132
	if ( !IS_NULL_id ( id ) ) adjust_access ( id, acc, expl ) ;
162
	if (!IS_NULL_id(id))adjust_access(id, acc, expl);
133
    }
163
    }
134
    return ;
164
    return;
135
}
165
}
136
 
166
 
137
 
167
 
138
/*
168
/*
139
    ACCESS DECLARATION FLAG
169
    ACCESS DECLARATION FLAG
140
 
170
 
141
    This flag is set to true by access_decl.
171
    This flag is set to true by access_decl.
142
*/
172
*/
143
 
173
 
144
int have_access_decl = 0 ;
174
int have_access_decl = 0;
145
 
175
 
146
 
176
 
147
/*
177
/*
148
    MAKE AN ACCESS DECLARATION
178
    MAKE AN ACCESS DECLARATION
149
 
179
 
150
    This routine adjusts the access of the member id of the current class.
180
    This routine adjusts the access of the member id of the current class.
151
    This is equivalent to a using declaration for id.
181
    This is equivalent to a using declaration for id.
152
*/
182
*/
153
 
183
 
154
IDENTIFIER access_decl
184
IDENTIFIER
155
    PROTO_N ( ( id ) )
-
 
156
    PROTO_T ( IDENTIFIER id )
185
access_decl(IDENTIFIER id)
157
{
186
{
158
    report ( crt_loc, ERR_class_access_dcl_using ( id ) ) ;
187
	report(crt_loc, ERR_class_access_dcl_using(id));
159
    have_access_decl = 1 ;
188
	have_access_decl = 1;
160
    id = using_identifier ( id ) ;
189
	id = using_identifier(id);
161
    return ( id ) ;
190
	return (id);
162
}
191
}
163
 
192
 
164
 
193
 
165
/*
194
/*
166
    MAKE A FRIENDLY FUNCTION
195
    MAKE A FRIENDLY FUNCTION
167
 
196
 
168
    This routine makes the function id into a friend of the class cs.
197
    This routine makes the function id into a friend of the class cs.
169
    The effect of this is to add cs to id's chums list and id to cs's
198
    The effect of this is to add cs to id's chums list and id to cs's
170
    pals list.
199
    pals list.
171
*/
200
*/
172
 
201
 
173
void friend_function
202
void
174
    PROTO_N ( ( cs, id, expl ) )
-
 
175
    PROTO_T ( CLASS_TYPE cs X IDENTIFIER id X int expl )
203
friend_function(CLASS_TYPE cs, IDENTIFIER id, int expl)
176
{
204
{
177
    if ( !IS_NULL_ctype ( cs ) ) {
205
    if (!IS_NULL_ctype(cs)) {
178
	IDENTIFIER cid ;
206
	IDENTIFIER cid;
179
	LIST ( IDENTIFIER ) pl ;
207
	LIST(IDENTIFIER)pl;
180
	LIST ( CLASS_TYPE ) fr, fs ;
208
	LIST(CLASS_TYPE)fr, fs;
181
 
209
 
182
	/* Make cs a pal of id */
210
	/* Make cs a pal of id */
183
	fr = DEREF_list ( id_function_etc_chums ( id ) ) ;
211
	fr = DEREF_list(id_function_etc_chums(id));
184
	fs = fr ;
212
	fs = fr;
185
	while ( !IS_NULL_list ( fs ) ) {
213
	while (!IS_NULL_list(fs)) {
186
	    CLASS_TYPE ct = DEREF_ctype ( HEAD_list ( fs ) ) ;
214
	    CLASS_TYPE ct = DEREF_ctype(HEAD_list(fs));
187
	    if ( eq_ctype ( ct, cs ) ) {
215
	    if (eq_ctype(ct, cs)) {
188
		/* id is already a friend of ns */
216
		/* id is already a friend of ns */
189
		if ( expl ) {
217
		if (expl) {
190
		    ERROR err = ERR_class_friend_dup_func ( id, cs ) ;
218
		    ERROR err = ERR_class_friend_dup_func(id, cs);
191
		    report ( crt_loc, err ) ;
219
		    report(crt_loc, err);
192
		}
220
		}
193
		return ;
221
		return;
194
	    }
222
	    }
195
	    fs = TAIL_list ( fs ) ;
223
	    fs = TAIL_list(fs);
196
	}
224
	}
197
	CONS_ctype ( cs, fr, fr ) ;
225
	CONS_ctype(cs, fr, fr);
198
	COPY_list ( id_function_etc_chums ( id ), fr ) ;
226
	COPY_list(id_function_etc_chums(id), fr);
199
 
227
 
200
	/* Make id a pal of cs */
228
	/* Make id a pal of cs */
201
	pl = DEREF_list ( ctype_pals ( cs ) ) ;
229
	pl = DEREF_list(ctype_pals(cs));
202
	CONS_id ( id, pl, pl ) ;
230
	CONS_id(id, pl, pl);
203
	COPY_list ( ctype_pals ( cs ), pl ) ;
231
	COPY_list(ctype_pals(cs), pl);
204
 
232
 
205
	/* Apply access checks immediately */
233
	/* Apply access checks immediately */
206
	cid = DEREF_id ( ctype_name ( cs ) ) ;
234
	cid = DEREF_id(ctype_name(cs));
207
	immediate_access ( cid, id ) ;
235
	immediate_access(cid, id);
208
    }
236
    }
209
    return ;
237
    return;
210
}
238
}
211
 
239
 
212
 
240
 
213
/*
241
/*
214
    MAKE A FRIENDLY CLASS
242
    MAKE A FRIENDLY CLASS
215
 
243
 
216
    This routine makes the class cid into a friend of the class cs.  The
244
    This routine makes the class cid into a friend of the class cs.  The
217
    effect of this is to add cs to cid's chums list and cid to cs's pals
245
    effect of this is to add cs to cid's chums list and cid to cs's pals
218
    list.
246
    list.
219
*/
247
*/
220
 
248
 
221
void friend_class
249
void
222
    PROTO_N ( ( cs, cid, expl ) )
-
 
223
    PROTO_T ( CLASS_TYPE cs X IDENTIFIER cid X int expl )
250
friend_class(CLASS_TYPE cs, IDENTIFIER cid, int expl)
224
{
251
{
225
    if ( !IS_NULL_ctype ( cs ) ) {
252
    if (!IS_NULL_ctype(cs)) {
226
	ERROR err ;
253
	ERROR err;
227
	TYPE t = DEREF_type ( id_class_name_etc_defn ( cid ) ) ;
254
	TYPE t = DEREF_type(id_class_name_etc_defn(cid));
228
	while ( IS_type_templ ( t ) ) {
255
	while (IS_type_templ(t)) {
229
	    t = DEREF_type ( type_templ_defn ( t ) ) ;
256
	    t = DEREF_type(type_templ_defn(t));
230
	}
257
	}
231
	if ( IS_type_compound ( t ) ) {
258
	if (IS_type_compound(t)) {
232
	    CLASS_TYPE ct = DEREF_ctype ( type_compound_defn ( t ) ) ;
259
	    CLASS_TYPE ct = DEREF_ctype(type_compound_defn(t));
233
	    if ( eq_ctype ( cs, ct ) ) {
260
	    if (eq_ctype(cs, ct)) {
234
		/* Any class is a friend of itself */
261
		/* Any class is a friend of itself */
235
		if ( expl ) {
262
		if (expl) {
236
		    err = ERR_class_friend_dup_class ( ct, cs ) ;
263
		    err = ERR_class_friend_dup_class(ct, cs);
237
		    report ( crt_loc, err ) ;
264
		    report(crt_loc, err);
238
		}
265
		}
239
	    } else {
266
	    } else {
240
		IDENTIFIER sid ;
267
		IDENTIFIER sid;
241
		LIST ( IDENTIFIER ) pl ;
268
		LIST(IDENTIFIER)pl;
242
 
269
 
243
		/* Make cs a chum of ct */
270
		/* Make cs a chum of ct */
244
		LIST ( CLASS_TYPE ) fr = DEREF_list ( ctype_chums ( ct ) ) ;
271
		LIST(CLASS_TYPE)fr = DEREF_list(ctype_chums(ct));
245
		LIST ( CLASS_TYPE ) fs = fr ;
272
		LIST(CLASS_TYPE)fs = fr;
246
		while ( !IS_NULL_list ( fs ) ) {
273
		while (!IS_NULL_list(fs)) {
247
		    CLASS_TYPE cr = DEREF_ctype ( HEAD_list ( fs ) ) ;
274
		    CLASS_TYPE cr = DEREF_ctype(HEAD_list(fs));
248
		    if ( eq_ctype ( cr, cs ) ) {
275
		    if (eq_ctype(cr, cs)) {
249
			/* ct is already a friend of cs */
276
			/* ct is already a friend of cs */
250
			if ( expl ) {
277
			if (expl) {
251
			    err = ERR_class_friend_dup_class ( ct, cs ) ;
278
			    err = ERR_class_friend_dup_class(ct, cs);
252
			    report ( crt_loc, err ) ;
279
			    report(crt_loc, err);
253
			}
280
			}
254
			return ;
281
			return;
255
		    }
282
		    }
256
		    fs = TAIL_list ( fs ) ;
283
		    fs = TAIL_list(fs);
257
		}
284
		}
258
		CONS_ctype ( cs, fr, fr ) ;
285
		CONS_ctype(cs, fr, fr);
259
		COPY_list ( ctype_chums ( ct ), fr ) ;
286
		COPY_list(ctype_chums(ct), fr);
260
 
287
 
261
		/* Make ct a pal of cs */
288
		/* Make ct a pal of cs */
262
		pl = DEREF_list ( ctype_pals ( cs ) ) ;
289
		pl = DEREF_list(ctype_pals(cs));
263
		CONS_id ( cid, pl, pl ) ;
290
		CONS_id(cid, pl, pl);
264
		COPY_list ( ctype_pals ( cs ), pl ) ;
291
		COPY_list(ctype_pals(cs), pl);
265
 
292
 
266
		/* Apply access checks immediately */
293
		/* Apply access checks immediately */
267
		sid = DEREF_id ( ctype_name ( cs ) ) ;
294
		sid = DEREF_id(ctype_name(cs));
268
		immediate_access ( sid, cid ) ;
295
		immediate_access(sid, cid);
269
	    }
296
	    }
270
	}
297
	}
271
    }
298
    }
272
    return ;
299
    return;
273
}
300
}
274
 
301
 
275
 
302
 
276
/*
303
/*
277
    LISTS OF PENDING ACCESS CHECKS
304
    LISTS OF PENDING ACCESS CHECKS
278
 
305
 
279
    Access control checking cannot be performed immediately because, for
306
    Access control checking cannot be performed immediately because, for
280
    example, it is not known until the end of a declaration whether that
307
    example, it is not known until the end of a declaration whether that
281
    declaration represents a friend function.  The list crt_access_list
308
    declaration represents a friend function.  The list crt_access_list
282
    is used to store any pending access checks.
309
    is used to store any pending access checks.
283
*/
310
*/
284
 
311
 
285
ACCESS_LIST crt_access_list = {
312
ACCESS_LIST crt_access_list = {
286
    NULL_list ( IDENTIFIER ), NULL_list ( GRAPH ),
313
	NULL_list(IDENTIFIER), NULL_list(GRAPH),
287
    NULL_list ( int ), 0, 0
314
	NULL_list(int), 0, 0
288
} ;
315
};
289
 
316
 
290
 
317
 
291
/*
318
/*
292
    FIND ACCESS LEVEL
319
    FIND ACCESS LEVEL
293
 
320
 
294
    This routine finds the access level for the members of the class
321
    This routine finds the access level for the members of the class
295
    namespace ns by the identifier pid (or a base class conversion from
322
    namespace ns by the identifier pid (or a base class conversion from
296
    ns if base is true).  It returns the highest access level greater
323
    ns if base is true).  It returns the highest access level greater
297
    than acc which can be accessed.  It also returns a secondary access
324
    than acc which can be accessed.  It also returns a secondary access
298
    giving the access to base class members, plus markers for whether
325
    giving the access to base class members, plus markers for whether
299
    the access is via the actual class, a derived class or a friend.
326
    the access is via the actual class, a derived class or a friend.
300
*/
327
*/
301
 
328
 
302
static DECL_SPEC find_access
329
static DECL_SPEC
303
    PROTO_N ( ( pid, ns, acc, base ) )
-
 
304
    PROTO_T ( IDENTIFIER *pid X NAMESPACE ns X DECL_SPEC acc X int base )
330
find_access(IDENTIFIER *pid, NAMESPACE ns, DECL_SPEC acc, int base)
305
{
331
{
306
    NAMESPACE cns ;
332
    NAMESPACE cns;
307
    CLASS_TYPE ct ;
333
    CLASS_TYPE ct;
308
    TYPE t = NULL_type ;
334
    TYPE t = NULL_type;
309
    IDENTIFIER id = *pid ;
335
    IDENTIFIER id = *pid;
310
 
336
 
311
    /* Find the namespace corresponding to id */
337
    /* Find the namespace corresponding to id */
312
    DECL_SPEC ok = ( dspec_public | dspec_public2 ) ;
338
    DECL_SPEC ok = (dspec_public | dspec_public2);
313
    if ( IS_NULL_id ( id ) ) return ( ok ) ;
339
    if (IS_NULL_id(id)) {
-
 
340
	    return (ok);
-
 
341
    }
314
    if ( IS_id_class_name ( id ) ) {
342
    if (IS_id_class_name(id)) {
315
	cns = find_namespace ( id ) ;
343
	cns = find_namespace(id);
316
    } else {
344
    } else {
317
	cns = DEREF_nspace ( id_parent ( id ) ) ;
345
	cns = DEREF_nspace(id_parent(id));
-
 
346
    }
-
 
347
    if (IS_NULL_nspace(cns)) {
-
 
348
	    return (ok);
318
    }
349
    }
319
    if ( IS_NULL_nspace ( cns ) ) return ( ok ) ;
-
 
320
 
350
 
321
    /* Map block identifiers to the corresponding function */
351
    /* Map block identifiers to the corresponding function */
322
    if ( IS_nspace_block ( cns ) ) {
352
    if (IS_nspace_block(cns)) {
323
	id = DEREF_id ( nspace_name ( cns ) ) ;
353
	id = DEREF_id(nspace_name(cns));
324
	cns = DEREF_nspace ( id_parent ( id ) ) ;
354
	cns = DEREF_nspace(id_parent(id));
325
	*pid = id ;
355
	*pid = id;
326
    }
356
    }
327
 
357
 
328
    /* Allow for equal namespaces */
358
    /* Allow for equal namespaces */
329
    if ( base ) {
359
    if (base) {
330
	ok = ( dspec_private | dspec_public2 ) ;
360
	ok = (dspec_private | dspec_public2);
331
    } else {
361
    } else {
332
	ok = ( dspec_private | dspec_protected2 ) ;
362
	ok = (dspec_private | dspec_protected2);
333
    }
363
    }
334
    if ( EQ_nspace ( cns, ns ) ) {
364
    if (EQ_nspace(cns, ns)) {
335
	ok |= dspec_defn ;
365
	ok |= dspec_defn;
336
	return ( ok ) ;
366
	return (ok);
337
    }
367
    }
338
    ct = namespace_class ( ns ) ;
368
    ct = namespace_class(ns);
339
    ct = expand_ctype ( ct, 2, &t ) ;
369
    ct = expand_ctype(ct, 2, &t);
340
    complete_class ( ct, 1 ) ;
370
    complete_class(ct, 1);
341
 
371
 
342
    /* Check access for classes */
372
    /* Check access for classes */
343
    if ( IS_nspace_ctype ( cns ) ) {
373
    if (IS_nspace_ctype(cns)) {
344
	LIST ( CLASS_TYPE ) fr ;
374
	LIST(CLASS_TYPE)fr;
345
	CLASS_TYPE cs = namespace_class ( cns ) ;
375
	CLASS_TYPE cs = namespace_class(cns);
346
	if ( eq_ctype ( cs, ct ) ) {
376
	if (eq_ctype(cs, ct)) {
347
	    /* Same class */
377
	    /* Same class */
348
	    ok |= dspec_defn ;
378
	    ok |= dspec_defn;
349
	    return ( ok ) ;
379
	    return (ok);
350
	}
380
	}
351
	fr = DEREF_list ( ctype_chums ( cs ) ) ;
381
	fr = DEREF_list(ctype_chums(cs));
352
	while ( !IS_NULL_list ( fr ) ) {
382
	while (!IS_NULL_list(fr)) {
353
	    CLASS_TYPE cr = DEREF_ctype ( HEAD_list ( fr ) ) ;
383
	    CLASS_TYPE cr = DEREF_ctype(HEAD_list(fr));
354
	    if ( eq_ctype ( cr, ct ) ) {
384
	    if (eq_ctype(cr, ct)) {
355
		/* Friend class */
385
		/* Friend class */
356
		ok |= ( dspec_defn | dspec_friend ) ;
386
		ok |= (dspec_defn | dspec_friend);
357
		return ( ok ) ;
387
		return (ok);
358
	    }
388
	    }
359
	    fr = TAIL_list ( fr ) ;
389
	    fr = TAIL_list(fr);
360
	}
390
	}
361
    }
391
    }
362
 
392
 
363
    /* Check for friend functions */
393
    /* Check for friend functions */
364
    if ( IS_id_function_etc ( id ) ) {
394
    if (IS_id_function_etc(id)) {
365
	LIST ( CLASS_TYPE ) fr ;
395
	LIST(CLASS_TYPE)fr;
366
	fr = DEREF_list ( id_function_etc_chums ( id ) ) ;
396
	fr = DEREF_list(id_function_etc_chums(id));
367
	while ( !IS_NULL_list ( fr ) ) {
397
	while (!IS_NULL_list(fr)) {
368
	    CLASS_TYPE cr = DEREF_ctype ( HEAD_list ( fr ) ) ;
398
	    CLASS_TYPE cr = DEREF_ctype(HEAD_list(fr));
369
	    if ( eq_ctype ( cr, ct ) ) {
399
	    if (eq_ctype(cr, ct)) {
370
		/* Friend function */
400
		/* Friend function */
371
		ok |= ( dspec_defn | dspec_friend ) ;
401
		ok |= (dspec_defn | dspec_friend);
372
		return ( ok ) ;
402
		return (ok);
373
	    }
403
	    }
374
	    fr = TAIL_list ( fr ) ;
404
	    fr = TAIL_list(fr);
375
	}
405
	}
376
    }
406
    }
377
 
407
 
378
    /* End here for private members */
408
    /* End here for private members */
379
    if ( acc == dspec_private || base ) {
409
    if (acc == dspec_private || base) {
380
	ok = ( dspec_public | dspec_public2 ) ;
410
	ok = (dspec_public | dspec_public2);
381
	return ( ok ) ;
411
	return (ok);
382
    }
412
    }
383
 
413
 
384
    /* Check access for derived classes */
414
    /* Check access for derived classes */
385
    ok = ( dspec_protected | dspec_protected2 ) ;
415
    ok = (dspec_protected | dspec_protected2);
386
    if ( IS_nspace_ctype ( cns ) ) {
416
    if (IS_nspace_ctype(cns)) {
387
	LIST ( CLASS_TYPE ) fr ;
417
	LIST(CLASS_TYPE)fr;
388
	CLASS_TYPE cs = namespace_class ( cns ) ;
418
	CLASS_TYPE cs = namespace_class(cns);
389
	GRAPH gr = find_base_class ( cs, ct, 0 ) ;
419
	GRAPH gr = find_base_class(cs, ct, 0);
390
	if ( !IS_NULL_graph ( gr ) ) {
420
	if (!IS_NULL_graph(gr)) {
391
	    /* Derived class */
421
	    /* Derived class */
392
	    ok |= dspec_inherit ;
422
	    ok |= dspec_inherit;
393
	    return ( ok ) ;
423
	    return (ok);
394
	}
424
	}
395
	fr = DEREF_list ( ctype_chums ( cs ) ) ;
425
	fr = DEREF_list(ctype_chums(cs));
396
	while ( !IS_NULL_list ( fr ) ) {
426
	while (!IS_NULL_list(fr)) {
397
	    CLASS_TYPE cr = DEREF_ctype ( HEAD_list ( fr ) ) ;
427
	    CLASS_TYPE cr = DEREF_ctype(HEAD_list(fr));
398
	    gr = find_base_class ( cr, ct, 0 ) ;
428
	    gr = find_base_class(cr, ct, 0);
399
	    if ( !IS_NULL_graph ( gr ) ) {
429
	    if (!IS_NULL_graph(gr)) {
400
		/* Friend class of derived class */
430
		/* Friend class of derived class */
401
		ok |= ( dspec_inherit | dspec_friend ) ;
431
		ok |= (dspec_inherit | dspec_friend);
402
		return ( ok ) ;
432
		return (ok);
403
	    }
433
	    }
404
	    fr = TAIL_list ( fr ) ;
434
	    fr = TAIL_list(fr);
405
	}
435
	}
406
    }
436
    }
407
 
437
 
408
    /* Check for derived friend functions */
438
    /* Check for derived friend functions */
409
    if ( IS_id_function_etc ( id ) ) {
439
    if (IS_id_function_etc(id)) {
410
	LIST ( CLASS_TYPE ) fr ;
440
	LIST(CLASS_TYPE)fr;
411
	fr = DEREF_list ( id_function_etc_chums ( id ) ) ;
441
	fr = DEREF_list(id_function_etc_chums(id));
412
	while ( !IS_NULL_list ( fr ) ) {
442
	while (!IS_NULL_list(fr)) {
413
	    CLASS_TYPE cr = DEREF_ctype ( HEAD_list ( fr ) ) ;
443
	    CLASS_TYPE cr = DEREF_ctype(HEAD_list(fr));
414
	    GRAPH gr = find_base_class ( cr, ct, 0 ) ;
444
	    GRAPH gr = find_base_class(cr, ct, 0);
415
	    if ( !IS_NULL_graph ( gr ) ) {
445
	    if (!IS_NULL_graph(gr)) {
416
		/* Friend function of derived class */
446
		/* Friend function of derived class */
417
		ok |= ( dspec_inherit | dspec_friend ) ;
447
		ok |= (dspec_inherit | dspec_friend);
418
		return ( ok ) ;
448
		return (ok);
419
	    }
449
	    }
420
	    fr = TAIL_list ( fr ) ;
450
	    fr = TAIL_list(fr);
421
	}
451
	}
422
    }
452
    }
423
 
453
 
424
    /* Default access */
454
    /* Default access */
425
    ok = ( dspec_public | dspec_public2 ) ;
455
    ok = (dspec_public | dspec_public2);
426
    return ( ok ) ;
456
    return (ok);
427
}
457
}
428
 
458
 
429
 
459
 
430
/*
460
/*
431
    COMPARE ACCESS LEVELS
461
    COMPARE ACCESS LEVELS
432
 
462
 
433
    This routine checks whether the access level ok returned by find_access
463
    This routine checks whether the access level ok returned by find_access
434
    is sufficient to access a member of type tag with declaration specifiers
464
    is sufficient to access a member of type tag with declaration specifiers
435
    ds.  It returns true if the access is an error.
465
    ds.  It returns true if the access is an error.
436
*/
466
*/
437
 
467
 
438
static int compare_access
468
static int
439
    PROTO_N ( ( ok, ds, tag, mem ) )
-
 
440
    PROTO_T ( DECL_SPEC ok X DECL_SPEC ds X unsigned tag X int mem )
469
compare_access(DECL_SPEC ok, DECL_SPEC ds, unsigned tag, int mem)
441
{
470
{
442
    int ret = 0 ;
471
	int ret = 0;
443
    DECL_SPEC acc = ( ds & dspec_access ) ;
472
	DECL_SPEC acc = (ds & dspec_access);
444
    DECL_SPEC level = ( ok & dspec_access ) ;
473
	DECL_SPEC level = (ok & dspec_access);
445
    if ( level < acc ) {
474
	if (level < acc) {
446
	/* Straightforward case */
475
		/* Straightforward case */
447
	ret = 1 ;
476
		ret = 1;
448
    } else {
477
	} else {
449
	/* Deal with inheritance */
478
		/* Deal with inheritance */
450
	if ( ds & dspec_inherit ) {
479
		if (ds & dspec_inherit) {
451
	    DECL_SPEC acc2 = ( ds & dspec_access2 ) ;
480
			DECL_SPEC acc2 = (ds & dspec_access2);
452
	    level = ( ok & dspec_access2 ) ;
481
			level = (ok & dspec_access2);
453
	    if ( level < acc2 ) ret = 1 ;
482
			if (level < acc2) {
-
 
483
				ret = 1;
-
 
484
			}
454
	}
485
		}
455
    }
486
	}
456
    if ( !ret && !mem ) {
487
	if (!ret && !mem) {
457
	if ( tag == id_member_tag || tag == id_mem_func_tag ) {
488
		if (tag == id_member_tag || tag == id_mem_func_tag) {
458
	    /* Check for access through derived class */
489
			/* Check for access through derived class */
459
	    if ( ok & dspec_inherit ) ret = 1 ;
490
			if (ok & dspec_inherit) {
-
 
491
				ret = 1;
-
 
492
			}
-
 
493
		}
460
	}
494
	}
461
    }
-
 
462
    return ( ret ) ;
495
	return (ret);
463
}
496
}
464
 
497
 
465
 
498
 
466
/*
499
/*
467
    CAN AN INHERITED MEMBER BE ACCESSED?
500
    CAN AN INHERITED MEMBER BE ACCESSED?
468
 
501
 
469
    This routine checks whether the inherited class member pid can be
502
    This routine checks whether the inherited class member pid can be
470
    accessed by the identifier id.  If so it returns true.  The direct
503
    accessed by the identifier id.  If so it returns true.  The direct
471
    cases, such as a member of a derived class accessing a member of a
504
    cases, such as a member of a derived class accessing a member of a
472
    base class are handled by the main part of do_member_access, this
505
    base class are handled by the main part of do_member_access, this
473
    routine deals with the indirect cases such as friends of classes
506
    routine deals with the indirect cases such as friends of classes
474
    intermediate between the base class and the derived class.
507
    intermediate between the base class and the derived class.
475
*/
508
*/
476
 
509
 
477
static int inherit_access
510
static int
478
    PROTO_N ( ( id, pid, mem ) )
-
 
479
    PROTO_T ( IDENTIFIER id X IDENTIFIER pid X int mem )
511
inherit_access(IDENTIFIER id, IDENTIFIER pid, int mem)
480
{
512
{
481
    /* Find inheritance base class */
513
	/* Find inheritance base class */
482
    unsigned tag = TAG_id ( pid ) ;
514
	unsigned tag = TAG_id(pid);
483
    IDENTIFIER bid = DEREF_id ( id_alias ( pid ) ) ;
515
	IDENTIFIER bid = DEREF_id(id_alias(pid));
484
    DECL_SPEC acc = DEREF_dspec ( id_storage ( bid ) ) ;
516
	DECL_SPEC acc = DEREF_dspec(id_storage(bid));
485
    NAMESPACE pns = DEREF_nspace ( id_parent ( pid ) ) ;
517
	NAMESPACE pns = DEREF_nspace(id_parent(pid));
486
    NAMESPACE bns = DEREF_nspace ( id_parent ( bid ) ) ;
518
	NAMESPACE bns = DEREF_nspace(id_parent(bid));
487
    CLASS_TYPE ct = namespace_class ( pns ) ;
519
	CLASS_TYPE ct = namespace_class(pns);
488
    CLASS_TYPE cs = namespace_class ( bns ) ;
520
	CLASS_TYPE cs = namespace_class(bns);
489
    GRAPH gr = find_base_class ( ct, cs, 0 ) ;
521
	GRAPH gr = find_base_class(ct, cs, 0);
490
 
522
 
491
    /* Scan through all base classes of ct containing bid */
523
	/* Scan through all base classes of ct containing bid */
492
    while ( !IS_NULL_graph ( gr ) ) {
524
	while (!IS_NULL_graph(gr)) {
493
	GRAPH gs = gr ;
525
		GRAPH gs = gr;
494
	while ( !IS_NULL_graph ( gs ) ) {
526
		while (!IS_NULL_graph(gs)) {
495
	    cs = DEREF_ctype ( graph_head ( gs ) ) ;
527
			cs = DEREF_ctype(graph_head(gs));
496
	    if ( !eq_ctype ( cs, ct ) ) {
528
			if (!eq_ctype(cs, ct)) {
497
		DECL_SPEC ds, ok ;
529
				DECL_SPEC ds, ok;
498
		ds = DEREF_dspec ( graph_access ( gr ) ) ;
530
				ds = DEREF_dspec(graph_access(gr));
499
		ds = join_access ( acc, ds ) ;
531
				ds = join_access(acc, ds);
500
		bns = DEREF_nspace ( ctype_member ( cs ) ) ;
532
				bns = DEREF_nspace(ctype_member(cs));
501
		ok = find_access ( &id, bns, ds, 2 ) ;
533
				ok = find_access(&id, bns, ds, 2);
502
		if ( ok & dspec_defn ) {
534
				if (ok & dspec_defn) {
503
		    /* id is a member or friend of cs */
535
					/* id is a member or friend of cs */
504
		    if ( !compare_access ( ok, ds, tag, mem ) ) {
536
					if (!compare_access(ok, ds, tag, mem)) {
505
			/* Can access bid */
537
						/* Can access bid */
506
			return ( 1 ) ;
538
						return (1);
507
		    }
539
					}
508
		}
540
				}
509
	    }
541
			}
510
	    gs = DEREF_graph ( graph_up ( gs ) ) ;
542
			gs = DEREF_graph(graph_up(gs));
511
	}
543
		}
512
	gr = DEREF_graph ( graph_equal ( gr ) ) ;
544
		gr = DEREF_graph(graph_equal(gr));
513
    }
545
	}
514
    return ( 0 ) ;
546
	return (0);
515
}
547
}
516
 
548
 
517
 
549
 
518
/*
550
/*
519
    CHECK A MEMBER ACCESS
551
    CHECK A MEMBER ACCESS
520
 
552
 
521
    This routine checks the access of the class member pid by the
553
    This routine checks the access of the class member pid by the
522
    identifier id.  It prints an error and returns true if the access
554
    identifier id.  It prints an error and returns true if the access
523
    is illegal.
555
    is illegal.
524
*/
556
*/
525
 
557
 
526
static int do_member_access
558
static int
527
    PROTO_N ( ( id, pid, mem ) )
-
 
528
    PROTO_T ( IDENTIFIER id X IDENTIFIER pid X int mem )
559
do_member_access(IDENTIFIER id, IDENTIFIER pid, int mem)
529
{
560
{
530
    int ret = 0 ;
561
	int ret = 0;
531
    NAMESPACE pns = DEREF_nspace ( id_parent ( pid ) ) ;
562
	NAMESPACE pns = DEREF_nspace(id_parent(pid));
532
    DECL_SPEC ds = DEREF_dspec ( id_storage ( pid ) ) ;
563
	DECL_SPEC ds = DEREF_dspec(id_storage(pid));
533
    DECL_SPEC acc = ( ds & dspec_access ) ;
564
	DECL_SPEC acc = (ds & dspec_access);
534
    DECL_SPEC ok = find_access ( &id, pns, acc, 0 ) ;
565
	DECL_SPEC ok = find_access(&id, pns, acc, 0);
535
    if ( compare_access ( ok, ds, TAG_id ( pid ), mem ) ) {
566
	if (compare_access(ok, ds, TAG_id(pid), mem)) {
536
	if ( ( ds & dspec_inherit ) && inherit_access ( id, pid, mem ) ) {
567
		if ((ds & dspec_inherit) && inherit_access(id, pid, mem)) {
537
	    /* Can access through inheritance */
568
			/* Can access through inheritance */
538
	    /* EMPTY */
569
			/* EMPTY */
539
	} else {
570
		} else {
540
	    /* Report access error */
571
			/* Report access error */
541
	    ERROR err ;
572
			ERROR err;
542
	    if ( IS_NULL_id ( id ) ) {
573
			if (IS_NULL_id(id)) {
543
		err = ERR_class_access_spec_none ( pid, acc ) ;
574
				err = ERR_class_access_spec_none(pid, acc);
544
	    } else {
575
			} else {
545
		err = ERR_class_access_spec_id ( pid, acc, id ) ;
576
				err = ERR_class_access_spec_id(pid, acc, id);
546
	    }
577
			}
547
	    report ( crt_loc, err ) ;
578
			report(crt_loc, err);
548
	    ret = 1 ;
579
			ret = 1;
-
 
580
		}
549
	}
581
	}
550
    }
-
 
551
    return ( ret ) ;
582
	return (ret);
552
}
583
}
553
 
584
 
554
 
585
 
555
/*
586
/*
556
    CHECK A BASE CLASS ACCESS
587
    CHECK A BASE CLASS ACCESS
557
 
588
 
558
    This routine checks the access of the base class gr by the
589
    This routine checks the access of the base class gr by the
559
    identifier id.  It prints an error and returns true if the access
590
    identifier id.  It prints an error and returns true if the access
560
    is illegal.
591
    is illegal.
561
*/
592
*/
562
 
593
 
563
static int do_base_access
594
static int
564
    PROTO_N ( ( id, gr ) )
-
 
565
    PROTO_T ( IDENTIFIER id X GRAPH gr )
595
do_base_access(IDENTIFIER id, GRAPH gr)
566
{
596
{
567
    int ret = 0 ;
597
	int ret = 0;
568
    GRAPH gt = DEREF_graph ( graph_top ( gr ) ) ;
598
	GRAPH gt = DEREF_graph(graph_top(gr));
569
    CLASS_TYPE ct = DEREF_ctype ( graph_head ( gt ) ) ;
599
	CLASS_TYPE ct = DEREF_ctype(graph_head(gt));
570
    NAMESPACE pns = DEREF_nspace ( ctype_member ( ct ) ) ;
600
	NAMESPACE pns = DEREF_nspace(ctype_member(ct));
571
    DECL_SPEC ds = DEREF_dspec ( graph_access ( gr ) ) ;
601
	DECL_SPEC ds = DEREF_dspec(graph_access(gr));
572
    DECL_SPEC acc = ( ds & dspec_access ) ;
602
	DECL_SPEC acc = (ds & dspec_access);
573
    DECL_SPEC ok = find_access ( &id, pns, acc, 1 ) ;
603
	DECL_SPEC ok = find_access(&id, pns, acc, 1);
574
    if ( compare_access ( ok, ds, null_tag, 0 ) ) {
604
	if (compare_access(ok, ds, null_tag, 0)) {
575
	/* Report access error */
605
		/* Report access error */
576
	ERROR err ;
606
		ERROR err;
577
	CLASS_TYPE cs = DEREF_ctype ( graph_head ( gr ) ) ;
607
		CLASS_TYPE cs = DEREF_ctype(graph_head(gr));
578
	if ( IS_NULL_id ( id ) ) {
608
		if (IS_NULL_id(id)) {
579
	    err = ERR_class_access_base_none ( cs, ct, acc ) ;
609
			err = ERR_class_access_base_none(cs, ct, acc);
580
	} else {
610
		} else {
581
	    err = ERR_class_access_base_id ( cs, ct, acc, id ) ;
611
			err = ERR_class_access_base_id(cs, ct, acc, id);
582
	}
612
		}
583
	err = concat_error ( err, ERR_conv_ptr_access () ) ;
613
		err = concat_error(err, ERR_conv_ptr_access());
584
	report ( crt_loc, err ) ;
614
		report(crt_loc, err);
585
	ret = 1 ;
615
		ret = 1;
586
    }
616
	}
587
    return ( ret ) ;
617
	return (ret);
588
}
618
}
589
 
619
 
590
 
620
 
591
/*
621
/*
592
    CLEAR A LIST OF PENDING IDENTIFIER ACCESS CHECKS
622
    CLEAR A LIST OF PENDING IDENTIFIER ACCESS CHECKS
593
 
623
 
594
    This routine clears the list of pending access checks given by p in
624
    This routine clears the list of pending access checks given by p in
595
    the context given by the identifier id.  It returns true if any
625
    the context given by the identifier id.  It returns true if any
596
    results in an error.
626
    results in an error.
597
*/
627
*/
598
 
628
 
599
static int clear_id_access
629
static int
600
    PROTO_N ( ( id, p, r ) )
-
 
601
    PROTO_T ( IDENTIFIER id X LIST ( IDENTIFIER ) p X LIST ( int ) r )
630
clear_id_access(IDENTIFIER id, LIST(IDENTIFIER)p, LIST(int)r)
602
{
631
{
603
    int ret = 0 ;
632
	int ret = 0;
604
    if ( !IS_NULL_list ( p ) ) {
633
	if (!IS_NULL_list(p)) {
605
	int mem = DEREF_int ( HEAD_list ( r ) ) ;
634
		int mem = DEREF_int(HEAD_list(r));
606
	IDENTIFIER pid = DEREF_id ( HEAD_list ( p ) ) ;
635
		IDENTIFIER pid = DEREF_id(HEAD_list(p));
607
	ret = clear_id_access ( id, TAIL_list ( p ), TAIL_list ( r ) ) ;
636
		ret = clear_id_access(id, TAIL_list(p), TAIL_list(r));
608
	if ( !IS_NULL_id ( pid ) && do_member_access ( id, pid, mem ) ) {
637
		if (!IS_NULL_id(pid) && do_member_access(id, pid, mem)) {
609
	    COPY_id ( HEAD_list ( p ), NULL_id ) ;
638
			COPY_id(HEAD_list(p), NULL_id);
610
	    ret = 1 ;
639
			ret = 1;
-
 
640
		}
611
	}
641
	}
612
    }
-
 
613
    return ( ret ) ;
642
	return (ret);
614
}
643
}
615
 
644
 
616
 
645
 
617
/*
646
/*
618
    CLEAR A LIST OF PENDING BASE CLASS ACCESS CHECKS
647
    CLEAR A LIST OF PENDING BASE CLASS ACCESS CHECKS
619
 
648
 
620
    This routine clears the list of pending base class access checks given
649
    This routine clears the list of pending base class access checks given
621
    by p in the context given by the identifier id.  It returns true if
650
    by p in the context given by the identifier id.  It returns true if
622
    any results in an error.
651
    any results in an error.
623
*/
652
*/
624
 
653
 
625
static int clear_base_access
654
static int
626
    PROTO_N ( ( id, p ) )
-
 
627
    PROTO_T ( IDENTIFIER id X LIST ( GRAPH ) p )
655
clear_base_access(IDENTIFIER id, LIST(GRAPH)p)
628
{
656
{
629
    int ret = 0 ;
657
	int ret = 0;
630
    if ( !IS_NULL_list ( p ) ) {
658
	if (!IS_NULL_list(p)) {
631
	GRAPH gr = DEREF_graph ( HEAD_list ( p ) ) ;
659
		GRAPH gr = DEREF_graph(HEAD_list(p));
632
	ret = clear_base_access ( id, TAIL_list ( p ) ) ;
660
		ret = clear_base_access(id, TAIL_list(p));
633
	if ( !IS_NULL_graph ( gr ) && do_base_access ( id, gr ) ) {
661
		if (!IS_NULL_graph(gr) && do_base_access(id, gr)) {
634
	    COPY_graph ( HEAD_list ( p ), NULL_graph ) ;
662
			COPY_graph(HEAD_list(p), NULL_graph);
635
	    ret = 1 ;
663
			ret = 1;
-
 
664
		}
636
	}
665
	}
637
    }
-
 
638
    return ( ret ) ;
666
	return (ret);
639
}
667
}
640
 
668
 
641
 
669
 
642
/*
670
/*
643
    CLEAR A LIST OF PENDING ACCESS CHECKS
671
    CLEAR A LIST OF PENDING ACCESS CHECKS
644
 
672
 
645
    This routine clears the list of pending access checks given by acc in
673
    This routine clears the list of pending access checks given by acc in
646
    the context given by the identifier id.  It returns true if any
674
    the context given by the identifier id.  It returns true if any
647
    results in an error.
675
    results in an error.
648
*/
676
*/
649
 
677
 
650
int clear_access
678
int
651
    PROTO_N ( ( id, acc ) )
-
 
652
    PROTO_T ( IDENTIFIER id X ACCESS_LIST *acc )
679
clear_access(IDENTIFIER id, ACCESS_LIST *acc)
653
{
680
{
654
    int ret = 0 ;
681
	int ret = 0;
655
    if ( acc->pending ) {
682
	if (acc->pending) {
656
	LIST ( IDENTIFIER ) p = acc->ids ;
683
		LIST(IDENTIFIER)p = acc->ids;
657
	LIST ( GRAPH ) q = acc->bases ;
684
		LIST(GRAPH)q = acc->bases;
658
	LIST ( int ) r = acc->info ;
685
		LIST(int)r = acc->info;
659
	if ( !IS_NULL_list ( p ) && clear_id_access ( id, p, r ) ) ret = 1 ;
686
		if (!IS_NULL_list(p) && clear_id_access(id, p, r)) {
-
 
687
			ret = 1;
-
 
688
		}
660
	if ( !IS_NULL_list ( q ) && clear_base_access ( id, q ) ) ret = 1 ;
689
		if (!IS_NULL_list(q) && clear_base_access(id, q)) {
-
 
690
			ret = 1;
661
    }
691
		}
-
 
692
	}
662
    return ( ret ) ;
693
	return (ret);
663
}
694
}
664
 
695
 
665
 
696
 
666
/*
697
/*
667
    CLEAR THE LIST OF CURRENT ACCESSES
698
    CLEAR THE LIST OF CURRENT ACCESSES
668
 
699
 
669
    This routine clears all outstanding accesses in the scope given by id.
700
    This routine clears all outstanding accesses in the scope given by id.
670
    It returns true if any results in an error.
701
    It returns true if any results in an error.
671
*/
702
*/
672
 
703
 
673
int report_access
704
int
674
    PROTO_N ( ( id ) )
-
 
675
    PROTO_T ( IDENTIFIER id )
705
report_access(IDENTIFIER id)
676
{
706
{
677
    ACCESS_LIST *acc = &crt_access_list ;
707
	ACCESS_LIST *acc = &crt_access_list;
678
    int ret = clear_access ( id, acc ) ;
708
	int ret = clear_access(id, acc);
679
    free_access ( acc ) ;
709
	free_access(acc);
680
    return ( ret ) ;
710
	return (ret);
681
}
711
}
682
 
712
 
683
 
713
 
684
/*
714
/*
685
    FREE AN ACCESS LIST
715
    FREE AN ACCESS LIST
686
 
716
 
687
    This routine frees the list of accesses given by acc.
717
    This routine frees the list of accesses given by acc.
688
*/
718
*/
689
 
-
 
690
void free_access
-
 
691
    PROTO_N ( ( acc ) )
-
 
692
    PROTO_T ( ACCESS_LIST *acc )
-
 
693
{
-
 
694
    LIST ( IDENTIFIER ) p = acc->ids ;
-
 
695
    LIST ( GRAPH ) q = acc->bases ;
-
 
696
    LIST ( int ) r = acc->info ;
-
 
697
    if ( !IS_NULL_list ( p ) ) {
-
 
698
	DESTROY_list ( p, SIZE_id ) ;
-
 
699
	acc->ids = NULL_list ( IDENTIFIER ) ;
-
 
700
    }
-
 
701
    if ( !IS_NULL_list ( q ) ) {
-
 
702
	DESTROY_list ( q, SIZE_graph ) ;
-
 
703
	acc->bases = NULL_list ( GRAPH ) ;
-
 
704
    }
-
 
705
    if ( !IS_NULL_list ( r ) ) {
-
 
706
	DESTROY_list ( r, SIZE_int ) ;
-
 
707
	acc->info = NULL_list ( int ) ;
-
 
708
    }
-
 
709
    acc->pending = 0 ;
-
 
710
    acc->inherit = 0 ;
-
 
711
    return ;
-
 
712
}
-
 
713
 
-
 
714
 
-
 
715
/*
-
 
716
    SAVE AN ACCESS LIST
-
 
717
 
-
 
718
    This routine saves the current access list into acc and clears the
-
 
719
    list.
-
 
720
*/
-
 
721
 
719
 
722
void save_access
720
void
723
    PROTO_N ( ( acc ) )
-
 
724
    PROTO_T ( ACCESS_LIST *acc )
721
free_access(ACCESS_LIST *acc)
725
{
722
{
726
    ACCESS_LIST *crt = &crt_access_list ;
-
 
727
    acc->ids = crt->ids ;
723
	LIST(IDENTIFIER)p = acc->ids;
728
    acc->bases = crt->bases ;
724
	LIST(GRAPH)q = acc->bases;
729
    acc->info = crt->info ;
725
	LIST(int)r = acc->info;
730
    acc->pending = crt->pending ;
726
	if (!IS_NULL_list(p)) {
731
    acc->inherit = crt->inherit ;
727
		DESTROY_list(p, SIZE_id);
732
    crt->ids = NULL_list ( IDENTIFIER ) ;
728
		acc->ids = NULL_list(IDENTIFIER);
-
 
729
	}
-
 
730
	if (!IS_NULL_list(q)) {
-
 
731
		DESTROY_list(q, SIZE_graph);
733
    crt->bases = NULL_list ( GRAPH ) ;
732
		acc->bases = NULL_list(GRAPH);
-
 
733
	}
-
 
734
	if (!IS_NULL_list(r)) {
-
 
735
		DESTROY_list(r, SIZE_int);
734
    crt->info = NULL_list ( int ) ;
736
		acc->info = NULL_list(int);
-
 
737
	}
735
    crt->pending = 0 ;
738
	acc->pending = 0;
736
    crt->inherit = 0 ;
739
	acc->inherit = 0;
737
    return ;
740
	return;
738
}
741
}
739
 
742
 
740
 
743
 
741
/*
744
/*
742
    RESTORE AN ACCESS LIST
745
    SAVE AN ACCESS LIST
743
 
746
 
744
    This routine clears the current access list in the scope given by
747
    This routine saves the current access list into acc and clears the
745
    id and resets the current access list the values stored in acc.
748
    list.
746
*/
749
*/
747
 
750
 
748
int restore_access
751
void
749
    PROTO_N ( ( id, acc ) )
-
 
750
    PROTO_T ( IDENTIFIER id X ACCESS_LIST *acc )
752
save_access(ACCESS_LIST *acc)
751
{
753
{
-
 
754
	ACCESS_LIST *crt = &crt_access_list;
-
 
755
	acc->ids = crt->ids;
-
 
756
	acc->bases = crt->bases;
-
 
757
	acc->info = crt->info;
-
 
758
	acc->pending = crt->pending;
-
 
759
	acc->inherit = crt->inherit;
-
 
760
	crt->ids = NULL_list(IDENTIFIER);
-
 
761
	crt->bases = NULL_list(GRAPH);
-
 
762
	crt->info = NULL_list(int);
-
 
763
	crt->pending = 0;
-
 
764
	crt->inherit = 0;
-
 
765
	return;
-
 
766
}
-
 
767
 
-
 
768
 
-
 
769
/*
-
 
770
    RESTORE AN ACCESS LIST
-
 
771
 
-
 
772
    This routine clears the current access list in the scope given by
-
 
773
    id and resets the current access list the values stored in acc.
-
 
774
*/
-
 
775
 
-
 
776
int
-
 
777
restore_access(IDENTIFIER id, ACCESS_LIST *acc)
-
 
778
{
752
    int ret = report_access ( id ) ;
779
	int ret = report_access(id);
753
    ACCESS_LIST *crt = &crt_access_list ;
780
	ACCESS_LIST *crt = &crt_access_list;
754
    crt->ids = acc->ids ;
781
	crt->ids = acc->ids;
755
    crt->bases = acc->bases ;
782
	crt->bases = acc->bases;
756
    crt->info = acc->info ;
783
	crt->info = acc->info;
757
    crt->pending = acc->pending ;
784
	crt->pending = acc->pending;
758
    crt->inherit = acc->inherit ;
785
	crt->inherit = acc->inherit;
759
    return ( ret ) ;
786
	return (ret);
760
}
787
}
761
 
788
 
762
 
789
 
763
/*
790
/*
764
    CHECK THE ACCESS TO AN IDENTIFIER
791
    CHECK THE ACCESS TO AN IDENTIFIER
765
 
792
 
766
    This routine adds the identifier id with access acc to the list of
793
    This routine adds the identifier id with access acc to the list of
767
    pending access checks.  acc will always be dspec_public, dspec_protected
794
    pending access checks.  acc will always be dspec_public, dspec_protected
768
    or dspec_private.
795
    or dspec_private.
769
*/
796
*/
770
 
797
 
771
void check_access
798
void
772
    PROTO_N ( ( id, acc ) )
-
 
773
    PROTO_T ( IDENTIFIER id X DECL_SPEC acc )
799
check_access(IDENTIFIER id, DECL_SPEC acc)
774
{
800
{
775
    if ( acc == dspec_public ) return ;
801
	if (acc == dspec_public) {
-
 
802
		return;
-
 
803
	}
776
    if ( do_access_checks ) {
804
	if (do_access_checks) {
777
	NAMESPACE ns = DEREF_nspace ( id_parent ( id ) ) ;
805
		NAMESPACE ns = DEREF_nspace(id_parent(id));
778
	if ( IS_nspace_ctype ( ns ) ) {
806
		if (IS_nspace_ctype(ns)) {
779
	    ACCESS_LIST *crt = &crt_access_list ;
807
			ACCESS_LIST *crt = &crt_access_list;
780
	    if ( in_function_defn && !in_declaration ) {
808
			if (in_function_defn && !in_declaration) {
781
		/* Calculate access immediately */
809
				/* Calculate access immediately */
782
		IGNORE do_member_access ( crt_func_id, id, crt->inherit ) ;
810
				IGNORE do_member_access(crt_func_id, id,
-
 
811
							crt->inherit);
783
	    } else {
812
			} else {
784
		/* Add to pending list */
813
				/* Add to pending list */
785
		CONS_id ( id, crt->ids, crt->ids ) ;
814
				CONS_id(id, crt->ids, crt->ids);
786
		CONS_int ( crt->inherit, crt->info, crt->info ) ;
815
				CONS_int(crt->inherit, crt->info, crt->info);
787
		crt->pending = 1 ;
816
				crt->pending = 1;
788
	    }
817
			}
789
	} else {
818
		} else {
790
	    DECL_SPEC ds = DEREF_dspec ( id_storage ( id ) ) ;
819
			DECL_SPEC ds = DEREF_dspec(id_storage(id));
791
	    if ( ds & dspec_auto ) {
820
			if (ds & dspec_auto) {
792
		/* Used to mark for-init variables */
821
				/* Used to mark for-init variables */
793
		report ( crt_loc, ERR_stmt_for_init ( id ) ) ;
822
				report(crt_loc, ERR_stmt_for_init(id));
794
		ds &= ~dspec_access ;
823
				ds &= ~dspec_access;
795
		COPY_dspec ( id_storage ( id ), ds ) ;
824
				COPY_dspec(id_storage(id), ds);
796
	    }
825
			}
797
	}
826
		}
798
    }
827
	}
799
    return ;
828
	return;
800
}
829
}
801
 
830
 
802
 
831
 
803
/*
832
/*
804
    CHECK THE ACCESS TO A BASE CLASS
833
    CHECK THE ACCESS TO A BASE CLASS
805
 
834
 
806
    This routine adds the base class graph gr to the list of pending
835
    This routine adds the base class graph gr to the list of pending
807
    base access checks.
836
    base access checks.
808
*/
837
*/
809
 
838
 
810
void check_base_access
839
void
811
    PROTO_N ( ( gr ) )
-
 
812
    PROTO_T ( GRAPH gr )
840
check_base_access(GRAPH gr)
813
{
841
{
814
    DECL_SPEC ds = DEREF_dspec ( graph_access ( gr ) ) ;
842
	DECL_SPEC ds = DEREF_dspec(graph_access(gr));
815
    DECL_SPEC acc = ( ds & dspec_access ) ;
843
	DECL_SPEC acc = (ds & dspec_access);
816
    DECL_SPEC acc2 = ( ds & dspec_access2 ) ;
844
	DECL_SPEC acc2 = (ds & dspec_access2);
817
    if ( acc == dspec_public ) return ;
845
	if (acc == dspec_public) {
-
 
846
		return;
-
 
847
	}
818
 
848
 
819
    if ( do_access_checks ) {
849
	if (do_access_checks) {
820
	/* Find best access to a virtual base */
850
		/* Find best access to a virtual base */
821
	GRAPH gs = DEREF_graph ( graph_equal ( gr ) ) ;
851
		GRAPH gs = DEREF_graph(graph_equal(gr));
822
	while ( !IS_NULL_graph ( gs ) ) {
852
		while (!IS_NULL_graph(gs)) {
823
	    DECL_SPEC pds = DEREF_dspec ( graph_access ( gs ) ) ;
853
			DECL_SPEC pds = DEREF_dspec(graph_access(gs));
824
	    DECL_SPEC pacc = ( pds & dspec_access ) ;
854
			DECL_SPEC pacc = (pds & dspec_access);
825
	    DECL_SPEC pacc2 = ( pds & dspec_access2 ) ;
855
			DECL_SPEC pacc2 = (pds & dspec_access2);
826
	    if ( pacc == dspec_public ) return ;
856
			if (pacc == dspec_public) {
-
 
857
				return;
-
 
858
			}
827
	    if ( pacc < acc || ( pacc == acc && pacc2 < acc2 ) ) {
859
			if (pacc < acc || (pacc == acc && pacc2 < acc2)) {
828
		acc = pacc ;
860
				acc = pacc;
829
		acc2 = pacc2 ;
861
				acc2 = pacc2;
830
		gr = gs ;
862
				gr = gs;
831
	    }
863
			}
832
	    gs = DEREF_graph ( graph_equal ( gs ) ) ;
864
			gs = DEREF_graph(graph_equal(gs));
833
	}
865
		}
834
 
866
 
835
	/* Check access control */
867
		/* Check access control */
836
	if ( in_function_defn && !in_declaration ) {
868
		if (in_function_defn && !in_declaration) {
837
	    /* Calculate access immediately */
869
			/* Calculate access immediately */
838
	    IGNORE do_base_access ( crt_func_id, gr ) ;
870
			IGNORE do_base_access(crt_func_id, gr);
839
	} else {
871
		} else {
840
	    /* Add to pending list */
872
			/* Add to pending list */
841
	    ACCESS_LIST *crt = &crt_access_list ;
873
			ACCESS_LIST *crt = &crt_access_list;
842
	    CONS_graph ( gr, crt->bases, crt->bases ) ;
874
			CONS_graph(gr, crt->bases, crt->bases);
843
	    crt->pending = 1 ;
875
			crt->pending = 1;
844
	}
876
		}
845
    }
877
	}
846
    return ;
878
	return;
847
}
879
}
848
 
880
 
849
 
881
 
850
/*
882
/*
851
    IMMEDIATELY CHECK THE ACCESS TO AN IDENTIFIER
883
    IMMEDIATELY CHECK THE ACCESS TO AN IDENTIFIER
852
 
884
 
853
    This routine applies an immediate access check to the identifier id
885
    This routine applies an immediate access check to the identifier id
854
    by cid.
886
    by cid.
855
*/
887
*/
856
 
888
 
857
void immediate_access
889
void
858
    PROTO_N ( ( cid, id ) )
-
 
859
    PROTO_T ( IDENTIFIER cid X IDENTIFIER id )
890
immediate_access(IDENTIFIER cid, IDENTIFIER id)
860
{
891
{
861
    DECL_SPEC acc = DEREF_dspec ( id_storage ( id ) ) ;
892
	DECL_SPEC acc = DEREF_dspec(id_storage(id));
862
    acc &= dspec_access ;
893
	acc &= dspec_access;
863
    if ( acc == dspec_none || acc == dspec_public ) return ;
894
	if (acc == dspec_none || acc == dspec_public) {
864
    if ( do_access_checks ) {
-
 
865
	NAMESPACE ns = DEREF_nspace ( id_parent ( id ) ) ;
-
 
866
	if ( IS_nspace_ctype ( ns ) ) {
895
		return;
867
	    int mem = crt_access_list.inherit ;
-
 
868
	    IGNORE do_member_access ( cid, id, mem ) ;
-
 
869
	}
896
	}
-
 
897
	if (do_access_checks) {
-
 
898
		NAMESPACE ns = DEREF_nspace(id_parent(id));
-
 
899
		if (IS_nspace_ctype(ns)) {
-
 
900
			int mem = crt_access_list.inherit;
-
 
901
			IGNORE do_member_access(cid, id, mem);
870
    }
902
		}
-
 
903
	}
871
    return ;
904
	return;
872
}
905
}