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 "ctype_ops.h"
64
#include "etype_ops.h"
65
#include "exp_ops.h"
66
#include "hashid_ops.h"
67
#include "id_ops.h"
68
#include "itype_ops.h"
69
#include "member_ops.h"
70
#include "nat_ops.h"
71
#include "nspace_ops.h"
72
#include "off_ops.h"
73
#include "type_ops.h"
74
#include "error.h"
75
#include "catalog.h"
76
#include "option.h"
77
#include "access.h"
78
#include "allocate.h"
79
#include "basetype.h"
80
#include "cast.h"
81
#include "check.h"
82
#include "chktype.h"
83
#include "constant.h"
84
#include "construct.h"
85
#include "convert.h"
86
#include "copy.h"
87
#include "declare.h"
88
#include "derive.h"
89
#include "destroy.h"
90
#include "dump.h"
91
#include "exception.h"
92
#include "expression.h"
93
#include "file.h"
94
#include "function.h"
95
#include "hash.h"
96
#include "identifier.h"
97
#include "initialise.h"
98
#include "lex.h"
99
#include "namespace.h"
100
#include "overload.h"
101
#include "predict.h"
102
#include "statement.h"
103
#include "syntax.h"
104
#include "template.h"
105
#include "typeid.h"
106
 
107
 
108
/*
109
    PERFORM AN ARITHMETIC OPERATION ON AN ARRAY DIMENSION
110
 
111
    This routine calculates the simple arithmetic operation 'a op b'.  Any
112
    conversion errors are suppressed.
113
*/
114
 
7 7u83 115
static EXP
116
make_dim_exp(int op, EXP a, EXP b)
2 7u83 117
{
7 7u83 118
	EXP e;
119
	int et;
120
	if (IS_NULL_exp(a)) {
121
		return (b);
122
	}
123
	if (IS_NULL_exp(b)) {
124
		return (a);
125
	}
126
	et = error_threshold;
127
	error_threshold = ERROR_SERIOUS;
128
	if (op == lex_plus) {
129
		e = make_plus_exp(a, b);
130
	} else {
131
		e = make_mult_exp(op, a, b);
132
	}
133
	error_threshold = et;
134
	return (e);
2 7u83 135
}
136
 
137
 
138
/*
139
    ALLOCATION ROUTINES
140
 
141
    The memory allocation and deallocation routines are only contained in
142
    the C++ producer.
143
*/
144
 
145
#if LANGUAGE_CPP
146
 
147
 
148
/*
149
    BAD ALLOCATION EXCEPTION TYPE
150
 
151
    The variable type_bad_alloc is used to represent the standard exception
152
    type 'std::bad_alloc' thrown when an allocation function fails.  The
153
    list alloc_types is used to record all the function types for simple
154
    allocation functions.
155
*/
156
 
7 7u83 157
static TYPE type_bad_alloc = NULL_type;
158
static LIST(TYPE) alloc_types = NULL_list(TYPE);
2 7u83 159
 
160
 
161
/*
162
    SET THE BAD ALLOCATION EXCEPTION TYPE
163
 
164
    This routine sets type_bad_alloc to be t, updating the exception
165
    specifiers of any simple allocation functions previously declared.
166
*/
167
 
7 7u83 168
static void
169
set_bad_alloc(TYPE t)
2 7u83 170
{
7 7u83 171
	if (!IS_NULL_type(t)) {
172
		LIST(TYPE)p = alloc_types;
173
		while (!IS_NULL_list(p)) {
174
			TYPE s = DEREF_type(HEAD_list(p));
175
			LIST(TYPE)e = DEREF_list(type_func_except(s));
176
			if (!IS_NULL_list(e) && !EQ_list(e, univ_type_set)) {
177
				/* Change 'throw ( X )' to
178
				 * 'throw ( std::bad_alloc )' */
179
				e = TAIL_list(e);
180
				CONS_type(t, e, e);
181
				COPY_list(type_func_except(s), e);
182
			}
183
			p = TAIL_list(p);
184
		}
185
		type_bad_alloc = t;
2 7u83 186
	}
7 7u83 187
	return;
2 7u83 188
}
189
 
190
 
191
/*
192
    CHECK AN ALLOCATION FUNCTION
193
 
194
    This routine checks whether the function type t is a suitable
195
    declaration for the allocation or deallocation function given by id.
196
    mem is true for member functions.  The basic forms allowed are:
197
 
198
	void *operator new ( size_t, [further parameters] ) ;
199
	void *operator new[] ( size_t, [further parameters] ) ;
200
	void operator delete ( void *, [further parameters] ) ;
201
	void operator delete[] ( void *, [further parameters] ) ;
202
 
203
    Before the introduction of placement delete the only further parameters
204
    allowed in a deallocation function was a single 'size_t' for member
205
    functions.  Note that template functions are allowed (indicated by
206
    templ), but they must have the form above and at least one further
207
    parameter.
208
*/
209
 
7 7u83 210
TYPE
211
check_allocator(TYPE t, IDENTIFIER id, int mem, int templ)
2 7u83 212
{
7 7u83 213
	if (IS_type_templ(t)) {
214
		/* Allow for template types */
215
		TYPE s = DEREF_type(type_templ_defn(t));
216
		s = check_allocator(s, id, mem, templ + 1);
217
		COPY_type(type_templ_defn(t), s);
2 7u83 218
 
219
	} else {
7 7u83 220
		/* Find the operator */
221
		HASHID nm = DEREF_hashid(id_name(id));
222
		int op = DEREF_int(hashid_op_lex(nm));
2 7u83 223
 
7 7u83 224
		/* Decompose function type */
225
		TYPE s;
226
		TYPE r = DEREF_type(type_func_ret(t));
227
		LIST(TYPE)p = DEREF_list(type_func_ptypes(t));
228
		LIST(IDENTIFIER)q = DEREF_list(type_func_pids(t));
229
		int ell = DEREF_int(type_func_ellipsis(t));
230
		if (!IS_NULL_list(p)) {
231
			s = DEREF_type(HEAD_list(p));
232
			p = TAIL_list(p);
233
		} else {
234
			s = type_void;
235
		}
2 7u83 236
 
7 7u83 237
		if (op == lex_new || op == lex_new_Harray) {
238
			/* Allocator should return 'void *' */
239
			TYPE u = type_void_star;
240
			if (!eq_type(r, u)) {
241
				report(crt_loc, ERR_basic_stc_alloc_ret(nm, u));
242
			}
2 7u83 243
 
7 7u83 244
			/* First parameter should be 'size_t' */
245
			u = type_size_t;
246
			if (!eq_type(s, u)) {
247
				report(crt_loc, ERR_basic_stc_alloc_p1(nm, u));
248
			}
2 7u83 249
 
7 7u83 250
			/* First parameter can't have a default argument */
251
			if (!IS_NULL_list(q)) {
252
				IDENTIFIER pid = DEREF_id(HEAD_list(q));
253
				EXP darg = DEREF_exp(id_parameter_init(pid));
254
				if (!IS_NULL_exp(darg)) {
255
					report(crt_loc,
256
					       ERR_basic_stc_alloc_d1(nm));
257
				}
258
			}
2 7u83 259
 
7 7u83 260
			/* Template functions should have another parameter */
261
			if (templ && IS_NULL_list(p)) {
262
				report(crt_loc, ERR_basic_stc_alloc_templ(nm));
263
			}
2 7u83 264
 
7 7u83 265
		} else {
266
			/* Deallocator should return 'void' */
267
			TYPE u = type_void;
268
			if (!eq_type(r, u)) {
269
				report(crt_loc, ERR_basic_stc_alloc_ret(nm, u));
270
			}
2 7u83 271
 
7 7u83 272
			/* First argument should be 'void *' */
273
			u = type_void_star;
274
			if (!eq_type(s, u)) {
275
				report(crt_loc, ERR_basic_stc_alloc_p1(nm, u));
276
			}
2 7u83 277
 
7 7u83 278
			/* Template functions should have another parameter */
279
			if (templ && IS_NULL_list(p)) {
280
				report(crt_loc, ERR_basic_stc_alloc_templ(nm));
281
			}
282
 
283
			/* Second argument may be 'size_t' (old form) */
284
			if (mem && !IS_NULL_list(p)) {
285
				u = type_size_t;
286
				s = DEREF_type(HEAD_list(p));
287
				if (!eq_type(s, u)) {
288
					report(crt_loc,
289
					       ERR_basic_stc_alloc_p2(nm, u));
290
				}
291
				p = TAIL_list(p);
292
			}
293
 
294
			/* No further arguments allowed (old form) */
295
			if (!IS_NULL_list(p) || ell) {
296
				report(crt_loc, ERR_basic_stc_alloc_pn(nm));
297
			}
2 7u83 298
		}
299
 
7 7u83 300
		/* Look up 'std::bad_alloc' */
301
		s = type_bad_alloc;
302
		if (IS_NULL_type(s)) {
303
			s = find_std_type("bad_alloc", 1, 0);
304
			set_bad_alloc(s);
305
		}
2 7u83 306
	}
7 7u83 307
	return (t);
2 7u83 308
}
309
 
310
 
311
/*
312
    CHECK AN ALLOCATOR DECLARATION
313
 
314
    This routine checks the allocator declaration id.  This should either
315
    be a class member or a member of the global namespace with external
316
    linkage.  alloc is 1 for allocator functions and 2 for deallocation
317
    functions.
318
*/
319
 
7 7u83 320
void
321
recheck_allocator(IDENTIFIER id, int alloc)
2 7u83 322
{
7 7u83 323
	NAMESPACE ns = DEREF_nspace(id_parent(id));
324
	if (alloc == 2) {
325
		IDENTIFIER over = DEREF_id(id_function_etc_over(id));
326
		if (!IS_NULL_id(over)) {
327
			/* Can't overload 'operator delete' (old form) */
328
			report(crt_loc, ERR_basic_stc_dealloc_over(over));
329
		}
2 7u83 330
	}
7 7u83 331
	if (!IS_NULL_nspace(ns)) {
332
		switch (TAG_nspace(ns)) {
333
		case nspace_global_tag: {
334
			/* Declared in global namespace */
335
			DECL_SPEC ds = DEREF_dspec(id_storage(id));
336
			if (ds & dspec_static) {
337
				report(crt_loc, ERR_basic_stc_alloc_link(id));
2 7u83 338
			}
7 7u83 339
			if (alloc == 1 && crt_file_type == 1) {
340
				/* Check for built-in allocation functions */
341
				TYPE t = DEREF_type(id_function_type(id));
342
				if (IS_type_func(t)) {
343
					LIST(TYPE)p;
344
					p = DEREF_list(type_func_ptypes(t));
345
					if (LENGTH_list(p) == 1) {
346
						CONS_type(t, alloc_types,
347
							  alloc_types);
348
					}
349
				}
350
			}
351
			break;
2 7u83 352
		}
7 7u83 353
		case nspace_ctype_tag: {
354
			/* Declared in class namespace */
355
			break;
356
		}
357
		default: {
358
			/* Declared in other namespace */
359
			report(crt_loc, ERR_basic_stc_alloc_nspace(id));
360
			break;
361
		}
362
		}
2 7u83 363
	}
7 7u83 364
	return;
2 7u83 365
}
366
 
367
 
368
/*
369
    FIND A DEALLOCATION FUNCTION
370
 
371
    This routine selects a deallocation function from the set of overloaded
372
    functions id.  If pid is not the null identifier then it is an
373
    allocation function for which a matching placement delete is required.
374
    mem is true for member functions.
375
*/
376
 
7 7u83 377
static IDENTIFIER
378
resolve_delete(IDENTIFIER id, IDENTIFIER pid, int mem)
2 7u83 379
{
7 7u83 380
	int eq = 0;
381
	IDENTIFIER rid;
382
	LIST(TYPE)p;
383
	TYPE fn = type_temp_func;
384
	LIST(IDENTIFIER)pids = NULL_list(IDENTIFIER);
385
	COPY_type(type_func_ret(fn), type_void);
386
	COPY_cv(type_func_mqual(fn), cv_none);
2 7u83 387
 
7 7u83 388
	/* Try placement delete */
389
	if (!IS_NULL_id(pid)) {
390
		TYPE t = DEREF_type(id_function_etc_type(pid));
391
		if (IS_type_func(t)) {
392
			p = DEREF_list(type_func_ptypes(t));
393
			if (!IS_NULL_list(p)) {
394
				p = TAIL_list(p);
395
			}
396
			CONS_type(type_void_star, p, p);
397
			COPY_list(type_func_ptypes(fn), p);
398
			COPY_list(type_func_mtypes(fn), p);
399
			rid = resolve_func(id, fn, 1, 1, pids, &eq);
400
			COPY_list(type_func_ptypes(fn), NULL_list(TYPE));
401
			COPY_list(type_func_mtypes(fn), NULL_list(TYPE));
402
			DESTROY_CONS_type(destroy, t, p, p);
403
			UNUSED(p);
404
			UNUSED(t);
405
			if (!IS_NULL_id(rid)) {
406
				return (rid);
407
			}
408
		}
409
		return (NULL_id);
2 7u83 410
	}
411
 
7 7u83 412
	/* Try 'void ( void * )' */
413
	CONS_type(type_void_star, NULL_list(TYPE), p);
414
	COPY_list(type_func_ptypes(fn), p);
415
	COPY_list(type_func_mtypes(fn), p);
416
	rid = resolve_func(id, fn, 0, 1, pids, &eq);
417
	COPY_list(type_func_ptypes(fn), NULL_list(TYPE));
418
	COPY_list(type_func_mtypes(fn), NULL_list(TYPE));
419
	DESTROY_list(p, SIZE_type);
420
	if (!IS_NULL_id(rid)) {
421
		return (rid);
422
	}
2 7u83 423
 
7 7u83 424
	/* Try 'void ( void *, size_t )' */
425
	if (mem) {
426
		CONS_type(type_size_t, NULL_list(TYPE), p);
427
		CONS_type(type_void_star, p, p);
428
		COPY_list(type_func_ptypes(fn), p);
429
		COPY_list(type_func_mtypes(fn), p);
430
		rid = resolve_func(id, fn, 0, 1, pids, &eq);
431
		COPY_list(type_func_ptypes(fn), NULL_list(TYPE));
432
		COPY_list(type_func_mtypes(fn), NULL_list(TYPE));
433
		DESTROY_list(p, SIZE_type);
434
		if (!IS_NULL_id(rid)) {
435
			return (rid);
436
		}
437
	}
438
	return (NULL_id);
2 7u83 439
}
440
 
441
 
442
/*
443
    LOOK UP AN ALLOCATOR FUNCTION
444
 
445
    This routine looks up the allocator function 'operator op'.  If b is
446
    true then the global namespace is checked first, otherwise if t is a
447
    class type then the members of t are checked, finally the allocator
448
    currently in scope is checked.  If option new_array is false and op
449
    is an array allocator, then the corresponding object allocator is
450
    returned, except if t is a class which has 'operator op' declared.
451
*/
452
 
7 7u83 453
IDENTIFIER
454
find_allocator(TYPE t, int op, int b, IDENTIFIER pid)
2 7u83 455
{
7 7u83 456
	int dealloc = 0;
457
	IDENTIFIER id = NULL_id;
458
	HASHID nm = lookup_op(op);
459
	HASHID nm_real = nm;
2 7u83 460
 
7 7u83 461
	/* Allow for pre-ISO dialect */
462
	switch (op) {
463
	case lex_new: {
464
		break;
2 7u83 465
	}
7 7u83 466
	case lex_new_Harray: {
467
		if (!option(OPT_new_array)) {
468
			nm = lookup_op(lex_new);
469
			t = type_error;
470
		}
471
		break;
2 7u83 472
	}
7 7u83 473
	case lex_delete: {
474
		dealloc = 1;
475
		break;
2 7u83 476
	}
7 7u83 477
	case lex_delete_Harray: {
478
		if (!option(OPT_new_array)) {
479
			nm = lookup_op(lex_delete);
480
			t = type_error;
481
		}
482
		dealloc = 1;
483
		break;
2 7u83 484
	}
485
	}
486
 
7 7u83 487
	if (b) {
488
		/* Try global scope ... */
489
		NAMESPACE ns = global_namespace;
490
		MEMBER mem = search_member(ns, nm, 0);
491
		if (!IS_NULL_member(mem)) {
492
			id = DEREF_id(member_id(mem));
493
			if (!IS_NULL_id(id) && dealloc) {
494
				id = resolve_delete(id, pid, 0);
495
			}
496
		}
2 7u83 497
 
7 7u83 498
	} else {
499
		/* Try class members ... */
500
		if (IS_type_compound(t)) {
501
			CLASS_TYPE ct = DEREF_ctype(type_compound_defn(t));
502
			NAMESPACE ns = DEREF_nspace(ctype_member(ct));
503
			id = search_field(ns, nm_real, 0, 0);
504
			if (IS_NULL_id(id) && !EQ_hashid(nm, nm_real)) {
505
				id = search_field(ns, nm, 0, 0);
506
			}
507
			if (!IS_NULL_id(id) && IS_id_ambig(id)) {
508
				id = report_ambiguous(id, 0, 1, 1);
509
			}
510
			if (!IS_NULL_id(id) && dealloc) {
511
				id = resolve_delete(id, pid, 1);
512
			}
513
		}
514
 
515
		/* Try current scope ... */
516
		if (IS_NULL_id(id)) {
517
			id = find_op_id(nm);
518
			if (!IS_NULL_id(id) && dealloc) {
519
				id = resolve_delete(id, pid, 0);
520
			}
521
		}
2 7u83 522
	}
523
 
7 7u83 524
	/* Return function */
525
	if (!IS_NULL_id(id)) {
526
		if (IS_id_function_etc(id)) {
527
			/* Function found */
528
			return (id);
529
		}
530
		if (is_ambiguous_func(id)) {
531
			if (dealloc) {
532
				/* Can't do overload resolution on delete */
533
				id = report_ambiguous(id, 0, 1, 1);
534
				return (id);
535
			}
536
			return (id);
537
		}
538
		if (!IS_id_dummy(id)) {
539
			/* Result is not a function */
540
			report(crt_loc, ERR_over_oper_func(id));
541
		}
2 7u83 542
	}
7 7u83 543
	if (IS_NULL_id(pid)) {
544
		/* Allocation functions not declared */
545
		report(crt_loc, ERR_lib_builtin(NULL_string, nm));
2 7u83 546
	}
7 7u83 547
	return (NULL_id);
2 7u83 548
}
549
 
550
 
551
/*
552
    CONSTRUCT A TEMPLATE DEPENDENT DELETE EXPRESSION
553
 
554
    This routine constructs a delete expression in the case where the
555
    expression type depends on a template parameter.
556
*/
557
 
7 7u83 558
static EXP
559
make_templ_delete(int op, int b, EXP a)
2 7u83 560
{
7 7u83 561
	EXP e;
562
	if (b) {
563
		/* Allow for '::delete' */
564
		if (op == lex_delete) {
565
			op = lex_delete_Hfull;
566
		} else {
567
			op = lex_delete_Harray_Hfull;
568
		}
2 7u83 569
	}
7 7u83 570
	MAKE_exp_op(type_void, op, a, NULL_exp, e);
571
	return (e);
2 7u83 572
}
573
 
574
 
575
/*
576
    CONSTRUCT A PLACEMENT DELETE EXPRESSION
577
 
578
    This routine constructs the expressions 'delete a' and 'delete [] a'
579
    (as indicated by op).  b indicates whether the expression was actually
580
    '::delete'.  pid is used in placement delete expressions to give the
581
    corresponding allocation function (place then gives the extra
582
    arguments), otherwise it is the null identifier.
583
*/
584
 
7 7u83 585
static EXP
586
placement_delete(int op, int b, EXP a, IDENTIFIER pid, LIST(EXP)place)
2 7u83 587
{
7 7u83 588
	int i;
589
	EXP e, c;
590
	TYPE t, p;
591
	IDENTIFIER id;
592
	unsigned npids;
593
	EXP d = NULL_exp;
594
	int need_cast = 1;
595
	int v = EXTRA_DESTR;
596
	ERROR err = NULL_err;
597
	LIST(EXP)args = NULL_list(EXP);
2 7u83 598
 
7 7u83 599
	/* Do operand conversion */
600
	a = convert_reference(a, REF_NORMAL);
601
	t = DEREF_type(exp_type(a));
602
	if (IS_type_compound(t)) {
603
		/* Conversion of class to pointer */
604
		c = convert_gen(CTYPE_PTR, a, &err);
605
		if (!IS_NULL_exp(c)) {
606
			if (!IS_NULL_err(err)) {
607
				err = concat_error(err,
608
						   ERR_expr_delete_conv(op));
609
				report(crt_loc, err);
610
			}
611
			a = c;
612
		}
2 7u83 613
	}
614
 
7 7u83 615
	/* Check operand type */
616
	a = convert_lvalue(a);
617
	t = DEREF_type(exp_type(a));
618
	if (IS_type_ptr(t)) {
619
		CV_SPEC cv;
620
		int arr = 0;
621
		p = DEREF_type(type_ptr_sub(t));
622
		if (is_templ_depend(p)) {
623
			e = make_templ_delete(op, b, a);
624
			return (e);
625
		}
626
		if (IS_type_top_etc(p)) {
627
			/* Check for 'void *' */
628
			report(crt_loc, ERR_expr_delete_void(op, t));
629
			need_cast = 0;
630
		} else {
631
			/* Check for incomplete types */
632
			err = check_object(p);
633
			if (!IS_NULL_err(err)) {
634
				err = concat_error(err,
635
						   ERR_expr_delete_obj(op));
636
				report(crt_loc, err);
2 7u83 637
			}
7 7u83 638
			err = check_incomplete(p);
639
			if (!IS_NULL_err(err)) {
640
				err = concat_error(err,
641
						   ERR_expr_delete_incompl(op));
642
				report(crt_loc, err);
643
				if (IS_type_compound(p)) {
644
					/* Mark incomplete class types */
645
					CLASS_TYPE ct =
646
					    DEREF_ctype(type_compound_defn(p));
647
					CLASS_USAGE cu =
648
					    DEREF_cusage(ctype_usage(ct));
649
					cu |= cusage_destr;
650
					if (b == 0) {
651
						if (op == lex_delete) {
652
							cu |= cusage_delete;
653
						} else {
654
							cu |= cusage_delete_array;
655
						}
656
					}
657
					COPY_cusage(ctype_usage(ct), cu);
658
				}
659
			}
2 7u83 660
		}
7 7u83 661
		while (IS_type_array(p)) {
662
			/* Allow for multi-dimensional arrays */
663
			arr = 1;
664
			p = DEREF_type(type_array_sub(p));
665
		}
666
		if (arr) {
667
			MAKE_type_ptr(cv_none, p, t);
668
		}
669
		cv = DEREF_cv(type_qual(p));
670
		if (cv & cv_const) {
671
			/* Check for deleting const objects */
672
			report(crt_loc, ERR_expr_delete_const(cv));
673
		}
674
	} else {
675
		/* Operand should be a pointer */
676
		if (is_templ_type(t)) {
677
			e = make_templ_delete(op, b, a);
678
			return (e);
679
		}
680
		if (!IS_type_error(t)) {
681
			report(crt_loc, ERR_expr_delete_ptr(op, t));
682
		}
683
		MAKE_exp_value(type_void, e);
684
		return (e);
2 7u83 685
	}
7 7u83 686
 
687
	/* Find destructors */
688
	err = NULL_err;
689
	i = (know_type(a) == 1 ? DEFAULT_DESTR : DEFAULT_DELETE);
690
	if (op == lex_delete && b == 0 && IS_NULL_id(pid)) {
691
		/* delete may be called via the destructor */
692
		v = (EXTRA_DESTR | EXTRA_DELETE);
2 7u83 693
	}
7 7u83 694
	d = init_default(p, &d, i, v, &err);
695
	if (!IS_NULL_err(err)) {
696
		report(crt_loc, err);
2 7u83 697
	}
7 7u83 698
	if (IS_NULL_exp(d)) {
699
		v = EXTRA_DESTR;
2 7u83 700
	}
701
 
7 7u83 702
	/* Find deallocation function */
703
	id = find_allocator(p, op, b, pid);
704
	if (!IS_NULL_id(id)) {
705
		LIST(IDENTIFIER)pids;
706
		TYPE fn = DEREF_type(id_function_etc_type(id));
707
		while (IS_type_templ(fn)) {
708
			fn = DEREF_type(type_templ_defn(fn));
709
		}
710
		pids = DEREF_list(type_func_pids(fn));
711
		npids = LENGTH_list(pids);
712
	} else {
713
		npids = 0;
2 7u83 714
	}
715
 
7 7u83 716
	/* Create dummy expression for first argument */
717
	MAKE_exp_dummy(t, a, LINK_NONE, NULL_off, 1, a);
2 7u83 718
 
7 7u83 719
	/* Create size variables if necessary */
720
	if (op == lex_delete || !IS_type_compound(p)) {
721
		c = NULL_exp;
722
		e = a;
2 7u83 723
	} else {
7 7u83 724
		OFFSET off;
725
		TYPE s = type_size_t;
726
		if (npids == 1 && IS_NULL_exp(d)) {
727
			MAKE_exp_null(s, c);
728
		} else {
729
			MAKE_exp_dummy(s, NULL_exp, LINK_NONE, NULL_off, 0, c);
730
		}
731
		MAKE_off_extra(p, -1, off);
732
		MAKE_exp_add_ptr(t, a, off, 0, e);
2 7u83 733
	}
734
 
7 7u83 735
	/* Create extra arguments */
736
	if (IS_NULL_id(pid)) {
737
		if (npids >= 2) {
738
			/* Pass size as extra argument */
739
			EXP sz = sizeof_exp(p);
740
			if (!IS_NULL_exp(c)) {
741
				EXP ex;
742
				OFFSET off;
743
				sz = make_dim_exp(lex_star, sz, c);
744
				MAKE_off_extra(p, 1, off);
745
				MAKE_exp_offset_size(type_size_t, off,
746
						     type_char, 1, ex);
747
				sz = make_dim_exp(lex_plus, sz, ex);
748
			}
749
			CONS_exp(sz, args, args);
750
		}
751
	} else {
752
		/* Copy placement arguments */
753
		/* NOT YET IMPLEMENTED */
754
		args = copy_exp_list(place, NULL_type, NULL_type);
2 7u83 755
	}
756
 
7 7u83 757
	/* Construct function call */
758
	if (!IS_NULL_id(id)) {
759
		if (need_cast) {
760
			MAKE_exp_cast(type_void_star, CONV_PTR_VOID, e, e);
761
		}
762
		CONS_exp(e, args, args);
763
		if (IS_id_stat_mem_func(id)) {
764
			/* Allow for static member functions */
765
			CONS_exp(NULL_exp, args, args);
766
		}
767
		use_func_id(id, 0, suppress_usage);
768
		e = apply_func_id(id, qual_none, NULL_graph, args);
769
		if (v == (EXTRA_DESTR | EXTRA_DELETE)) {
770
			/* 'operator delete' called via destructor */
771
			MAKE_exp_paren(type_void, e, e);
772
		}
773
	} else {
774
		e = NULL_exp;
2 7u83 775
	}
776
 
7 7u83 777
	/* Construct result */
778
	MAKE_exp_dealloc(type_void, d, e, a, c, e);
779
	return (e);
2 7u83 780
}
781
 
782
 
783
/*
784
    CREATE A SIMPLE DELETE EXPRESSION
785
 
786
    This routine is a special case of placement_delete which handles the
787
    explicit delete expressions.
788
*/
789
 
7 7u83 790
EXP
791
make_delete_exp(int op, int b, EXP a)
2 7u83 792
{
7 7u83 793
	EXP e = placement_delete(op, b, a, NULL_id, NULL_list(EXP));
794
	return (e);
2 7u83 795
}
796
 
797
 
798
/*
799
    DELETE ARRAY ANACHRONISM
800
 
801
    It used to be necessary to include the size of the array being deleted
802
    in 'delete []'.  This routine deals with this anachronism.
803
*/
804
 
7 7u83 805
void
806
old_delete_array(EXP e)
2 7u83 807
{
7 7u83 808
	/* Check that e is a suitable array bound */
809
	int op = lex_delete_Harray;
810
	IGNORE make_new_array_dim(e);
2 7u83 811
 
7 7u83 812
	/* But complain just the same */
813
	report(crt_loc, ERR_expr_delete_array(op));
814
	return;
2 7u83 815
}
816
 
817
 
818
/*
819
    CONSTRUCT A NEW ARRAY BOUND
820
 
821
    In a new-declarator the first array bound can be a variable expression,
822
    whereas all subsequent array bounds must be constant expressions as
823
    normal.  This routine is a version of make_array_dim designed exclusively
824
    to deal with this first bound.  Note that the result is not strictly
825
    a legal NAT and is only used to pass the bound information to
826
    make_new_exp, where it is prompty destroyed.
827
*/
828
 
7 7u83 829
NAT
830
make_new_array_dim(EXP e)
2 7u83 831
{
7 7u83 832
	NAT n;
833
	if (IS_exp_int_lit(e)) {
834
		/* Get the value if e is constant */
835
		n = DEREF_nat(exp_int_lit_nat(e));
836
	} else {
837
		/* Make dummy literal */
838
		MAKE_nat_calc(e, n);
839
	}
840
	return (n);
2 7u83 841
}
842
 
843
 
844
/*
845
    CONSTRUCT A TEMPLATE DEPENDENT NEW EXPRESSION
846
 
847
    This routine constructs a new expression in the case where the object
848
    type is a template parameter.  t gives the given type with array
849
    dimension d, while p is the pointer type.
850
*/
851
 
7 7u83 852
static EXP
853
make_templ_new(TYPE t, EXP d, TYPE p, int b, LIST(EXP)place, EXP init)
2 7u83 854
{
7 7u83 855
	EXP e;
856
	int op = (b ? lex_new_Hfull : lex_new);
857
	CONS_exp(init, place, place);
858
	CONS_exp(d, place, place);
859
	MAKE_exp_value(t, e);
860
	CONS_exp(e, place, place);
861
	MAKE_exp_opn(p, op, place, e);
862
	return (e);
2 7u83 863
}
864
 
865
 
866
/*
867
    CONSTRUCT A NEW EXPRESSION
868
 
869
    This routine constructs the expression 'new ( place ) ( t ) ( init )',
870
    where place is a possibly empty list of expressions and init is
871
    a new-initialiser expression.  n gives the number of types defined
872
    in t and b indicates whether the expression was actually '::new'.
873
*/
874
 
7 7u83 875
EXP
876
make_new_exp(TYPE t, int n, int b, LIST(EXP)place, EXP init)
2 7u83 877
{
7 7u83 878
	EXP e;
879
	EXP sz;
880
	TYPE ret;
881
	TYPE u = t;
882
	IDENTIFIER id;
883
	EXP v = NULL_exp;
884
	NAT d = NULL_nat;
885
	EXP gc = NULL_exp;
886
	EXP arr = NULL_exp;
887
	int need_cast = 1;
888
	int op = lex_new;
889
	int opd = lex_delete;
890
	LIST(EXP)placement = NULL_list(EXP);
2 7u83 891
 
7 7u83 892
	/* Check for type definitions */
893
	if (n) {
894
		report(crt_loc, ERR_expr_new_typedef());
895
	}
2 7u83 896
 
7 7u83 897
	/* Find result type (a pointer to t) and size of t */
898
	if (IS_type_array(t)) {
899
		/* Array form */
900
		EXP c1;
901
		TYPE tsz = type_size_t;
902
		TYPE s = DEREF_type(type_array_sub(t));
903
		MAKE_type_ptr(cv_none, s, ret);
2 7u83 904
 
7 7u83 905
		/* Check initial array bound */
906
		d = DEREF_nat(type_array_size(t));
907
		if (IS_nat_calc(d)) {
908
			/* Variable sized array */
909
			TYPE tc;
910
			unsigned cc;
911
			c1 = DEREF_exp(nat_calc_value(d));
912
			tc = DEREF_type(exp_type(c1));
913
			cc = type_category(&tc);
914
			if (!IS_TYPE_INT(cc) && !IS_TYPE_TEMPL(cc)) {
915
				/* Should have integral type */
916
				if (!IS_TYPE_ERROR(cc)) {
917
					report(crt_loc, ERR_expr_new_dim(tc));
918
				}
919
			}
920
			if (!in_template_decl) {
921
				/* Convert dimension to type 'size_t' */
922
				c1 = cast_exp(tsz, c1, KILL_err, CAST_STATIC);
923
			}
924
			u = s;
925
			v = c1;
926
		} else {
927
			c1 = calc_nat_value(d, tsz);
2 7u83 928
		}
7 7u83 929
 
930
		/* Find overall array size */
931
		if (IS_type_array(s)) {
932
			EXP c2 = sizeof_array(&s, tsz);
933
			c1 = make_dim_exp(lex_star, c2, c1);
934
		}
935
		if (IS_exp_int_lit(c1)) {
936
			/* Constant sized array */
937
			if (IS_type_compound(s)) {
938
				TYPE tc = DEREF_type(exp_type(c1));
939
				MAKE_exp_dummy(tc, c1, LINK_NONE, NULL_off, 0,
940
					       arr);
941
			}
942
			sz = sizeof_exp(t);
943
			d = DEREF_nat(exp_int_lit_nat(c1));
944
		} else {
945
			/* Variable sized array */
946
			TYPE tc = DEREF_type(exp_type(c1));
947
			MAKE_exp_dummy(tc, c1, LINK_NONE, NULL_off, 0, arr);
948
			sz = sizeof_exp(s);
949
			sz = make_dim_exp(lex_star, sz, arr);
950
			MAKE_nat_calc(c1, d);
951
			if (!IS_type_compound(s)) {
952
				arr = NULL_exp;
953
			}
954
		}
955
 
956
		/* Add extra array space */
957
		if (IS_type_compound(s)) {
958
			OFFSET off;
959
			MAKE_off_extra(s, 1, off);
960
			MAKE_exp_offset_size(tsz, off, type_char, 1, c1);
961
			sz = make_dim_exp(lex_plus, sz, c1);
962
		}
963
		op = lex_new_Harray;
964
		opd = lex_delete_Harray;
965
		t = s;
2 7u83 966
	} else {
7 7u83 967
		/* Normal form */
968
		if (IS_type_top_etc(t)) {
969
			need_cast = 0;
970
		}
971
		MAKE_type_ptr(cv_none, t, ret);
972
		sz = sizeof_exp(t);
2 7u83 973
	}
974
 
7 7u83 975
	/* Do reference conversions */
976
	if (!IS_NULL_list(place)) {
977
		place = convert_args(place);
978
		placement = place;
2 7u83 979
	}
980
 
7 7u83 981
	/* Check for template parameters */
982
	if (is_templ_type(t)) {
983
		e = make_templ_new(u, v, ret, b, place, init);
984
		return (e);
2 7u83 985
	}
986
 
7 7u83 987
	/* Add 'sizeof ( t )' to the start of placement */
988
	CONS_exp(sz, place, place);
2 7u83 989
 
7 7u83 990
	/* Call allocator function */
991
	id = find_allocator(t, op, b, NULL_id);
992
	if (IS_NULL_id(id)) {
993
		e = make_error_exp(0);
994
		return (e);
995
	}
996
	if (IS_id_stat_mem_func(id)) {
997
		CONS_exp(NULL_exp, place, place);
998
	}
999
	id = resolve_call(id, place, qual_none, 0);
1000
	use_func_id(id, 0, suppress_usage);
1001
	e = apply_func_id(id, qual_none, NULL_graph, place);
1002
	if (need_cast) {
1003
		MAKE_exp_cast(ret,(CONV_PTR_VOID | CONV_REVERSE), e, e);
1004
	}
2 7u83 1005
 
7 7u83 1006
	/* Deal with array initialisers */
1007
	if (!IS_NULL_exp(init)) {
1008
		EXP a0 = new_try_body(init);
1009
		if (IS_NULL_exp(a0)) {
1010
			/* Can happen with templates */
1011
			init = NULL_exp;
1012
		} else {
1013
			if (!IS_NULL_nat(d)) {
1014
				EXP a = DEREF_exp(exp_assign_arg(a0));
1015
				MAKE_type_array(cv_none, t, d, t);
1016
				MAKE_exp_nof(t, NULL_exp, d, a, NULL_exp, a);
1017
				COPY_exp(exp_assign_arg(a0), a);
1018
				a = DEREF_exp(exp_assign_ref(a0));
1019
				COPY_type(exp_type(a), t);
1020
				COPY_type(exp_type(a0), t);
1021
				/* NOT YET IMPLEMENTED - destructors of
1022
				 * temporaries */
1023
			}
1024
		}
1025
	}
2 7u83 1026
 
7 7u83 1027
	/* Deal with clean-up routine */
1028
	if (!IS_NULL_exp(init)) {
1029
		EXP a;
1030
		int du = do_dump;
1031
		int ac = do_access_checks;
1032
		do_dump = 0;
1033
		do_access_checks = 0;
1034
		MAKE_exp_value(ret, a);
1035
		if (IS_NULL_list(placement)) {
1036
			id = NULL_id;
1037
		}
1038
		gc = placement_delete(opd, b, a, id, placement);
1039
		do_access_checks = ac;
1040
		do_dump = du;
2 7u83 1041
	}
1042
 
7 7u83 1043
	/* Return the result */
1044
	MAKE_exp_alloc(ret, e, init, gc, arr, e);
1045
	return (e);
2 7u83 1046
}
1047
 
1048
 
1049
/*
1050
    CREATE A NEW-INITIALISER
1051
 
1052
    This routine creates a new-initialiser expression of type t from the
1053
    expression list p.
1054
*/
1055
 
7 7u83 1056
EXP
1057
make_new_init(TYPE t, LIST(EXP)p, int init)
2 7u83 1058
{
7 7u83 1059
	EXP e;
1060
	int op = lex_new;
1061
	ERROR err = check_complete(t);
1062
	if (!IS_NULL_err(err)) {
1063
		/* Type should be complete */
1064
		err = concat_error(err, ERR_expr_new_incompl());
1065
		report(crt_loc, err);
2 7u83 1066
	}
7 7u83 1067
	err = check_abstract(t);
1068
	if (!IS_NULL_err(err)) {
1069
		/* Type can't be abstract */
1070
		err = concat_error(err, ERR_expr_new_abstract());
1071
		report(crt_loc, err);
1072
		err = NULL_err;
2 7u83 1073
	}
7 7u83 1074
	while (IS_type_array(t)) {
1075
		/* Step over array components */
1076
		op = lex_new_Harray;
1077
		if (init) {
1078
			report(crt_loc, ERR_expr_new_array_init(op));
1079
			init = 0;
1080
		}
1081
		t = DEREF_type(type_array_sub(t));
2 7u83 1082
	}
7 7u83 1083
	p = convert_args(p);
1084
	if (is_templ_type(t)) {
1085
		if (op == lex_new_Harray) {
1086
			/* Create dummy array type */
1087
			NAT n = small_nat[1];
1088
			MAKE_type_array(cv_none, t, n, t);
1089
		}
1090
		if (init) {
1091
			MAKE_exp_opn(t, lex_compute, p, e);
1092
		} else {
1093
			MAKE_exp_op(t, lex_compute, NULL_exp, NULL_exp, e);
1094
		}
2 7u83 1095
	} else {
7 7u83 1096
		if (init) {
1097
			e = init_constr(t, p, &err);
1098
		} else {
1099
			e = init_empty(t, cv_none, 0, &err);
1100
		}
1101
		if (!IS_NULL_err(err)) {
1102
			/* Report conversion errors */
1103
			err = concat_error(ERR_expr_new_init(op), err);
1104
			report(crt_loc, err);
1105
		}
1106
		if (!IS_NULL_exp(e)) {
1107
			/* Assign value to dummy expression */
1108
			EXP a;
1109
			MAKE_exp_dummy(t, NULL_exp, LINK_NONE, NULL_off, 1, a);
1110
			MAKE_exp_assign(t, a, e, e);
1111
		}
2 7u83 1112
	}
7 7u83 1113
	return (e);
2 7u83 1114
}
1115
 
1116
 
1117
/*
1118
    BEGIN A NEW-INITIALISER TRY BLOCK
1119
 
1120
    Each new-initialiser is enclosed in a dummy try block.  This is because
1121
    if the initialiser throws an exception it is necessary to catch it,
1122
    delete the memory just allocated, and then re-throw the exception to
1123
    the enclosing real handler.
1124
*/
1125
 
7 7u83 1126
EXP
1127
begin_new_try(void)
2 7u83 1128
{
7 7u83 1129
	EXP a = begin_try_stmt(0);
1130
	EXP b = begin_compound_stmt(2);
1131
	COPY_exp(exp_try_block_body(a), b);
1132
	return (a);
2 7u83 1133
}
1134
 
1135
 
1136
/*
1137
    END A NEW-INITIALISER TRY BLOCK
1138
 
1139
    This routine adds the new-initialiser expression b to the try block a.
1140
*/
1141
 
7 7u83 1142
EXP
1143
end_new_try(EXP a, EXP b)
2 7u83 1144
{
7 7u83 1145
	EXP c = DEREF_exp(exp_try_block_body(a));
1146
	c = add_compound_stmt(c, b);
1147
	c = end_compound_stmt(c);
1148
	a = cont_try_stmt(a, c);
1149
	a = end_try_stmt(a, 1);
1150
	if (IS_NULL_exp(b)) {
1151
		free_exp(a, 1);
1152
		a = NULL_exp;
1153
	}
1154
	return (a);
2 7u83 1155
}
1156
 
1157
 
1158
/*
1159
    FIND THE BODY OF A NEW-INITIALISER TRY BLOCK
1160
 
1161
    This routine returns the initialiser component of the new-initialiser
1162
    try block a.
1163
*/
1164
 
7 7u83 1165
EXP
1166
new_try_body(EXP a)
2 7u83 1167
{
7 7u83 1168
	while (!IS_NULL_exp(a)) {
1169
		switch (TAG_exp(a)) {
1170
		case exp_try_block_tag: {
1171
			a = DEREF_exp(exp_try_block_body(a));
1172
			break;
2 7u83 1173
		}
7 7u83 1174
		case exp_decl_stmt_tag: {
1175
			a = DEREF_exp(exp_decl_stmt_body(a));
1176
			break;
1177
		}
1178
		case exp_sequence_tag: {
1179
			LIST(EXP)p = DEREF_list(exp_sequence_first(a));
1180
			p = TAIL_list(p);
1181
			if (IS_NULL_list(p)) {
1182
				a = NULL_exp;
1183
			} else {
1184
				a = DEREF_exp(HEAD_list(p));
1185
			}
1186
			break;
1187
		}
1188
		case exp_location_tag: {
1189
			a = DEREF_exp(exp_location_arg(a));
1190
			break;
1191
		}
1192
		default: {
1193
			return (a);
1194
		}
1195
		}
2 7u83 1196
	}
7 7u83 1197
	return (NULL_exp);
2 7u83 1198
}
1199
 
1200
 
1201
/*
1202
    END OF ALLOCATION ROUTINES
1203
 
1204
    The remaining routines are common to both producers.
1205
*/
1206
 
1207
#endif /* LANGUAGE_CPP */
1208
 
1209
 
1210
/*
1211
    MULTIPLY ARRAY DIMENSIONS
1212
 
1213
    This routine multiplies the dimensions of any array components in the
1214
    type pointed to by pt returning it as an expression of type s.  It
1215
    assigns the non-array components back to pt.
1216
*/
1217
 
7 7u83 1218
EXP
1219
sizeof_array(TYPE *pt, TYPE s)
2 7u83 1220
{
7 7u83 1221
	TYPE t = *pt;
1222
	EXP a = NULL_exp;
1223
	while (IS_type_array(t)) {
1224
		EXP b;
1225
		NAT n = DEREF_nat(type_array_size(t));
1226
		if (IS_NULL_nat(n)) {
1227
			n = small_nat[0];
1228
		}
1229
		b = calc_nat_value(n, s);
1230
		a = make_dim_exp(lex_star, a, b);
1231
		t = DEREF_type(type_array_sub(t));
1232
	}
1233
	*pt = t;
1234
	return (a);
2 7u83 1235
}
1236
 
1237
 
1238
/*
1239
    FIND THE SIZE OF A TYPE
1240
 
1241
    This routine calculates the size of the type t when this can be precisely
1242
    evaluated, returning the null literal if this is not possible.
1243
*/
1244
 
7 7u83 1245
static NAT
1246
sizeof_type(TYPE t)
2 7u83 1247
{
7 7u83 1248
	switch (TAG_type(t)) {
1249
	case type_integer_tag: {
1250
		/* Allow for integral types */
1251
		INT_TYPE it = DEREF_itype(type_integer_rep(t));
1252
		if (IS_itype_basic(it)) {
1253
			BASE_TYPE bt = DEREF_btype(itype_basic_rep(it));
1254
			if (bt & btype_char) {
1255
				/* char has size one */
1256
				NAT n = small_nat[1];
1257
				return (n);
1258
			}
2 7u83 1259
		}
7 7u83 1260
		break;
2 7u83 1261
	}
7 7u83 1262
	case type_top_tag:
1263
	case type_bottom_tag: {
1264
		/* void has size one */
1265
		NAT n = small_nat[1];
1266
		return (n);
2 7u83 1267
	}
7 7u83 1268
	case type_array_tag: {
1269
		/* Allow for array types */
1270
		TYPE s = type_size_t;
1271
		EXP a = sizeof_array(&t, s);
1272
		NAT n = sizeof_type(t);
1273
		if (!IS_NULL_nat(n)) {
1274
			EXP b = calc_nat_value(n, s);
1275
			a = make_dim_exp(lex_star, a, b);
1276
			if (IS_exp_int_lit(a)) {
1277
				n = DEREF_nat(exp_int_lit_nat(a));
1278
				return (n);
1279
			}
2 7u83 1280
		}
7 7u83 1281
		break;
2 7u83 1282
	}
7 7u83 1283
	case type_enumerate_tag: {
1284
		/* An enumeration maps to its underlying type */
1285
		ENUM_TYPE et = DEREF_etype(type_enumerate_defn(t));
1286
		TYPE s = DEREF_type(etype_rep(et));
1287
		return (sizeof_type(s));
2 7u83 1288
	}
7 7u83 1289
	}
1290
	return (NULL_nat);
2 7u83 1291
}
1292
 
1293
 
1294
/*
1295
    CREATE A SIZEOF EXPRESSION
1296
 
1297
    This routine constructs the expression 'sizeof ( t )' without applying
1298
    any checks to t.
1299
*/
1300
 
7 7u83 1301
EXP
1302
sizeof_exp(TYPE t)
2 7u83 1303
{
7 7u83 1304
	EXP e;
1305
	NAT sz = sizeof_type(t);
1306
	if (IS_NULL_nat(sz)) {
1307
		/* Calculate size if it is not obvious */
1308
		OFFSET off;
1309
		MAKE_off_type(t, off);
1310
		MAKE_exp_offset_size(type_size_t, off, type_char, 1, e);
1311
		MAKE_nat_calc(e, sz);
1312
	}
1313
	MAKE_exp_int_lit(type_size_t, sz, exp_offset_size_tag, e);
1314
	return (e);
2 7u83 1315
}
1316
 
1317
 
1318
/*
1319
    CONSTRUCT A SIZEOF EXPRESSION
1320
 
1321
    This routine constructs the expression 'sizeof ( t )'.  Note that
1322
    'sizeof a' has already been reduced to 'sizeof ( typeof ( a ) )'
1323
    except in the case where the result depends on a template parameter.
1324
    The argument n gives the number of types defined in t.  Note that the
1325
    result is a constant integer expression.
1326
*/
1327
 
7 7u83 1328
EXP
1329
make_sizeof_exp(TYPE t, EXP a, int n, int op)
2 7u83 1330
{
7 7u83 1331
	/* Deal with argument dependent case */
2 7u83 1332
#if LANGUAGE_CPP
7 7u83 1333
	if (!IS_NULL_exp(a)) {
1334
		EXP e;
1335
		NAT sz;
1336
		TYPE s = type_size_t;
1337
		MAKE_exp_op(s, op, a, NULL_exp, e);
1338
		MAKE_nat_calc(e, sz);
1339
		MAKE_exp_int_lit(s, sz, exp_op_tag, e);
1340
		return (e);
1341
	}
2 7u83 1342
#else
7 7u83 1343
	UNUSED(a);
2 7u83 1344
#endif
1345
 
7 7u83 1346
	/* Check on type */
1347
	switch (TAG_type(t)) {
1348
	case type_func_tag: {
1349
		/* Can't have sizeof (function) */
1350
		report(crt_loc, ERR_expr_sizeof_func(op));
1351
		MAKE_type_ptr(cv_none, t, t);
1352
		break;
2 7u83 1353
	}
7 7u83 1354
	case type_bitfield_tag: {
1355
		/* Can't have sizeof (bitfield) */
1356
		report(crt_loc, ERR_expr_sizeof_bitf(op));
1357
		t = find_bitfield_type(t);
1358
		break;
2 7u83 1359
	}
7 7u83 1360
	case type_ref_tag: {
1361
		/* sizeof (T &) equals sizeof (T) */
1362
		t = DEREF_type(type_ref_sub(t));
1363
		break;
2 7u83 1364
	}
1365
	default : {
7 7u83 1366
		/* Can't have sizeof (incomplete) */
1367
		ERROR err = check_incomplete(t);
1368
		if (!IS_NULL_err(err)) {
1369
			err = concat_error(err, ERR_expr_sizeof_incompl(op));
1370
			report(crt_loc, err);
1371
		}
1372
		break;
2 7u83 1373
	}
7 7u83 1374
	}
2 7u83 1375
 
7 7u83 1376
	/* Report on type definitions */
1377
	if (n) {
1378
		report(crt_loc, ERR_expr_sizeof_typedef(op));
1379
	}
2 7u83 1380
 
7 7u83 1381
	/* Calculate result */
1382
	return (sizeof_exp(t));
2 7u83 1383
}
1384
 
1385
 
1386
/*
1387
    FIND THE TYPE OF AN EXPRESSION
1388
 
1389
    This routine returns the type of the expression pointed to by pa after
1390
    apply reference conversions to it.  It is used, for example, to
1391
    transform 'sizeof ( a )' into 'sizeof ( t )'.  n gives the number of
1392
    side effects in pa.
1393
*/
1394
 
7 7u83 1395
TYPE
1396
typeof_exp(EXP *pa, int n, int op)
2 7u83 1397
{
7 7u83 1398
	TYPE t;
1399
	EXP a = *pa;
1400
	if (n) {
1401
		report(crt_loc, ERR_expr_sizeof_side(op));
1402
	}
1403
	a = convert_reference(a, REF_NORMAL);
1404
	a = convert_none(a);
1405
	t = DEREF_type(exp_type(a));
1406
	if (!is_templ_type(t)) {
1407
		/* Free operand in simple case */
1408
		free_exp(a, 2);
1409
		a = NULL_exp;
1410
	}
1411
	*pa = a;
1412
	return (t);
2 7u83 1413
}
1414
 
1415
 
1416
/*
1417
    FIND THE NUMBER OF ITEMS IN AN INITIALISER EXPRESSION
1418
 
1419
    This routine returns the number of initialisers in the expression e
1420
    counting each array element separately.
1421
*/
1422
 
7 7u83 1423
EXP
1424
sizeof_init(EXP e, TYPE s)
2 7u83 1425
{
7 7u83 1426
	EXP a = NULL_exp;
1427
	unsigned long v = 0;
1428
	if (!IS_NULL_exp(e)) {
1429
		LIST(EXP)p, q;
1430
		if (IS_exp_comma(e)) {
1431
			p = DEREF_list(exp_comma_args(e));
1432
			p = END_list(p);
1433
			e = DEREF_exp(HEAD_list(p));
1434
		}
1435
		if (IS_exp_initialiser(e)) {
1436
			p = DEREF_list(exp_initialiser_args(e));
1437
			q = NULL_list(EXP);
1438
		} else {
1439
			CONS_exp(e, NULL_list(EXP), p);
1440
			q = p;
1441
		}
1442
		while (!IS_NULL_list(p)) {
1443
			EXP b = DEREF_exp(HEAD_list(p));
1444
			if (!IS_NULL_exp(b)) {
1445
				TYPE t = DEREF_type(exp_type(b));
1446
				if (IS_type_array(t)) {
1447
					/* Multiply up array bounds */
1448
					EXP c = sizeof_array(&t, s);
1449
					a = make_dim_exp(lex_plus, a, c);
1450
				} else {
1451
					/* Other types count once */
1452
					v++;
1453
				}
1454
			}
1455
			p = TAIL_list(p);
1456
		}
1457
		if (!IS_NULL_list(q)) {
1458
			DESTROY_list(q, SIZE_exp);
1459
		}
2 7u83 1460
	}
7 7u83 1461
	if (IS_NULL_exp(a)) {
1462
		NAT n = make_nat_value(v);
1463
		a = calc_nat_value(n, s);
2 7u83 1464
	} else {
7 7u83 1465
		if (v) {
1466
			NAT n = make_nat_value(v);
1467
			EXP c = calc_nat_value(n, s);
1468
			a = make_dim_exp(lex_plus, a, c);
2 7u83 1469
		}
1470
	}
7 7u83 1471
	return (a);
2 7u83 1472
}