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