Subversion Repositories tendra.SVN

Rev

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

Rev Author Line No. Line
2 7u83 1
/*
2
    		 Crown Copyright (c) 1997
3
 
4
    This TenDRA(r) Computer Program is subject to Copyright
5
    owned by the United Kingdom Secretary of State for Defence
6
    acting through the Defence Evaluation and Research Agency
7
    (DERA).  It is made available to Recipients with a
8
    royalty-free licence for its use, reproduction, transfer
9
    to other parties and amendment for any purpose not excluding
10
    product development provided that any such use et cetera
11
    shall be deemed to be acceptance of the following conditions:-
12
 
13
        (1) Its Recipients shall ensure that this Notice is
14
        reproduced upon any copies or amended versions of it;
15
 
16
        (2) Any amended version of it shall be clearly marked to
17
        show both the nature of and the organisation responsible
18
        for the relevant amendment or amendments;
19
 
20
        (3) Its onward transfer from a recipient to another
21
        party shall be deemed to be that party's acceptance of
22
        these conditions;
23
 
24
        (4) DERA gives no warranty or assurance as to its
25
        quality or suitability for any purpose and DERA accepts
26
        no liability whatsoever in relation to any use to which
27
        it may be put.
28
*/
29
 
30
 
31
#include "config.h"
32
#include "c_types.h"
33
#include "ctype_ops.h"
34
#include "exp_ops.h"
35
#include "hashid_ops.h"
36
#include "graph_ops.h"
37
#include "id_ops.h"
38
#include "member_ops.h"
39
#include "nspace_ops.h"
40
#include "off_ops.h"
41
#include "type_ops.h"
42
#include "error.h"
43
#include "catalog.h"
44
#include "access.h"
45
#include "basetype.h"
46
#include "cast.h"
47
#include "check.h"
48
#include "chktype.h"
49
#include "class.h"
50
#include "constant.h"
51
#include "convert.h"
52
#include "copy.h"
53
#include "derive.h"
54
#include "expression.h"
55
#include "function.h"
56
#include "hash.h"
57
#include "identifier.h"
58
#include "initialise.h"
59
#include "instance.h"
60
#include "member.h"
61
#include "namespace.h"
62
#include "operator.h"
63
#include "parse.h"
64
#include "predict.h"
65
#include "statement.h"
66
#include "syntax.h"
67
#include "template.h"
68
#include "token.h"
69
 
70
 
71
/*
72
    FORM THE ADDRESS OF AN EXPRESSION
73
 
74
    This routine forms the address of the expression e.  If e is not an
75
    lvalue then a temporary is introduced and its address is returned.
76
*/
77
 
78
static EXP member_address
79
    PROTO_N ( ( e ) )
80
    PROTO_T ( EXP e )
81
{
82
    TYPE t = DEREF_type ( exp_type ( e ) ) ;
83
    CV_SPEC qual = DEREF_cv ( type_qual ( t ) ) ;
84
    if ( qual & cv_lvalue ) {
85
	t = rvalue_type ( t ) ;
86
    } else {
87
	ERROR err = NULL_err ;
88
	e = make_temporary ( t, e, NULL_exp, 0, &err ) ;
89
	if ( !IS_NULL_err ( err ) ) report ( crt_loc, err ) ;
90
    }
91
    MAKE_type_ptr ( cv_none, t, t ) ;
92
    MAKE_exp_address ( t, e, e ) ;
93
    return ( e ) ;
94
}
95
 
96
 
97
/*
98
    BEGIN A FIELD SELECTOR EXPRESSION
99
 
100
    This routine begins the construction of the field selector expressions
101
    'a.b' and 'a->b' (as indicated by op).  The base type of a (after
102
    removing pointers in the '->' case) is returned via pt.  Note that
103
    it is not checked that this is a class type at this stage because the
104
    explicit destructor notation can apply to any type.  Note that '->'
105
    can be overloaded (albeit in a different way to most other operations)
106
    but '.' can't.
107
*/
108
 
109
EXP begin_field_exp
110
    PROTO_N ( ( op, a, pt, pns ) )
111
    PROTO_T ( int op X EXP a X TYPE *pt X NAMESPACE *pns )
112
{
113
    TYPE t, s ;
114
    unsigned c ;
115
    int ptr = 0 ;
116
    unsigned tag ;
117
 
118
    /* Do operand conversion */
119
    if ( op == lex_arrow ) {
120
	/* Check for overloading with '->' */
121
#if LANGUAGE_CPP
122
	int go = 1 ;
123
	LIST ( TYPE ) prev = NULL_list ( TYPE ) ;
124
	do {
125
	    /* Perform reference conversions */
126
	    a = convert_reference ( a, REF_NORMAL ) ;
127
	    t = DEREF_type ( exp_type ( a ) ) ;
128
	    c = type_category ( &t ) ;
129
	    if ( overload_depth ) break ;
130
	    if ( IS_TYPE_TEMPL ( c ) ) {
131
		/* Template parameter type */
132
		EXP e ;
133
		MAKE_exp_op ( t, op, a, a, e ) ;
134
		cache_lookup = 0 ;
135
		*pns = NULL_nspace ;
136
		*pt = t ;
137
		return ( e ) ;
138
	    }
139
	    if ( IS_TYPE_OVERLOAD ( c ) ) {
140
		EXP e = unary_overload ( lex_arrow, a ) ;
141
		if ( IS_NULL_exp ( e ) ) {
142
		    /* '->' isn't overloaded */
143
		    go = 0 ;
144
		} else {
145
		    /* '->' is overloaded, try again */
146
		    LIST ( TYPE ) p = prev ;
147
		    while ( !IS_NULL_list ( p ) ) {
148
			/* Check for cycles */
149
			s = DEREF_type ( HEAD_list ( p ) ) ;
150
			if ( eq_type ( s, t ) ) {
151
			    ERROR err = ERR_over_match_oper_arrow () ;
152
			    report ( crt_loc, err ) ;
153
			    go = 0 ;
154
			    break ;
155
			}
156
			p = TAIL_list ( p ) ;
157
		    }
158
		    CONS_type ( t, prev, prev ) ;
159
		    a = e ;
160
		}
161
	    } else {
162
		/* '->' can't be overloaded */
163
		go = 0 ;
164
	    }
165
	} while ( go ) ;
166
	DESTROY_list ( prev, SIZE_type ) ;
167
#else
168
	/* Perform reference conversions */
169
	a = convert_reference ( a, REF_NORMAL ) ;
170
	t = DEREF_type ( exp_type ( a ) ) ;
171
	c = type_category ( &t ) ;
172
#endif
173
 
174
	/* Do lvalue conversions if necessary */
175
	if ( IS_TYPE_ADDRESS ( c ) ) {
176
	    a = convert_lvalue ( a ) ;
177
	    t = DEREF_type ( exp_type ( a ) ) ;
178
	}
179
    } else {
180
	/* For '.' just do reference conversions */
181
	a = convert_reference ( a, REF_NORMAL ) ;
182
	t = DEREF_type ( exp_type ( a ) ) ;
183
#if LANGUAGE_CPP
184
	c = type_category ( &t ) ;
185
	if ( IS_TYPE_TEMPL ( c ) ) {
186
	    /* Template parameter type */
187
	    EXP e ;
188
	    MAKE_exp_op ( t, op, a, a, e ) ;
189
	    cache_lookup = 0 ;
190
	    *pns = NULL_nspace ;
191
	    *pt = t ;
192
	    return ( e ) ;
193
	}
194
#endif
195
    }
196
 
197
    /* Check operand type */
198
    tag = TAG_type ( t ) ;
199
    if ( tag == type_token_tag ) {
200
	t = expand_type ( t, 0 ) ;
201
	tag = TAG_type ( t ) ;
202
    }
203
    if ( tag == type_ptr_tag ) {
204
	s = DEREF_type ( type_ptr_sub ( t ) ) ;
205
	tag = TAG_type ( s ) ;
206
	if ( tag == type_token_tag ) {
207
	    if ( op == lex_arrow && is_templ_type ( s ) ) {
208
		/* Template parameter type */
209
		EXP e ;
210
		MAKE_exp_op ( s, op, a, a, e ) ;
211
		cache_lookup = 0 ;
212
		*pns = NULL_nspace ;
213
		*pt = s ;
214
		return ( e ) ;
215
	    }
216
	    s = expand_type ( s, 0 ) ;
217
	    tag = TAG_type ( s ) ;
218
	}
219
	ptr = 1 ;
220
    } else {
221
	s = t ;
222
    }
223
    if ( tag == type_compound_tag ) {
224
	/* Operand is a class or a pointer to a class */
225
	ERROR err ;
226
	CLASS_TYPE ct = DEREF_ctype ( type_compound_defn ( s ) ) ;
227
	NAMESPACE ns = DEREF_nspace ( ctype_member ( ct ) ) ;
228
 
229
	/* Check that the correct operator has been used */
230
	if ( op == lex_arrow ) {
231
	    if ( !ptr ) report ( crt_loc, ERR_expr_ref_arrow_dot ( t ) ) ;
232
	} else {
233
	    if ( ptr ) report ( crt_loc, ERR_expr_ref_dot_arrow ( t ) ) ;
234
	}
235
 
236
	/* Check that the class is complete */
237
	err = check_incomplete ( s ) ;
238
	cache_lookup = 0 ;
239
	if ( !IS_NULL_err ( err ) ) {
240
	    /* Incomplete class */
241
	    BASE_TYPE key = find_class_key ( ct ) ;
242
	    err = concat_error ( err, ERR_expr_ref_incompl ( op, key ) ) ;
243
	    report ( crt_loc, err ) ;
244
	    ns = NULL_nspace ;
245
	    s = type_error ;
246
	} else {
247
	    /* Complete class */
248
	    add_namespace ( ns ) ;
249
	}
250
	*pns = ns ;
251
	*pt = s ;
252
 
253
	/* Check for null pointers */
254
	if ( IS_exp_null ( a ) && ptr ) {
255
	    report ( crt_loc, ERR_expr_unary_op_indir_null ( op ) ) ;
256
	}
257
 
258
    } else {
259
	/* Bad operand type */
260
	if ( !IS_type_error ( s ) ) {
261
	    if ( op == lex_arrow ) {
262
		if ( !ptr ) {
263
		    string key = find_vocab ( lex_class ) ;
264
		    report ( crt_loc, ERR_expr_ref_arrow_op ( t, key ) ) ;
265
		    s = type_error ;
266
		}
267
	    } else {
268
		s = t ;
269
	    }
270
	}
271
	cache_lookup = 0 ;
272
	*pns = NULL_nspace ;
273
	*pt = s ;
274
    }
275
    return ( a ) ;
276
}
277
 
278
 
279
/*
280
    CREATE A FIELD SELECTOR EXPRESSION
281
 
282
    This routine completes the field selector expression constructed by
283
    begin_field_exp.  The a arguments is the outputs of this routine,
284
    ns represents the class namespace of the type of a, op indicated which
285
    selector is being used, and fld indicates the field being selected.
286
*/
287
 
288
static EXP apply_field_op
289
    PROTO_N ( ( op, a, ns, fld, templ ) )
290
    PROTO_T ( int op X EXP a X NAMESPACE ns X IDENTIFIER fld X int templ )
291
{
292
    EXP e ;
293
    GRAPH gr ;
294
    HASHID nm ;
295
    TYPE t, s ;
296
    string key ;
297
    CV_SPEC qual ;
298
    ERROR err = NULL_err ;
299
    LIST ( TOKEN ) args = NULL_list ( TOKEN ) ;
300
 
301
    /* Find the type of a */
302
    s = DEREF_type ( exp_type ( a ) ) ;
303
    qual = find_cv_qual ( s ) ;
304
 
305
    /* Check for template members */
306
    if ( templ && IS_id_undef ( fld ) ) {
307
	TYPE form = DEREF_type ( id_undef_form ( fld ) ) ;
308
	if ( !IS_NULL_type ( form ) && IS_type_token ( form ) ) {
309
	    fld = DEREF_id ( type_token_tok ( form ) ) ;
310
	    args = DEREF_list ( type_token_args ( form ) ) ;
311
	    templ = 2 ;
312
	}
313
    }
314
 
315
    /* Check that fld is a member of ns */
316
    gr = is_subfield ( ns, fld ) ;
317
    if ( !IS_NULL_graph ( gr ) ) {
318
	IDENTIFIER orig = fld ;
319
	fld = search_subfield ( ns, gr, orig ) ;
320
	if ( templ == 2 ) {
321
	    /* Apply template arguments */
322
	    fld = apply_template ( fld, args, 0, 0 ) ;
323
	}
324
	switch ( TAG_id ( fld ) ) {
325
 
326
	    case id_stat_member_tag : {
327
		/* Static data members */
328
		e = make_id_exp ( fld ) ;
329
		e = join_exp ( a, e ) ;
330
		return ( e ) ;
331
	    }
332
 
333
	    case id_mem_func_tag :
334
	    case id_stat_mem_func_tag : {
335
		/* Member functions */
336
		if ( !templ ) {
337
		    IDENTIFIER tid = find_template ( fld, 0 ) ;
338
		    if ( !IS_NULL_id ( tid ) ) {
339
			/* Should have 'template' prefix */
340
			report ( crt_loc, ERR_temp_names_mem ( fld ) ) ;
341
		    }
342
		}
343
 
344
		/* Form '*a' for pointers */
345
		if ( IS_type_ptr ( s ) ) {
346
		    s = DEREF_type ( type_ptr_sub ( s ) ) ;
347
		    s = lvalue_type ( s ) ;
348
		    MAKE_exp_indir ( s, a, a ) ;
349
		}
350
 
351
		/* Construct the result */
352
		e = make_id_exp ( fld ) ;
353
		t = DEREF_type ( exp_type ( e ) ) ;
354
		MAKE_exp_call ( t, e, a, gr, e ) ;
355
		return ( e ) ;
356
	    }
357
 
358
	    case id_member_tag : {
359
		/* Non-static data members */
360
		TYPE p ;
361
		OFFSET off ;
362
		int virt = 0 ;
363
 
364
		/* Allow for pointer types */
365
		if ( IS_type_ptr ( s ) ) {
366
		    /* Form '*a' for pointers */
367
		    s = DEREF_type ( type_ptr_sub ( s ) ) ;
368
		    qual = DEREF_cv ( type_qual ( s ) ) ;
369
		    qual |= cv_lvalue ;
370
		} else {
371
		    /* Form '&a' for non-pointers */
372
		    a = member_address ( a ) ;
373
		}
374
 
375
		/* Find result type */
376
		use_id ( fld, 0 ) ;
377
		t = DEREF_type ( id_member_type ( fld ) ) ;
378
		if ( !IS_type_ref ( t ) ) {
379
		    CV_SPEC cv = find_cv_qual ( t ) ;
380
		    cv &= cv_qual ;
381
		    if ( qual & cv_const ) {
382
			DECL_SPEC ds = DEREF_dspec ( id_storage ( fld ) ) ;
383
			if ( !( ds & dspec_mutable ) ) {
384
			    /* 'mutable' cancels out 'const' */
385
			    cv |= cv_const ;
386
			}
387
		    }
388
		    if ( qual & cv_volatile ) {
389
			cv |= cv_volatile ;
390
		    }
391
		    t = qualify_type ( t, cv, 0 ) ;
392
		}
393
 
394
		/* Check for virtual base members */
395
		gr = DEREF_graph ( id_member_base ( fld ) ) ;
396
		if ( !IS_NULL_graph ( gr ) ) {
397
		    DECL_SPEC acc = DEREF_dspec ( graph_access ( gr ) ) ;
398
		    if ( acc & dspec_mutable ) {
399
			/* Contained in virtual base */
400
			if ( know_type ( a ) != 1 ) virt = 1 ;
401
		    }
402
		}
403
 
404
		/* Form the result */
405
		off = DEREF_off ( id_member_off ( fld ) ) ;
406
		MAKE_type_ptr ( cv_none, t, p ) ;
407
		MAKE_exp_add_ptr ( p, a, off, virt, e ) ;
408
		if ( qual & cv_lvalue ) {
409
		    /* The result is an lvalue if s is */
410
		    t = lvalue_type ( t ) ;
411
		    MAKE_exp_indir ( t, e, e ) ;
412
		} else {
413
		    MAKE_exp_contents ( t, e, e ) ;
414
		}
415
		return ( e ) ;
416
	    }
417
 
418
	    case id_enumerator_tag : {
419
		/* Enumerator members */
420
		NAT n ;
421
		unsigned etag ;
422
		use_id ( fld, 0 ) ;
423
		e = DEREF_exp ( id_enumerator_value ( fld ) ) ;
424
		DECONS_exp_int_lit ( t, n, etag, e ) ;
425
		MAKE_exp_int_lit ( t, n, etag, e ) ;
426
		e = join_exp ( a, e ) ;
427
		return ( e ) ;
428
	    }
429
 
430
	    case id_ambig_tag : {
431
		/* Ambiguous members */
432
		IGNORE report_ambiguous ( fld, 0, 1, 0 ) ;
433
		e = make_error_exp ( 1 ) ;
434
		e = join_exp ( a, e ) ;
435
		return ( e ) ;
436
	    }
437
 
438
	    case id_class_name_tag :
439
	    case id_class_alias_tag :
440
	    case id_enum_name_tag :
441
	    case id_enum_alias_tag :
442
	    case id_type_alias_tag : {
443
		/* Type members */
444
		err = ERR_expr_ref_type ( fld ) ;
445
		break ;
446
	    }
447
 
448
	    case id_undef_tag : {
449
		/* Undefined members */
450
		nm = DEREF_hashid ( id_name ( fld ) ) ;
451
		err = ERR_lookup_qual_undef ( nm, ns ) ;
452
		break ;
453
	    }
454
	}
455
    }
456
 
457
    /* Report any errors */
458
    nm = DEREF_hashid ( id_name ( fld ) ) ;
459
    if ( IS_hashid_destr ( nm ) ) {
460
	/* Pseudo-destructor call */
461
	destroy_error ( err, 1 ) ;
462
	return ( NULL_exp ) ;
463
    }
464
    key = find_vocab ( lex_class ) ;
465
    if ( IS_NULL_err ( err ) ) err = ERR_lookup_qual_bad ( fld, ns ) ;
466
    err = concat_error ( err, ERR_expr_ref_select ( op, key ) ) ;
467
    report ( crt_loc, err ) ;
468
    e = make_error_exp ( 1 ) ;
469
    e = join_exp ( a, e ) ;
470
    return ( e ) ;
471
}
472
 
473
 
474
/*
475
    COMPLETE A FIELD SELECTOR EXPRESSION
476
 
477
    This routine gives the main interface to apply_field_op, allowing for
478
    the error case and adjusting the name look-up stack.  a is the return
479
    value from begin_field_exp, while t is the returned base type.  The
480
    field identifier is given by fld, this being prefixed by template if
481
    templ is true.
482
*/
483
 
484
EXP end_field_exp
485
    PROTO_N ( ( op, a, t, ns, fld, templ ) )
486
    PROTO_T ( int op X EXP a X TYPE t X NAMESPACE ns X
487
	      IDENTIFIER fld X int templ )
488
{
489
    EXP e ;
490
    QUALIFIER cq = crt_id_qualifier ;
491
    if ( cq == qual_full || cq == qual_top ) {
492
	/* Bad field selector */
493
	report ( crt_loc, ERR_expr_ref_qual ( cq, fld ) ) ;
494
    }
495
    if ( !IS_NULL_nspace ( ns ) ) {
496
	/* Class types */
497
	remove_namespace () ;
498
	cache_lookup = old_cache_lookup ;
499
	if ( cq != qual_none ) templ = 1 ;
500
	e = apply_field_op ( op, a, ns, fld, templ ) ;
501
	if ( !IS_NULL_exp ( e ) ) return ( e ) ;
502
    } else {
503
	cache_lookup = old_cache_lookup ;
504
    }
505
 
506
    if ( IS_exp_op ( a ) ) {
507
	/* Template parameter types */
508
	EXP b ;
509
	if ( cq == qual_none ) fld = underlying_id ( fld ) ;
510
	MAKE_exp_member ( t, fld, qual_nested, b ) ;
511
	COPY_exp ( exp_op_arg2 ( a ), b ) ;
512
	e = a ;
513
    } else {
514
	/* Other types */
515
	if ( !IS_type_error ( t ) ) {
516
	    HASHID nm = DEREF_hashid ( id_name ( fld ) ) ;
517
	    if ( IS_hashid_destr ( nm ) ) {
518
		/* Allow for pseudo-destructor call */
519
		TYPE fn = type_func_void ;
520
		TYPE r = DEREF_type ( hashid_destr_type ( nm ) ) ;
521
		TYPE s = expand_type ( r, 2 ) ;
522
		if ( !EQ_type ( s, r ) ) {
523
		    nm = lookup_destr ( s, NULL_id ) ;
524
		    fld = DEREF_id ( hashid_id ( nm ) ) ;
525
		    t = expand_type ( t, 2 ) ;
526
		    r = s ;
527
		}
528
		/* NOT YET IMPLEMENTED - scalar type */
529
		if ( !eq_type_unqual ( t, r ) && !IS_type_error ( r ) ) {
530
		    /* Destructor types should match */
531
		    report ( crt_loc, ERR_expr_pseudo_obj ( nm, t ) ) ;
532
		}
533
		MAKE_exp_undeclared ( fn, fld, cq, e ) ;
534
		MAKE_exp_call ( fn, e, a, NULL_graph, e ) ;
535
	    } else {
536
		/* Anything else is illegal */
537
		string key = find_vocab ( lex_class ) ;
538
		TYPE s = DEREF_type ( exp_type ( a ) ) ;
539
		if ( op == lex_arrow ) {
540
		    report ( crt_loc, ERR_expr_ref_arrow_op ( s, key ) ) ;
541
		} else {
542
		    report ( crt_loc, ERR_expr_ref_dot_op ( s, key ) ) ;
543
		}
544
		e = make_error_exp ( 1 ) ;
545
	    }
546
	} else {
547
	    e = make_error_exp ( 1 ) ;
548
	}
549
    }
550
    return ( e ) ;
551
}
552
 
553
 
554
/*
555
    CONSTRUCT A FIELD SELECTOR EXPRESSION
556
 
557
    This routine is an alternative interface to the field selector
558
    expression routines used in the instantiation of template functions.
559
    It constructs 'a.b' or 'a->b' depending on op, where b is an
560
    identifier expression giving the member name.
561
*/
562
 
563
EXP make_field_exp
564
    PROTO_N ( ( op, a, b ) )
565
    PROTO_T ( int op X EXP a X EXP b )
566
{
567
    TYPE t = NULL_type ;
568
    NAMESPACE ns = NULL_nspace ;
569
    QUALIFIER cq = crt_id_qualifier ;
570
    EXP e = begin_field_exp ( op, a, &t, &ns ) ;
571
    IDENTIFIER fld = DEREF_id ( exp_member_id ( b ) ) ;
572
    QUALIFIER qual = DEREF_qual ( exp_member_qual ( b ) ) ;
573
    crt_id_qualifier = qual ;
574
    if ( !IS_NULL_nspace ( ns ) ) {
575
	/* Rescan field for class namespaces */
576
	fld = rescan_id ( fld, qual, 0 ) ;
577
    }
578
    e = end_field_exp ( op, e, t, ns, fld, 1 ) ;
579
    crt_id_qualifier = cq ;
580
    return ( e ) ;
581
}
582
 
583
 
584
/*
585
    CONSTRUCT A MEMBER SELECTOR EXPRESSION
586
 
587
    This routine constructs the member selector expressions 'a.*b' and
588
    'a->*b' (as indicated by op).  Note that '->*' can be overloaded but
589
    '.*' can't.
590
*/
591
 
592
#if LANGUAGE_CPP
593
 
594
EXP make_member_exp
595
    PROTO_N ( ( op, a, b ) )
596
    PROTO_T ( int op X EXP a X EXP b )
597
{
598
    EXP e ;
599
    int is_ptr ;
600
    CV_SPEC qual ;
601
    TYPE ta, tap ;
602
    unsigned sa, sb ;
603
    TYPE tb, tbr, tbp ;
604
    CLASS_TYPE ca, cb ;
605
 
606
    /* Do reference conversions */
607
    a = convert_reference ( a, REF_NORMAL ) ;
608
    b = convert_reference ( b, REF_NORMAL ) ;
609
 
610
    /* Find operand types */
611
    ta = DEREF_type ( exp_type ( a ) ) ;
612
    sa = type_category ( &ta ) ;
613
    tb = DEREF_type ( exp_type ( b ) ) ;
614
    sb = type_category ( &tb ) ;
615
 
616
    /* Check for overloading */
617
    if ( op == lex_arrow_Hstar ) {
618
	if ( IS_TYPE_OVERLOAD ( sa ) || IS_TYPE_OVERLOAD ( sb ) ) {
619
	    if ( overload_depth == 0 ) {
620
		e = binary_overload ( op, a, b ) ;
621
		return ( e ) ;
622
	    }
623
	}
624
    } else {
625
	if ( IS_TYPE_TEMPL ( sa ) || IS_TYPE_TEMPL ( sb ) ) {
626
	    if ( overload_depth == 0 ) {
627
		e = binary_overload ( op, a, b ) ;
628
		return ( e ) ;
629
	    }
630
	}
631
    }
632
 
633
    /* Do lvalue conversion */
634
    if ( IS_TYPE_ADDRESS ( sb ) ) {
635
	b = convert_lvalue ( b ) ;
636
	tb = DEREF_type ( exp_type ( b ) ) ;
637
    }
638
 
639
    /* Second operand must be pointer to member */
640
    if ( !IS_TYPE_PTR_MEM ( sb ) ) {
641
	if ( !IS_TYPE_ERROR ( sa ) && !IS_TYPE_ERROR ( sb ) ) {
642
	    report ( crt_loc, ERR_expr_mptr_oper_op2 ( op, tb ) ) ;
643
	}
644
	e = make_error_exp ( 1 ) ;
645
	return ( e ) ;
646
    }
647
    cb = DEREF_ctype ( type_ptr_mem_of ( tb ) ) ;
648
    tbr = DEREF_type ( type_ptr_mem_sub ( tb ) ) ;
649
    if ( in_template_decl ) {
650
	/* Allow for template parameters */
651
	TYPE fb = DEREF_type ( ctype_form ( cb ) ) ;
652
	if ( is_templ_type ( fb ) ) {
653
	    MAKE_exp_op ( fb, op, a, b, e ) ;
654
	    return ( e ) ;
655
	}
656
    }
657
 
658
    /* Check first operand type */
659
    if ( IS_type_ptr ( ta ) ) {
660
	a = convert_lvalue ( a ) ;
661
	ta = DEREF_type ( exp_type ( a ) ) ;
662
	tap = DEREF_type ( type_ptr_sub ( ta ) ) ;
663
	qual = DEREF_cv ( type_qual ( tap ) ) ;
664
	qual |= cv_lvalue ;
665
	is_ptr = 1 ;
666
    } else {
667
	tap = ta ;
668
	qual = DEREF_cv ( type_qual ( ta ) ) ;
669
	is_ptr = 0 ;
670
    }
671
    if ( IS_type_compound ( tap ) ) {
672
	ERROR err ;
673
	ca = DEREF_ctype ( type_compound_defn ( tap ) ) ;
674
	if ( eq_ctype ( ca, cb ) ) {
675
	    /* Equal base types */
676
	    /* EMPTY */
677
	} else {
678
	    GRAPH gr = find_base_class ( ca, cb, 1 ) ;
679
	    if ( !IS_NULL_graph ( gr ) ) {
680
		/* cb is a base class of ca */
681
		OFFSET off ;
682
		err = check_ambig_base ( gr ) ;
683
		if ( !IS_NULL_err ( err ) ) {
684
		    ERROR err2 = ERR_expr_mptr_oper_ambig ( op ) ;
685
		    err = concat_error ( err, err2 ) ;
686
		    report ( crt_loc, err ) ;
687
		}
688
		check_base_access ( gr ) ;
689
		off = DEREF_off ( graph_off ( gr ) ) ;
690
		tap = make_class_type ( cb ) ;
691
		MAKE_type_ptr ( cv_none, tap, ta ) ;
692
		if ( is_ptr ) {
693
		    a = make_base_cast ( ta, a, off ) ;
694
		} else {
695
		    a = member_address ( a ) ;
696
		    a = make_base_cast ( ta, a, off ) ;
697
		    ta = lvalue_type ( tap ) ;
698
		    MAKE_exp_indir ( ta, a, a ) ;
699
		}
700
	    } else {
701
		/* cb is not a base class of ca */
702
		goto error_lab ;
703
	    }
704
	}
705
	err = check_incomplete ( tap ) ;
706
	if ( !IS_NULL_err ( err ) ) {
707
	    /* Class should be complete */
708
	    err = concat_error ( err, ERR_expr_mptr_oper_compl ( op ) ) ;
709
	    report ( crt_loc, err ) ;
710
	}
711
    } else {
712
	/* Invalid base type */
713
	if ( !IS_type_error ( tap ) ) {
714
	    error_lab : {
715
		ERROR err ;
716
		IDENTIFIER cid = DEREF_id ( ctype_name ( cb ) ) ;
717
		if ( op == lex_arrow_Hstar ) {
718
		    err = ERR_expr_mptr_oper_arrow_op ( cid, ta ) ;
719
		} else {
720
		    err = ERR_expr_mptr_oper_dot_op ( cid, ta ) ;
721
		}
722
		report ( crt_loc, err ) ;
723
	    }
724
	}
725
	e = make_error_exp ( 1 ) ;
726
	return ( e ) ;
727
    }
728
 
729
    /* Correct base type */
730
    if ( op == lex_arrow_Hstar ) {
731
	if ( !is_ptr ) {
732
	    report ( crt_loc, ERR_expr_mptr_oper_arrow_dot ( ta ) ) ;
733
	}
734
    } else {
735
	if ( is_ptr ) {
736
	    report ( crt_loc, ERR_expr_mptr_oper_dot_arrow ( ta ) ) ;
737
	}
738
    }
739
 
740
    /* Check for null pointers */
741
    if ( IS_exp_null ( a ) && is_ptr ) {
742
	report ( crt_loc, ERR_expr_unary_op_indir_null ( op ) ) ;
743
    }
744
    if ( IS_exp_null ( b ) ) {
745
	report ( crt_loc, ERR_expr_mptr_oper_null ( op ) ) ;
746
    }
747
 
748
    /* Construct the result */
749
    if ( IS_type_func ( tbr ) ) {
750
	/* Member functions */
751
	if ( is_ptr ) {
752
	    ta = lvalue_type ( ta ) ;
753
	    MAKE_exp_indir ( ta, a, a ) ;
754
	}
755
	MAKE_exp_call ( tbr, b, a, NULL_graph, e ) ;
756
    } else {
757
	/* Data members */
758
	OFFSET off ;
759
	CV_SPEC cv1 = ( qual & cv_qual ) ;
760
	if ( cv1 ) {
761
	    /* The result type inherits both qualifiers */
762
	    CV_SPEC cv2 = DEREF_cv ( type_qual ( tbr ) ) ;
763
	    tbr = qualify_type ( tbr, ( cv1 | cv2 ), 0 ) ;
764
	}
765
	if ( !is_ptr ) {
766
	    /* For non-pointers construct '&a' */
767
	    a = member_address ( a ) ;
768
	}
769
	MAKE_off_ptr_mem ( b, off ) ;
770
	MAKE_type_ptr ( cv_none, tbr, tbp ) ;
771
	MAKE_exp_add_ptr ( tbp, a, off, 0, e ) ;
772
	if ( qual & cv_lvalue ) {
773
	    /* The result is an lvalue if tap is */
774
	    tbr = lvalue_type ( tbr ) ;
775
	    MAKE_exp_indir ( tbr, e, e ) ;
776
	} else {
777
	    MAKE_exp_contents ( tbr, e, e ) ;
778
	}
779
    }
780
    return ( e ) ;
781
}
782
 
783
#endif
784
 
785
 
786
/*
787
    LOOK UP A MEMBER IN A MEMBER FUNCTION DEFINITION
788
 
789
    This routine looks up the member fld.  In a member function definition
790
    the routine returns 'this->fld' for non-static data members and the
791
    parameter corresponding to 'this' for non-static function members,
792
    otherwise the null expression is returned.
793
*/
794
 
795
EXP make_this_field
796
    PROTO_N ( ( fld ) )
797
    PROTO_T ( IDENTIFIER fld )
798
{
799
    IDENTIFIER fn = crt_func_id ;
800
    if ( in_function_defn && IS_id_mem_func ( fn ) ) {
801
	NAMESPACE ns = DEREF_nspace ( id_parent ( fn ) ) ;
802
	GRAPH gr = is_subfield ( ns, fld ) ;
803
	if ( !IS_NULL_graph ( gr ) ) {
804
	    switch ( TAG_id ( fld ) ) {
805
		case id_member_tag :
806
		case id_mem_func_tag : {
807
		    EXP e ;
808
		    TYPE t ;
809
		    IDENTIFIER id = this_param ( fn, 1 ) ;
810
		    if ( in_default_arg ) {
811
			/* Can't use in default argument */
812
			ERROR err = ERR_dcl_fct_default_param ( fld ) ;
813
			report ( crt_loc, err ) ;
814
		    }
815
		    e = DEREF_exp ( id_parameter_init ( id ) ) ;
816
		    t = DEREF_type ( exp_type ( e ) ) ;
817
		    MAKE_exp_copy ( t, e, e ) ;
818
		    e = apply_field_op ( lex_arrow, e, ns, fld, 1 ) ;
819
		    return ( e ) ;
820
		}
821
	    }
822
	}
823
    }
824
    return ( NULL_exp ) ;
825
}
826
 
827
 
828
/*
829
    DECOMPOSE A BITFIELD OFFSET
830
 
831
    This routine decomposes the bitfield member offset off into its member
832
    component, which is returned, and its base class component, which is
833
    assigned to off.
834
*/
835
 
836
OFFSET decons_bitf_off
837
    PROTO_N ( ( off ) )
838
    PROTO_T ( OFFSET *off )
839
{
840
    OFFSET off1 = *off ;
841
    if ( !IS_NULL_off ( off1 ) && IS_off_plus ( off1 ) ) {
842
	*off = DEREF_off ( off_plus_arg1 ( off1 ) ) ;
843
	off1 = DEREF_off ( off_plus_arg2 ( off1 ) ) ;
844
    } else {
845
	*off = NULL_off ;
846
    }
847
    return ( off1 ) ;
848
}
849
 
850
 
851
/*
852
    DECOMPOSE A BITFIELD EXPRESSION
853
 
854
    This routine decomposes the lvalue bitfield expression e into its
855
    bitfield member offset, which is returned, and its class pointer
856
    component, which is assigned to e.
857
*/
858
 
859
OFFSET decons_bitf_exp
860
    PROTO_N ( ( e ) )
861
    PROTO_T ( EXP *e )
862
{
863
    EXP a = *e ;
864
    OFFSET off = NULL_off ;
865
    switch ( TAG_exp ( a ) ) {
866
 
867
	case exp_indir_tag : {
868
	    /* Simple field access */
869
	    a = DEREF_exp ( exp_indir_ptr ( a ) ) ;
870
	    if ( IS_exp_add_ptr ( a ) ) {
871
		TYPE t ;
872
		int virt ;
873
		OFFSET off1 ;
874
		DECONS_exp_add_ptr ( t, a, off1, virt, a ) ;
875
		UNUSED ( t ) ;
876
		t = DEREF_type ( exp_type ( a ) ) ;
877
		off = decons_bitf_off ( &off1 ) ;
878
		if ( !IS_NULL_off ( off1 ) ) {
879
		    MAKE_exp_add_ptr ( t, a, off1, virt, a ) ;
880
		}
881
		if ( IS_exp_address ( a ) ) {
882
		    a = DEREF_exp ( exp_address_arg ( a ) ) ;
883
		} else {
884
		    if ( IS_type_ptr ( t ) ) {
885
			t = DEREF_type ( type_ptr_sub ( t ) ) ;
886
		    }
887
		    t = lvalue_type ( t ) ;
888
		    MAKE_exp_indir ( t, a, a ) ;
889
		}
890
		*e = a ;
891
	    }
892
	    break ;
893
	}
894
 
895
	case exp_comma_tag : {
896
	    /* Comma expression */
897
	    TYPE t = DEREF_type ( exp_type ( a ) ) ;
898
	    LIST ( EXP ) p = DEREF_list ( exp_comma_args ( a ) ) ;
899
	    LIST ( EXP ) q = NULL_list ( EXP ) ;
900
	    while ( !IS_NULL_list ( p ) ) {
901
		EXP b = DEREF_exp ( HEAD_list ( p ) ) ;
902
		p = TAIL_list ( p ) ;
903
		if ( IS_NULL_list ( p ) ) {
904
		    off = decons_bitf_exp ( &b ) ;
905
		    t = DEREF_type ( exp_type ( b ) ) ;
906
		}
907
		CONS_exp ( b, q, q ) ;
908
	    }
909
	    q = REVERSE_list ( q ) ;
910
	    MAKE_exp_comma ( t, q, a ) ;
911
	    *e = a ;
912
	    break ;
913
	}
914
 
915
	case exp_if_stmt_tag : {
916
	    /* Conditional expression */
917
	    TYPE t ;
918
	    EXP c = DEREF_exp ( exp_if_stmt_cond ( a ) ) ;
919
	    EXP b1 = DEREF_exp ( exp_if_stmt_true_code ( a ) ) ;
920
	    EXP b2 = DEREF_exp ( exp_if_stmt_false_code ( a ) ) ;
921
	    OFFSET off1 = decons_bitf_exp ( &b1 ) ;
922
	    OFFSET off2 = decons_bitf_exp ( &b2 ) ;
923
	    if ( eq_offset ( off1, off2, 0 ) ) {
924
		off = off1 ;
925
	    } else {
926
		/* NOT YET IMPLEMENTED */
927
		off = off1 ;
928
	    }
929
	    t = DEREF_type ( exp_type ( b1 ) ) ;
930
	    MAKE_exp_if_stmt ( t, c, b1, b2, NULL_id, a ) ;
931
	    *e = a ;
932
	    break ;
933
	}
934
    }
935
    return ( off ) ;
936
}
937
 
938
 
939
/*
940
    SET MEMBER OFFSET LOOK-UP NAMESPACE
941
 
942
    This routine sets the look-up namespace to that for the class type t.
943
    If t is not a class type then the null namespace is returned.
944
*/
945
 
946
NAMESPACE offset_nspace
947
    PROTO_N ( ( t ) )
948
    PROTO_T ( TYPE t )
949
{
950
    NAMESPACE ns ;
951
    if ( IS_type_compound ( t ) ) {
952
	CLASS_TYPE ct = DEREF_ctype ( type_compound_defn ( t ) ) ;
953
	complete_class ( ct, 1 ) ;
954
	ns = DEREF_nspace ( ctype_member ( ct ) ) ;
955
	cache_lookup = 0 ;
956
	add_namespace ( ns ) ;
957
    } else {
958
	ns = NULL_nspace ;
959
	cache_lookup = 0 ;
960
    }
961
    return ( ns ) ;
962
}
963
 
964
 
965
/*
966
    FIND A MEMBER OFFSET
967
 
968
    This routine finds the offset of the member id of the class type t.
969
    ns gives the namespace associated with t.  The member type is
970
    returned via pt.  id must denote a simple, non-virtual data member.
971
*/
972
 
973
OFFSET offset_member
974
    PROTO_N ( ( t, id, pt, ns, adjust ) )
975
    PROTO_T ( TYPE t X IDENTIFIER id X TYPE *pt X NAMESPACE ns X int adjust )
976
{
977
    if ( !IS_NULL_nspace ( ns ) ) {
978
	GRAPH gr ;
979
	if ( adjust ) {
980
	    remove_namespace () ;
981
	    cache_lookup = old_cache_lookup ;
982
	}
983
	gr = is_subfield ( ns, id ) ;
984
	if ( !IS_NULL_graph ( gr ) ) {
985
	    IDENTIFIER fld = search_subfield ( ns, gr, id ) ;
986
	    switch ( TAG_id ( fld ) ) {
987
		case id_member_tag : {
988
		    /* Data members */
989
		    TYPE s = DEREF_type ( id_member_type ( fld ) ) ;
990
		    OFFSET off = DEREF_off ( id_member_off ( fld ) ) ;
991
		    gr = DEREF_graph ( id_member_base ( fld ) ) ;
992
		    if ( !IS_NULL_graph ( gr ) ) {
993
			/* Check for virtual bases */
994
			DECL_SPEC acc = DEREF_dspec ( graph_access ( gr ) ) ;
995
			if ( acc & dspec_mutable ) goto default_lab ;
996
		    }
997
		    use_id ( fld, 0 ) ;
998
		    *pt = s ;
999
		    return ( off ) ;
1000
		}
1001
		case id_ambig_tag : {
1002
		    /* Ambiguous members */
1003
		    IGNORE report_ambiguous ( fld, 0, 1, 0 ) ;
1004
		    break ;
1005
		}
1006
		case id_undef_tag : {
1007
		    /* Undefined members */
1008
		    HASHID nm = DEREF_hashid ( id_name ( fld ) ) ;
1009
		    report ( crt_loc, ERR_lookup_qual_undef ( nm, ns ) ) ;
1010
		    break ;
1011
		}
1012
		default :
1013
		default_lab : {
1014
		    /* Other members */
1015
		    ERROR err = ERR_expr_const_off_mem ( fld ) ;
1016
		    err = concat_error ( err, ERR_token_mem_off () ) ;
1017
		    report ( crt_loc, err ) ;
1018
		    break ;
1019
		}
1020
	    }
1021
	} else {
1022
	    /* id is not a member of ns */
1023
	    report ( crt_loc, ERR_lookup_qual_bad ( id, ns ) ) ;
1024
	}
1025
    } else {
1026
	if ( !IS_type_error ( t ) ) {
1027
	    /* t is not a class type */
1028
	    string key = find_vocab ( lex_class ) ;
1029
	    report ( crt_loc, ERR_expr_ref_dot_op ( t, key ) ) ;
1030
	}
1031
	cache_lookup = old_cache_lookup ;
1032
    }
1033
    *pt = type_error ;
1034
    return ( NULL_off ) ;
1035
}
1036
 
1037
 
1038
/*
1039
    FIND AN INDEX OFFSET
1040
 
1041
    This routine finds the offset of the eth member of the array type t.
1042
    The member type is returned via pt.  e must denote an integer constant
1043
    expression.
1044
*/
1045
 
1046
OFFSET offset_index
1047
    PROTO_N ( ( t, e, pt ) )
1048
    PROTO_T ( TYPE t X EXP e X TYPE *pt )
1049
{
1050
    if ( IS_type_array ( t ) ) {
1051
	OFFSET off ;
1052
	ERROR err = NULL_err ;
1053
	TYPE s = DEREF_type ( type_array_sub ( t ) ) ;
1054
	IGNORE make_nat_exp ( e, &err ) ;
1055
	if ( !IS_NULL_err ( err ) ) {
1056
	    err = concat_error ( err, ERR_expr_const_off_dim () ) ;
1057
	    err = concat_error ( err, ERR_token_mem_off () ) ;
1058
	    report ( crt_loc, err ) ;
1059
	}
1060
	check_bounds ( lex_array_Hop, t, e ) ;
1061
	off = make_off_mult ( s, e, 0 ) ;
1062
	*pt = s ;
1063
	return ( off ) ;
1064
    }
1065
    if ( !IS_type_error ( t ) ) {
1066
	ERROR err = ERR_expr_const_off_array ( t ) ;
1067
	err = concat_error ( err, ERR_token_mem_off () ) ;
1068
	report ( crt_loc, err ) ;
1069
    }
1070
    *pt = type_error ;
1071
    return ( NULL_off ) ;
1072
}
1073
 
1074
 
1075
/*
1076
    ADD TWO OFFSETS
1077
 
1078
    This routine adds the two offsets a and b, either of which may be
1079
    null.
1080
*/
1081
 
1082
OFFSET offset_add
1083
    PROTO_N ( ( a, b ) )
1084
    PROTO_T ( OFFSET a X OFFSET b )
1085
{
1086
    OFFSET off ;
1087
    if ( is_zero_offset ( a ) ) return ( b ) ;
1088
    if ( is_zero_offset ( b ) ) return ( a ) ;
1089
    MAKE_off_plus ( a, b, off ) ;
1090
    return ( off ) ;
1091
}