Subversion Repositories tendra.SVN

Rev

Go to most recent revision | Details | Last modification | View Log | RSS feed

Rev Author Line No. Line
2 7u83 1
/*
2
    		 Crown Copyright (c) 1997
3
 
4
    This TenDRA(r) Computer Program is subject to Copyright
5
    owned by the United Kingdom Secretary of State for Defence
6
    acting through the Defence Evaluation and Research Agency
7
    (DERA).  It is made available to Recipients with a
8
    royalty-free licence for its use, reproduction, transfer
9
    to other parties and amendment for any purpose not excluding
10
    product development provided that any such use et cetera
11
    shall be deemed to be acceptance of the following conditions:-
12
 
13
        (1) Its Recipients shall ensure that this Notice is
14
        reproduced upon any copies or amended versions of it;
15
 
16
        (2) Any amended version of it shall be clearly marked to
17
        show both the nature of and the organisation responsible
18
        for the relevant amendment or amendments;
19
 
20
        (3) Its onward transfer from a recipient to another
21
        party shall be deemed to be that party's acceptance of
22
        these conditions;
23
 
24
        (4) DERA gives no warranty or assurance as to its
25
        quality or suitability for any purpose and DERA accepts
26
        no liability whatsoever in relation to any use to which
27
        it may be put.
28
*/
29
 
30
 
31
#include "config.h"
32
#include "c_types.h"
33
#include "ctype_ops.h"
34
#include "exp_ops.h"
35
#include "hashid_ops.h"
36
#include "id_ops.h"
37
#include "inst_ops.h"
38
#include "member_ops.h"
39
#include "nspace_ops.h"
40
#include "off_ops.h"
41
#include "tok_ops.h"
42
#include "type_ops.h"
43
#include "error.h"
44
#include "catalog.h"
45
#include "basetype.h"
46
#include "check.h"
47
#include "chktype.h"
48
#include "class.h"
49
#include "compile.h"
50
#include "constant.h"
51
#include "construct.h"
52
#include "convert.h"
53
#include "declare.h"
54
#include "dump.h"
55
#include "file.h"
56
#include "function.h"
57
#include "hash.h"
58
#include "identifier.h"
59
#include "initialise.h"
60
#include "instance.h"
61
#include "literal.h"
62
#include "namespace.h"
63
#include "option.h"
64
#include "preproc.h"
65
#include "save.h"
66
#include "statement.h"
67
#include "stmt.h"
68
#include "syntax.h"
69
#include "tok.h"
70
#include "variable.h"
71
 
72
 
73
/*
74
    VARIABLE ANALYSIS FLAGS
75
 
76
    The flag suppress_variable may be set to 1 to suppress variable
77
    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
79
    that objects with C linkage in anonymous namespaces are anonymous.
80
*/
81
 
82
int suppress_variable = 0 ;
83
int anon_c_linkage = 0 ;
84
 
85
 
86
/*
87
    CHECK A VARIABLE OR FUNCTION USAGE
88
 
89
    This routine checks the usage of the identifier id.  The flag anon
90
    is true if the complete reach of the identifier is being analysed.  For
91
    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
93
    its entire program.
94
*/
95
 
96
static void check_usage
97
    PROTO_N ( ( id, blk, anon ) )
98
    PROTO_T ( IDENTIFIER id X EXP blk X int anon )
99
{
100
    int opt ;
101
    ERROR err ;
102
    LOCATION loc ;
103
    HASHID nm = DEREF_hashid ( id_name ( id ) ) ;
104
    if ( !IS_hashid_anon ( nm ) ) {
105
	/* Ignore anonymous identifiers */
106
	DECL_SPEC ds = DEREF_dspec ( id_storage ( id ) ) ;
107
	if ( anon == ANON_NAMESPACE && ( ds & dspec_c ) ) {
108
	    if ( !anon_c_linkage ) anon = ANON_NONE ;
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 ;
114
	    }
115
	}
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 ) {
128
		    /* Defined and used */
129
		    /* EMPTY */
130
		} else {
131
		    /* Defined but not used */
132
		    if ( ds & ( dspec_inline | dspec_virtual ) ) {
133
			/* Ignore inline and virtual functions */
134
			/* EMPTY */
135
		    } else {
136
			if ( ds & dspec_auto ) {
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
			}
151
		    }
152
		}
153
	    } else {
154
		if ( ds & dspec_used ) {
155
		    /* Used but not defined */
156
		    if ( IS_id_class_name_etc ( id ) ) {
157
			/* Alright for type names */
158
			/* EMPTY */
159
		    } else {
160
			if ( ds & dspec_inline ) {
161
			    err = ERR_basic_odr_inline ( id ) ;
162
			} else {
163
			    err = ERR_basic_odr_undef ( id ) ;
164
			}
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
		}
201
	    }
202
	}
203
    }
204
    return ;
205
}
206
 
207
 
208
/*
209
    CHECK A TEMPLATE IDENTIFIER
210
 
211
    This routine calls check_identifier for each instance of the template
212
    id.  t gives the template type, otherwise the parameters are as in
213
    check_identifier.
214
*/
215
 
216
static void check_template_id
217
    PROTO_N ( ( t, id, ns, blk, anon, chk ) )
218
    PROTO_T ( TYPE t X IDENTIFIER id X NAMESPACE ns X EXP blk X
219
	      int anon X int chk )
220
{
221
    DECL_SPEC ds = DEREF_dspec ( id_storage ( id ) ) ;
222
    if ( !( ds & dspec_done ) ) {
223
	/* Scan through template applications */
224
	TOKEN sort = DEREF_tok ( type_templ_sort ( t ) ) ;
225
	INSTANCE apps = DEREF_inst ( tok_templ_apps ( sort ) ) ;
226
	COPY_dspec ( id_storage ( id ), ( ds | dspec_done ) ) ;
227
	while ( !IS_NULL_inst ( apps ) ) {
228
	    DECL_SPEC acc = DEREF_dspec ( inst_templ_access ( apps ) ) ;
229
	    if ( !( acc & ( dspec_main | dspec_alias ) ) ) {
230
		if ( ( acc & dspec_instance ) && !( acc & dspec_mutable ) ) {
231
		    IDENTIFIER aid = DEREF_id ( inst_templ_id ( apps ) ) ;
232
		    IGNORE check_identifier ( aid, ns, blk, anon, chk ) ;
233
		}
234
	    }
235
	    apps = DEREF_inst ( inst_next ( apps ) ) ;
236
	}
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 ) {
256
	IDENTIFIER id = DEREF_id ( ctype_destr ( ct ) ) ;
257
	if ( !IS_NULL_id ( id ) && IS_id_mem_func ( id ) ) {
258
	    DECL_SPEC ds = DEREF_dspec ( id_storage ( id ) ) ;
259
	    if ( !( ds & dspec_trivial ) ) {
260
		DEREF_loc ( id_loc ( id ), loc ) ;
261
		report ( loc, ERR_expr_delete_post ( id ) ) ;
262
	    }
263
	}
264
    }
265
    if ( cu & cusage_delete ) {
266
	IDENTIFIER id = find_operator ( ct, lex_delete ) ;
267
	if ( !IS_NULL_id ( id ) ) {
268
	    DEREF_loc ( id_loc ( id ), loc ) ;
269
	    report ( loc, ERR_expr_delete_post ( id ) ) ;
270
	}
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
	}
278
    }
279
    if ( cu & cusage_address ) {
280
	IDENTIFIER id = find_operator ( ct, lex_and_H1 ) ;
281
	while ( !IS_NULL_id ( id ) && IS_id_function_etc ( id ) ) {
282
	    TYPE t = DEREF_type ( id_function_etc_type ( id ) ) ;
283
	    if ( min_no_args ( t ) == 1 ) {
284
		DEREF_loc ( id_loc ( id ), loc ) ;
285
		report ( loc, ERR_expr_unary_op_ref_post ( id ) ) ;
286
		break ;
287
	    }
288
	    id = DEREF_id ( id_function_etc_over ( id ) ) ;
289
	}
290
    }
291
    return ;
292
}
293
 
294
 
295
/*
296
    COMPLETE A TENTATIVE DEFINITION
297
 
298
    This routine completes a C-style tentative definition of the
299
    variable id.  That is, if id has not been defined elsewhere, then
300
    it is defined to be zero.
301
*/
302
 
303
static int define_tentative
304
    PROTO_N ( ( id, anon ) )
305
    PROTO_T ( IDENTIFIER id X int anon )
306
{
307
    int def = 0 ;
308
    EXP e = DEREF_exp ( id_variable_etc_init ( id ) ) ;
309
    if ( !IS_NULL_exp ( e ) && IS_exp_zero ( e ) ) {
310
	LOCATION loc ;
311
	DECL_SPEC ds = DEREF_dspec ( id_storage ( id ) ) ;
312
	TYPE t = DEREF_type ( id_variable_etc_type ( id ) ) ;
313
	bad_crt_loc++ ;
314
	loc = crt_loc ;
315
	DEREF_loc ( id_loc ( id ), crt_loc ) ;
316
	if ( anon || !( ds & dspec_extern ) ) {
317
	    /* Types for internal objects should be complete */
318
	    ERROR err = check_complete ( t ) ;
319
	    if ( !IS_NULL_err ( err ) ) {
320
		ERROR err2 = ERR_basic_types_tent_incompl ( id ) ;
321
		err = concat_error ( err, err2 ) ;
322
		report ( crt_loc, err ) ;
323
            }
324
	}
325
	if ( IS_type_array ( t ) ) {
326
	    /* Complete array 'A []' to 'A [1]' */
327
	    NAT n = DEREF_nat ( type_array_size ( t ) ) ;
328
	    if ( IS_NULL_nat ( n ) ) {
329
		CV_SPEC qual = DEREF_cv ( type_qual ( t ) ) ;
330
		TYPE s = DEREF_type ( type_array_sub ( t ) ) ;
331
		n = small_nat [1] ;
332
		MAKE_type_array ( qual, s, n, t ) ;
333
		COPY_type ( id_variable_etc_type ( id ), t ) ;
334
	    }
335
	}
336
	e = init_general ( t, NULL_exp, id, 0 ) ;
337
	COPY_exp ( id_variable_etc_init ( id ), e ) ;
338
	define_id ( id ) ;
339
	crt_loc = loc ;
340
	bad_crt_loc-- ;
341
	def = 1 ;
342
    }
343
    return ( def ) ;
344
}
345
 
346
 
347
/*
348
    CHECK A GLOBAL IDENTIFIER
349
 
350
    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
352
    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
354
    translation unit.  The routine returns the number of identifiers in
355
    id (allowing for overloaded functions).
356
*/
357
 
358
unsigned long check_identifier
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 )
361
{
362
    unsigned long n = 1 ;
363
    if ( spec_unit ) spec_unit = save_id ( spec_unit, id, ns ) ;
364
    switch ( TAG_id ( id ) ) {
365
 
366
	case id_class_name_tag : {
367
	    /* Check the members of a class */
368
	    DECL_SPEC ds = DEREF_dspec ( id_storage ( id ) ) ;
369
	    if ( !( ds & dspec_implicit ) ) {
370
		int templ = 0 ;
371
		CLASS_TYPE ct ;
372
		CLASS_INFO ci ;
373
		NAMESPACE cns ;
374
		int tchk = chk ;
375
		TYPE t = DEREF_type ( id_class_name_defn ( id ) ) ;
376
		TYPE s = t ;
377
		while ( IS_type_templ ( t ) ) {
378
		    /* Template classes */
379
		    templ = 1 ;
380
		    tchk = 0 ;
381
		    t = DEREF_type ( type_templ_defn ( t ) ) ;
382
		}
383
		ct = DEREF_ctype ( type_compound_defn ( t ) ) ;
384
		cns = DEREF_nspace ( ctype_member ( ct ) ) ;
385
		ci = DEREF_cinfo ( ctype_info ( ct ) ) ;
386
		if ( ci & cinfo_complete ) {
387
		    /* Check class member namespace */
388
		    CLASS_USAGE cu = DEREF_cusage ( ctype_usage ( ct ) ) ;
389
		    IDENTIFIER cid = DEREF_id ( ctype_name ( ct ) ) ;
390
		    HASHID cnm = DEREF_hashid ( id_name ( cid ) ) ;
391
		    if ( IS_hashid_anon ( cnm ) ) anon = ANON_CLASS ;
392
#if LANGUAGE_CPP
393
		    if ( ( ci & cinfo_polymorphic ) && tchk ) {
394
			/* Compile virtual function table */
395
			compile_virtual ( ct, anon ) ;
396
		    }
397
#endif
398
		    if ( cu != cusage_none ) {
399
			/* Check class usage */
400
			check_class_usage ( ct, cu ) ;
401
		    }
402
		} else {
403
		    if ( ( ci & cinfo_incomplete ) && tchk ) {
404
			/* Report incomplete types */
405
			complete_class ( ct, 0 ) ;
406
			ci = DEREF_cinfo ( ctype_info ( ct ) ) ;
407
			if ( !( ci & cinfo_complete ) ) {
408
			    ERROR err = ERR_basic_types_completed ( t ) ;
409
			    if ( !IS_NULL_err ( err ) ) {
410
				LOCATION loc ;
411
				DEREF_loc ( id_loc ( id ), loc ) ;
412
				report ( loc, err ) ;
413
			    }
414
			}
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
		}
423
	    }
424
	    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
	}
446
 
447
	case id_variable_tag : {
448
	    /* Check variable usage */
449
	    if ( chk ) {
450
		DECL_SPEC ds = DEREF_dspec ( id_storage ( id ) ) ;
451
		if ( ( ds & dspec_static ) && preserve_all ) {
452
		    compile_preserve ( id ) ;
453
		}
454
		check_usage ( id, blk, anon ) ;
455
		if ( IS_NULL_exp ( blk ) ) {
456
		    if ( ds & dspec_defn ) {
457
			IGNORE define_tentative ( id, anon ) ;
458
		    }
459
		    compile_variable ( id, 0 ) ;
460
		} else {
461
		    /* End of local block */
462
		    if ( ds & dspec_auto ) {
463
			EXP term ;
464
			ds &= ~dspec_access ;
465
			COPY_dspec ( id_storage ( id ), ds ) ;
466
			term = DEREF_exp ( id_variable_etc_term ( id ) ) ;
467
			if ( !IS_NULL_exp ( term ) ) {
468
			    if ( do_usage ) dump_destr ( id, &stmt_loc ) ;
469
			}
470
		    }
471
		}
472
	    }
473
	    break ;
474
	}
475
 
476
	case id_parameter_tag : {
477
	    /* Check parameter usage */
478
	    if ( chk && suppress_variable == 0 ) {
479
		check_usage ( id, blk, anon ) ;
480
	    }
481
	    break ;
482
	}
483
 
484
	case id_stat_member_tag : {
485
	    /* Check static data member usage */
486
	    if ( anon == ANON_CLASS ) {
487
		LOCATION loc ;
488
		DEREF_loc ( id_loc ( id ), loc ) ;
489
		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
		}
500
	    }
501
	    break ;
502
	}
503
 
504
	case id_function_tag :
505
	case id_mem_func_tag :
506
	case id_stat_mem_func_tag : {
507
	    /* Check member function usage */
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 ) {
516
		    DECL_SPEC ds = DEREF_dspec ( id_storage ( id ) ) ;
517
		    if ( ( ds & dspec_static ) && preserve_all ) {
518
			compile_preserve ( id ) ;
519
		    }
520
		    if ( ds & dspec_inline ) {
521
			if ( !anon ) anon = ANON_INLINE ;
522
		    }
523
		    check_usage ( id, blk, anon ) ;
524
		    if ( IS_NULL_exp ( blk ) ) compile_function ( id, 0 ) ;
525
		}
526
	    } else {
527
		/* Template functions */
528
		check_template_id ( t, id, ns, blk, anon, chk ) ;
529
	    }
530
	    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 :
543
	case id_member_tag :
544
	case id_weak_param_tag : {
545
	    /* Don't check these (yet) */
546
	    break ;
547
	}
548
    }
549
    return ( n ) ;
550
}
551
 
552
 
553
/*
554
    CHECK A NAMESPACE
555
 
556
    This routine scans through all the members of the namespace ns, calling
557
    check_identifier for each member (including hidden members) and
558
    compiling any functions or non-local variables.  It returns the number
559
    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
561
    of ns is local to the current translation unit.
562
*/
563
 
564
unsigned long check_namespace
565
    PROTO_N ( ( ns, blk, anon, chk ) )
566
    PROTO_T ( NAMESPACE ns X EXP blk X int anon X int chk )
567
{
568
    unsigned long n = 0 ;
569
    if ( !IS_NULL_nspace ( ns ) ) {
570
	MEMBER mem ;
571
	LIST ( IDENTIFIER ) extra ;
572
 
573
	/* Find namespace components */
574
	switch ( TAG_nspace ( ns ) ) {
575
	    case nspace_named_tag :
576
	    case nspace_global_tag :
577
	    case nspace_ctype_tag : {
578
		mem = DEREF_member ( nspace_named_etc_first ( ns ) ) ;
579
		extra = DEREF_list ( nspace_named_etc_extra ( ns ) ) ;
580
		break ;
581
	    }
582
	    case nspace_unnamed_tag : {
583
		mem = DEREF_member ( nspace_unnamed_first ( ns ) ) ;
584
		extra = DEREF_list ( nspace_unnamed_extra ( ns ) ) ;
585
		if ( anon != ANON_GLOBAL && suppress_variable != 2 ) {
586
		    anon = ANON_NAMESPACE ;
587
		}
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
 
598
	/* Scan through namespace members */
599
	while ( !IS_NULL_member ( mem ) ) {
600
	    IDENTIFIER id = DEREF_id ( member_id ( mem ) ) ;
601
	    IDENTIFIER alt = DEREF_id ( member_alt ( mem ) ) ;
602
	    if ( !IS_NULL_id ( id ) ) {
603
		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 ) ;
607
	    }
608
	    mem = DEREF_member ( member_next ( mem ) ) ;
609
	}
610
 
611
	/* Scan through extra namespace members */
612
	while ( !IS_NULL_list ( extra ) ) {
613
	    IDENTIFIER id = DEREF_id ( HEAD_list ( extra ) ) ;
614
	    n += check_identifier ( id, ns, blk, anon, chk ) ;
615
	    extra = TAIL_list ( extra ) ;
616
	}
617
    }
618
    if ( spec_unit ) spec_unit = save_end ( spec_unit, ns ) ;
619
    return ( n ) ;
620
}
621
 
622
 
623
/*
624
    CHECK THE TOKEN NAMESPACE
625
 
626
    This routine applies the usage checks to the tokens declared in the
627
    translation unit.
628
*/
629
 
630
static void check_token
631
    PROTO_Z ()
632
{
633
    NAMESPACE ns = token_namespace ;
634
    MEMBER mem = DEREF_member ( nspace_global_first ( ns ) ) ;
635
    while ( !IS_NULL_member ( mem ) ) {
636
	IDENTIFIER id = DEREF_id ( member_id ( mem ) ) ;
637
	if ( !IS_NULL_id ( id ) ) {
638
	    DECL_SPEC ds = DEREF_dspec ( id_storage ( id ) ) ;
639
	    if ( !( ds & dspec_done ) ) {
640
		if ( ds & dspec_defn ) {
641
		    /* Defined token */
642
		    compile_token ( id, 1 ) ;
643
		} else if ( !( ds & dspec_pure ) ) {
644
		    /* Undefined token */
645
		    LOCATION loc ;
646
		    TOKEN tok = DEREF_tok ( id_token_sort ( id ) ) ;
647
		    bad_crt_loc++ ;
648
		    loc = crt_loc ;
649
		    DEREF_loc ( id_loc ( id ), crt_loc ) ;
650
		    if ( IS_tok_func ( tok ) ) {
651
			/* Implicitly define 'FUNC' tokens */
652
			IDENTIFIER fn = DEREF_id ( id_token_alt ( id ) ) ;
653
			COPY_id ( tok_func_defn ( tok ), fn ) ;
654
			ds |= dspec_defn ;
655
			COPY_dspec ( id_storage ( id ), ds ) ;
656
			if ( !( ds & dspec_explicit ) ) {
657
			    /* Not explicitly redeclared */
658
			    report ( crt_loc, ERR_token_def_implicit ( id ) ) ;
659
			}
660
			use_func_id ( fn, 0, 0 ) ;
661
			compile_function ( fn, 0 ) ;
662
			compile_token ( id, 1 ) ;
663
		    } else if ( ds & dspec_static ) {
664
			/* Check for built-in token definitions */
665
			if ( builtin_token ( id ) != -1 ) {
666
			    ds = DEREF_dspec ( id_storage ( id ) ) ;
667
			    if ( !( ds & dspec_defn ) ) {
668
				compile_token ( id, 0 ) ;
669
			    }
670
			} else if ( suppress_variable != 2 ) {
671
			    compile_token ( id, 0 ) ;
672
			}
673
		    }
674
		    crt_loc = loc ;
675
		    bad_crt_loc-- ;
676
		}
677
	    }
678
	}
679
	mem = DEREF_member ( member_next ( mem ) ) ;
680
    }
681
    return ;
682
}
683
 
684
 
685
/*
686
    CHECK THE GLOBAL NAMESPACE
687
 
688
    This routine applies check_namespace to the global namespace,
689
    including checking the main function if complete is true.  It also
690
    calls check_token.
691
*/
692
 
693
unsigned long check_global
694
    PROTO_N ( ( complete ) )
695
    PROTO_T ( int complete )
696
{
697
    /* Check main function if necessary */
698
    unsigned long n ;
699
    int anon = ANON_NONE ;
700
    NAMESPACE ns = global_namespace ;
701
    if ( complete && suppress_variable != 2 ) {
702
	IDENTIFIER id = main_function ;
703
	HASHID nm = KEYWORD ( lex_main ) ;
704
	if ( IS_NULL_id ( id ) ) {
705
	    /* Look up if not defined */
706
	    MEMBER mem = search_member ( ns, nm, 0 ) ;
707
	    if ( !IS_NULL_member ( mem ) ) {
708
		id = DEREF_id ( member_id ( mem ) ) ;
709
		if ( !IS_NULL_id ( id ) && IS_id_function ( id ) ) {
710
		    main_function = id ;
711
		} 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 */
722
	    DECL_SPEC ds = DEREF_dspec ( id_storage ( id ) ) ;
723
	    ds |= ( dspec_used | dspec_called ) ;
724
	    COPY_dspec ( id_storage ( id ), ds ) ;
725
	}
726
	anon = ANON_GLOBAL ;
727
    }
728
 
729
    /* Apply checks to namespaces */
730
    begin_spec () ;
731
    n = check_namespace ( ns, NULL_exp, anon, 1 ) ;
732
    end_spec () ;
733
    check_token () ;
734
    return ( n ) ;
735
}
736
 
737
 
738
/*
739
    CONSTRUCT A SET EXPRESSION
740
 
741
    This routine constructs the expression 'set ( a )'.
742
*/
743
 
744
EXP make_set_exp
745
    PROTO_N ( ( a ) )
746
    PROTO_T ( EXP a )
747
{
748
    EXP e ;
749
    a = convert_reference ( a, REF_NORMAL ) ;
750
    a = convert_lvalue ( a ) ;
751
    MAKE_exp_set ( type_void, a, e ) ;
752
    return ( e ) ;
753
}
754
 
755
 
756
/*
757
    CONSTRUCT AN UNUSED EXPRESSION
758
 
759
    This routine constructs the expression 'unused ( a )'.
760
*/
761
 
762
EXP make_unused_exp
763
    PROTO_N ( ( a ) )
764
    PROTO_T ( EXP a )
765
{
766
    EXP e ;
767
    a = convert_reference ( a, REF_NORMAL ) ;
768
    a = convert_lvalue ( a ) ;
769
    MAKE_exp_unused ( type_void, a, e ) ;
770
    return ( e ) ;
771
}
772
 
773
 
774
/*
775
    PRESERVE ALL STATIC IDENTIFIERS
776
 
777
    This flag is set to true to indicate that all static identifiers
778
    should be preserved.
779
*/
780
 
781
int preserve_all = 0 ;
782
 
783
 
784
/*
785
    PRESERVE AN IDENTIFIER
786
 
787
    This routine preserves or suspends the static identifier id, as
788
    indicated by the action act.
789
*/
790
 
791
void preserve_id
792
    PROTO_N ( ( id, act ) )
793
    PROTO_T ( IDENTIFIER id X int act )
794
{
795
    switch ( TAG_id ( id ) ) {
796
	case id_function_tag : {
797
	    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 ) {
806
		    compile_preserve ( id ) ;
807
		} else if ( act == lex_suspend ) {
808
		    ds |= dspec_used ;
809
		    COPY_dspec ( id_storage ( id ), ds ) ;
810
		}
811
	    }
812
	    break ;
813
	}
814
	default : {
815
	    ERROR err = ERR_pragma_preserve_undecl ( act, id ) ;
816
	    report ( preproc_loc, err ) ;
817
	    break ;
818
	}
819
    }
820
    return ;
821
}
822
 
823
 
824
/*
825
    FLOW ANALYSIS FLAGS
826
 
827
    These values are used to mark the various usage states in the flow
828
    analysis routines.  The fact that va_variable equals dspec_auto and
829
    va_done equals dspec_done is important, but the other values are
830
    merely convenient.
831
*/
832
 
833
typedef DECL_SPEC VAR_INFO ;
834
 
835
#define va_none			dspec_none
836
#define va_used_this		dspec_used
837
#define va_set			dspec_defn
838
#define va_maybe_set		dspec_inherit
839
 
840
#define va_filter		( va_used_this | va_set | va_maybe_set )
841
 
842
#define va_any_use		dspec_static
843
#define va_any_set		dspec_extern
844
 
845
#define va_done			dspec_done
846
#define va_variable		dspec_auto
847
#define va_ignore		dspec_ignore
848
#define va_error		dspec_implicit
849
 
850
#define va_address		dspec_register
851
#define va_assign		dspec_mutable
852
#define va_alias_used		dspec_inline
853
#define va_alias_set		dspec_virtual
854
#define va_partial		dspec_explicit
855
#define va_member		dspec_friend
856
#define va_this			dspec_typedef
857
#define va_dummy		dspec_pure
858
 
859
#define va_alias		( va_alias_used | va_alias_set )
860
#define va_becomes		( va_assign | va_dummy )
861
#define va_other		( va_address | va_becomes | va_partial )
862
#define va_mask			( va_alias | va_other )
863
 
864
#define va_unreached		dspec_main
865
 
866
 
867
/*
868
    FORWARD DECLARATIONS
869
 
870
    The following declarations are required for the flow analysis
871
    routines.
872
*/
873
 
874
static VAR_INFO flow_exp PROTO_S ( ( EXP, VAR_INFO ) ) ;
875
static VAR_INFO flow_alias_exp PROTO_S ( ( EXP, VAR_INFO ) ) ;
876
static VAR_INFO flow_stmt PROTO_S ( ( EXP, VAR_INFO, int ) ) ;
877
static VAR_INFO flow_offset PROTO_S ( ( OFFSET, VAR_INFO, int ) ) ;
878
static void set_variable PROTO_S ( ( IDENTIFIER, VAR_INFO ) ) ;
879
 
880
 
881
/*
882
    LIST OF CURRENTLY ACTIVE VARIABLES
883
 
884
    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
886
    routines.
887
*/
888
 
889
typedef LIST ( VARIABLE ) VAR_LIST ;
890
static VAR_LIST crt_flow_vars = NULL_list ( VARIABLE ) ;
891
static VAR_LIST crt_flow_mems = NULL_list ( VARIABLE ) ;
892
static LIST ( IDENTIFIER ) crt_flow_assign = NULL_list ( IDENTIFIER ) ;
893
 
894
 
895
/*
896
    START VARIABLE ANALYSIS
897
 
898
    This routine is called at the start of the analysis of the local
899
    variable id.
900
*/
901
 
902
static void start_variable
903
    PROTO_N ( ( id, ds, use ) )
904
    PROTO_T ( IDENTIFIER id X DECL_SPEC ds X VAR_INFO use )
905
{
906
    VARIABLE var ;
907
    use |= ( va_variable | va_done | va_used_this ) ;
908
    if ( !( ds & dspec_used ) ) use |= va_ignore ;
909
    var.id = id ;
910
    var.info = DEREF_dspec ( id_storage ( id ) ) ;
911
    COPY_dspec ( id_storage ( id ), use ) ;
912
    CONS_var ( var, crt_flow_vars, crt_flow_vars ) ;
913
    DEREF_loc ( id_loc ( id ), stmt_loc ) ;
914
    return ;
915
}
916
 
917
 
918
/*
919
    SHOULD VARIABLE ANALYSIS BE IGNORED?
920
 
921
    This routine checks whether any variable analysis errors involving
922
    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
924
    been replaced by its definition (see convert_lvalue).
925
*/
926
 
927
static int ignore_variable
928
    PROTO_N ( ( id ) )
929
    PROTO_T ( IDENTIFIER id )
930
{
931
    HASHID nm = DEREF_hashid ( id_name ( id ) ) ;
932
    if ( IS_hashid_anon ( nm ) ) return ( 1 ) ;
933
    if ( IS_id_variable ( id ) ) {
934
	TYPE t = DEREF_type ( id_variable_type ( id ) ) ;
935
	CV_SPEC cv = find_cv_qual ( t ) ;
936
	if ( cv & cv_volatile ) {
937
	    /* Ignore volatile variables */
938
	    return ( 1 ) ;
939
	}
940
	if ( cv == ( cv_const | cv_lvalue ) ) {
941
	    /* Check for const variables */
942
	    EXP e = DEREF_exp ( id_variable_init ( id ) ) ;
943
	    if ( !IS_NULL_exp ( e ) ) {
944
		if ( IS_exp_int_lit ( e ) ) return ( 1 ) ;
945
		if ( IS_exp_null ( e ) ) return ( 1 ) ;
946
	    }
947
	}
948
    } else if ( IS_id_member ( id ) ) {
949
	TYPE t = DEREF_type ( id_member_type ( id ) ) ;
950
	CV_SPEC cv = find_cv_qual ( t ) ;
951
	if ( cv & cv_volatile ) {
952
	    /* Ignore volatile members */
953
	    return ( 1 ) ;
954
	}
955
    }
956
    return ( 0 ) ;
957
}
958
 
959
 
960
/*
961
    END A VARIABLE SETTING
962
 
963
    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
965
    checks whether the variable has been assigned to and not used.
966
*/
967
 
968
static VAR_INFO end_usage
969
    PROTO_N ( ( id, ds, ret ) )
970
    PROTO_T ( IDENTIFIER id X VAR_INFO ds X int ret )
971
{
972
    if ( ret && ( ds & va_member ) ) {
973
	/* Class members are used after return */
974
	if ( ret == 2 ) {
975
	    set_variable ( id, va_member ) ;
976
	    ds = DEREF_dspec ( id_storage ( id ) ) ;
977
	} else {
978
	    ds |= va_used_this ;
979
	}
980
    } else if ( !( ds & va_used_this ) && ( ds & va_set ) ) {
981
	if ( !( ds & va_ignore ) && !ignore_variable ( id ) ) {
982
	    report ( stmt_loc, ERR_stmt_dcl_reset ( id ) ) ;
983
	    ds |= va_error ;
984
	}
985
	ds |= va_used_this ;
986
    }
987
    return ( ds ) ;
988
}
989
 
990
 
991
/*
992
    END VARIABLE ANALYSIS
993
 
994
    This routine is called at the end of the analysis of a local
995
    variable.  Note that unused variable have already been dealt with.
996
*/
997
 
998
static void end_variable
999
    PROTO_N ( ( flow, ret ) )
1000
    PROTO_T ( int flow X int ret )
1001
{
1002
    VARIABLE var ;
1003
    DESTROY_CONS_var ( destroy, var, crt_flow_vars, crt_flow_vars ) ;
1004
    if ( flow ) {
1005
	VAR_INFO use = DEREF_dspec ( id_storage ( var.id ) ) ;
1006
	use = end_usage ( var.id, use, ret ) ;
1007
	if ( !( use & ( va_member | va_ignore ) ) ) {
1008
	    if ( !( use & va_any_use ) ) {
1009
		/* Not used in reached code */
1010
		if ( !ignore_variable ( var.id ) ) {
1011
		    LOCATION loc ;
1012
		    DEREF_loc ( id_loc ( var.id ), loc ) ;
1013
		    report ( loc, ERR_stmt_dcl_unused ( var.id ) ) ;
1014
		}
1015
	    } else if ( !( use & va_any_set ) ) {
1016
		/* Not set in reached code */
1017
		if ( !( use & va_error ) && !ignore_variable ( var.id ) ) {
1018
		    LOCATION loc ;
1019
		    DEREF_loc ( id_loc ( var.id ), loc ) ;
1020
		    report ( loc, ERR_stmt_dcl_unset ( var.id ) ) ;
1021
		}
1022
	    }
1023
	}
1024
    }
1025
    COPY_dspec ( id_storage ( var.id ), var.info ) ;
1026
    return ;
1027
}
1028
 
1029
 
1030
/*
1031
    SET A VARIABLE
1032
 
1033
    This routine adjusts the variable analysis information for the local
1034
    variable use according to the analysis state use.
1035
*/
1036
 
1037
static void set_variable
1038
    PROTO_N ( ( id, use ) )
1039
    PROTO_T ( IDENTIFIER id X VAR_INFO use )
1040
{
1041
    if ( !( use & va_unreached ) ) {
1042
	VAR_INFO ds = DEREF_dspec ( id_storage ( id ) ) ;
1043
	if ( use & va_assign ) {
1044
	    /* Assignment */
1045
	    if ( use & va_dummy ) {
1046
		set_variable ( id, va_none ) ;
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 ;
1061
		    }
1062
		}
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
	}
1099
	COPY_dspec ( id_storage ( id ), ds ) ;
1100
    }
1101
    return ;
1102
}
1103
 
1104
 
1105
/*
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
1130
 
1131
    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,
1133
    from dq, from both, or from neither.
1134
*/
1135
 
1136
static VAR_INFO merge_usage
1137
    PROTO_N ( ( dp, dq, u ) )
1138
    PROTO_T ( VAR_INFO dp X VAR_INFO dq X int u )
1139
{
1140
    VAR_INFO ds = ( dp | dq ) ;
1141
    VAR_INFO dt = dspec_none ;
1142
    switch ( u ) {
1143
	case 0 : dt = ( dp & dq ) ; break ;
1144
	case 1 : dt = dp ; break ;
1145
	case 2 : dt = dq ; break ;
1146
    }
1147
    ds = ( ( ds & ~va_filter ) | ( dt & va_filter ) ) ;
1148
    return ( ds ) ;
1149
}
1150
 
1151
 
1152
/*
1153
    SEARCH A LIST OF VARIABLES
1154
 
1155
    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.
1157
    It returns a pointer to the variable if it exists and a null pointer
1158
    otherwise.
1159
*/
1160
 
1161
static PTR ( VARIABLE ) search_vars
1162
    PROTO_N ( ( p, q, id ) )
1163
    PROTO_T ( VAR_LIST p X VAR_LIST q X IDENTIFIER id )
1164
{
1165
    if ( !IS_NULL_list ( q ) ) {
1166
	PTR ( VARIABLE ) ptr = HEAD_list ( q ) ;
1167
	IDENTIFIER pid = DEREF_id ( var_id ( ptr ) ) ;
1168
	if ( EQ_id ( pid, id ) ) return ( ptr ) ;
1169
    }
1170
    while ( !IS_NULL_list ( p ) ) {
1171
	PTR ( VARIABLE ) ptr = HEAD_list ( p ) ;
1172
	IDENTIFIER pid = DEREF_id ( var_id ( ptr ) ) ;
1173
	if ( EQ_id ( pid, id ) ) return ( ptr ) ;
1174
	p = TAIL_list ( p ) ;
1175
    }
1176
    return ( NULL_ptr ( VARIABLE ) ) ;
1177
}
1178
 
1179
 
1180
/*
1181
    SAVE CURRENT VARIABLE SETTINGS
1182
 
1183
    This routine saves the current variable settings by merging them with
1184
    those stored in the list va.
1185
*/
1186
 
1187
static VAR_LIST save_vars
1188
    PROTO_N ( ( va, cond ) )
1189
    PROTO_T ( VAR_LIST va X int cond )
1190
{
1191
    VAR_LIST vb = crt_flow_vars ;
1192
    VAR_LIST vc = va ;
1193
    VAR_LIST vd = va ;
1194
    while ( !IS_NULL_list ( vb ) ) {
1195
	VARIABLE var ;
1196
	PTR ( VARIABLE ) pvar ;
1197
	var.id = DEREF_id ( var_id ( HEAD_list ( vb ) ) ) ;
1198
	var.info = DEREF_dspec ( id_storage ( var.id ) ) ;
1199
	if ( cond ) {
1200
	    var.info |= va_used_this ;
1201
	    COPY_dspec ( id_storage ( var.id ), var.info ) ;
1202
	}
1203
	pvar = search_vars ( vc, vd, var.id ) ;
1204
	if ( IS_NULL_ptr ( pvar ) ) {
1205
	    /* Add new identifier to list */
1206
	    CONS_var ( var, va, va ) ;
1207
	} else {
1208
	    /* Merge with existing information */
1209
	    VAR_INFO acc = DEREF_dspec ( var_info ( pvar ) ) ;
1210
	    acc = merge_usage ( acc, var.info, 0 ) ;
1211
	    COPY_dspec ( var_info ( pvar ), acc ) ;
1212
	}
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 ) ;
1218
}
1219
 
1220
 
1221
/*
1222
    LOAD CURRENT VARIABLE SETTINGS
1223
 
1224
    This routine loads the current variable settings by merging them with
1225
    those stored in the list va.
1226
*/
1227
 
1228
static void load_vars
1229
    PROTO_N ( ( va, u ) )
1230
    PROTO_T ( VAR_LIST va X int u )
1231
{
1232
    VAR_LIST vb = crt_flow_vars ;
1233
    VAR_LIST vc = va ;
1234
    while ( !IS_NULL_list ( vb ) ) {
1235
	IDENTIFIER id = DEREF_id ( var_id ( HEAD_list ( vb ) ) ) ;
1236
	VAR_INFO acc = DEREF_dspec ( id_storage ( id ) ) ;
1237
	PTR ( VARIABLE ) pvar = search_vars ( va, vc, id ) ;
1238
	if ( !IS_NULL_ptr ( pvar ) ) {
1239
	    VAR_INFO pacc = DEREF_dspec ( var_info ( pvar ) ) ;
1240
	    acc = merge_usage ( acc, pacc, u ) ;
1241
	}
1242
	COPY_dspec ( id_storage ( id ), acc ) ;
1243
	if ( !IS_NULL_list ( vc ) ) vc = TAIL_list ( vc ) ;
1244
	vb = TAIL_list ( vb ) ;
1245
    }
1246
    return ;
1247
}
1248
 
1249
 
1250
/*
1251
    SWAP CURRENT VARIABLE SETTINGS
1252
 
1253
    This routine swaps the current variable settings with those stored in
1254
    the list va.
1255
*/
1256
 
1257
static void swap_vars
1258
    PROTO_N ( ( va ) )
1259
    PROTO_T ( VAR_LIST va )
1260
{
1261
    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 ) ) ) ;
1286
	VAR_INFO acc = DEREF_dspec ( id_storage ( id ) ) ;
1287
	acc |= use ;
1288
	COPY_dspec ( id_storage ( id ), acc ) ;
1289
	va = TAIL_list ( va ) ;
1290
    }
1291
    return ;
1292
}
1293
 
1294
 
1295
/*
1296
    PERFORM FLOW ANALYSIS ON A GOTO STATEMENT
1297
 
1298
    This routine performs flow analysis on a jump to the label lab.  cond
1299
    is true to indicate a conditional jump.
1300
*/
1301
 
1302
static VAR_INFO flow_goto_stmt
1303
    PROTO_N ( ( lab, use, cond ) )
1304
    PROTO_T ( IDENTIFIER lab X VAR_INFO use X int cond )
1305
{
1306
    if ( !( use & va_unreached ) ) {
1307
	VAR_INFO ds = DEREF_dspec ( id_storage ( lab ) ) ;
1308
	if ( ds & dspec_reserve ) {
1309
	    /* Has backward jump */
1310
	    mark_vars ( crt_flow_vars, va_used_this ) ;
1311
	} else {
1312
	    /* Only forward jumps */
1313
	    VAR_LIST va = DEREF_list ( id_label_vars ( lab ) ) ;
1314
	    va = save_vars ( va, cond ) ;
1315
	    COPY_list ( id_label_vars ( lab ), va ) ;
1316
	}
1317
	ds |= dspec_temp ;
1318
	COPY_dspec ( id_storage ( lab ), ds ) ;
1319
	use |= va_unreached ;
1320
    }
1321
    return ( use ) ;
1322
}
1323
 
1324
 
1325
/*
1326
    PERFORM FLOW ANALYSIS ON A LABELLED STATEMENT
1327
 
1328
    This routine performs flow analysis on the statement labelled by the
1329
    label lab.
1330
*/
1331
 
1332
static VAR_INFO flow_label_stmt
1333
    PROTO_N ( ( lab, use, flow ) )
1334
    PROTO_T ( IDENTIFIER lab X VAR_INFO use X int flow )
1335
{
1336
    EXP e = DEREF_exp ( id_label_stmt ( lab ) ) ;
1337
    VAR_INFO ds = DEREF_dspec ( id_storage ( lab ) ) ;
1338
    if ( ds & dspec_reserve ) {
1339
	/* Has backward jump */
1340
	mark_vars ( crt_flow_vars, ( va_maybe_set | va_used_this ) ) ;
1341
	use &= ~va_unreached ;
1342
    } else {
1343
	/* Only forward jumps */
1344
	int unreached = 0 ;
1345
	VAR_LIST va = DEREF_list ( id_label_vars ( lab ) ) ;
1346
	if ( use & va_unreached ) unreached = 2 ;
1347
	load_vars ( va, unreached ) ;
1348
	DESTROY_list ( va, SIZE_var ) ;
1349
	COPY_list ( id_label_vars ( lab ), NULL_list ( VARIABLE ) ) ;
1350
	if ( ds & dspec_temp ) use &= ~va_unreached ;
1351
    }
1352
    if ( !IS_NULL_exp ( e ) ) {
1353
	e = DEREF_exp ( exp_label_stmt_body ( e ) ) ;
1354
	use = flow_stmt ( e, use, flow ) ;
1355
    }
1356
    return ( use ) ;
1357
}
1358
 
1359
 
1360
/*
1361
    CHECK A SEQUENCE POINT
1362
 
1363
    This routine is called at each sequence point in the flow analysis
1364
    routines.  It clears the list of identifiers assigned since the last
1365
    sequence point.
1366
*/
1367
 
1368
static void flow_sequence_point
1369
    PROTO_Z ()
1370
{
1371
    LIST ( IDENTIFIER ) p = crt_flow_assign ;
1372
    while ( !IS_NULL_list ( p ) ) {
1373
	VAR_INFO ds ;
1374
	IDENTIFIER id ;
1375
	DESTROY_CONS_id ( destroy, id, p, p ) ;
1376
	ds = DEREF_dspec ( id_storage ( id ) ) ;
1377
	ds &= ~va_assign ;
1378
	COPY_dspec ( id_storage ( id ), ds ) ;
1379
    }
1380
    crt_flow_assign = NULL_list ( IDENTIFIER ) ;
1381
    return ;
1382
}
1383
 
1384
 
1385
/*
1386
    PERFORM FLOW ANALYSIS ON AN UNREACHABLE STATEMENT
1387
 
1388
    This routine performs flow analysis following a return statement (in
1389
    which case ret is true) or other expression which causes execution to
1390
    cease.
1391
*/
1392
 
1393
static VAR_INFO flow_terminate
1394
    PROTO_N ( ( use, ret ) )
1395
    PROTO_T ( VAR_INFO use X int ret )
1396
{
1397
    if ( !( use & va_unreached ) ) {
1398
	VAR_LIST va = crt_flow_vars ;
1399
	while ( !IS_NULL_list ( va ) ) {
1400
	    IDENTIFIER id = DEREF_id ( var_id ( HEAD_list ( va ) ) ) ;
1401
	    VAR_INFO ds = DEREF_dspec ( id_storage ( id ) ) ;
1402
	    ds = end_usage ( id, ds, ret ) ;
1403
	    COPY_dspec ( id_storage ( id ), ds ) ;
1404
	    va = TAIL_list ( va ) ;
1405
	}
1406
    }
1407
    UNUSED ( ret ) ;
1408
    use |= va_unreached ;
1409
    return ( use ) ;
1410
}
1411
 
1412
 
1413
/*
1414
    PERFORM FLOW ANALYSIS ON AN IF EXPRESSION
1415
 
1416
    This routine preforms flow analysis on the if expression with condition
1417
    c and branches a and b.
1418
*/
1419
 
1420
static VAR_INFO flow_if_exp
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 )
1423
{
1424
    VAR_LIST va ;
1425
    VAR_INFO ua, ub ;
1426
    int unreached = 0 ;
1427
    unsigned cv = eval_const_cond ( c ) ;
1428
    if ( flow ) {
1429
	/* Condition */
1430
	use = flow_exp ( c, use ) ;
1431
	flow_sequence_point () ;
1432
    }
1433
    ua = use ;
1434
    ub = use ;
1435
    if ( cv == BOOL_FALSE ) ua |= va_unreached ;
1436
    if ( cv == BOOL_TRUE ) ub |= va_unreached ;
1437
    va = save_vars ( NULL_list ( VARIABLE ), 1 ) ;
1438
    ua = flow_stmt ( a, ua, flow ) ;
1439
    swap_vars ( va ) ;
1440
    ub = flow_stmt ( b, ub, flow ) ;
1441
    if ( ua & va_unreached ) unreached |= 1 ;
1442
    if ( ub & va_unreached ) unreached |= 2 ;
1443
    load_vars ( va, unreached ) ;
1444
    DESTROY_list ( va, SIZE_var ) ;
1445
    use = ( ua & ub ) ;
1446
    return ( use ) ;
1447
}
1448
 
1449
 
1450
/*
1451
    PROCESS A FLOW ANALYSIS DIRECTIVE
1452
 
1453
    This routine processes the flow analysis directive indicated by act
1454
    to the expression e.
1455
*/
1456
 
1457
static VAR_INFO flow_set
1458
    PROTO_N ( ( e, use, act ) )
1459
    PROTO_T ( EXP e X VAR_INFO use X VAR_INFO act )
1460
{
1461
    if ( !( use & va_unreached ) && !IS_NULL_exp ( e ) ) {
1462
	EXP a = NULL_exp ;
1463
	if ( IS_exp_contents ( e ) ) {
1464
	    /* Check for simple lvalues */
1465
	    a = DEREF_exp ( exp_contents_ptr ( e ) ) ;
1466
	} else if ( IS_exp_address ( e ) ) {
1467
	    /* Check for array to pointer conversions */
1468
	    EXP b = DEREF_exp ( exp_address_arg ( e ) ) ;
1469
	    TYPE s = DEREF_type ( exp_type ( b ) ) ;
1470
	    if ( IS_type_array ( s ) ) a = b ;
1471
	}
1472
	if ( !IS_NULL_exp ( a ) && IS_exp_identifier ( a ) ) {
1473
	    IDENTIFIER id = DEREF_id ( exp_identifier_id ( a ) ) ;
1474
	    if ( IS_id_variable_etc ( id ) ) {
1475
		DECL_SPEC ds = DEREF_dspec ( id_storage ( id ) ) ;
1476
		if ( ds & dspec_auto ) {
1477
		    if ( act & va_set ) {
1478
			/* Set variable */
1479
			ds |= ( va_set | va_maybe_set | va_any_set ) ;
1480
			ds &= ~va_used_this ;
1481
		    } else {
1482
			/* Unused variable */
1483
			set_variable ( id, act ) ;
1484
			ds = DEREF_dspec ( id_storage ( id ) ) ;
1485
			ds &= ~( va_set | va_maybe_set ) ;
1486
		    }
1487
		    COPY_dspec ( id_storage ( id ), ds ) ;
1488
		}
1489
	    }
1490
	}
1491
    }
1492
    return ( use ) ;
1493
}
1494
 
1495
 
1496
/*
1497
    PERFORM FLOW ANALYSIS ON A LIST OF TOKEN ARGUMENTS
1498
 
1499
    This routine performs flow analysis on the list of token arguments p.
1500
*/
1501
 
1502
static VAR_INFO flow_token_list
1503
    PROTO_N ( ( p, use ) )
1504
    PROTO_T ( LIST ( TOKEN ) p X VAR_INFO use )
1505
{
1506
    while ( !IS_NULL_list ( p ) ) {
1507
	TOKEN tok = DEREF_tok ( HEAD_list ( p ) ) ;
1508
	if ( !IS_NULL_tok ( tok ) ) {
1509
	    switch ( TAG_tok ( tok ) ) {
1510
		case tok_exp_tag : {
1511
		    /* Expression tokens */
1512
		    EXP e = DEREF_exp ( tok_exp_value ( tok ) ) ;
1513
		    use = flow_alias_exp ( e, use ) ;
1514
		    break ;
1515
		}
1516
		case tok_stmt_tag : {
1517
		    /* Statement tokens */
1518
		    EXP e = DEREF_exp ( tok_stmt_value ( tok ) ) ;
1519
		    use = flow_stmt ( e, use, 1 ) ;
1520
		    break ;
1521
		}
1522
		case tok_member_tag : {
1523
		    /* Member tokens */
1524
		    OFFSET off = DEREF_off ( tok_member_value ( tok ) ) ;
1525
		    use = flow_offset ( off, use, 0 ) ;
1526
		    break ;
1527
		}
1528
	    }
1529
	}
1530
	p = TAIL_list ( p ) ;
1531
    }
1532
    return ( use ) ;
1533
}
1534
 
1535
 
1536
/*
1537
    PERFORM FLOW ANALYSIS ON AN OFFSET
1538
 
1539
    This routine performs flow analysis on the offset off.  mem is true
1540
    in member functions when the offset is being added to 'this'.
1541
*/
1542
 
1543
static VAR_INFO flow_offset
1544
    PROTO_N ( ( off, use, mem ) )
1545
    PROTO_T ( OFFSET off X VAR_INFO use X int mem )
1546
{
1547
    DECL_SPEC ua = ( use & ~va_mask ) ;
1548
    if ( IS_NULL_off ( off ) ) return ( ua ) ;
1549
    ASSERT ( ORDER_off == 13 ) ;
1550
    switch ( TAG_off ( off ) ) {
1551
 
1552
	case off_member_tag : {
1553
	    /* Member offsets */
1554
	    if ( mem ) {
1555
		IDENTIFIER id = DEREF_id ( off_member_id ( off ) ) ;
1556
		VAR_INFO ds = DEREF_dspec ( id_storage ( id ) ) ;
1557
		if ( ds & va_variable ) set_variable ( id, use ) ;
1558
	    }
1559
	    break ;
1560
	}
1561
 
1562
	case off_ptr_mem_tag : {
1563
	    /* Pointer to member offsets */
1564
	    EXP a = DEREF_exp ( off_ptr_mem_arg ( off ) ) ;
1565
	    ua = flow_exp ( a, ua ) ;
1566
	    break ;
1567
	}
1568
 
1569
	case off_negate_tag : {
1570
	    /* Negated offsets */
1571
	    OFFSET off1 = DEREF_off ( off_negate_arg ( off ) ) ;
1572
	    ua = flow_offset ( off1, ua, 0 ) ;
1573
	    break ;
1574
	}
1575
 
1576
	case off_plus_tag : {
1577
	    /* Offset addition */
1578
	    OFFSET off1 = DEREF_off ( off_plus_arg1 ( off ) ) ;
1579
	    OFFSET off2 = DEREF_off ( off_plus_arg2 ( off ) ) ;
1580
	    ua = flow_offset ( off1, ua, 0 ) ;
1581
	    ua = flow_offset ( off2, ua, 0 ) ;
1582
	    break ;
1583
	}
1584
 
1585
	case off_mult_tag : {
1586
	    /* Offset multiplication */
1587
	    OFFSET off1 = DEREF_off ( off_mult_arg1 ( off ) ) ;
1588
	    EXP a = DEREF_exp ( off_mult_arg2 ( off ) ) ;
1589
	    ua = flow_offset ( off1, ua, 0 ) ;
1590
	    ua = flow_exp ( a, ua ) ;
1591
	    break ;
1592
	}
1593
 
1594
	case off_ptr_diff_tag : {
1595
	    /* Difference of two pointers */
1596
	    EXP a = DEREF_exp ( off_ptr_diff_ptr1 ( off ) ) ;
1597
	    EXP b = DEREF_exp ( off_ptr_diff_ptr2 ( off ) ) ;
1598
	    ua = flow_exp ( a, ua ) ;
1599
	    ua = flow_exp ( b, ua ) ;
1600
	    break ;
1601
	}
1602
 
1603
	case off_token_tag : {
1604
	    /* Tokenised offsets */
1605
	    LIST ( TOKEN ) args = DEREF_list ( off_token_args ( off ) ) ;
1606
	    ua = flow_token_list ( args, ua ) ;
1607
	    break ;
1608
	}
1609
    }
1610
    ua &= ~va_mask ;
1611
    return ( ua ) ;
1612
}
1613
 
1614
 
1615
/*
1616
    PERFORM FLOW ANALYSIS ON A LIST OF EXPRESSIONS
1617
 
1618
    This routine performs flow analysis on the list of expressions p.
1619
*/
1620
 
1621
static VAR_INFO flow_exp_list
1622
    PROTO_N ( ( p, use, fn ) )
1623
    PROTO_T ( LIST ( EXP ) p X VAR_INFO use X int fn )
1624
{
1625
    while ( !IS_NULL_list ( p ) ) {
1626
	EXP a = DEREF_exp ( HEAD_list ( p ) ) ;
1627
	if ( !IS_NULL_exp ( a ) ) {
1628
	    VAR_INFO ua ;
1629
	    if ( fn ) {
1630
		ua = flow_alias_exp ( a, use ) ;
1631
	    } else {
1632
		ua = flow_exp ( a, use ) ;
1633
	    }
1634
	    if ( ua & va_unreached ) use |= va_unreached ;
1635
	}
1636
	p = TAIL_list ( p ) ;
1637
    }
1638
    return ( use ) ;
1639
}
1640
 
1641
 
1642
/*
1643
    PERFORM FLOW ANALYSIS ON AN ALIASED EXPRESSION
1644
 
1645
    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
1647
    there are read-only and read-write aliases, depending on whether the
1648
    access is through a pointer or reference to const or not.
1649
*/
1650
 
1651
static VAR_INFO flow_alias_exp
1652
    PROTO_N ( ( e, use ) )
1653
    PROTO_T ( EXP e X VAR_INFO use )
1654
{
1655
    VAR_INFO ua = ( use | va_alias_used ) ;
1656
    if ( !IS_NULL_exp ( e ) ) {
1657
	TYPE t = DEREF_type ( exp_type ( e ) ) ;
1658
	CV_SPEC cv = find_cv_qual ( t ) ;
1659
	if ( cv & cv_lvalue ) {
1660
	    /* Aliased via lvalue */
1661
	    if ( !( cv & cv_const ) ) ua |= va_alias_set ;
1662
	}
1663
	if ( IS_type_ptr_etc ( t ) ) {
1664
	    /* Aliased via pointer or reference */
1665
	    TYPE s = DEREF_type ( type_ptr_etc_sub ( t ) ) ;
1666
	    cv = find_cv_qual ( s ) ;
1667
	    if ( !( cv & cv_const ) ) ua |= va_alias_set ;
1668
	}
1669
    }
1670
    ua = flow_exp ( e, ua ) ;
1671
    return ( ua ) ;
1672
}
1673
 
1674
 
1675
/*
1676
    PERFORM FLOW ANALYSIS ON AN EXPRESSION
1677
 
1678
    This routine performs flow analysis on the expression e.
1679
*/
1680
 
1681
static VAR_INFO flow_exp
1682
    PROTO_N ( ( e, use ) )
1683
    PROTO_T ( EXP e X VAR_INFO use )
1684
{
1685
    VAR_INFO ua = ( use & ~va_mask ) ;
1686
    if ( IS_NULL_exp ( e ) ) return ( ua ) ;
1687
    ASSERT ( ORDER_exp == 88 ) ;
1688
    switch ( TAG_exp ( e ) ) {
1689
 
1690
	case exp_identifier_tag : {
1691
	    /* Identifier expressions */
1692
	    IDENTIFIER id = DEREF_id ( exp_identifier_id ( e ) ) ;
1693
	    if ( IS_id_variable_etc ( id ) ) {
1694
		DECL_SPEC ds = DEREF_dspec ( id_storage ( id ) ) ;
1695
		if ( ds & dspec_auto ) {
1696
		    set_variable ( id, use ) ;
1697
		    if ( ( ds & va_this ) && ( use & va_alias ) ) {
1698
			/* Allow for aliasing using 'this' */
1699
			set_members ( use ) ;
1700
		    }
1701
		}
1702
	    }
1703
	    break ;
1704
	}
1705
 
1706
	case exp_assign_tag : {
1707
	    /* Assignment expressions */
1708
	    EXP a = DEREF_exp ( exp_assign_ref ( e ) ) ;
1709
	    EXP b = DEREF_exp ( exp_assign_arg ( e ) ) ;
1710
	    ua = flow_alias_exp ( b, ua ) ;
1711
	    if ( ua & va_unreached ) use |= va_unreached ;
1712
	    ua = flow_exp ( a, ( use | va_assign ) ) ;
1713
	    break ;
1714
	}
1715
 
1716
	case exp_init_tag : {
1717
	    /* Initialisation expressions */
1718
	    EXP a = DEREF_exp ( exp_init_arg ( e ) ) ;
1719
	    ua = flow_alias_exp ( a, ua ) ;
1720
	    if ( ua & va_unreached ) use |= va_unreached ;
1721
	    if ( !IS_NULL_exp ( a ) ) {
1722
		IDENTIFIER id = DEREF_id ( exp_init_id ( e ) ) ;
1723
		if ( IS_id_variable ( id ) ) {
1724
		    DECL_SPEC ds = DEREF_dspec ( id_storage ( id ) ) ;
1725
		    if ( ds & dspec_auto ) {
1726
			/* Initialiser expression */
1727
			set_variable ( id, ( use | va_assign ) ) ;
1728
			break ;
1729
		    }
1730
		}
1731
	    }
1732
	    break ;
1733
	}
1734
 
1735
	case exp_preinc_tag : {
1736
	    /* Pre-increment expressions */
1737
	    EXP a = DEREF_exp ( exp_preinc_ref ( e ) ) ;
1738
	    EXP b = DEREF_exp ( exp_preinc_op ( e ) ) ;
1739
	    EXP c = DEREF_exp ( exp_dummy_value ( a ) ) ;
1740
	    int op = DEREF_int ( exp_preinc_becomes ( e ) ) ;
1741
	    if ( op == lex_assign ) {
1742
		/* Bitfield assignment */
1743
		ua = flow_alias_exp ( b, ua ) ;
1744
		if ( ua & va_unreached ) use |= va_unreached ;
1745
		if ( !IS_NULL_list ( crt_flow_mems ) && is_this_exp ( c ) ) {
1746
		    /* Have 'this->off' */
1747
		    OFFSET off = DEREF_off ( exp_dummy_off ( a ) ) ;
1748
		    ua = flow_offset ( off, ( use | va_assign ), 1 ) ;
1749
		    break ;
1750
		}
1751
		use |= va_partial ;
1752
	    } else {
1753
		COPY_exp ( exp_dummy_value ( a ), NULL_exp ) ;
1754
		ua = flow_exp ( b, ua ) ;
1755
		COPY_exp ( exp_dummy_value ( a ), c ) ;
1756
		if ( ua & va_unreached ) use |= va_unreached ;
1757
		use |= va_becomes ;
1758
	    }
1759
	    ua = flow_exp ( c, ( use | va_assign ) ) ;
1760
	    break ;
1761
	}
1762
 
1763
	case exp_postinc_tag : {
1764
	    /* Post-increment expressions */
1765
	    EXP a = DEREF_exp ( exp_postinc_ref ( e ) ) ;
1766
	    EXP b = DEREF_exp ( exp_postinc_op ( e ) ) ;
1767
	    EXP c = DEREF_exp ( exp_dummy_value ( a ) ) ;
1768
	    COPY_exp ( exp_dummy_value ( a ), NULL_exp ) ;
1769
	    ua = flow_exp ( b, ua ) ;
1770
	    COPY_exp ( exp_dummy_value ( a ), c ) ;
1771
	    if ( ua & va_unreached ) use |= va_unreached ;
1772
	    ua = flow_exp ( a, ( use | va_becomes ) ) ;
1773
	    break ;
1774
	}
1775
 
1776
	case exp_indir_tag : {
1777
	    /* Indirection 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 ) ) ;
1803
		ua = flow_exp ( b, use ) ;
1804
		break ;
1805
	    }
1806
	    ua = flow_exp ( a, ua ) ;
1807
	    break ;
1808
	}
1809
 
1810
	case exp_contents_tag : {
1811
	    /* Contents expressions */
1812
	    EXP a = DEREF_exp ( exp_contents_ptr ( e ) ) ;
1813
	    ua = flow_exp ( a, ua ) ;
1814
	    break ;
1815
	}
1816
 
1817
	case exp_address_tag : {
1818
	    /* Address expressions */
1819
	    EXP a = DEREF_exp ( exp_address_arg ( e ) ) ;
1820
	    if ( IS_exp_indir ( a ) && !is_this_exp ( a ) ) {
1821
		EXP b = DEREF_exp ( exp_indir_ptr ( a ) ) ;
1822
		TYPE t = DEREF_type ( exp_type ( b ) ) ;
1823
		if ( !IS_type_ref ( t ) ) {
1824
		    ua = flow_exp ( b, use ) ;
1825
		    break ;
1826
		}
1827
	    }
1828
	    ua = ( use & ~va_other ) ;
1829
	    ua = flow_exp ( a, ( ua | va_address ) ) ;
1830
	    break ;
1831
	}
1832
 
1833
	case exp_address_mem_tag : {
1834
	    /* Member address expressions */
1835
	    EXP a = DEREF_exp ( exp_address_mem_arg ( e ) ) ;
1836
	    ua = flow_exp ( a, ua ) ;
1837
	    break ;
1838
	}
1839
 
1840
	case exp_func_tag : {
1841
	    /* Function expressions */
1842
	    TYPE t = DEREF_type ( exp_type ( e ) ) ;
1843
	    EXP a = DEREF_exp ( exp_func_fn ( e ) ) ;
1844
	    LIST ( EXP ) args = DEREF_list ( exp_func_args ( e ) ) ;
1845
	    ua = flow_exp ( a, ua ) ;
1846
	    ua = flow_exp_list ( args, ua, 1 ) ;
1847
	    if ( IS_type_bottom ( t ) ) {
1848
		/* Deal with functions like exit */
1849
		ua = flow_terminate ( ua, 1 ) ;
1850
	    }
1851
	    break ;
1852
	}
1853
 
1854
	case exp_func_id_tag : {
1855
	    /* Function expressions */
1856
	    TYPE t = DEREF_type ( exp_type ( e ) ) ;
1857
	    LIST ( EXP ) args = DEREF_list ( exp_func_id_args ( e ) ) ;
1858
	    ua = flow_exp_list ( args, ua, 1 ) ;
1859
	    if ( IS_type_bottom ( t ) ) {
1860
		/* Deal with functions like exit */
1861
		ua = flow_terminate ( ua, 1 ) ;
1862
	    }
1863
	    break ;
1864
	}
1865
 
1866
	case exp_call_tag : {
1867
	    /* Pointer to member function expressions */
1868
	    EXP a = DEREF_exp ( exp_call_ptr ( e ) ) ;
1869
	    EXP b = DEREF_exp ( exp_call_arg ( e ) ) ;
1870
	    ua = flow_exp ( a, ua ) ;
1871
	    ua = flow_exp ( b, ua ) ;
1872
	    break ;
1873
	}
1874
 
1875
	case exp_negate_tag :
1876
	case exp_compl_tag :
1877
	case exp_not_tag :
1878
	case exp_abs_tag : {
1879
	    /* Unary expressions */
1880
	    EXP a = DEREF_exp ( exp_negate_etc_arg ( e ) ) ;
1881
	    ua = flow_exp ( a, ua ) ;
1882
	    break ;
1883
	}
1884
 
1885
	case exp_plus_tag :
1886
	case exp_minus_tag :
1887
	case exp_mult_tag :
1888
	case exp_div_tag :
1889
	case exp_rem_tag :
1890
	case exp_and_tag :
1891
	case exp_or_tag :
1892
	case exp_xor_tag :
1893
	case exp_lshift_tag :
1894
	case exp_rshift_tag :
1895
	case exp_max_tag :
1896
	case exp_min_tag : {
1897
	    /* Binary expressions */
1898
	    EXP a = DEREF_exp ( exp_plus_etc_arg1 ( e ) ) ;
1899
	    EXP b = DEREF_exp ( exp_plus_etc_arg2 ( e ) ) ;
1900
	    ua = flow_exp ( a, ua ) ;
1901
	    ua = flow_exp ( b, ua ) ;
1902
	    break ;
1903
	}
1904
 
1905
	case exp_log_and_tag :
1906
	case exp_log_or_tag : {
1907
	    /* Logical expressions */
1908
	    EXP a = DEREF_exp ( exp_plus_etc_arg1 ( e ) ) ;
1909
	    EXP b = DEREF_exp ( exp_plus_etc_arg2 ( e ) ) ;
1910
	    ua = flow_exp ( a, ua ) ;
1911
	    flow_sequence_point () ;
1912
	    ua = flow_exp ( b, ua ) ;
1913
	    break ;
1914
	}
1915
 
1916
	case exp_test_tag : {
1917
	    /* Test expressions */
1918
	    EXP a = DEREF_exp ( exp_test_arg ( e ) ) ;
1919
	    ua = flow_exp ( a, ua ) ;
1920
	    break ;
1921
	}
1922
 
1923
	case exp_compare_tag : {
1924
	    /* Comparison expressions */
1925
	    EXP a = DEREF_exp ( exp_compare_arg1 ( e ) ) ;
1926
	    EXP b = DEREF_exp ( exp_compare_arg2 ( e ) ) ;
1927
	    ua = flow_exp ( a, ua ) ;
1928
	    ua = flow_exp ( b, ua ) ;
1929
	    break ;
1930
	}
1931
 
1932
	case exp_cast_tag : {
1933
	    /* Cast expressions */
1934
	    TYPE t = DEREF_type ( exp_type ( e ) ) ;
1935
	    EXP a = DEREF_exp ( exp_cast_arg ( e ) ) ;
1936
	    ua = ( use & ~va_other ) ;
1937
	    ua = flow_exp ( a, ua ) ;
1938
	    if ( IS_type_bottom ( t ) ) {
1939
		/* Allow for casting to bottom */
1940
		ua = flow_terminate ( ua, 1 ) ;
1941
	    }
1942
	    break ;
1943
	}
1944
 
1945
	case exp_base_cast_tag : {
1946
	    /* Base cast expressions */
1947
	    EXP a = DEREF_exp ( exp_base_cast_arg ( e ) ) ;
1948
	    ua = ( use & ~va_other ) ;
1949
	    ua = flow_exp ( a, ua ) ;
1950
	    break ;
1951
	}
1952
 
1953
	case exp_dyn_cast_tag : {
1954
	    /* Dynamic cast expressions */
1955
	    EXP a = DEREF_exp ( exp_dyn_cast_arg ( e ) ) ;
1956
	    ua = ( use & ~va_other ) ;
1957
	    ua = flow_exp ( a, ua ) ;
1958
	    break ;
1959
	}
1960
 
1961
	case exp_add_ptr_tag : {
1962
	    /* Pointer addition expressions */
1963
	    EXP a = DEREF_exp ( exp_add_ptr_ptr ( e ) ) ;
1964
	    OFFSET off = DEREF_off ( exp_add_ptr_off ( e ) ) ;
1965
	    if ( !IS_NULL_list ( crt_flow_mems ) && is_this_exp ( a ) ) {
1966
		/* Have 'this->off' */
1967
		use &= ~va_other ;
1968
		ua = flow_offset ( off, use, 1 ) ;
1969
		break ;
1970
	    }
1971
	    ua = flow_offset ( off, ua, 0 ) ;
1972
	    if ( ua & va_unreached ) use |= va_unreached ;
1973
	    use &= ~va_other ;
1974
	    ua = flow_exp ( a, use ) ;
1975
	    break ;
1976
	}
1977
 
1978
	case exp_offset_size_tag : {
1979
	    /* Offset expressions */
1980
	    OFFSET off = DEREF_off ( exp_offset_size_off ( e ) ) ;
1981
	    ua = flow_offset ( off, ua, 0 ) ;
1982
	    break ;
1983
	}
1984
 
1985
	case exp_constr_tag : {
1986
	    /* Constructor calls */
1987
	    EXP a = DEREF_exp ( exp_constr_call ( e ) ) ;
1988
	    ua = flow_exp ( a, ua ) ;
1989
	    break ;
1990
	}
1991
 
1992
	case exp_destr_tag : {
1993
	    /* Destructor calls */
1994
	    EXP a = DEREF_exp ( exp_destr_call ( e ) ) ;
1995
	    ua = flow_exp ( a, ua ) ;
1996
	    break ;
1997
	}
1998
 
1999
	case exp_alloc_tag : {
2000
	    /* Allocation expressions */
2001
	    EXP a = DEREF_exp ( exp_alloc_call ( e ) ) ;
2002
	    EXP b = DEREF_exp ( exp_alloc_init ( e ) ) ;
2003
	    ua = flow_exp ( a, ua ) ;
2004
	    ua = flow_exp ( b, ua ) ;
2005
	    break ;
2006
	}
2007
 
2008
	case exp_dealloc_tag : {
2009
	    /* Deallocation expressions */
2010
	    EXP a = DEREF_exp ( exp_dealloc_term ( e ) ) ;
2011
	    EXP b = DEREF_exp ( exp_dealloc_call ( e ) ) ;
2012
	    EXP c = DEREF_exp ( exp_dealloc_arg ( e ) ) ;
2013
	    EXP d = DEREF_exp ( exp_dummy_value ( c ) ) ;
2014
	    ua = flow_exp ( a, ua ) ;
2015
	    ua = flow_exp ( b, ua ) ;
2016
	    ua = flow_set ( d, ua, va_none ) ;
2017
	    break ;
2018
	}
2019
 
2020
	case exp_rtti_tag : {
2021
	    /* Run-time type information expressions */
2022
	    EXP a = DEREF_exp ( exp_rtti_arg ( e ) ) ;
2023
	    ua = flow_exp ( a, ua ) ;
2024
	    break ;
2025
	}
2026
 
2027
	case exp_dynamic_tag : {
2028
	    /* Dynamic initialiser expressions */
2029
	    EXP a = DEREF_exp ( exp_dynamic_arg ( e ) ) ;
2030
	    ua = flow_exp ( a, ua ) ;
2031
	    break ;
2032
	}
2033
 
2034
	case exp_aggregate_tag : {
2035
	    /* Aggregate initialiser expressions */
2036
	    LIST ( EXP ) args ;
2037
	    args = DEREF_list ( exp_aggregate_args ( e ) ) ;
2038
	    ua = flow_exp_list ( args, ua, 0 ) ;
2039
	    break ;
2040
	}
2041
 
2042
	case exp_initialiser_tag : {
2043
	    /* Constructor initialiser expressions */
2044
	    int kind = DEREF_int ( exp_initialiser_kind ( e ) ) ;
2045
	    LIST ( EXP ) p = DEREF_list ( exp_initialiser_args ( e ) ) ;
2046
	    LIST ( OFFSET ) q = DEREF_list ( exp_initialiser_offs ( e ) ) ;
2047
	    if ( kind == 0 ) q = NULL_list ( OFFSET ) ;
2048
	    while ( !IS_NULL_list ( p ) ) {
2049
		EXP a = DEREF_exp ( HEAD_list ( p ) ) ;
2050
		ua = flow_exp ( a, ua ) ;
2051
		if ( !IS_NULL_list ( q ) ) {
2052
		    OFFSET off = DEREF_off ( HEAD_list ( q ) ) ;
2053
		    if ( kind != DEFAULT_DESTR && !IS_NULL_exp ( a ) ) {
2054
			ua |= va_assign ;
2055
		    }
2056
		    ua = flow_offset ( off, ua, 1 ) ;
2057
		    flow_sequence_point () ;
2058
		    q = TAIL_list ( q ) ;
2059
		}
2060
		p = TAIL_list ( p ) ;
2061
	    }
2062
	    break ;
2063
	}
2064
 
2065
	case exp_nof_tag : {
2066
	    /* Array initialiser expressions */
2067
	    EXP a = DEREF_exp ( exp_nof_start ( e ) ) ;
2068
	    EXP b = DEREF_exp ( exp_nof_pad ( e ) ) ;
2069
	    EXP c = DEREF_exp ( exp_nof_end ( e ) ) ;
2070
	    ua = flow_exp ( a, ua ) ;
2071
	    ua = flow_exp ( b, ua ) ;
2072
	    ua = flow_exp ( c, ua ) ;
2073
	    break ;
2074
	}
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 : {
2095
	    /* Conditional expressions */
2096
	    EXP c = DEREF_exp ( exp_if_stmt_cond ( e ) ) ;
2097
	    EXP a = DEREF_exp ( exp_if_stmt_true_code ( e ) ) ;
2098
	    EXP b = DEREF_exp ( exp_if_stmt_false_code ( e ) ) ;
2099
	    ua = flow_if_exp ( c, a, b, ua, 1 ) ;
2100
	    break ;
2101
	}
2102
 
2103
	case exp_exception_tag : {
2104
	    /* Exception expressions */
2105
	    EXP a = DEREF_exp ( exp_exception_arg ( e ) ) ;
2106
	    ua = flow_exp ( a, ua ) ;
2107
	    ua = flow_terminate ( ua, 1 ) ;
2108
	    break ;
2109
	}
2110
 
2111
	case exp_set_tag : {
2112
	    /* Set expressions */
2113
	    EXP a = DEREF_exp ( exp_set_arg ( e ) ) ;
2114
	    ua = flow_set ( a, ua, va_set ) ;
2115
	    break ;
2116
	}
2117
 
2118
	case exp_unused_tag : {
2119
	    /* Unused expressions */
2120
	    EXP a = DEREF_exp ( exp_unused_arg ( e ) ) ;
2121
	    ua = flow_set ( a, ua, va_none ) ;
2122
	    break ;
2123
	}
2124
 
2125
	case exp_op_tag : {
2126
	    /* Undetermined expressions */
2127
	    EXP a = DEREF_exp ( exp_op_arg1 ( e ) ) ;
2128
	    EXP b = DEREF_exp ( exp_op_arg2 ( e ) ) ;
2129
	    ua = flow_exp ( a, ua ) ;
2130
	    ua = flow_exp ( b, ua ) ;
2131
	    break ;
2132
	}
2133
 
2134
	case exp_opn_tag : {
2135
	    /* Undetermined expressions */
2136
	    LIST ( EXP ) args = DEREF_list ( exp_opn_args ( e ) ) ;
2137
	    ua = flow_exp_list ( args, ua, 0 ) ;
2138
	    break ;
2139
	}
2140
 
2141
	case exp_token_tag : {
2142
	    /* Tokenised expressions */
2143
	    LIST ( TOKEN ) args = DEREF_list ( exp_token_args ( e ) ) ;
2144
	    ua = flow_token_list ( args, ua ) ;
2145
	    break ;
2146
	}
2147
 
2148
	case exp_dummy_tag : {
2149
	    /* Dummy expressions */
2150
	    EXP a = DEREF_exp ( exp_dummy_value ( e ) ) ;
2151
	    ua = flow_exp ( a, use ) ;
2152
	    break ;
2153
	}
2154
 
2155
	case exp_paren_tag :
2156
	case exp_copy_tag : {
2157
	    /* Parenthesised expressions */
2158
	    EXP a = DEREF_exp ( exp_paren_etc_arg ( e ) ) ;
2159
	    ua = flow_exp ( a, use ) ;
2160
	    break ;
2161
	}
2162
 
2163
	case exp_location_tag : {
2164
	    /* Location expressions */
2165
	    EXP a = DEREF_exp ( exp_location_arg ( e ) ) ;
2166
	    ua = flow_exp ( a, use ) ;
2167
	    DEREF_loc ( exp_location_end ( e ), stmt_loc ) ;
2168
	    break ;
2169
	}
2170
 
2171
	case exp_sequence_tag :
2172
	case exp_solve_stmt_tag :
2173
	case exp_decl_stmt_tag :
2174
	case exp_while_stmt_tag :
2175
	case exp_do_stmt_tag :
2176
	case exp_switch_stmt_tag :
2177
	case exp_hash_if_tag :
2178
	case exp_return_stmt_tag :
2179
	case exp_goto_stmt_tag :
2180
	case exp_label_stmt_tag :
2181
	case exp_try_block_tag :
2182
	case exp_handler_tag :
2183
	case exp_reach_tag :
2184
	case exp_unreach_tag : {
2185
	    /* Statements */
2186
	    ua = flow_stmt ( e, ua, 1 ) ;
2187
	    break ;
2188
	}
2189
    }
2190
    ua &= ~va_mask ;
2191
    return ( ua ) ;
2192
}
2193
 
2194
 
2195
/*
2196
    PERFORM FLOW ANALYSIS FOR DESTRUCTORS
2197
 
2198
    This routine performs flow analysis for any destructors called by
2199
    the goto or return statement a.  b gives smallest statement enclosing
2200
    both the jump and its destination.
2201
*/
2202
 
2203
static void flow_jump
2204
    PROTO_N ( ( a, b ) )
2205
    PROTO_T ( EXP a X EXP b )
2206
{
2207
    unsigned long d = no_destructors ;
2208
    while ( !IS_NULL_exp ( a ) && !EQ_exp ( a, b ) && d ) {
2209
	/* Scan up to enclosing statement */
2210
	if ( IS_exp_decl_stmt ( a ) ) {
2211
	    IDENTIFIER id = DEREF_id ( exp_decl_stmt_id ( a ) ) ;
2212
	    if ( IS_id_variable ( id ) ) {
2213
		DECL_SPEC ds = DEREF_dspec ( id_storage ( id ) ) ;
2214
		if ( ds & dspec_auto ) {
2215
		    /* Local variable */
2216
		    EXP term = DEREF_exp ( id_variable_term ( id ) ) ;
2217
		    if ( !IS_NULL_exp ( term ) ) {
2218
			if ( do_usage ) dump_destr ( id, &stmt_loc ) ;
2219
			d-- ;
2220
		    }
2221
		}
2222
	    }
2223
	}
2224
	a = get_parent_stmt ( a ) ;
2225
    }
2226
    return ;
2227
}
2228
 
2229
 
2230
/*
2231
    PERFORM FLOW ANALYSIS ON A WHILE STATEMENT
2232
 
2233
    This routine performs flow analysis on the while statement e.
2234
*/
2235
 
2236
static VAR_INFO flow_while_stmt
2237
    PROTO_N ( ( e, use, flow ) )
2238
    PROTO_T ( EXP e X VAR_INFO use X int flow )
2239
{
2240
    VAR_INFO ua ;
2241
    EXP c = DEREF_exp ( exp_while_stmt_cond ( e ) ) ;
2242
    EXP a = DEREF_exp ( exp_while_stmt_body ( e ) ) ;
2243
    IDENTIFIER blab = DEREF_id ( exp_while_stmt_break_lab ( e ) ) ;
2244
    IDENTIFIER clab = DEREF_id ( exp_while_stmt_cont_lab ( e ) ) ;
2245
    unsigned cv = eval_const_cond ( c ) ;
2246
    if ( flow ) {
2247
	use = flow_exp ( c, use ) ;
2248
	flow_sequence_point () ;
2249
    }
2250
    ua = use ;
2251
    if ( cv != BOOL_TRUE ) {
2252
	IGNORE flow_goto_stmt ( blab, use, 1 ) ;
2253
	if ( cv == BOOL_FALSE ) ua |= va_unreached ;
2254
    }
2255
    ua = flow_stmt ( a, ua, flow ) ;
2256
    ua = flow_label_stmt ( clab, ua, flow ) ;
2257
    if ( flow ) {
2258
	IGNORE flow_exp ( c, ua ) ;
2259
	flow_sequence_point () ;
2260
    }
2261
    mark_vars ( crt_flow_vars, va_used_this ) ;
2262
    use = flow_label_stmt ( blab, ( use | va_unreached ), flow ) ;
2263
    return ( use ) ;
2264
}
2265
 
2266
 
2267
/*
2268
    PERFORM FLOW ANALYSIS ON A DO STATEMENT
2269
 
2270
    This routine performs flow analysis on the do statement e.
2271
*/
2272
 
2273
static VAR_INFO flow_do_stmt
2274
    PROTO_N ( ( e, use, flow ) )
2275
    PROTO_T ( EXP e X VAR_INFO use X int flow )
2276
{
2277
    EXP c = DEREF_exp ( exp_do_stmt_cond ( e ) ) ;
2278
    EXP a = DEREF_exp ( exp_do_stmt_body ( e ) ) ;
2279
    IDENTIFIER blab = DEREF_id ( exp_do_stmt_break_lab ( e ) ) ;
2280
    IDENTIFIER clab = DEREF_id ( exp_do_stmt_cont_lab ( e ) ) ;
2281
    unsigned cv = eval_const_cond ( c ) ;
2282
    use = flow_stmt ( a, use, flow ) ;
2283
    use = flow_label_stmt ( clab, use, flow ) ;
2284
    if ( flow ) {
2285
	use = flow_exp ( c, use ) ;
2286
	flow_sequence_point () ;
2287
    }
2288
    mark_vars ( crt_flow_vars, va_used_this ) ;
2289
    if ( cv == BOOL_TRUE ) use |= va_unreached ;
2290
    use = flow_label_stmt ( blab, use, flow ) ;
2291
    return ( use ) ;
2292
}
2293
 
2294
 
2295
/*
2296
    PERFORM FLOW ANALYSIS ON A SOLVE STATEMENT
2297
 
2298
    This routine performs flow analysis on the solve statement e with
2299
    associated variables p.
2300
*/
2301
 
2302
static VAR_INFO flow_solve_stmt
2303
    PROTO_N ( ( e, p, use, flow ) )
2304
    PROTO_T ( EXP e X LIST ( IDENTIFIER ) p X VAR_INFO use X int flow )
2305
{
2306
    if ( !IS_NULL_list ( p ) ) {
2307
	/* Scan through variables */
2308
	IDENTIFIER id = DEREF_id ( HEAD_list ( p ) ) ;
2309
	DECL_SPEC ds = DEREF_dspec ( id_storage ( id ) ) ;
2310
	if ( ( ds & dspec_auto ) && !( ds & dspec_done ) ) {
2311
	    start_variable ( id, ds, va_none ) ;
2312
	    use = flow_solve_stmt ( e, TAIL_list ( p ), use, flow ) ;
2313
	    end_variable ( flow, 0 ) ;
2314
	    return ( use ) ;
2315
	}
2316
	use = flow_solve_stmt ( e, TAIL_list ( p ), use, flow ) ;
2317
	return ( use ) ;
2318
    }
2319
    use = flow_stmt ( e, use, flow ) ;
2320
    return ( use ) ;
2321
}
2322
 
2323
 
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
/*
2373
    PERFORM FLOW ANALYSIS ON A TRY BLOCK
2374
 
2375
    This routine performs flow analysis on the try block e.
2376
*/
2377
 
2378
static VAR_INFO flow_try_block
2379
    PROTO_N ( ( e, use, flow ) )
2380
    PROTO_T ( EXP e X VAR_INFO use X int flow )
2381
{
2382
    VAR_INFO ua = ( use | va_unreached ) ;
2383
    EXP a = DEREF_exp ( exp_try_block_body ( e ) ) ;
2384
    LIST ( EXP ) p = DEREF_list ( exp_try_block_handlers ( e ) ) ;
2385
    EXP c = DEREF_exp ( exp_try_block_ellipsis ( e ) ) ;
2386
    use = flow_stmt ( a, use, flow ) ;
2387
    /* NOT YET IMPLEMENTED */
2388
    while ( !IS_NULL_list ( p ) ) {
2389
	EXP b = DEREF_exp ( HEAD_list ( p ) ) ;
2390
	IGNORE flow_stmt ( b, ua, flow ) ;
2391
	p = TAIL_list ( p ) ;
2392
    }
2393
    IGNORE flow_stmt ( c, ua, flow ) ;
2394
    return ( use ) ;
2395
}
2396
 
2397
 
2398
/*
2399
    PERFORM FLOW ANALYSIS ON A DECLARATION STATEMENT
2400
 
2401
    This routine performs flow analysis on the declaration statement e.
2402
*/
2403
 
2404
static VAR_INFO flow_decl_stmt
2405
    PROTO_N ( ( e, use, flow ) )
2406
    PROTO_T ( EXP e X VAR_INFO use X int flow )
2407
{
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 */
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 ) ;
2419
	    }
2420
	    if ( !IS_NULL_exp ( b ) ) {
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 ) ;
2435
	}
2436
    }
2437
    use = flow_stmt ( a, use, flow ) ;
2438
    return ( use ) ;
2439
}
2440
 
2441
 
2442
/*
2443
    PERFORM FLOW ANALYSIS ON A STATEMENT
2444
 
2445
    This routine performs flow analysis on the statement e.
2446
*/
2447
 
2448
static VAR_INFO flow_stmt
2449
    PROTO_N ( ( e, use, flow ) )
2450
    PROTO_T ( EXP e X VAR_INFO use X int flow )
2451
{
2452
    /* Deal with statements */
2453
    VAR_INFO ua = ( use & ~va_mask ) ;
2454
    if ( IS_NULL_exp ( e ) ) return ( ua ) ;
2455
    ASSERT ( ORDER_exp == 88 ) ;
2456
    switch ( TAG_exp ( e ) ) {
2457
 
2458
	case exp_sequence_tag : {
2459
	    /* Compound statements */
2460
	    LIST ( EXP ) p = DEREF_list ( exp_sequence_first ( e ) ) ;
2461
	    while ( !IS_NULL_list ( p ) ) {
2462
		EXP a = DEREF_exp ( HEAD_list ( p ) ) ;
2463
		if ( !IS_NULL_exp ( a ) ) {
2464
		    VAR_INFO ub = flow_stmt ( a, ua, flow ) ;
2465
		    if ( ub & va_unreached ) {
2466
			ua |= va_unreached ;
2467
		    } else {
2468
			ua &= ~va_unreached ;
2469
		    }
2470
		}
2471
		p = TAIL_list ( p ) ;
2472
	    }
2473
	    break ;
2474
	}
2475
 
2476
	case exp_solve_stmt_tag : {
2477
	    /* Solve statements */
2478
	    LIST ( IDENTIFIER ) p ;
2479
	    EXP a = DEREF_exp ( exp_solve_stmt_body ( e ) ) ;
2480
	    p = DEREF_list ( exp_solve_stmt_vars ( e ) ) ;
2481
	    ua = flow_solve_stmt ( a, p, ua, flow ) ;
2482
	    break ;
2483
	}
2484
 
2485
	case exp_decl_stmt_tag : {
2486
	    /* Declaration statements */
2487
	    ua = flow_decl_stmt ( e, ua, flow ) ;
2488
	    break ;
2489
	}
2490
 
2491
	case exp_if_stmt_tag : {
2492
	    /* Conditional statements */
2493
	    EXP c = DEREF_exp ( exp_if_stmt_cond ( e ) ) ;
2494
	    EXP a = DEREF_exp ( exp_if_stmt_true_code ( e ) ) ;
2495
	    EXP b = DEREF_exp ( exp_if_stmt_false_code ( e ) ) ;
2496
	    ua = flow_if_exp ( c, a, b, ua, flow ) ;
2497
	    break ;
2498
	}
2499
 
2500
	case exp_while_stmt_tag : {
2501
	    /* While statements */
2502
	    ua = flow_while_stmt ( e, ua, flow ) ;
2503
	    break ;
2504
	}
2505
 
2506
	case exp_do_stmt_tag : {
2507
	    /* Do statements */
2508
	    ua = flow_do_stmt ( e, ua, flow ) ;
2509
	    break ;
2510
	}
2511
 
2512
	case exp_switch_stmt_tag : {
2513
	    /* Switch statements */
2514
	    ua = flow_switch_stmt ( e, ua, flow ) ;
2515
	    break ;
2516
	}
2517
 
2518
	case exp_hash_if_tag : {
2519
	    /* Target dependent conditional statements */
2520
	    EXP c = DEREF_exp ( exp_hash_if_cond ( e ) ) ;
2521
	    EXP a = DEREF_exp ( exp_hash_if_true_code ( e ) ) ;
2522
	    EXP b = DEREF_exp ( exp_hash_if_false_code ( e ) ) ;
2523
	    ua = flow_if_exp ( c, a, b, ua, flow ) ;
2524
	    break ;
2525
	}
2526
 
2527
	case exp_return_stmt_tag : {
2528
	    /* Return statements */
2529
	    EXP a = DEREF_exp ( exp_return_stmt_value ( e ) ) ;
2530
	    if ( flow ) {
2531
		ua = flow_exp ( a, ua ) ;
2532
		flow_sequence_point () ;
2533
	    }
2534
	    ua = flow_terminate ( ua, 2 ) ;
2535
	    flow_jump ( e, NULL_exp ) ;
2536
	    break ;
2537
	}
2538
 
2539
	case exp_goto_stmt_tag : {
2540
	    /* Goto statements */
2541
	    EXP join = DEREF_exp ( exp_goto_stmt_join ( e ) ) ;
2542
	    IDENTIFIER lab = DEREF_id ( exp_goto_stmt_label ( e ) ) ;
2543
	    lab = DEREF_id ( id_alias ( lab ) ) ;
2544
	    ua = flow_goto_stmt ( lab, ua, 0 ) ;
2545
	    flow_jump ( e, join ) ;
2546
	    break ;
2547
	}
2548
 
2549
	case exp_label_stmt_tag : {
2550
	    /* Labelled statements */
2551
	    IDENTIFIER lab = DEREF_id ( exp_label_stmt_label ( e ) ) ;
2552
	    ua = flow_label_stmt ( lab, ua, flow ) ;
2553
	    break ;
2554
	}
2555
 
2556
	case exp_try_block_tag : {
2557
	    /* Try blocks */
2558
	    ua = flow_try_block ( e, ua, flow ) ;
2559
	    break ;
2560
	}
2561
 
2562
	case exp_handler_tag : {
2563
	    /* Exception handlers */
2564
	    EXP a = DEREF_exp ( exp_handler_body ( e ) ) ;
2565
	    ua = flow_stmt ( a, ua, flow ) ;
2566
	    break ;
2567
	}
2568
 
2569
	case exp_reach_tag : {
2570
	    /* Reached statements */
2571
	    EXP a = DEREF_exp ( exp_reach_body ( e ) ) ;
2572
	    ua &= ~va_unreached ;
2573
	    ua = flow_stmt ( a, ua, flow ) ;
2574
	    break ;
2575
	}
2576
 
2577
	case exp_unreach_tag : {
2578
	    /* Unreached statements */
2579
	    EXP a = DEREF_exp ( exp_unreach_body ( e ) ) ;
2580
	    ua |= va_unreached ;
2581
	    ua = flow_stmt ( a, ua, flow ) ;
2582
	    break ;
2583
	}
2584
 
2585
	case exp_location_tag : {
2586
	    /* Location expressions */
2587
	    EXP a = DEREF_exp ( exp_location_arg ( e ) ) ;
2588
	    ua = flow_stmt ( a, use, flow ) ;
2589
	    DEREF_loc ( exp_location_end ( e ), stmt_loc ) ;
2590
	    break ;
2591
	}
2592
 
2593
	default : {
2594
	    /* Simple expressions */
2595
	    if ( !( ua & va_unreached ) && flow ) {
2596
		ua = flow_exp ( e, ua ) ;
2597
		flow_sequence_point () ;
2598
	    }
2599
	    break ;
2600
	}
2601
    }
2602
    ua &= ~va_mask ;
2603
    return ( ua ) ;
2604
}
2605
 
2606
 
2607
/*
2608
    PERFORM FLOW ANALYSIS ON A FUNCTION DEFINITION
2609
 
2610
    This routine performs the flow analysis on the compound statement e
2611
    which defines the function id.  Full flow analysis is enabled if
2612
    flow is true, otherwise a minimal scan sufficient to determine all
2613
    implicit destructor calls is done.
2614
*/
2615
 
2616
void check_flow
2617
    PROTO_N ( ( id, e, flow ) )
2618
    PROTO_T ( IDENTIFIER id X EXP e X int flow )
2619
{
2620
    VAR_INFO use ;
2621
    LIST ( IDENTIFIER ) pids ;
2622
    if ( IS_id_function_etc ( id ) ) {
2623
	TYPE t = DEREF_type ( id_function_etc_type ( id ) ) ;
2624
	while ( IS_type_templ ( t ) ) {
2625
	    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
		}
2647
		crt_flow_mems = crt_flow_vars ;
2648
	    }
2649
	    if ( !IS_NULL_id ( pid ) ) {
2650
		start_variable ( pid, dspec_none, va_this ) ;
2651
		set_variable ( pid, va_assign ) ;
2652
	    }
2653
	}
2654
	pids = DEREF_list ( type_func_pids ( t ) ) ;
2655
	while ( !IS_NULL_list ( pids ) ) {
2656
	    /* Set up parameter scopes */
2657
	    IDENTIFIER pid = DEREF_id ( HEAD_list ( pids ) ) ;
2658
	    if ( !IS_NULL_id ( pid ) ) {
2659
		DECL_SPEC ds = DEREF_dspec ( id_storage ( pid ) ) ;
2660
		start_variable ( pid, ds, va_none ) ;
2661
		set_variable ( pid, va_assign ) ;
2662
	    }
2663
	    pids = TAIL_list ( pids ) ;
2664
	}
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 ;
2676
    return ;
2677
}