OSDN Git Service

2000-09-25 Kazu Hirata <kazu@hxi.com>
[pf3gnuchains/gcc-fork.git] / gcc / c-semantics.c
1 /* This file contains the definitions and documentation for the common
2    tree codes used in the GNU C and C++ compilers (see c-common.def
3    for the standard codes).  
4    Copyright (C) 2000 Free Software Foundation, Inc.  Written by
5    Benjamin Chelf (chelf@codesourcery.com).
6
7 This file is part of GNU CC.
8
9 GNU CC is free software; you can redistribute it and/or modify
10 it under the terms of the GNU General Public License as published by
11 the Free Software Foundation; either version 2, or (at your option)
12 any later version.
13
14 GNU CC is distributed in the hope that it will be useful,
15 but WITHOUT ANY WARRANTY; without even the implied warranty of
16 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
17 GNU General Public License for more details.
18
19 You should have received a copy of the GNU General Public License
20 along with GNU CC; see the file COPYING.  If not, write to
21 the Free Software Foundation, 59 Temple Place - Suite 330,
22 Boston, MA 02111-1307, USA.  */
23
24 #include "config.h"
25 #include "system.h"
26 #include "tree.h"
27 #include "function.h"
28 #include "splay-tree.h"
29 #include "varray.h"
30 #include "c-common.h"
31 #include "except.h"
32 #include "toplev.h"
33 #include "flags.h"
34 #include "ggc.h"
35 #include "rtl.h"
36 #include "output.h"
37 #include "timevar.h"
38
39 /* If non-NULL, the address of a language-specific function for
40    expanding statements.  */
41 void (*lang_expand_stmt) PARAMS ((tree));
42
43 /* If non-NULL, the address of a language-specific function for
44    expanding a DECL_STMT.  After the language-independent cases are
45    handled, this function will be called.  If this function is not
46    defined, it is assumed that declarations other than those for
47    variables and labels do not require any RTL generation.  */
48 void (*lang_expand_decl_stmt) PARAMS ((tree));
49
50 static tree prune_unused_decls PARAMS ((tree *, int *, void *));
51
52 /* Create an empty statement tree rooted at T.  */
53
54 void
55 begin_stmt_tree (t)
56      tree *t;
57 {
58   /* We create a trivial EXPR_STMT so that last_tree is never NULL in
59      what follows.  We remove the extraneous statement in
60      finish_stmt_tree.  */
61   *t = build_nt (EXPR_STMT, void_zero_node);
62   last_tree = *t;
63   last_expr_type = NULL_TREE;
64 }
65
66 /* T is a statement.  Add it to the statement-tree.  */
67
68 tree
69 add_stmt (t)
70      tree t;
71 {
72   /* Add T to the statement-tree.  */
73   TREE_CHAIN (last_tree) = t;
74   last_tree = t;
75   /* When we expand a statement-tree, we must know whether or not the
76      statements are full-expresions.  We record that fact here.  */
77   STMT_IS_FULL_EXPR_P (last_tree) = stmts_are_full_exprs_p ();
78   return t;
79 }
80
81 /* Create a declaration statement for the declaration given by the
82    DECL.  */
83
84 void
85 add_decl_stmt (decl)
86      tree decl;
87 {
88   tree decl_stmt;
89
90   /* We need the type to last until instantiation time.  */
91   decl_stmt = build_stmt (DECL_STMT, decl);
92   add_stmt (decl_stmt); 
93 }
94
95 /* Add a scope-statement to the statement-tree.  BEGIN_P indicates
96    whether this statements opens or closes a scope.  PARTIAL_P is true
97    for a partial scope, i.e, the scope that begins after a label when
98    an object that needs a cleanup is created.  If BEGIN_P is nonzero,
99    returns a new TREE_LIST representing the top of the SCOPE_STMT
100    stack.  The TREE_PURPOSE is the new SCOPE_STMT.  If BEGIN_P is
101    zero, returns a TREE_LIST whose TREE_VALUE is the new SCOPE_STMT,
102    and whose TREE_PURPOSE is the matching SCOPE_STMT iwth
103    SCOPE_BEGIN_P set.  */
104
105 tree
106 add_scope_stmt (begin_p, partial_p)
107      int begin_p;
108      int partial_p;
109 {
110   tree ss;
111   tree top;
112
113   /* Build the statement.  */
114   ss = build_stmt (SCOPE_STMT, NULL_TREE);
115   SCOPE_BEGIN_P (ss) = begin_p;
116   SCOPE_PARTIAL_P (ss) = partial_p;
117
118   /* Keep the scope stack up to date.  */
119   if (begin_p)
120     {
121       *current_scope_stmt_stack () 
122         = tree_cons (ss, NULL_TREE, *current_scope_stmt_stack ());
123       top = *current_scope_stmt_stack ();
124     }
125   else
126     {
127       top = *current_scope_stmt_stack ();
128       TREE_VALUE (top) = ss;
129       *current_scope_stmt_stack () = TREE_CHAIN (top);
130     }
131
132   /* Add the new statement to the statement-tree.  */
133   add_stmt (ss);
134
135   return top;
136 }
137
138 /* Remove declarations of internal variables that are not used from a
139    stmt tree.  To qualify, the variable must have a name and must have
140    a zero DECL_SOURCE_LINE.  We tried to remove all variables for
141    which TREE_USED was false, but it turns out that there's tons of
142    variables for which TREE_USED is false but that are still in fact
143    used.  */
144
145 static tree
146 prune_unused_decls (tp, walk_subtrees, data)
147      tree *tp;
148      int *walk_subtrees ATTRIBUTE_UNUSED;
149      void *data ATTRIBUTE_UNUSED;
150 {
151   tree t = *tp;
152
153   if (t == NULL_TREE)
154     {
155       *walk_subtrees = 0;
156       return NULL_TREE;
157     }
158
159   if (TREE_CODE (t) == DECL_STMT)
160     {
161       tree d = DECL_STMT_DECL (t);
162       if (!TREE_USED (d) && DECL_NAME (d) && DECL_SOURCE_LINE (d) == 0)
163         {
164           *tp = TREE_CHAIN (t);
165           /* Recurse on the new value of tp, otherwise we will skip
166              the next statement.  */
167           return prune_unused_decls (tp, walk_subtrees, data);
168         }
169     }
170   else if (TREE_CODE (t) == SCOPE_STMT)
171     {
172       /* Remove all unused decls from the BLOCK of this SCOPE_STMT.  */
173       tree block = SCOPE_STMT_BLOCK (t);
174
175       if (block)
176         {
177           tree *vp;
178
179           for (vp = &BLOCK_VARS (block); *vp; )
180             {
181               tree v = *vp;
182               if (! TREE_USED (v) && DECL_NAME (v) && DECL_SOURCE_LINE (v) == 0)
183                 *vp = TREE_CHAIN (v);  /* drop */
184               else
185                 vp = &TREE_CHAIN (v);  /* advance */
186             }
187           /* If there are now no variables, the entire BLOCK can be dropped.
188              (This causes SCOPE_NULLIFIED_P (t) to be true.)  */
189           if (BLOCK_VARS (block) == NULL_TREE)
190             SCOPE_STMT_BLOCK (t) = NULL_TREE;
191         }
192     }
193   return NULL_TREE;
194 }
195
196 /* Finish the statement tree rooted at T.  */
197
198 void
199 finish_stmt_tree (t)
200      tree *t;
201 {
202   tree stmt;
203   
204   /* Remove the fake extra statement added in begin_stmt_tree.  */
205   stmt = TREE_CHAIN (*t);
206   *t = stmt;
207   last_tree = NULL_TREE;
208
209   /* Remove unused decls from the stmt tree.  */
210   walk_stmt_tree (t, prune_unused_decls, NULL);
211
212   if (cfun && stmt)
213     {
214       /* The line-number recorded in the outermost statement in a function
215          is the line number of the end of the function.  */
216       STMT_LINENO (stmt) = lineno;
217       STMT_LINENO_FOR_FN_P (stmt) = 1;
218     }
219 }
220
221 /* Build a generic statement based on the given type of node and
222    arguments. Similar to `build_nt', except that we set
223    TREE_COMPLEXITY to be the current line number.  */
224
225 tree
226 build_stmt VPARAMS ((enum tree_code code, ...))
227 {
228 #ifndef ANSI_PROTOTYPES
229   enum tree_code code;
230 #endif
231   va_list p;
232   register tree t;
233   register int length;
234   register int i;
235
236   VA_START (p, code);
237
238 #ifndef ANSI_PROTOTYPES
239   code = va_arg (p, enum tree_code);
240 #endif
241
242   t = make_node (code);
243   length = TREE_CODE_LENGTH (code);
244   TREE_COMPLEXITY (t) = lineno;
245
246   for (i = 0; i < length; i++)
247     TREE_OPERAND (t, i) = va_arg (p, tree);
248
249   va_end (p);
250   return t;
251 }
252
253 /* Some statements, like for-statements or if-statements, require a
254    condition.  This condition can be a declaration.  If T is such a
255    declaration it is processed, and an expression appropriate to use
256    as the condition is returned.  Otherwise, T itself is returned.  */
257
258 tree
259 expand_cond (t)
260      tree t;
261 {
262   if (t && TREE_CODE (t) == TREE_LIST)
263     {
264       expand_stmt (TREE_PURPOSE (t));
265       return TREE_VALUE (t);
266     }
267   else 
268     return t;
269 }
270
271 /* Create RTL for the local static variable DECL.  */
272
273 void
274 make_rtl_for_local_static (decl)
275      tree decl;
276 {
277   const char *asmspec = NULL;
278
279   /* If we inlined this variable, we could see it's declaration
280      again.  */
281   if (TREE_ASM_WRITTEN (decl))
282     return;
283
284   if (DECL_ASSEMBLER_NAME (decl) != DECL_NAME (decl))
285     {
286       /* The only way this situaton can occur is if the
287          user specified a name for this DECL using the
288          `attribute' syntax.  */
289       asmspec = IDENTIFIER_POINTER (DECL_ASSEMBLER_NAME (decl));
290       DECL_ASSEMBLER_NAME (decl) = DECL_NAME (decl);
291     }
292
293   rest_of_decl_compilation (decl, asmspec, /*top_level=*/0, /*at_end=*/0);
294 }
295
296 /* Let the back-end know about DECL.  */
297
298 void
299 emit_local_var (decl)
300      tree decl;
301 {
302   /* Create RTL for this variable.  */
303   if (!DECL_RTL (decl))
304     {
305       if (DECL_ASSEMBLER_NAME (decl) != DECL_NAME (decl))
306         /* The user must have specified an assembler name for this
307            variable.  Set that up now.  */
308         rest_of_decl_compilation
309           (decl, IDENTIFIER_POINTER (DECL_ASSEMBLER_NAME (decl)),
310            /*top_level=*/0, /*at_end=*/0);
311       else
312         expand_decl (decl);
313     }
314
315   /* Actually do the initialization.  */
316   if (stmts_are_full_exprs_p ())
317     expand_start_target_temps ();
318
319   expand_decl_init (decl);
320
321   if (stmts_are_full_exprs_p ())
322     expand_end_target_temps ();
323 }
324
325 /* Helper for generating the RTL at the beginning of a scope. */
326
327 void
328 genrtl_do_pushlevel ()
329 {
330   emit_line_note (input_filename, lineno);
331   clear_last_expr ();
332 }
333
334 /* Generate the RTL for DESTINATION, which is a GOTO_STMT. */
335
336 void
337 genrtl_goto_stmt (destination)
338      tree destination;
339 {
340   if (TREE_CODE (destination) == IDENTIFIER_NODE)
341     abort ();
342   
343   /* We warn about unused labels with -Wunused.  That means we have to
344      mark the used labels as used.  */
345   if (TREE_CODE (destination) == LABEL_DECL)
346     TREE_USED (destination) = 1;
347   
348   emit_line_note (input_filename, lineno);
349   
350   if (TREE_CODE (destination) == LABEL_DECL)
351     {
352       label_rtx (destination);
353       expand_goto (destination); 
354     }
355   else
356     expand_computed_goto (destination);
357 }
358
359 /* Generate the RTL for EXPR, which is an EXPR_STMT. */
360
361 void 
362 genrtl_expr_stmt (expr)
363      tree expr;
364 {
365   if (expr != NULL_TREE)
366     {
367       emit_line_note (input_filename, lineno);
368       
369       if (stmts_are_full_exprs_p ())
370         expand_start_target_temps ();
371       
372       if (expr != error_mark_node)
373         expand_expr_stmt (expr);
374       
375       if (stmts_are_full_exprs_p ())
376         expand_end_target_temps ();
377     }
378 }
379
380 /* Generate the RTL for T, which is a DECL_STMT. */
381
382 void
383 genrtl_decl_stmt (t)
384      tree t;
385 {
386   tree decl;
387   emit_line_note (input_filename, lineno);
388   decl = DECL_STMT_DECL (t);
389   /* If this is a declaration for an automatic local
390      variable, initialize it.  Note that we might also see a
391      declaration for a namespace-scope object (declared with
392      `extern').  We don't have to handle the initialization
393      of those objects here; they can only be declarations,
394      rather than definitions.  */
395   if (TREE_CODE (decl) == VAR_DECL 
396       && !TREE_STATIC (decl)
397       && !DECL_EXTERNAL (decl))
398     {
399       /* Let the back-end know about this variable.  */
400       if (!anon_aggr_type_p (TREE_TYPE (decl)))
401         emit_local_var (decl);
402       else
403         expand_anon_union_decl (decl, NULL_TREE, 
404                                 DECL_ANON_UNION_ELEMS (decl));
405     }
406   else if (TREE_CODE (decl) == VAR_DECL && TREE_STATIC (decl))
407     {
408       if (DECL_ARTIFICIAL (decl) && ! TREE_USED (decl))
409         /* Do not emit unused decls. This is not just an
410            optimization. We really do not want to emit
411            __PRETTY_FUNCTION__ etc, if they're never used.  */
412         DECL_IGNORED_P (decl) = 1;
413       else
414         make_rtl_for_local_static (decl);
415     }
416   else if (TREE_CODE (decl) == LABEL_DECL 
417            && C_DECLARED_LABEL_FLAG (decl))
418     declare_nonlocal_label (decl);
419   else if (lang_expand_decl_stmt)
420     (*lang_expand_decl_stmt) (t);
421 }
422
423 /* Generate the RTL for T, which is an IF_STMT. */
424
425 void
426 genrtl_if_stmt (t)
427      tree t;
428 {
429   tree cond;
430   genrtl_do_pushlevel ();
431   cond = expand_cond (IF_COND (t));
432   emit_line_note (input_filename, lineno);
433   expand_start_cond (cond, 0);
434   if (THEN_CLAUSE (t))
435     expand_stmt (THEN_CLAUSE (t));
436   if (ELSE_CLAUSE (t))
437     {
438       expand_start_else ();
439       expand_stmt (ELSE_CLAUSE (t));
440     }
441   expand_end_cond ();
442 }
443
444 /* Generate the RTL for T, which is a WHILE_STMT. */
445
446 void
447 genrtl_while_stmt (t)
448      tree t;
449 {
450   tree cond;
451   emit_nop ();
452   emit_line_note (input_filename, lineno);
453   expand_start_loop (1); 
454   genrtl_do_pushlevel ();
455
456   cond = expand_cond (WHILE_COND (t));
457   emit_line_note (input_filename, lineno);
458   expand_exit_loop_if_false (0, cond);
459   genrtl_do_pushlevel ();
460   
461   expand_stmt (WHILE_BODY (t));
462
463   expand_end_loop ();
464 }
465
466 /* Generate the RTL for T, which is a DO_STMT. */
467
468 void
469 genrtl_do_stmt (t)
470      tree t;
471 {
472   tree cond;
473   emit_nop ();
474   emit_line_note (input_filename, lineno);
475   expand_start_loop_continue_elsewhere (1);
476
477   expand_stmt (DO_BODY (t));
478
479   expand_loop_continue_here ();
480
481   cond = expand_cond (DO_COND (t));
482   emit_line_note (input_filename, lineno);
483   expand_exit_loop_if_false (0, cond);
484   expand_end_loop ();
485 }
486
487 /* Build the node for a return statement and return it. */
488
489 tree
490 build_return_stmt (expr)
491      tree expr;
492 {
493   return (build_stmt (RETURN_STMT, expr));
494 }
495
496 /* Generate the RTL for STMT, which is a RETURN_STMT. */
497
498 void
499 genrtl_return_stmt (stmt)
500      tree stmt;
501 {
502   tree expr = RETURN_EXPR (stmt);
503
504   emit_line_note (input_filename, lineno);
505   if (!expr)
506     expand_null_return ();
507   else
508     {
509       expand_start_target_temps ();
510       expand_return (expr);
511       expand_end_target_temps ();
512     }
513 }
514
515 /* Generate the RTL for T, which is a FOR_STMT. */
516
517 void
518 genrtl_for_stmt (t)
519      tree t;
520 {
521   tree cond;
522   const char *saved_filename;
523   int saved_lineno;
524
525   if (NEW_FOR_SCOPE_P (t))
526     genrtl_do_pushlevel ();
527
528   expand_stmt (FOR_INIT_STMT (t));
529
530   /* Expand the initialization.  */
531   emit_nop ();
532   emit_line_note (input_filename, lineno);
533   expand_start_loop_continue_elsewhere (1); 
534   genrtl_do_pushlevel ();
535   cond = expand_cond (FOR_COND (t));
536
537   /* Save the filename and line number so that we expand the FOR_EXPR
538      we can reset them back to the saved values.  */
539   saved_filename = input_filename;
540   saved_lineno = lineno;
541
542   /* Expand the condition.  */
543   emit_line_note (input_filename, lineno);
544   if (cond)
545     expand_exit_loop_if_false (0, cond);
546
547   /* Expand the body.  */
548   genrtl_do_pushlevel ();
549   expand_stmt (FOR_BODY (t));
550
551   /* Expand the increment expression.  */
552   input_filename = saved_filename;
553   lineno = saved_lineno;
554   emit_line_note (input_filename, lineno);
555   expand_loop_continue_here ();
556   if (FOR_EXPR (t))
557     genrtl_expr_stmt (FOR_EXPR (t));
558   expand_end_loop ();
559 }
560
561 /* Build a break statement node and return it. */
562
563 tree
564 build_break_stmt ()
565 {
566   return (build_stmt (BREAK_STMT));
567 }
568
569 /* Generate the RTL for a BREAK_STMT. */
570
571 void
572 genrtl_break_stmt ()
573 {
574   emit_line_note (input_filename, lineno);
575   if ( ! expand_exit_something ())
576     error ("break statement not within loop or switch");
577 }
578
579 /* Build a continue statement node and return it. */
580
581 tree
582 build_continue_stmt ()
583 {
584   return (build_stmt (CONTINUE_STMT));
585 }
586
587 /* Generate the RTL for a CONTINUE_STMT. */
588
589 void
590 genrtl_continue_stmt ()
591 {
592   emit_line_note (input_filename, lineno);
593   if (! expand_continue_loop (0))
594     error ("continue statement not within a loop");   
595 }
596
597 /* Generate the RTL for T, which is a SCOPE_STMT. */
598
599 void
600 genrtl_scope_stmt (t)
601      tree t;
602 {
603   if (!SCOPE_NO_CLEANUPS_P (t))
604     {
605       if (SCOPE_BEGIN_P (t))
606         expand_start_bindings_and_block (2 * SCOPE_NULLIFIED_P (t),
607                                          SCOPE_STMT_BLOCK (t));
608       else if (SCOPE_END_P (t))
609         expand_end_bindings (NULL_TREE, !SCOPE_NULLIFIED_P (t), 0);
610     }
611   else if (!SCOPE_NULLIFIED_P (t))
612     {
613       rtx note = emit_note (NULL,
614                             (SCOPE_BEGIN_P (t) 
615                              ? NOTE_INSN_BLOCK_BEG
616                              : NOTE_INSN_BLOCK_END));
617       NOTE_BLOCK (note) = SCOPE_STMT_BLOCK (t);
618     }
619 }
620
621 /* Generate the RTL for T, which is a SWITCH_STMT. */
622
623 void
624 genrtl_switch_stmt (t)
625      tree t;
626 {
627   tree cond;
628   genrtl_do_pushlevel ();
629  
630   cond = expand_cond (SWITCH_COND (t));
631   if (cond == error_mark_node)
632     /* The code is in error, but we don't want expand_end_case to
633        crash. */
634     cond = boolean_false_node;
635
636   emit_line_note (input_filename, lineno);
637   expand_start_case (1, cond, TREE_TYPE (cond), "switch statement");
638   expand_stmt (SWITCH_BODY (t));
639   expand_end_case (cond);
640 }
641
642 /* Create a CASE_LABEL tree node and return it. */
643
644 tree
645 build_case_label (low_value, high_value, label_decl)
646      tree low_value;
647      tree high_value;
648      tree label_decl;
649 {
650   return build_stmt (CASE_LABEL, low_value, high_value, label_decl);
651 }
652
653
654 /* Generate the RTL for a CASE_LABEL. */
655
656 void 
657 genrtl_case_label (case_label)
658      tree case_label;
659 {
660   tree duplicate;
661   tree cleanup;
662
663   cleanup = last_cleanup_this_contour ();
664   if (cleanup)
665     {
666       static int explained = 0;
667       warning_with_decl (TREE_PURPOSE (cleanup), 
668                          "destructor needed for `%#D'");
669       warning ("where case label appears here");
670       if (!explained)
671         {
672           warning ("(enclose actions of previous case statements requiring destructors in their own scope.)");
673           explained = 1;
674         }
675     }
676
677   add_case_node (CASE_LOW (case_label), CASE_HIGH (case_label), 
678                  CASE_LABEL_DECL (case_label), &duplicate);
679 }
680
681 /* Generate the RTL for T, which is a COMPOUND_STMT. */
682
683 void
684 genrtl_compound_stmt (t)
685     tree t;
686 {
687   expand_stmt (COMPOUND_BODY (t));
688 }
689
690 /* Generate the RTL for an ASM_STMT. */
691
692 void
693 genrtl_asm_stmt (cv_qualifier, string, output_operands,
694                  input_operands, clobbers)
695      tree cv_qualifier;
696      tree string;
697      tree output_operands;
698      tree input_operands;
699      tree clobbers;
700 {
701   if (cv_qualifier != NULL_TREE
702       && cv_qualifier != ridpointers[(int) RID_VOLATILE])
703     {
704       warning ("%s qualifier ignored on asm",
705                IDENTIFIER_POINTER (cv_qualifier));
706       cv_qualifier = NULL_TREE;
707     }
708
709   emit_line_note (input_filename, lineno);
710   if (output_operands != NULL_TREE || input_operands != NULL_TREE
711       || clobbers != NULL_TREE)
712       c_expand_asm_operands (string, output_operands,
713                              input_operands, 
714                              clobbers,
715                              cv_qualifier != NULL_TREE,
716                              input_filename, lineno);
717   else
718     expand_asm (string);
719 }
720
721 /* Generate the RTL for a DECL_CLEANUP. */
722
723 void 
724 genrtl_decl_cleanup (decl, cleanup)
725      tree decl;
726      tree cleanup;
727 {
728   if (!decl || (DECL_SIZE (decl) && TREE_TYPE (decl) != error_mark_node))
729     expand_decl_cleanup (decl, cleanup);
730 }
731
732 /* We're about to expand T, a statement.  Set up appropriate context
733    for the substitution.  */
734
735 void
736 prep_stmt (t)
737      tree t;
738 {
739   if (!STMT_LINENO_FOR_FN_P (t))
740     lineno = STMT_LINENO (t);
741   current_stmt_tree ()->stmts_are_full_exprs_p = STMT_IS_FULL_EXPR_P (t);
742 }
743
744 /* Generate the RTL for the statement T, its substatements, and any
745    other statements at its nesting level. */
746
747 void
748 expand_stmt (t)
749      tree t;
750 {
751   while (t && t != error_mark_node)
752     {
753       int saved_stmts_are_full_exprs_p;
754
755       /* Set up context appropriately for handling this statement.  */
756       saved_stmts_are_full_exprs_p = stmts_are_full_exprs_p ();
757       prep_stmt (t);
758
759       switch (TREE_CODE (t))
760         {
761         case RETURN_STMT:
762           genrtl_return_stmt (t);
763           break;
764
765         case EXPR_STMT:
766           genrtl_expr_stmt (EXPR_STMT_EXPR (t));
767           break;
768
769         case DECL_STMT:
770           genrtl_decl_stmt (t);
771           break;
772
773         case FOR_STMT:
774           genrtl_for_stmt (t);
775           break;
776
777         case WHILE_STMT:
778           genrtl_while_stmt (t);
779           break;
780
781         case DO_STMT:
782           genrtl_do_stmt (t);
783           break;
784
785         case IF_STMT:
786           genrtl_if_stmt (t);
787           break;
788
789         case COMPOUND_STMT:
790           genrtl_compound_stmt (t);
791           break;
792
793         case BREAK_STMT:
794           genrtl_break_stmt ();
795           break;
796
797         case CONTINUE_STMT:
798           genrtl_continue_stmt ();
799           break;
800
801         case SWITCH_STMT:
802           genrtl_switch_stmt (t);
803           break;
804
805         case CASE_LABEL:
806           genrtl_case_label (t);
807           break;
808
809         case LABEL_STMT:
810           expand_label (LABEL_STMT_LABEL (t));
811           break;
812
813         case GOTO_STMT:
814           genrtl_goto_stmt (GOTO_DESTINATION (t));
815           break;
816
817         case ASM_STMT:
818           genrtl_asm_stmt (ASM_CV_QUAL (t), ASM_STRING (t),
819                            ASM_OUTPUTS (t), ASM_INPUTS (t), ASM_CLOBBERS (t));
820           break;
821
822         case SCOPE_STMT:
823           genrtl_scope_stmt (t);
824           break;
825
826         default:
827           if (lang_expand_stmt)
828             (*lang_expand_stmt) (t);
829           else 
830             abort ();
831           break;
832         }
833
834       /* Restore saved state.  */
835       current_stmt_tree ()->stmts_are_full_exprs_p = 
836         saved_stmts_are_full_exprs_p;
837
838       /* Go on to the next statement in this scope.  */
839       t = TREE_CHAIN (t);
840     }
841 }
842