Warning: Undefined variable $n in /usr/local/www/websvn.planix.org/include/diff_util.php on line 243

Warning: Undefined variable $n in /usr/local/www/websvn.planix.org/include/diff_util.php on line 247

Warning: Undefined variable $m in /usr/local/www/websvn.planix.org/include/diff_util.php on line 251

Warning: Undefined variable $n in /usr/local/www/websvn.planix.org/include/diff_util.php on line 243

Warning: Undefined variable $n in /usr/local/www/websvn.planix.org/include/diff_util.php on line 247

Warning: Undefined variable $m in /usr/local/www/websvn.planix.org/include/diff_util.php on line 251

Warning: Undefined variable $n in /usr/local/www/websvn.planix.org/include/diff_util.php on line 243

Warning: Undefined variable $n in /usr/local/www/websvn.planix.org/include/diff_util.php on line 247

Warning: Undefined variable $m in /usr/local/www/websvn.planix.org/include/diff_util.php on line 251
WebSVN – tendra.SVN – Diff – /trunk/src/producers/common/construct/variable.c – Rev 2 and 7

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
*/
29
 
59
 
30
 
60
 
31
#include "config.h"
61
#include "config.h"
32
#include "c_types.h"
62
#include "c_types.h"
33
#include "ctype_ops.h"
63
#include "ctype_ops.h"
34
#include "exp_ops.h"
64
#include "exp_ops.h"
35
#include "hashid_ops.h"
65
#include "hashid_ops.h"
Line 77... Line 107...
77
    analysis on function parameters and to 2 to suppress all variable
107
    analysis on function parameters and to 2 to suppress all variable
78
    analysis.  The flag anon_c_linkage may be set to true to indicate
108
    analysis.  The flag anon_c_linkage may be set to true to indicate
79
    that objects with C linkage in anonymous namespaces are anonymous.
109
    that objects with C linkage in anonymous namespaces are anonymous.
80
*/
110
*/
81
 
111
 
82
int suppress_variable = 0 ;
112
int suppress_variable = 0;
83
int anon_c_linkage = 0 ;
113
int anon_c_linkage = 0;
84
 
114
 
85
 
115
 
86
/*
116
/*
87
    CHECK A VARIABLE OR FUNCTION USAGE
117
    CHECK A VARIABLE OR FUNCTION USAGE
88
 
118
 
Line 91... Line 121...
91
    example, the reach of a local variable is its scope, that of an internal
121
    example, the reach of a local variable is its scope, that of an internal
92
    variable is its translation unit, and that of an external variable is
122
    variable is its translation unit, and that of an external variable is
93
    its entire program.
123
    its entire program.
94
*/
124
*/
95
 
125
 
96
static void check_usage
126
static void
97
    PROTO_N ( ( id, blk, anon ) )
-
 
98
    PROTO_T ( IDENTIFIER id X EXP blk X int anon )
127
check_usage(IDENTIFIER id, EXP blk, int anon)
99
{
128
{
100
    int opt ;
129
	int opt;
101
    ERROR err ;
130
	ERROR err;
102
    LOCATION loc ;
131
	LOCATION loc;
103
    HASHID nm = DEREF_hashid ( id_name ( id ) ) ;
132
	HASHID nm = DEREF_hashid(id_name(id));
104
    if ( !IS_hashid_anon ( nm ) ) {
133
	if (!IS_hashid_anon(nm)) {
105
	/* Ignore anonymous identifiers */
134
		/* Ignore anonymous identifiers */
106
	DECL_SPEC ds = DEREF_dspec ( id_storage ( id ) ) ;
135
		DECL_SPEC ds = DEREF_dspec(id_storage(id));
107
	if ( anon == ANON_NAMESPACE && ( ds & dspec_c ) ) {
136
		if (anon == ANON_NAMESPACE && (ds & dspec_c)) {
108
	    if ( !anon_c_linkage ) anon = ANON_NONE ;
137
			if (!anon_c_linkage) {
109
	}
-
 
110
	if ( ds & dspec_static ) {
-
 
111
	    if ( !IS_NULL_exp ( blk ) || suppress_variable == 2 ) {
-
 
112
		/* Global statics are external to a block etc. */
-
 
113
		ds |= dspec_extern ;
138
				anon = ANON_NONE;
114
	    }
139
			}
115
	}
140
		}
116
	if ( anon || !( ds & dspec_extern ) ) {
-
 
117
	    if ( ds & dspec_implicit ) {
-
 
118
		/* Ignore implicitly declared constructors etc. */
-
 
119
		/* EMPTY */
-
 
120
	    } else if ( ds & ( dspec_inherit | dspec_alias ) ) {
-
 
121
		/* Don't deal with inherited members here */
-
 
122
		/* EMPTY */
-
 
123
	    } else if ( ds & dspec_token ) {
-
 
124
		/* Ignore tokenised identifiers */
-
 
125
		/* EMPTY */
-
 
126
	    } else if ( ds & dspec_defn ) {
-
 
127
		if ( ds & dspec_used ) {
141
		if (ds & dspec_static) {
128
		    /* Defined and used */
-
 
129
		    /* EMPTY */
-
 
130
		} else {
-
 
131
		    /* Defined but not used */
-
 
132
		    if ( ds & ( dspec_inline | dspec_virtual ) ) {
142
			if (!IS_NULL_exp(blk) || suppress_variable == 2) {
133
			/* Ignore inline and virtual functions */
143
				/* Global statics are external to a block
134
			/* EMPTY */
144
				 * etc. */
135
		    } else {
-
 
136
			if ( ds & dspec_auto ) {
145
				ds |= dspec_extern;
137
			    err = ERR_stmt_dcl_unused ( id ) ;
-
 
138
			} else {
-
 
139
			    if ( ds & dspec_static ) {
-
 
140
				opt = OPT_discard_static ;
-
 
141
			    } else {
-
 
142
				opt = OPT_variable ;
-
 
143
			    }
-
 
144
			    err = ERR_basic_odr_unused ( id ) ;
-
 
145
			    err = set_severity ( err, opt, 0 ) ;
-
 
146
			}
-
 
147
			if ( !IS_NULL_err ( err ) ) {
-
 
148
			    DEREF_loc ( id_loc ( id ), loc ) ;
-
 
149
			    report ( loc, err ) ;
-
 
150
			}
146
			}
151
		    }
-
 
152
		}
147
		}
-
 
148
		if (anon || !(ds & dspec_extern)) {
-
 
149
			if (ds & dspec_implicit) {
-
 
150
				/* Ignore implicitly declared constructors
153
	    } else {
151
				 * etc. */
-
 
152
				/* EMPTY */
-
 
153
			} else if (ds & (dspec_inherit | dspec_alias)) {
-
 
154
				/* Don't deal with inherited members here */
-
 
155
				/* EMPTY */
-
 
156
			} else if (ds & dspec_token) {
-
 
157
				/* Ignore tokenised identifiers */
-
 
158
				/* EMPTY */
-
 
159
			} else if (ds & dspec_defn) {
154
		if ( ds & dspec_used ) {
160
				if (ds & dspec_used) {
-
 
161
					/* Defined and used */
-
 
162
					/* EMPTY */
-
 
163
				} else {
155
		    /* Used but not defined */
164
					/* Defined but not used */
156
		    if ( IS_id_class_name_etc ( id ) ) {
165
					if (ds & (dspec_inline |
-
 
166
						  dspec_virtual)) {
-
 
167
						/* Ignore inline and virtual
157
			/* Alright for type names */
168
						 * functions */
158
			/* EMPTY */
169
						/* EMPTY */
159
		    } else {
170
					} else {
160
			if ( ds & dspec_inline ) {
171
						if (ds & dspec_auto) {
-
 
172
							err = ERR_stmt_dcl_unused(id);
-
 
173
						} else {
-
 
174
							if (ds & dspec_static) {
-
 
175
								opt = OPT_discard_static;
-
 
176
							} else {
-
 
177
								opt = OPT_variable;
-
 
178
							}
161
			    err = ERR_basic_odr_inline ( id ) ;
179
							err = ERR_basic_odr_unused(id);
-
 
180
							err = set_severity(err, opt, 0);
-
 
181
						}
-
 
182
						if (!IS_NULL_err(err)) {
-
 
183
							DEREF_loc(id_loc(id),
-
 
184
								  loc);
-
 
185
							report(loc, err);
-
 
186
						}
-
 
187
					}
-
 
188
				}
162
			} else {
189
			} else {
-
 
190
				if (ds & dspec_used) {
-
 
191
					/* Used but not defined */
-
 
192
					if (IS_id_class_name_etc(id)) {
-
 
193
						/* Alright for type names */
-
 
194
						/* EMPTY */
-
 
195
					} else {
-
 
196
						if (ds & dspec_inline) {
-
 
197
							err = ERR_basic_odr_inline(id);
-
 
198
						} else {
163
			    err = ERR_basic_odr_undef ( id ) ;
199
							err = ERR_basic_odr_undef(id);
-
 
200
						}
-
 
201
						if (!IS_NULL_err(err)) {
-
 
202
							DEREF_loc(id_loc(id),
-
 
203
								  loc);
-
 
204
							report(loc, err);
-
 
205
						}
-
 
206
						ds |= dspec_defn;
-
 
207
						COPY_dspec(id_storage(id), ds);
-
 
208
					}
-
 
209
				} else if (ds & dspec_virtual) {
-
 
210
					/* Undefined virtual function */
-
 
211
					if (ds & dspec_pure) {
-
 
212
						/* Allow pure virtual
-
 
213
						 * functions */
-
 
214
						/* EMPTY */
-
 
215
					} else {
-
 
216
						err = ERR_basic_odr_undef(id);
-
 
217
						if (!IS_NULL_err(err)) {
-
 
218
							DEREF_loc(id_loc(id),
-
 
219
								  loc);
-
 
220
							report(loc, err);
-
 
221
						}
-
 
222
					}
-
 
223
				} else if (ds & dspec_inline) {
-
 
224
					/* Ignore inline functions */
-
 
225
					/* EMPTY */
-
 
226
				} else {
-
 
227
					/* Not used or defined */
-
 
228
					if (ds & dspec_static) {
-
 
229
						opt = OPT_discard_static;
-
 
230
					} else {
-
 
231
						opt = OPT_variable;
-
 
232
					}
-
 
233
					err = ERR_basic_odr_redundant(id);
-
 
234
					err = set_severity(err, opt, 0);
-
 
235
					if (!IS_NULL_err(err)) {
-
 
236
						DEREF_loc(id_loc(id), loc);
-
 
237
						report(loc, err);
-
 
238
					}
-
 
239
				}
164
			}
240
			}
165
			if ( !IS_NULL_err ( err ) ) {
-
 
166
			    DEREF_loc ( id_loc ( id ), loc ) ;
-
 
167
			    report ( loc, err ) ;
-
 
168
			}
-
 
169
			ds |= dspec_defn ;
-
 
170
			COPY_dspec ( id_storage ( id ), ds ) ;
-
 
171
		    }
-
 
172
		} else if ( ds & dspec_virtual ) {
-
 
173
		    /* Undefined virtual function */
-
 
174
		    if ( ds & dspec_pure ) {
-
 
175
			/* Allow pure virtual functions */
-
 
176
			/* EMPTY */
-
 
177
		    } else {
-
 
178
			err = ERR_basic_odr_undef ( id ) ;
-
 
179
			if ( !IS_NULL_err ( err ) ) {
-
 
180
			    DEREF_loc ( id_loc ( id ), loc ) ;
-
 
181
			    report ( loc, err ) ;
-
 
182
			}
-
 
183
		    }
-
 
184
		} else if ( ds & dspec_inline ) {
-
 
185
		    /* Ignore inline functions */
-
 
186
		    /* EMPTY */
-
 
187
		} else {
-
 
188
		    /* Not used or defined */
-
 
189
		    if ( ds & dspec_static ) {
-
 
190
			opt = OPT_discard_static ;
-
 
191
		    } else {
-
 
192
			opt = OPT_variable ;
-
 
193
		    }
-
 
194
		    err = ERR_basic_odr_redundant ( id ) ;
-
 
195
		    err = set_severity ( err, opt, 0 ) ;
-
 
196
		    if ( !IS_NULL_err ( err ) ) {
-
 
197
			DEREF_loc ( id_loc ( id ), loc ) ;
-
 
198
			report ( loc, err ) ;
-
 
199
		    }
-
 
200
		}
241
		}
201
	    }
-
 
202
	}
242
	}
203
    }
-
 
204
    return ;
243
	return;
205
}
244
}
206
 
245
 
207
 
246
 
208
/*
247
/*
209
    CHECK A TEMPLATE IDENTIFIER
248
    CHECK A TEMPLATE IDENTIFIER
Line 211... Line 250...
211
    This routine calls check_identifier for each instance of the template
250
    This routine calls check_identifier for each instance of the template
212
    id.  t gives the template type, otherwise the parameters are as in
251
    id.  t gives the template type, otherwise the parameters are as in
213
    check_identifier.
252
    check_identifier.
214
*/
253
*/
215
 
254
 
216
static void check_template_id
255
static void
-
 
256
check_template_id(TYPE t, IDENTIFIER id, NAMESPACE ns, EXP blk, int anon,
-
 
257
		  int chk)
-
 
258
{
-
 
259
	DECL_SPEC ds = DEREF_dspec(id_storage(id));
-
 
260
	if (!(ds & dspec_done)) {
-
 
261
		/* Scan through template applications */
-
 
262
		TOKEN sort = DEREF_tok(type_templ_sort(t));
-
 
263
		INSTANCE apps = DEREF_inst(tok_templ_apps(sort));
217
    PROTO_N ( ( t, id, ns, blk, anon, chk ) )
264
		COPY_dspec(id_storage(id), (ds | dspec_done));
-
 
265
		while (!IS_NULL_inst(apps)) {
218
    PROTO_T ( TYPE t X IDENTIFIER id X NAMESPACE ns X EXP blk X
266
			DECL_SPEC acc = DEREF_dspec(inst_templ_access(apps));
-
 
267
			if (!(acc & (dspec_main | dspec_alias))) {
-
 
268
				if ((acc & dspec_instance) &&
-
 
269
				    !(acc & dspec_mutable)) {
-
 
270
					IDENTIFIER aid =
-
 
271
					    DEREF_id(inst_templ_id(apps));
-
 
272
					IGNORE check_identifier(aid, ns, blk,
219
	      int anon X int chk )
273
								anon, chk);
-
 
274
				}
-
 
275
			}
-
 
276
			apps = DEREF_inst(inst_next(apps));
-
 
277
		}
-
 
278
		if (spec_unit) {
-
 
279
			spec_unit = save_end(spec_unit, NULL_nspace);
-
 
280
		}
-
 
281
		COPY_dspec(id_storage(id), ds);
-
 
282
	}
-
 
283
	return;
-
 
284
}
-
 
285
 
-
 
286
 
-
 
287
/*
-
 
288
    CHECK A CLASS USAGE
-
 
289
 
-
 
290
    This routine checks the class usage information cu for the type ct.
-
 
291
*/
-
 
292
 
-
 
293
static void
-
 
294
check_class_usage(CLASS_TYPE ct, CLASS_USAGE cu)
220
{
295
{
221
    DECL_SPEC ds = DEREF_dspec ( id_storage ( id ) ) ;
296
	LOCATION loc;
222
    if ( !( ds & dspec_done ) ) {
297
	if (cu & cusage_destr) {
223
	/* Scan through template applications */
-
 
224
	TOKEN sort = DEREF_tok ( type_templ_sort ( t ) ) ;
298
		IDENTIFIER id = DEREF_id(ctype_destr(ct));
225
	INSTANCE apps = DEREF_inst ( tok_templ_apps ( sort ) ) ;
-
 
226
	COPY_dspec ( id_storage ( id ), ( ds | dspec_done ) ) ;
-
 
227
	while ( !IS_NULL_inst ( apps ) ) {
299
		if (!IS_NULL_id(id) && IS_id_mem_func(id)) {
228
	    DECL_SPEC acc = DEREF_dspec ( inst_templ_access ( apps ) ) ;
300
			DECL_SPEC ds = DEREF_dspec(id_storage(id));
229
	    if ( !( acc & ( dspec_main | dspec_alias ) ) ) {
301
			if (!(ds & dspec_trivial)) {
230
		if ( ( acc & dspec_instance ) && !( acc & dspec_mutable ) ) {
-
 
231
		    IDENTIFIER aid = DEREF_id ( inst_templ_id ( apps ) ) ;
302
				DEREF_loc(id_loc(id), loc);
232
		    IGNORE check_identifier ( aid, ns, blk, anon, chk ) ;
303
				report(loc, ERR_expr_delete_post(id));
-
 
304
			}
233
		}
305
		}
234
	    }
-
 
235
	    apps = DEREF_inst ( inst_next ( apps ) ) ;
-
 
236
	}
306
	}
237
	if ( spec_unit ) spec_unit = save_end ( spec_unit, NULL_nspace ) ;
-
 
238
	COPY_dspec ( id_storage ( id ), ds ) ;
-
 
239
    }
-
 
240
    return ;
-
 
241
}
-
 
242
 
-
 
243
 
-
 
244
/*
-
 
245
    CHECK A CLASS USAGE
-
 
246
 
-
 
247
    This routine checks the class usage information cu for the type ct.
-
 
248
*/
-
 
249
 
-
 
250
static void check_class_usage
-
 
251
    PROTO_N ( ( ct, cu ) )
-
 
252
    PROTO_T ( CLASS_TYPE ct X CLASS_USAGE cu )
-
 
253
{
-
 
254
    LOCATION loc ;
-
 
255
    if ( cu & cusage_destr ) {
307
	if (cu & cusage_delete) {
256
	IDENTIFIER id = DEREF_id ( ctype_destr ( ct ) ) ;
308
		IDENTIFIER id = find_operator(ct, lex_delete);
257
	if ( !IS_NULL_id ( id ) && IS_id_mem_func ( id ) ) {
309
		if (!IS_NULL_id(id)) {
258
	    DECL_SPEC ds = DEREF_dspec ( id_storage ( id ) ) ;
-
 
259
	    if ( !( ds & dspec_trivial ) ) {
-
 
260
		DEREF_loc ( id_loc ( id ), loc ) ;
310
			DEREF_loc(id_loc(id), loc);
261
		report ( loc, ERR_expr_delete_post ( id ) ) ;
311
			report(loc, ERR_expr_delete_post(id));
262
	    }
312
		}
263
	}
313
	}
264
    }
-
 
265
    if ( cu & cusage_delete ) {
314
	if (cu & cusage_delete_array) {
266
	IDENTIFIER id = find_operator ( ct, lex_delete ) ;
315
		IDENTIFIER id = find_operator(ct, lex_delete_Harray);
267
	if ( !IS_NULL_id ( id ) ) {
316
		if (!IS_NULL_id(id)) {
268
	    DEREF_loc ( id_loc ( id ), loc ) ;
317
			DEREF_loc(id_loc(id), loc);
269
	    report ( loc, ERR_expr_delete_post ( id ) ) ;
318
			report(loc, ERR_expr_delete_post(id));
270
	}
319
		}
271
    }
-
 
272
    if ( cu & cusage_delete_array ) {
-
 
273
	IDENTIFIER id = find_operator ( ct, lex_delete_Harray ) ;
-
 
274
	if ( !IS_NULL_id ( id ) ) {
-
 
275
	    DEREF_loc ( id_loc ( id ), loc ) ;
-
 
276
	    report ( loc, ERR_expr_delete_post ( id ) ) ;
-
 
277
	}
320
	}
278
    }
-
 
279
    if ( cu & cusage_address ) {
321
	if (cu & cusage_address) {
280
	IDENTIFIER id = find_operator ( ct, lex_and_H1 ) ;
322
		IDENTIFIER id = find_operator(ct, lex_and_H1);
281
	while ( !IS_NULL_id ( id ) && IS_id_function_etc ( id ) ) {
323
		while (!IS_NULL_id(id) && IS_id_function_etc(id)) {
282
	    TYPE t = DEREF_type ( id_function_etc_type ( id ) ) ;
324
			TYPE t = DEREF_type(id_function_etc_type(id));
283
	    if ( min_no_args ( t ) == 1 ) {
325
			if (min_no_args(t) == 1) {
284
		DEREF_loc ( id_loc ( id ), loc ) ;
326
				DEREF_loc(id_loc(id), loc);
285
		report ( loc, ERR_expr_unary_op_ref_post ( id ) ) ;
327
				report(loc, ERR_expr_unary_op_ref_post(id));
286
		break ;
328
				break;
287
	    }
329
			}
288
	    id = DEREF_id ( id_function_etc_over ( id ) ) ;
330
			id = DEREF_id(id_function_etc_over(id));
-
 
331
		}
289
	}
332
	}
290
    }
-
 
291
    return ;
333
	return;
292
}
334
}
293
 
335
 
294
 
336
 
295
/*
337
/*
296
    COMPLETE A TENTATIVE DEFINITION
338
    COMPLETE A TENTATIVE DEFINITION
297
 
339
 
298
    This routine completes a C-style tentative definition of the
340
    This routine completes a C-style tentative definition of the
299
    variable id.  That is, if id has not been defined elsewhere, then
341
    variable id.  That is, if id has not been defined elsewhere, then
300
    it is defined to be zero.
342
    it is defined to be zero.
301
*/
343
*/
302
 
344
 
303
static int define_tentative
345
static int
304
    PROTO_N ( ( id, anon ) )
-
 
305
    PROTO_T ( IDENTIFIER id X int anon )
346
define_tentative(IDENTIFIER id, int anon)
306
{
347
{
307
    int def = 0 ;
348
	int def = 0;
308
    EXP e = DEREF_exp ( id_variable_etc_init ( id ) ) ;
349
	EXP e = DEREF_exp(id_variable_etc_init(id));
309
    if ( !IS_NULL_exp ( e ) && IS_exp_zero ( e ) ) {
350
	if (!IS_NULL_exp(e) && IS_exp_zero(e)) {
310
	LOCATION loc ;
351
		LOCATION loc;
311
	DECL_SPEC ds = DEREF_dspec ( id_storage ( id ) ) ;
352
		DECL_SPEC ds = DEREF_dspec(id_storage(id));
312
	TYPE t = DEREF_type ( id_variable_etc_type ( id ) ) ;
353
		TYPE t = DEREF_type(id_variable_etc_type(id));
313
	bad_crt_loc++ ;
354
		bad_crt_loc++;
314
	loc = crt_loc ;
355
		loc = crt_loc;
315
	DEREF_loc ( id_loc ( id ), crt_loc ) ;
356
		DEREF_loc(id_loc(id), crt_loc);
316
	if ( anon || !( ds & dspec_extern ) ) {
357
		if (anon || !(ds & dspec_extern)) {
317
	    /* Types for internal objects should be complete */
358
			/* Types for internal objects should be complete */
318
	    ERROR err = check_complete ( t ) ;
359
			ERROR err = check_complete(t);
319
	    if ( !IS_NULL_err ( err ) ) {
360
			if (!IS_NULL_err(err)) {
320
		ERROR err2 = ERR_basic_types_tent_incompl ( id ) ;
361
				ERROR err2 = ERR_basic_types_tent_incompl(id);
321
		err = concat_error ( err, err2 ) ;
362
				err = concat_error(err, err2);
322
		report ( crt_loc, err ) ;
363
				report(crt_loc, err);
323
            }
364
			}
324
	}
365
		}
325
	if ( IS_type_array ( t ) ) {
366
		if (IS_type_array(t)) {
326
	    /* Complete array 'A []' to 'A [1]' */
367
			/* Complete array 'A []' to 'A [1]' */
327
	    NAT n = DEREF_nat ( type_array_size ( t ) ) ;
368
			NAT n = DEREF_nat(type_array_size(t));
328
	    if ( IS_NULL_nat ( n ) ) {
369
			if (IS_NULL_nat(n)) {
329
		CV_SPEC qual = DEREF_cv ( type_qual ( t ) ) ;
370
				CV_SPEC qual = DEREF_cv(type_qual(t));
330
		TYPE s = DEREF_type ( type_array_sub ( t ) ) ;
371
				TYPE s = DEREF_type(type_array_sub(t));
331
		n = small_nat [1] ;
372
				n = small_nat[1];
332
		MAKE_type_array ( qual, s, n, t ) ;
373
				MAKE_type_array(qual, s, n, t);
333
		COPY_type ( id_variable_etc_type ( id ), t ) ;
374
				COPY_type(id_variable_etc_type(id), t);
334
	    }
375
			}
335
	}
376
		}
336
	e = init_general ( t, NULL_exp, id, 0 ) ;
377
		e = init_general(t, NULL_exp, id, 0);
337
	COPY_exp ( id_variable_etc_init ( id ), e ) ;
378
		COPY_exp(id_variable_etc_init(id), e);
338
	define_id ( id ) ;
379
		define_id(id);
339
	crt_loc = loc ;
380
		crt_loc = loc;
340
	bad_crt_loc-- ;
381
		bad_crt_loc--;
341
	def = 1 ;
382
		def = 1;
342
    }
383
	}
343
    return ( def ) ;
384
	return (def);
344
}
385
}
345
 
386
 
346
 
387
 
347
/*
388
/*
348
    CHECK A GLOBAL IDENTIFIER
389
    CHECK A GLOBAL IDENTIFIER
349
 
390
 
350
    This routine applies the global program checks to the identifier id
391
    This routine applies the global program checks to the identifier id
351
    from the namespace ns.  If id is a class or namespace name then the
392
    from the namespace ns.  If id is a class or namespace name then the
352
    checks are also applied recursively to the members of id.  The flag
393
    checks are also applied recursively to the members of id.  The flag
353
    anon is true if the parent namespace of id is local to the current
394
    anon is true if the parent namespace of id is local to the current
354
    translation unit.  The routine returns the number of identifiers in
395
    translation unit.  The routine returns the number of identifiers in
355
    id (allowing for overloaded functions).
396
    id (allowing for overloaded functions).
356
*/
397
*/
357
 
398
 
358
unsigned long check_identifier
399
unsigned long
359
    PROTO_N ( ( id, ns, blk, anon, chk ) )
-
 
360
    PROTO_T ( IDENTIFIER id X NAMESPACE ns X EXP blk X int anon X int chk )
400
check_identifier(IDENTIFIER id, NAMESPACE ns, EXP blk, int anon, int chk)
361
{
401
{
362
    unsigned long n = 1 ;
402
	unsigned long n = 1;
-
 
403
	if (spec_unit) {
363
    if ( spec_unit ) spec_unit = save_id ( spec_unit, id, ns ) ;
404
		spec_unit = save_id(spec_unit, id, ns);
-
 
405
	}
364
    switch ( TAG_id ( id ) ) {
406
	switch (TAG_id(id)) {
365
 
-
 
366
	case id_class_name_tag : {
407
	case id_class_name_tag: {
367
	    /* Check the members of a class */
408
		/* Check the members of a class */
368
	    DECL_SPEC ds = DEREF_dspec ( id_storage ( id ) ) ;
409
		DECL_SPEC ds = DEREF_dspec(id_storage(id));
369
	    if ( !( ds & dspec_implicit ) ) {
410
		if (!(ds & dspec_implicit)) {
370
		int templ = 0 ;
411
			int templ = 0;
371
		CLASS_TYPE ct ;
412
			CLASS_TYPE ct;
372
		CLASS_INFO ci ;
413
			CLASS_INFO ci;
373
		NAMESPACE cns ;
414
			NAMESPACE cns;
374
		int tchk = chk ;
415
			int tchk = chk;
375
		TYPE t = DEREF_type ( id_class_name_defn ( id ) ) ;
416
			TYPE t = DEREF_type(id_class_name_defn(id));
376
		TYPE s = t ;
417
			TYPE s = t;
377
		while ( IS_type_templ ( t ) ) {
418
			while (IS_type_templ(t)) {
378
		    /* Template classes */
419
				/* Template classes */
379
		    templ = 1 ;
420
				templ = 1;
380
		    tchk = 0 ;
421
				tchk = 0;
381
		    t = DEREF_type ( type_templ_defn ( t ) ) ;
422
				t = DEREF_type(type_templ_defn(t));
382
		}
423
			}
383
		ct = DEREF_ctype ( type_compound_defn ( t ) ) ;
424
			ct = DEREF_ctype(type_compound_defn(t));
384
		cns = DEREF_nspace ( ctype_member ( ct ) ) ;
425
			cns = DEREF_nspace(ctype_member(ct));
385
		ci = DEREF_cinfo ( ctype_info ( ct ) ) ;
426
			ci = DEREF_cinfo(ctype_info(ct));
386
		if ( ci & cinfo_complete ) {
427
			if (ci & cinfo_complete) {
387
		    /* Check class member namespace */
428
				/* Check class member namespace */
388
		    CLASS_USAGE cu = DEREF_cusage ( ctype_usage ( ct ) ) ;
429
				CLASS_USAGE cu = DEREF_cusage(ctype_usage(ct));
389
		    IDENTIFIER cid = DEREF_id ( ctype_name ( ct ) ) ;
430
				IDENTIFIER cid = DEREF_id(ctype_name(ct));
390
		    HASHID cnm = DEREF_hashid ( id_name ( cid ) ) ;
431
				HASHID cnm = DEREF_hashid(id_name(cid));
391
		    if ( IS_hashid_anon ( cnm ) ) anon = ANON_CLASS ;
432
				if (IS_hashid_anon(cnm)) {
-
 
433
					anon = ANON_CLASS;
-
 
434
				}
392
#if LANGUAGE_CPP
435
#if LANGUAGE_CPP
393
		    if ( ( ci & cinfo_polymorphic ) && tchk ) {
436
				if ((ci & cinfo_polymorphic) && tchk) {
394
			/* Compile virtual function table */
437
					/* Compile virtual function table */
395
			compile_virtual ( ct, anon ) ;
438
					compile_virtual(ct, anon);
396
		    }
439
				}
397
#endif
440
#endif
398
		    if ( cu != cusage_none ) {
441
				if (cu != cusage_none) {
399
			/* Check class usage */
442
					/* Check class usage */
400
			check_class_usage ( ct, cu ) ;
443
					check_class_usage(ct, cu);
401
		    }
444
				}
402
		} else {
445
			} else {
403
		    if ( ( ci & cinfo_incomplete ) && tchk ) {
446
				if ((ci & cinfo_incomplete) && tchk) {
404
			/* Report incomplete types */
447
					/* Report incomplete types */
405
			complete_class ( ct, 0 ) ;
448
					complete_class(ct, 0);
406
			ci = DEREF_cinfo ( ctype_info ( ct ) ) ;
449
					ci = DEREF_cinfo(ctype_info(ct));
407
			if ( !( ci & cinfo_complete ) ) {
450
					if (!(ci & cinfo_complete)) {
408
			    ERROR err = ERR_basic_types_completed ( t ) ;
451
						ERROR err = ERR_basic_types_completed(t);
409
			    if ( !IS_NULL_err ( err ) ) {
452
						if (!IS_NULL_err(err)) {
410
				LOCATION loc ;
453
							LOCATION loc;
411
				DEREF_loc ( id_loc ( id ), loc ) ;
454
							DEREF_loc(id_loc(id),
-
 
455
								  loc);
412
				report ( loc, err ) ;
456
							report(loc, err);
413
			    }
457
						}
-
 
458
					}
-
 
459
				}
-
 
460
				cns = NULL_nspace;
-
 
461
			}
-
 
462
			IGNORE check_namespace(cns, NULL_exp, anon, tchk);
-
 
463
			if (templ) {
-
 
464
				/* Template classes */
-
 
465
				check_template_id(s, id, ns, blk, anon, chk);
414
			}
466
			}
415
		    }
-
 
416
		    cns = NULL_nspace ;
-
 
417
		}
-
 
418
		IGNORE check_namespace ( cns, NULL_exp, anon, tchk ) ;
-
 
419
		if ( templ ) {
-
 
420
		    /* Template classes */
-
 
421
		    check_template_id ( s, id, ns, blk, anon, chk ) ;
-
 
422
		}
467
		}
423
	    }
-
 
424
	    goto type_label ;
468
		goto type_label;
425
	}
-
 
426
 
-
 
427
	case id_enum_name_tag :
-
 
428
	case id_class_alias_tag :
-
 
429
	case id_enum_alias_tag :
-
 
430
	case id_type_alias_tag :
-
 
431
	type_label : {
-
 
432
	    /* Compile type names */
-
 
433
	    if ( chk ) {
-
 
434
		if ( anon ) check_usage ( id, blk, anon ) ;
-
 
435
		if ( IS_NULL_exp ( blk ) ) compile_type ( id ) ;
-
 
436
	    }
-
 
437
	    break ;
-
 
438
	}
-
 
439
 
-
 
440
	case id_nspace_name_tag : {
-
 
441
	    /* Check the members of a namespace */
-
 
442
	    NAMESPACE cns = DEREF_nspace ( id_nspace_name_defn ( id ) ) ;
-
 
443
	    n += check_namespace ( cns, NULL_exp, anon, chk ) ;
-
 
444
	    break ;
-
 
445
	}
469
	}
446
 
-
 
447
	case id_variable_tag : {
470
	case id_enum_name_tag:
-
 
471
	case id_class_alias_tag:
-
 
472
	case id_enum_alias_tag:
-
 
473
	case id_type_alias_tag:
-
 
474
type_label:
448
	    /* Check variable usage */
475
		/* Compile type names */
449
	    if ( chk ) {
476
		if (chk) {
-
 
477
			if (anon) {
450
		DECL_SPEC ds = DEREF_dspec ( id_storage ( id ) ) ;
478
				check_usage(id, blk, anon);
-
 
479
			}
451
		if ( ( ds & dspec_static ) && preserve_all ) {
480
			if (IS_NULL_exp(blk)) {
452
		    compile_preserve ( id ) ;
481
				compile_type(id);
-
 
482
			}
453
		}
483
		}
-
 
484
		break;
-
 
485
	case id_nspace_name_tag: {
-
 
486
		/* Check the members of a namespace */
-
 
487
		NAMESPACE cns = DEREF_nspace(id_nspace_name_defn(id));
-
 
488
		n += check_namespace(cns, NULL_exp, anon, chk);
-
 
489
		break;
-
 
490
	}
-
 
491
	case id_variable_tag:
-
 
492
		/* Check variable usage */
-
 
493
		if (chk) {
-
 
494
			DECL_SPEC ds = DEREF_dspec(id_storage(id));
-
 
495
			if ((ds & dspec_static) && preserve_all) {
-
 
496
				compile_preserve(id);
-
 
497
			}
454
		check_usage ( id, blk, anon ) ;
498
			check_usage(id, blk, anon);
455
		if ( IS_NULL_exp ( blk ) ) {
499
			if (IS_NULL_exp(blk)) {
456
		    if ( ds & dspec_defn ) {
500
				if (ds & dspec_defn) {
457
			IGNORE define_tentative ( id, anon ) ;
501
					IGNORE define_tentative(id, anon);
458
		    }
502
				}
459
		    compile_variable ( id, 0 ) ;
503
				compile_variable(id, 0);
460
		} else {
504
			} else {
461
		    /* End of local block */
505
				/* End of local block */
462
		    if ( ds & dspec_auto ) {
506
				if (ds & dspec_auto) {
463
			EXP term ;
507
					EXP term;
464
			ds &= ~dspec_access ;
508
					ds &= ~dspec_access;
465
			COPY_dspec ( id_storage ( id ), ds ) ;
509
					COPY_dspec(id_storage(id), ds);
466
			term = DEREF_exp ( id_variable_etc_term ( id ) ) ;
510
					term = DEREF_exp(id_variable_etc_term(id));
467
			if ( !IS_NULL_exp ( term ) ) {
511
					if (!IS_NULL_exp(term)) {
-
 
512
						if (do_usage) {
-
 
513
							dump_destr(id,
468
			    if ( do_usage ) dump_destr ( id, &stmt_loc ) ;
514
								   &stmt_loc);
-
 
515
						}
-
 
516
					}
-
 
517
				}
469
			}
518
			}
470
		    }
-
 
471
		}
519
		}
472
	    }
-
 
473
	    break ;
520
		break;
474
	}
-
 
475
 
-
 
476
	case id_parameter_tag : {
521
	case id_parameter_tag: {
477
	    /* Check parameter usage */
522
		/* Check parameter usage */
478
	    if ( chk && suppress_variable == 0 ) {
523
		if (chk && suppress_variable == 0) {
479
		check_usage ( id, blk, anon ) ;
524
			check_usage(id, blk, anon);
480
	    }
525
		}
481
	    break ;
526
		break;
482
	}
527
	}
483
 
528
 
484
	case id_stat_member_tag : {
529
	case id_stat_member_tag:
485
	    /* Check static data member usage */
530
		/* Check static data member usage */
486
	    if ( anon == ANON_CLASS ) {
531
		if (anon == ANON_CLASS) {
487
		LOCATION loc ;
532
			LOCATION loc;
488
		DEREF_loc ( id_loc ( id ), loc ) ;
533
			DEREF_loc(id_loc(id), loc);
489
		report ( loc, ERR_class_static_data_anon ( id ) ) ;
534
			report(loc, ERR_class_static_data_anon(id));
490
	    }
-
 
491
	    if ( chk ) {
-
 
492
		check_usage ( id, blk, anon ) ;
-
 
493
		if ( IS_NULL_exp ( blk ) ) {
-
 
494
		    DECL_SPEC ds = DEREF_dspec ( id_storage ( id ) ) ;
-
 
495
		    if ( ds & dspec_defn ) {
-
 
496
			IGNORE define_tentative ( id, anon ) ;
-
 
497
		    }
-
 
498
		    compile_variable ( id, 0 ) ;
-
 
499
		}
535
		}
-
 
536
		if (chk) {
-
 
537
			check_usage(id, blk, anon);
-
 
538
			if (IS_NULL_exp(blk)) {
-
 
539
				DECL_SPEC ds = DEREF_dspec(id_storage(id));
-
 
540
				if (ds & dspec_defn) {
-
 
541
					IGNORE define_tentative(id, anon);
-
 
542
				}
-
 
543
				compile_variable(id, 0);
-
 
544
			}
-
 
545
		}
-
 
546
		break;
-
 
547
	case id_function_tag:
-
 
548
	case id_mem_func_tag:
-
 
549
	case id_stat_mem_func_tag: {
-
 
550
		/* Check member function usage */
-
 
551
		TYPE t = DEREF_type(id_function_etc_type(id));
-
 
552
		IDENTIFIER over = DEREF_id(id_function_etc_over(id));
-
 
553
		if (!IS_NULL_id(over)) {
-
 
554
			n += check_identifier(over, ns, blk, anon, chk);
-
 
555
		}
-
 
556
		if (IS_type_func(t)) {
-
 
557
			/* Simple functions */
-
 
558
			if (chk) {
-
 
559
				DECL_SPEC ds = DEREF_dspec(id_storage(id));
-
 
560
				if ((ds & dspec_static) && preserve_all) {
-
 
561
					compile_preserve(id);
-
 
562
				}
-
 
563
				if (ds & dspec_inline) {
-
 
564
					if (!anon) {
-
 
565
						anon = ANON_INLINE;
500
	    }
566
					}
-
 
567
				}
-
 
568
				check_usage(id, blk, anon);
-
 
569
				if (IS_NULL_exp(blk)) {
-
 
570
					compile_function(id, 0);
-
 
571
				}
-
 
572
			}
-
 
573
		} else {
-
 
574
			/* Template functions */
-
 
575
			check_template_id(t, id, ns, blk, anon, chk);
-
 
576
		}
501
	    break ;
577
		break;
502
	}
578
	}
503
 
-
 
504
	case id_function_tag :
579
	case id_enumerator_tag:
505
	case id_mem_func_tag :
-
 
506
	case id_stat_mem_func_tag : {
-
 
507
	    /* Check member function usage */
580
		/* Check enumerator value */
508
	    TYPE t = DEREF_type ( id_function_etc_type ( id ) ) ;
-
 
509
	    IDENTIFIER over = DEREF_id ( id_function_etc_over ( id ) ) ;
-
 
510
	    if ( !IS_NULL_id ( over ) ) {
-
 
511
		n += check_identifier ( over, ns, blk, anon, chk ) ;
-
 
512
	    }
-
 
513
	    if ( IS_type_func ( t ) ) {
-
 
514
		/* Simple functions */
-
 
515
		if ( chk ) {
581
		if (chk) {
516
		    DECL_SPEC ds = DEREF_dspec ( id_storage ( id ) ) ;
582
			EXP e = DEREF_exp(id_enumerator_value(id));
517
		    if ( ( ds & dspec_static ) && preserve_all ) {
583
			if (overflow_exp(e)) {
518
			compile_preserve ( id ) ;
584
				compile_variable(id, 0);
519
		    }
-
 
520
		    if ( ds & dspec_inline ) {
-
 
521
			if ( !anon ) anon = ANON_INLINE ;
-
 
522
		    }
585
			}
523
		    check_usage ( id, blk, anon ) ;
-
 
524
		    if ( IS_NULL_exp ( blk ) ) compile_function ( id, 0 ) ;
-
 
525
		}
586
		}
526
	    } else {
-
 
527
		/* Template functions */
-
 
528
		check_template_id ( t, id, ns, blk, anon, chk ) ;
-
 
529
	    }
-
 
530
	    break ;
587
		break;
531
	}
-
 
532
 
-
 
533
	case id_enumerator_tag : {
-
 
534
	    /* Check enumerator value */
-
 
535
	    if ( chk ) {
-
 
536
		EXP e = DEREF_exp ( id_enumerator_value ( id ) ) ;
-
 
537
		if ( overflow_exp ( e ) ) compile_variable ( id, 0 ) ;
-
 
538
	    }
-
 
539
	    break ;
-
 
540
	}
-
 
541
 
-
 
542
	case id_nspace_alias_tag :
588
	case id_nspace_alias_tag:
543
	case id_member_tag :
589
	case id_member_tag:
544
	case id_weak_param_tag : {
590
	case id_weak_param_tag:
545
	    /* Don't check these (yet) */
591
		/* Don't check these (yet) */
546
	    break ;
592
		break;
547
	}
593
	}
548
    }
-
 
549
    return ( n ) ;
594
	return (n);
550
}
595
}
551
 
596
 
552
 
597
 
553
/*
598
/*
554
    CHECK A NAMESPACE
599
    CHECK A NAMESPACE
Line 559... Line 604...
559
    of identifiers declared in ns.  ns may be a block scope associated
604
    of identifiers declared in ns.  ns may be a block scope associated
560
    with the statement blk.  The flag anon is true if the parent namespace
605
    with the statement blk.  The flag anon is true if the parent namespace
561
    of ns is local to the current translation unit.
606
    of ns is local to the current translation unit.
562
*/
607
*/
563
 
608
 
564
unsigned long check_namespace
609
unsigned long
565
    PROTO_N ( ( ns, blk, anon, chk ) )
-
 
566
    PROTO_T ( NAMESPACE ns X EXP blk X int anon X int chk )
610
check_namespace(NAMESPACE ns, EXP blk, int anon, int chk)
567
{
611
{
568
    unsigned long n = 0 ;
612
	unsigned long n = 0;
569
    if ( !IS_NULL_nspace ( ns ) ) {
613
	if (!IS_NULL_nspace(ns)) {
570
	MEMBER mem ;
614
		MEMBER mem;
571
	LIST ( IDENTIFIER ) extra ;
615
		LIST(IDENTIFIER) extra;
572
 
616
 
573
	/* Find namespace components */
617
		/* Find namespace components */
574
	switch ( TAG_nspace ( ns ) ) {
618
		switch (TAG_nspace(ns)) {
575
	    case nspace_named_tag :
619
		case nspace_named_tag:
576
	    case nspace_global_tag :
620
		case nspace_global_tag:
577
	    case nspace_ctype_tag : {
621
		case nspace_ctype_tag:
578
		mem = DEREF_member ( nspace_named_etc_first ( ns ) ) ;
622
			mem = DEREF_member(nspace_named_etc_first(ns));
579
		extra = DEREF_list ( nspace_named_etc_extra ( ns ) ) ;
623
			extra = DEREF_list(nspace_named_etc_extra(ns));
580
		break ;
624
			break;
581
	    }
-
 
582
	    case nspace_unnamed_tag : {
625
		case nspace_unnamed_tag:
583
		mem = DEREF_member ( nspace_unnamed_first ( ns ) ) ;
626
			mem = DEREF_member(nspace_unnamed_first(ns));
584
		extra = DEREF_list ( nspace_unnamed_extra ( ns ) ) ;
627
			extra = DEREF_list(nspace_unnamed_extra(ns));
585
		if ( anon != ANON_GLOBAL && suppress_variable != 2 ) {
628
			if (anon != ANON_GLOBAL && suppress_variable != 2) {
586
		    anon = ANON_NAMESPACE ;
629
				anon = ANON_NAMESPACE;
-
 
630
			}
-
 
631
			break;
-
 
632
		default:
-
 
633
			mem = DEREF_member(nspace_last(ns));
-
 
634
			extra = NULL_list(IDENTIFIER);
-
 
635
			anon = ANON_NONE;
-
 
636
			break;
-
 
637
		}
-
 
638
 
-
 
639
		/* Scan through namespace members */
-
 
640
		while (!IS_NULL_member(mem)) {
-
 
641
			IDENTIFIER id = DEREF_id(member_id(mem));
-
 
642
			IDENTIFIER alt = DEREF_id(member_alt(mem));
-
 
643
			if (!IS_NULL_id(id)) {
-
 
644
				n += check_identifier(id, ns, blk, anon, chk);
-
 
645
			}
-
 
646
			if (!IS_NULL_id(alt) && !EQ_id(id, alt)) {
-
 
647
				n += check_identifier(alt, ns, blk, anon, chk);
-
 
648
			}
-
 
649
			mem = DEREF_member(member_next(mem));
587
		}
650
		}
588
		break ;
-
 
589
	    }
-
 
590
	    default : {
-
 
591
		mem = DEREF_member ( nspace_last ( ns ) ) ;
-
 
592
		extra = NULL_list ( IDENTIFIER ) ;
-
 
593
		anon = ANON_NONE ;
-
 
594
		break ;
-
 
595
	    }
-
 
596
	}
-
 
597
 
651
 
598
	/* Scan through namespace members */
652
		/* Scan through extra namespace members */
599
	while ( !IS_NULL_member ( mem ) ) {
653
		while (!IS_NULL_list(extra)) {
600
	    IDENTIFIER id = DEREF_id ( member_id ( mem ) ) ;
654
			IDENTIFIER id = DEREF_id(HEAD_list(extra));
601
	    IDENTIFIER alt = DEREF_id ( member_alt ( mem ) ) ;
-
 
602
	    if ( !IS_NULL_id ( id ) ) {
-
 
603
		n += check_identifier ( id, ns, blk, anon, chk ) ;
655
			n += check_identifier(id, ns, blk, anon, chk);
604
	    }
-
 
605
	    if ( !IS_NULL_id ( alt ) && !EQ_id ( id, alt ) ) {
-
 
606
		n += check_identifier ( alt, ns, blk, anon, chk ) ;
656
			extra = TAIL_list(extra);
607
	    }
657
		}
608
	    mem = DEREF_member ( member_next ( mem ) ) ;
-
 
609
	}
658
	}
610
 
-
 
611
	/* Scan through extra namespace members */
-
 
612
	while ( !IS_NULL_list ( extra ) ) {
659
	if (spec_unit) {
613
	    IDENTIFIER id = DEREF_id ( HEAD_list ( extra ) ) ;
-
 
614
	    n += check_identifier ( id, ns, blk, anon, chk ) ;
-
 
615
	    extra = TAIL_list ( extra ) ;
660
		spec_unit = save_end(spec_unit, ns);
616
	}
661
	}
617
    }
-
 
618
    if ( spec_unit ) spec_unit = save_end ( spec_unit, ns ) ;
-
 
619
    return ( n ) ;
662
	return (n);
620
}
663
}
621
 
664
 
622
 
665
 
623
/*
666
/*
624
    CHECK THE TOKEN NAMESPACE
667
    CHECK THE TOKEN NAMESPACE
625
 
668
 
626
    This routine applies the usage checks to the tokens declared in the
669
    This routine applies the usage checks to the tokens declared in the
627
    translation unit.
670
    translation unit.
628
*/
671
*/
629
 
672
 
630
static void check_token
673
static void
631
    PROTO_Z ()
674
check_token(void)
632
{
675
{
633
    NAMESPACE ns = token_namespace ;
676
    NAMESPACE ns = token_namespace;
634
    MEMBER mem = DEREF_member ( nspace_global_first ( ns ) ) ;
677
    MEMBER mem = DEREF_member(nspace_global_first(ns));
635
    while ( !IS_NULL_member ( mem ) ) {
678
    while (!IS_NULL_member(mem)) {
636
	IDENTIFIER id = DEREF_id ( member_id ( mem ) ) ;
679
	IDENTIFIER id = DEREF_id(member_id(mem));
637
	if ( !IS_NULL_id ( id ) ) {
680
	if (!IS_NULL_id(id)) {
638
	    DECL_SPEC ds = DEREF_dspec ( id_storage ( id ) ) ;
681
	    DECL_SPEC ds = DEREF_dspec(id_storage(id));
639
	    if ( !( ds & dspec_done ) ) {
682
	    if (!(ds & dspec_done)) {
640
		if ( ds & dspec_defn ) {
683
		if (ds & dspec_defn) {
641
		    /* Defined token */
684
		    /* Defined token */
642
		    compile_token ( id, 1 ) ;
685
		    compile_token(id, 1);
643
		} else if ( !( ds & dspec_pure ) ) {
686
		} else if (!(ds & dspec_pure)) {
644
		    /* Undefined token */
687
		    /* Undefined token */
645
		    LOCATION loc ;
688
		    LOCATION loc;
646
		    TOKEN tok = DEREF_tok ( id_token_sort ( id ) ) ;
689
		    TOKEN tok = DEREF_tok(id_token_sort(id));
647
		    bad_crt_loc++ ;
690
		    bad_crt_loc++;
648
		    loc = crt_loc ;
691
		    loc = crt_loc;
649
		    DEREF_loc ( id_loc ( id ), crt_loc ) ;
692
		    DEREF_loc(id_loc(id), crt_loc);
650
		    if ( IS_tok_func ( tok ) ) {
693
		    if (IS_tok_func(tok)) {
651
			/* Implicitly define 'FUNC' tokens */
694
			/* Implicitly define 'FUNC' tokens */
652
			IDENTIFIER fn = DEREF_id ( id_token_alt ( id ) ) ;
695
			IDENTIFIER fn = DEREF_id(id_token_alt(id));
653
			COPY_id ( tok_func_defn ( tok ), fn ) ;
696
			COPY_id(tok_func_defn(tok), fn);
654
			ds |= dspec_defn ;
697
			ds |= dspec_defn;
655
			COPY_dspec ( id_storage ( id ), ds ) ;
698
			COPY_dspec(id_storage(id), ds);
656
			if ( !( ds & dspec_explicit ) ) {
699
			if (!(ds & dspec_explicit)) {
657
			    /* Not explicitly redeclared */
700
			    /* Not explicitly redeclared */
658
			    report ( crt_loc, ERR_token_def_implicit ( id ) ) ;
701
			    report(crt_loc, ERR_token_def_implicit(id));
659
			}
702
			}
660
			use_func_id ( fn, 0, 0 ) ;
703
			use_func_id(fn, 0, 0);
661
			compile_function ( fn, 0 ) ;
704
			compile_function(fn, 0);
662
			compile_token ( id, 1 ) ;
705
			compile_token(id, 1);
663
		    } else if ( ds & dspec_static ) {
706
		    } else if (ds & dspec_static) {
664
			/* Check for built-in token definitions */
707
			/* Check for built-in token definitions */
665
			if ( builtin_token ( id ) != -1 ) {
708
			if (builtin_token(id)!= -1) {
666
			    ds = DEREF_dspec ( id_storage ( id ) ) ;
709
			    ds = DEREF_dspec(id_storage(id));
667
			    if ( !( ds & dspec_defn ) ) {
710
			    if (!(ds & dspec_defn)) {
668
				compile_token ( id, 0 ) ;
711
				compile_token(id, 0);
669
			    }
712
			    }
670
			} else if ( suppress_variable != 2 ) {
713
			} else if (suppress_variable != 2) {
671
			    compile_token ( id, 0 ) ;
714
			    compile_token(id, 0);
672
			}
715
			}
673
		    }
716
		    }
674
		    crt_loc = loc ;
717
		    crt_loc = loc;
675
		    bad_crt_loc-- ;
718
		    bad_crt_loc--;
676
		}
719
		}
677
	    }
720
	    }
678
	}
721
	}
679
	mem = DEREF_member ( member_next ( mem ) ) ;
722
	mem = DEREF_member(member_next(mem));
680
    }
723
    }
681
    return ;
724
    return;
682
}
725
}
683
 
726
 
684
 
727
 
685
/*
728
/*
686
    CHECK THE GLOBAL NAMESPACE
729
    CHECK THE GLOBAL NAMESPACE
Line 688... Line 731...
688
    This routine applies check_namespace to the global namespace,
731
    This routine applies check_namespace to the global namespace,
689
    including checking the main function if complete is true.  It also
732
    including checking the main function if complete is true.  It also
690
    calls check_token.
733
    calls check_token.
691
*/
734
*/
692
 
735
 
693
unsigned long check_global
736
unsigned long
694
    PROTO_N ( ( complete ) )
-
 
695
    PROTO_T ( int complete )
737
check_global(int complete)
696
{
738
{
697
    /* Check main function if necessary */
739
	/* Check main function if necessary */
698
    unsigned long n ;
740
	unsigned long n;
699
    int anon = ANON_NONE ;
741
	int anon = ANON_NONE;
700
    NAMESPACE ns = global_namespace ;
742
	NAMESPACE ns = global_namespace;
701
    if ( complete && suppress_variable != 2 ) {
743
	if (complete && suppress_variable != 2) {
702
	IDENTIFIER id = main_function ;
744
		IDENTIFIER id = main_function;
703
	HASHID nm = KEYWORD ( lex_main ) ;
745
		HASHID nm = KEYWORD(lex_main);
704
	if ( IS_NULL_id ( id ) ) {
746
		if (IS_NULL_id(id)) {
705
	    /* Look up if not defined */
747
			/* Look up if not defined */
706
	    MEMBER mem = search_member ( ns, nm, 0 ) ;
748
			MEMBER mem = search_member(ns, nm, 0);
707
	    if ( !IS_NULL_member ( mem ) ) {
749
			if (!IS_NULL_member(mem)) {
708
		id = DEREF_id ( member_id ( mem ) ) ;
750
				id = DEREF_id(member_id(mem));
709
		if ( !IS_NULL_id ( id ) && IS_id_function ( id ) ) {
751
				if (!IS_NULL_id(id) && IS_id_function(id)) {
710
		    main_function = id ;
752
					main_function = id;
-
 
753
				} else {
-
 
754
					id = NULL_id;
-
 
755
				}
-
 
756
			}
-
 
757
		}
-
 
758
		if (IS_NULL_id(id)) {
-
 
759
			id = DEREF_id(hashid_id(nm));
-
 
760
			id = underlying_id(id);
-
 
761
			report(builtin_loc, ERR_basic_odr_undef(id));
711
		} else {
762
		} else {
712
		    id = NULL_id ;
-
 
713
		}
-
 
714
	    }
-
 
715
	}
-
 
716
	if ( IS_NULL_id ( id ) ) {
-
 
717
	    id = DEREF_id ( hashid_id ( nm ) ) ;
-
 
718
	    id = underlying_id ( id ) ;
-
 
719
	    report ( builtin_loc, ERR_basic_odr_undef ( id ) ) ;
-
 
720
	} else {
-
 
721
	    /* Mark as being used */
763
			/* Mark as being used */
722
	    DECL_SPEC ds = DEREF_dspec ( id_storage ( id ) ) ;
764
			DECL_SPEC ds = DEREF_dspec(id_storage(id));
723
	    ds |= ( dspec_used | dspec_called ) ;
765
			ds |= (dspec_used | dspec_called);
724
	    COPY_dspec ( id_storage ( id ), ds ) ;
766
			COPY_dspec(id_storage(id), ds);
725
	}
767
		}
726
	anon = ANON_GLOBAL ;
768
		anon = ANON_GLOBAL;
727
    }
769
	}
728
 
770
 
729
    /* Apply checks to namespaces */
771
	/* Apply checks to namespaces */
730
    begin_spec () ;
772
	begin_spec();
731
    n = check_namespace ( ns, NULL_exp, anon, 1 ) ;
773
	n = check_namespace(ns, NULL_exp, anon, 1);
732
    end_spec () ;
774
	end_spec();
733
    check_token () ;
775
	check_token();
734
    return ( n ) ;
776
	return (n);
735
}
777
}
736
 
778
 
737
 
779
 
738
/*
780
/*
739
    CONSTRUCT A SET EXPRESSION
781
    CONSTRUCT A SET EXPRESSION
740
 
782
 
741
    This routine constructs the expression 'set ( a )'.
783
    This routine constructs the expression 'set ( a )'.
742
*/
784
*/
743
 
785
 
744
EXP make_set_exp
786
EXP
745
    PROTO_N ( ( a ) )
-
 
746
    PROTO_T ( EXP a )
787
make_set_exp(EXP a)
747
{
788
{
748
    EXP e ;
789
	EXP e;
749
    a = convert_reference ( a, REF_NORMAL ) ;
790
	a = convert_reference(a, REF_NORMAL);
750
    a = convert_lvalue ( a ) ;
791
	a = convert_lvalue(a);
751
    MAKE_exp_set ( type_void, a, e ) ;
792
	MAKE_exp_set(type_void, a, e);
752
    return ( e ) ;
793
	return (e);
753
}
794
}
754
 
795
 
755
 
796
 
756
/*
797
/*
757
    CONSTRUCT AN UNUSED EXPRESSION
798
    CONSTRUCT AN UNUSED EXPRESSION
758
 
799
 
759
    This routine constructs the expression 'unused ( a )'.
800
    This routine constructs the expression 'unused ( a )'.
760
*/
801
*/
761
 
802
 
762
EXP make_unused_exp
803
EXP
763
    PROTO_N ( ( a ) )
-
 
764
    PROTO_T ( EXP a )
804
make_unused_exp(EXP a)
765
{
805
{
766
    EXP e ;
806
	EXP e;
767
    a = convert_reference ( a, REF_NORMAL ) ;
807
	a = convert_reference(a, REF_NORMAL);
768
    a = convert_lvalue ( a ) ;
808
	a = convert_lvalue(a);
769
    MAKE_exp_unused ( type_void, a, e ) ;
809
	MAKE_exp_unused(type_void, a, e);
770
    return ( e ) ;
810
	return (e);
771
}
811
}
772
 
812
 
773
 
813
 
774
/*
814
/*
775
    PRESERVE ALL STATIC IDENTIFIERS
815
    PRESERVE ALL STATIC IDENTIFIERS
776
 
816
 
777
    This flag is set to true to indicate that all static identifiers
817
    This flag is set to true to indicate that all static identifiers
778
    should be preserved.
818
    should be preserved.
779
*/
819
*/
780
 
820
 
781
int preserve_all = 0 ;
821
int preserve_all = 0;
782
 
822
 
783
 
823
 
784
/*
824
/*
785
    PRESERVE AN IDENTIFIER
825
    PRESERVE AN IDENTIFIER
786
 
826
 
787
    This routine preserves or suspends the static identifier id, as
827
    This routine preserves or suspends the static identifier id, as
788
    indicated by the action act.
828
    indicated by the action act.
789
*/
829
*/
790
 
830
 
791
void preserve_id
831
void
792
    PROTO_N ( ( id, act ) )
-
 
793
    PROTO_T ( IDENTIFIER id X int act )
832
preserve_id(IDENTIFIER id, int act)
794
{
833
{
795
    switch ( TAG_id ( id ) ) {
834
	switch (TAG_id(id)) {
796
	case id_function_tag : {
835
	case id_function_tag: {
797
	    IDENTIFIER over = DEREF_id ( id_function_over ( id ) ) ;
836
		IDENTIFIER over = DEREF_id(id_function_over(id));
798
	    if ( !IS_NULL_id ( over ) ) preserve_id ( over, act ) ;
-
 
799
	    goto action_lab ;
-
 
800
	}
-
 
801
	case id_variable_tag :
-
 
802
	action_lab : {
-
 
803
	    DECL_SPEC ds = DEREF_dspec ( id_storage ( id ) ) ;
-
 
804
	    if ( ds & dspec_static ) {
-
 
805
		if ( act == lex_preserve ) {
837
		if (!IS_NULL_id(over)) {
806
		    compile_preserve ( id ) ;
838
			preserve_id(over, act);
807
		} else if ( act == lex_suspend ) {
-
 
808
		    ds |= dspec_used ;
-
 
809
		    COPY_dspec ( id_storage ( id ), ds ) ;
-
 
810
		}
839
		}
-
 
840
		goto action_lab;
-
 
841
	}
-
 
842
	case id_variable_tag:
-
 
843
action_lab: {
-
 
844
		    DECL_SPEC ds = DEREF_dspec(id_storage(id));
-
 
845
		    if (ds & dspec_static) {
-
 
846
			    if (act == lex_preserve) {
-
 
847
				    compile_preserve(id);
-
 
848
			    } else if (act == lex_suspend) {
-
 
849
				    ds |= dspec_used;
-
 
850
				    COPY_dspec(id_storage(id), ds);
-
 
851
			    }
-
 
852
		    }
-
 
853
		    break;
811
	    }
854
	    }
812
	    break ;
-
 
813
	}
-
 
814
	default : {
855
	default: {
815
	    ERROR err = ERR_pragma_preserve_undecl ( act, id ) ;
856
		ERROR err = ERR_pragma_preserve_undecl(act, id);
816
	    report ( preproc_loc, err ) ;
857
		report(preproc_loc, err);
817
	    break ;
858
		break;
818
	}
859
	}
819
    }
860
	}
820
    return ;
861
	return;
821
}
862
}
822
 
863
 
823
 
864
 
824
/*
865
/*
825
    FLOW ANALYSIS FLAGS
866
    FLOW ANALYSIS FLAGS
Line 828... Line 869...
828
    analysis routines.  The fact that va_variable equals dspec_auto and
869
    analysis routines.  The fact that va_variable equals dspec_auto and
829
    va_done equals dspec_done is important, but the other values are
870
    va_done equals dspec_done is important, but the other values are
830
    merely convenient.
871
    merely convenient.
831
*/
872
*/
832
 
873
 
833
typedef DECL_SPEC VAR_INFO ;
874
typedef DECL_SPEC VAR_INFO;
834
 
875
 
835
#define va_none			dspec_none
876
#define va_none			dspec_none
836
#define va_used_this		dspec_used
877
#define va_used_this		dspec_used
837
#define va_set			dspec_defn
878
#define va_set			dspec_defn
838
#define va_maybe_set		dspec_inherit
879
#define va_maybe_set		dspec_inherit
839
 
880
 
840
#define va_filter		( va_used_this | va_set | va_maybe_set )
881
#define va_filter		(va_used_this | va_set | va_maybe_set)
841
 
882
 
842
#define va_any_use		dspec_static
883
#define va_any_use		dspec_static
843
#define va_any_set		dspec_extern
884
#define va_any_set		dspec_extern
844
 
885
 
845
#define va_done			dspec_done
886
#define va_done			dspec_done
Line 854... Line 895...
854
#define va_partial		dspec_explicit
895
#define va_partial		dspec_explicit
855
#define va_member		dspec_friend
896
#define va_member		dspec_friend
856
#define va_this			dspec_typedef
897
#define va_this			dspec_typedef
857
#define va_dummy		dspec_pure
898
#define va_dummy		dspec_pure
858
 
899
 
859
#define va_alias		( va_alias_used | va_alias_set )
900
#define va_alias		(va_alias_used | va_alias_set)
860
#define va_becomes		( va_assign | va_dummy )
901
#define va_becomes		(va_assign | va_dummy)
861
#define va_other		( va_address | va_becomes | va_partial )
902
#define va_other		(va_address | va_becomes | va_partial)
862
#define va_mask			( va_alias | va_other )
903
#define va_mask			(va_alias | va_other)
863
 
904
 
864
#define va_unreached		dspec_main
905
#define va_unreached		dspec_main
865
 
906
 
866
 
907
 
867
/*
908
/*
Line 869... Line 910...
869
 
910
 
870
    The following declarations are required for the flow analysis
911
    The following declarations are required for the flow analysis
871
    routines.
912
    routines.
872
*/
913
*/
873
 
914
 
874
static VAR_INFO flow_exp PROTO_S ( ( EXP, VAR_INFO ) ) ;
915
static VAR_INFO flow_exp(EXP, VAR_INFO);
875
static VAR_INFO flow_alias_exp PROTO_S ( ( EXP, VAR_INFO ) ) ;
916
static VAR_INFO flow_alias_exp(EXP, VAR_INFO);
876
static VAR_INFO flow_stmt PROTO_S ( ( EXP, VAR_INFO, int ) ) ;
917
static VAR_INFO flow_stmt(EXP, VAR_INFO, int);
877
static VAR_INFO flow_offset PROTO_S ( ( OFFSET, VAR_INFO, int ) ) ;
918
static VAR_INFO flow_offset(OFFSET, VAR_INFO, int);
878
static void set_variable PROTO_S ( ( IDENTIFIER, VAR_INFO ) ) ;
919
static void set_variable(IDENTIFIER, VAR_INFO);
879
 
920
 
880
 
921
 
881
/*
922
/*
882
    LIST OF CURRENTLY ACTIVE VARIABLES
923
    LIST OF CURRENTLY ACTIVE VARIABLES
883
 
924
 
884
    The variable crt_flow_vars is used to hold a list of all the local
925
    The variable crt_flow_vars is used to hold a list of all the local
885
    variables which are in scope at any point in the variable analysis
926
    variables which are in scope at any point in the variable analysis
886
    routines.
927
    routines.
887
*/
928
*/
888
 
929
 
889
typedef LIST ( VARIABLE ) VAR_LIST ;
930
typedef LIST(VARIABLE) VAR_LIST;
890
static VAR_LIST crt_flow_vars = NULL_list ( VARIABLE ) ;
931
static VAR_LIST crt_flow_vars = NULL_list(VARIABLE);
891
static VAR_LIST crt_flow_mems = NULL_list ( VARIABLE ) ;
932
static VAR_LIST crt_flow_mems = NULL_list(VARIABLE);
892
static LIST ( IDENTIFIER ) crt_flow_assign = NULL_list ( IDENTIFIER ) ;
933
static LIST(IDENTIFIER) crt_flow_assign = NULL_list(IDENTIFIER);
893
 
934
 
894
 
935
 
895
/*
936
/*
896
    START VARIABLE ANALYSIS
937
    START VARIABLE ANALYSIS
897
 
938
 
898
    This routine is called at the start of the analysis of the local
939
    This routine is called at the start of the analysis of the local
899
    variable id.
940
    variable id.
900
*/
941
*/
901
 
942
 
902
static void start_variable
943
static void
903
    PROTO_N ( ( id, ds, use ) )
-
 
904
    PROTO_T ( IDENTIFIER id X DECL_SPEC ds X VAR_INFO use )
944
start_variable(IDENTIFIER id, DECL_SPEC ds, VAR_INFO use)
905
{
945
{
906
    VARIABLE var ;
946
	VARIABLE var;
907
    use |= ( va_variable | va_done | va_used_this ) ;
947
	use |= (va_variable | va_done | va_used_this);
908
    if ( !( ds & dspec_used ) ) use |= va_ignore ;
948
	if (!(ds & dspec_used)) {
-
 
949
		use |= va_ignore;
-
 
950
	}
909
    var.id = id ;
951
	var.id = id;
910
    var.info = DEREF_dspec ( id_storage ( id ) ) ;
952
	var.info = DEREF_dspec(id_storage(id));
911
    COPY_dspec ( id_storage ( id ), use ) ;
953
	COPY_dspec(id_storage(id), use);
912
    CONS_var ( var, crt_flow_vars, crt_flow_vars ) ;
954
	CONS_var(var, crt_flow_vars, crt_flow_vars);
913
    DEREF_loc ( id_loc ( id ), stmt_loc ) ;
955
	DEREF_loc(id_loc(id), stmt_loc);
914
    return ;
956
	return;
915
}
957
}
916
 
958
 
917
 
959
 
918
/*
960
/*
919
    SHOULD VARIABLE ANALYSIS BE IGNORED?
961
    SHOULD VARIABLE ANALYSIS BE IGNORED?
920
 
962
 
921
    This routine checks whether any variable analysis errors involving
963
    This routine checks whether any variable analysis errors involving
922
    the local variable id should be ignored.  This is done if id is an
964
    the local variable id should be ignored.  This is done if id is an
923
    anonymous identifier or is a const variable all of whose uses have
965
    anonymous identifier or is a const variable all of whose uses have
924
    been replaced by its definition (see convert_lvalue).
966
    been replaced by its definition (see convert_lvalue).
925
*/
967
*/
926
 
968
 
927
static int ignore_variable
969
static int
928
    PROTO_N ( ( id ) )
-
 
929
    PROTO_T ( IDENTIFIER id )
970
ignore_variable(IDENTIFIER id)
930
{
971
{
931
    HASHID nm = DEREF_hashid ( id_name ( id ) ) ;
972
	HASHID nm = DEREF_hashid(id_name(id));
932
    if ( IS_hashid_anon ( nm ) ) return ( 1 ) ;
973
	if (IS_hashid_anon(nm)) {
-
 
974
		return (1);
-
 
975
	}
933
    if ( IS_id_variable ( id ) ) {
976
	if (IS_id_variable(id)) {
934
	TYPE t = DEREF_type ( id_variable_type ( id ) ) ;
977
		TYPE t = DEREF_type(id_variable_type(id));
935
	CV_SPEC cv = find_cv_qual ( t ) ;
978
		CV_SPEC cv = find_cv_qual(t);
936
	if ( cv & cv_volatile ) {
979
		if (cv & cv_volatile) {
937
	    /* Ignore volatile variables */
980
			/* Ignore volatile variables */
938
	    return ( 1 ) ;
981
			return (1);
939
	}
982
		}
940
	if ( cv == ( cv_const | cv_lvalue ) ) {
983
		if (cv == (cv_const | cv_lvalue)) {
941
	    /* Check for const variables */
984
			/* Check for const variables */
942
	    EXP e = DEREF_exp ( id_variable_init ( id ) ) ;
985
			EXP e = DEREF_exp(id_variable_init(id));
943
	    if ( !IS_NULL_exp ( e ) ) {
986
			if (!IS_NULL_exp(e)) {
944
		if ( IS_exp_int_lit ( e ) ) return ( 1 ) ;
987
				if (IS_exp_int_lit(e)) {
-
 
988
					return (1);
-
 
989
				}
945
		if ( IS_exp_null ( e ) ) return ( 1 ) ;
990
				if (IS_exp_null(e)) {
-
 
991
					return (1);
946
	    }
992
				}
-
 
993
			}
947
	}
994
		}
948
    } else if ( IS_id_member ( id ) ) {
995
	} else if (IS_id_member(id)) {
949
	TYPE t = DEREF_type ( id_member_type ( id ) ) ;
996
		TYPE t = DEREF_type(id_member_type(id));
950
	CV_SPEC cv = find_cv_qual ( t ) ;
997
		CV_SPEC cv = find_cv_qual(t);
951
	if ( cv & cv_volatile ) {
998
		if (cv & cv_volatile) {
952
	    /* Ignore volatile members */
999
			/* Ignore volatile members */
953
	    return ( 1 ) ;
1000
			return (1);
954
	}
1001
		}
955
    }
1002
	}
956
    return ( 0 ) ;
1003
	return (0);
957
}
1004
}
958
 
1005
 
959
 
1006
 
960
/*
1007
/*
961
    END A VARIABLE SETTING
1008
    END A VARIABLE SETTING
962
 
1009
 
963
    This routine marks the end of the variable setting ds.  ret is true if
1010
    This routine marks the end of the variable setting ds.  ret is true if
964
    this end of scope is due to a return statement.  In particular it
1011
    this end of scope is due to a return statement.  In particular it
965
    checks whether the variable has been assigned to and not used.
1012
    checks whether the variable has been assigned to and not used.
966
*/
1013
*/
967
 
1014
 
968
static VAR_INFO end_usage
1015
static VAR_INFO
969
    PROTO_N ( ( id, ds, ret ) )
-
 
970
    PROTO_T ( IDENTIFIER id X VAR_INFO ds X int ret )
1016
end_usage(IDENTIFIER id, VAR_INFO ds, int ret)
971
{
1017
{
972
    if ( ret && ( ds & va_member ) ) {
1018
	if (ret && (ds & va_member)) {
973
	/* Class members are used after return */
1019
		/* Class members are used after return */
974
	if ( ret == 2 ) {
1020
		if (ret == 2) {
975
	    set_variable ( id, va_member ) ;
1021
			set_variable(id, va_member);
976
	    ds = DEREF_dspec ( id_storage ( id ) ) ;
1022
			ds = DEREF_dspec(id_storage(id));
977
	} else {
1023
		} else {
978
	    ds |= va_used_this ;
1024
			ds |= va_used_this;
979
	}
1025
		}
980
    } else if ( !( ds & va_used_this ) && ( ds & va_set ) ) {
1026
	} else if (!(ds & va_used_this) && (ds & va_set)) {
981
	if ( !( ds & va_ignore ) && !ignore_variable ( id ) ) {
1027
		if (!(ds & va_ignore) && !ignore_variable(id)) {
982
	    report ( stmt_loc, ERR_stmt_dcl_reset ( id ) ) ;
1028
			report(stmt_loc, ERR_stmt_dcl_reset(id));
983
	    ds |= va_error ;
1029
			ds |= va_error;
-
 
1030
		}
-
 
1031
		ds |= va_used_this;
984
	}
1032
	}
985
	ds |= va_used_this ;
-
 
986
    }
-
 
987
    return ( ds ) ;
1033
	return (ds);
988
}
1034
}
989
 
1035
 
990
 
1036
 
991
/*
1037
/*
992
    END VARIABLE ANALYSIS
1038
    END VARIABLE ANALYSIS
993
 
1039
 
994
    This routine is called at the end of the analysis of a local
1040
    This routine is called at the end of the analysis of a local
995
    variable.  Note that unused variable have already been dealt with.
1041
    variable.  Note that unused variable have already been dealt with.
996
*/
1042
*/
997
 
1043
 
998
static void end_variable
1044
static void
999
    PROTO_N ( ( flow, ret ) )
-
 
1000
    PROTO_T ( int flow X int ret )
1045
end_variable(int flow, int ret)
1001
{
1046
{
1002
    VARIABLE var ;
1047
	VARIABLE var;
1003
    DESTROY_CONS_var ( destroy, var, crt_flow_vars, crt_flow_vars ) ;
1048
	DESTROY_CONS_var(destroy, var, crt_flow_vars, crt_flow_vars);
1004
    if ( flow ) {
1049
	if (flow) {
1005
	VAR_INFO use = DEREF_dspec ( id_storage ( var.id ) ) ;
1050
		VAR_INFO use = DEREF_dspec(id_storage(var.id));
1006
	use = end_usage ( var.id, use, ret ) ;
1051
		use = end_usage(var.id, use, ret);
1007
	if ( !( use & ( va_member | va_ignore ) ) ) {
1052
		if (!(use & (va_member | va_ignore))) {
1008
	    if ( !( use & va_any_use ) ) {
1053
			if (!(use & va_any_use)) {
1009
		/* Not used in reached code */
1054
				/* Not used in reached code */
1010
		if ( !ignore_variable ( var.id ) ) {
1055
				if (!ignore_variable(var.id)) {
1011
		    LOCATION loc ;
1056
					LOCATION loc;
1012
		    DEREF_loc ( id_loc ( var.id ), loc ) ;
1057
					DEREF_loc(id_loc(var.id), loc);
-
 
1058
					report(loc,
1013
		    report ( loc, ERR_stmt_dcl_unused ( var.id ) ) ;
1059
					       ERR_stmt_dcl_unused(var.id));
1014
		}
1060
				}
1015
	    } else if ( !( use & va_any_set ) ) {
1061
			} else if (!(use & va_any_set)) {
1016
		/* Not set in reached code */
1062
				/* Not set in reached code */
-
 
1063
				if (!(use & va_error) &&
1017
		if ( !( use & va_error ) && !ignore_variable ( var.id ) ) {
1064
				    !ignore_variable(var.id)) {
1018
		    LOCATION loc ;
1065
					LOCATION loc;
1019
		    DEREF_loc ( id_loc ( var.id ), loc ) ;
1066
					DEREF_loc(id_loc(var.id), loc);
1020
		    report ( loc, ERR_stmt_dcl_unset ( var.id ) ) ;
1067
					report(loc, ERR_stmt_dcl_unset(var.id));
1021
		}
1068
				}
1022
	    }
1069
			}
1023
	}
1070
		}
1024
    }
1071
	}
1025
    COPY_dspec ( id_storage ( var.id ), var.info ) ;
1072
	COPY_dspec(id_storage(var.id), var.info);
1026
    return ;
1073
	return;
1027
}
1074
}
1028
 
1075
 
1029
 
1076
 
1030
/*
1077
/*
1031
    SET A VARIABLE
1078
    SET A VARIABLE
1032
 
1079
 
1033
    This routine adjusts the variable analysis information for the local
1080
    This routine adjusts the variable analysis information for the local
1034
    variable use according to the analysis state use.
1081
    variable use according to the analysis state use.
1035
*/
1082
*/
1036
 
1083
 
1037
static void set_variable
1084
static void
-
 
1085
set_variable(IDENTIFIER id, VAR_INFO use)
-
 
1086
{
-
 
1087
	if (!(use & va_unreached)) {
-
 
1088
		VAR_INFO ds = DEREF_dspec(id_storage(id));
-
 
1089
		if (use & va_assign) {
-
 
1090
			/* Assignment */
-
 
1091
			if (use & va_dummy) {
-
 
1092
				set_variable(id, va_none);
-
 
1093
				ds = DEREF_dspec(id_storage(id));
-
 
1094
			}
-
 
1095
			if (use & va_partial) {
-
 
1096
				/* Partial assignment */
-
 
1097
				ds |= (va_maybe_set | va_any_set);
-
 
1098
				ds |= va_used_this;
-
 
1099
			} else {
-
 
1100
				/* Complete assignment */
-
 
1101
				ds = end_usage(id, ds, 0);
-
 
1102
				if (ds & va_assign) {
-
 
1103
					if (!(ds & va_ignore) &&
-
 
1104
					    !ignore_variable(id)) {
-
 
1105
						/* Multiple assignments */
-
 
1106
						report(stmt_loc,
-
 
1107
						       ERR_expr_ass_twice(id));
-
 
1108
						ds |= va_error;
-
 
1109
					}
-
 
1110
				}
-
 
1111
				CONS_id(id, crt_flow_assign, crt_flow_assign);
-
 
1112
				ds |= (va_set | va_maybe_set | va_any_set |
-
 
1113
				       va_assign);
-
 
1114
				ds &= ~va_used_this;
-
 
1115
			}
-
 
1116
		} else if (use & va_alias_set) {
-
 
1117
			/* Read-write alias */
-
 
1118
			ds |= (va_maybe_set | va_any_set);
-
 
1119
			ds |= (va_used_this | va_any_use);
-
 
1120
		} else if (use & va_alias_used) {
-
 
1121
			/* Read-only alias */
-
 
1122
			ds |= (va_used_this | va_any_use);
-
 
1123
		} else if (use & va_address) {
-
 
1124
			/* Address */
-
 
1125
			ds |= (va_used_this | va_any_use);
-
 
1126
		} else {
-
 
1127
			/* Use */
-
 
1128
			if (!(ds & (va_set | va_maybe_set))) {
-
 
1129
				/* Used without being set */
-
 
1130
				if (!(ds & va_ignore) && !ignore_variable(id)) {
-
 
1131
					ERROR err;
-
 
1132
					if (use & va_member) {
-
 
1133
						err = ERR_class_base_init_none(id);
-
 
1134
					} else {
-
 
1135
						err = ERR_stmt_dcl_unset(id);
-
 
1136
					}
-
 
1137
					report(stmt_loc, err);
-
 
1138
					ds |= va_error;
-
 
1139
				}
-
 
1140
				ds |= (va_maybe_set | va_any_set);
-
 
1141
			}
-
 
1142
			ds |= (va_used_this | va_any_use);
-
 
1143
		}
-
 
1144
		COPY_dspec(id_storage(id), ds);
-
 
1145
	}
-
 
1146
	return;
-
 
1147
}
-
 
1148
 
-
 
1149
 
-
 
1150
/*
1038
    PROTO_N ( ( id, use ) )
1151
    SET ALL CLASS MEMBERS
-
 
1152
 
-
 
1153
    This routine calls set_variable for each of the class members in the
-
 
1154
    current variable list.
-
 
1155
*/
-
 
1156
 
-
 
1157
static void
1039
    PROTO_T ( IDENTIFIER id X VAR_INFO use )
1158
set_members(VAR_INFO use)
1040
{
1159
{
1041
    if ( !( use & va_unreached ) ) {
1160
	if (!(use & va_unreached)) {
1042
	VAR_INFO ds = DEREF_dspec ( id_storage ( id ) ) ;
1161
		VAR_LIST va = crt_flow_mems;
1043
	if ( use & va_assign ) {
1162
		while (!IS_NULL_list(va)) {
1044
	    /* Assignment */
-
 
1045
	    if ( use & va_dummy ) {
1163
			IDENTIFIER id = DEREF_id(var_id(HEAD_list(va)));
1046
		set_variable ( id, va_none ) ;
1164
			set_variable(id, use);
1047
		ds = DEREF_dspec ( id_storage ( id ) ) ;
-
 
1048
	    }
-
 
1049
	    if ( use & va_partial ) {
-
 
1050
		/* Partial assignment */
-
 
1051
		ds |= ( va_maybe_set | va_any_set ) ;
-
 
1052
		ds |= va_used_this ;
-
 
1053
	    } else {
-
 
1054
		/* Complete assignment */
-
 
1055
		ds = end_usage ( id, ds, 0 ) ;
-
 
1056
		if ( ds & va_assign ) {
-
 
1057
		    if ( !( ds & va_ignore ) && !ignore_variable ( id ) ) {
-
 
1058
			/* Multiple assignments */
-
 
1059
			report ( stmt_loc, ERR_expr_ass_twice ( id ) ) ;
-
 
1060
			ds |= va_error ;
1165
			va = TAIL_list(va);
1061
		    }
-
 
1062
		}
1166
		}
1063
		CONS_id ( id, crt_flow_assign, crt_flow_assign ) ;
-
 
1064
		ds |= ( va_set | va_maybe_set | va_any_set | va_assign ) ;
-
 
1065
		ds &= ~va_used_this ;
-
 
1066
	    }
-
 
1067
 
-
 
1068
	} else if ( use & va_alias_set ) {
-
 
1069
	    /* Read-write alias */
-
 
1070
	    ds |= ( va_maybe_set | va_any_set ) ;
-
 
1071
	    ds |= ( va_used_this | va_any_use ) ;
-
 
1072
 
-
 
1073
	} else if ( use & va_alias_used ) {
-
 
1074
	    /* Read-only alias */
-
 
1075
	    ds |= ( va_used_this | va_any_use ) ;
-
 
1076
 
-
 
1077
	} else if ( use & va_address ) {
-
 
1078
	    /* Address */
-
 
1079
	    ds |= ( va_used_this | va_any_use ) ;
-
 
1080
 
-
 
1081
	} else {
-
 
1082
	    /* Use */
-
 
1083
	    if ( !( ds & ( va_set | va_maybe_set ) ) ) {
-
 
1084
		/* Used without being set */
-
 
1085
		if ( !( ds & va_ignore ) && !ignore_variable ( id ) ) {
-
 
1086
		    ERROR err ;
-
 
1087
		    if ( use & va_member ) {
-
 
1088
			err = ERR_class_base_init_none ( id ) ;
-
 
1089
		    } else {
-
 
1090
			err = ERR_stmt_dcl_unset ( id ) ;
-
 
1091
		    }
-
 
1092
		    report ( stmt_loc, err ) ;
-
 
1093
		    ds |= va_error ;
-
 
1094
		}
-
 
1095
		ds |= ( va_maybe_set | va_any_set ) ;
-
 
1096
	    }
-
 
1097
	    ds |= ( va_used_this | va_any_use ) ;
-
 
1098
	}
1167
	}
1099
	COPY_dspec ( id_storage ( id ), ds ) ;
-
 
1100
    }
-
 
1101
    return ;
1168
	return;
1102
}
1169
}
1103
 
1170
 
1104
 
1171
 
1105
/*
1172
/*
1106
    SET ALL CLASS MEMBERS
-
 
1107
 
-
 
1108
    This routine calls set_variable for each of the class members in the
-
 
1109
    current variable list.
-
 
1110
*/
-
 
1111
 
-
 
1112
static void set_members
-
 
1113
    PROTO_N ( ( use ) )
-
 
1114
    PROTO_T ( VAR_INFO use )
-
 
1115
{
-
 
1116
    if ( !( use & va_unreached ) ) {
-
 
1117
	VAR_LIST va = crt_flow_mems ;
-
 
1118
	while ( !IS_NULL_list ( va ) ) {
-
 
1119
	    IDENTIFIER id = DEREF_id ( var_id ( HEAD_list ( va ) ) ) ;
-
 
1120
	    set_variable ( id, use ) ;
-
 
1121
	    va = TAIL_list ( va ) ;
-
 
1122
	}
-
 
1123
    }
-
 
1124
    return ;
-
 
1125
}
-
 
1126
 
-
 
1127
 
-
 
1128
/*
-
 
1129
    MERGE A VARIABLE SETTING
1173
    MERGE A VARIABLE SETTING
1130
 
1174
 
1131
    This routine merges the variable analysis settings given by dp and dq.
1175
    This routine merges the variable analysis settings given by dp and dq.
1132
    u indicates whether the variable set values are to be taken from dp,
1176
    u indicates whether the variable set values are to be taken from dp,
1133
    from dq, from both, or from neither.
1177
    from dq, from both, or from neither.
1134
*/
1178
*/
1135
 
1179
 
1136
static VAR_INFO merge_usage
1180
static VAR_INFO
1137
    PROTO_N ( ( dp, dq, u ) )
-
 
1138
    PROTO_T ( VAR_INFO dp X VAR_INFO dq X int u )
1181
merge_usage(VAR_INFO dp, VAR_INFO dq, int u)
1139
{
1182
{
1140
    VAR_INFO ds = ( dp | dq ) ;
1183
	VAR_INFO ds = (dp | dq);
1141
    VAR_INFO dt = dspec_none ;
1184
	VAR_INFO dt = dspec_none;
1142
    switch ( u ) {
1185
	switch (u) {
-
 
1186
	case 0:
1143
	case 0 : dt = ( dp & dq ) ; break ;
1187
		dt = (dp & dq);
-
 
1188
		break;
-
 
1189
	case 1:
1144
	case 1 : dt = dp ; break ;
1190
		dt = dp;
-
 
1191
		break;
-
 
1192
	case 2:
1145
	case 2 : dt = dq ; break ;
1193
		dt = dq;
-
 
1194
		break;
1146
    }
1195
	}
1147
    ds = ( ( ds & ~va_filter ) | ( dt & va_filter ) ) ;
1196
	ds = ((ds & ~va_filter) | (dt & va_filter));
1148
    return ( ds ) ;
1197
	return (ds);
1149
}
1198
}
1150
 
1199
 
1151
 
1200
 
1152
/*
1201
/*
1153
    SEARCH A LIST OF VARIABLES
1202
    SEARCH A LIST OF VARIABLES
1154
 
1203
 
1155
    This routine searches the list of variables p for one corresponding to
1204
    This routine searches the list of variables p for one corresponding to
1156
    id.  q is a member of p which corresponds to id is the simplest case.
1205
    id.  q is a member of p which corresponds to id is the simplest case.
1157
    It returns a pointer to the variable if it exists and a null pointer
1206
    It returns a pointer to the variable if it exists and a null pointer
1158
    otherwise.
1207
    otherwise.
1159
*/
1208
*/
1160
 
1209
 
1161
static PTR ( VARIABLE ) search_vars
1210
static PTR(VARIABLE)
1162
    PROTO_N ( ( p, q, id ) )
-
 
1163
    PROTO_T ( VAR_LIST p X VAR_LIST q X IDENTIFIER id )
1211
search_vars(VAR_LIST p, VAR_LIST q, IDENTIFIER id)
1164
{
1212
{
1165
    if ( !IS_NULL_list ( q ) ) {
1213
	if (!IS_NULL_list(q)) {
1166
	PTR ( VARIABLE ) ptr = HEAD_list ( q ) ;
1214
		PTR(VARIABLE) ptr = HEAD_list(q);
1167
	IDENTIFIER pid = DEREF_id ( var_id ( ptr ) ) ;
1215
		IDENTIFIER pid = DEREF_id(var_id(ptr));
1168
	if ( EQ_id ( pid, id ) ) return ( ptr ) ;
1216
		if (EQ_id(pid, id)) {
-
 
1217
			return (ptr);
1169
    }
1218
		}
-
 
1219
	}
1170
    while ( !IS_NULL_list ( p ) ) {
1220
	while (!IS_NULL_list(p)) {
1171
	PTR ( VARIABLE ) ptr = HEAD_list ( p ) ;
1221
		PTR(VARIABLE) ptr = HEAD_list(p);
1172
	IDENTIFIER pid = DEREF_id ( var_id ( ptr ) ) ;
1222
		IDENTIFIER pid = DEREF_id(var_id(ptr));
1173
	if ( EQ_id ( pid, id ) ) return ( ptr ) ;
1223
		if (EQ_id(pid, id)) {
-
 
1224
			return (ptr);
-
 
1225
		}
1174
	p = TAIL_list ( p ) ;
1226
		p = TAIL_list(p);
1175
    }
1227
	}
1176
    return ( NULL_ptr ( VARIABLE ) ) ;
1228
	return (NULL_ptr(VARIABLE));
1177
}
1229
}
1178
 
1230
 
1179
 
1231
 
1180
/*
1232
/*
1181
    SAVE CURRENT VARIABLE SETTINGS
1233
    SAVE CURRENT VARIABLE SETTINGS
1182
 
1234
 
1183
    This routine saves the current variable settings by merging them with
1235
    This routine saves the current variable settings by merging them with
1184
    those stored in the list va.
1236
    those stored in the list va.
1185
*/
1237
*/
1186
 
1238
 
1187
static VAR_LIST save_vars
1239
static VAR_LIST
1188
    PROTO_N ( ( va, cond ) )
-
 
1189
    PROTO_T ( VAR_LIST va X int cond )
1240
save_vars(VAR_LIST va, int cond)
1190
{
1241
{
1191
    VAR_LIST vb = crt_flow_vars ;
1242
	VAR_LIST vb = crt_flow_vars;
1192
    VAR_LIST vc = va ;
1243
	VAR_LIST vc = va;
1193
    VAR_LIST vd = va ;
1244
	VAR_LIST vd = va;
1194
    while ( !IS_NULL_list ( vb ) ) {
1245
	while (!IS_NULL_list(vb)) {
1195
	VARIABLE var ;
1246
		VARIABLE var;
1196
	PTR ( VARIABLE ) pvar ;
1247
		PTR(VARIABLE) pvar;
1197
	var.id = DEREF_id ( var_id ( HEAD_list ( vb ) ) ) ;
1248
		var.id = DEREF_id(var_id(HEAD_list(vb)));
1198
	var.info = DEREF_dspec ( id_storage ( var.id ) ) ;
1249
		var.info = DEREF_dspec(id_storage(var.id));
1199
	if ( cond ) {
1250
		if (cond) {
1200
	    var.info |= va_used_this ;
1251
			var.info |= va_used_this;
1201
	    COPY_dspec ( id_storage ( var.id ), var.info ) ;
1252
			COPY_dspec(id_storage(var.id), var.info);
1202
	}
1253
		}
1203
	pvar = search_vars ( vc, vd, var.id ) ;
1254
		pvar = search_vars(vc, vd, var.id);
1204
	if ( IS_NULL_ptr ( pvar ) ) {
1255
		if (IS_NULL_ptr(pvar)) {
1205
	    /* Add new identifier to list */
1256
			/* Add new identifier to list */
1206
	    CONS_var ( var, va, va ) ;
1257
			CONS_var(var, va, va);
1207
	} else {
1258
		} else {
1208
	    /* Merge with existing information */
1259
			/* Merge with existing information */
1209
	    VAR_INFO acc = DEREF_dspec ( var_info ( pvar ) ) ;
1260
			VAR_INFO acc = DEREF_dspec(var_info(pvar));
1210
	    acc = merge_usage ( acc, var.info, 0 ) ;
1261
			acc = merge_usage(acc, var.info, 0);
1211
	    COPY_dspec ( var_info ( pvar ), acc ) ;
1262
			COPY_dspec(var_info(pvar), acc);
-
 
1263
		}
-
 
1264
		if (!IS_NULL_list(vd)) {
-
 
1265
			vd = TAIL_list(vd);
-
 
1266
		}
-
 
1267
		vb = TAIL_list(vb);
-
 
1268
	}
-
 
1269
	if (IS_NULL_list(vc)) {
-
 
1270
		va = REVERSE_list(va);
1212
	}
1271
	}
1213
	if ( !IS_NULL_list ( vd ) ) vd = TAIL_list ( vd ) ;
-
 
1214
	vb = TAIL_list ( vb ) ;
-
 
1215
    }
-
 
1216
    if ( IS_NULL_list ( vc ) ) va = REVERSE_list ( va ) ;
-
 
1217
    return ( va ) ;
1272
	return (va);
1218
}
1273
}
1219
 
1274
 
1220
 
1275
 
1221
/*
1276
/*
1222
    LOAD CURRENT VARIABLE SETTINGS
1277
    LOAD CURRENT VARIABLE SETTINGS
1223
 
1278
 
1224
    This routine loads the current variable settings by merging them with
1279
    This routine loads the current variable settings by merging them with
1225
    those stored in the list va.
1280
    those stored in the list va.
1226
*/
1281
*/
1227
 
1282
 
1228
static void load_vars
1283
static void
1229
    PROTO_N ( ( va, u ) )
-
 
1230
    PROTO_T ( VAR_LIST va X int u )
1284
load_vars(VAR_LIST va, int u)
1231
{
1285
{
1232
    VAR_LIST vb = crt_flow_vars ;
1286
	VAR_LIST vb = crt_flow_vars;
1233
    VAR_LIST vc = va ;
1287
	VAR_LIST vc = va;
1234
    while ( !IS_NULL_list ( vb ) ) {
1288
	while (!IS_NULL_list(vb)) {
1235
	IDENTIFIER id = DEREF_id ( var_id ( HEAD_list ( vb ) ) ) ;
1289
		IDENTIFIER id = DEREF_id(var_id(HEAD_list(vb)));
1236
	VAR_INFO acc = DEREF_dspec ( id_storage ( id ) ) ;
1290
		VAR_INFO acc = DEREF_dspec(id_storage(id));
1237
	PTR ( VARIABLE ) pvar = search_vars ( va, vc, id ) ;
1291
		PTR(VARIABLE)pvar = search_vars(va, vc, id);
1238
	if ( !IS_NULL_ptr ( pvar ) ) {
1292
		if (!IS_NULL_ptr(pvar)) {
1239
	    VAR_INFO pacc = DEREF_dspec ( var_info ( pvar ) ) ;
1293
			VAR_INFO pacc = DEREF_dspec(var_info(pvar));
1240
	    acc = merge_usage ( acc, pacc, u ) ;
1294
			acc = merge_usage(acc, pacc, u);
1241
	}
1295
		}
1242
	COPY_dspec ( id_storage ( id ), acc ) ;
1296
		COPY_dspec(id_storage(id), acc);
1243
	if ( !IS_NULL_list ( vc ) ) vc = TAIL_list ( vc ) ;
1297
		if (!IS_NULL_list(vc)) {
-
 
1298
			vc = TAIL_list(vc);
-
 
1299
		}
1244
	vb = TAIL_list ( vb ) ;
1300
		vb = TAIL_list(vb);
1245
    }
1301
	}
1246
    return ;
1302
	return;
1247
}
1303
}
1248
 
1304
 
1249
 
1305
 
1250
/*
1306
/*
1251
    SWAP CURRENT VARIABLE SETTINGS
1307
    SWAP CURRENT VARIABLE SETTINGS
1252
 
1308
 
1253
    This routine swaps the current variable settings with those stored in
1309
    This routine swaps the current variable settings with those stored in
1254
    the list va.
1310
    the list va.
1255
*/
1311
*/
-
 
1312
 
-
 
1313
static void
-
 
1314
swap_vars(VAR_LIST va)
-
 
1315
{
-
 
1316
	while (!IS_NULL_list(va)) {
-
 
1317
		VARIABLE var;
-
 
1318
		VAR_INFO acc;
-
 
1319
		DEREF_var(HEAD_list(va), var);
-
 
1320
		acc = DEREF_dspec(id_storage(var.id));
-
 
1321
		COPY_dspec(var_info(HEAD_list(va)), acc);
-
 
1322
		COPY_dspec(id_storage(var.id), var.info);
-
 
1323
		va = TAIL_list(va);
-
 
1324
	}
-
 
1325
	return;
-
 
1326
}
-
 
1327
 
-
 
1328
 
-
 
1329
/*
-
 
1330
    MARK VARIABLE SETTINGS
1256
 
1331
 
-
 
1332
    This routine marks all the variables in the list va with use.
-
 
1333
*/
-
 
1334
 
1257
static void swap_vars
1335
static void
1258
    PROTO_N ( ( va ) )
-
 
1259
    PROTO_T ( VAR_LIST va )
1336
mark_vars(VAR_LIST va, VAR_INFO use)
1260
{
1337
{
1261
    while ( !IS_NULL_list ( va ) ) {
1338
	while (!IS_NULL_list(va)) {
1262
	VARIABLE var ;
-
 
1263
	VAR_INFO acc ;
-
 
1264
	DEREF_var ( HEAD_list ( va ), var ) ;
-
 
1265
	acc = DEREF_dspec ( id_storage ( var.id ) ) ;
-
 
1266
	COPY_dspec ( var_info ( HEAD_list ( va ) ), acc ) ;
-
 
1267
	COPY_dspec ( id_storage ( var.id ), var.info ) ;
-
 
1268
	va = TAIL_list ( va ) ;
-
 
1269
    }
-
 
1270
    return ;
-
 
1271
}
-
 
1272
 
-
 
1273
 
-
 
1274
/*
-
 
1275
    MARK VARIABLE SETTINGS
-
 
1276
 
-
 
1277
    This routine marks all the variables in the list va with use.
-
 
1278
*/
-
 
1279
 
-
 
1280
static void mark_vars
-
 
1281
    PROTO_N ( ( va, use ) )
-
 
1282
    PROTO_T ( VAR_LIST va X VAR_INFO use )
-
 
1283
{
-
 
1284
    while ( !IS_NULL_list ( va ) ) {
-
 
1285
	IDENTIFIER id = DEREF_id ( var_id ( HEAD_list ( va ) ) ) ;
1339
		IDENTIFIER id = DEREF_id(var_id(HEAD_list(va)));
1286
	VAR_INFO acc = DEREF_dspec ( id_storage ( id ) ) ;
1340
		VAR_INFO acc = DEREF_dspec(id_storage(id));
1287
	acc |= use ;
1341
		acc |= use;
1288
	COPY_dspec ( id_storage ( id ), acc ) ;
1342
		COPY_dspec(id_storage(id), acc);
1289
	va = TAIL_list ( va ) ;
1343
		va = TAIL_list(va);
1290
    }
1344
	}
1291
    return ;
1345
	return;
1292
}
1346
}
1293
 
1347
 
1294
 
1348
 
1295
/*
1349
/*
1296
    PERFORM FLOW ANALYSIS ON A GOTO STATEMENT
1350
    PERFORM FLOW ANALYSIS ON A GOTO STATEMENT
1297
 
1351
 
1298
    This routine performs flow analysis on a jump to the label lab.  cond
1352
    This routine performs flow analysis on a jump to the label lab.  cond
1299
    is true to indicate a conditional jump.
1353
    is true to indicate a conditional jump.
1300
*/
1354
*/
1301
 
1355
 
1302
static VAR_INFO flow_goto_stmt
1356
static VAR_INFO
1303
    PROTO_N ( ( lab, use, cond ) )
-
 
1304
    PROTO_T ( IDENTIFIER lab X VAR_INFO use X int cond )
1357
flow_goto_stmt(IDENTIFIER lab, VAR_INFO use, int cond)
1305
{
1358
{
1306
    if ( !( use & va_unreached ) ) {
1359
	if (!(use & va_unreached)) {
1307
	VAR_INFO ds = DEREF_dspec ( id_storage ( lab ) ) ;
1360
		VAR_INFO ds = DEREF_dspec(id_storage(lab));
1308
	if ( ds & dspec_reserve ) {
1361
		if (ds & dspec_reserve) {
1309
	    /* Has backward jump */
1362
			/* Has backward jump */
1310
	    mark_vars ( crt_flow_vars, va_used_this ) ;
1363
			mark_vars(crt_flow_vars, va_used_this);
1311
	} else {
1364
		} else {
1312
	    /* Only forward jumps */
1365
			/* Only forward jumps */
1313
	    VAR_LIST va = DEREF_list ( id_label_vars ( lab ) ) ;
1366
			VAR_LIST va = DEREF_list(id_label_vars(lab));
1314
	    va = save_vars ( va, cond ) ;
1367
			va = save_vars(va, cond);
1315
	    COPY_list ( id_label_vars ( lab ), va ) ;
1368
			COPY_list(id_label_vars(lab), va);
-
 
1369
		}
-
 
1370
		ds |= dspec_temp;
-
 
1371
		COPY_dspec(id_storage(lab), ds);
-
 
1372
		use |= va_unreached;
1316
	}
1373
	}
1317
	ds |= dspec_temp ;
-
 
1318
	COPY_dspec ( id_storage ( lab ), ds ) ;
-
 
1319
	use |= va_unreached ;
-
 
1320
    }
-
 
1321
    return ( use ) ;
1374
	return (use);
1322
}
1375
}
1323
 
1376
 
1324
 
1377
 
1325
/*
1378
/*
1326
    PERFORM FLOW ANALYSIS ON A LABELLED STATEMENT
1379
    PERFORM FLOW ANALYSIS ON A LABELLED STATEMENT
1327
 
1380
 
1328
    This routine performs flow analysis on the statement labelled by the
1381
    This routine performs flow analysis on the statement labelled by the
1329
    label lab.
1382
    label lab.
1330
*/
1383
*/
1331
 
1384
 
1332
static VAR_INFO flow_label_stmt
1385
static VAR_INFO
1333
    PROTO_N ( ( lab, use, flow ) )
-
 
1334
    PROTO_T ( IDENTIFIER lab X VAR_INFO use X int flow )
1386
flow_label_stmt(IDENTIFIER lab, VAR_INFO use, int flow)
1335
{
1387
{
1336
    EXP e = DEREF_exp ( id_label_stmt ( lab ) ) ;
1388
	EXP e = DEREF_exp(id_label_stmt(lab));
1337
    VAR_INFO ds = DEREF_dspec ( id_storage ( lab ) ) ;
1389
	VAR_INFO ds = DEREF_dspec(id_storage(lab));
1338
    if ( ds & dspec_reserve ) {
1390
	if (ds & dspec_reserve) {
1339
	/* Has backward jump */
1391
		/* Has backward jump */
1340
	mark_vars ( crt_flow_vars, ( va_maybe_set | va_used_this ) ) ;
1392
		mark_vars(crt_flow_vars,(va_maybe_set | va_used_this));
1341
	use &= ~va_unreached ;
1393
		use &= ~va_unreached;
1342
    } else {
1394
	} else {
1343
	/* Only forward jumps */
1395
		/* Only forward jumps */
1344
	int unreached = 0 ;
1396
		int unreached = 0;
1345
	VAR_LIST va = DEREF_list ( id_label_vars ( lab ) ) ;
1397
		VAR_LIST va = DEREF_list(id_label_vars(lab));
1346
	if ( use & va_unreached ) unreached = 2 ;
1398
		if (use & va_unreached) {
-
 
1399
			unreached = 2;
-
 
1400
		}
1347
	load_vars ( va, unreached ) ;
1401
		load_vars(va, unreached);
1348
	DESTROY_list ( va, SIZE_var ) ;
1402
		DESTROY_list(va, SIZE_var);
1349
	COPY_list ( id_label_vars ( lab ), NULL_list ( VARIABLE ) ) ;
1403
		COPY_list(id_label_vars(lab), NULL_list(VARIABLE));
-
 
1404
		if (ds & dspec_temp) {
1350
	if ( ds & dspec_temp ) use &= ~va_unreached ;
1405
			use &= ~va_unreached;
1351
    }
1406
		}
-
 
1407
	}
1352
    if ( !IS_NULL_exp ( e ) ) {
1408
	if (!IS_NULL_exp(e)) {
1353
	e = DEREF_exp ( exp_label_stmt_body ( e ) ) ;
1409
		e = DEREF_exp(exp_label_stmt_body(e));
1354
	use = flow_stmt ( e, use, flow ) ;
1410
		use = flow_stmt(e, use, flow);
1355
    }
1411
	}
1356
    return ( use ) ;
1412
	return (use);
1357
}
1413
}
1358
 
1414
 
1359
 
1415
 
1360
/*
1416
/*
1361
    CHECK A SEQUENCE POINT
1417
    CHECK A SEQUENCE POINT
Line 1363... Line 1419...
1363
    This routine is called at each sequence point in the flow analysis
1419
    This routine is called at each sequence point in the flow analysis
1364
    routines.  It clears the list of identifiers assigned since the last
1420
    routines.  It clears the list of identifiers assigned since the last
1365
    sequence point.
1421
    sequence point.
1366
*/
1422
*/
1367
 
1423
 
1368
static void flow_sequence_point
1424
static void
1369
    PROTO_Z ()
1425
flow_sequence_point(void)
1370
{
1426
{
1371
    LIST ( IDENTIFIER ) p = crt_flow_assign ;
1427
	LIST(IDENTIFIER) p = crt_flow_assign;
1372
    while ( !IS_NULL_list ( p ) ) {
1428
	while (!IS_NULL_list(p)) {
1373
	VAR_INFO ds ;
1429
		VAR_INFO ds;
1374
	IDENTIFIER id ;
1430
		IDENTIFIER id;
1375
	DESTROY_CONS_id ( destroy, id, p, p ) ;
1431
		DESTROY_CONS_id(destroy, id, p, p);
1376
	ds = DEREF_dspec ( id_storage ( id ) ) ;
1432
		ds = DEREF_dspec(id_storage(id));
1377
	ds &= ~va_assign ;
1433
		ds &= ~va_assign;
1378
	COPY_dspec ( id_storage ( id ), ds ) ;
1434
		COPY_dspec(id_storage(id), ds);
1379
    }
1435
	}
1380
    crt_flow_assign = NULL_list ( IDENTIFIER ) ;
1436
	crt_flow_assign = NULL_list(IDENTIFIER);
1381
    return ;
1437
	return;
1382
}
1438
}
1383
 
1439
 
1384
 
1440
 
1385
/*
1441
/*
1386
    PERFORM FLOW ANALYSIS ON AN UNREACHABLE STATEMENT
1442
    PERFORM FLOW ANALYSIS ON AN UNREACHABLE STATEMENT
1387
 
1443
 
1388
    This routine performs flow analysis following a return statement (in
1444
    This routine performs flow analysis following a return statement (in
1389
    which case ret is true) or other expression which causes execution to
1445
    which case ret is true) or other expression which causes execution to
1390
    cease.
1446
    cease.
1391
*/
1447
*/
1392
 
1448
 
1393
static VAR_INFO flow_terminate
1449
static VAR_INFO
1394
    PROTO_N ( ( use, ret ) )
-
 
1395
    PROTO_T ( VAR_INFO use X int ret )
1450
flow_terminate(VAR_INFO use, int ret)
1396
{
1451
{
1397
    if ( !( use & va_unreached ) ) {
1452
	if (!(use & va_unreached)) {
1398
	VAR_LIST va = crt_flow_vars ;
1453
		VAR_LIST va = crt_flow_vars;
1399
	while ( !IS_NULL_list ( va ) ) {
1454
		while (!IS_NULL_list(va)) {
1400
	    IDENTIFIER id = DEREF_id ( var_id ( HEAD_list ( va ) ) ) ;
1455
			IDENTIFIER id = DEREF_id(var_id(HEAD_list(va)));
1401
	    VAR_INFO ds = DEREF_dspec ( id_storage ( id ) ) ;
1456
			VAR_INFO ds = DEREF_dspec(id_storage(id));
1402
	    ds = end_usage ( id, ds, ret ) ;
1457
			ds = end_usage(id, ds, ret);
1403
	    COPY_dspec ( id_storage ( id ), ds ) ;
1458
			COPY_dspec(id_storage(id), ds);
1404
	    va = TAIL_list ( va ) ;
1459
			va = TAIL_list(va);
1405
	}
1460
		}
1406
    }
1461
	}
1407
    UNUSED ( ret ) ;
1462
	UNUSED(ret);
1408
    use |= va_unreached ;
1463
	use |= va_unreached;
1409
    return ( use ) ;
1464
	return (use);
1410
}
1465
}
1411
 
1466
 
1412
 
1467
 
1413
/*
1468
/*
1414
    PERFORM FLOW ANALYSIS ON AN IF EXPRESSION
1469
    PERFORM FLOW ANALYSIS ON AN IF EXPRESSION
1415
 
1470
 
1416
    This routine preforms flow analysis on the if expression with condition
1471
    This routine preforms flow analysis on the if expression with condition
1417
    c and branches a and b.
1472
    c and branches a and b.
1418
*/
1473
*/
1419
 
1474
 
1420
static VAR_INFO flow_if_exp
1475
static VAR_INFO
1421
    PROTO_N ( ( c, a, b, use, flow ) )
-
 
1422
    PROTO_T ( EXP c X EXP a X EXP b X VAR_INFO use X int flow )
1476
flow_if_exp(EXP c, EXP a, EXP b, VAR_INFO use, int flow)
1423
{
1477
{
1424
    VAR_LIST va ;
1478
	VAR_LIST va;
1425
    VAR_INFO ua, ub ;
1479
	VAR_INFO ua, ub;
1426
    int unreached = 0 ;
1480
	int unreached = 0;
1427
    unsigned cv = eval_const_cond ( c ) ;
1481
	unsigned cv = eval_const_cond(c);
1428
    if ( flow ) {
1482
	if (flow) {
1429
	/* Condition */
1483
		/* Condition */
1430
	use = flow_exp ( c, use ) ;
1484
		use = flow_exp(c, use);
1431
	flow_sequence_point () ;
1485
		flow_sequence_point();
1432
    }
1486
	}
1433
    ua = use ;
1487
	ua = use;
1434
    ub = use ;
1488
	ub = use;
1435
    if ( cv == BOOL_FALSE ) ua |= va_unreached ;
1489
	if (cv == BOOL_FALSE) {
-
 
1490
		ua |= va_unreached;
-
 
1491
	}
1436
    if ( cv == BOOL_TRUE ) ub |= va_unreached ;
1492
	if (cv == BOOL_TRUE) {
-
 
1493
		ub |= va_unreached;
-
 
1494
	}
1437
    va = save_vars ( NULL_list ( VARIABLE ), 1 ) ;
1495
	va = save_vars(NULL_list(VARIABLE), 1);
1438
    ua = flow_stmt ( a, ua, flow ) ;
1496
	ua = flow_stmt(a, ua, flow);
1439
    swap_vars ( va ) ;
1497
	swap_vars(va);
1440
    ub = flow_stmt ( b, ub, flow ) ;
1498
	ub = flow_stmt(b, ub, flow);
1441
    if ( ua & va_unreached ) unreached |= 1 ;
1499
	if (ua & va_unreached) {
-
 
1500
		unreached |= 1;
-
 
1501
	}
1442
    if ( ub & va_unreached ) unreached |= 2 ;
1502
	if (ub & va_unreached) {
-
 
1503
		unreached |= 2;
-
 
1504
	}
1443
    load_vars ( va, unreached ) ;
1505
	load_vars(va, unreached);
1444
    DESTROY_list ( va, SIZE_var ) ;
1506
	DESTROY_list(va, SIZE_var);
1445
    use = ( ua & ub ) ;
1507
	use = (ua & ub);
1446
    return ( use ) ;
1508
	return (use);
1447
}
1509
}
1448
 
1510
 
1449
 
1511
 
1450
/*
1512
/*
1451
    PROCESS A FLOW ANALYSIS DIRECTIVE
1513
    PROCESS A FLOW ANALYSIS DIRECTIVE
1452
 
1514
 
1453
    This routine processes the flow analysis directive indicated by act
1515
    This routine processes the flow analysis directive indicated by act
1454
    to the expression e.
1516
    to the expression e.
1455
*/
1517
*/
1456
 
1518
 
1457
static VAR_INFO flow_set
1519
static VAR_INFO
1458
    PROTO_N ( ( e, use, act ) )
-
 
1459
    PROTO_T ( EXP e X VAR_INFO use X VAR_INFO act )
1520
flow_set(EXP e, VAR_INFO use, VAR_INFO act)
1460
{
1521
{
1461
    if ( !( use & va_unreached ) && !IS_NULL_exp ( e ) ) {
1522
	if (!(use & va_unreached) && !IS_NULL_exp(e)) {
1462
	EXP a = NULL_exp ;
1523
		EXP a = NULL_exp;
1463
	if ( IS_exp_contents ( e ) ) {
1524
		if (IS_exp_contents(e)) {
1464
	    /* Check for simple lvalues */
1525
			/* Check for simple lvalues */
1465
	    a = DEREF_exp ( exp_contents_ptr ( e ) ) ;
1526
			a = DEREF_exp(exp_contents_ptr(e));
1466
	} else if ( IS_exp_address ( e ) ) {
1527
		} else if (IS_exp_address(e)) {
1467
	    /* Check for array to pointer conversions */
1528
			/* Check for array to pointer conversions */
1468
	    EXP b = DEREF_exp ( exp_address_arg ( e ) ) ;
1529
			EXP b = DEREF_exp(exp_address_arg(e));
1469
	    TYPE s = DEREF_type ( exp_type ( b ) ) ;
1530
			TYPE s = DEREF_type(exp_type(b));
1470
	    if ( IS_type_array ( s ) ) a = b ;
1531
			if (IS_type_array(s)) {
-
 
1532
				a = b;
-
 
1533
			}
1471
	}
1534
		}
1472
	if ( !IS_NULL_exp ( a ) && IS_exp_identifier ( a ) ) {
1535
		if (!IS_NULL_exp(a) && IS_exp_identifier(a)) {
1473
	    IDENTIFIER id = DEREF_id ( exp_identifier_id ( a ) ) ;
1536
			IDENTIFIER id = DEREF_id(exp_identifier_id(a));
1474
	    if ( IS_id_variable_etc ( id ) ) {
1537
			if (IS_id_variable_etc(id)) {
1475
		DECL_SPEC ds = DEREF_dspec ( id_storage ( id ) ) ;
1538
				DECL_SPEC ds = DEREF_dspec(id_storage(id));
1476
		if ( ds & dspec_auto ) {
1539
				if (ds & dspec_auto) {
1477
		    if ( act & va_set ) {
1540
					if (act & va_set) {
1478
			/* Set variable */
1541
						/* Set variable */
1479
			ds |= ( va_set | va_maybe_set | va_any_set ) ;
1542
						ds |= (va_set | va_maybe_set |
-
 
1543
						       va_any_set);
1480
			ds &= ~va_used_this ;
1544
						ds &= ~va_used_this;
1481
		    } else {
1545
					} else {
1482
			/* Unused variable */
1546
						/* Unused variable */
1483
			set_variable ( id, act ) ;
1547
						set_variable(id, act);
1484
			ds = DEREF_dspec ( id_storage ( id ) ) ;
1548
						ds = DEREF_dspec(id_storage(id));
1485
			ds &= ~( va_set | va_maybe_set ) ;
1549
						ds &= ~(va_set | va_maybe_set);
1486
		    }
1550
					}
1487
		    COPY_dspec ( id_storage ( id ), ds ) ;
1551
					COPY_dspec(id_storage(id), ds);
-
 
1552
				}
1488
		}
1553
			}
1489
	    }
1554
		}
1490
	}
1555
	}
1491
    }
-
 
1492
    return ( use ) ;
1556
	return (use);
1493
}
1557
}
1494
 
1558
 
1495
 
1559
 
1496
/*
1560
/*
1497
    PERFORM FLOW ANALYSIS ON A LIST OF TOKEN ARGUMENTS
1561
    PERFORM FLOW ANALYSIS ON A LIST OF TOKEN ARGUMENTS
1498
 
1562
 
1499
    This routine performs flow analysis on the list of token arguments p.
1563
    This routine performs flow analysis on the list of token arguments p.
1500
*/
1564
*/
1501
 
1565
 
1502
static VAR_INFO flow_token_list
1566
static VAR_INFO
1503
    PROTO_N ( ( p, use ) )
-
 
1504
    PROTO_T ( LIST ( TOKEN ) p X VAR_INFO use )
1567
flow_token_list(LIST(TOKEN) p, VAR_INFO use)
1505
{
1568
{
1506
    while ( !IS_NULL_list ( p ) ) {
1569
	while (!IS_NULL_list(p)) {
1507
	TOKEN tok = DEREF_tok ( HEAD_list ( p ) ) ;
1570
		TOKEN tok = DEREF_tok(HEAD_list(p));
1508
	if ( !IS_NULL_tok ( tok ) ) {
1571
		if (!IS_NULL_tok(tok)) {
1509
	    switch ( TAG_tok ( tok ) ) {
1572
			switch (TAG_tok(tok)) {
1510
		case tok_exp_tag : {
1573
			case tok_exp_tag: {
1511
		    /* Expression tokens */
1574
				/* Expression tokens */
1512
		    EXP e = DEREF_exp ( tok_exp_value ( tok ) ) ;
1575
				EXP e = DEREF_exp(tok_exp_value(tok));
1513
		    use = flow_alias_exp ( e, use ) ;
1576
				use = flow_alias_exp(e, use);
1514
		    break ;
1577
				break;
1515
		}
1578
			}
1516
		case tok_stmt_tag : {
1579
			case tok_stmt_tag: {
1517
		    /* Statement tokens */
1580
				/* Statement tokens */
1518
		    EXP e = DEREF_exp ( tok_stmt_value ( tok ) ) ;
1581
				EXP e = DEREF_exp(tok_stmt_value(tok));
1519
		    use = flow_stmt ( e, use, 1 ) ;
1582
				use = flow_stmt(e, use, 1);
1520
		    break ;
1583
				break;
1521
		}
1584
			}
1522
		case tok_member_tag : {
1585
			case tok_member_tag: {
1523
		    /* Member tokens */
1586
				/* Member tokens */
1524
		    OFFSET off = DEREF_off ( tok_member_value ( tok ) ) ;
1587
				OFFSET off = DEREF_off(tok_member_value(tok));
1525
		    use = flow_offset ( off, use, 0 ) ;
1588
				use = flow_offset(off, use, 0);
1526
		    break ;
1589
				break;
-
 
1590
			}
-
 
1591
			}
1527
		}
1592
		}
1528
	    }
1593
		p = TAIL_list(p);
1529
	}
1594
	}
1530
	p = TAIL_list ( p ) ;
-
 
1531
    }
-
 
1532
    return ( use ) ;
1595
	return (use);
1533
}
1596
}
1534
 
1597
 
1535
 
1598
 
1536
/*
1599
/*
1537
    PERFORM FLOW ANALYSIS ON AN OFFSET
1600
    PERFORM FLOW ANALYSIS ON AN OFFSET
1538
 
1601
 
1539
    This routine performs flow analysis on the offset off.  mem is true
1602
    This routine performs flow analysis on the offset off.  mem is true
1540
    in member functions when the offset is being added to 'this'.
1603
    in member functions when the offset is being added to 'this'.
1541
*/
1604
*/
1542
 
1605
 
1543
static VAR_INFO flow_offset
1606
static VAR_INFO
1544
    PROTO_N ( ( off, use, mem ) )
-
 
1545
    PROTO_T ( OFFSET off X VAR_INFO use X int mem )
1607
flow_offset(OFFSET off, VAR_INFO use, int mem)
1546
{
1608
{
1547
    DECL_SPEC ua = ( use & ~va_mask ) ;
1609
	DECL_SPEC ua = (use & ~va_mask);
1548
    if ( IS_NULL_off ( off ) ) return ( ua ) ;
1610
	if (IS_NULL_off(off)) {
-
 
1611
		return (ua);
-
 
1612
	}
1549
    ASSERT ( ORDER_off == 13 ) ;
1613
	ASSERT(ORDER_off == 13);
1550
    switch ( TAG_off ( off ) ) {
1614
	switch (TAG_off(off)) {
1551
 
-
 
1552
	case off_member_tag : {
1615
	case off_member_tag:
1553
	    /* Member offsets */
1616
		/* Member offsets */
1554
	    if ( mem ) {
1617
		if (mem) {
1555
		IDENTIFIER id = DEREF_id ( off_member_id ( off ) ) ;
1618
			IDENTIFIER id = DEREF_id(off_member_id(off));
1556
		VAR_INFO ds = DEREF_dspec ( id_storage ( id ) ) ;
1619
			VAR_INFO ds = DEREF_dspec(id_storage(id));
-
 
1620
			if (ds & va_variable) {
1557
		if ( ds & va_variable ) set_variable ( id, use ) ;
1621
				set_variable(id, use);
1558
	    }
1622
			}
1559
	    break ;
-
 
1560
	}
1623
		}
1561
 
1624
		break;
1562
	case off_ptr_mem_tag : {
1625
	case off_ptr_mem_tag: {
1563
	    /* Pointer to member offsets */
1626
		/* Pointer to member offsets */
1564
	    EXP a = DEREF_exp ( off_ptr_mem_arg ( off ) ) ;
1627
		EXP a = DEREF_exp(off_ptr_mem_arg(off));
1565
	    ua = flow_exp ( a, ua ) ;
1628
		ua = flow_exp(a, ua);
1566
	    break ;
1629
		break;
1567
	}
1630
	}
1568
 
-
 
1569
	case off_negate_tag : {
1631
	case off_negate_tag: {
1570
	    /* Negated offsets */
1632
		/* Negated offsets */
1571
	    OFFSET off1 = DEREF_off ( off_negate_arg ( off ) ) ;
1633
		OFFSET off1 = DEREF_off(off_negate_arg(off));
1572
	    ua = flow_offset ( off1, ua, 0 ) ;
1634
		ua = flow_offset(off1, ua, 0);
1573
	    break ;
1635
		break;
1574
	}
1636
	}
1575
 
-
 
1576
	case off_plus_tag : {
1637
	case off_plus_tag: {
1577
	    /* Offset addition */
1638
		/* Offset addition */
1578
	    OFFSET off1 = DEREF_off ( off_plus_arg1 ( off ) ) ;
1639
		OFFSET off1 = DEREF_off(off_plus_arg1(off));
1579
	    OFFSET off2 = DEREF_off ( off_plus_arg2 ( off ) ) ;
1640
		OFFSET off2 = DEREF_off(off_plus_arg2(off));
1580
	    ua = flow_offset ( off1, ua, 0 ) ;
1641
		ua = flow_offset(off1, ua, 0);
1581
	    ua = flow_offset ( off2, ua, 0 ) ;
1642
		ua = flow_offset(off2, ua, 0);
1582
	    break ;
1643
		break;
1583
	}
1644
	}
1584
 
-
 
1585
	case off_mult_tag : {
1645
	case off_mult_tag: {
1586
	    /* Offset multiplication */
1646
		/* Offset multiplication */
1587
	    OFFSET off1 = DEREF_off ( off_mult_arg1 ( off ) ) ;
1647
		OFFSET off1 = DEREF_off(off_mult_arg1(off));
1588
	    EXP a = DEREF_exp ( off_mult_arg2 ( off ) ) ;
1648
		EXP a = DEREF_exp(off_mult_arg2(off));
1589
	    ua = flow_offset ( off1, ua, 0 ) ;
1649
		ua = flow_offset(off1, ua, 0);
1590
	    ua = flow_exp ( a, ua ) ;
1650
		ua = flow_exp(a, ua);
1591
	    break ;
1651
		break;
1592
	}
1652
	}
1593
 
-
 
1594
	case off_ptr_diff_tag : {
1653
	case off_ptr_diff_tag: {
1595
	    /* Difference of two pointers */
1654
		/* Difference of two pointers */
1596
	    EXP a = DEREF_exp ( off_ptr_diff_ptr1 ( off ) ) ;
1655
		EXP a = DEREF_exp(off_ptr_diff_ptr1(off));
1597
	    EXP b = DEREF_exp ( off_ptr_diff_ptr2 ( off ) ) ;
1656
		EXP b = DEREF_exp(off_ptr_diff_ptr2(off));
1598
	    ua = flow_exp ( a, ua ) ;
1657
		ua = flow_exp(a, ua);
1599
	    ua = flow_exp ( b, ua ) ;
1658
		ua = flow_exp(b, ua);
1600
	    break ;
1659
		break;
1601
	}
1660
	}
1602
 
-
 
1603
	case off_token_tag : {
1661
	case off_token_tag: {
1604
	    /* Tokenised offsets */
1662
		/* Tokenised offsets */
1605
	    LIST ( TOKEN ) args = DEREF_list ( off_token_args ( off ) ) ;
1663
		LIST(TOKEN)args = DEREF_list(off_token_args(off));
1606
	    ua = flow_token_list ( args, ua ) ;
1664
		ua = flow_token_list(args, ua);
1607
	    break ;
1665
		break;
1608
	}
1666
	}
1609
    }
1667
	}
1610
    ua &= ~va_mask ;
1668
	ua &= ~va_mask;
1611
    return ( ua ) ;
1669
	return (ua);
1612
}
1670
}
1613
 
1671
 
1614
 
1672
 
1615
/*
1673
/*
1616
    PERFORM FLOW ANALYSIS ON A LIST OF EXPRESSIONS
1674
    PERFORM FLOW ANALYSIS ON A LIST OF EXPRESSIONS
1617
 
1675
 
1618
    This routine performs flow analysis on the list of expressions p.
1676
    This routine performs flow analysis on the list of expressions p.
1619
*/
1677
*/
1620
 
1678
 
1621
static VAR_INFO flow_exp_list
1679
static VAR_INFO
1622
    PROTO_N ( ( p, use, fn ) )
-
 
1623
    PROTO_T ( LIST ( EXP ) p X VAR_INFO use X int fn )
1680
flow_exp_list(LIST(EXP) p, VAR_INFO use, int fn)
1624
{
1681
{
1625
    while ( !IS_NULL_list ( p ) ) {
1682
	while (!IS_NULL_list(p)) {
1626
	EXP a = DEREF_exp ( HEAD_list ( p ) ) ;
1683
		EXP a = DEREF_exp(HEAD_list(p));
1627
	if ( !IS_NULL_exp ( a ) ) {
1684
		if (!IS_NULL_exp(a)) {
1628
	    VAR_INFO ua ;
1685
			VAR_INFO ua;
1629
	    if ( fn ) {
1686
			if (fn) {
1630
		ua = flow_alias_exp ( a, use ) ;
1687
				ua = flow_alias_exp(a, use);
1631
	    } else {
1688
			} else {
1632
		ua = flow_exp ( a, use ) ;
1689
				ua = flow_exp(a, use);
1633
	    }
1690
			}
1634
	    if ( ua & va_unreached ) use |= va_unreached ;
1691
			if (ua & va_unreached) {
-
 
1692
				use |= va_unreached;
-
 
1693
			}
-
 
1694
		}
-
 
1695
		p = TAIL_list(p);
1635
	}
1696
	}
1636
	p = TAIL_list ( p ) ;
-
 
1637
    }
-
 
1638
    return ( use ) ;
1697
	return (use);
1639
}
1698
}
1640
 
1699
 
1641
 
1700
 
1642
/*
1701
/*
1643
    PERFORM FLOW ANALYSIS ON AN ALIASED EXPRESSION
1702
    PERFORM FLOW ANALYSIS ON AN ALIASED EXPRESSION
1644
 
1703
 
1645
    This routine performs flow analysis on the expression e which may be
1704
    This routine performs flow analysis on the expression e which may be
1646
    aliased by being on the right hand side of an assignment.  Note that
1705
    aliased by being on the right hand side of an assignment.  Note that
1647
    there are read-only and read-write aliases, depending on whether the
1706
    there are read-only and read-write aliases, depending on whether the
1648
    access is through a pointer or reference to const or not.
1707
    access is through a pointer or reference to const or not.
1649
*/
1708
*/
1650
 
1709
 
1651
static VAR_INFO flow_alias_exp
1710
static VAR_INFO
1652
    PROTO_N ( ( e, use ) )
-
 
1653
    PROTO_T ( EXP e X VAR_INFO use )
1711
flow_alias_exp(EXP e, VAR_INFO use)
1654
{
1712
{
1655
    VAR_INFO ua = ( use | va_alias_used ) ;
1713
	VAR_INFO ua = (use | va_alias_used);
1656
    if ( !IS_NULL_exp ( e ) ) {
1714
	if (!IS_NULL_exp(e)) {
1657
	TYPE t = DEREF_type ( exp_type ( e ) ) ;
1715
		TYPE t = DEREF_type(exp_type(e));
1658
	CV_SPEC cv = find_cv_qual ( t ) ;
1716
		CV_SPEC cv = find_cv_qual(t);
1659
	if ( cv & cv_lvalue ) {
1717
		if (cv & cv_lvalue) {
1660
	    /* Aliased via lvalue */
1718
			/* Aliased via lvalue */
1661
	    if ( !( cv & cv_const ) ) ua |= va_alias_set ;
1719
			if (!(cv & cv_const)) {
-
 
1720
				ua |= va_alias_set;
-
 
1721
			}
1662
	}
1722
		}
1663
	if ( IS_type_ptr_etc ( t ) ) {
1723
		if (IS_type_ptr_etc(t)) {
1664
	    /* Aliased via pointer or reference */
1724
			/* Aliased via pointer or reference */
1665
	    TYPE s = DEREF_type ( type_ptr_etc_sub ( t ) ) ;
1725
			TYPE s = DEREF_type(type_ptr_etc_sub(t));
1666
	    cv = find_cv_qual ( s ) ;
1726
			cv = find_cv_qual(s);
1667
	    if ( !( cv & cv_const ) ) ua |= va_alias_set ;
1727
			if (!(cv & cv_const)) {
-
 
1728
				ua |= va_alias_set;
-
 
1729
			}
-
 
1730
		}
1668
	}
1731
	}
1669
    }
-
 
1670
    ua = flow_exp ( e, ua ) ;
1732
	ua = flow_exp(e, ua);
1671
    return ( ua ) ;
1733
	return (ua);
1672
}
1734
}
1673
 
1735
 
1674
 
1736
 
1675
/*
1737
/*
1676
    PERFORM FLOW ANALYSIS ON AN EXPRESSION
1738
    PERFORM FLOW ANALYSIS ON AN EXPRESSION
1677
 
1739
 
1678
    This routine performs flow analysis on the expression e.
1740
    This routine performs flow analysis on the expression e.
1679
*/
1741
*/
1680
 
1742
 
1681
static VAR_INFO flow_exp
1743
static VAR_INFO
1682
    PROTO_N ( ( e, use ) )
-
 
1683
    PROTO_T ( EXP e X VAR_INFO use )
1744
flow_exp(EXP e, VAR_INFO use)
1684
{
1745
{
1774
	}
2075
	}
1775
 
-
 
1776
	case exp_indir_tag : {
2076
	case exp_dynamic_tag: {
1777
	    /* Indirection expressions */
2077
		/* Dynamic initialiser expressions */
1778
	    EXP a = DEREF_exp ( exp_indir_ptr ( e ) ) ;
-
 
1779
	    if ( !IS_NULL_list ( crt_flow_mems ) && is_this_exp ( e ) ) {
-
 
1780
		/* Have '*this' */
-
 
1781
		set_members ( use ) ;
-
 
1782
		break ;
-
 
1783
	    }
-
 
1784
	    if ( IS_exp_add_ptr ( a ) ) {
-
 
1785
		EXP b = DEREF_exp ( exp_add_ptr_ptr ( a ) ) ;
-
 
1786
		OFFSET off = DEREF_off ( exp_add_ptr_off ( a ) ) ;
-
 
1787
		if ( !IS_NULL_list ( crt_flow_mems ) && is_this_exp ( b ) ) {
-
 
1788
		    /* Have 'this->off' */
-
 
1789
		    ua = flow_offset ( off, use, 1 ) ;
-
 
1790
		    break ;
-
 
1791
		}
-
 
1792
		if ( IS_exp_address ( b ) ) {
-
 
1793
		    /* Have 'c.off' */
-
 
1794
		    EXP c = DEREF_exp ( exp_address_arg ( b ) ) ;
-
 
1795
		    ua = flow_offset ( off, use, 0 ) ;
-
 
1796
		    if ( ua & va_unreached ) use |= va_unreached ;
-
 
1797
		    ua = flow_exp ( c, ( use | va_partial ) ) ;
-
 
1798
		    break ;
-
 
1799
		}
-
 
1800
	    } else if ( IS_exp_address ( a ) ) {
-
 
1801
		/* Have '*&b' */
-
 
1802
		EXP b = DEREF_exp ( exp_address_arg ( a ) ) ;
2078
		EXP a = DEREF_exp(exp_dynamic_arg(e));
1803
		ua = flow_exp ( b, use ) ;
2079
		ua = flow_exp(a, ua);
1804
		break ;
2080
		break;
1805
	    }
-
 
1806
	    ua = flow_exp ( a, ua ) ;
-
 
1807
	    break ;
-
 
1808
	}
2081
	}
1809
 
-
 
1810
	case exp_contents_tag : {
2082
	case exp_aggregate_tag: {
1811
	    /* Contents expressions */
2083
		/* Aggregate initialiser expressions */
-
 
2084
		LIST(EXP) args;
1812
	    EXP a = DEREF_exp ( exp_contents_ptr ( e ) ) ;
2085
		args = DEREF_list(exp_aggregate_args(e));
1813
	    ua = flow_exp ( a, ua ) ;
2086
		ua = flow_exp_list(args, ua, 0);
1814
	    break ;
2087
		break;
1815
	}
2088
	}
1816
 
-
 
1817
	case exp_address_tag : {
2089
	case exp_initialiser_tag: {
1818
	    /* Address expressions */
2090
		/* Constructor initialiser expressions */
1819
	    EXP a = DEREF_exp ( exp_address_arg ( e ) ) ;
2091
		int kind = DEREF_int(exp_initialiser_kind(e));
1820
	    if ( IS_exp_indir ( a ) && !is_this_exp ( a ) ) {
-
 
1821
		EXP b = DEREF_exp ( exp_indir_ptr ( a ) ) ;
2092
		LIST(EXP) p = DEREF_list(exp_initialiser_args(e));
1822
		TYPE t = DEREF_type ( exp_type ( b ) ) ;
2093
		LIST(OFFSET) q = DEREF_list(exp_initialiser_offs(e));
1823
		if ( !IS_type_ref ( t ) ) {
2094
		if (kind == 0) {
1824
		    ua = flow_exp ( b, use ) ;
2095
			q = NULL_list(OFFSET);
1825
		    break ;
-
 
1826
		}
2096
		}
2074
	}
2143
	}
2075
 
-
 
2076
	case exp_comma_tag : {
-
 
2077
	    /* Comma expressions */
-
 
2078
	    LIST ( EXP ) p = DEREF_list ( exp_comma_args ( e ) ) ;
-
 
2079
	    if ( !IS_NULL_list ( p ) ) {
-
 
2080
		EXP a ;
-
 
2081
		for ( ; ; ) {
-
 
2082
		    a = DEREF_exp ( HEAD_list ( p ) ) ;
-
 
2083
		    p = TAIL_list ( p ) ;
-
 
2084
		    if ( IS_NULL_list ( p ) ) break ;
-
 
2085
		    ua = flow_exp ( a, ua ) ;
-
 
2086
		    flow_sequence_point () ;
-
 
2087
		    if ( ua & va_unreached ) use |= va_unreached ;
-
 
2088
		}
-
 
2089
		ua = flow_exp ( a, use ) ;
-
 
2090
	    }
-
 
2091
	    break ;
-
 
2092
	}
-
 
2093
 
-
 
2094
	case exp_if_stmt_tag : {
2144
	case exp_if_stmt_tag: {
2095
	    /* Conditional expressions */
2145
		/* Conditional expressions */
2096
	    EXP c = DEREF_exp ( exp_if_stmt_cond ( e ) ) ;
2146
		EXP c = DEREF_exp(exp_if_stmt_cond(e));
2097
	    EXP a = DEREF_exp ( exp_if_stmt_true_code ( e ) ) ;
2147
		EXP a = DEREF_exp(exp_if_stmt_true_code(e));
2098
	    EXP b = DEREF_exp ( exp_if_stmt_false_code ( e ) ) ;
2148
		EXP b = DEREF_exp(exp_if_stmt_false_code(e));
2099
	    ua = flow_if_exp ( c, a, b, ua, 1 ) ;
2149
		ua = flow_if_exp(c, a, b, ua, 1);
2100
	    break ;
2150
		break;
2101
	}
2151
	}
2102
 
-
 
2103
	case exp_exception_tag : {
2152
	case exp_exception_tag: {
2104
	    /* Exception expressions */
2153
		/* Exception expressions */
2105
	    EXP a = DEREF_exp ( exp_exception_arg ( e ) ) ;
2154
		EXP a = DEREF_exp(exp_exception_arg(e));
2106
	    ua = flow_exp ( a, ua ) ;
2155
		ua = flow_exp(a, ua);
2107
	    ua = flow_terminate ( ua, 1 ) ;
2156
		ua = flow_terminate(ua, 1);
2108
	    break ;
2157
		break;
2109
	}
2158
	}
2110
 
-
 
2111
	case exp_set_tag : {
2159
	case exp_set_tag: {
2112
	    /* Set expressions */
2160
		/* Set expressions */
2113
	    EXP a = DEREF_exp ( exp_set_arg ( e ) ) ;
2161
		EXP a = DEREF_exp(exp_set_arg(e));
2114
	    ua = flow_set ( a, ua, va_set ) ;
2162
		ua = flow_set(a, ua, va_set);
2115
	    break ;
2163
		break;
2116
	}
2164
	}
2117
 
-
 
2118
	case exp_unused_tag : {
2165
	case exp_unused_tag: {
2119
	    /* Unused expressions */
2166
		/* Unused expressions */
2120
	    EXP a = DEREF_exp ( exp_unused_arg ( e ) ) ;
2167
		EXP a = DEREF_exp(exp_unused_arg(e));
2121
	    ua = flow_set ( a, ua, va_none ) ;
2168
		ua = flow_set(a, ua, va_none);
2122
	    break ;
2169
		break;
2123
	}
2170
	}
2124
 
-
 
2125
	case exp_op_tag : {
2171
	case exp_op_tag: {
2126
	    /* Undetermined expressions */
2172
		/* Undetermined expressions */
2127
	    EXP a = DEREF_exp ( exp_op_arg1 ( e ) ) ;
2173
		EXP a = DEREF_exp(exp_op_arg1(e));
2128
	    EXP b = DEREF_exp ( exp_op_arg2 ( e ) ) ;
2174
		EXP b = DEREF_exp(exp_op_arg2(e));
2129
	    ua = flow_exp ( a, ua ) ;
2175
		ua = flow_exp(a, ua);
2130
	    ua = flow_exp ( b, ua ) ;
2176
		ua = flow_exp(b, ua);
2131
	    break ;
2177
		break;
2132
	}
2178
	}
2133
 
-
 
2134
	case exp_opn_tag : {
2179
	case exp_opn_tag: {
2135
	    /* Undetermined expressions */
2180
		/* Undetermined expressions */
2136
	    LIST ( EXP ) args = DEREF_list ( exp_opn_args ( e ) ) ;
2181
		LIST(EXP) args = DEREF_list(exp_opn_args(e));
2137
	    ua = flow_exp_list ( args, ua, 0 ) ;
2182
		ua = flow_exp_list(args, ua, 0);
2138
	    break ;
2183
		break;
2139
	}
2184
	}
2140
 
-
 
2141
	case exp_token_tag : {
2185
	case exp_token_tag: {
2142
	    /* Tokenised expressions */
2186
		/* Tokenised expressions */
2143
	    LIST ( TOKEN ) args = DEREF_list ( exp_token_args ( e ) ) ;
2187
		LIST(TOKEN) args = DEREF_list(exp_token_args(e));
2144
	    ua = flow_token_list ( args, ua ) ;
2188
		ua = flow_token_list(args, ua);
2145
	    break ;
2189
		break;
2146
	}
2190
	}
2147
 
-
 
2148
	case exp_dummy_tag : {
2191
	case exp_dummy_tag: {
2149
	    /* Dummy expressions */
2192
		/* Dummy expressions */
2150
	    EXP a = DEREF_exp ( exp_dummy_value ( e ) ) ;
2193
		EXP a = DEREF_exp(exp_dummy_value(e));
2151
	    ua = flow_exp ( a, use ) ;
2194
		ua = flow_exp(a, use);
2152
	    break ;
2195
		break;
2153
	}
2196
	}
2154
 
-
 
2155
	case exp_paren_tag :
2197
	case exp_paren_tag:
2156
	case exp_copy_tag : {
2198
	case exp_copy_tag: {
2157
	    /* Parenthesised expressions */
2199
		/* Parenthesised expressions */
2158
	    EXP a = DEREF_exp ( exp_paren_etc_arg ( e ) ) ;
2200
		EXP a = DEREF_exp(exp_paren_etc_arg(e));
2159
	    ua = flow_exp ( a, use ) ;
2201
		ua = flow_exp(a, use);
2160
	    break ;
2202
		break;
2161
	}
2203
	}
2162
 
-
 
2163
	case exp_location_tag : {
2204
	case exp_location_tag: {
2164
	    /* Location expressions */
2205
		/* Location expressions */
2165
	    EXP a = DEREF_exp ( exp_location_arg ( e ) ) ;
2206
		EXP a = DEREF_exp(exp_location_arg(e));
2166
	    ua = flow_exp ( a, use ) ;
2207
		ua = flow_exp(a, use);
2167
	    DEREF_loc ( exp_location_end ( e ), stmt_loc ) ;
2208
		DEREF_loc(exp_location_end(e), stmt_loc);
2168
	    break ;
2209
		break;
2169
	}
2210
	}
2170
 
-
 
2171
	case exp_sequence_tag :
2211
	case exp_sequence_tag:
2172
	case exp_solve_stmt_tag :
2212
	case exp_solve_stmt_tag:
2173
	case exp_decl_stmt_tag :
2213
	case exp_decl_stmt_tag:
2174
	case exp_while_stmt_tag :
2214
	case exp_while_stmt_tag:
2175
	case exp_do_stmt_tag :
2215
	case exp_do_stmt_tag:
2176
	case exp_switch_stmt_tag :
2216
	case exp_switch_stmt_tag:
2177
	case exp_hash_if_tag :
2217
	case exp_hash_if_tag:
2178
	case exp_return_stmt_tag :
2218
	case exp_return_stmt_tag:
2179
	case exp_goto_stmt_tag :
2219
	case exp_goto_stmt_tag:
2180
	case exp_label_stmt_tag :
2220
	case exp_label_stmt_tag:
2181
	case exp_try_block_tag :
2221
	case exp_try_block_tag:
2182
	case exp_handler_tag :
2222
	case exp_handler_tag:
2183
	case exp_reach_tag :
2223
	case exp_reach_tag:
2184
	case exp_unreach_tag : {
2224
	case exp_unreach_tag:
2185
	    /* Statements */
2225
		/* Statements */
2186
	    ua = flow_stmt ( e, ua, 1 ) ;
2226
		ua = flow_stmt(e, ua, 1);
2187
	    break ;
2227
		break;
2188
	}
2228
	}
2189
    }
-
 
2190
    ua &= ~va_mask ;
2229
	ua &= ~va_mask;
2191
    return ( ua ) ;
2230
	return (ua);
2192
}
2231
}
2193
 
2232
 
2194
 
2233
 
2195
/*
2234
/*
2196
    PERFORM FLOW ANALYSIS FOR DESTRUCTORS
2235
    PERFORM FLOW ANALYSIS FOR DESTRUCTORS
2197
 
2236
 
2198
    This routine performs flow analysis for any destructors called by
2237
    This routine performs flow analysis for any destructors called by
2199
    the goto or return statement a.  b gives smallest statement enclosing
2238
    the goto or return statement a.  b gives smallest statement enclosing
2200
    both the jump and its destination.
2239
    both the jump and its destination.
2201
*/
2240
*/
2202
 
2241
 
2203
static void flow_jump
2242
static void
2204
    PROTO_N ( ( a, b ) )
-
 
2205
    PROTO_T ( EXP a X EXP b )
2243
flow_jump(EXP a, EXP b)
2206
{
2244
{
2207
    unsigned long d = no_destructors ;
2245
	unsigned long d = no_destructors;
2208
    while ( !IS_NULL_exp ( a ) && !EQ_exp ( a, b ) && d ) {
2246
	while (!IS_NULL_exp(a) && !EQ_exp(a, b) && d) {
2209
	/* Scan up to enclosing statement */
2247
		/* Scan up to enclosing statement */
2210
	if ( IS_exp_decl_stmt ( a ) ) {
2248
		if (IS_exp_decl_stmt(a)) {
2211
	    IDENTIFIER id = DEREF_id ( exp_decl_stmt_id ( a ) ) ;
2249
			IDENTIFIER id = DEREF_id(exp_decl_stmt_id(a));
2212
	    if ( IS_id_variable ( id ) ) {
2250
			if (IS_id_variable(id)) {
2213
		DECL_SPEC ds = DEREF_dspec ( id_storage ( id ) ) ;
2251
				DECL_SPEC ds = DEREF_dspec(id_storage(id));
2214
		if ( ds & dspec_auto ) {
2252
				if (ds & dspec_auto) {
2215
		    /* Local variable */
2253
					/* Local variable */
-
 
2254
					EXP term =
2216
		    EXP term = DEREF_exp ( id_variable_term ( id ) ) ;
2255
					    DEREF_exp(id_variable_term(id));
2217
		    if ( !IS_NULL_exp ( term ) ) {
2256
					if (!IS_NULL_exp(term)) {
-
 
2257
						if (do_usage) {
-
 
2258
							dump_destr(id,
2218
			if ( do_usage ) dump_destr ( id, &stmt_loc ) ;
2259
								   &stmt_loc);
-
 
2260
						}
2219
			d-- ;
2261
						d--;
2220
		    }
2262
					}
2221
		}
2263
				}
2222
	    }
2264
			}
2223
	}
2265
		}
2224
	a = get_parent_stmt ( a ) ;
2266
		a = get_parent_stmt(a);
2225
    }
2267
	}
2226
    return ;
2268
	return;
2227
}
2269
}
2228
 
2270
 
2229
 
2271
 
2230
/*
2272
/*
2231
    PERFORM FLOW ANALYSIS ON A WHILE STATEMENT
2273
    PERFORM FLOW ANALYSIS ON A WHILE STATEMENT
2232
 
2274
 
2233
    This routine performs flow analysis on the while statement e.
2275
    This routine performs flow analysis on the while statement e.
2234
*/
2276
*/
2235
 
2277
 
2236
static VAR_INFO flow_while_stmt
2278
static VAR_INFO
2237
    PROTO_N ( ( e, use, flow ) )
-
 
2238
    PROTO_T ( EXP e X VAR_INFO use X int flow )
2279
flow_while_stmt(EXP e, VAR_INFO use, int flow)
2239
{
2280
{
2240
    VAR_INFO ua ;
2281
	VAR_INFO ua;
2241
    EXP c = DEREF_exp ( exp_while_stmt_cond ( e ) ) ;
2282
	EXP c = DEREF_exp(exp_while_stmt_cond(e));
2242
    EXP a = DEREF_exp ( exp_while_stmt_body ( e ) ) ;
2283
	EXP a = DEREF_exp(exp_while_stmt_body(e));
2243
    IDENTIFIER blab = DEREF_id ( exp_while_stmt_break_lab ( e ) ) ;
2284
	IDENTIFIER blab = DEREF_id(exp_while_stmt_break_lab(e));
2244
    IDENTIFIER clab = DEREF_id ( exp_while_stmt_cont_lab ( e ) ) ;
2285
	IDENTIFIER clab = DEREF_id(exp_while_stmt_cont_lab(e));
2245
    unsigned cv = eval_const_cond ( c ) ;
2286
	unsigned cv = eval_const_cond(c);
2246
    if ( flow ) {
2287
	if (flow) {
2247
	use = flow_exp ( c, use ) ;
2288
		use = flow_exp(c, use);
2248
	flow_sequence_point () ;
2289
		flow_sequence_point();
2249
    }
2290
	}
2250
    ua = use ;
2291
	ua = use;
2251
    if ( cv != BOOL_TRUE ) {
2292
	if (cv != BOOL_TRUE) {
2252
	IGNORE flow_goto_stmt ( blab, use, 1 ) ;
2293
		IGNORE flow_goto_stmt(blab, use, 1);
2253
	if ( cv == BOOL_FALSE ) ua |= va_unreached ;
2294
		if (cv == BOOL_FALSE) {
-
 
2295
			ua |= va_unreached;
2254
    }
2296
		}
-
 
2297
	}
2255
    ua = flow_stmt ( a, ua, flow ) ;
2298
	ua = flow_stmt(a, ua, flow);
2256
    ua = flow_label_stmt ( clab, ua, flow ) ;
2299
	ua = flow_label_stmt(clab, ua, flow);
2257
    if ( flow ) {
2300
	if (flow) {
2258
	IGNORE flow_exp ( c, ua ) ;
2301
		IGNORE flow_exp(c, ua);
2259
	flow_sequence_point () ;
2302
		flow_sequence_point();
2260
    }
2303
	}
2261
    mark_vars ( crt_flow_vars, va_used_this ) ;
2304
	mark_vars(crt_flow_vars, va_used_this);
2262
    use = flow_label_stmt ( blab, ( use | va_unreached ), flow ) ;
2305
	use = flow_label_stmt(blab,(use | va_unreached), flow);
2263
    return ( use ) ;
2306
	return (use);
2264
}
2307
}
2265
 
2308
 
2266
 
2309
 
2267
/*
2310
/*
2268
    PERFORM FLOW ANALYSIS ON A DO STATEMENT
2311
    PERFORM FLOW ANALYSIS ON A DO STATEMENT
2269
 
2312
 
2270
    This routine performs flow analysis on the do statement e.
2313
    This routine performs flow analysis on the do statement e.
2271
*/
2314
*/
-
 
2315
 
-
 
2316
static VAR_INFO
-
 
2317
flow_do_stmt(EXP e, VAR_INFO use, int flow)
-
 
2318
{
-
 
2319
	EXP c = DEREF_exp(exp_do_stmt_cond(e));
-
 
2320
	EXP a = DEREF_exp(exp_do_stmt_body(e));
-
 
2321
	IDENTIFIER blab = DEREF_id(exp_do_stmt_break_lab(e));
-
 
2322
	IDENTIFIER clab = DEREF_id(exp_do_stmt_cont_lab(e));
-
 
2323
	unsigned cv = eval_const_cond(c);
-
 
2324
	use = flow_stmt(a, use, flow);
-
 
2325
	use = flow_label_stmt(clab, use, flow);
-
 
2326
	if (flow) {
-
 
2327
		use = flow_exp(c, use);
-
 
2328
		flow_sequence_point();
-
 
2329
	}
-
 
2330
	mark_vars(crt_flow_vars, va_used_this);
-
 
2331
	if (cv == BOOL_TRUE) {
-
 
2332
		use |= va_unreached;
-
 
2333
	}
-
 
2334
	use = flow_label_stmt(blab, use, flow);
-
 
2335
	return (use);
-
 
2336
}
-
 
2337
 
-
 
2338
 
-
 
2339
/*
-
 
2340
    PERFORM FLOW ANALYSIS ON A SOLVE STATEMENT
2272
 
2341
 
2273
static VAR_INFO flow_do_stmt
2342
    This routine performs flow analysis on the solve statement e with
2274
    PROTO_N ( ( e, use, flow ) )
2343
    associated variables p.
-
 
2344
*/
-
 
2345
 
-
 
2346
static VAR_INFO
2275
    PROTO_T ( EXP e X VAR_INFO use X int flow )
2347
flow_solve_stmt(EXP e, LIST(IDENTIFIER) p, VAR_INFO use, int flow)
2276
{
2348
{
2277
    EXP c = DEREF_exp ( exp_do_stmt_cond ( e ) ) ;
2349
	if (!IS_NULL_list(p)) {
2278
    EXP a = DEREF_exp ( exp_do_stmt_body ( e ) ) ;
2350
		/* Scan through variables */
2279
    IDENTIFIER blab = DEREF_id ( exp_do_stmt_break_lab ( e ) ) ;
2351
		IDENTIFIER id = DEREF_id(HEAD_list(p));
2280
    IDENTIFIER clab = DEREF_id ( exp_do_stmt_cont_lab ( e ) ) ;
2352
		DECL_SPEC ds = DEREF_dspec(id_storage(id));
2281
    unsigned cv = eval_const_cond ( c ) ;
2353
		if ((ds & dspec_auto) && !(ds & dspec_done)) {
2282
    use = flow_stmt ( a, use, flow ) ;
2354
			start_variable(id, ds, va_none);
2283
    use = flow_label_stmt ( clab, use, flow ) ;
2355
			use = flow_solve_stmt(e, TAIL_list(p), use, flow);
2284
    if ( flow ) {
-
 
2285
	use = flow_exp ( c, use ) ;
2356
			end_variable(flow, 0);
2286
	flow_sequence_point () ;
2357
			return (use);
2287
    }
2358
		}
2288
    mark_vars ( crt_flow_vars, va_used_this ) ;
2359
		use = flow_solve_stmt(e, TAIL_list(p), use, flow);
2289
    if ( cv == BOOL_TRUE ) use |= va_unreached ;
2360
		return (use);
-
 
2361
	}
2290
    use = flow_label_stmt ( blab, use, flow ) ;
2362
	use = flow_stmt(e, use, flow);
2291
    return ( use ) ;
2363
	return (use);
2292
}
2364
}
2293
 
2365
 
2294
 
2366
 
2295
/*
2367
/*
2296
    PERFORM FLOW ANALYSIS ON A SOLVE STATEMENT
2368
    PERFORM FLOW ANALYSIS ON A SWITCH STATEMENT
2297
 
-
 
2298
    This routine performs flow analysis on the solve statement e with
-
 
2299
    associated variables p.
-
 
2300
*/
-
 
2301
 
2369
 
-
 
2370
    This routine performs flow analysis on the switch statement e.
-
 
2371
*/
-
 
2372
 
2302
static VAR_INFO flow_solve_stmt
2373
static VAR_INFO
2303
    PROTO_N ( ( e, p, use, flow ) )
-
 
2304
    PROTO_T ( EXP e X LIST ( IDENTIFIER ) p X VAR_INFO use X int flow )
2374
flow_switch_stmt(EXP e, VAR_INFO use, int flow)
2305
{
2375
{
2306
    if ( !IS_NULL_list ( p ) ) {
2376
	EXP a = DEREF_exp(exp_switch_stmt_body(e));
2307
	/* Scan through variables */
2377
	int exhaust = DEREF_int(exp_switch_stmt_exhaust(e));
2308
	IDENTIFIER id = DEREF_id ( HEAD_list ( p ) ) ;
2378
	LIST(IDENTIFIER) p = DEREF_list(exp_switch_stmt_case_labs(e));
2309
	DECL_SPEC ds = DEREF_dspec ( id_storage ( id ) ) ;
2379
	IDENTIFIER dlab = DEREF_id(exp_switch_stmt_default_lab(e));
2310
	if ( ( ds & dspec_auto ) && !( ds & dspec_done ) ) {
2380
	IDENTIFIER blab = DEREF_id(exp_switch_stmt_break_lab(e));
-
 
2381
	if (flow) {
2311
	    start_variable ( id, ds, va_none ) ;
2382
		/* Deal with control statement */
2312
	    use = flow_solve_stmt ( e, TAIL_list ( p ), use, flow ) ;
2383
		EXP c = DEREF_exp(exp_switch_stmt_control(e));
2313
	    end_variable ( flow, 0 ) ;
2384
		use = flow_exp(c, use);
2314
	    return ( use ) ;
2385
		flow_sequence_point();
2315
	}
2386
	}
-
 
2387
	if (!IS_NULL_id(dlab)) {
-
 
2388
		/* Mark jumps to default statement */
-
 
2389
		dlab = DEREF_id(id_alias(dlab));
2316
	use = flow_solve_stmt ( e, TAIL_list ( p ), use, flow ) ;
2390
		IGNORE flow_goto_stmt(dlab, use, 1);
2317
	return ( use ) ;
2391
		exhaust = 1;
-
 
2392
	}
-
 
2393
	while (!IS_NULL_list(p)) {
-
 
2394
		/* Mark jumps to case statements */
-
 
2395
		IDENTIFIER clab = DEREF_id(HEAD_list(p));
-
 
2396
		clab = DEREF_id(id_alias(clab));
-
 
2397
		if (!EQ_id(clab, dlab)) {
-
 
2398
			/* Only mark each label once */
-
 
2399
			IGNORE flow_goto_stmt(clab, use, 1);
-
 
2400
			dlab = clab;
2318
    }
2401
		}
-
 
2402
		p = TAIL_list(p);
-
 
2403
	}
-
 
2404
	if (!exhaust) {
-
 
2405
		/* Break label is reached in non-exhaustive cases */
-
 
2406
		IGNORE flow_goto_stmt(blab, use, 1);
-
 
2407
	}
-
 
2408
	use = flow_stmt(a,(use | va_unreached), flow);
2319
    use = flow_stmt ( e, use, flow ) ;
2409
	use = flow_label_stmt(blab, use, flow);
2320
    return ( use ) ;
2410
	return (use);
2321
}
2411
}
2322
 
2412
 
2323
 
2413
 
2324
/*
-
 
2325
    PERFORM FLOW ANALYSIS ON A SWITCH STATEMENT
-
 
2326
 
-
 
2327
    This routine performs flow analysis on the switch statement e.
-
 
2328
*/
-
 
2329
 
-
 
2330
static VAR_INFO flow_switch_stmt
-
 
2331
    PROTO_N ( ( e, use, flow ) )
-
 
2332
    PROTO_T ( EXP e X VAR_INFO use X int flow )
-
 
2333
{
-
 
2334
    EXP a = DEREF_exp ( exp_switch_stmt_body ( e ) ) ;
-
 
2335
    int exhaust = DEREF_int ( exp_switch_stmt_exhaust ( e ) ) ;
-
 
2336
    LIST ( IDENTIFIER ) p = DEREF_list ( exp_switch_stmt_case_labs ( e ) ) ;
-
 
2337
    IDENTIFIER dlab = DEREF_id ( exp_switch_stmt_default_lab ( e ) ) ;
-
 
2338
    IDENTIFIER blab = DEREF_id ( exp_switch_stmt_break_lab ( e ) ) ;
-
 
2339
    if ( flow ) {
-
 
2340
	/* Deal with control statement */
-
 
2341
	EXP c = DEREF_exp ( exp_switch_stmt_control ( e ) ) ;
-
 
2342
	use = flow_exp ( c, use ) ;
-
 
2343
	flow_sequence_point () ;
-
 
2344
    }
-
 
2345
    if ( !IS_NULL_id ( dlab ) ) {
-
 
2346
	/* Mark jumps to default statement */
-
 
2347
	dlab = DEREF_id ( id_alias ( dlab ) ) ;
-
 
2348
	IGNORE flow_goto_stmt ( dlab, use, 1 ) ;
-
 
2349
	exhaust = 1 ;
-
 
2350
    }
-
 
2351
    while ( !IS_NULL_list ( p ) ) {
-
 
2352
	/* Mark jumps to case statements */
-
 
2353
	IDENTIFIER clab = DEREF_id ( HEAD_list ( p ) ) ;
-
 
2354
	clab = DEREF_id ( id_alias ( clab ) ) ;
-
 
2355
	if ( !EQ_id ( clab, dlab ) ) {
-
 
2356
	    /* Only mark each label once */
-
 
2357
	    IGNORE flow_goto_stmt ( clab, use, 1 ) ;
-
 
2358
	    dlab = clab ;
-
 
2359
	}
-
 
2360
	p = TAIL_list ( p ) ;
-
 
2361
    }
-
 
2362
    if ( !exhaust ) {
-
 
2363
	/* Break label is reached in non-exhaustive cases */
-
 
2364
	IGNORE flow_goto_stmt ( blab, use, 1 ) ;
-
 
2365
    }
-
 
2366
    use = flow_stmt ( a, ( use | va_unreached ), flow ) ;
-
 
2367
    use = flow_label_stmt ( blab, use, flow ) ;
-
 
2368
    return ( use ) ;
-
 
2369
}
-
 
2370
 
-
 
2371
 
-
 
2372
/*
2414
/*
2373
    PERFORM FLOW ANALYSIS ON A TRY BLOCK
2415
    PERFORM FLOW ANALYSIS ON A TRY BLOCK
2374
 
2416
 
2375
    This routine performs flow analysis on the try block e.
2417
    This routine performs flow analysis on the try block e.
2376
*/
2418
*/
2377
 
2419
 
2378
static VAR_INFO flow_try_block
2420
static VAR_INFO
2379
    PROTO_N ( ( e, use, flow ) )
-
 
2380
    PROTO_T ( EXP e X VAR_INFO use X int flow )
2421
flow_try_block(EXP e, VAR_INFO use, int flow)
2381
{
2422
{
2382
    VAR_INFO ua = ( use | va_unreached ) ;
2423
	VAR_INFO ua = (use | va_unreached);
2383
    EXP a = DEREF_exp ( exp_try_block_body ( e ) ) ;
2424
	EXP a = DEREF_exp(exp_try_block_body(e));
2384
    LIST ( EXP ) p = DEREF_list ( exp_try_block_handlers ( e ) ) ;
2425
	LIST(EXP) p = DEREF_list(exp_try_block_handlers(e));
2385
    EXP c = DEREF_exp ( exp_try_block_ellipsis ( e ) ) ;
2426
	EXP c = DEREF_exp(exp_try_block_ellipsis(e));
2386
    use = flow_stmt ( a, use, flow ) ;
2427
	use = flow_stmt(a, use, flow);
2387
    /* NOT YET IMPLEMENTED */
2428
	/* NOT YET IMPLEMENTED */
2388
    while ( !IS_NULL_list ( p ) ) {
2429
	while (!IS_NULL_list(p)) {
2389
	EXP b = DEREF_exp ( HEAD_list ( p ) ) ;
2430
		EXP b = DEREF_exp(HEAD_list(p));
2390
	IGNORE flow_stmt ( b, ua, flow ) ;
2431
		IGNORE flow_stmt(b, ua, flow);
2391
	p = TAIL_list ( p ) ;
2432
		p = TAIL_list(p);
2392
    }
2433
	}
2393
    IGNORE flow_stmt ( c, ua, flow ) ;
2434
	IGNORE flow_stmt(c, ua, flow);
2394
    return ( use ) ;
2435
	return (use);
2395
}
2436
}
2396
 
2437
 
2397
 
2438
 
2398
/*
2439
/*
2399
    PERFORM FLOW ANALYSIS ON A DECLARATION STATEMENT
2440
    PERFORM FLOW ANALYSIS ON A DECLARATION STATEMENT
2400
 
2441
 
2401
    This routine performs flow analysis on the declaration statement e.
2442
    This routine performs flow analysis on the declaration statement e.
2402
*/
2443
*/
2403
 
2444
 
2404
static VAR_INFO flow_decl_stmt
2445
static VAR_INFO
-
 
2446
flow_decl_stmt(EXP e, VAR_INFO use, int flow)
-
 
2447
{
-
 
2448
	EXP a = DEREF_exp(exp_decl_stmt_body(e));
-
 
2449
	IDENTIFIER id = DEREF_id(exp_decl_stmt_id(e));
-
 
2450
	if (IS_id_variable(id)) {
-
 
2451
		DECL_SPEC ds = DEREF_dspec(id_storage(id));
-
 
2452
		if (ds & dspec_auto) {
-
 
2453
			/* Local variable */
-
 
2454
			EXP b = DEREF_exp(id_variable_init(id));
-
 
2455
			EXP d = DEREF_exp(id_variable_term(id));
-
 
2456
			if (!IS_NULL_exp(d)) {
-
 
2457
				no_destructors++;
-
 
2458
			}
-
 
2459
			if (!(ds & dspec_done)) {
-
 
2460
				start_variable(id, ds, va_none);
-
 
2461
			}
-
 
2462
			if (!IS_NULL_exp(b)) {
-
 
2463
				/* Initialiser expression */
-
 
2464
				if (flow) {
-
 
2465
					use = flow_alias_exp(b, use);
-
 
2466
				}
-
 
2467
				set_variable(id,(use | va_assign));
-
 
2468
				flow_sequence_point();
-
 
2469
			}
-
 
2470
			use = flow_stmt(a, use, flow);
-
 
2471
			if (flow) {
-
 
2472
				/* Destructor */
-
 
2473
				use = flow_exp(d, use);
-
 
2474
				flow_sequence_point();
-
 
2475
			}
-
 
2476
			if (!(ds & dspec_done)) {
-
 
2477
				end_variable(flow, 0);
-
 
2478
			}
-
 
2479
			if (!IS_NULL_exp(d)) {
-
 
2480
				no_destructors--;
-
 
2481
			}
-
 
2482
			return (use);
-
 
2483
		}
-
 
2484
	}
2405
    PROTO_N ( ( e, use, flow ) )
2485
	use = flow_stmt(a, use, flow);
-
 
2486
	return (use);
-
 
2487
}
-
 
2488
 
-
 
2489
 
-
 
2490
/*
-
 
2491
    PERFORM FLOW ANALYSIS ON A STATEMENT
-
 
2492
 
-
 
2493
    This routine performs flow analysis on the statement e.
-
 
2494
*/
-
 
2495
 
-
 
2496
static VAR_INFO
2406
    PROTO_T ( EXP e X VAR_INFO use X int flow )
2497
flow_stmt(EXP e, VAR_INFO use, int flow)
2407
{
2498
{
2408
    EXP a = DEREF_exp ( exp_decl_stmt_body ( e ) ) ;
-
 
2409
    IDENTIFIER id = DEREF_id ( exp_decl_stmt_id ( e ) ) ;
-
 
2410
    if ( IS_id_variable ( id ) ) {
-
 
2411
	DECL_SPEC ds = DEREF_dspec ( id_storage ( id ) ) ;
-
 
2412
	if ( ds & dspec_auto ) {
-
 
2413
	    /* Local variable */
2499
	/* Deal with statements */
2414
	    EXP b = DEREF_exp ( id_variable_init ( id ) ) ;
-
 
2415
	    EXP d = DEREF_exp ( id_variable_term ( id ) ) ;
-
 
2416
	    if ( !IS_NULL_exp ( d ) ) no_destructors++ ;
-
 
2417
	    if ( !( ds & dspec_done ) ) {
-
 
2418
		start_variable ( id, ds, va_none ) ;
2500
	VAR_INFO ua = (use & ~va_mask);
2419
	    }
-
 
2420
	    if ( !IS_NULL_exp ( b ) ) {
2501
	if (IS_NULL_exp(e)) {
2421
		/* Initialiser expression */
-
 
2422
		if ( flow ) use = flow_alias_exp ( b, use ) ;
-
 
2423
		set_variable ( id, ( use | va_assign ) ) ;
-
 
2424
		flow_sequence_point () ;
-
 
2425
	    }
-
 
2426
	    use = flow_stmt ( a, use, flow ) ;
-
 
2427
	    if ( flow ) {
-
 
2428
		/* Destructor */
-
 
2429
		use = flow_exp ( d, use ) ;
-
 
2430
		flow_sequence_point () ;
-
 
2431
	    }
-
 
2432
	    if ( !( ds & dspec_done ) ) end_variable ( flow, 0 ) ;
-
 
2433
	    if ( !IS_NULL_exp ( d ) ) no_destructors-- ;
-
 
2434
	    return ( use ) ;
2502
		return (ua);
2435
	}
2503
	}
2591
	}
2612
	}
2592
 
-
 
2593
	default : {
2613
	case exp_location_tag: {
2594
	    /* Simple expressions */
2614
		/* Location expressions */
2595
	    if ( !( ua & va_unreached ) && flow ) {
2615
		EXP a = DEREF_exp(exp_location_arg(e));
2596
		ua = flow_exp ( e, ua ) ;
2616
		ua = flow_stmt(a, use, flow);
2597
		flow_sequence_point () ;
2617
		DEREF_loc(exp_location_end(e), stmt_loc);
2598
	    }
-
 
2599
	    break ;
2618
		break;
2600
	}
2619
	}
-
 
2620
	default:
-
 
2621
		/* Simple expressions */
-
 
2622
		if (!(ua & va_unreached) && flow) {
-
 
2623
			ua = flow_exp(e, ua);
-
 
2624
			flow_sequence_point();
2601
    }
2625
		}
-
 
2626
		break;
-
 
2627
	}
2602
    ua &= ~va_mask ;
2628
	ua &= ~va_mask;
2603
    return ( ua ) ;
2629
	return (ua);
2604
}
2630
}
2605
 
2631
 
2606
 
2632
 
2607
/*
2633
/*
2608
    PERFORM FLOW ANALYSIS ON A FUNCTION DEFINITION
2634
    PERFORM FLOW ANALYSIS ON A FUNCTION DEFINITION
Line 2611... Line 2637...
2611
    which defines the function id.  Full flow analysis is enabled if
2637
    which defines the function id.  Full flow analysis is enabled if
2612
    flow is true, otherwise a minimal scan sufficient to determine all
2638
    flow is true, otherwise a minimal scan sufficient to determine all
2613
    implicit destructor calls is done.
2639
    implicit destructor calls is done.
2614
*/
2640
*/
2615
 
2641
 
2616
void check_flow
2642
void
2617
    PROTO_N ( ( id, e, flow ) )
-
 
2618
    PROTO_T ( IDENTIFIER id X EXP e X int flow )
2643
check_flow(IDENTIFIER id, EXP e, int flow)
2619
{
2644
{
2620
    VAR_INFO use ;
2645
	VAR_INFO use;
2621
    LIST ( IDENTIFIER ) pids ;
2646
	LIST(IDENTIFIER) pids;
2622
    if ( IS_id_function_etc ( id ) ) {
2647
	if (IS_id_function_etc(id)) {
2623
	TYPE t = DEREF_type ( id_function_etc_type ( id ) ) ;
2648
		TYPE t = DEREF_type(id_function_etc_type(id));
2624
	while ( IS_type_templ ( t ) ) {
2649
		while (IS_type_templ(t)) {
2625
	    t = DEREF_type ( type_templ_defn ( t ) ) ;
2650
			t = DEREF_type(type_templ_defn(t));
2626
	}
-
 
2627
	if ( IS_id_mem_func ( id ) ) {
-
 
2628
	    /* Allow for 'this' parameter and class members */
-
 
2629
	    IDENTIFIER pid = this_param ( id, 0 ) ;
-
 
2630
	    if ( flow ) {
-
 
2631
		HASHID nm = DEREF_hashid ( id_name ( id ) ) ;
-
 
2632
		CLASS_TYPE ct = parent_class ( id ) ;
-
 
2633
		NAMESPACE ns = DEREF_nspace ( ctype_member ( ct ) ) ;
-
 
2634
		MEMBER mem = DEREF_member ( nspace_ctype_first ( ns ) ) ;
-
 
2635
		mem = next_data_member ( mem, 0 ) ;
-
 
2636
		while ( !IS_NULL_member ( mem ) ) {
-
 
2637
		    IDENTIFIER mid = DEREF_id ( member_id ( mem ) ) ;
-
 
2638
		    start_variable ( mid, dspec_used, va_member ) ;
-
 
2639
		    if ( !IS_hashid_constr ( nm ) ) {
-
 
2640
			/* Members are set except in constructors */
-
 
2641
			set_variable ( mid, va_assign ) ;
-
 
2642
			set_variable ( mid, va_none ) ;
-
 
2643
		    }
-
 
2644
		    mem = DEREF_member ( member_next ( mem ) ) ;
-
 
2645
		    mem = next_data_member ( mem, 0 ) ;
-
 
2646
		}
2651
		}
-
 
2652
		if (IS_id_mem_func(id)) {
-
 
2653
			/* Allow for 'this' parameter and class members */
-
 
2654
			IDENTIFIER pid = this_param(id, 0);
-
 
2655
			if (flow) {
-
 
2656
				HASHID nm = DEREF_hashid(id_name(id));
-
 
2657
				CLASS_TYPE ct = parent_class(id);
-
 
2658
				NAMESPACE ns = DEREF_nspace(ctype_member(ct));
-
 
2659
				MEMBER mem =
-
 
2660
				    DEREF_member(nspace_ctype_first(ns));
-
 
2661
				mem = next_data_member(mem, 0);
-
 
2662
				while (!IS_NULL_member(mem)) {
-
 
2663
					IDENTIFIER mid =
-
 
2664
					    DEREF_id(member_id(mem));
-
 
2665
					start_variable(mid, dspec_used,
-
 
2666
						       va_member);
-
 
2667
					if (!IS_hashid_constr(nm)) {
-
 
2668
						/* Members are set except in
-
 
2669
						 * constructors */
-
 
2670
						set_variable(mid, va_assign);
-
 
2671
						set_variable(mid, va_none);
-
 
2672
					}
-
 
2673
					mem = DEREF_member(member_next(mem));
-
 
2674
					mem = next_data_member(mem, 0);
-
 
2675
				}
2647
		crt_flow_mems = crt_flow_vars ;
2676
				crt_flow_mems = crt_flow_vars;
2648
	    }
2677
			}
2649
	    if ( !IS_NULL_id ( pid ) ) {
2678
			if (!IS_NULL_id(pid)) {
2650
		start_variable ( pid, dspec_none, va_this ) ;
2679
				start_variable(pid, dspec_none, va_this);
2651
		set_variable ( pid, va_assign ) ;
2680
				set_variable(pid, va_assign);
2652
	    }
2681
			}
2653
	}
2682
		}
2654
	pids = DEREF_list ( type_func_pids ( t ) ) ;
2683
		pids = DEREF_list(type_func_pids(t));
2655
	while ( !IS_NULL_list ( pids ) ) {
2684
		while (!IS_NULL_list(pids)) {
2656
	    /* Set up parameter scopes */
2685
			/* Set up parameter scopes */
2657
	    IDENTIFIER pid = DEREF_id ( HEAD_list ( pids ) ) ;
2686
			IDENTIFIER pid = DEREF_id(HEAD_list(pids));
2658
	    if ( !IS_NULL_id ( pid ) ) {
2687
			if (!IS_NULL_id(pid)) {
2659
		DECL_SPEC ds = DEREF_dspec ( id_storage ( pid ) ) ;
2688
				DECL_SPEC ds = DEREF_dspec(id_storage(pid));
2660
		start_variable ( pid, ds, va_none ) ;
2689
				start_variable(pid, ds, va_none);
2661
		set_variable ( pid, va_assign ) ;
2690
				set_variable(pid, va_assign);
2662
	    }
2691
			}
2663
	    pids = TAIL_list ( pids ) ;
2692
			pids = TAIL_list(pids);
-
 
2693
		}
-
 
2694
	}
-
 
2695
	DEREF_loc(id_loc(id), stmt_loc);
-
 
2696
	flow_sequence_point();
-
 
2697
	use = flow_stmt(e, va_none, flow);
-
 
2698
	IGNORE flow_terminate(use, 2);
-
 
2699
	crt_flow_mems = NULL_list(VARIABLE);
-
 
2700
	while (!IS_NULL_list(crt_flow_vars)) {
-
 
2701
		/* End parameter and member scopes */
-
 
2702
		end_variable(flow, 2);
2664
	}
2703
	}
2665
    }
-
 
2666
    DEREF_loc ( id_loc ( id ), stmt_loc ) ;
-
 
2667
    flow_sequence_point () ;
-
 
2668
    use = flow_stmt ( e, va_none, flow ) ;
-
 
2669
    IGNORE flow_terminate ( use, 2 ) ;
-
 
2670
    crt_flow_mems = NULL_list ( VARIABLE ) ;
-
 
2671
    while ( !IS_NULL_list ( crt_flow_vars ) ) {
-
 
2672
	/* End parameter and member scopes */
-
 
2673
	end_variable ( flow, 2 ) ;
-
 
2674
    }
-
 
2675
    stmt_loc = crt_loc ;
2704
	stmt_loc = crt_loc;
2676
    return ;
2705
	return;
2677
}
2706
}