]> git.ipfire.org Git - thirdparty/gcc.git/blame - gcc/cp/semantics.c
* pa.h: Add declarations for many functions defined in pa.c.
[thirdparty/gcc.git] / gcc / cp / semantics.c
CommitLineData
ad321293
MM
1/* Perform the semantic phase of parsing, i.e., the process of
2 building tree structure, checking semantic consistency, and
3 building RTL. These routines are used both during actual parsing
4 and during the instantiation of template functions.
5
6 Copyright (C) 1998 Free Software Foundation, Inc.
7 Written by Mark Mitchell (mmitchell@usa.net) based on code found
8 formerly in parse.y and pt.c.
9
10 This file is part of GNU CC.
11
12 GNU CC is free software; you can redistribute it and/or modify it
13 under the terms of the GNU General Public License as published by
14 the Free Software Foundation; either version 2, or (at your option)
15 any later version.
16
17 GNU CC is distributed in the hope that it will be useful, but
18 WITHOUT ANY WARRANTY; without even the implied warranty of
19 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
20 General Public License for more details.
21
22 You should have received a copy of the GNU General Public License
23 along with GNU CC; see the file COPYING. If not, write to the Free
24 Software Foundation, 59 Temple Place - Suite 330, Boston, MA
25 02111-1307, USA. */
26
27#include "config.h"
28#include <stdio.h>
29#include "tree.h"
30#include "cp-tree.h"
31#include "except.h"
32#include "lex.h"
33
34/* There routines provide a modular interface to perform many parsing
35 operations. They may therefore be used during actual parsing, or
36 during template instantiation, which may be regarded as a
37 degenerate form of parsing. Since the current g++ parser is
38 lacking in several respects, and will be reimplemented, we are
39 attempting to move most code that is not directly related to
40 parsing into this file; that will make implementing the new parser
41 much easier since it will be able to make use of these routines. */
42
43/* When parsing a template, LAST_TREE contains the last statement
44 parsed. These are chained together through the TREE_CHAIN field,
45 but often need to be re-organized since the parse is performed
46 bottom-up. This macro makes LAST_TREE the indicated SUBSTMT of
47 STMT. */
48
49#define RECHAIN_STMTS(stmt, substmt, last) \
50 do { \
51 substmt = last; \
52 TREE_CHAIN (stmt) = NULL_TREE; \
53 last_tree = stmt; \
54 } while (0)
55
56#define RECHAIN_STMTS_FROM_LAST(stmt, substmt) \
57 RECHAIN_STMTS (stmt, substmt, last_tree)
58
59#define RECHAIN_STMTS_FROM_CHAIN(stmt, substmt) \
60 RECHAIN_STMTS (stmt, substmt, TREE_CHAIN (stmt))
61
62/* Finish an expression-statement, whose EXPRESSION is as indicated. */
63
64void
65finish_expr_stmt (expr)
66 tree expr;
67{
68 if (!processing_template_decl)
69 {
70 emit_line_note (input_filename, lineno);
71 /* Do default conversion if safe and possibly important,
72 in case within ({...}). */
73 if ((TREE_CODE (TREE_TYPE (expr)) == ARRAY_TYPE
74 && lvalue_p (expr))
75 || TREE_CODE (TREE_TYPE (expr)) == FUNCTION_TYPE)
76 expr = default_conversion (expr);
77 }
78
79 cplus_expand_expr_stmt (expr);
80 clear_momentary ();
81 finish_stmt ();
82}
83
84/* Begin an if-statement. Returns a newly created IF_STMT if
85 appropriate. */
86
87tree
88begin_if_stmt ()
89{
90 tree r;
91
92 if (processing_template_decl)
93 {
94 r = build_min_nt (IF_STMT, NULL_TREE, NULL_TREE, NULL_TREE);
95 add_tree (r);
96 }
97 else
98 r = NULL_TREE;
99
100 do_pushlevel ();
101
102 return r;
103}
104
105/* Process the COND of an if-statement, which may be given by
106 IF_STMT. */
107
108void
109finish_if_stmt_cond (cond, if_stmt)
110 tree cond;
111 tree if_stmt;
112{
113 if (processing_template_decl)
114 {
115 if (last_tree != if_stmt)
116 RECHAIN_STMTS_FROM_LAST (if_stmt, IF_COND (if_stmt));
117 else
118 IF_COND (if_stmt) = cond;
119 }
120 else
121 {
122 emit_line_note (input_filename, lineno);
123 expand_start_cond (condition_conversion (cond), 0);
124 }
125}
126
127/* Finish the then-clause of an if-statement, which may be given by
128 IF_STMT. */
129
130tree
131finish_then_clause (if_stmt)
132 tree if_stmt;
133{
134 if (processing_template_decl)
135 {
136 RECHAIN_STMTS_FROM_CHAIN (if_stmt,
137 THEN_CLAUSE (if_stmt));
138 last_tree = if_stmt;
139 return if_stmt;
140 }
141 else
142 return NULL_TREE;
143}
144
145/* Begin the else-clause of an if-statement. */
146
147void
148begin_else_clause ()
149{
150 if (!processing_template_decl)
151 expand_start_else ();
152}
153
154/* Finish the else-clause of an if-statement, which may be given by
155 IF_STMT. */
156
157void
158finish_else_clause (if_stmt)
159 tree if_stmt;
160{
161 if (processing_template_decl)
162 RECHAIN_STMTS_FROM_CHAIN (if_stmt, ELSE_CLAUSE (if_stmt));
163}
164
165/* Finsh an if-statement. */
166
167void
168finish_if_stmt ()
169{
170 if (!processing_template_decl)
171 expand_end_cond ();
172
173 do_poplevel ();
174 finish_stmt ();
175}
176
177/* Begin a while-statement. Returns a newly created WHILE_STMT if
178 appropriate. */
179
180tree
181begin_while_stmt ()
182{
183 tree r;
184
185 if (processing_template_decl)
186 {
187 r = build_min_nt (WHILE_STMT, NULL_TREE, NULL_TREE);
188 add_tree (r);
189 }
190 else
191 {
192 emit_nop ();
193 emit_line_note (input_filename, lineno);
194 expand_start_loop (1);
195 r = NULL_TREE;
196 }
197
198 do_pushlevel ();
199
200 return r;
201}
202
203/* Process the COND of an if-statement, which may be given by
204 WHILE_STMT. */
205
206void
207finish_while_stmt_cond (cond, while_stmt)
208 tree cond;
209 tree while_stmt;
210{
211 if (processing_template_decl)
212 {
213 if (last_tree != while_stmt)
214 RECHAIN_STMTS_FROM_LAST (while_stmt,
215 WHILE_COND (while_stmt));
216 else
217 TREE_OPERAND (while_stmt, 0) = cond;
218 }
219 else
220 {
221 emit_line_note (input_filename, lineno);
222 expand_exit_loop_if_false (0, condition_conversion (cond));
223 }
224
225 /* If COND wasn't a declaration, clear out the
226 block we made for it and start a new one here so the
227 optimization in expand_end_loop will work. */
228 if (getdecls () == NULL_TREE)
229 {
230 do_poplevel ();
231 do_pushlevel ();
232 }
233}
234
235/* Finish a while-statement, which may be given by WHILE_STMT. */
236
237void
238finish_while_stmt (while_stmt)
239 tree while_stmt;
240{
241 do_poplevel ();
242
243 if (processing_template_decl)
244 RECHAIN_STMTS_FROM_CHAIN (while_stmt, WHILE_BODY (while_stmt));
245 else
246 expand_end_loop ();
247 finish_stmt ();
248}
249
250/* Begin a do-statement. Returns a newly created DO_STMT if
251 appropriate. */
252
253tree
254begin_do_stmt ()
255{
256 if (processing_template_decl)
257 {
258 tree r = build_min_nt (DO_STMT, NULL_TREE, NULL_TREE);
259 add_tree (r);
260 return r;
261 }
262 else
263 {
264 emit_nop ();
265 emit_line_note (input_filename, lineno);
266 expand_start_loop_continue_elsewhere (1);
267 return NULL_TREE;
268 }
269}
270
271/* Finish the body of a do-statement, which may be given by DO_STMT. */
272
273void
274finish_do_body (do_stmt)
275 tree do_stmt;
276{
277 if (processing_template_decl)
278 RECHAIN_STMTS_FROM_CHAIN (do_stmt, DO_BODY (do_stmt));
279 else
280 expand_loop_continue_here ();
281}
282
283/* Finish a do-statement, which may be given by DO_STMT, and whose
284 COND is as indicated. */
285
286void
287finish_do_stmt (cond, do_stmt)
288 tree cond;
289 tree do_stmt;
290{
291 if (processing_template_decl)
292 DO_COND (do_stmt) = cond;
293 else
294 {
295 emit_line_note (input_filename, lineno);
296 expand_exit_loop_if_false (0, condition_conversion (cond));
297 expand_end_loop ();
298 }
299
300 clear_momentary ();
301 finish_stmt ();
302}
303
304/* Finish a return-statement. The EXPRESSION returned, if any, is as
305 indicated. */
306
307void
308finish_return_stmt (expr)
309 tree expr;
310{
311 emit_line_note (input_filename, lineno);
312 c_expand_return (expr);
313 finish_stmt ();
314}
315
316/* Begin a for-statement. Returns a new FOR_STMT if appropriate. */
317
318tree
319begin_for_stmt ()
320{
321 tree r;
322
323 if (processing_template_decl)
324 {
325 r = build_min_nt (FOR_STMT, NULL_TREE, NULL_TREE,
326 NULL_TREE, NULL_TREE);
327 add_tree (r);
328 }
329 else
330 r = NULL_TREE;
331
332 if (flag_new_for_scope > 0)
333 {
334 do_pushlevel ();
335 note_level_for_for ();
336 }
337
338 return r;
339}
340
341/* Finish the for-init-statement of a for-statement, which may be
342 given by FOR_STMT. */
343
344void
345finish_for_init_stmt (for_stmt)
346 tree for_stmt;
347{
348 if (processing_template_decl)
349 {
350 if (last_tree != for_stmt)
351 RECHAIN_STMTS_FROM_CHAIN (for_stmt, FOR_INIT_STMT (for_stmt));
352 }
353 else
354 {
355 emit_nop ();
356 emit_line_note (input_filename, lineno);
357 expand_start_loop_continue_elsewhere (1);
358 }
359
360 do_pushlevel ();
361}
362
363/* Finish the COND of a for-statement, which may be given by
364 FOR_STMT. */
365
366void
367finish_for_cond (cond, for_stmt)
368 tree cond;
369 tree for_stmt;
370{
371 if (processing_template_decl)
372 {
373 if (last_tree != for_stmt)
374 RECHAIN_STMTS_FROM_LAST (for_stmt, FOR_COND (for_stmt));
375 else
376 FOR_COND (for_stmt) = cond;
377 }
378 else
379 {
380 emit_line_note (input_filename, lineno);
381 if (cond)
382 expand_exit_loop_if_false (0, cond);
383 }
384
385 /* If the cond wasn't a declaration, clear out the
386 block we made for it and start a new one here so the
387 optimization in expand_end_loop will work. */
388 if (getdecls () == NULL_TREE)
389 {
390 do_poplevel ();
391 do_pushlevel ();
392 }
393}
394
395/* Finish the increment-EXPRESSION in a for-statement, which may be
396 given by FOR_STMT. */
397
398void
399finish_for_expr (expr, for_stmt)
400 tree expr;
401 tree for_stmt;
402{
403 if (processing_template_decl)
404 FOR_EXPR (for_stmt) = expr;
405
406 /* Don't let the tree nodes for EXPR be discarded
407 by clear_momentary during the parsing of the next stmt. */
408 push_momentary ();
409}
410
411/* Finish the body of a for-statement, which may be given by
412 FOR_STMT. The increment-EXPR for the loop must be
413 provided. */
414
415void
416finish_for_stmt (expr, for_stmt)
417 tree expr;
418 tree for_stmt;
419{
420 /* Pop the scope for the body of the loop. */
421 do_poplevel ();
422
423 if (processing_template_decl)
424 RECHAIN_STMTS_FROM_CHAIN (for_stmt, FOR_BODY (for_stmt));
425 else
426 {
427 emit_line_note (input_filename, lineno);
428 expand_loop_continue_here ();
429 if (expr)
430 cplus_expand_expr_stmt (expr);
431 expand_end_loop ();
432 }
433
434 pop_momentary ();
435
436 if (flag_new_for_scope > 0)
437 do_poplevel ();
438
439 finish_stmt ();
440}
441
442/* Finish a break-statement. */
443
444void
445finish_break_stmt ()
446{
447 emit_line_note (input_filename, lineno);
448 if (processing_template_decl)
449 add_tree (build_min_nt (BREAK_STMT));
450 else if ( ! expand_exit_something ())
451 cp_error ("break statement not within loop or switch");
452}
453
454/* Finish a continue-statement. */
455
456void
457finish_continue_stmt ()
458{
459 emit_line_note (input_filename, lineno);
460 if (processing_template_decl)
461 add_tree (build_min_nt (CONTINUE_STMT));
462 else if (! expand_continue_loop (0))
463 cp_error ("continue statement not within a loop");
464}
465
466/* Begin a switch-statement. */
467
468void
469begin_switch_stmt ()
470{
471 do_pushlevel ();
472}
473
474/* Finish the cond of a switch-statement. Returns a new
475 SWITCH_STMT if appropriate. */
476
477tree
478finish_switch_cond (cond)
479 tree cond;
480{
481 tree r;
482
483 if (processing_template_decl)
484 {
485 r = build_min_nt (SWITCH_STMT, cond, NULL_TREE);
486 add_tree (r);
487 }
488 else
489 {
490 emit_line_note (input_filename, lineno);
491 c_expand_start_case (cond);
492 r = NULL_TREE;
493 }
494 push_switch ();
495
496 /* Don't let the tree nodes for COND be discarded by
497 clear_momentary during the parsing of the next stmt. */
498 push_momentary ();
499
500 return r;
501}
502
503/* Finish the body of a switch-statement, which may be given by
504 SWITCH_STMT. The COND to switch on is indicated. */
505
506void
507finish_switch_stmt (cond, switch_stmt)
508 tree cond;
509 tree switch_stmt;
510{
511 if (processing_template_decl)
512 RECHAIN_STMTS_FROM_CHAIN (switch_stmt, SWITCH_BODY (switch_stmt));
513 else
514 expand_end_case (cond);
515 pop_momentary ();
516 pop_switch ();
517 do_poplevel ();
518 finish_stmt ();
519}
520
521/* Finish a case-label. */
522
523void
524finish_case_label (low_value, high_value)
525 tree low_value;
526 tree high_value;
527{
528 do_case (low_value, high_value);
529}
530
531
532/* Finish a goto-statement. */
533
534void
535finish_goto_stmt (destination)
536 tree destination;
537{
538 if (processing_template_decl)
539 add_tree (build_min_nt (GOTO_STMT, destination));
540 else
541 {
542 emit_line_note (input_filename, lineno);
543
544 if (TREE_CODE (destination) == IDENTIFIER_NODE)
545 {
546 tree decl = lookup_label (destination);
547 TREE_USED (decl) = 1;
548 expand_goto (decl);
549 }
550 else
551 expand_computed_goto (destination);
552 }
553}
554
555/* Begin a try-block. Returns a newly-created TRY_BLOCK if
556 appropriate. */
557
558tree
559begin_try_block ()
560{
561 if (processing_template_decl)
562 {
563 tree r = build_min_nt (TRY_BLOCK, NULL_TREE,
564 NULL_TREE);
565 add_tree (r);
566 return r;
567 }
568 else
569 {
570 emit_line_note (input_filename, lineno);
571 expand_start_try_stmts ();
572 return NULL_TREE;
573 }
574}
575
576/* Finish a try-block, which may be given by TRY_BLOCK. */
577
578void
579finish_try_block (try_block)
580 tree try_block;
581{
582 if (processing_template_decl)
583 RECHAIN_STMTS_FROM_LAST (try_block, TRY_STMTS (try_block));
584 else
585 expand_start_all_catch ();
586}
587
588/* Finish a handler-sequence for a try-block, which may be given by
589 TRY_BLOCK. */
590
591void
592finish_handler_sequence (try_block)
593 tree try_block;
594{
595 if (processing_template_decl)
596 RECHAIN_STMTS_FROM_CHAIN (try_block, TRY_HANDLERS (try_block));
597 else
598 expand_end_all_catch ();
599}
600
601/* Begin a handler. Returns a HANDLER if appropriate. */
602
603tree
604begin_handler ()
605{
606 tree r;
607
608 if (processing_template_decl)
609 {
610 r = build_min_nt (HANDLER, NULL_TREE, NULL_TREE);
611 add_tree (r);
612 }
613 else
614 r = NULL_TREE;
615
616 do_pushlevel ();
617
618 return r;
619}
620
621/* Finish the handler-parameters for a handler, which may be given by
622 HANDLER. */
623
624void
625finish_handler_parms (handler)
626 tree handler;
627{
628 if (processing_template_decl)
629 RECHAIN_STMTS_FROM_CHAIN (handler, HANDLER_PARMS (handler));
630}
631
632/* Finish a handler, which may be given by HANDLER. */
633
634void
635finish_handler (handler)
636 tree handler;
637{
638 if (processing_template_decl)
639 RECHAIN_STMTS_FROM_CHAIN (handler, HANDLER_BODY (handler));
640 else
641 expand_end_catch_block ();
642
643 do_poplevel ();
644}
645
646/* Begin a compound-statement. If HAS_NO_SCOPE is non-zero, the
647 compound-statement does not define a scope. Returns a new
648 COMPOUND_STMT if appropriate. */
649
650tree
651begin_compound_stmt (has_no_scope)
652 int has_no_scope;
653{
654 tree r;
655
656 if (processing_template_decl)
657 {
658 r = build_min_nt (COMPOUND_STMT, NULL_TREE);
659 add_tree (r);
660 if (has_no_scope)
661 COMPOUND_STMT_NO_SCOPE (r) = 1;
662 }
663 else
664 r = NULL_TREE;
665
666 if (!has_no_scope)
667 do_pushlevel ();
668
669 return r;
670}
671
672
673/* Finish a compound-statement, which may be given by COMPOUND_STMT.
674 If HAS_NO_SCOPE is non-zero, the compound statement does not define
675 a scope. */
676
677tree
678finish_compound_stmt (has_no_scope, compound_stmt)
679 int has_no_scope;
680 tree compound_stmt;
681{
682 tree r;
683
684 if (!has_no_scope)
685 r = do_poplevel ();
686 else
687 r = NULL_TREE;
688
689 if (processing_template_decl)
690 RECHAIN_STMTS_FROM_CHAIN (compound_stmt,
691 COMPOUND_BODY (compound_stmt));
692
693 finish_stmt ();
694
695 return r;
696}
697
698/* Finish an asm-statement, whose components are a CV_QUALIFIER, a
699 STRING, some OUTPUT_OPERANDS, some INPUT_OPERANDS, and some
700 CLOBBERS. */
701
702void
703finish_asm_stmt (cv_qualifier, string, output_operands,
704 input_operands, clobbers)
705 tree cv_qualifier;
706 tree string;
707 tree output_operands;
708 tree input_operands;
709 tree clobbers;
710{
711 if (TREE_CHAIN (string))
e6f1275f 712 string = combine_strings (string);
ad321293
MM
713
714 if (processing_template_decl)
715 {
716 tree r = build_min_nt (ASM_STMT, cv_qualifier, string,
717 output_operands, input_operands,
718 clobbers);
719 add_tree (r);
720 }
721 else
722 {
723 emit_line_note (input_filename, lineno);
e6f1275f
JM
724 if (output_operands != NULL_TREE || input_operands != NULL_TREE
725 || clobbers != NULL_TREE)
ad321293
MM
726 {
727 if (cv_qualifier != NULL_TREE
728 && cv_qualifier != ridpointers[(int) RID_VOLATILE])
729 cp_warning ("%s qualifier ignored on asm",
730 IDENTIFIER_POINTER (cv_qualifier));
731
732 c_expand_asm_operands (string, output_operands,
733 input_operands,
734 clobbers,
735 cv_qualifier
736 == ridpointers[(int) RID_VOLATILE],
737 input_filename, lineno);
738 }
739 else
740 {
741 if (cv_qualifier != NULL_TREE)
742 cp_warning ("%s qualifier ignored on asm",
743 IDENTIFIER_POINTER (cv_qualifier));
744 expand_asm (string);
745 }
746
747 finish_stmt ();
748 }
749}