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