Subversion Repositories tendra.SVN

Rev

Rev 5 | Details | Compare with Previous | 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 "graph_ops.h"
65
#include "id_ops.h"
66
#include "member_ops.h"
67
#include "nspace_ops.h"
68
#include "type_ops.h"
69
#include "error.h"
70
#include "catalog.h"
71
#include "access.h"
72
#include "chktype.h"
73
#include "class.h"
74
#include "declare.h"
75
#include "initialise.h"
76
#include "merge.h"
77
#include "namespace.h"
78
#include "redeclare.h"
79
#include "token.h"
80
 
81
 
82
/*
83
    NAME MERGING FLAG
84
 
85
    This flag is set to true to indicate that name merging is taking
86
    place.
87
*/
88
 
6 7u83 89
int force_merge = 0;
2 7u83 90
 
91
 
92
/*
93
    ARE TWO CLASSES LAYOUT COMPATIBLE?
94
 
95
    This routine checks whether the classes ct and cs are layout compatible,
96
    i.e. they have the same member types and accesses.
97
*/
98
 
6 7u83 99
int
100
compatible_class(CLASS_TYPE ct, CLASS_TYPE cs)
2 7u83 101
{
6 7u83 102
	GRAPH gt, gs;
103
	MEMBER mt, ms;
104
	BASE_TYPE kt, ks;
105
	NAMESPACE nt, ns;
106
	LIST(GRAPH) bt, bs;
2 7u83 107
 
6 7u83 108
	/* Check for obvious equality */
109
	if (eq_ctype(ct, cs)) {
110
		return (1);
111
	}
2 7u83 112
 
6 7u83 113
	/* Check class keys */
114
	kt = find_class_key(ct);
115
	ks = find_class_key(cs);
116
	if (!equal_key(kt, ks)) {
117
		return (0);
118
	}
2 7u83 119
 
6 7u83 120
	/* Check base classes */
121
	gt = DEREF_graph(ctype_base(ct));
122
	gs = DEREF_graph(ctype_base(cs));
123
	bt = DEREF_list(graph_tails(gt));
124
	bs = DEREF_list(graph_tails(gs));
125
	while (!IS_NULL_list(bt) && !IS_NULL_list(bs)) {
126
		GRAPH ht = DEREF_graph(HEAD_list(bt));
127
		GRAPH hs = DEREF_graph(HEAD_list(bs));
128
		CLASS_TYPE pt = DEREF_ctype(graph_head(ht));
129
		CLASS_TYPE ps = DEREF_ctype(graph_head(hs));
130
		DECL_SPEC at = DEREF_dspec(graph_access(ht));
131
		DECL_SPEC as = DEREF_dspec(graph_access(hs));
132
		at &= (dspec_access | dspec_virtual);
133
		as &= (dspec_access | dspec_virtual);
134
		if (at != as) {
135
			return (0);
136
		}
137
		if (!compatible_class(pt, ps)) {
138
			return (0);
139
		}
140
		bs = TAIL_list(bs);
141
		bt = TAIL_list(bt);
142
	}
143
	if (!EQ_list(bt, bs)) {
144
		return (0);
145
	}
2 7u83 146
 
6 7u83 147
	/* Check class members */
148
	nt = DEREF_nspace(ctype_member(ct));
149
	mt = DEREF_member(nspace_ctype_first(nt));
150
	mt = next_data_member(mt, 1);
151
	ns = DEREF_nspace(ctype_member(cs));
152
	ms = DEREF_member(nspace_ctype_first(ns));
153
	ms = next_data_member(ms, 1);
154
	while (!IS_NULL_member(mt) && !IS_NULL_member(ms)) {
155
		IDENTIFIER it = DEREF_id(member_id(mt));
156
		IDENTIFIER is = DEREF_id(member_id(ms));
157
		TYPE t = DEREF_type(id_member_type(it));
158
		TYPE s = DEREF_type(id_member_type(is));
159
		DECL_SPEC at = DEREF_dspec(id_storage(it));
160
		DECL_SPEC as = DEREF_dspec(id_storage(is));
161
		at &= dspec_access;
162
		as &= dspec_access;
163
		if (at != as) {
164
			return (0);
165
		}
166
		if (!eq_type(t, s)) {
167
			return (0);
168
		}
169
		ms = DEREF_member(member_next(ms));
170
		ms = next_data_member(ms, 1);
171
		mt = DEREF_member(member_next(mt));
172
		mt = next_data_member(mt, 1);
173
	}
174
	if (!EQ_member(mt, ms)) {
175
		return (0);
176
	}
177
	return (1);
2 7u83 178
}
179
 
180
 
181
/*
182
    ARE TWO TYPES TO BE MERGED?
183
 
184
    This routine checks whether the identifiers tid and sid are to be made
185
    equal by merge_id.  This essentially means that they should be the
186
    same.
187
*/
188
 
6 7u83 189
int
190
merge_type(IDENTIFIER tid, IDENTIFIER sid)
2 7u83 191
{
6 7u83 192
	while (!EQ_id(tid, sid)) {
193
		unsigned tt, ts;
194
		HASHID tnm, snm;
195
		NAMESPACE nt, ns;
2 7u83 196
 
6 7u83 197
		/* Check identifiers */
198
		if (IS_NULL_id(tid)) {
199
			return (0);
200
		}
201
		if (IS_NULL_id(sid)) {
202
			return (0);
203
		}
204
		tt = TAG_id(tid);
205
		ts = TAG_id(sid);
206
		if (tt != ts) {
207
			return (0);
208
		}
2 7u83 209
 
6 7u83 210
		/* Check identifier names */
211
		tnm = DEREF_hashid(id_name(tid));
212
		snm = DEREF_hashid(id_name(sid));
213
		if (!EQ_hashid(tnm, snm)) {
214
			return (0);
215
		}
2 7u83 216
 
6 7u83 217
		/* Check identifier namespaces */
218
		nt = DEREF_nspace(id_parent(tid));
219
		ns = DEREF_nspace(id_parent(sid));
220
		if (EQ_nspace(nt, ns)) {
221
			return (1);
222
		}
223
		if (IS_NULL_nspace(nt)) {
224
			return (0);
225
		}
226
		if (IS_NULL_nspace(ns)) {
227
			return (0);
228
		}
229
		tt = TAG_nspace(nt);
230
		ts = TAG_nspace(ns);
231
		if (tt != ts) {
232
			return (0);
233
		}
234
		switch (tt) {
235
		case nspace_global_tag:
236
			return (1);
237
		case nspace_ctype_tag:
238
		case nspace_named_tag:
239
		case nspace_unnamed_tag:
240
			break;
241
		default:
242
			return (0);
243
		}
244
		tid = DEREF_id(nspace_name(nt));
245
		sid = DEREF_id(nspace_name(ns));
2 7u83 246
	}
6 7u83 247
	return (1);
2 7u83 248
}
249
 
250
 
251
/*
252
    CHECK FOR CONSISTENT REDEFINITION
253
 
254
    This routine checks whether the definitions of the objects pid and
255
    qid and consistent.
256
*/
257
 
6 7u83 258
static int
259
consistent_redef(IDENTIFIER pid, IDENTIFIER qid)
2 7u83 260
{
6 7u83 261
	int ok = 1;
262
	switch (TAG_id(pid)) {
263
	case id_nspace_name_tag: {
264
		/* Merge namespace definitions */
265
		NAMESPACE pns = DEREF_nspace(id_nspace_name_defn(pid));
266
		NAMESPACE qns = DEREF_nspace(id_nspace_name_defn(qid));
267
		if (IS_nspace_named(pns)) {
268
			COPY_nspace(id_nspace_name_defn(pid), qns);
269
			merge_namespaces(qns, pns);
270
		} else {
271
			merge_namespaces(NULL_nspace, pns);
272
		}
273
		break;
2 7u83 274
	}
6 7u83 275
	case id_class_name_tag: {
276
		BASE_TYPE bt, bs;
277
		CLASS_TYPE ct, cs;
278
		NAMESPACE pns, qns;
279
		TYPE t = DEREF_type(id_class_name_defn(pid));
280
		TYPE s = DEREF_type(id_class_name_defn(qid));
281
		while (IS_type_templ(t)) {
282
			t = DEREF_type(type_templ_defn(t));
283
		}
284
		ct = DEREF_ctype(type_compound_defn(t));
285
		bt = find_class_key(ct);
286
		pns = DEREF_nspace(ctype_member(ct));
287
		while (IS_type_templ(s)) {
288
			s = DEREF_type(type_templ_defn(s));
289
		}
290
		cs = DEREF_ctype(type_compound_defn(s));
291
		bs = find_class_key(cs);
292
		qns = DEREF_nspace(ctype_member(cs));
293
		COPY_nspace(ctype_member(ct), qns);
294
		if (!equal_key(bt, bs)) {
295
			/* Inconsistent key */
296
			PTR(LOCATION) loc = id_loc(qid);
297
			ERROR err = ERR_dcl_type_elab_bad(bt, bs, qid, loc);
298
			report(crt_loc, err);
299
		}
300
		merge_namespaces(qns, pns);
301
		break;
2 7u83 302
	}
6 7u83 303
	case id_variable_tag:
304
	case id_stat_member_tag:
305
		ok = 0;
306
		break;
2 7u83 307
	}
6 7u83 308
	return (ok);
2 7u83 309
}
310
 
311
 
312
/*
313
    EXPAND AN IDENTIFIER
314
 
315
    This routine expands the identifier id read from a spec input file.
316
    This is necessary because id may still contain pending identifiers.
317
*/
318
 
6 7u83 319
static void
320
expand_id(IDENTIFIER id)
2 7u83 321
{
6 7u83 322
	DEREF_loc(id_loc(id), crt_loc);
323
	decl_loc = crt_loc;
324
	return;
2 7u83 325
}
326
 
327
 
328
/*
329
    DECLARATION SPECIFIER MASK
330
 
331
    The macro dspec_mask is a mask which gives those declaration specifiers
332
    which should be the same for all declarations.
333
*/
334
 
335
#define dspec_mem_func\
6 7u83 336
   (dspec_virtual | dspec_pure | dspec_explicit | dspec_implicit)
2 7u83 337
 
338
#define dspec_mask\
6 7u83 339
   (dspec_storage | dspec_access | dspec_language | dspec_mem_func)
2 7u83 340
 
341
 
342
/*
343
    MERGE AN IDENTIFIER INTO A NAMESPACE
344
 
345
    This routine merges the identifier id read from a spec input file
346
    into the namespace ns.
347
*/
348
 
6 7u83 349
static void
350
merge_id(NAMESPACE ns, IDENTIFIER id)
2 7u83 351
{
6 7u83 352
	int type;
353
	HASHID nm;
354
	MEMBER mem;
355
	IDENTIFIER pid;
2 7u83 356
 
6 7u83 357
	/* Allow for overloaded functions */
358
	if (IS_id_function_etc(id)) {
359
		IDENTIFIER over = DEREF_id(id_function_etc_over(id));
360
		if (!IS_NULL_id(over)) {
361
			merge_id(ns, over);
362
		}
363
	}
2 7u83 364
 
6 7u83 365
	/* Find previous declaration */
366
	expand_id(id);
367
	if (IS_NULL_nspace(ns)) {
368
		return;
369
	}
370
	nm = DEREF_hashid(id_name(id));
371
	mem = search_member(ns, nm, 1);
372
	if (is_tagged_type(id)) {
373
		pid = type_member(mem, 3);
374
		type = 1;
375
	} else {
376
		pid = DEREF_id(member_id(mem));
377
		type = 0;
378
	}
2 7u83 379
 
6 7u83 380
	/* Check previous declaration */
381
	if (!IS_NULL_id(pid)) {
382
		unsigned tag = TAG_id(id);
383
		unsigned ptag = TAG_id(pid);
384
		if (tag == id_stat_mem_func_tag) {
385
			tag = id_mem_func_tag;
2 7u83 386
		}
6 7u83 387
		if (ptag == id_stat_mem_func_tag) {
388
			ptag = id_mem_func_tag;
2 7u83 389
		}
6 7u83 390
		if (tag == ptag) {
391
			int ok = 1;
392
			DECL_SPEC ds = DEREF_dspec(id_storage(id));
393
			DECL_SPEC pds = DEREF_dspec(id_storage(pid));
394
			PTR(TYPE) pt = NULL_ptr(TYPE);
395
			PTR(TYPE) ps = NULL_ptr(TYPE);
396
			switch (tag) {
397
			case id_class_name_tag:
398
			case id_enum_name_tag:
399
			case id_class_alias_tag:
400
			case id_enum_alias_tag:
401
			case id_type_alias_tag:
402
				pt = id_class_name_etc_defn(id);
403
				ps = id_class_name_etc_defn(pid);
404
				break;
405
			case id_variable_tag:
406
			case id_parameter_tag:
407
			case id_stat_member_tag:
408
				pt = id_variable_etc_type(id);
409
				ps = id_variable_etc_type(pid);
410
				break;
2 7u83 411
#if 0
6 7u83 412
			case id_function_tag:
413
			case id_mem_func_tag:
414
			case id_stat_mem_func_tag: {
415
				/* NOT YET IMPLEMENTED - function overloading */
416
				pt = id_function_etc_type(id);
417
				ps = id_function_etc_type(pid);
418
				break;
419
			}
2 7u83 420
#endif
6 7u83 421
			case id_member_tag:
422
				pt = id_member_type(id);
423
				ps = id_member_type(pid);
424
				break;
425
			case id_enumerator_tag:
426
				pt = id_enumerator_etype(id);
427
				ps = id_enumerator_etype(pid);
428
				break;
429
			}
2 7u83 430
 
6 7u83 431
			/* Check type compatibility */
432
			if (!IS_NULL_ptr(pt) && !IS_NULL_ptr(ps)) {
433
				ERROR err = NULL_err;
434
				TYPE t = DEREF_type(pt);
435
				TYPE s = DEREF_type(ps);
436
				t = expand_type(t, 1);
437
				s = expand_type(s, 1);
438
				s = check_compatible(s, t, 0, &err, 1);
439
				if (!IS_NULL_err(err)) {
440
					/* Incompatible declaration */
441
					PTR(LOCATION) ploc = id_loc(pid);
442
					ERROR err2 =
443
					    ERR_basic_link_decl_type(pid, ploc);
444
					err = concat_error(err, err2);
445
					report(crt_loc, err);
446
					ok = 0;
447
				} else {
448
					COPY_type(pt, t);
449
					COPY_type(ps, s);
450
				}
451
			}
2 7u83 452
 
6 7u83 453
			/* Check declaration specifiers */
454
			if (ok && (ds & dspec_mask)!= (pds & dspec_mask)) {
455
				PTR(LOCATION) ploc = id_loc(pid);
456
				DECL_SPEC st = (ds & dspec_storage);
457
				DECL_SPEC pst = (pds & dspec_storage);
458
				if (st != pst) {
459
					/* Inconsistent linkage */
460
					ERROR err;
461
					if (pst & dspec_static) {
462
						err = ERR_dcl_stc_internal(pid, ploc);
463
					} else {
464
						err = ERR_dcl_stc_external(pid, ploc);
465
					}
466
					report(crt_loc, err);
467
				}
468
				st = (ds & dspec_access);
469
				pst = (pds & dspec_access);
470
				if (st != pst) {
471
					/* Adjust access */
472
					adjust_access(pid, st, 0);
473
				}
474
				st = (ds & dspec_language);
475
				pst = (pds & dspec_language);
476
				if (st != pst) {
477
					/* Inconsistent language */
478
					string lang =
479
					    linkage_string(pst, cv_none);
480
					ERROR err =
481
					    ERR_dcl_link_lang(pid, lang, ploc);
482
					report(crt_loc, err);
483
				}
484
				st = (ds & dspec_mem_func);
485
				pst = (pds & dspec_mem_func);
486
				if (st != pst) {
487
					/* NOT YET IMPLEMENTED */
488
					/* EMPTY */
489
				}
490
			}
2 7u83 491
 
6 7u83 492
			/* Check for multiple definitions */
493
			if (pds & dspec_defn) {
494
				if (ds & dspec_defn) {
495
					if (!consistent_redef(id, pid) && ok) {
496
						PTR(LOCATION) ploc =
497
						    id_loc(pid);
498
						report(crt_loc, ERR_basic_odr_def(pid, ploc));
499
					}
500
				} else {
501
					id = pid;
502
				}
503
			}
504
 
2 7u83 505
		} else {
6 7u83 506
			/* Redeclared as different type of object */
507
			PTR(LOCATION) ploc = id_loc(pid);
508
			report(crt_loc, ERR_basic_odr_diff(pid, ploc));
2 7u83 509
		}
6 7u83 510
	}
2 7u83 511
 
6 7u83 512
	/* Set member */
513
	COPY_nspace(id_parent(id), ns);
514
	if (type) {
515
		set_type_member(mem, id);
2 7u83 516
	} else {
6 7u83 517
		set_member(mem, id);
2 7u83 518
	}
6 7u83 519
	return;
2 7u83 520
}
521
 
522
 
523
/*
524
    MERGE TWO NAMESPACES
525
 
526
    This routine merges the namespace ns with the additional members
527
    read from a spec input file given by pns.
528
*/
529
 
6 7u83 530
void
531
merge_namespaces(NAMESPACE ns, NAMESPACE pns)
2 7u83 532
{
6 7u83 533
	MEMBER mem = DEREF_member(nspace_named_etc_first(pns));
534
	LIST(IDENTIFIER) ids = DEREF_list(nspace_named_etc_extra(pns));
535
	force_merge++;
536
	while (!IS_NULL_member(mem)) {
537
		IDENTIFIER id = DEREF_id(member_id(mem));
538
		IDENTIFIER alt = DEREF_id(member_alt(mem));
539
		if (!IS_NULL_id(id)) {
540
			merge_id(ns, id);
541
		}
542
		if (!IS_NULL_id(alt) && !EQ_id(id, alt)) {
543
			merge_id(ns, alt);
544
		}
545
		mem = DEREF_member(member_next(mem));
2 7u83 546
	}
6 7u83 547
	while (!IS_NULL_list(ids)) {
548
		IDENTIFIER id = DEREF_id(HEAD_list(ids));
549
		expand_id(id);
550
		ids = TAIL_list(ids);
2 7u83 551
	}
6 7u83 552
	force_merge--;
553
	return;
2 7u83 554
}