Subversion Repositories tendra.SVN

Rev

Rev 2 | 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 "exp_ops.h"
64
#include "hashid_ops.h"
65
#include "id_ops.h"
66
#include "tok_ops.h"
67
#include "type_ops.h"
68
#include "error.h"
69
#include "catalog.h"
70
#include "option.h"
71
#include "allocate.h"
72
#include "basetype.h"
73
#include "cast.h"
74
#include "chktype.h"
75
#include "class.h"
76
#include "construct.h"
77
#include "convert.h"
78
#include "declare.h"
79
#include "derive.h"
80
#include "destroy.h"
81
#include "exception.h"
82
#include "expression.h"
83
#include "file.h"
84
#include "function.h"
85
#include "hash.h"
86
#include "identifier.h"
87
#include "initialise.h"
88
#include "label.h"
89
#include "namespace.h"
90
#include "predict.h"
91
#include "redeclare.h"
92
#include "statement.h"
93
#include "syntax.h"
94
#include "template.h"
95
#include "tokdef.h"
96
#include "typeid.h"
97
 
98
 
99
/*
100
    THE SET OF ALL TYPES
101
 
102
    The dummy list univ_type_set is used to represent the set of all
103
    types.  These sets of types are used to represent exception
104
    specifications for functions.  The list empty_type_set is used to
105
    give the exception specification for a function when none is given,
106
    by default it equals univ_type_set.
107
*/
108
 
7 7u83 109
LIST(TYPE) univ_type_set = NULL_list(TYPE);
110
LIST(TYPE) empty_type_set = NULL_list(TYPE);
2 7u83 111
 
112
 
113
/*
114
    INITIALISE THE SET OF ALL TYPES
115
 
116
    This routine initialises the set of all types to a dummy unique list.
117
*/
118
 
7 7u83 119
void
120
init_exception(void)
2 7u83 121
{
7 7u83 122
	LIST(TYPE)p;
123
	CONS_type(type_any, NULL_list(TYPE), p);
124
	p = uniq_type_set(p);
125
	COPY_list(type_func_except(type_func_void), p);
126
	COPY_list(type_func_except(type_temp_func), p);
127
	empty_type_set = p;
128
	univ_type_set = p;
129
	return;
2 7u83 130
}
131
 
132
 
133
/*
134
    IS A TYPE IN A SET OF TYPES?
135
 
136
    This routine checks whether the type t is an element of the set of
137
    types listed as p.
138
*/
139
 
7 7u83 140
int
141
in_type_set(LIST(TYPE)p, TYPE t)
2 7u83 142
{
7 7u83 143
	if (EQ_list(p, univ_type_set)) {
144
		return (1);
2 7u83 145
	}
7 7u83 146
	expand_tokdef++;
147
	while (!IS_NULL_list(p)) {
148
		TYPE s = DEREF_type(HEAD_list(p));
149
		if (EQ_type(t, s) || eq_type_unqual(t, s)) {
150
			expand_tokdef--;
151
			return (1);
152
		}
153
		p = TAIL_list(p);
154
	}
155
	expand_tokdef--;
156
	return (0);
2 7u83 157
}
158
 
159
 
160
/*
161
    IS A TYPE DERIVABLE FROM A SET OF TYPES?
162
 
163
    This routine checks whether an exception of type t will be caught by
164
    an element of the set of types listed as p.  It returns the catching
165
    type, or the null type if no match is found.
166
*/
167
 
7 7u83 168
static TYPE
169
from_type_set(LIST(TYPE)p, TYPE t)
2 7u83 170
{
7 7u83 171
	if (EQ_list(p, univ_type_set)) {
172
		/* The universal set catches everything */
173
		return (t);
174
	}
175
	expand_tokdef++;
176
	if (IS_type_ref(t)) {
177
		t = DEREF_type(type_ref_sub(t));
178
	}
179
	while (!IS_NULL_list(p)) {
180
		TYPE r = DEREF_type(HEAD_list(p));
181
		if (!IS_NULL_type(r)) {
182
			TYPE s = r;
183
			unsigned rank;
184
			CONVERSION conv;
185
			if (IS_type_ref(s)) {
186
				s = DEREF_type(type_ref_sub(s));
187
			}
188
			if (eq_type_unqual(t, s)) {
189
				/* Exact match is allowed */
190
				expand_tokdef--;
191
				return (r);
192
			}
193
			conv.from = t;
194
			conv.to = s;
195
			rank = std_convert_seq(&conv, NULL_exp, 0, 0);
196
			switch (rank) {
197
			case CONV_EXACT:
198
			case CONV_QUAL:
199
			case CONV_BASE:
200
			case CONV_PTR_BASE:
201
			case CONV_PTR_VOID:
202
			case CONV_PTR_BOTTOM:
203
				/* These conversions are allowed */
204
				expand_tokdef--;
205
				return (r);
206
			}
2 7u83 207
		}
7 7u83 208
		p = TAIL_list(p);
2 7u83 209
	}
7 7u83 210
	expand_tokdef--;
211
	return (NULL_type);
2 7u83 212
}
213
 
214
 
215
/*
216
    ARE TWO TYPE SETS EQUAL?
217
 
218
    This routine checks whether the sets of types listed as p and q are
219
    equal.  It returns 2 if they are equal, 1 if p is a subset of q, and
220
 
221
    duplicate elements a fair amount can be deduced from the cardinalities
222
    of the sets, also the search is optimised if the types are given in
223
    the same order in each set.  If eq is true then only equality is
224
    checked for.
225
*/
226
 
7 7u83 227
int
228
eq_type_set(LIST(TYPE) p, LIST(TYPE) q, int eq)
2 7u83 229
{
7 7u83 230
	unsigned n, m;
231
	LIST(TYPE)r;
2 7u83 232
 
7 7u83 233
	/* Deal with the set of all types */
234
	if (EQ_list(p, q)) {
235
		return (2);
236
	}
237
	if (EQ_list(q, univ_type_set) && !eq) {
238
		return (1);
239
	}
240
	if (EQ_list(p, univ_type_set)) {
241
		return (0);
242
	}
2 7u83 243
 
7 7u83 244
	/* Check whether p is larger than q */
245
	n = LENGTH_list(p);
246
	m = LENGTH_list(q);
247
	if (n > m) {
248
		return (0);
249
	}
250
	if (n < m && eq) {
251
		return (0);
252
	}
2 7u83 253
 
7 7u83 254
	/* Check whether p is a subset of q */
255
	r = q;
256
	while (!IS_NULL_list(p)) {
257
		TYPE t = DEREF_type(HEAD_list(p));
258
		TYPE s = DEREF_type(HEAD_list(r));
259
		if (!EQ_type(t, s) && !eq_type_unqual(t, s)) {
260
			if (!in_type_set(q, t)) {
261
				return (0);
262
			}
263
		}
264
		r = TAIL_list(r);
265
		p = TAIL_list(p);
2 7u83 266
	}
267
 
7 7u83 268
	/* Check for equality using set sizes */
269
	if (n < m) {
270
		return (1);
271
	}
272
	return (2);
2 7u83 273
}
274
 
275
 
276
/*
277
    ADD AN ELEMENT TO A TYPE SET
278
 
279
    This routine adds the type t to the type set p if it is not already
280
    a member.
281
*/
282
 
7 7u83 283
LIST(TYPE)
284
cons_type_set(LIST(TYPE) p, TYPE t)
2 7u83 285
{
7 7u83 286
	if (!IS_NULL_type(t) && !in_type_set(p, t)) {
287
		CONS_type(t, p, p);
288
	}
289
	return (p);
2 7u83 290
}
291
 
292
 
293
/*
294
    FIND THE UNION OF TWO TYPE SETS
295
 
296
    This routine adds the elements of the type set q to the type set p.
297
*/
298
 
7 7u83 299
LIST(TYPE)
300
union_type_set(LIST(TYPE)p, LIST(TYPE)q)
2 7u83 301
{
7 7u83 302
	if (!EQ_list(p, univ_type_set)) {
303
		if (EQ_list(q, univ_type_set)) {
304
			DESTROY_list(p, SIZE_type);
305
			p = q;
306
		} else {
307
			while (!IS_NULL_list(q)) {
308
				TYPE t = DEREF_type(HEAD_list(q));
309
				if (!IS_NULL_type(t)) {
310
					if (!in_type_set(p, t)) {
311
						CONS_type(t, p, p);
312
					}
313
				}
314
				q = TAIL_list(q);
315
			}
2 7u83 316
		}
317
	}
7 7u83 318
	return (p);
2 7u83 319
}
320
 
321
 
322
/*
323
    MAKE A UNIQUE COPY OF A TYPE SET
324
 
325
    This routine maintains a list of type sets.  If p equals an element of
326
    this list then the copy is returned and p is destroyed.  Otherwise p
327
    is added to the list.
328
*/
329
 
7 7u83 330
LIST(TYPE)
331
uniq_type_set(LIST(TYPE)p)
2 7u83 332
{
7 7u83 333
	static LIST(LIST(TYPE)) sets = NULL_list(LIST(TYPE));
334
	LIST(LIST(TYPE))s = sets;
335
	while (!IS_NULL_list(s)) {
336
		LIST(TYPE)q = DEREF_list(HEAD_list(s));
337
		if (eq_type_set(p, q, 1) == 2) {
338
			DESTROY_list(p, SIZE_type);
339
			return (q);
340
		}
341
		s = TAIL_list(s);
2 7u83 342
	}
7 7u83 343
	CONS_list(p, sets, sets);
344
	return (p);
2 7u83 345
}
346
 
347
 
348
/*
349
    COMPARE THE EXCEPTION SPECIFIERS OF TWO TYPES
350
 
351
    This routine compares the exception specifiers of the similar types
352
    s and t.  It returns 2 if they are equal, 1 if s is more constrained
353
    than t, and 0 otherwise.
354
*/
355
 
7 7u83 356
int
357
eq_except(TYPE s, TYPE t)
2 7u83 358
{
7 7u83 359
	unsigned ns, nt;
360
	if (EQ_type(s, t)) {
361
		return (2);
362
	}
363
	if (IS_NULL_type(s)) {
364
		return (0);
365
	}
366
	if (IS_NULL_type(t)) {
367
		return (0);
368
	}
369
	ns = TAG_type(s);
370
	nt = TAG_type(t);
371
	if (ns != nt) {
372
		return (2);
373
	}
374
	ASSERT(ORDER_type == 18);
375
	switch (ns) {
376
	case type_func_tag: {
377
		/* Function types */
378
		LIST(TYPE)es = DEREF_list(type_func_except(s));
379
		LIST(TYPE)et = DEREF_list(type_func_except(t));
380
		int eq = eq_type_set(es, et, 0);
381
		if (eq) {
382
			TYPE rs, rt;
383
			LIST(TYPE)ps = DEREF_list(type_func_ptypes(s));
384
			LIST(TYPE)pt = DEREF_list(type_func_ptypes(t));
385
			while (!IS_NULL_list(ps) && !IS_NULL_list(pt)) {
386
				rs = DEREF_type(HEAD_list(ps));
387
				rt = DEREF_type(HEAD_list(pt));
388
				if (eq_except(rs, rt) != 2) {
389
					return (0);
390
				}
391
				pt = TAIL_list(pt);
392
				ps = TAIL_list(ps);
393
			}
394
			rs = DEREF_type(type_func_ret(s));
395
			rt = DEREF_type(type_func_ret(t));
396
			if (eq_except(rs, rt) != 2) {
397
				return (0);
398
			}
2 7u83 399
		}
7 7u83 400
		return (eq);
2 7u83 401
	}
7 7u83 402
	case type_ptr_tag:
403
	case type_ref_tag: {
404
		/* Pointer and reference types */
405
		TYPE ps = DEREF_type(type_ptr_etc_sub(s));
406
		TYPE pt = DEREF_type(type_ptr_etc_sub(t));
407
		return (eq_except(ps, pt));
2 7u83 408
	}
7 7u83 409
	case type_ptr_mem_tag: {
410
		/* Pointer to member types */
411
		TYPE ps = DEREF_type(type_ptr_mem_sub(s));
412
		TYPE pt = DEREF_type(type_ptr_mem_sub(t));
413
		return (eq_except(ps, pt));
2 7u83 414
	}
7 7u83 415
	case type_array_tag: {
416
		/* Array types */
417
		TYPE ps = DEREF_type(type_array_sub(s));
418
		TYPE pt = DEREF_type(type_array_sub(t));
419
		return (eq_except(ps, pt));
2 7u83 420
	}
7 7u83 421
	case type_templ_tag: {
422
		/* Template types */
423
		TOKEN as = DEREF_tok(type_templ_sort(s));
424
		TOKEN at = DEREF_tok(type_templ_sort(t));
425
		LIST(IDENTIFIER) qs = DEREF_list(tok_templ_pids(as));
426
		LIST(IDENTIFIER) qt = DEREF_list(tok_templ_pids(at));
427
		int eq = eq_templ_params(qs, qt);
428
		if (eq) {
429
			TYPE ps = DEREF_type(type_templ_defn(s));
430
			TYPE pt = DEREF_type(type_templ_defn(t));
431
			eq = eq_except(ps, pt);
432
		}
433
		restore_templ_params(qs);
434
		return (eq);
2 7u83 435
	}
7 7u83 436
	}
437
	return (2);
2 7u83 438
}
439
 
440
 
441
/*
442
    CREATE AN EXCEPTION TYPE
443
 
444
    This routine converts the exception type t to its primary form.
445
    Reference types are replaced by the referenced type and any top level
446
    type qualifiers are removed.  chk gives the context for the conversion,
447
    1 for a throw expression, 2 for a catch statement, 3 for an exception
448
    specifier and 0 otherwise.
449
*/
450
 
7 7u83 451
TYPE
452
exception_type(TYPE t, int chk)
2 7u83 453
{
7 7u83 454
	if (!IS_NULL_type(t)) {
455
		unsigned tag = TAG_type(t);
456
		if (tag == type_ref_tag) {
457
			t = DEREF_type(type_ref_sub(t));
458
			tag = TAG_type(t);
2 7u83 459
		}
7 7u83 460
		t = qualify_type(t, cv_none, 0);
461
		if (chk) {
462
			/* Check exception type */
463
			TYPE s = t;
464
			if (tag == type_ptr_tag) {
465
				s = DEREF_type(type_ptr_sub(s));
466
				tag = TAG_type(s);
467
			}
468
			if (tag == type_compound_tag) {
469
				ERROR err = check_incomplete(s);
470
				if (!IS_NULL_err(err)) {
471
					/* Can't have an incomplete class */
472
					ERROR err2 = NULL_err;
473
					switch (chk) {
474
					case 1:
475
						err2 =
476
						    ERR_except_throw_incompl();
477
						break;
478
					case 2:
479
						err2 =
480
						    ERR_except_handle_incompl();
481
						break;
482
					case 3:
483
						err2 =
484
						    ERR_except_spec_incompl();
485
						break;
486
					}
487
					err = concat_error(err, err2);
488
					report(crt_loc, err);
489
				}
490
				if (chk == 1) {
491
					/* Can't throw a type with an ambiguous base */
492
					CLASS_TYPE cs =
493
					    DEREF_ctype(type_compound_defn(s));
494
					err = class_info(cs, cinfo_ambiguous,
495
							 1);
496
					if (!IS_NULL_err(err)) {
497
						ERROR err2 =
498
						    ERR_except_throw_ambig();
499
						err = concat_error(err, err2);
500
						report(crt_loc, err);
501
					}
502
				}
503
			}
2 7u83 504
		}
505
	}
7 7u83 506
	return (t);
2 7u83 507
}
508
 
509
 
510
/*
511
    CHECK AN EXCEPTION SPECIFIER TYPE
512
 
513
    This routine checks the type t, which forms part of an exception
514
    specification for a function.  The argument n gives the number of types
515
    defined in t.
516
*/
517
 
7 7u83 518
TYPE
519
check_except_type(TYPE t, int n)
2 7u83 520
{
7 7u83 521
	if (n) {
522
		report(crt_loc, ERR_except_spec_typedef());
523
	}
524
	IGNORE exception_type(t, 3);
525
	return (t);
2 7u83 526
}
527
 
528
 
529
/*
530
    STACK OF CURRENTLY ACTIVE TRY BLOCKS
531
 
532
    The stack crt_try_block is used to hold all the currently active try
533
    blocks and exception handlers.  The flag in_func_handler is set to
534
    1 (or 2 for constructors and destructors) in the handler of a function
535
    try block.
536
*/
537
 
7 7u83 538
STACK(EXP) crt_try_blocks = NULL_stack(EXP);
539
static STACK(STACK(EXP)) past_try_blocks = NULL_stack(STACK(EXP));
540
int in_func_handler = 0;
2 7u83 541
 
542
 
543
/*
544
    CHECK A THROWN TYPE
545
 
546
    This routine checks the type t thrown from an explicit throw expression
547
    (if expl is true) or a function call.  The null type is used to
548
    indicate an unknown type.  The routine returns true if the exception
549
    is caught by an enclosing handler.
550
*/
551
 
7 7u83 552
int
553
check_throw(TYPE t, int expl)
2 7u83 554
{
7 7u83 555
	IDENTIFIER fn;
556
	LIST(EXP) p = LIST_stack(crt_try_blocks);
557
	while (!IS_NULL_list(p)) {
558
		EXP e = DEREF_exp(HEAD_list(p));
559
		if (IS_exp_try_block(e)) {
560
			/* Add to list of thrown types */
561
			LIST(TYPE)q;
562
			q = DEREF_list(exp_try_block_ttypes(e));
563
			if (!EQ_list(q, univ_type_set)) {
564
				LIST(LOCATION)ql;
565
				ql = DEREF_list(exp_try_block_tlocs(e));
566
				if (IS_NULL_type(t)) {
567
					DESTROY_list(q, SIZE_type);
568
					DESTROY_list(ql, SIZE_loc);
569
					q = univ_type_set;
570
					ql = NULL_list(LOCATION);
571
					CONS_loc(crt_loc, ql, ql);
572
				} else {
573
					if (!in_type_set(q, t)) {
574
						CONS_type(t, q, q);
575
						CONS_loc(crt_loc, ql, ql);
576
					}
577
				}
578
				COPY_list(exp_try_block_ttypes(e), q);
579
				COPY_list(exp_try_block_tlocs(e), ql);
580
			}
581
			return (1);
2 7u83 582
		}
7 7u83 583
		if (IS_NULL_type(t) && expl && IS_exp_handler(e)) {
584
			/* Can deduce type of 'throw' inside a handler */
585
			IDENTIFIER ex = DEREF_id(exp_handler_except(e));
586
			if (!IS_NULL_id(ex)) {
587
				t = DEREF_type(id_variable_etc_type(ex));
588
				t = exception_type(t, 0);
589
			}
590
		}
591
		p = TAIL_list(p);
2 7u83 592
	}
7 7u83 593
 
594
	/* Exception not caught by any try block */
595
	fn = crt_func_id;
596
	if (IS_NULL_type(t)) {
597
		t = type_any;
2 7u83 598
	}
7 7u83 599
	if (IS_NULL_id(fn)) {
600
		report(crt_loc, ERR_except_spec_throw(t));
601
	} else {
602
		report(crt_loc, ERR_except_spec_call(fn, t));
603
	}
604
	return (0);
2 7u83 605
}
606
 
607
 
608
/*
609
    CHECK THE EXCEPTIONS THROWN IN A TRY BLOCK
610
 
611
    This routine checks the exceptions thrown in the try block e.  Any
612
    which are not caught by the handlers of e are passed to the enclosing
613
    block or reported if this is the outermost block.  The routine
614
    returns true if all the exceptions are handled by an enclosing block.
615
*/
616
 
7 7u83 617
int
618
check_try_block(EXP e)
2 7u83 619
{
7 7u83 620
	int res = 1;
621
	if (IS_exp_try_block(e)) {
622
		LOCATION loc;
623
		LIST(LOCATION)ql;
624
		LIST(TYPE)p = DEREF_list(exp_try_block_htypes(e));
625
		LIST(TYPE)q = DEREF_list(exp_try_block_ttypes(e));
626
		EXP a = DEREF_exp(exp_try_block_ellipsis(e));
627
		if (EQ_list(p, univ_type_set)) {
628
			/* Have handlers for any type */
629
			return (1);
2 7u83 630
		}
7 7u83 631
		if (!IS_NULL_exp(a) && IS_exp_handler(a)) {
632
			/* Have a ... handler */
633
			return (1);
634
		}
635
		bad_crt_loc++;
636
		loc = crt_loc;
637
		ql = DEREF_list(exp_try_block_tlocs(e));
638
		if (EQ_list(q, univ_type_set)) {
639
			/* Can throw any type */
640
			DEREF_loc(HEAD_list(ql), crt_loc);
641
			res = check_throw(NULL_type, 0);
642
		} else {
643
			/* Can throw a finite set of types */
644
			q = REVERSE_list(q);
645
			ql = REVERSE_list(ql);
646
			COPY_list(exp_try_block_ttypes(e), q);
647
			COPY_list(exp_try_block_tlocs(e), ql);
648
			while (!IS_NULL_list(q)) {
649
				TYPE t = DEREF_type(HEAD_list(q));
650
				TYPE u = from_type_set(p, t);
651
				if (IS_NULL_type(u)) {
652
					/* Throw uncaught type to enclosing
653
					 * block */
654
					DEREF_loc(HEAD_list(ql), crt_loc);
655
					if (!check_throw(t, 0)) {
656
						res = 0;
657
					}
658
				}
659
				ql = TAIL_list(ql);
660
				q = TAIL_list(q);
661
			}
662
		}
663
		crt_loc = loc;
664
		bad_crt_loc--;
2 7u83 665
	}
7 7u83 666
	return (res);
2 7u83 667
}
668
 
669
 
670
/*
671
    CHECK THE EXCEPTIONS THROWN BY A FUNCTION CALL
672
 
673
    This routine checks the possible exceptions thrown by a call to a
674
    function of type fn.  When known the function name is given by fid.
675
    The routine returns true if the exception is handled by an enclosing
676
    try-block.
677
*/
678
 
7 7u83 679
int
680
check_func_throw(TYPE fn, IDENTIFIER fid)
2 7u83 681
{
7 7u83 682
	int res = 1;
683
	if (IS_type_func(fn)) {
684
		LIST(TYPE)p = DEREF_list(type_func_except(fn));
685
		if (IS_NULL_list(p)) {
686
			return (1);
687
		}
688
		if (EQ_list(p, univ_type_set)) {
689
			/* Can throw any type */
690
			res = check_throw(NULL_type, 0);
691
		} else {
692
			/* Can throw a finite set of types */
693
			while (!IS_NULL_list(p)) {
694
				TYPE t = DEREF_type(HEAD_list(p));
695
				if (!IS_NULL_type(t)) {
696
					if (!check_throw(t, 0)) {
697
						res = 0;
698
					}
699
				}
700
				p = TAIL_list(p);
701
			}
702
		}
2 7u83 703
	} else {
7 7u83 704
		res = check_throw(NULL_type, 0);
2 7u83 705
	}
7 7u83 706
	UNUSED(fid);
707
	return (res);
2 7u83 708
}
709
 
710
 
711
/*
712
    START THE EXCEPTION CHECKS FOR A FUNCTION DEFINITION
713
 
714
    This routine starts the exception specification checks for a function
715
    which throws the types p.
716
*/
717
 
7 7u83 718
void
719
start_try_check(LIST(TYPE) p)
2 7u83 720
{
7 7u83 721
	EXP e;
722
	MAKE_exp_try_block(type_void, NULL_exp, 0, e);
723
	COPY_list(exp_try_block_htypes(e), p);
724
	PUSH_stack(crt_try_blocks, past_try_blocks);
725
	crt_try_blocks = NULL_stack(EXP);
726
	PUSH_exp(e, crt_try_blocks);
727
	return;
2 7u83 728
}
729
 
730
 
731
/*
732
    END THE EXCEPTION CHECKS FOR A FUNCTION DEFINITION
733
 
734
    This routine ends the exception specification checks for the function
735
    id with definition a.
736
*/
737
 
7 7u83 738
EXP
739
end_try_check(IDENTIFIER id, EXP a)
2 7u83 740
{
7 7u83 741
	EXP e;
742
	POP_exp(e, crt_try_blocks);
743
	POP_stack(crt_try_blocks, past_try_blocks);
744
	if (!IS_NULL_exp(e) && IS_exp_try_block(e)) {
745
		IDENTIFIER fid = crt_func_id;
746
		crt_func_id = id;
747
		IGNORE check_try_block(e);
748
		if (EQ_id(fid, id)) {
749
			LIST(TYPE)p = DEREF_list(exp_try_block_ttypes(e));
750
			if (IS_NULL_list(p) && !in_template_decl) {
751
				/* Function can't throw an exception */
752
				DECL_SPEC ds = DEREF_dspec(id_storage(id));
753
				ds |= dspec_friend;
754
				COPY_dspec(id_storage(id), ds);
755
			}
756
		}
757
		COPY_list(exp_try_block_htypes(e), NULL_list(TYPE));
758
		free_exp(e, 1);
759
		crt_func_id = fid;
2 7u83 760
	}
7 7u83 761
	return (a);
2 7u83 762
}
763
 
764
 
765
/*
766
    EXCEPTION HANDLING ROUTINES
767
 
768
    The exception handling routines are only included in the C++ producer.
769
*/
770
 
771
#if LANGUAGE_CPP
772
 
773
 
774
/*
775
    BEGIN THE CONSTRUCTION OF A TRY STATEMENT
776
 
777
    This routine begins the construction of the statement 'try { body }
778
    handlers'.  It is called immediately after the 'try'.  func is true
779
    for a function-try-block.
780
*/
781
 
7 7u83 782
EXP
783
begin_try_stmt(int func)
2 7u83 784
{
7 7u83 785
	EXP e;
786
	if (func) {
787
		/* Check function try blocks */
788
		IDENTIFIER fn = crt_func_id;
789
		if (!IS_NULL_id(fn)) {
790
			HASHID nm = DEREF_hashid(id_name(fn));
791
			unsigned tag = TAG_hashid(nm);
792
			if (tag == hashid_constr_tag ||
793
			    tag == hashid_destr_tag) {
794
				/* Constructors and destructors are marked */
795
				func = 2;
796
			}
797
		} else {
798
			func = 0;
799
		}
2 7u83 800
	}
7 7u83 801
	MAKE_exp_try_block(type_void, NULL_exp, func, e);
802
	CONS_exp(e, all_try_blocks, all_try_blocks);
803
	PUSH_exp(e, crt_try_blocks);
804
	return (e);
2 7u83 805
}
806
 
807
 
808
/*
809
    INJECT FUNCTION PARAMETERS INTO A HANDLER
810
 
811
    It is not allowed to redeclare a function parameter in the body or
812
    the handler of a function-try-block.  This routine ensures this by
813
    injecting the function parameters into the current scope when prev
814
    is a function-try-block.
815
*/
816
 
7 7u83 817
void
818
inject_try_stmt(EXP prev)
2 7u83 819
{
7 7u83 820
	int func = DEREF_int(exp_try_block_func(prev));
821
	if (func) {
822
		IDENTIFIER id = crt_func_id;
823
		if (!IS_NULL_id(id) && IS_id_function_etc(id)) {
824
			LIST(IDENTIFIER)pids;
825
			NAMESPACE ns = crt_namespace;
826
			TYPE t = DEREF_type(id_function_etc_type(id));
827
			while (IS_type_templ(t)) {
828
				t = DEREF_type(type_templ_defn(t));
829
			}
830
			pids = DEREF_list(type_func_pids(t));
831
			while (!IS_NULL_list(pids)) {
832
				IDENTIFIER pid = DEREF_id(HEAD_list(pids));
833
				IGNORE redeclare_id(ns, pid);
834
				pids = TAIL_list(pids);
835
			}
836
		}
2 7u83 837
	}
7 7u83 838
	return;
2 7u83 839
}
840
 
841
 
842
/*
843
    CONTINUE THE CONSTRUCTION OF A TRY STATEMENT
844
 
845
    This routine continues the contruction of the try statement prev by
846
    filling in the given body statement.
847
*/
848
 
7 7u83 849
EXP
850
cont_try_stmt(EXP prev, EXP body)
2 7u83 851
{
7 7u83 852
	EXP e;
853
	int func = DEREF_int(exp_try_block_func(prev));
854
	if (func) {
855
		in_func_handler = func;
856
	}
857
	COPY_exp(exp_try_block_body(prev), body);
858
	set_parent_stmt(body, prev);
859
	POP_exp(e, crt_try_blocks);
860
	UNUSED(e);
861
	return (prev);
2 7u83 862
}
863
 
864
 
865
/*
866
    COMPLETE THE CONSTRUCTION OF A TRY STATEMENT
867
 
868
    This routine completes the contruction of the try statement prev.  It
869
    checks whether it contains at least one handler and determines the
870
    reachability of the following statement.
871
*/
872
 
7 7u83 873
EXP
874
end_try_stmt(EXP prev, int empty)
2 7u83 875
{
7 7u83 876
	EXP e;
877
	TYPE t;
878
	int all_bottom = 1;
879
	int func = DEREF_int(exp_try_block_func(prev));
2 7u83 880
 
7 7u83 881
	/* Check handler list */
882
	EXP ell = DEREF_exp(exp_try_block_ellipsis(prev));
883
	LIST(EXP)hs = DEREF_list(exp_try_block_handlers(prev));
884
	LIST(TYPE)ps = DEREF_list(exp_try_block_ttypes(prev));
885
	unsigned nh = LENGTH_list(hs);
886
	if (IS_NULL_exp(ell)) {
887
		/* Create default handler if necessary */
888
		if (IS_NULL_list(hs) && !empty) {
889
			/* Check that there is at least one handler */
890
			report(crt_loc, ERR_except_handlers());
891
		}
892
		MAKE_exp_exception(type_bottom, ell, NULL_exp, NULL_exp, 0,
893
				   ell);
894
		COPY_exp(exp_try_block_ellipsis(prev), ell);
895
	} else {
896
		nh++;
2 7u83 897
	}
7 7u83 898
	IGNORE check_value(OPT_VAL_exception_handlers,(ulong)nh);
2 7u83 899
 
7 7u83 900
	/* Do unreached code analysis */
901
	e = DEREF_exp(exp_try_block_body(prev));
902
	t = DEREF_type(exp_type(e));
903
	if (IS_type_bottom(t)) {
904
		/* Don't reach end of try block */
905
		t = DEREF_type(exp_type(ell));
906
		if (!IS_type_bottom(t)) {
907
			all_bottom = 0;
908
		}
909
		while (!IS_NULL_list(hs) && all_bottom) {
910
			/* Check the other handlers */
911
			e = DEREF_exp(HEAD_list(hs));
912
			t = DEREF_type(exp_type(e));
913
			if (!IS_type_bottom(t)) {
914
				all_bottom = 0;
915
			}
916
			hs = TAIL_list(hs);
917
		}
918
	} else {
919
		/* Reach end of try block */
920
		all_bottom = 0;
2 7u83 921
	}
7 7u83 922
	if (all_bottom) {
923
		COPY_type(exp_type(prev), type_bottom);
924
		unreached_code = 1;
925
		unreached_last = 0;
926
	} else {
927
		unreached_code = unreached_prev;
928
	}
929
	if (IS_NULL_list(ps) && !empty && !in_template_decl) {
930
		report(crt_loc, ERR_except_not());
931
	}
932
	if (func) {
933
		in_func_handler = 0;
934
	}
935
	IGNORE check_try_block(prev);
936
	return (prev);
2 7u83 937
}
938
 
939
 
940
/*
941
    MARK ALL VARIABLES ENCLOSING A TRY BLOCK
942
 
943
    This routine marks all the local variables of the function id which
944
    contain a try block within their scope.
945
*/
946
 
7 7u83 947
void
948
end_try_blocks(IDENTIFIER id)
2 7u83 949
{
7 7u83 950
	LIST(EXP)p = all_try_blocks;
951
	if (!IS_NULL_list(p)) {
952
		if (!IS_NULL_id(id)) {
953
			/* Mark function */
954
			DECL_SPEC ds = DEREF_dspec(id_storage(id));
955
			ds |= dspec_mutable;
956
			COPY_dspec(id_storage(id), ds);
2 7u83 957
		}
7 7u83 958
		while (!IS_NULL_list(p)) {
959
			EXP a = DEREF_exp(HEAD_list(p));
960
			while (!IS_NULL_exp(a)) {
961
				if (IS_exp_decl_stmt(a)) {
962
					IDENTIFIER pid =
963
					    DEREF_id(exp_decl_stmt_id(a));
964
					DECL_SPEC ds =
965
					    DEREF_dspec(id_storage(pid));
966
					if (ds & dspec_auto) {
967
						/* Mark local variable */
968
						ds |= dspec_mutable;
969
						COPY_dspec(id_storage(pid), ds);
970
					}
971
				}
972
				a = get_parent_stmt(a);
973
			}
974
			p = TAIL_list(p);
975
		}
2 7u83 976
	}
7 7u83 977
	return;
2 7u83 978
}
979
 
980
 
981
/*
982
    DECLARE AN EXCEPTION HANDLER
983
 
984
    This routine declares an exception handler named id with type t and
985
    declaration specifiers ds (which should always be empty).  n gives
986
    the number of types defined in t.
987
*/
988
 
7 7u83 989
IDENTIFIER
990
make_except_decl(DECL_SPEC ds, TYPE t, IDENTIFIER id, int n)
2 7u83 991
{
7 7u83 992
	/* Declare id as a local variable */
993
	EXP e;
994
	if (crt_id_qualifier == qual_nested || crt_templ_qualifier) {
995
		/* Other illegal identifiers are caught elsewhere */
996
		report(crt_loc, ERR_dcl_meaning_id(qual_nested, id));
997
	}
998
	if (n) {
999
		report(crt_loc, ERR_except_handle_typedef());
1000
	}
1001
	t = make_param_type(t, CONTEXT_PARAMETER);
1002
	id = make_object_decl(ds, t, id, 0);
2 7u83 1003
 
7 7u83 1004
	/* The initialising value is the current exception */
1005
	if (IS_type_ref(t)) {
1006
		t = DEREF_type(type_ref_sub(t));
1007
	}
1008
	t = lvalue_type(t);
1009
	MAKE_exp_thrown(t, 0, e);
1010
	IGNORE init_object(id, e);
1011
	return (id);
2 7u83 1012
}
1013
 
1014
 
1015
/*
1016
    BEGIN THE CONSTRUCTION OF A CATCH STATEMENT
1017
 
1018
    This routine begins the construction of the handler 'catch ( ex )
1019
    { body }' associated with the try block block.  It is called after the
1020
    declaration of ex.  Note that ex can be the null identifier, indicating
1021
    that the handler is '...'.
1022
*/
1023
 
7 7u83 1024
EXP
1025
begin_catch_stmt(EXP block, IDENTIFIER ex)
2 7u83 1026
{
7 7u83 1027
	/* Construct the result */
1028
	EXP e, d;
1029
	MAKE_exp_handler(type_void, ex, NULL_exp, e);
1030
	COPY_exp(exp_handler_parent(e), block);
1031
	unreached_code = 0;
1032
	unreached_last = 0;
2 7u83 1033
 
7 7u83 1034
	/* Check for '...' handlers */
1035
	d = DEREF_exp(exp_try_block_ellipsis(block));
1036
	if (!IS_NULL_exp(d)) {
1037
		/* Already have a '...' handler */
1038
		report(crt_loc, ERR_except_handle_ellipsis());
1039
		unreached_code = 1;
1040
	} else if (IS_NULL_id(ex)) {
1041
		/* Set the '...' handler if necessary */
1042
		COPY_exp(exp_try_block_ellipsis(block), e);
1043
	} else {
1044
		/* Add to list of other handlers */
1045
		TYPE t0;
1046
		TYPE t, s;
1047
		LIST(EXP) p, q;
1048
		LIST(TYPE) u, v;
2 7u83 1049
 
7 7u83 1050
		/* Check list of handler types */
1051
		u = DEREF_list(exp_try_block_htypes(block));
1052
		t0 = DEREF_type(id_variable_etc_type(ex));
1053
		t = exception_type(t0, 2);
1054
		s = from_type_set(u, t);
1055
		if (!IS_NULL_type(s)) {
1056
			report(crt_loc, ERR_except_handle_unreach(t0, s));
1057
			unreached_code = 1;
1058
		}
1059
		CONS_type(t, NULL_list(TYPE), v);
1060
		u = APPEND_list(u, v);
1061
		COPY_list(exp_try_block_htypes(block), u);
1062
 
1063
		/* Add ex to list of handler expressions */
1064
		p = DEREF_list(exp_try_block_handlers(block));
1065
		CONS_exp(e, NULL_list(EXP), q);
1066
		p = APPEND_list(p, q);
1067
		COPY_list(exp_try_block_handlers(block), p);
2 7u83 1068
	}
7 7u83 1069
	PUSH_exp(e, crt_try_blocks);
1070
	return (e);
2 7u83 1071
}
1072
 
1073
 
1074
/*
1075
    COMPLETE THE CONSTRUCTION OF A CATCH STATEMENT
1076
 
1077
    This routine completes the construction of the catch statement prev by
1078
    filling in the given body statement.
1079
*/
1080
 
7 7u83 1081
EXP
1082
end_catch_stmt(EXP prev, EXP body)
2 7u83 1083
{
7 7u83 1084
	EXP e;
1085
	if (unreached_code) {
1086
		/* Mark unreached statements */
1087
		COPY_type(exp_type(prev), type_bottom);
1088
	} else {
1089
		/* Control reaches end of handler */
1090
		int func;
1091
		e = DEREF_exp(exp_handler_parent(prev));
1092
		func = DEREF_int(exp_try_block_func(e));
1093
		if (func == 2) {
1094
			/* Re-throw current exception */
1095
			e = make_throw_exp(NULL_exp, 0);
1096
			body = add_compound_stmt(body, e);
1097
			COPY_type(exp_type(prev), type_bottom);
1098
		}
2 7u83 1099
	}
7 7u83 1100
	COPY_exp(exp_handler_body(prev), body);
1101
	set_parent_stmt(body, prev);
1102
	POP_exp(e, crt_try_blocks);
1103
	UNUSED(e);
1104
	return (prev);
2 7u83 1105
}
1106
 
1107
 
1108
/*
1109
    CONSTRUCT A THROW ARGUMENT FROM A TYPE
1110
 
1111
    The syntax 'throw t' for a type t is exactly equivalent to 'throw t ()'.
1112
    This routine constructs the argument 't ()'.  n gives the number of types
1113
    defined in t.
1114
*/
1115
 
7 7u83 1116
EXP
1117
make_throw_arg(TYPE t, int n)
2 7u83 1118
{
7 7u83 1119
	EXP e;
1120
	report(crt_loc, ERR_except_throw_type());
1121
	if (n) {
1122
		report(crt_loc, ERR_except_throw_typedef());
1123
	}
1124
	e = make_func_cast_exp(t, NULL_list(EXP));
1125
	return (e);
2 7u83 1126
}
1127
 
1128
 
1129
/*
1130
    CONSTRUCT A THROW EXPRESSION
1131
 
1132
    This routine constructs the expressions 'throw a' and 'throw' (if a is
1133
    the null expression).  Note that a is assigned to a temporary variable
1134
    of its own type.
1135
*/
1136
 
7 7u83 1137
EXP
1138
make_throw_exp(EXP a, int expl)
2 7u83 1139
{
7 7u83 1140
	EXP e;
1141
	EXP b = NULL_exp;
1142
	EXP d = NULL_exp;
1143
	if (!IS_NULL_exp(a)) {
1144
		/* Perform operand conversions on a */
1145
		TYPE t;
1146
		ERROR err;
1147
		a = convert_reference(a, REF_NORMAL);
1148
		t = DEREF_type(exp_type(a));
1149
		if (!IS_type_compound(t)) {
1150
			a = convert_lvalue(a);
1151
			t = DEREF_type(exp_type(a));
1152
		}
1153
		t = exception_type(t, 1);
1154
		IGNORE check_throw(t, 1);
1155
		b = sizeof_exp(t);
1156
		err = check_complete(t);
1157
		if (IS_NULL_err(err)) {
1158
			/* Exception is assigned to temporary variable */
1159
			a = init_assign(t, cv_none, a, &err);
1160
			d = init_default(t, &d, DEFAULT_DESTR, EXTRA_DESTR,
1161
					 &err);
1162
			if (!IS_NULL_err(err)) {
1163
				err = init_error(err, 0);
1164
			}
1165
		}
1166
		if (!IS_NULL_err(err)) {
1167
			/* Report type errors */
1168
			err = concat_error(err, ERR_except_throw_copy());
1169
			report(crt_loc, err);
1170
		}
1171
		a = check_return_exp(a, lex_throw);
1172
	} else {
1173
		/* Check thrown type */
1174
		IGNORE check_throw(NULL_type, 1);
2 7u83 1175
	}
7 7u83 1176
	MAKE_exp_exception(type_bottom, a, b, d, expl, e);
1177
	return (e);
2 7u83 1178
}
1179
 
1180
 
1181
#endif