Subversion Repositories tendra.SVN

Rev

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

Rev Author Line No. Line
2 7u83 1
/*
7 7u83 2
 * Copyright (c) 2002-2006 The TenDRA Project <http://www.tendra.org/>.
3
 * All rights reserved.
4
 *
5
 * Redistribution and use in source and binary forms, with or without
6
 * modification, are permitted provided that the following conditions are met:
7
 *
8
 * 1. Redistributions of source code must retain the above copyright notice,
9
 *    this list of conditions and the following disclaimer.
10
 * 2. Redistributions in binary form must reproduce the above copyright notice,
11
 *    this list of conditions and the following disclaimer in the documentation
12
 *    and/or other materials provided with the distribution.
13
 * 3. Neither the name of The TenDRA Project nor the names of its contributors
14
 *    may be used to endorse or promote products derived from this software
15
 *    without specific, prior written permission.
16
 *
17
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ``AS
18
 * IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
19
 * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
20
 * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT HOLDERS OR
21
 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
22
 * EXEMPLARY OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
23
 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
24
 * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
25
 * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
26
 * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
27
 * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
28
 *
29
 * $Id$
30
 */
31
/*
2 7u83 32
    		 Crown Copyright (c) 1997
7 7u83 33
 
2 7u83 34
    This TenDRA(r) Computer Program is subject to Copyright
35
    owned by the United Kingdom Secretary of State for Defence
36
    acting through the Defence Evaluation and Research Agency
37
    (DERA).  It is made available to Recipients with a
38
    royalty-free licence for its use, reproduction, transfer
39
    to other parties and amendment for any purpose not excluding
40
    product development provided that any such use et cetera
41
    shall be deemed to be acceptance of the following conditions:-
7 7u83 42
 
2 7u83 43
        (1) Its Recipients shall ensure that this Notice is
44
        reproduced upon any copies or amended versions of it;
7 7u83 45
 
2 7u83 46
        (2) Any amended version of it shall be clearly marked to
47
        show both the nature of and the organisation responsible
48
        for the relevant amendment or amendments;
7 7u83 49
 
2 7u83 50
        (3) Its onward transfer from a recipient to another
51
        party shall be deemed to be that party's acceptance of
52
        these conditions;
7 7u83 53
 
2 7u83 54
        (4) DERA gives no warranty or assurance as to its
55
        quality or suitability for any purpose and DERA accepts
56
        no liability whatsoever in relation to any use to which
57
        it may be put.
58
*/
59
 
60
 
61
#include "config.h"
62
#include "c_types.h"
63
#include "ctype_ops.h"
64
#include "exp_ops.h"
65
#include "hashid_ops.h"
66
#include "id_ops.h"
67
#include "inst_ops.h"
68
#include "member_ops.h"
69
#include "nspace_ops.h"
70
#include "off_ops.h"
71
#include "tok_ops.h"
72
#include "type_ops.h"
73
#include "error.h"
74
#include "catalog.h"
75
#include "basetype.h"
76
#include "check.h"
77
#include "chktype.h"
78
#include "class.h"
79
#include "compile.h"
80
#include "constant.h"
81
#include "construct.h"
82
#include "convert.h"
83
#include "declare.h"
84
#include "dump.h"
85
#include "file.h"
86
#include "function.h"
87
#include "hash.h"
88
#include "identifier.h"
89
#include "initialise.h"
90
#include "instance.h"
91
#include "literal.h"
92
#include "namespace.h"
93
#include "option.h"
94
#include "preproc.h"
95
#include "save.h"
96
#include "statement.h"
97
#include "stmt.h"
98
#include "syntax.h"
99
#include "tok.h"
100
#include "variable.h"
101
 
102
 
103
/*
104
    VARIABLE ANALYSIS FLAGS
105
 
106
    The flag suppress_variable may be set to 1 to suppress variable
107
    analysis on function parameters and to 2 to suppress all variable
108
    analysis.  The flag anon_c_linkage may be set to true to indicate
109
    that objects with C linkage in anonymous namespaces are anonymous.
110
*/
111
 
7 7u83 112
int suppress_variable = 0;
113
int anon_c_linkage = 0;
2 7u83 114
 
115
 
116
/*
117
    CHECK A VARIABLE OR FUNCTION USAGE
118
 
119
    This routine checks the usage of the identifier id.  The flag anon
120
    is true if the complete reach of the identifier is being analysed.  For
121
    example, the reach of a local variable is its scope, that of an internal
122
    variable is its translation unit, and that of an external variable is
123
    its entire program.
124
*/
125
 
7 7u83 126
static void
127
check_usage(IDENTIFIER id, EXP blk, int anon)
2 7u83 128
{
7 7u83 129
	int opt;
130
	ERROR err;
131
	LOCATION loc;
132
	HASHID nm = DEREF_hashid(id_name(id));
133
	if (!IS_hashid_anon(nm)) {
134
		/* Ignore anonymous identifiers */
135
		DECL_SPEC ds = DEREF_dspec(id_storage(id));
136
		if (anon == ANON_NAMESPACE && (ds & dspec_c)) {
137
			if (!anon_c_linkage) {
138
				anon = ANON_NONE;
2 7u83 139
			}
7 7u83 140
		}
141
		if (ds & dspec_static) {
142
			if (!IS_NULL_exp(blk) || suppress_variable == 2) {
143
				/* Global statics are external to a block
144
				 * etc. */
145
				ds |= dspec_extern;
2 7u83 146
			}
147
		}
7 7u83 148
		if (anon || !(ds & dspec_extern)) {
149
			if (ds & dspec_implicit) {
150
				/* Ignore implicitly declared constructors
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) {
160
				if (ds & dspec_used) {
161
					/* Defined and used */
162
					/* EMPTY */
163
				} else {
164
					/* Defined but not used */
165
					if (ds & (dspec_inline |
166
						  dspec_virtual)) {
167
						/* Ignore inline and virtual
168
						 * functions */
169
						/* EMPTY */
170
					} else {
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
							}
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
				}
2 7u83 189
			} else {
7 7u83 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 {
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
				}
2 7u83 240
			}
241
		}
242
	}
7 7u83 243
	return;
2 7u83 244
}
245
 
246
 
247
/*
248
    CHECK A TEMPLATE IDENTIFIER
249
 
250
    This routine calls check_identifier for each instance of the template
251
    id.  t gives the template type, otherwise the parameters are as in
252
    check_identifier.
253
*/
254
 
7 7u83 255
static void
256
check_template_id(TYPE t, IDENTIFIER id, NAMESPACE ns, EXP blk, int anon,
257
		  int chk)
2 7u83 258
{
7 7u83 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));
264
		COPY_dspec(id_storage(id), (ds | dspec_done));
265
		while (!IS_NULL_inst(apps)) {
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,
273
								anon, chk);
274
				}
275
			}
276
			apps = DEREF_inst(inst_next(apps));
2 7u83 277
		}
7 7u83 278
		if (spec_unit) {
279
			spec_unit = save_end(spec_unit, NULL_nspace);
280
		}
281
		COPY_dspec(id_storage(id), ds);
2 7u83 282
	}
7 7u83 283
	return;
2 7u83 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
 
7 7u83 293
static void
294
check_class_usage(CLASS_TYPE ct, CLASS_USAGE cu)
2 7u83 295
{
7 7u83 296
	LOCATION loc;
297
	if (cu & cusage_destr) {
298
		IDENTIFIER id = DEREF_id(ctype_destr(ct));
299
		if (!IS_NULL_id(id) && IS_id_mem_func(id)) {
300
			DECL_SPEC ds = DEREF_dspec(id_storage(id));
301
			if (!(ds & dspec_trivial)) {
302
				DEREF_loc(id_loc(id), loc);
303
				report(loc, ERR_expr_delete_post(id));
304
			}
305
		}
2 7u83 306
	}
7 7u83 307
	if (cu & cusage_delete) {
308
		IDENTIFIER id = find_operator(ct, lex_delete);
309
		if (!IS_NULL_id(id)) {
310
			DEREF_loc(id_loc(id), loc);
311
			report(loc, ERR_expr_delete_post(id));
312
		}
2 7u83 313
	}
7 7u83 314
	if (cu & cusage_delete_array) {
315
		IDENTIFIER id = find_operator(ct, lex_delete_Harray);
316
		if (!IS_NULL_id(id)) {
317
			DEREF_loc(id_loc(id), loc);
318
			report(loc, ERR_expr_delete_post(id));
319
		}
2 7u83 320
	}
7 7u83 321
	if (cu & cusage_address) {
322
		IDENTIFIER id = find_operator(ct, lex_and_H1);
323
		while (!IS_NULL_id(id) && IS_id_function_etc(id)) {
324
			TYPE t = DEREF_type(id_function_etc_type(id));
325
			if (min_no_args(t) == 1) {
326
				DEREF_loc(id_loc(id), loc);
327
				report(loc, ERR_expr_unary_op_ref_post(id));
328
				break;
329
			}
330
			id = DEREF_id(id_function_etc_over(id));
331
		}
2 7u83 332
	}
7 7u83 333
	return;
2 7u83 334
}
335
 
336
 
337
/*
338
    COMPLETE A TENTATIVE DEFINITION
339
 
340
    This routine completes a C-style tentative definition of the
341
    variable id.  That is, if id has not been defined elsewhere, then
342
    it is defined to be zero.
343
*/
344
 
7 7u83 345
static int
346
define_tentative(IDENTIFIER id, int anon)
2 7u83 347
{
7 7u83 348
	int def = 0;
349
	EXP e = DEREF_exp(id_variable_etc_init(id));
350
	if (!IS_NULL_exp(e) && IS_exp_zero(e)) {
351
		LOCATION loc;
352
		DECL_SPEC ds = DEREF_dspec(id_storage(id));
353
		TYPE t = DEREF_type(id_variable_etc_type(id));
354
		bad_crt_loc++;
355
		loc = crt_loc;
356
		DEREF_loc(id_loc(id), crt_loc);
357
		if (anon || !(ds & dspec_extern)) {
358
			/* Types for internal objects should be complete */
359
			ERROR err = check_complete(t);
360
			if (!IS_NULL_err(err)) {
361
				ERROR err2 = ERR_basic_types_tent_incompl(id);
362
				err = concat_error(err, err2);
363
				report(crt_loc, err);
364
			}
365
		}
366
		if (IS_type_array(t)) {
367
			/* Complete array 'A []' to 'A [1]' */
368
			NAT n = DEREF_nat(type_array_size(t));
369
			if (IS_NULL_nat(n)) {
370
				CV_SPEC qual = DEREF_cv(type_qual(t));
371
				TYPE s = DEREF_type(type_array_sub(t));
372
				n = small_nat[1];
373
				MAKE_type_array(qual, s, n, t);
374
				COPY_type(id_variable_etc_type(id), t);
375
			}
376
		}
377
		e = init_general(t, NULL_exp, id, 0);
378
		COPY_exp(id_variable_etc_init(id), e);
379
		define_id(id);
380
		crt_loc = loc;
381
		bad_crt_loc--;
382
		def = 1;
2 7u83 383
	}
7 7u83 384
	return (def);
2 7u83 385
}
386
 
387
 
388
/*
389
    CHECK A GLOBAL IDENTIFIER
390
 
391
    This routine applies the global program checks to the identifier id
392
    from the namespace ns.  If id is a class or namespace name then the
393
    checks are also applied recursively to the members of id.  The flag
394
    anon is true if the parent namespace of id is local to the current
395
    translation unit.  The routine returns the number of identifiers in
396
    id (allowing for overloaded functions).
397
*/
398
 
7 7u83 399
unsigned long
400
check_identifier(IDENTIFIER id, NAMESPACE ns, EXP blk, int anon, int chk)
2 7u83 401
{
7 7u83 402
	unsigned long n = 1;
403
	if (spec_unit) {
404
		spec_unit = save_id(spec_unit, id, ns);
405
	}
406
	switch (TAG_id(id)) {
407
	case id_class_name_tag: {
408
		/* Check the members of a class */
409
		DECL_SPEC ds = DEREF_dspec(id_storage(id));
410
		if (!(ds & dspec_implicit)) {
411
			int templ = 0;
412
			CLASS_TYPE ct;
413
			CLASS_INFO ci;
414
			NAMESPACE cns;
415
			int tchk = chk;
416
			TYPE t = DEREF_type(id_class_name_defn(id));
417
			TYPE s = t;
418
			while (IS_type_templ(t)) {
419
				/* Template classes */
420
				templ = 1;
421
				tchk = 0;
422
				t = DEREF_type(type_templ_defn(t));
423
			}
424
			ct = DEREF_ctype(type_compound_defn(t));
425
			cns = DEREF_nspace(ctype_member(ct));
426
			ci = DEREF_cinfo(ctype_info(ct));
427
			if (ci & cinfo_complete) {
428
				/* Check class member namespace */
429
				CLASS_USAGE cu = DEREF_cusage(ctype_usage(ct));
430
				IDENTIFIER cid = DEREF_id(ctype_name(ct));
431
				HASHID cnm = DEREF_hashid(id_name(cid));
432
				if (IS_hashid_anon(cnm)) {
433
					anon = ANON_CLASS;
434
				}
2 7u83 435
#if LANGUAGE_CPP
7 7u83 436
				if ((ci & cinfo_polymorphic) && tchk) {
437
					/* Compile virtual function table */
438
					compile_virtual(ct, anon);
439
				}
2 7u83 440
#endif
7 7u83 441
				if (cu != cusage_none) {
442
					/* Check class usage */
443
					check_class_usage(ct, cu);
444
				}
445
			} else {
446
				if ((ci & cinfo_incomplete) && tchk) {
447
					/* Report incomplete types */
448
					complete_class(ct, 0);
449
					ci = DEREF_cinfo(ctype_info(ct));
450
					if (!(ci & cinfo_complete)) {
451
						ERROR err = ERR_basic_types_completed(t);
452
						if (!IS_NULL_err(err)) {
453
							LOCATION loc;
454
							DEREF_loc(id_loc(id),
455
								  loc);
456
							report(loc, err);
457
						}
458
					}
459
				}
460
				cns = NULL_nspace;
2 7u83 461
			}
7 7u83 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);
466
			}
2 7u83 467
		}
7 7u83 468
		goto type_label;
469
	}
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:
475
		/* Compile type names */
476
		if (chk) {
477
			if (anon) {
478
				check_usage(id, blk, anon);
479
			}
480
			if (IS_NULL_exp(blk)) {
481
				compile_type(id);
482
			}
2 7u83 483
		}
7 7u83 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;
2 7u83 490
	}
7 7u83 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
			}
498
			check_usage(id, blk, anon);
499
			if (IS_NULL_exp(blk)) {
500
				if (ds & dspec_defn) {
501
					IGNORE define_tentative(id, anon);
502
				}
503
				compile_variable(id, 0);
504
			} else {
505
				/* End of local block */
506
				if (ds & dspec_auto) {
507
					EXP term;
508
					ds &= ~dspec_access;
509
					COPY_dspec(id_storage(id), ds);
510
					term = DEREF_exp(id_variable_etc_term(id));
511
					if (!IS_NULL_exp(term)) {
512
						if (do_usage) {
513
							dump_destr(id,
514
								   &stmt_loc);
515
						}
516
					}
517
				}
518
			}
519
		}
520
		break;
521
	case id_parameter_tag: {
522
		/* Check parameter usage */
523
		if (chk && suppress_variable == 0) {
524
			check_usage(id, blk, anon);
525
		}
526
		break;
2 7u83 527
	}
528
 
7 7u83 529
	case id_stat_member_tag:
530
		/* Check static data member usage */
531
		if (anon == ANON_CLASS) {
532
			LOCATION loc;
533
			DEREF_loc(id_loc(id), loc);
534
			report(loc, ERR_class_static_data_anon(id));
2 7u83 535
		}
7 7u83 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);
2 7u83 544
			}
545
		}
7 7u83 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);
2 7u83 555
		}
7 7u83 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;
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
		}
577
		break;
2 7u83 578
	}
7 7u83 579
	case id_enumerator_tag:
580
		/* Check enumerator value */
581
		if (chk) {
582
			EXP e = DEREF_exp(id_enumerator_value(id));
583
			if (overflow_exp(e)) {
584
				compile_variable(id, 0);
585
			}
2 7u83 586
		}
7 7u83 587
		break;
588
	case id_nspace_alias_tag:
589
	case id_member_tag:
590
	case id_weak_param_tag:
591
		/* Don't check these (yet) */
592
		break;
2 7u83 593
	}
7 7u83 594
	return (n);
2 7u83 595
}
596
 
597
 
598
/*
599
    CHECK A NAMESPACE
600
 
601
    This routine scans through all the members of the namespace ns, calling
602
    check_identifier for each member (including hidden members) and
603
    compiling any functions or non-local variables.  It returns the number
604
    of identifiers declared in ns.  ns may be a block scope associated
605
    with the statement blk.  The flag anon is true if the parent namespace
606
    of ns is local to the current translation unit.
607
*/
608
 
7 7u83 609
unsigned long
610
check_namespace(NAMESPACE ns, EXP blk, int anon, int chk)
2 7u83 611
{
7 7u83 612
	unsigned long n = 0;
613
	if (!IS_NULL_nspace(ns)) {
614
		MEMBER mem;
615
		LIST(IDENTIFIER) extra;
2 7u83 616
 
7 7u83 617
		/* Find namespace components */
618
		switch (TAG_nspace(ns)) {
619
		case nspace_named_tag:
620
		case nspace_global_tag:
621
		case nspace_ctype_tag:
622
			mem = DEREF_member(nspace_named_etc_first(ns));
623
			extra = DEREF_list(nspace_named_etc_extra(ns));
624
			break;
625
		case nspace_unnamed_tag:
626
			mem = DEREF_member(nspace_unnamed_first(ns));
627
			extra = DEREF_list(nspace_unnamed_extra(ns));
628
			if (anon != ANON_GLOBAL && suppress_variable != 2) {
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;
2 7u83 637
		}
638
 
7 7u83 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));
650
		}
2 7u83 651
 
7 7u83 652
		/* Scan through extra namespace members */
653
		while (!IS_NULL_list(extra)) {
654
			IDENTIFIER id = DEREF_id(HEAD_list(extra));
655
			n += check_identifier(id, ns, blk, anon, chk);
656
			extra = TAIL_list(extra);
657
		}
2 7u83 658
	}
7 7u83 659
	if (spec_unit) {
660
		spec_unit = save_end(spec_unit, ns);
661
	}
662
	return (n);
2 7u83 663
}
664
 
665
 
666
/*
667
    CHECK THE TOKEN NAMESPACE
668
 
669
    This routine applies the usage checks to the tokens declared in the
670
    translation unit.
671
*/
672
 
7 7u83 673
static void
674
check_token(void)
2 7u83 675
{
7 7u83 676
    NAMESPACE ns = token_namespace;
677
    MEMBER mem = DEREF_member(nspace_global_first(ns));
678
    while (!IS_NULL_member(mem)) {
679
	IDENTIFIER id = DEREF_id(member_id(mem));
680
	if (!IS_NULL_id(id)) {
681
	    DECL_SPEC ds = DEREF_dspec(id_storage(id));
682
	    if (!(ds & dspec_done)) {
683
		if (ds & dspec_defn) {
2 7u83 684
		    /* Defined token */
7 7u83 685
		    compile_token(id, 1);
686
		} else if (!(ds & dspec_pure)) {
2 7u83 687
		    /* Undefined token */
7 7u83 688
		    LOCATION loc;
689
		    TOKEN tok = DEREF_tok(id_token_sort(id));
690
		    bad_crt_loc++;
691
		    loc = crt_loc;
692
		    DEREF_loc(id_loc(id), crt_loc);
693
		    if (IS_tok_func(tok)) {
2 7u83 694
			/* Implicitly define 'FUNC' tokens */
7 7u83 695
			IDENTIFIER fn = DEREF_id(id_token_alt(id));
696
			COPY_id(tok_func_defn(tok), fn);
697
			ds |= dspec_defn;
698
			COPY_dspec(id_storage(id), ds);
699
			if (!(ds & dspec_explicit)) {
2 7u83 700
			    /* Not explicitly redeclared */
7 7u83 701
			    report(crt_loc, ERR_token_def_implicit(id));
2 7u83 702
			}
7 7u83 703
			use_func_id(fn, 0, 0);
704
			compile_function(fn, 0);
705
			compile_token(id, 1);
706
		    } else if (ds & dspec_static) {
2 7u83 707
			/* Check for built-in token definitions */
7 7u83 708
			if (builtin_token(id)!= -1) {
709
			    ds = DEREF_dspec(id_storage(id));
710
			    if (!(ds & dspec_defn)) {
711
				compile_token(id, 0);
2 7u83 712
			    }
7 7u83 713
			} else if (suppress_variable != 2) {
714
			    compile_token(id, 0);
2 7u83 715
			}
716
		    }
7 7u83 717
		    crt_loc = loc;
718
		    bad_crt_loc--;
2 7u83 719
		}
720
	    }
721
	}
7 7u83 722
	mem = DEREF_member(member_next(mem));
2 7u83 723
    }
7 7u83 724
    return;
2 7u83 725
}
726
 
727
 
728
/*
729
    CHECK THE GLOBAL NAMESPACE
730
 
731
    This routine applies check_namespace to the global namespace,
732
    including checking the main function if complete is true.  It also
733
    calls check_token.
734
*/
735
 
7 7u83 736
unsigned long
737
check_global(int complete)
2 7u83 738
{
7 7u83 739
	/* Check main function if necessary */
740
	unsigned long n;
741
	int anon = ANON_NONE;
742
	NAMESPACE ns = global_namespace;
743
	if (complete && suppress_variable != 2) {
744
		IDENTIFIER id = main_function;
745
		HASHID nm = KEYWORD(lex_main);
746
		if (IS_NULL_id(id)) {
747
			/* Look up if not defined */
748
			MEMBER mem = search_member(ns, nm, 0);
749
			if (!IS_NULL_member(mem)) {
750
				id = DEREF_id(member_id(mem));
751
				if (!IS_NULL_id(id) && IS_id_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));
2 7u83 762
		} else {
7 7u83 763
			/* Mark as being used */
764
			DECL_SPEC ds = DEREF_dspec(id_storage(id));
765
			ds |= (dspec_used | dspec_called);
766
			COPY_dspec(id_storage(id), ds);
2 7u83 767
		}
7 7u83 768
		anon = ANON_GLOBAL;
2 7u83 769
	}
770
 
7 7u83 771
	/* Apply checks to namespaces */
772
	begin_spec();
773
	n = check_namespace(ns, NULL_exp, anon, 1);
774
	end_spec();
775
	check_token();
776
	return (n);
2 7u83 777
}
778
 
779
 
780
/*
781
    CONSTRUCT A SET EXPRESSION
782
 
783
    This routine constructs the expression 'set ( a )'.
784
*/
785
 
7 7u83 786
EXP
787
make_set_exp(EXP a)
2 7u83 788
{
7 7u83 789
	EXP e;
790
	a = convert_reference(a, REF_NORMAL);
791
	a = convert_lvalue(a);
792
	MAKE_exp_set(type_void, a, e);
793
	return (e);
2 7u83 794
}
795
 
796
 
797
/*
798
    CONSTRUCT AN UNUSED EXPRESSION
799
 
800
    This routine constructs the expression 'unused ( a )'.
801
*/
802
 
7 7u83 803
EXP
804
make_unused_exp(EXP a)
2 7u83 805
{
7 7u83 806
	EXP e;
807
	a = convert_reference(a, REF_NORMAL);
808
	a = convert_lvalue(a);
809
	MAKE_exp_unused(type_void, a, e);
810
	return (e);
2 7u83 811
}
812
 
813
 
814
/*
815
    PRESERVE ALL STATIC IDENTIFIERS
816
 
817
    This flag is set to true to indicate that all static identifiers
818
    should be preserved.
819
*/
820
 
7 7u83 821
int preserve_all = 0;
2 7u83 822
 
823
 
824
/*
825
    PRESERVE AN IDENTIFIER
826
 
827
    This routine preserves or suspends the static identifier id, as
828
    indicated by the action act.
829
*/
830
 
7 7u83 831
void
832
preserve_id(IDENTIFIER id, int act)
2 7u83 833
{
7 7u83 834
	switch (TAG_id(id)) {
835
	case id_function_tag: {
836
		IDENTIFIER over = DEREF_id(id_function_over(id));
837
		if (!IS_NULL_id(over)) {
838
			preserve_id(over, act);
839
		}
840
		goto action_lab;
2 7u83 841
	}
7 7u83 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;
2 7u83 854
	    }
7 7u83 855
	default: {
856
		ERROR err = ERR_pragma_preserve_undecl(act, id);
857
		report(preproc_loc, err);
858
		break;
2 7u83 859
	}
860
	}
7 7u83 861
	return;
2 7u83 862
}
863
 
864
 
865
/*
866
    FLOW ANALYSIS FLAGS
867
 
868
    These values are used to mark the various usage states in the flow
869
    analysis routines.  The fact that va_variable equals dspec_auto and
870
    va_done equals dspec_done is important, but the other values are
871
    merely convenient.
872
*/
873
 
7 7u83 874
typedef DECL_SPEC VAR_INFO;
2 7u83 875
 
876
#define va_none			dspec_none
877
#define va_used_this		dspec_used
878
#define va_set			dspec_defn
879
#define va_maybe_set		dspec_inherit
880
 
7 7u83 881
#define va_filter		(va_used_this | va_set | va_maybe_set)
2 7u83 882
 
883
#define va_any_use		dspec_static
884
#define va_any_set		dspec_extern
885
 
886
#define va_done			dspec_done
887
#define va_variable		dspec_auto
888
#define va_ignore		dspec_ignore
889
#define va_error		dspec_implicit
890
 
891
#define va_address		dspec_register
892
#define va_assign		dspec_mutable
893
#define va_alias_used		dspec_inline
894
#define va_alias_set		dspec_virtual
895
#define va_partial		dspec_explicit
896
#define va_member		dspec_friend
897
#define va_this			dspec_typedef
898
#define va_dummy		dspec_pure
899
 
7 7u83 900
#define va_alias		(va_alias_used | va_alias_set)
901
#define va_becomes		(va_assign | va_dummy)
902
#define va_other		(va_address | va_becomes | va_partial)
903
#define va_mask			(va_alias | va_other)
2 7u83 904
 
905
#define va_unreached		dspec_main
906
 
907
 
908
/*
909
    FORWARD DECLARATIONS
910
 
911
    The following declarations are required for the flow analysis
912
    routines.
913
*/
914
 
7 7u83 915
static VAR_INFO flow_exp(EXP, VAR_INFO);
916
static VAR_INFO flow_alias_exp(EXP, VAR_INFO);
917
static VAR_INFO flow_stmt(EXP, VAR_INFO, int);
918
static VAR_INFO flow_offset(OFFSET, VAR_INFO, int);
919
static void set_variable(IDENTIFIER, VAR_INFO);
2 7u83 920
 
921
 
922
/*
923
    LIST OF CURRENTLY ACTIVE VARIABLES
924
 
925
    The variable crt_flow_vars is used to hold a list of all the local
926
    variables which are in scope at any point in the variable analysis
927
    routines.
928
*/
929
 
7 7u83 930
typedef LIST(VARIABLE) VAR_LIST;
931
static VAR_LIST crt_flow_vars = NULL_list(VARIABLE);
932
static VAR_LIST crt_flow_mems = NULL_list(VARIABLE);
933
static LIST(IDENTIFIER) crt_flow_assign = NULL_list(IDENTIFIER);
2 7u83 934
 
935
 
936
/*
937
    START VARIABLE ANALYSIS
938
 
939
    This routine is called at the start of the analysis of the local
940
    variable id.
941
*/
942
 
7 7u83 943
static void
944
start_variable(IDENTIFIER id, DECL_SPEC ds, VAR_INFO use)
2 7u83 945
{
7 7u83 946
	VARIABLE var;
947
	use |= (va_variable | va_done | va_used_this);
948
	if (!(ds & dspec_used)) {
949
		use |= va_ignore;
950
	}
951
	var.id = id;
952
	var.info = DEREF_dspec(id_storage(id));
953
	COPY_dspec(id_storage(id), use);
954
	CONS_var(var, crt_flow_vars, crt_flow_vars);
955
	DEREF_loc(id_loc(id), stmt_loc);
956
	return;
2 7u83 957
}
958
 
959
 
960
/*
961
    SHOULD VARIABLE ANALYSIS BE IGNORED?
962
 
963
    This routine checks whether any variable analysis errors involving
964
    the local variable id should be ignored.  This is done if id is an
965
    anonymous identifier or is a const variable all of whose uses have
966
    been replaced by its definition (see convert_lvalue).
967
*/
968
 
7 7u83 969
static int
970
ignore_variable(IDENTIFIER id)
2 7u83 971
{
7 7u83 972
	HASHID nm = DEREF_hashid(id_name(id));
973
	if (IS_hashid_anon(nm)) {
974
		return (1);
2 7u83 975
	}
7 7u83 976
	if (IS_id_variable(id)) {
977
		TYPE t = DEREF_type(id_variable_type(id));
978
		CV_SPEC cv = find_cv_qual(t);
979
		if (cv & cv_volatile) {
980
			/* Ignore volatile variables */
981
			return (1);
982
		}
983
		if (cv == (cv_const | cv_lvalue)) {
984
			/* Check for const variables */
985
			EXP e = DEREF_exp(id_variable_init(id));
986
			if (!IS_NULL_exp(e)) {
987
				if (IS_exp_int_lit(e)) {
988
					return (1);
989
				}
990
				if (IS_exp_null(e)) {
991
					return (1);
992
				}
993
			}
994
		}
995
	} else if (IS_id_member(id)) {
996
		TYPE t = DEREF_type(id_member_type(id));
997
		CV_SPEC cv = find_cv_qual(t);
998
		if (cv & cv_volatile) {
999
			/* Ignore volatile members */
1000
			return (1);
1001
		}
2 7u83 1002
	}
7 7u83 1003
	return (0);
2 7u83 1004
}
1005
 
1006
 
1007
/*
1008
    END A VARIABLE SETTING
1009
 
1010
    This routine marks the end of the variable setting ds.  ret is true if
1011
    this end of scope is due to a return statement.  In particular it
1012
    checks whether the variable has been assigned to and not used.
1013
*/
1014
 
7 7u83 1015
static VAR_INFO
1016
end_usage(IDENTIFIER id, VAR_INFO ds, int ret)
2 7u83 1017
{
7 7u83 1018
	if (ret && (ds & va_member)) {
1019
		/* Class members are used after return */
1020
		if (ret == 2) {
1021
			set_variable(id, va_member);
1022
			ds = DEREF_dspec(id_storage(id));
1023
		} else {
1024
			ds |= va_used_this;
1025
		}
1026
	} else if (!(ds & va_used_this) && (ds & va_set)) {
1027
		if (!(ds & va_ignore) && !ignore_variable(id)) {
1028
			report(stmt_loc, ERR_stmt_dcl_reset(id));
1029
			ds |= va_error;
1030
		}
1031
		ds |= va_used_this;
2 7u83 1032
	}
7 7u83 1033
	return (ds);
2 7u83 1034
}
1035
 
1036
 
1037
/*
1038
    END VARIABLE ANALYSIS
1039
 
1040
    This routine is called at the end of the analysis of a local
1041
    variable.  Note that unused variable have already been dealt with.
1042
*/
1043
 
7 7u83 1044
static void
1045
end_variable(int flow, int ret)
2 7u83 1046
{
7 7u83 1047
	VARIABLE var;
1048
	DESTROY_CONS_var(destroy, var, crt_flow_vars, crt_flow_vars);
1049
	if (flow) {
1050
		VAR_INFO use = DEREF_dspec(id_storage(var.id));
1051
		use = end_usage(var.id, use, ret);
1052
		if (!(use & (va_member | va_ignore))) {
1053
			if (!(use & va_any_use)) {
1054
				/* Not used in reached code */
1055
				if (!ignore_variable(var.id)) {
1056
					LOCATION loc;
1057
					DEREF_loc(id_loc(var.id), loc);
1058
					report(loc,
1059
					       ERR_stmt_dcl_unused(var.id));
1060
				}
1061
			} else if (!(use & va_any_set)) {
1062
				/* Not set in reached code */
1063
				if (!(use & va_error) &&
1064
				    !ignore_variable(var.id)) {
1065
					LOCATION loc;
1066
					DEREF_loc(id_loc(var.id), loc);
1067
					report(loc, ERR_stmt_dcl_unset(var.id));
1068
				}
1069
			}
2 7u83 1070
		}
1071
	}
7 7u83 1072
	COPY_dspec(id_storage(var.id), var.info);
1073
	return;
2 7u83 1074
}
1075
 
1076
 
1077
/*
1078
    SET A VARIABLE
1079
 
1080
    This routine adjusts the variable analysis information for the local
1081
    variable use according to the analysis state use.
1082
*/
1083
 
7 7u83 1084
static void
1085
set_variable(IDENTIFIER id, VAR_INFO use)
2 7u83 1086
{
7 7u83 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);
2 7u83 1143
		}
7 7u83 1144
		COPY_dspec(id_storage(id), ds);
2 7u83 1145
	}
7 7u83 1146
	return;
2 7u83 1147
}
1148
 
1149
 
1150
/*
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
 
7 7u83 1157
static void
1158
set_members(VAR_INFO use)
2 7u83 1159
{
7 7u83 1160
	if (!(use & va_unreached)) {
1161
		VAR_LIST va = crt_flow_mems;
1162
		while (!IS_NULL_list(va)) {
1163
			IDENTIFIER id = DEREF_id(var_id(HEAD_list(va)));
1164
			set_variable(id, use);
1165
			va = TAIL_list(va);
1166
		}
2 7u83 1167
	}
7 7u83 1168
	return;
2 7u83 1169
}
1170
 
1171
 
1172
/*
1173
    MERGE A VARIABLE SETTING
1174
 
1175
    This routine merges the variable analysis settings given by dp and dq.
1176
    u indicates whether the variable set values are to be taken from dp,
1177
    from dq, from both, or from neither.
1178
*/
1179
 
7 7u83 1180
static VAR_INFO
1181
merge_usage(VAR_INFO dp, VAR_INFO dq, int u)
2 7u83 1182
{
7 7u83 1183
	VAR_INFO ds = (dp | dq);
1184
	VAR_INFO dt = dspec_none;
1185
	switch (u) {
1186
	case 0:
1187
		dt = (dp & dq);
1188
		break;
1189
	case 1:
1190
		dt = dp;
1191
		break;
1192
	case 2:
1193
		dt = dq;
1194
		break;
1195
	}
1196
	ds = ((ds & ~va_filter) | (dt & va_filter));
1197
	return (ds);
2 7u83 1198
}
1199
 
1200
 
1201
/*
1202
    SEARCH A LIST OF VARIABLES
1203
 
1204
    This routine searches the list of variables p for one corresponding to
1205
    id.  q is a member of p which corresponds to id is the simplest case.
1206
    It returns a pointer to the variable if it exists and a null pointer
1207
    otherwise.
1208
*/
1209
 
7 7u83 1210
static PTR(VARIABLE)
1211
search_vars(VAR_LIST p, VAR_LIST q, IDENTIFIER id)
2 7u83 1212
{
7 7u83 1213
	if (!IS_NULL_list(q)) {
1214
		PTR(VARIABLE) ptr = HEAD_list(q);
1215
		IDENTIFIER pid = DEREF_id(var_id(ptr));
1216
		if (EQ_id(pid, id)) {
1217
			return (ptr);
1218
		}
1219
	}
1220
	while (!IS_NULL_list(p)) {
1221
		PTR(VARIABLE) ptr = HEAD_list(p);
1222
		IDENTIFIER pid = DEREF_id(var_id(ptr));
1223
		if (EQ_id(pid, id)) {
1224
			return (ptr);
1225
		}
1226
		p = TAIL_list(p);
1227
	}
1228
	return (NULL_ptr(VARIABLE));
2 7u83 1229
}
1230
 
1231
 
1232
/*
1233
    SAVE CURRENT VARIABLE SETTINGS
1234
 
1235
    This routine saves the current variable settings by merging them with
1236
    those stored in the list va.
1237
*/
1238
 
7 7u83 1239
static VAR_LIST
1240
save_vars(VAR_LIST va, int cond)
2 7u83 1241
{
7 7u83 1242
	VAR_LIST vb = crt_flow_vars;
1243
	VAR_LIST vc = va;
1244
	VAR_LIST vd = va;
1245
	while (!IS_NULL_list(vb)) {
1246
		VARIABLE var;
1247
		PTR(VARIABLE) pvar;
1248
		var.id = DEREF_id(var_id(HEAD_list(vb)));
1249
		var.info = DEREF_dspec(id_storage(var.id));
1250
		if (cond) {
1251
			var.info |= va_used_this;
1252
			COPY_dspec(id_storage(var.id), var.info);
1253
		}
1254
		pvar = search_vars(vc, vd, var.id);
1255
		if (IS_NULL_ptr(pvar)) {
1256
			/* Add new identifier to list */
1257
			CONS_var(var, va, va);
1258
		} else {
1259
			/* Merge with existing information */
1260
			VAR_INFO acc = DEREF_dspec(var_info(pvar));
1261
			acc = merge_usage(acc, var.info, 0);
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);
2 7u83 1268
	}
7 7u83 1269
	if (IS_NULL_list(vc)) {
1270
		va = REVERSE_list(va);
2 7u83 1271
	}
7 7u83 1272
	return (va);
2 7u83 1273
}
1274
 
1275
 
1276
/*
1277
    LOAD CURRENT VARIABLE SETTINGS
1278
 
1279
    This routine loads the current variable settings by merging them with
1280
    those stored in the list va.
1281
*/
1282
 
7 7u83 1283
static void
1284
load_vars(VAR_LIST va, int u)
2 7u83 1285
{
7 7u83 1286
	VAR_LIST vb = crt_flow_vars;
1287
	VAR_LIST vc = va;
1288
	while (!IS_NULL_list(vb)) {
1289
		IDENTIFIER id = DEREF_id(var_id(HEAD_list(vb)));
1290
		VAR_INFO acc = DEREF_dspec(id_storage(id));
1291
		PTR(VARIABLE)pvar = search_vars(va, vc, id);
1292
		if (!IS_NULL_ptr(pvar)) {
1293
			VAR_INFO pacc = DEREF_dspec(var_info(pvar));
1294
			acc = merge_usage(acc, pacc, u);
1295
		}
1296
		COPY_dspec(id_storage(id), acc);
1297
		if (!IS_NULL_list(vc)) {
1298
			vc = TAIL_list(vc);
1299
		}
1300
		vb = TAIL_list(vb);
2 7u83 1301
	}
7 7u83 1302
	return;
2 7u83 1303
}
1304
 
1305
 
1306
/*
1307
    SWAP CURRENT VARIABLE SETTINGS
1308
 
1309
    This routine swaps the current variable settings with those stored in
1310
    the list va.
1311
*/
1312
 
7 7u83 1313
static void
1314
swap_vars(VAR_LIST va)
2 7u83 1315
{
7 7u83 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;
2 7u83 1326
}
1327
 
1328
 
1329
/*
1330
    MARK VARIABLE SETTINGS
1331
 
1332
    This routine marks all the variables in the list va with use.
1333
*/
1334
 
7 7u83 1335
static void
1336
mark_vars(VAR_LIST va, VAR_INFO use)
2 7u83 1337
{
7 7u83 1338
	while (!IS_NULL_list(va)) {
1339
		IDENTIFIER id = DEREF_id(var_id(HEAD_list(va)));
1340
		VAR_INFO acc = DEREF_dspec(id_storage(id));
1341
		acc |= use;
1342
		COPY_dspec(id_storage(id), acc);
1343
		va = TAIL_list(va);
1344
	}
1345
	return;
2 7u83 1346
}
1347
 
1348
 
1349
/*
1350
    PERFORM FLOW ANALYSIS ON A GOTO STATEMENT
1351
 
1352
    This routine performs flow analysis on a jump to the label lab.  cond
1353
    is true to indicate a conditional jump.
1354
*/
1355
 
7 7u83 1356
static VAR_INFO
1357
flow_goto_stmt(IDENTIFIER lab, VAR_INFO use, int cond)
2 7u83 1358
{
7 7u83 1359
	if (!(use & va_unreached)) {
1360
		VAR_INFO ds = DEREF_dspec(id_storage(lab));
1361
		if (ds & dspec_reserve) {
1362
			/* Has backward jump */
1363
			mark_vars(crt_flow_vars, va_used_this);
1364
		} else {
1365
			/* Only forward jumps */
1366
			VAR_LIST va = DEREF_list(id_label_vars(lab));
1367
			va = save_vars(va, cond);
1368
			COPY_list(id_label_vars(lab), va);
1369
		}
1370
		ds |= dspec_temp;
1371
		COPY_dspec(id_storage(lab), ds);
1372
		use |= va_unreached;
2 7u83 1373
	}
7 7u83 1374
	return (use);
2 7u83 1375
}
1376
 
1377
 
1378
/*
1379
    PERFORM FLOW ANALYSIS ON A LABELLED STATEMENT
1380
 
1381
    This routine performs flow analysis on the statement labelled by the
1382
    label lab.
1383
*/
1384
 
7 7u83 1385
static VAR_INFO
1386
flow_label_stmt(IDENTIFIER lab, VAR_INFO use, int flow)
2 7u83 1387
{
7 7u83 1388
	EXP e = DEREF_exp(id_label_stmt(lab));
1389
	VAR_INFO ds = DEREF_dspec(id_storage(lab));
1390
	if (ds & dspec_reserve) {
1391
		/* Has backward jump */
1392
		mark_vars(crt_flow_vars,(va_maybe_set | va_used_this));
1393
		use &= ~va_unreached;
1394
	} else {
1395
		/* Only forward jumps */
1396
		int unreached = 0;
1397
		VAR_LIST va = DEREF_list(id_label_vars(lab));
1398
		if (use & va_unreached) {
1399
			unreached = 2;
1400
		}
1401
		load_vars(va, unreached);
1402
		DESTROY_list(va, SIZE_var);
1403
		COPY_list(id_label_vars(lab), NULL_list(VARIABLE));
1404
		if (ds & dspec_temp) {
1405
			use &= ~va_unreached;
1406
		}
1407
	}
1408
	if (!IS_NULL_exp(e)) {
1409
		e = DEREF_exp(exp_label_stmt_body(e));
1410
		use = flow_stmt(e, use, flow);
1411
	}
1412
	return (use);
2 7u83 1413
}
1414
 
1415
 
1416
/*
1417
    CHECK A SEQUENCE POINT
1418
 
1419
    This routine is called at each sequence point in the flow analysis
1420
    routines.  It clears the list of identifiers assigned since the last
1421
    sequence point.
1422
*/
1423
 
7 7u83 1424
static void
1425
flow_sequence_point(void)
2 7u83 1426
{
7 7u83 1427
	LIST(IDENTIFIER) p = crt_flow_assign;
1428
	while (!IS_NULL_list(p)) {
1429
		VAR_INFO ds;
1430
		IDENTIFIER id;
1431
		DESTROY_CONS_id(destroy, id, p, p);
1432
		ds = DEREF_dspec(id_storage(id));
1433
		ds &= ~va_assign;
1434
		COPY_dspec(id_storage(id), ds);
1435
	}
1436
	crt_flow_assign = NULL_list(IDENTIFIER);
1437
	return;
2 7u83 1438
}
1439
 
1440
 
1441
/*
1442
    PERFORM FLOW ANALYSIS ON AN UNREACHABLE STATEMENT
1443
 
1444
    This routine performs flow analysis following a return statement (in
1445
    which case ret is true) or other expression which causes execution to
1446
    cease.
1447
*/
1448
 
7 7u83 1449
static VAR_INFO
1450
flow_terminate(VAR_INFO use, int ret)
2 7u83 1451
{
7 7u83 1452
	if (!(use & va_unreached)) {
1453
		VAR_LIST va = crt_flow_vars;
1454
		while (!IS_NULL_list(va)) {
1455
			IDENTIFIER id = DEREF_id(var_id(HEAD_list(va)));
1456
			VAR_INFO ds = DEREF_dspec(id_storage(id));
1457
			ds = end_usage(id, ds, ret);
1458
			COPY_dspec(id_storage(id), ds);
1459
			va = TAIL_list(va);
1460
		}
2 7u83 1461
	}
7 7u83 1462
	UNUSED(ret);
1463
	use |= va_unreached;
1464
	return (use);
2 7u83 1465
}
1466
 
1467
 
1468
/*
1469
    PERFORM FLOW ANALYSIS ON AN IF EXPRESSION
1470
 
1471
    This routine preforms flow analysis on the if expression with condition
1472
    c and branches a and b.
1473
*/
1474
 
7 7u83 1475
static VAR_INFO
1476
flow_if_exp(EXP c, EXP a, EXP b, VAR_INFO use, int flow)
2 7u83 1477
{
7 7u83 1478
	VAR_LIST va;
1479
	VAR_INFO ua, ub;
1480
	int unreached = 0;
1481
	unsigned cv = eval_const_cond(c);
1482
	if (flow) {
1483
		/* Condition */
1484
		use = flow_exp(c, use);
1485
		flow_sequence_point();
1486
	}
1487
	ua = use;
1488
	ub = use;
1489
	if (cv == BOOL_FALSE) {
1490
		ua |= va_unreached;
1491
	}
1492
	if (cv == BOOL_TRUE) {
1493
		ub |= va_unreached;
1494
	}
1495
	va = save_vars(NULL_list(VARIABLE), 1);
1496
	ua = flow_stmt(a, ua, flow);
1497
	swap_vars(va);
1498
	ub = flow_stmt(b, ub, flow);
1499
	if (ua & va_unreached) {
1500
		unreached |= 1;
1501
	}
1502
	if (ub & va_unreached) {
1503
		unreached |= 2;
1504
	}
1505
	load_vars(va, unreached);
1506
	DESTROY_list(va, SIZE_var);
1507
	use = (ua & ub);
1508
	return (use);
2 7u83 1509
}
1510
 
1511
 
1512
/*
1513
    PROCESS A FLOW ANALYSIS DIRECTIVE
1514
 
1515
    This routine processes the flow analysis directive indicated by act
1516
    to the expression e.
1517
*/
1518
 
7 7u83 1519
static VAR_INFO
1520
flow_set(EXP e, VAR_INFO use, VAR_INFO act)
2 7u83 1521
{
7 7u83 1522
	if (!(use & va_unreached) && !IS_NULL_exp(e)) {
1523
		EXP a = NULL_exp;
1524
		if (IS_exp_contents(e)) {
1525
			/* Check for simple lvalues */
1526
			a = DEREF_exp(exp_contents_ptr(e));
1527
		} else if (IS_exp_address(e)) {
1528
			/* Check for array to pointer conversions */
1529
			EXP b = DEREF_exp(exp_address_arg(e));
1530
			TYPE s = DEREF_type(exp_type(b));
1531
			if (IS_type_array(s)) {
1532
				a = b;
1533
			}
2 7u83 1534
		}
7 7u83 1535
		if (!IS_NULL_exp(a) && IS_exp_identifier(a)) {
1536
			IDENTIFIER id = DEREF_id(exp_identifier_id(a));
1537
			if (IS_id_variable_etc(id)) {
1538
				DECL_SPEC ds = DEREF_dspec(id_storage(id));
1539
				if (ds & dspec_auto) {
1540
					if (act & va_set) {
1541
						/* Set variable */
1542
						ds |= (va_set | va_maybe_set |
1543
						       va_any_set);
1544
						ds &= ~va_used_this;
1545
					} else {
1546
						/* Unused variable */
1547
						set_variable(id, act);
1548
						ds = DEREF_dspec(id_storage(id));
1549
						ds &= ~(va_set | va_maybe_set);
1550
					}
1551
					COPY_dspec(id_storage(id), ds);
1552
				}
1553
			}
1554
		}
2 7u83 1555
	}
7 7u83 1556
	return (use);
2 7u83 1557
}
1558
 
1559
 
1560
/*
1561
    PERFORM FLOW ANALYSIS ON A LIST OF TOKEN ARGUMENTS
1562
 
1563
    This routine performs flow analysis on the list of token arguments p.
1564
*/
1565
 
7 7u83 1566
static VAR_INFO
1567
flow_token_list(LIST(TOKEN) p, VAR_INFO use)
2 7u83 1568
{
7 7u83 1569
	while (!IS_NULL_list(p)) {
1570
		TOKEN tok = DEREF_tok(HEAD_list(p));
1571
		if (!IS_NULL_tok(tok)) {
1572
			switch (TAG_tok(tok)) {
1573
			case tok_exp_tag: {
1574
				/* Expression tokens */
1575
				EXP e = DEREF_exp(tok_exp_value(tok));
1576
				use = flow_alias_exp(e, use);
1577
				break;
1578
			}
1579
			case tok_stmt_tag: {
1580
				/* Statement tokens */
1581
				EXP e = DEREF_exp(tok_stmt_value(tok));
1582
				use = flow_stmt(e, use, 1);
1583
				break;
1584
			}
1585
			case tok_member_tag: {
1586
				/* Member tokens */
1587
				OFFSET off = DEREF_off(tok_member_value(tok));
1588
				use = flow_offset(off, use, 0);
1589
				break;
1590
			}
1591
			}
2 7u83 1592
		}
7 7u83 1593
		p = TAIL_list(p);
2 7u83 1594
	}
7 7u83 1595
	return (use);
2 7u83 1596
}
1597
 
1598
 
1599
/*
1600
    PERFORM FLOW ANALYSIS ON AN OFFSET
1601
 
1602
    This routine performs flow analysis on the offset off.  mem is true
1603
    in member functions when the offset is being added to 'this'.
1604
*/
1605
 
7 7u83 1606
static VAR_INFO
1607
flow_offset(OFFSET off, VAR_INFO use, int mem)
2 7u83 1608
{
7 7u83 1609
	DECL_SPEC ua = (use & ~va_mask);
1610
	if (IS_NULL_off(off)) {
1611
		return (ua);
2 7u83 1612
	}
7 7u83 1613
	ASSERT(ORDER_off == 13);
1614
	switch (TAG_off(off)) {
1615
	case off_member_tag:
1616
		/* Member offsets */
1617
		if (mem) {
1618
			IDENTIFIER id = DEREF_id(off_member_id(off));
1619
			VAR_INFO ds = DEREF_dspec(id_storage(id));
1620
			if (ds & va_variable) {
1621
				set_variable(id, use);
1622
			}
1623
		}
1624
		break;
1625
	case off_ptr_mem_tag: {
1626
		/* Pointer to member offsets */
1627
		EXP a = DEREF_exp(off_ptr_mem_arg(off));
1628
		ua = flow_exp(a, ua);
1629
		break;
2 7u83 1630
	}
7 7u83 1631
	case off_negate_tag: {
1632
		/* Negated offsets */
1633
		OFFSET off1 = DEREF_off(off_negate_arg(off));
1634
		ua = flow_offset(off1, ua, 0);
1635
		break;
2 7u83 1636
	}
7 7u83 1637
	case off_plus_tag: {
1638
		/* Offset addition */
1639
		OFFSET off1 = DEREF_off(off_plus_arg1(off));
1640
		OFFSET off2 = DEREF_off(off_plus_arg2(off));
1641
		ua = flow_offset(off1, ua, 0);
1642
		ua = flow_offset(off2, ua, 0);
1643
		break;
2 7u83 1644
	}
7 7u83 1645
	case off_mult_tag: {
1646
		/* Offset multiplication */
1647
		OFFSET off1 = DEREF_off(off_mult_arg1(off));
1648
		EXP a = DEREF_exp(off_mult_arg2(off));
1649
		ua = flow_offset(off1, ua, 0);
1650
		ua = flow_exp(a, ua);
1651
		break;
2 7u83 1652
	}
7 7u83 1653
	case off_ptr_diff_tag: {
1654
		/* Difference of two pointers */
1655
		EXP a = DEREF_exp(off_ptr_diff_ptr1(off));
1656
		EXP b = DEREF_exp(off_ptr_diff_ptr2(off));
1657
		ua = flow_exp(a, ua);
1658
		ua = flow_exp(b, ua);
1659
		break;
2 7u83 1660
	}
7 7u83 1661
	case off_token_tag: {
1662
		/* Tokenised offsets */
1663
		LIST(TOKEN)args = DEREF_list(off_token_args(off));
1664
		ua = flow_token_list(args, ua);
1665
		break;
2 7u83 1666
	}
7 7u83 1667
	}
1668
	ua &= ~va_mask;
1669
	return (ua);
2 7u83 1670
}
1671
 
1672
 
1673
/*
1674
    PERFORM FLOW ANALYSIS ON A LIST OF EXPRESSIONS
1675
 
1676
    This routine performs flow analysis on the list of expressions p.
1677
*/
1678
 
7 7u83 1679
static VAR_INFO
1680
flow_exp_list(LIST(EXP) p, VAR_INFO use, int fn)
2 7u83 1681
{
7 7u83 1682
	while (!IS_NULL_list(p)) {
1683
		EXP a = DEREF_exp(HEAD_list(p));
1684
		if (!IS_NULL_exp(a)) {
1685
			VAR_INFO ua;
1686
			if (fn) {
1687
				ua = flow_alias_exp(a, use);
1688
			} else {
1689
				ua = flow_exp(a, use);
1690
			}
1691
			if (ua & va_unreached) {
1692
				use |= va_unreached;
1693
			}
1694
		}
1695
		p = TAIL_list(p);
2 7u83 1696
	}
7 7u83 1697
	return (use);
2 7u83 1698
}
1699
 
1700
 
1701
/*
1702
    PERFORM FLOW ANALYSIS ON AN ALIASED EXPRESSION
1703
 
1704
    This routine performs flow analysis on the expression e which may be
1705
    aliased by being on the right hand side of an assignment.  Note that
1706
    there are read-only and read-write aliases, depending on whether the
1707
    access is through a pointer or reference to const or not.
1708
*/
1709
 
7 7u83 1710
static VAR_INFO
1711
flow_alias_exp(EXP e, VAR_INFO use)
2 7u83 1712
{
7 7u83 1713
	VAR_INFO ua = (use | va_alias_used);
1714
	if (!IS_NULL_exp(e)) {
1715
		TYPE t = DEREF_type(exp_type(e));
1716
		CV_SPEC cv = find_cv_qual(t);
1717
		if (cv & cv_lvalue) {
1718
			/* Aliased via lvalue */
1719
			if (!(cv & cv_const)) {
1720
				ua |= va_alias_set;
1721
			}
1722
		}
1723
		if (IS_type_ptr_etc(t)) {
1724
			/* Aliased via pointer or reference */
1725
			TYPE s = DEREF_type(type_ptr_etc_sub(t));
1726
			cv = find_cv_qual(s);
1727
			if (!(cv & cv_const)) {
1728
				ua |= va_alias_set;
1729
			}
1730
		}
2 7u83 1731
	}
7 7u83 1732
	ua = flow_exp(e, ua);
1733
	return (ua);
2 7u83 1734
}
1735
 
1736
 
1737
/*
1738
    PERFORM FLOW ANALYSIS ON AN EXPRESSION
1739
 
1740
    This routine performs flow analysis on the expression e.
1741
*/
1742
 
7 7u83 1743
static VAR_INFO
1744
flow_exp(EXP e, VAR_INFO use)
2 7u83 1745
{
7 7u83 1746
	VAR_INFO ua = (use & ~va_mask);
1747
	if (IS_NULL_exp(e)) {
1748
		return (ua);
1749
	}
1750
	ASSERT(ORDER_exp == 88);
1751
	switch (TAG_exp(e)) {
1752
	case exp_identifier_tag: {
1753
		/* Identifier expressions */
1754
		IDENTIFIER id = DEREF_id(exp_identifier_id(e));
1755
		if (IS_id_variable_etc(id)) {
1756
			DECL_SPEC ds = DEREF_dspec(id_storage(id));
1757
			if (ds & dspec_auto) {
1758
				set_variable(id, use);
1759
				if ((ds & va_this) && (use & va_alias)) {
1760
					/* Allow for aliasing using 'this' */
1761
					set_members(use);
1762
				}
1763
			}
2 7u83 1764
		}
7 7u83 1765
		break;
2 7u83 1766
	}
7 7u83 1767
	case exp_assign_tag: {
1768
		/* Assignment expressions */
1769
		EXP a = DEREF_exp(exp_assign_ref(e));
1770
		EXP b = DEREF_exp(exp_assign_arg(e));
1771
		ua = flow_alias_exp(b, ua);
1772
		if (ua & va_unreached) {
1773
			use |= va_unreached;
1774
		}
1775
		ua = flow_exp(a,(use | va_assign));
1776
		break;
2 7u83 1777
	}
7 7u83 1778
	case exp_init_tag: {
1779
		/* Initialisation expressions */
1780
		EXP a = DEREF_exp(exp_init_arg(e));
1781
		ua = flow_alias_exp(a, ua);
1782
		if (ua & va_unreached) {
1783
			use |= va_unreached;
2 7u83 1784
		}
7 7u83 1785
		if (!IS_NULL_exp(a)) {
1786
			IDENTIFIER id = DEREF_id(exp_init_id(e));
1787
			if (IS_id_variable(id)) {
1788
				DECL_SPEC ds = DEREF_dspec(id_storage(id));
1789
				if (ds & dspec_auto) {
1790
					/* Initialiser expression */
1791
					set_variable(id,(use | va_assign));
1792
					break;
1793
				}
1794
			}
1795
		}
1796
		break;
2 7u83 1797
	}
7 7u83 1798
	case exp_preinc_tag: {
1799
		/* Pre-increment expressions */
1800
		EXP a = DEREF_exp(exp_preinc_ref(e));
1801
		EXP b = DEREF_exp(exp_preinc_op(e));
1802
		EXP c = DEREF_exp(exp_dummy_value(a));
1803
		int op = DEREF_int(exp_preinc_becomes(e));
1804
		if (op == lex_assign) {
1805
			/* Bitfield assignment */
1806
			ua = flow_alias_exp(b, ua);
1807
			if (ua & va_unreached) {
1808
				use |= va_unreached;
1809
			}
1810
			if (!IS_NULL_list(crt_flow_mems) && is_this_exp(c)) {
1811
				/* Have 'this->off' */
1812
				OFFSET off = DEREF_off(exp_dummy_off(a));
1813
				ua = flow_offset(off,(use | va_assign), 1);
1814
				break;
1815
			}
1816
			use |= va_partial;
1817
		} else {
1818
			COPY_exp(exp_dummy_value(a), NULL_exp);
1819
			ua = flow_exp(b, ua);
1820
			COPY_exp(exp_dummy_value(a), c);
1821
			if (ua & va_unreached) {
1822
				use |= va_unreached;
1823
			}
1824
			use |= va_becomes;
2 7u83 1825
		}
7 7u83 1826
		ua = flow_exp(c,(use | va_assign));
1827
		break;
2 7u83 1828
	}
7 7u83 1829
	case exp_postinc_tag: {
1830
		/* Post-increment expressions */
1831
		EXP a = DEREF_exp(exp_postinc_ref(e));
1832
		EXP b = DEREF_exp(exp_postinc_op(e));
1833
		EXP c = DEREF_exp(exp_dummy_value(a));
1834
		COPY_exp(exp_dummy_value(a), NULL_exp);
1835
		ua = flow_exp(b, ua);
1836
		COPY_exp(exp_dummy_value(a), c);
1837
		if (ua & va_unreached) {
1838
			use |= va_unreached;
1839
		}
1840
		ua = flow_exp(a,(use | va_becomes));
1841
		break;
2 7u83 1842
	}
7 7u83 1843
	case exp_indir_tag: {
1844
		/* Indirection expressions */
1845
		EXP a = DEREF_exp(exp_indir_ptr(e));
1846
		if (!IS_NULL_list(crt_flow_mems) && is_this_exp(e)) {
1847
			/* Have '*this' */
1848
			set_members(use);
1849
			break;
2 7u83 1850
		}
7 7u83 1851
		if (IS_exp_add_ptr(a)) {
1852
			EXP b = DEREF_exp(exp_add_ptr_ptr(a));
1853
			OFFSET off = DEREF_off(exp_add_ptr_off(a));
1854
			if (!IS_NULL_list(crt_flow_mems) && is_this_exp(b)) {
1855
				/* Have 'this->off' */
1856
				ua = flow_offset(off, use, 1);
1857
				break;
1858
			}
1859
			if (IS_exp_address(b)) {
1860
				/* Have 'c.off' */
1861
				EXP c = DEREF_exp(exp_address_arg(b));
1862
				ua = flow_offset(off, use, 0);
1863
				if (ua & va_unreached) {
1864
					use |= va_unreached;
1865
				}
1866
				ua = flow_exp(c,(use | va_partial));
1867
				break;
1868
			}
1869
		} else if (IS_exp_address(a)) {
1870
			/* Have '*&b' */
1871
			EXP b = DEREF_exp(exp_address_arg(a));
1872
			ua = flow_exp(b, use);
1873
			break;
2 7u83 1874
		}
7 7u83 1875
		ua = flow_exp(a, ua);
1876
		break;
2 7u83 1877
	}
7 7u83 1878
	case exp_contents_tag: {
1879
		/* Contents expressions */
1880
		EXP a = DEREF_exp(exp_contents_ptr(e));
1881
		ua = flow_exp(a, ua);
1882
		break;
2 7u83 1883
	}
7 7u83 1884
	case exp_address_tag: {
1885
		/* Address expressions */
1886
		EXP a = DEREF_exp(exp_address_arg(e));
1887
		if (IS_exp_indir(a) && !is_this_exp(a)) {
1888
			EXP b = DEREF_exp(exp_indir_ptr(a));
1889
			TYPE t = DEREF_type(exp_type(b));
1890
			if (!IS_type_ref(t)) {
1891
				ua = flow_exp(b, use);
1892
				break;
1893
			}
2 7u83 1894
		}
7 7u83 1895
		ua = (use & ~va_other);
1896
		ua = flow_exp(a,(ua | va_address));
1897
		break;
2 7u83 1898
	}
7 7u83 1899
	case exp_address_mem_tag: {
1900
		/* Member address expressions */
1901
		EXP a = DEREF_exp(exp_address_mem_arg(e));
1902
		ua = flow_exp(a, ua);
1903
		break;
2 7u83 1904
	}
7 7u83 1905
	case exp_func_tag: {
1906
		/* Function expressions */
1907
		TYPE t = DEREF_type(exp_type(e));
1908
		EXP a = DEREF_exp(exp_func_fn(e));
1909
		LIST(EXP)args = DEREF_list(exp_func_args(e));
1910
		ua = flow_exp(a, ua);
1911
		ua = flow_exp_list(args, ua, 1);
1912
		if (IS_type_bottom(t)) {
1913
			/* Deal with functions like exit */
1914
			ua = flow_terminate(ua, 1);
1915
		}
1916
		break;
2 7u83 1917
	}
7 7u83 1918
	case exp_func_id_tag: {
1919
		/* Function expressions */
1920
		TYPE t = DEREF_type(exp_type(e));
1921
		LIST(EXP) args = DEREF_list(exp_func_id_args(e));
1922
		ua = flow_exp_list(args, ua, 1);
1923
		if (IS_type_bottom(t)) {
1924
			/* Deal with functions like exit */
1925
			ua = flow_terminate(ua, 1);
1926
		}
1927
		break;
2 7u83 1928
	}
7 7u83 1929
	case exp_call_tag: {
1930
		/* Pointer to member function expressions */
1931
		EXP a = DEREF_exp(exp_call_ptr(e));
1932
		EXP b = DEREF_exp(exp_call_arg(e));
1933
		ua = flow_exp(a, ua);
1934
		ua = flow_exp(b, ua);
1935
		break;
2 7u83 1936
	}
7 7u83 1937
	case exp_negate_tag:
1938
	case exp_compl_tag:
1939
	case exp_not_tag:
1940
	case exp_abs_tag: {
1941
		/* Unary expressions */
1942
		EXP a = DEREF_exp(exp_negate_etc_arg(e));
1943
		ua = flow_exp(a, ua);
1944
		break;
2 7u83 1945
	}
7 7u83 1946
	case exp_plus_tag:
1947
	case exp_minus_tag:
1948
	case exp_mult_tag:
1949
	case exp_div_tag:
1950
	case exp_rem_tag:
1951
	case exp_and_tag:
1952
	case exp_or_tag:
1953
	case exp_xor_tag:
1954
	case exp_lshift_tag:
1955
	case exp_rshift_tag:
1956
	case exp_max_tag:
1957
	case exp_min_tag: {
1958
		/* Binary expressions */
1959
		EXP a = DEREF_exp(exp_plus_etc_arg1(e));
1960
		EXP b = DEREF_exp(exp_plus_etc_arg2(e));
1961
		ua = flow_exp(a, ua);
1962
		ua = flow_exp(b, ua);
1963
		break;
2 7u83 1964
	}
7 7u83 1965
	case exp_log_and_tag:
1966
	case exp_log_or_tag: {
1967
		/* Logical expressions */
1968
		EXP a = DEREF_exp(exp_plus_etc_arg1(e));
1969
		EXP b = DEREF_exp(exp_plus_etc_arg2(e));
1970
		ua = flow_exp(a, ua);
1971
		flow_sequence_point();
1972
		ua = flow_exp(b, ua);
1973
		break;
2 7u83 1974
	}
7 7u83 1975
	case exp_test_tag: {
1976
		/* Test expressions */
1977
		EXP a = DEREF_exp(exp_test_arg(e));
1978
		ua = flow_exp(a, ua);
1979
		break;
2 7u83 1980
	}
7 7u83 1981
	case exp_compare_tag: {
1982
		/* Comparison expressions */
1983
		EXP a = DEREF_exp(exp_compare_arg1(e));
1984
		EXP b = DEREF_exp(exp_compare_arg2(e));
1985
		ua = flow_exp(a, ua);
1986
		ua = flow_exp(b, ua);
1987
		break;
2 7u83 1988
	}
7 7u83 1989
	case exp_cast_tag: {
1990
		/* Cast expressions */
1991
		TYPE t = DEREF_type(exp_type(e));
1992
		EXP a = DEREF_exp(exp_cast_arg(e));
1993
		ua = (use & ~va_other);
1994
		ua = flow_exp(a, ua);
1995
		if (IS_type_bottom(t)) {
1996
			/* Allow for casting to bottom */
1997
			ua = flow_terminate(ua, 1);
1998
		}
1999
		break;
2 7u83 2000
	}
7 7u83 2001
	case exp_base_cast_tag: {
2002
		/* Base cast expressions */
2003
		EXP a = DEREF_exp(exp_base_cast_arg(e));
2004
		ua = (use & ~va_other);
2005
		ua = flow_exp(a, ua);
2006
		break;
2 7u83 2007
	}
7 7u83 2008
	case exp_dyn_cast_tag: {
2009
		/* Dynamic cast expressions */
2010
		EXP a = DEREF_exp(exp_dyn_cast_arg(e));
2011
		ua = (use & ~va_other);
2012
		ua = flow_exp(a, ua);
2013
		break;
2 7u83 2014
	}
7 7u83 2015
	case exp_add_ptr_tag: {
2016
		/* Pointer addition expressions */
2017
		EXP a = DEREF_exp(exp_add_ptr_ptr(e));
2018
		OFFSET off = DEREF_off(exp_add_ptr_off(e));
2019
		if (!IS_NULL_list(crt_flow_mems) && is_this_exp(a)) {
2020
			/* Have 'this->off' */
2021
			use &= ~va_other;
2022
			ua = flow_offset(off, use, 1);
2023
			break;
2024
		}
2025
		ua = flow_offset(off, ua, 0);
2026
		if (ua & va_unreached) {
2027
			use |= va_unreached;
2028
		}
2029
		use &= ~va_other;
2030
		ua = flow_exp(a, use);
2031
		break;
2 7u83 2032
	}
7 7u83 2033
	case exp_offset_size_tag: {
2034
		/* Offset expressions */
2035
		OFFSET off = DEREF_off(exp_offset_size_off(e));
2036
		ua = flow_offset(off, ua, 0);
2037
		break;
2 7u83 2038
	}
7 7u83 2039
	case exp_constr_tag: {
2040
		/* Constructor calls */
2041
		EXP a = DEREF_exp(exp_constr_call(e));
2042
		ua = flow_exp(a, ua);
2043
		break;
2 7u83 2044
	}
7 7u83 2045
	case exp_destr_tag: {
2046
		/* Destructor calls */
2047
		EXP a = DEREF_exp(exp_destr_call(e));
2048
		ua = flow_exp(a, ua);
2049
		break;
2 7u83 2050
	}
7 7u83 2051
	case exp_alloc_tag: {
2052
		/* Allocation expressions */
2053
		EXP a = DEREF_exp(exp_alloc_call(e));
2054
		EXP b = DEREF_exp(exp_alloc_init(e));
2055
		ua = flow_exp(a, ua);
2056
		ua = flow_exp(b, ua);
2057
		break;
2 7u83 2058
	}
7 7u83 2059
	case exp_dealloc_tag: {
2060
		/* Deallocation expressions */
2061
		EXP a = DEREF_exp(exp_dealloc_term(e));
2062
		EXP b = DEREF_exp(exp_dealloc_call(e));
2063
		EXP c = DEREF_exp(exp_dealloc_arg(e));
2064
		EXP d = DEREF_exp(exp_dummy_value(c));
2065
		ua = flow_exp(a, ua);
2066
		ua = flow_exp(b, ua);
2067
		ua = flow_set(d, ua, va_none);
2068
		break;
2 7u83 2069
	}
7 7u83 2070
	case exp_rtti_tag: {
2071
		/* Run-time type information expressions */
2072
		EXP a = DEREF_exp(exp_rtti_arg(e));
2073
		ua = flow_exp(a, ua);
2074
		break;
2 7u83 2075
	}
7 7u83 2076
	case exp_dynamic_tag: {
2077
		/* Dynamic initialiser expressions */
2078
		EXP a = DEREF_exp(exp_dynamic_arg(e));
2079
		ua = flow_exp(a, ua);
2080
		break;
2 7u83 2081
	}
7 7u83 2082
	case exp_aggregate_tag: {
2083
		/* Aggregate initialiser expressions */
2084
		LIST(EXP) args;
2085
		args = DEREF_list(exp_aggregate_args(e));
2086
		ua = flow_exp_list(args, ua, 0);
2087
		break;
2 7u83 2088
	}
7 7u83 2089
	case exp_initialiser_tag: {
2090
		/* Constructor initialiser expressions */
2091
		int kind = DEREF_int(exp_initialiser_kind(e));
2092
		LIST(EXP) p = DEREF_list(exp_initialiser_args(e));
2093
		LIST(OFFSET) q = DEREF_list(exp_initialiser_offs(e));
2094
		if (kind == 0) {
2095
			q = NULL_list(OFFSET);
2 7u83 2096
		}
7 7u83 2097
		while (!IS_NULL_list(p)) {
2098
			EXP a = DEREF_exp(HEAD_list(p));
2099
			ua = flow_exp(a, ua);
2100
			if (!IS_NULL_list(q)) {
2101
				OFFSET off = DEREF_off(HEAD_list(q));
2102
				if (kind != DEFAULT_DESTR && !IS_NULL_exp(a)) {
2103
					ua |= va_assign;
2104
				}
2105
				ua = flow_offset(off, ua, 1);
2106
				flow_sequence_point();
2107
				q = TAIL_list(q);
2108
			}
2109
			p = TAIL_list(p);
2110
		}
2111
		break;
2 7u83 2112
	}
7 7u83 2113
	case exp_nof_tag: {
2114
		/* Array initialiser expressions */
2115
		EXP a = DEREF_exp(exp_nof_start(e));
2116
		EXP b = DEREF_exp(exp_nof_pad(e));
2117
		EXP c = DEREF_exp(exp_nof_end(e));
2118
		ua = flow_exp(a, ua);
2119
		ua = flow_exp(b, ua);
2120
		ua = flow_exp(c, ua);
2121
		break;
2 7u83 2122
	}
7 7u83 2123
	case exp_comma_tag: {
2124
		/* Comma expressions */
2125
		LIST(EXP) p = DEREF_list(exp_comma_args(e));
2126
		if (!IS_NULL_list(p)) {
2127
			EXP a;
2128
			for (;;) {
2129
				a = DEREF_exp(HEAD_list(p));
2130
				p = TAIL_list(p);
2131
				if (IS_NULL_list(p)) {
2132
					break;
2133
				}
2134
				ua = flow_exp(a, ua);
2135
				flow_sequence_point();
2136
				if (ua & va_unreached) {
2137
					use |= va_unreached;
2138
				}
2139
			}
2140
			ua = flow_exp(a, use);
2 7u83 2141
		}
7 7u83 2142
		break;
2 7u83 2143
	}
7 7u83 2144
	case exp_if_stmt_tag: {
2145
		/* Conditional expressions */
2146
		EXP c = DEREF_exp(exp_if_stmt_cond(e));
2147
		EXP a = DEREF_exp(exp_if_stmt_true_code(e));
2148
		EXP b = DEREF_exp(exp_if_stmt_false_code(e));
2149
		ua = flow_if_exp(c, a, b, ua, 1);
2150
		break;
2 7u83 2151
	}
7 7u83 2152
	case exp_exception_tag: {
2153
		/* Exception expressions */
2154
		EXP a = DEREF_exp(exp_exception_arg(e));
2155
		ua = flow_exp(a, ua);
2156
		ua = flow_terminate(ua, 1);
2157
		break;
2 7u83 2158
	}
7 7u83 2159
	case exp_set_tag: {
2160
		/* Set expressions */
2161
		EXP a = DEREF_exp(exp_set_arg(e));
2162
		ua = flow_set(a, ua, va_set);
2163
		break;
2 7u83 2164
	}
7 7u83 2165
	case exp_unused_tag: {
2166
		/* Unused expressions */
2167
		EXP a = DEREF_exp(exp_unused_arg(e));
2168
		ua = flow_set(a, ua, va_none);
2169
		break;
2 7u83 2170
	}
7 7u83 2171
	case exp_op_tag: {
2172
		/* Undetermined expressions */
2173
		EXP a = DEREF_exp(exp_op_arg1(e));
2174
		EXP b = DEREF_exp(exp_op_arg2(e));
2175
		ua = flow_exp(a, ua);
2176
		ua = flow_exp(b, ua);
2177
		break;
2 7u83 2178
	}
7 7u83 2179
	case exp_opn_tag: {
2180
		/* Undetermined expressions */
2181
		LIST(EXP) args = DEREF_list(exp_opn_args(e));
2182
		ua = flow_exp_list(args, ua, 0);
2183
		break;
2 7u83 2184
	}
7 7u83 2185
	case exp_token_tag: {
2186
		/* Tokenised expressions */
2187
		LIST(TOKEN) args = DEREF_list(exp_token_args(e));
2188
		ua = flow_token_list(args, ua);
2189
		break;
2 7u83 2190
	}
7 7u83 2191
	case exp_dummy_tag: {
2192
		/* Dummy expressions */
2193
		EXP a = DEREF_exp(exp_dummy_value(e));
2194
		ua = flow_exp(a, use);
2195
		break;
2 7u83 2196
	}
7 7u83 2197
	case exp_paren_tag:
2198
	case exp_copy_tag: {
2199
		/* Parenthesised expressions */
2200
		EXP a = DEREF_exp(exp_paren_etc_arg(e));
2201
		ua = flow_exp(a, use);
2202
		break;
2 7u83 2203
	}
7 7u83 2204
	case exp_location_tag: {
2205
		/* Location expressions */
2206
		EXP a = DEREF_exp(exp_location_arg(e));
2207
		ua = flow_exp(a, use);
2208
		DEREF_loc(exp_location_end(e), stmt_loc);
2209
		break;
2 7u83 2210
	}
7 7u83 2211
	case exp_sequence_tag:
2212
	case exp_solve_stmt_tag:
2213
	case exp_decl_stmt_tag:
2214
	case exp_while_stmt_tag:
2215
	case exp_do_stmt_tag:
2216
	case exp_switch_stmt_tag:
2217
	case exp_hash_if_tag:
2218
	case exp_return_stmt_tag:
2219
	case exp_goto_stmt_tag:
2220
	case exp_label_stmt_tag:
2221
	case exp_try_block_tag:
2222
	case exp_handler_tag:
2223
	case exp_reach_tag:
2224
	case exp_unreach_tag:
2225
		/* Statements */
2226
		ua = flow_stmt(e, ua, 1);
2227
		break;
2 7u83 2228
	}
7 7u83 2229
	ua &= ~va_mask;
2230
	return (ua);
2 7u83 2231
}
2232
 
2233
 
2234
/*
2235
    PERFORM FLOW ANALYSIS FOR DESTRUCTORS
2236
 
2237
    This routine performs flow analysis for any destructors called by
2238
    the goto or return statement a.  b gives smallest statement enclosing
2239
    both the jump and its destination.
2240
*/
2241
 
7 7u83 2242
static void
2243
flow_jump(EXP a, EXP b)
2 7u83 2244
{
7 7u83 2245
	unsigned long d = no_destructors;
2246
	while (!IS_NULL_exp(a) && !EQ_exp(a, b) && d) {
2247
		/* Scan up to enclosing statement */
2248
		if (IS_exp_decl_stmt(a)) {
2249
			IDENTIFIER id = DEREF_id(exp_decl_stmt_id(a));
2250
			if (IS_id_variable(id)) {
2251
				DECL_SPEC ds = DEREF_dspec(id_storage(id));
2252
				if (ds & dspec_auto) {
2253
					/* Local variable */
2254
					EXP term =
2255
					    DEREF_exp(id_variable_term(id));
2256
					if (!IS_NULL_exp(term)) {
2257
						if (do_usage) {
2258
							dump_destr(id,
2259
								   &stmt_loc);
2260
						}
2261
						d--;
2262
					}
2263
				}
2264
			}
2 7u83 2265
		}
7 7u83 2266
		a = get_parent_stmt(a);
2 7u83 2267
	}
7 7u83 2268
	return;
2 7u83 2269
}
2270
 
2271
 
2272
/*
2273
    PERFORM FLOW ANALYSIS ON A WHILE STATEMENT
2274
 
2275
    This routine performs flow analysis on the while statement e.
2276
*/
2277
 
7 7u83 2278
static VAR_INFO
2279
flow_while_stmt(EXP e, VAR_INFO use, int flow)
2 7u83 2280
{
7 7u83 2281
	VAR_INFO ua;
2282
	EXP c = DEREF_exp(exp_while_stmt_cond(e));
2283
	EXP a = DEREF_exp(exp_while_stmt_body(e));
2284
	IDENTIFIER blab = DEREF_id(exp_while_stmt_break_lab(e));
2285
	IDENTIFIER clab = DEREF_id(exp_while_stmt_cont_lab(e));
2286
	unsigned cv = eval_const_cond(c);
2287
	if (flow) {
2288
		use = flow_exp(c, use);
2289
		flow_sequence_point();
2290
	}
2291
	ua = use;
2292
	if (cv != BOOL_TRUE) {
2293
		IGNORE flow_goto_stmt(blab, use, 1);
2294
		if (cv == BOOL_FALSE) {
2295
			ua |= va_unreached;
2296
		}
2297
	}
2298
	ua = flow_stmt(a, ua, flow);
2299
	ua = flow_label_stmt(clab, ua, flow);
2300
	if (flow) {
2301
		IGNORE flow_exp(c, ua);
2302
		flow_sequence_point();
2303
	}
2304
	mark_vars(crt_flow_vars, va_used_this);
2305
	use = flow_label_stmt(blab,(use | va_unreached), flow);
2306
	return (use);
2 7u83 2307
}
2308
 
2309
 
2310
/*
2311
    PERFORM FLOW ANALYSIS ON A DO STATEMENT
2312
 
2313
    This routine performs flow analysis on the do statement e.
2314
*/
2315
 
7 7u83 2316
static VAR_INFO
2317
flow_do_stmt(EXP e, VAR_INFO use, int flow)
2 7u83 2318
{
7 7u83 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);
2 7u83 2336
}
2337
 
2338
 
2339
/*
2340
    PERFORM FLOW ANALYSIS ON A SOLVE STATEMENT
2341
 
2342
    This routine performs flow analysis on the solve statement e with
2343
    associated variables p.
2344
*/
2345
 
7 7u83 2346
static VAR_INFO
2347
flow_solve_stmt(EXP e, LIST(IDENTIFIER) p, VAR_INFO use, int flow)
2 7u83 2348
{
7 7u83 2349
	if (!IS_NULL_list(p)) {
2350
		/* Scan through variables */
2351
		IDENTIFIER id = DEREF_id(HEAD_list(p));
2352
		DECL_SPEC ds = DEREF_dspec(id_storage(id));
2353
		if ((ds & dspec_auto) && !(ds & dspec_done)) {
2354
			start_variable(id, ds, va_none);
2355
			use = flow_solve_stmt(e, TAIL_list(p), use, flow);
2356
			end_variable(flow, 0);
2357
			return (use);
2358
		}
2359
		use = flow_solve_stmt(e, TAIL_list(p), use, flow);
2360
		return (use);
2 7u83 2361
	}
7 7u83 2362
	use = flow_stmt(e, use, flow);
2363
	return (use);
2 7u83 2364
}
2365
 
2366
 
2367
/*
2368
    PERFORM FLOW ANALYSIS ON A SWITCH STATEMENT
2369
 
2370
    This routine performs flow analysis on the switch statement e.
2371
*/
2372
 
7 7u83 2373
static VAR_INFO
2374
flow_switch_stmt(EXP e, VAR_INFO use, int flow)
2 7u83 2375
{
7 7u83 2376
	EXP a = DEREF_exp(exp_switch_stmt_body(e));
2377
	int exhaust = DEREF_int(exp_switch_stmt_exhaust(e));
2378
	LIST(IDENTIFIER) p = DEREF_list(exp_switch_stmt_case_labs(e));
2379
	IDENTIFIER dlab = DEREF_id(exp_switch_stmt_default_lab(e));
2380
	IDENTIFIER blab = DEREF_id(exp_switch_stmt_break_lab(e));
2381
	if (flow) {
2382
		/* Deal with control statement */
2383
		EXP c = DEREF_exp(exp_switch_stmt_control(e));
2384
		use = flow_exp(c, use);
2385
		flow_sequence_point();
2 7u83 2386
	}
7 7u83 2387
	if (!IS_NULL_id(dlab)) {
2388
		/* Mark jumps to default statement */
2389
		dlab = DEREF_id(id_alias(dlab));
2390
		IGNORE flow_goto_stmt(dlab, use, 1);
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;
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);
2409
	use = flow_label_stmt(blab, use, flow);
2410
	return (use);
2 7u83 2411
}
2412
 
2413
 
2414
/*
2415
    PERFORM FLOW ANALYSIS ON A TRY BLOCK
2416
 
2417
    This routine performs flow analysis on the try block e.
2418
*/
2419
 
7 7u83 2420
static VAR_INFO
2421
flow_try_block(EXP e, VAR_INFO use, int flow)
2 7u83 2422
{
7 7u83 2423
	VAR_INFO ua = (use | va_unreached);
2424
	EXP a = DEREF_exp(exp_try_block_body(e));
2425
	LIST(EXP) p = DEREF_list(exp_try_block_handlers(e));
2426
	EXP c = DEREF_exp(exp_try_block_ellipsis(e));
2427
	use = flow_stmt(a, use, flow);
2428
	/* NOT YET IMPLEMENTED */
2429
	while (!IS_NULL_list(p)) {
2430
		EXP b = DEREF_exp(HEAD_list(p));
2431
		IGNORE flow_stmt(b, ua, flow);
2432
		p = TAIL_list(p);
2433
	}
2434
	IGNORE flow_stmt(c, ua, flow);
2435
	return (use);
2 7u83 2436
}
2437
 
2438
 
2439
/*
2440
    PERFORM FLOW ANALYSIS ON A DECLARATION STATEMENT
2441
 
2442
    This routine performs flow analysis on the declaration statement e.
2443
*/
2444
 
7 7u83 2445
static VAR_INFO
2446
flow_decl_stmt(EXP e, VAR_INFO use, int flow)
2 7u83 2447
{
7 7u83 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
		}
2 7u83 2484
	}
7 7u83 2485
	use = flow_stmt(a, use, flow);
2486
	return (use);
2 7u83 2487
}
2488
 
2489
 
2490
/*
2491
    PERFORM FLOW ANALYSIS ON A STATEMENT
2492
 
2493
    This routine performs flow analysis on the statement e.
2494
*/
2495
 
7 7u83 2496
static VAR_INFO
2497
flow_stmt(EXP e, VAR_INFO use, int flow)
2 7u83 2498
{
7 7u83 2499
	/* Deal with statements */
2500
	VAR_INFO ua = (use & ~va_mask);
2501
	if (IS_NULL_exp(e)) {
2502
		return (ua);
2503
	}
2504
	ASSERT(ORDER_exp == 88);
2505
	switch (TAG_exp(e)) {
2506
	case exp_sequence_tag: {
2507
		/* Compound statements */
2508
		LIST(EXP) p = DEREF_list(exp_sequence_first(e));
2509
		while (!IS_NULL_list(p)) {
2510
			EXP a = DEREF_exp(HEAD_list(p));
2511
			if (!IS_NULL_exp(a)) {
2512
				VAR_INFO ub = flow_stmt(a, ua, flow);
2513
				if (ub & va_unreached) {
2514
					ua |= va_unreached;
2515
				} else {
2516
					ua &= ~va_unreached;
2517
				}
2518
			}
2519
			p = TAIL_list(p);
2 7u83 2520
		}
7 7u83 2521
		break;
2 7u83 2522
	}
7 7u83 2523
	case exp_solve_stmt_tag: {
2524
		/* Solve statements */
2525
		LIST(IDENTIFIER) p;
2526
		EXP a = DEREF_exp(exp_solve_stmt_body(e));
2527
		p = DEREF_list(exp_solve_stmt_vars(e));
2528
		ua = flow_solve_stmt(a, p, ua, flow);
2529
		break;
2 7u83 2530
	}
7 7u83 2531
	case exp_decl_stmt_tag:
2532
		/* Declaration statements */
2533
		ua = flow_decl_stmt(e, ua, flow);
2534
		break;
2535
	case exp_if_stmt_tag: {
2536
		/* Conditional statements */
2537
		EXP c = DEREF_exp(exp_if_stmt_cond(e));
2538
		EXP a = DEREF_exp(exp_if_stmt_true_code(e));
2539
		EXP b = DEREF_exp(exp_if_stmt_false_code(e));
2540
		ua = flow_if_exp(c, a, b, ua, flow);
2541
		break;
2 7u83 2542
	}
7 7u83 2543
	case exp_while_stmt_tag:
2544
		/* While statements */
2545
		ua = flow_while_stmt(e, ua, flow);
2546
		break;
2547
	case exp_do_stmt_tag:
2548
		/* Do statements */
2549
		ua = flow_do_stmt(e, ua, flow);
2550
		break;
2551
	case exp_switch_stmt_tag:
2552
		/* Switch statements */
2553
		ua = flow_switch_stmt(e, ua, flow);
2554
		break;
2555
	case exp_hash_if_tag: {
2556
		/* Target dependent conditional statements */
2557
		EXP c = DEREF_exp(exp_hash_if_cond(e));
2558
		EXP a = DEREF_exp(exp_hash_if_true_code(e));
2559
		EXP b = DEREF_exp(exp_hash_if_false_code(e));
2560
		ua = flow_if_exp(c, a, b, ua, flow);
2561
		break;
2 7u83 2562
	}
7 7u83 2563
	case exp_return_stmt_tag: {
2564
		/* Return statements */
2565
		EXP a = DEREF_exp(exp_return_stmt_value(e));
2566
		if (flow) {
2567
			ua = flow_exp(a, ua);
2568
			flow_sequence_point();
2569
		}
2570
		ua = flow_terminate(ua, 2);
2571
		flow_jump(e, NULL_exp);
2572
		break;
2 7u83 2573
	}
7 7u83 2574
	case exp_goto_stmt_tag: {
2575
		/* Goto statements */
2576
		EXP join = DEREF_exp(exp_goto_stmt_join(e));
2577
		IDENTIFIER lab = DEREF_id(exp_goto_stmt_label(e));
2578
		lab = DEREF_id(id_alias(lab));
2579
		ua = flow_goto_stmt(lab, ua, 0);
2580
		flow_jump(e, join);
2581
		break;
2 7u83 2582
	}
7 7u83 2583
	case exp_label_stmt_tag: {
2584
		/* Labelled statements */
2585
		IDENTIFIER lab = DEREF_id(exp_label_stmt_label(e));
2586
		ua = flow_label_stmt(lab, ua, flow);
2587
		break;
2 7u83 2588
	}
7 7u83 2589
	case exp_try_block_tag:
2590
		/* Try blocks */
2591
		ua = flow_try_block(e, ua, flow);
2592
		break;
2593
	case exp_handler_tag: {
2594
		/* Exception handlers */
2595
		EXP a = DEREF_exp(exp_handler_body(e));
2596
		ua = flow_stmt(a, ua, flow);
2597
		break;
2 7u83 2598
	}
7 7u83 2599
	case exp_reach_tag: {
2600
		/* Reached statements */
2601
		EXP a = DEREF_exp(exp_reach_body(e));
2602
		ua &= ~va_unreached;
2603
		ua = flow_stmt(a, ua, flow);
2604
		break;
2 7u83 2605
	}
7 7u83 2606
	case exp_unreach_tag: {
2607
		/* Unreached statements */
2608
		EXP a = DEREF_exp(exp_unreach_body(e));
2609
		ua |= va_unreached;
2610
		ua = flow_stmt(a, ua, flow);
2611
		break;
2 7u83 2612
	}
7 7u83 2613
	case exp_location_tag: {
2614
		/* Location expressions */
2615
		EXP a = DEREF_exp(exp_location_arg(e));
2616
		ua = flow_stmt(a, use, flow);
2617
		DEREF_loc(exp_location_end(e), stmt_loc);
2618
		break;
2 7u83 2619
	}
7 7u83 2620
	default:
2621
		/* Simple expressions */
2622
		if (!(ua & va_unreached) && flow) {
2623
			ua = flow_exp(e, ua);
2624
			flow_sequence_point();
2625
		}
2626
		break;
2 7u83 2627
	}
7 7u83 2628
	ua &= ~va_mask;
2629
	return (ua);
2 7u83 2630
}
2631
 
2632
 
2633
/*
2634
    PERFORM FLOW ANALYSIS ON A FUNCTION DEFINITION
2635
 
2636
    This routine performs the flow analysis on the compound statement e
2637
    which defines the function id.  Full flow analysis is enabled if
2638
    flow is true, otherwise a minimal scan sufficient to determine all
2639
    implicit destructor calls is done.
2640
*/
2641
 
7 7u83 2642
void
2643
check_flow(IDENTIFIER id, EXP e, int flow)
2 7u83 2644
{
7 7u83 2645
	VAR_INFO use;
2646
	LIST(IDENTIFIER) pids;
2647
	if (IS_id_function_etc(id)) {
2648
		TYPE t = DEREF_type(id_function_etc_type(id));
2649
		while (IS_type_templ(t)) {
2650
			t = DEREF_type(type_templ_defn(t));
2 7u83 2651
		}
7 7u83 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
				}
2676
				crt_flow_mems = crt_flow_vars;
2677
			}
2678
			if (!IS_NULL_id(pid)) {
2679
				start_variable(pid, dspec_none, va_this);
2680
				set_variable(pid, va_assign);
2681
			}
2682
		}
2683
		pids = DEREF_list(type_func_pids(t));
2684
		while (!IS_NULL_list(pids)) {
2685
			/* Set up parameter scopes */
2686
			IDENTIFIER pid = DEREF_id(HEAD_list(pids));
2687
			if (!IS_NULL_id(pid)) {
2688
				DECL_SPEC ds = DEREF_dspec(id_storage(pid));
2689
				start_variable(pid, ds, va_none);
2690
				set_variable(pid, va_assign);
2691
			}
2692
			pids = TAIL_list(pids);
2693
		}
2 7u83 2694
	}
7 7u83 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);
2 7u83 2703
	}
7 7u83 2704
	stmt_loc = crt_loc;
2705
	return;
2 7u83 2706
}