Warning: Attempt to read property "date" on null in /usr/local/www/websvn.planix.org/blame.php on line 247

Warning: Attempt to read property "msg" on null in /usr/local/www/websvn.planix.org/blame.php on line 247

Warning: Attempt to read property "date" on null in /usr/local/www/websvn.planix.org/blame.php on line 247

Warning: Attempt to read property "msg" on null in /usr/local/www/websvn.planix.org/blame.php on line 247
WebSVN – tendra.SVN – Blame – /branches/tendra5-amd64/src/producers/common/construct/typeid.c – Rev 6

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
/*
6 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
6 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:-
6 7u83 42
 
2 7u83 43
        (1) Its Recipients shall ensure that this Notice is
44
        reproduced upon any copies or amended versions of it;
6 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;
6 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;
6 7u83 53
 
2 7u83 54
        (4) DERA gives no warranty or assurance as to its
55
        quality or suitability for any purpose and DERA accepts
56
        no liability whatsoever in relation to any use to which
57
        it may be put.
58
*/
59
 
60
 
61
#include "config.h"
62
#include "c_types.h"
63
#include "ctype_ops.h"
64
#include "exp_ops.h"
65
#include "graph_ops.h"
66
#include "hashid_ops.h"
67
#include "id_ops.h"
68
#include "type_ops.h"
69
#include "virt_ops.h"
70
#include "error.h"
71
#include "catalog.h"
72
#include "access.h"
73
#include "basetype.h"
74
#include "cast.h"
75
#include "check.h"
76
#include "chktype.h"
77
#include "class.h"
78
#include "constant.h"
79
#include "convert.h"
80
#include "derive.h"
81
#include "destroy.h"
82
#include "exception.h"
83
#include "expression.h"
84
#include "hash.h"
85
#include "identifier.h"
86
#include "initialise.h"
87
#include "interface.h"
88
#include "literal.h"
89
#include "namespace.h"
90
#include "overload.h"
91
#include "syntax.h"
92
#include "template.h"
93
#include "tok.h"
94
#include "token.h"
95
#include "typeid.h"
96
#include "ustring.h"
97
 
98
 
99
/*
100
    STANDARD CLASS NAMES
101
 
102
    These variables are used to hold the names of the various built-in
103
    class types.  They are defined here as the majority are concerned
104
    with run-time type information.
105
*/
106
 
6 7u83 107
static CONST char *std_name = "std";
108
static NAMESPACE std_namespace = NULL_nspace;
2 7u83 109
 
110
 
111
/*
112
    FIND THE STANDARD NAMESPACE
113
 
114
    This routine returns the std namespace if this has been declared.
115
*/
116
 
6 7u83 117
static NAMESPACE
118
find_std_namespace(void)
2 7u83 119
{
6 7u83 120
	NAMESPACE ns = std_namespace;
121
	if (IS_NULL_nspace(ns)) {
122
		string s = ustrlit(std_name);
123
		if (s == NULL) {
124
			/* Use global namespace if std_name is not given */
125
			ns = global_namespace;
126
		} else {
127
			/* Look up 'std' in the global namespace */
128
			unsigned long h = hash(s);
129
			HASHID nm = lookup_name(s, h, 0, lex_identifier);
130
			MEMBER mem = search_member(global_namespace, nm, 0);
131
			IDENTIFIER id = type_member(mem, 2);
132
			if (!IS_NULL_id(id) && IS_id_nspace_name_etc(id)) {
133
				ns = DEREF_nspace(id_nspace_name_etc_defn(id));
134
			}
135
		}
136
		std_namespace = ns;
2 7u83 137
	}
6 7u83 138
	return (ns);
2 7u83 139
}
140
 
141
 
142
/*
143
    SET THE STANDARD NAMESPACE
144
 
145
    This routine sets the std namespace according to the identifier id.
146
    The null identifier is used to indicate the global namespace.
147
*/
148
 
6 7u83 149
void
150
set_std_namespace(IDENTIFIER id)
2 7u83 151
{
6 7u83 152
	std_name = NULL;
153
	std_namespace = NULL_nspace;
154
	if (!IS_NULL_id(id)) {
155
		HASHID nm = DEREF_hashid(id_name(id));
156
		if (IS_hashid_name_etc(nm)) {
157
			string s = DEREF_string(hashid_name_etc_text(nm));
158
			std_name = strlit(s);
159
		}
2 7u83 160
	}
6 7u83 161
	IGNORE find_std_namespace();
162
	return;
2 7u83 163
}
164
 
165
 
166
/*
167
    LOOK UP A STANDARD CLASS TYPE
168
 
169
    This routine looks up the standard class named s in the std namespace.
170
    The null type is returned if the type has not been declared and, in
171
    addition, an error is reported if err is true.
172
*/
173
 
6 7u83 174
TYPE
175
find_std_type(CONST char *s, int type, int err)
2 7u83 176
{
6 7u83 177
	string us = ustrlit(s);
178
	unsigned long h = hash(us);
179
	HASHID nm = lookup_name(us, h, 0, lex_identifier);
180
	NAMESPACE ns = find_std_namespace();
181
	if (!IS_NULL_nspace(ns)) {
182
		IDENTIFIER id = search_id(ns, nm, 0, type);
183
		if (!IS_NULL_id(id) && IS_id_class_name_etc(id)) {
184
			TYPE t = DEREF_type(id_class_name_etc_defn(id));
185
			return (t);
186
		}
2 7u83 187
	}
6 7u83 188
	if (err) {
189
		us = ustrlit(std_name);
190
		report(crt_loc, ERR_lib_builtin(us, nm));
191
	}
192
	return (NULL_type);
2 7u83 193
}
194
 
195
 
196
/*
197
    RUN-TIME TYPE INFORMATION ROUTINES
198
 
199
    The run-time type information routines are only included in the
200
    C++ producer.
201
*/
202
 
203
#if LANGUAGE_CPP
204
 
205
 
206
/*
207
    STANDARD CLASS TYPES
208
 
209
    The variable type_info_ref represents the type 'const type_info &'
210
    returned by the typeid operation.  The variables type_bad_cast and
211
    type_bad_typeid represent the types 'bad_cast' and 'bad_typeid'
212
    thrown by the dynamic_cast and typeid operators.
213
*/
214
 
6 7u83 215
static TYPE type_info_ref = NULL_type;
216
static TYPE type_bad_cast = NULL_type;
217
static TYPE type_bad_typeid = NULL_type;
2 7u83 218
 
219
 
220
/*
221
    GET THE TYPE_INFO TYPE
222
 
223
    This routine returns the type of the typeid operator.  An internal
224
    error is reported if this has not been initialised.
225
*/
226
 
6 7u83 227
TYPE
228
get_type_info(int op, TYPE t, int err)
2 7u83 229
{
6 7u83 230
	TYPE r = NULL_type;
231
	if (op == lex_typeid) {
232
		r = type_info_ref;
233
		if (IS_NULL_type(r)) {
234
			r = find_std_type("type_info", 1, err);
235
			if (IS_NULL_type(r)) {
236
				if (err) {
237
					r = type_error;
238
				} else {
239
					CV_SPEC cv = (cv_lvalue | cv_const);
240
					MAKE_type_dummy(cv, TOK_typeid_type, r);
241
				}
242
			} else {
243
				/* Form 'lvalue const type_info' */
244
				r = qualify_type(r,(cv_lvalue | cv_const), 0);
245
				type_info_ref = r;
246
			}
247
		}
248
	} else {
249
		if (IS_type_compound(t)) {
250
			CLASS_TYPE ct = DEREF_ctype(type_compound_defn(t));
251
			VIRTUAL vt = DEREF_virt(ctype_virt(ct));
252
			if (!IS_NULL_virt(vt)) {
253
				/* Form array of pointers to members */
254
				unsigned long m = DEREF_ulong(virt_no(vt));
255
				NAT n = make_nat_value(m + VIRTUAL_EXTRA);
256
				r = copy_typedef(NULL_id, type_func_void,
257
						 cv_none);
258
				MAKE_type_ptr_mem(cv_const, ct, r, r);
259
				MAKE_type_array(cv_lvalue, r, n, r);
260
			}
2 7u83 261
		} else {
6 7u83 262
			if (is_templ_type(t)) {
263
				r = t;
264
			}
2 7u83 265
		}
6 7u83 266
		if (IS_NULL_type(r)) {
267
			/* No virtual function table */
268
			report(crt_loc, ERR_expr_typeid_vtable(op));
269
		}
2 7u83 270
	}
6 7u83 271
	return (r);
2 7u83 272
}
273
 
274
 
275
/*
276
    THROW A STANDARD EXCEPTION
277
 
278
    This routine returns an expression corresponding to throwing the
279
    'bad_cast' or 'bad_typeid' types (as indicated by s and pr).  An
280
    error is reported if this type has not been declared.
281
*/
282
 
6 7u83 283
static EXP
284
throw_bad_op(CONST char *s, TYPE *pr)
2 7u83 285
{
6 7u83 286
	EXP e;
287
	TYPE r = *pr;
288
	if (IS_NULL_type(r)) {
289
		r = find_std_type(s, 1, 1);
290
		if (IS_NULL_type(r)) {
291
			return (NULL_exp);
292
		}
293
		*pr = r;
294
	}
295
	e = make_func_cast_exp(r, NULL_list(EXP));
296
	e = make_throw_exp(e, 0);
297
	return (e);
2 7u83 298
}
299
 
300
 
301
/*
302
    FIND A TYPEID ARGUMENT
303
 
304
    This routine simplifies the typeid argument expression a according to
305
    the rule 'p [i]' -> '*p'.  Unfortunately '*( p + i )' which is otherwise
306
    identical to 'p [i]' is not treated in the same manner.  The result
307
    is the address of a.
308
*/
309
 
6 7u83 310
static EXP
311
typeid_arg(int op, EXP a)
2 7u83 312
{
6 7u83 313
	while (IS_exp_paren(a)) {
314
		/* Remove any brackets */
315
		a = DEREF_exp(exp_paren_arg(a));
2 7u83 316
	}
6 7u83 317
	if (IS_exp_indir(a)) {
318
		int i = DEREF_int(exp_indir_index(a));
319
		a = DEREF_exp(exp_indir_ptr(a));
320
		if (i && IS_exp_add_ptr(a)) {
321
			OFFSET off = DEREF_off(exp_add_ptr_off(a));
322
			if (!is_const_offset(off, 2, 0)) {
323
				report(crt_loc, ERR_expr_typeid_index(op));
324
			}
325
			a = DEREF_exp(exp_add_ptr_ptr(a));
326
		}
327
	} else {
328
		TYPE t = DEREF_type(exp_type(a));
329
		MAKE_type_ptr(cv_none, t, t);
330
		MAKE_exp_address(t, a, a);
331
	}
332
	return (a);
2 7u83 333
}
334
 
335
 
336
/*
337
    CONSTRUCT A TYPEID EXPRESSION
338
 
339
    This routine constructs the type identification expression 'op ( a )'
340
    for an expression a.  n gives the number of side effects in a.  Note
341
    that suppress_usage is true during the evaluation of a and in this
342
    routine.  If it turns out that the expression is used (because it is
343
    an lvalue of polymorphic type) then mark_used needs to be called
344
    to mark any variable uses which have been missed.
345
*/
346
 
6 7u83 347
EXP
348
make_typeid_exp(int op, EXP a, int n)
2 7u83 349
{
6 7u83 350
	EXP e;
351
	TYPE t;
352
	CV_SPEC cv;
353
	a = convert_reference(a, REF_NORMAL);
354
	a = convert_none(a);
355
	a = convert_bitfield(a);
356
	t = DEREF_type(exp_type(a));
357
	if (is_templ_type(t)) {
358
		/* Allow for template types */
359
		TYPE r = get_type_info(op, t, 1);
360
		MAKE_exp_op(r, op, a, NULL_exp, e);
361
		return (e);
2 7u83 362
	}
6 7u83 363
	cv = DEREF_cv(type_qual(t));
364
	if ((cv & cv_lvalue) && IS_type_compound(t)) {
365
		CLASS_TYPE ct = DEREF_ctype(type_compound_defn(t));
366
		CLASS_INFO ci = DEREF_cinfo(ctype_info(ct));
367
		if (ci & cinfo_polymorphic) {
368
			/* lvalue of polymorphic type */
369
			TYPE r = get_type_info(op, t, 1);
370
			int use = suppress_usage;
371
			if (use) {
372
				suppress_usage--;
373
			}
374
			a = typeid_arg(op, a);
375
			mark_used(a);
376
			if (know_type(a)!= 1) {
377
				/* Can throw 'bad_typeid' */
378
				EXP b = throw_bad_op("bad_typeid",
379
						     &type_bad_typeid);
380
				t = DEREF_type(exp_type(a));
381
				MAKE_exp_dummy(t, a, LINK_NONE, NULL_off, 1, a);
382
				MAKE_exp_rtti(r, a, b, op, e);
383
				suppress_usage = use;
384
				return (e);
385
			}
386
			suppress_usage = use;
387
		}
388
	}
389
	if (n) {
390
		report(crt_loc, ERR_expr_typeid_side(op));
391
	}
392
	free_exp(a, 2);
393
	e = make_typeid_type(op, t, 0);
394
	return (e);
2 7u83 395
}
396
 
397
 
398
/*
399
    CONSTRUCT A TYPEID TYPE EXPRESSION
400
 
401
    This routine constructs the type identification expression 'op ( t )'
402
    for a type t.  The argument n gives the number of types defined in t.
403
*/
404
 
6 7u83 405
EXP
406
make_typeid_type(int op, TYPE t, int n)
2 7u83 407
{
6 7u83 408
	EXP e;
409
	TYPE r;
410
	if (n) {
411
		report(crt_loc, ERR_expr_typeid_typedef(op));
2 7u83 412
	}
6 7u83 413
	if (IS_type_ref(t)) {
414
		/* Remove reference component */
415
		t = DEREF_type(type_ref_sub(t));
416
	}
417
	if (IS_type_compound(t)) {
418
		/* Check for incomplete class types */
419
		ERROR err = check_incomplete(t);
420
		if (!IS_NULL_err(err)) {
421
			err = concat_error(err, ERR_expr_typeid_incompl(op));
422
			report(crt_loc, err);
423
		}
424
	}
425
	t = qualify_type(t, cv_none, 0);
426
	r = get_type_info(op, t, 1);
427
	MAKE_exp_rtti_type(r, t, op, e);
428
	return (e);
2 7u83 429
}
430
 
431
 
432
/*
433
    CONSTRUCT A TEMPLATE DEPENDENT DYNAMIC CAST EXPRESSION
434
 
435
    This routine constructs a template dependent dynamic cast of the
436
    expression a to the type t.
437
*/
438
 
6 7u83 439
static EXP
440
dynamic_cast_templ(TYPE t, EXP a)
2 7u83 441
{
6 7u83 442
	EXP e;
443
	MAKE_exp_op(t, lex_dynamic_Hcast, a, NULL_exp, e);
444
	return (e);
2 7u83 445
}
446
 
447
 
448
/*
449
    CONSTRUCT A DYNAMIC CAST EXPRESSION
450
 
451
    This routine constructs the expression 'dynamic_cast < t > ( a )'.
452
    The argument n gives the number of types defined in t.
453
*/
454
 
6 7u83 455
EXP
456
make_dynamic_cast_exp(TYPE t, EXP a, int n)
2 7u83 457
{
6 7u83 458
	TYPE s;
459
	CV_SPEC cv;
460
	int ok = 1;
461
	int ptr = 0;
462
	unsigned qual;
463
	EXP e = NULL_exp;
464
	TYPE p = NULL_type;
465
	ERROR err = NULL_err;
466
	CLASS_TYPE ct = NULL_ctype;
467
	CLASS_TYPE cs = NULL_ctype;
2 7u83 468
 
6 7u83 469
	/* Can't define types */
470
	if (n) {
471
		report(crt_loc, ERR_expr_cast_dynam_typedef());
472
	}
2 7u83 473
 
6 7u83 474
	/* Do reference conversion */
475
	a = convert_reference(a, REF_NORMAL);
476
	s = DEREF_type(exp_type(a));
477
	cv = DEREF_cv(type_qual(s));
2 7u83 478
 
6 7u83 479
	/* Check target type */
480
	if (IS_type_token(t)) {
481
		if (is_templ_type(t)) {
482
			e = dynamic_cast_templ(t, a);
483
			return (e);
484
		}
485
		t = expand_type(t, 1);
2 7u83 486
	}
6 7u83 487
	if (IS_type_ptr(t)) {
488
		/* Pointer types */
489
		p = DEREF_type(type_ptr_sub(t));
490
		if (IS_type_token(p)) {
491
			if (is_templ_type(p)) {
492
				e = dynamic_cast_templ(t, a);
493
				return (e);
494
			}
495
			p = expand_type(p, 1);
496
		}
497
		if (IS_type_top_etc(p)) {
498
			/* 'void *' allowed */
499
			ptr = 2;
500
		} else if (IS_type_compound(p)) {
501
			ct = DEREF_ctype(type_compound_defn(p));
502
			err = check_incomplete(p);
503
			if (!IS_NULL_err(err)) {
504
				ok = 0;
505
			}
506
			ptr = 1;
507
		} else {
508
			ok = 0;
509
		}
510
	} else if (IS_type_ref(t)) {
511
		p = DEREF_type(type_ref_sub(t));
512
		if (IS_type_token(p)) {
513
			if (is_templ_type(p)) {
514
				e = dynamic_cast_templ(t, a);
515
				return (e);
516
			}
517
			p = expand_type(p, 1);
518
		}
519
		if (IS_type_compound(p)) {
520
			ct = DEREF_ctype(type_compound_defn(p));
521
			err = check_incomplete(p);
522
			if (!IS_NULL_err(err)) {
523
				ok = 0;
524
			}
525
		} else {
526
			ok = 0;
527
		}
2 7u83 528
	} else {
6 7u83 529
		ok = 0;
2 7u83 530
	}
6 7u83 531
	if (!ok) {
532
		/* Invalid target type */
533
		IGNORE convert_lvalue(e);
534
		err = concat_error(err, ERR_expr_cast_dynam_type(t));
535
		report(crt_loc, err);
536
		e = make_error_exp(0);
537
		return (e);
2 7u83 538
	}
539
 
6 7u83 540
	/* Check operand type */
541
	if (is_templ_type(s)) {
542
		e = dynamic_cast_templ(t, a);
543
		return (e);
2 7u83 544
	}
6 7u83 545
	if (ptr) {
546
		if (cv & cv_lvalue) {
547
			a = convert_lvalue(a);
2 7u83 548
		}
6 7u83 549
		if (IS_type_token(s)) {
550
			s = expand_type(s, 1);
551
		}
552
		if (IS_type_ptr(s)) {
553
			/* Argument must be a pointer */
554
			TYPE q = DEREF_type(type_ptr_sub(s));
555
			if (IS_type_token(q)) {
556
				if (is_templ_type(q)) {
557
					e = dynamic_cast_templ(t, a);
558
					return (e);
559
				}
560
				q = expand_type(q, 1);
561
			}
562
			if (IS_type_compound(q)) {
563
				cs = DEREF_ctype(type_compound_defn(q));
564
				err = check_incomplete(q);
565
				if (!IS_NULL_err(err)) {
566
					ok = 0;
567
				}
568
			} else {
569
				ok = 0;
570
			}
571
		} else {
572
			ok = 0;
573
		}
574
		if (!ok) {
575
			err = concat_error(err, ERR_expr_cast_dynam_ptr(s));
576
			report(crt_loc, err);
577
			e = make_error_exp(0);
578
			return (e);
579
		}
2 7u83 580
	} else {
6 7u83 581
		/* Reference types */
582
		if (cv & cv_lvalue) {
583
			/* Argument must be an lvalue */
584
			if (IS_type_token(s)) {
585
				s = expand_type(s, 1);
586
			}
587
			if (IS_type_compound(s)) {
588
				cs = DEREF_ctype(type_compound_defn(s));
589
				err = check_incomplete(s);
590
				if (!IS_NULL_err(err)) {
591
					ok = 0;
592
				}
593
			} else {
594
				ok = 0;
595
			}
596
		} else {
597
			err = ERR_basic_lval_not();
598
			ok = 0;
599
		}
600
		if (!ok) {
601
			err = concat_error(err, ERR_expr_cast_dynam_ref(s));
602
			report(crt_loc, err);
603
			e = make_error_exp(1);
604
			return (e);
605
		}
606
 
607
		/* Convert to pointers */
608
		t = rvalue_type(p);
609
		MAKE_type_ptr(cv_none, t, t);
610
		s = rvalue_type(s);
611
		MAKE_type_ptr(cv_none, s, s);
612
		MAKE_exp_address(s, a, a);
2 7u83 613
	}
6 7u83 614
 
615
	/* Check for qualification conversions */
616
	qual = check_qualifier(t, s, 0);
617
	if (qual == QUAL_OK) {
618
		/* Exact match */
619
		e = a;
2 7u83 620
	} else {
6 7u83 621
		if (IS_exp_null(a)) {
622
			/* Null pointer conversion */
623
			e = make_null_exp(t);
624
		} else if (qual & QUAL_SIMILAR) {
625
			/* Qualification conversion */
626
			MAKE_exp_cast(t, CONV_QUAL, a, e);
627
		} else {
628
			/* Check for base class conversions */
629
			if (ptr != 2) {
630
				GRAPH gr = find_base_class(cs, ct, 1);
631
				if (!IS_NULL_graph(gr)) {
632
					/* Base class conversion */
633
					OFFSET off;
634
					err = check_ambig_base(gr);
635
					if (!IS_NULL_err(err)) {
636
						ERROR err2 =
637
						    ERR_conv_ptr_ambiguous();
638
						err = concat_error(err, err2);
639
						err2 = ERR_expr_cast_dynam_bad();
640
						err = concat_error(err, err2);
641
						report(crt_loc, err);
642
					}
643
					check_base_access(gr);
644
					off = DEREF_off(graph_off(gr));
645
					e = make_base_cast(t, a, off);
646
				}
647
			}
2 7u83 648
 
6 7u83 649
			/* Otherwise cs must be polymorphic */
650
			if (IS_NULL_exp(e)) {
651
				CLASS_INFO ci = DEREF_cinfo(ctype_info(cs));
652
				if (ci & cinfo_polymorphic) {
653
					if (ptr == 2) {
654
						/* Conversion to 'void *' */
655
						MAKE_exp_cast(t, CONV_PTR_VOID,
656
							      a, e);
657
					} else {
658
						/* Dynamic cast */
659
						EXP b = NULL_exp;
660
						if (ptr == 0) {
661
							/* Can throw 'bad_cast'
662
							 * for references */
663
							b = throw_bad_op("bad_cast", &type_bad_cast);
664
						}
665
						MAKE_exp_dummy(s, a, LINK_NONE,
666
							       NULL_off, 0, a);
667
						MAKE_exp_dyn_cast(t, a, b, e);
668
					}
669
				} else {
670
					err = ERR_expr_cast_dynam_poly(cs);
671
					report(crt_loc, err);
672
					e = make_error_exp(0);
673
					return (e);
674
				}
675
			}
2 7u83 676
		}
677
 
6 7u83 678
		/* Check for casting away const-ness */
679
		if (qual != QUAL_OK) {
680
			err = NULL_err;
681
			cast_away_const(qual, &err, CAST_DYNAMIC);
682
			if (!IS_NULL_err(err)) {
683
				err = concat_error(err,
684
						   ERR_expr_cast_dynam_bad());
685
				report(crt_loc, err);
2 7u83 686
			}
687
		}
688
	}
6 7u83 689
	if (ptr == 0) {
690
		/* Take indirection for references */
691
		MAKE_exp_indir(p, e, e);
2 7u83 692
	}
6 7u83 693
	return (e);
2 7u83 694
}
695
 
696
 
697
#endif /* LANGUAGE_CPP */