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 5

Subversion Repositories tendra.SVN

Rev

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

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