Subversion Repositories tendra.SVN

Rev

Rev 7 | 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 "id_ops.h"
66
#include "nspace_ops.h"
67
#include "tok_ops.h"
68
#include "type_ops.h"
69
#include "error.h"
70
#include "catalog.h"
71
#include "access.h"
72
#include "basetype.h"
73
#include "class.h"
74
#include "declare.h"
75
#include "file.h"
76
#include "function.h"
77
#include "initialise.h"
78
#include "macro.h"
79
#include "namespace.h"
80
#include "parse.h"
81
#include "predict.h"
82
#include "rewrite.h"
83
#include "statement.h"
84
#include "syntax.h"
85
 
86
 
87
/*
88
    COUNT OF NUMBER OF SKIPPED FUNCTIONS
89
 
90
    This value is used to keep track of the number of functions skipped
91
    and subsequently compiled.
92
*/
93
 
7 7u83 94
static int functions_pending = 0;
2 7u83 95
 
96
 
97
/*
98
    SKIP A FUNCTION DEFINITION
99
 
100
    This routine skips the function definition for the function id given by
101
    the current sequence of lexical tokens.  Note that last_lex_token is
102
    set to lex_func_Hop to indicate that a function definition has been
103
    skipped.
104
*/
105
 
7 7u83 106
void
107
skip_function(IDENTIFIER id)
2 7u83 108
{
7 7u83 109
	EXP e;
110
	LOCATION loc;
111
	int t = crt_lex_token;
112
	PPTOKEN *p = crt_token;
113
	PPTOKEN *q = p;
114
	int brackets = 0;
115
	int try_block = 0;
2 7u83 116
 
7 7u83 117
	/* Check for previous definition */
118
	if (!IS_NULL_id(id)) {
119
		PTR(LOCATION)ploc = id_loc(id);
120
		COPY_loc(ploc, decl_loc);
121
		e = DEREF_exp(id_function_etc_defn(id));
122
		if (!IS_NULL_exp(e)) {
123
			/* Function already defined */
124
			report(crt_loc, ERR_basic_odr_def_func(id, ploc));
125
		}
2 7u83 126
	}
127
 
7 7u83 128
	/* Skip definition */
129
	loc = crt_loc;
130
	if (t == lex_try) {
131
		try_block = 1;
132
	}
133
	for (;;) {
134
		if (t == lex_open_Hbrace_H1 || t == lex_open_Hbrace_H2) {
135
			/* Start of block */
136
			brackets++;
137
		} else if (t == lex_close_Hbrace_H1 ||
138
			   t == lex_close_Hbrace_H2) {
139
			/* End of block */
140
			brackets--;
141
			if (brackets <= 0) {
142
				q = crt_token;
143
				t = expand_preproc(EXPAND_AHEAD);
144
				if (t != lex_catch || !try_block) {
145
					/* End of function */
146
					break;
147
				}
148
			}
149
		} else if (t == lex_semicolon && brackets == 0) {
150
			/* Premature end of function */
151
			break;
152
		} else if (t == lex_eof) {
153
			/* Premature end of file */
154
			report(loc, ERR_class_mfct_eof(id));
155
			crt_lex_token = t;
156
			return;
2 7u83 157
		}
7 7u83 158
		q = crt_token;
159
		t = expand_preproc(EXPAND_AHEAD);
2 7u83 160
	}
7 7u83 161
	last_lex_token = lex_func_Hop;
162
	crt_lex_token = t;
163
	snip_tokens(p, q);
2 7u83 164
 
7 7u83 165
	/* Create the definition */
166
	MAKE_exp_uncompiled(type_void, loc, p, e);
167
	if (!IS_NULL_id(id)) {
168
		COPY_exp(id_function_etc_defn(id), e);
169
		functions_pending++;
170
	}
171
	return;
2 7u83 172
}
173
 
174
 
175
/*
176
    SKIP A DEFAULT ARGUMENT VALUE
177
 
178
    This routine skips the default argument value for the function parameter
179
    id given by the current sequence of lexical tokens.  It returns an
180
    expression giving the skipped value which is associated with id by
181
    init_param.
182
*/
183
 
7 7u83 184
EXP
185
skip_default_arg(IDENTIFIER id)
2 7u83 186
{
7 7u83 187
	EXP e;
188
	LOCATION loc;
189
	int brackets = 0;
190
	int t = crt_lex_token;
191
	PPTOKEN *p = crt_token;
192
	PPTOKEN *q = p;
2 7u83 193
 
7 7u83 194
	/* Skip definition */
195
	loc = crt_loc;
196
	for (;;) {
197
		if (t == lex_open_Hround || t == lex_open_Htemplate) {
198
			brackets++;
199
		} else if (t == lex_close_Hround || t == lex_close_Htemplate) {
200
			if (brackets == 0) {
201
				break;
202
			}
203
			brackets--;
204
		} else if (t == lex_comma) {
205
			if (brackets == 0) {
206
				break;
207
			}
208
		} else if (t == lex_eof) {
209
			/* Premature end of file */
210
			report(loc, ERR_class_mfct_eof(id));
211
			crt_lex_token = t;
212
			return (NULL_exp);
213
		}
214
		q = crt_token;
215
		t = expand_preproc(EXPAND_AHEAD);
2 7u83 216
	}
7 7u83 217
	crt_lex_token = t;
218
	snip_tokens(p, q);
2 7u83 219
 
7 7u83 220
	/* Create the definition */
221
	MAKE_exp_uncompiled(type_error, loc, p, e);
222
	functions_pending++;
223
	return (e);
2 7u83 224
}
225
 
226
 
227
/*
228
    BRING A SET OF TEMPLATE ARGUMENTS INTO SCOPE
229
 
230
    When rescanning a template member function it is necessary to bring
231
    the template parameters back into scope.  This routine performs this
232
    operation for the template type t.  It returns the non-template
233
    component of t.
234
*/
235
 
7 7u83 236
TYPE
237
begin_templ_scope(TYPE t)
2 7u83 238
{
7 7u83 239
	if (!IS_NULL_type(t) && IS_type_templ(t)) {
240
		TYPE s = DEREF_type(type_templ_defn(t));
241
		TOKEN sort = DEREF_tok(type_templ_sort(t));
242
		NAMESPACE ns = DEREF_nspace(tok_templ_pars(sort));
243
		if (!IS_NULL_nspace(ns)) {
244
			record_location++;
245
			in_template_decl++;
246
			add_namespace(ns);
247
		}
248
		t = begin_templ_scope(s);
2 7u83 249
	}
7 7u83 250
	return (t);
2 7u83 251
}
252
 
253
 
254
/*
255
    TAKE A SET OF TEMPLATE ARGUMENTS OUT OF SCOPE
256
 
257
    This routine removes any template parameters brought into scope by
258
    begin_templ_scope.
259
*/
260
 
7 7u83 261
void
262
end_templ_scope(TYPE t)
2 7u83 263
{
7 7u83 264
	if (!IS_NULL_type(t) && IS_type_templ(t)) {
265
		TYPE s = DEREF_type(type_templ_defn(t));
266
		TOKEN sort = DEREF_tok(type_templ_sort(t));
267
		NAMESPACE ns = DEREF_nspace(tok_templ_pars(sort));
268
		end_templ_scope(s);
269
		if (!IS_NULL_nspace(ns)) {
270
			remove_namespace();
271
			in_template_decl--;
272
			record_location--;
273
		}
2 7u83 274
	}
7 7u83 275
	return;
2 7u83 276
}
277
 
278
 
279
/*
280
    COMPILE A FUNCTION DEFINITION
281
 
282
    This routine compiles any previously skipped definition for the
283
    function id.
284
*/
285
 
7 7u83 286
static void
287
rescan_function(IDENTIFIER id)
2 7u83 288
{
7 7u83 289
	EXP e = DEREF_exp(id_function_etc_defn(id));
290
	if (!IS_NULL_exp(e) && IS_exp_uncompiled(e)) {
291
		PPTOKEN *p;
292
		PARSE_STATE s;
293
		TYPE fn = DEREF_type(id_function_etc_type(id));
2 7u83 294
 
7 7u83 295
		/* Mark function as inline */
296
		DECL_SPEC ds = DEREF_dspec(id_storage(id));
297
		ds |= dspec_inline;
298
		COPY_dspec(id_storage(id), ds);
2 7u83 299
 
7 7u83 300
		/* Save current compiler state */
301
		save_state(&s, 1);
2 7u83 302
 
7 7u83 303
		/* Set parser to stored definition */
304
		DEREF_loc(exp_uncompiled_start(e), crt_loc);
305
		crt_line_changed = 1;
306
		crt_file_changed = 1;
307
		p = DEREF_pptok(exp_uncompiled_defn(e));
308
		init_parser(p);
2 7u83 309
 
7 7u83 310
		/* Start function definition */
311
		in_class_defn = 0;
312
		in_function_defn++;
313
		really_in_function_defn++;
314
		COPY_exp(id_function_etc_defn(id), NULL_exp);
315
		DEREF_loc(id_loc(id), decl_loc);
316
		IGNORE begin_templ_scope(fn);
317
		begin_function(id);
2 7u83 318
 
7 7u83 319
		/* Parse the stored function definition */
320
		ADVANCE_LEXER;
321
		parse_func(&e);
322
		if (crt_lex_token != lex_eof && !have_syntax_error) {
323
			ERROR err = ERR_lex_parse(crt_token);
324
			report(crt_loc, err);
325
			unreached_code = 1;
326
		}
2 7u83 327
 
7 7u83 328
		/* End the function definition */
329
		IGNORE end_function(id, e);
330
		end_templ_scope(fn);
2 7u83 331
 
7 7u83 332
		/* Reset the parser */
333
		restore_state(&s);
334
		p = restore_parser();
335
		free_tok_list(p);
336
		functions_pending--;
337
	}
338
	return;
2 7u83 339
}
340
 
341
 
342
/*
343
    COMPILE A DEFAULT ARGUMENT VALUE
344
 
345
    This routine compiles any previously skipped default argument value
346
    for the parameter id.
347
*/
348
 
7 7u83 349
void
350
rescan_param(IDENTIFIER id, int rescan)
2 7u83 351
{
7 7u83 352
	EXP e = DEREF_exp(id_parameter_init(id));
353
	if (!IS_NULL_exp(e) && IS_exp_uncompiled(e)) {
354
		PPTOKEN *p;
355
		PARSE_STATE s;
356
		TYPE fn = NULL_type;
357
		NAMESPACE ns = DEREF_nspace(id_parent(id));
358
		IDENTIFIER pid = DEREF_id(nspace_name(ns));
359
		if (!IS_NULL_id(pid) && IS_id_function_etc(pid)) {
360
			fn = DEREF_type(id_function_etc_type(pid));
361
		} else {
362
			CLASS_TYPE ct = crt_class;
363
			if (!IS_NULL_ctype(ct)) {
364
				pid = DEREF_id(ctype_name(ct));
365
			} else {
366
				pid = NULL_id;
367
			}
368
		}
2 7u83 369
 
7 7u83 370
		/* Save current compiler state */
371
		save_state(&s, 1);
2 7u83 372
 
7 7u83 373
		/* Set parser to stored definition */
374
		DEREF_loc(exp_uncompiled_start(e), crt_loc);
375
		crt_line_changed = 1;
376
		crt_file_changed = 1;
377
		p = DEREF_pptok(exp_uncompiled_defn(e));
378
		init_parser(p);
2 7u83 379
 
7 7u83 380
		/* Start dafault argument value */
381
		in_class_defn = 0;
382
		COPY_exp(id_parameter_init(id), NULL_exp);
383
		if (rescan) {
384
			IGNORE begin_templ_scope(fn);
385
			push_namespace(ns);
386
		}
2 7u83 387
 
7 7u83 388
		/* Parse the stored expression */
389
		ADVANCE_LEXER;
390
		in_default_arg++;
391
		parse_exp(&e);
392
		in_default_arg--;
393
		if (crt_lex_token != lex_eof && !have_syntax_error) {
394
			ERROR err = ERR_lex_parse(crt_token);
395
			report(crt_loc, err);
396
		}
2 7u83 397
 
7 7u83 398
		/* End the default argument value */
399
		init_param(id, e);
400
		if (rescan) {
401
			IGNORE pop_namespace();
402
			end_templ_scope(fn);
403
		}
2 7u83 404
 
7 7u83 405
		/* Reset the parser */
406
		if (crt_access_list.pending) {
407
			IGNORE report_access(pid);
408
		}
409
		restore_state(&s);
410
		p = restore_parser();
411
		free_tok_list(p);
412
		functions_pending--;
2 7u83 413
	}
7 7u83 414
	return;
2 7u83 415
}
416
 
417
 
418
/*
419
    COMPILE ALL FUNCTIONS IN A NAMESPACE
420
 
421
    This routine scans through the current class and any nested classes
422
    compiling any function definitions which remain uncompiled.
423
*/
424
 
7 7u83 425
void
426
rescan_functions(void)
2 7u83 427
{
7 7u83 428
	CLASS_TYPE ct = crt_class;
429
	LIST(IDENTIFIER) ft = DEREF_list(ctype_nest(ct));
430
	while (!IS_NULL_list(ft)) {
431
		IDENTIFIER id = DEREF_id(HEAD_list(ft));
432
		switch (TAG_id(id)) {
433
		case id_class_name_tag: {
434
			/* Deal with nested classes */
435
			CLASS_TYPE cs;
436
			CLASS_INFO ci;
437
			NAMESPACE cns;
438
			TYPE t = DEREF_type(id_class_name_defn(id));
439
			TYPE s = begin_templ_scope(t);
440
			cs = DEREF_ctype(type_compound_defn(s));
441
			ci = DEREF_cinfo(ctype_info(cs));
442
			if (ci & cinfo_complete) {
443
				cns = DEREF_nspace(ctype_member(cs));
444
				push_class(cs);
445
				push_namespace(cns);
446
				rescan_functions();
447
				IGNORE pop_namespace();
448
				pop_class();
449
			}
450
			end_templ_scope(t);
451
			break;
2 7u83 452
		}
7 7u83 453
		case id_function_tag:
454
		case id_mem_func_tag:
455
		case id_stat_mem_func_tag:
456
			/* Deal with inline functions (including friends) */
457
			rescan_function(id);
458
			break;
459
		case id_parameter_tag:
460
			/* Deal with default arguments */
461
			rescan_param(id, 1);
462
			break;
463
		}
464
		ft = TAIL_list(ft);
2 7u83 465
	}
7 7u83 466
	return;
2 7u83 467
}