OSDN Git Service

625f7261a92de9c5bf181e172a09feadca25f09f
[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 the DECL_ASSEMBLER_NAME is not the same as the DECL_NAME, then
285      either we already created RTL for this DECL (and since it was a
286      local variable, its DECL_ASSMEMBLER_NAME got hacked up to prevent
287      clashes with other local statics with the same name by a previous
288      call to make_decl_rtl), or the user explicitly requested a
289      particular assembly name for this variable, using the GNU
290      extension for this purpose:
291
292        int i asm ("j");
293
294      There's no way to know which case we're in, here.  But, it turns
295      out we're safe.  If there's already RTL, then
296      rest_of_decl_compilation ignores the ASMSPEC parameter, so we
297      may as well not pass it in.  If there isn't RTL, then we didn't
298      already create RTL, which means that the modification to
299      DECL_ASSEMBLER_NAME came only via the explicit extension.  */
300   if (DECL_ASSEMBLER_NAME (decl) != DECL_NAME (decl)
301       && !DECL_RTL (decl))
302     asmspec = IDENTIFIER_POINTER (DECL_ASSEMBLER_NAME (decl));
303
304   rest_of_decl_compilation (decl, asmspec, /*top_level=*/0, /*at_end=*/0);
305 }
306
307 /* Let the back-end know about DECL.  */
308
309 void
310 emit_local_var (decl)
311      tree decl;
312 {
313   /* Create RTL for this variable.  */
314   if (!DECL_RTL (decl))
315     {
316       if (DECL_ASSEMBLER_NAME (decl) != DECL_NAME (decl))
317         /* The user must have specified an assembler name for this
318            variable.  Set that up now.  */
319         rest_of_decl_compilation
320           (decl, IDENTIFIER_POINTER (DECL_ASSEMBLER_NAME (decl)),
321            /*top_level=*/0, /*at_end=*/0);
322       else
323         expand_decl (decl);
324     }
325
326   /* Actually do the initialization.  */
327   if (stmts_are_full_exprs_p ())
328     expand_start_target_temps ();
329
330   expand_decl_init (decl);
331
332   if (stmts_are_full_exprs_p ())
333     expand_end_target_temps ();
334 }
335
336 /* Helper for generating the RTL at the beginning of a scope. */
337
338 void
339 genrtl_do_pushlevel ()
340 {
341   emit_line_note (input_filename, lineno);
342   clear_last_expr ();
343 }
344
345 /* Generate the RTL for DESTINATION, which is a GOTO_STMT. */
346
347 void
348 genrtl_goto_stmt (destination)
349      tree destination;
350 {
351   if (TREE_CODE (destination) == IDENTIFIER_NODE)
352     abort ();
353   
354   /* We warn about unused labels with -Wunused.  That means we have to
355      mark the used labels as used.  */
356   if (TREE_CODE (destination) == LABEL_DECL)
357     TREE_USED (destination) = 1;
358   
359   emit_line_note (input_filename, lineno);
360   
361   if (TREE_CODE (destination) == LABEL_DECL)
362     {
363       label_rtx (destination);
364       expand_goto (destination); 
365     }
366   else
367     expand_computed_goto (destination);
368 }
369
370 /* Generate the RTL for EXPR, which is an EXPR_STMT. */
371
372 void 
373 genrtl_expr_stmt (expr)
374      tree expr;
375 {
376   if (expr != NULL_TREE)
377     {
378       emit_line_note (input_filename, lineno);
379       
380       if (stmts_are_full_exprs_p ())
381         expand_start_target_temps ();
382       
383       if (expr != error_mark_node)
384         expand_expr_stmt (expr);
385       
386       if (stmts_are_full_exprs_p ())
387         expand_end_target_temps ();
388     }
389 }
390
391 /* Generate the RTL for T, which is a DECL_STMT. */
392
393 void
394 genrtl_decl_stmt (t)
395      tree t;
396 {
397   tree decl;
398   emit_line_note (input_filename, lineno);
399   decl = DECL_STMT_DECL (t);
400   /* If this is a declaration for an automatic local
401      variable, initialize it.  Note that we might also see a
402      declaration for a namespace-scope object (declared with
403      `extern').  We don't have to handle the initialization
404      of those objects here; they can only be declarations,
405      rather than definitions.  */
406   if (TREE_CODE (decl) == VAR_DECL 
407       && !TREE_STATIC (decl)
408       && !DECL_EXTERNAL (decl))
409     {
410       /* Let the back-end know about this variable.  */
411       if (!anon_aggr_type_p (TREE_TYPE (decl)))
412         emit_local_var (decl);
413       else
414         expand_anon_union_decl (decl, NULL_TREE, 
415                                 DECL_ANON_UNION_ELEMS (decl));
416     }
417   else if (TREE_CODE (decl) == VAR_DECL && TREE_STATIC (decl))
418     {
419       if (DECL_ARTIFICIAL (decl) && ! TREE_USED (decl))
420         /* Do not emit unused decls. This is not just an
421            optimization. We really do not want to emit
422            __PRETTY_FUNCTION__ etc, if they're never used.  */
423         DECL_IGNORED_P (decl) = 1;
424       else
425         make_rtl_for_local_static (decl);
426     }
427   else if (TREE_CODE (decl) == LABEL_DECL 
428            && C_DECLARED_LABEL_FLAG (decl))
429     declare_nonlocal_label (decl);
430   else if (lang_expand_decl_stmt)
431     (*lang_expand_decl_stmt) (t);
432 }
433
434 /* Generate the RTL for T, which is an IF_STMT. */
435
436 void
437 genrtl_if_stmt (t)
438      tree t;
439 {
440   tree cond;
441   genrtl_do_pushlevel ();
442   cond = expand_cond (IF_COND (t));
443   emit_line_note (input_filename, lineno);
444   expand_start_cond (cond, 0);
445   if (THEN_CLAUSE (t))
446     expand_stmt (THEN_CLAUSE (t));
447   if (ELSE_CLAUSE (t))
448     {
449       expand_start_else ();
450       expand_stmt (ELSE_CLAUSE (t));
451     }
452   expand_end_cond ();
453 }
454
455 /* Generate the RTL for T, which is a WHILE_STMT. */
456
457 void
458 genrtl_while_stmt (t)
459      tree t;
460 {
461   tree cond;
462   emit_nop ();
463   emit_line_note (input_filename, lineno);
464   expand_start_loop (1); 
465   genrtl_do_pushlevel ();
466
467   cond = expand_cond (WHILE_COND (t));
468   emit_line_note (input_filename, lineno);
469   expand_exit_loop_if_false (0, cond);
470   genrtl_do_pushlevel ();
471   
472   expand_stmt (WHILE_BODY (t));
473
474   expand_end_loop ();
475 }
476
477 /* Generate the RTL for T, which is a DO_STMT. */
478
479 void
480 genrtl_do_stmt (t)
481      tree t;
482 {
483   tree cond = DO_COND (t);
484
485   /* Recognize the common special-case of do { ... } while (0) and do
486      not emit the loop widgetry in this case.  In particular this
487      avoids cluttering the rtl with dummy loop notes, which can affect
488      alignment of adjacent labels.  */
489   if (integer_zerop (cond))
490     expand_stmt (DO_BODY (t));
491   else
492     {
493       emit_nop ();
494       emit_line_note (input_filename, lineno);
495       expand_start_loop_continue_elsewhere (1);
496
497       expand_stmt (DO_BODY (t));
498
499       expand_loop_continue_here ();
500       cond = expand_cond (cond);
501       emit_line_note (input_filename, lineno);
502       expand_exit_loop_if_false (0, cond);
503       expand_end_loop ();
504     }
505 }
506
507 /* Build the node for a return statement and return it. */
508
509 tree
510 build_return_stmt (expr)
511      tree expr;
512 {
513   return (build_stmt (RETURN_STMT, expr));
514 }
515
516 /* Generate the RTL for STMT, which is a RETURN_STMT. */
517
518 void
519 genrtl_return_stmt (stmt)
520      tree stmt;
521 {
522   tree expr = RETURN_EXPR (stmt);
523
524   emit_line_note (input_filename, lineno);
525   if (!expr)
526     expand_null_return ();
527   else
528     {
529       expand_start_target_temps ();
530       expand_return (expr);
531       expand_end_target_temps ();
532     }
533 }
534
535 /* Generate the RTL for T, which is a FOR_STMT. */
536
537 void
538 genrtl_for_stmt (t)
539      tree t;
540 {
541   tree cond;
542   const char *saved_filename;
543   int saved_lineno;
544
545   if (NEW_FOR_SCOPE_P (t))
546     genrtl_do_pushlevel ();
547
548   expand_stmt (FOR_INIT_STMT (t));
549
550   /* Expand the initialization.  */
551   emit_nop ();
552   emit_line_note (input_filename, lineno);
553   expand_start_loop_continue_elsewhere (1); 
554   genrtl_do_pushlevel ();
555   cond = expand_cond (FOR_COND (t));
556
557   /* Save the filename and line number so that we expand the FOR_EXPR
558      we can reset them back to the saved values.  */
559   saved_filename = input_filename;
560   saved_lineno = lineno;
561
562   /* Expand the condition.  */
563   emit_line_note (input_filename, lineno);
564   if (cond)
565     expand_exit_loop_if_false (0, cond);
566
567   /* Expand the body.  */
568   genrtl_do_pushlevel ();
569   expand_stmt (FOR_BODY (t));
570
571   /* Expand the increment expression.  */
572   input_filename = saved_filename;
573   lineno = saved_lineno;
574   emit_line_note (input_filename, lineno);
575   expand_loop_continue_here ();
576   if (FOR_EXPR (t))
577     genrtl_expr_stmt (FOR_EXPR (t));
578   expand_end_loop ();
579 }
580
581 /* Build a break statement node and return it. */
582
583 tree
584 build_break_stmt ()
585 {
586   return (build_stmt (BREAK_STMT));
587 }
588
589 /* Generate the RTL for a BREAK_STMT. */
590
591 void
592 genrtl_break_stmt ()
593 {
594   emit_line_note (input_filename, lineno);
595   if ( ! expand_exit_something ())
596     error ("break statement not within loop or switch");
597 }
598
599 /* Build a continue statement node and return it. */
600
601 tree
602 build_continue_stmt ()
603 {
604   return (build_stmt (CONTINUE_STMT));
605 }
606
607 /* Generate the RTL for a CONTINUE_STMT. */
608
609 void
610 genrtl_continue_stmt ()
611 {
612   emit_line_note (input_filename, lineno);
613   if (! expand_continue_loop (0))
614     error ("continue statement not within a loop");   
615 }
616
617 /* Generate the RTL for T, which is a SCOPE_STMT. */
618
619 void
620 genrtl_scope_stmt (t)
621      tree t;
622 {
623   if (!SCOPE_NO_CLEANUPS_P (t))
624     {
625       if (SCOPE_BEGIN_P (t))
626         expand_start_bindings_and_block (2 * SCOPE_NULLIFIED_P (t),
627                                          SCOPE_STMT_BLOCK (t));
628       else if (SCOPE_END_P (t))
629         expand_end_bindings (NULL_TREE, !SCOPE_NULLIFIED_P (t), 0);
630     }
631   else if (!SCOPE_NULLIFIED_P (t))
632     {
633       rtx note = emit_note (NULL,
634                             (SCOPE_BEGIN_P (t) 
635                              ? NOTE_INSN_BLOCK_BEG
636                              : NOTE_INSN_BLOCK_END));
637       NOTE_BLOCK (note) = SCOPE_STMT_BLOCK (t);
638     }
639 }
640
641 /* Generate the RTL for T, which is a SWITCH_STMT. */
642
643 void
644 genrtl_switch_stmt (t)
645      tree t;
646 {
647   tree cond;
648   genrtl_do_pushlevel ();
649  
650   cond = expand_cond (SWITCH_COND (t));
651   if (cond == error_mark_node)
652     /* The code is in error, but we don't want expand_end_case to
653        crash. */
654     cond = boolean_false_node;
655
656   emit_line_note (input_filename, lineno);
657   expand_start_case (1, cond, TREE_TYPE (cond), "switch statement");
658   expand_stmt (SWITCH_BODY (t));
659   expand_end_case (cond);
660 }
661
662 /* Create a CASE_LABEL tree node and return it. */
663
664 tree
665 build_case_label (low_value, high_value, label_decl)
666      tree low_value;
667      tree high_value;
668      tree label_decl;
669 {
670   return build_stmt (CASE_LABEL, low_value, high_value, label_decl);
671 }
672
673
674 /* Generate the RTL for a CASE_LABEL. */
675
676 void 
677 genrtl_case_label (case_label)
678      tree case_label;
679 {
680   tree duplicate;
681   tree cleanup;
682
683   cleanup = last_cleanup_this_contour ();
684   if (cleanup)
685     {
686       static int explained = 0;
687       warning_with_decl (TREE_PURPOSE (cleanup), 
688                          "destructor needed for `%#D'");
689       warning ("where case label appears here");
690       if (!explained)
691         {
692           warning ("(enclose actions of previous case statements requiring destructors in their own scope.)");
693           explained = 1;
694         }
695     }
696
697   add_case_node (CASE_LOW (case_label), CASE_HIGH (case_label), 
698                  CASE_LABEL_DECL (case_label), &duplicate);
699 }
700
701 /* Generate the RTL for T, which is a COMPOUND_STMT. */
702
703 void
704 genrtl_compound_stmt (t)
705     tree t;
706 {
707   expand_stmt (COMPOUND_BODY (t));
708 }
709
710 /* Generate the RTL for an ASM_STMT. */
711
712 void
713 genrtl_asm_stmt (cv_qualifier, string, output_operands,
714                  input_operands, clobbers)
715      tree cv_qualifier;
716      tree string;
717      tree output_operands;
718      tree input_operands;
719      tree clobbers;
720 {
721   if (cv_qualifier != NULL_TREE
722       && cv_qualifier != ridpointers[(int) RID_VOLATILE])
723     {
724       warning ("%s qualifier ignored on asm",
725                IDENTIFIER_POINTER (cv_qualifier));
726       cv_qualifier = NULL_TREE;
727     }
728
729   emit_line_note (input_filename, lineno);
730   if (output_operands != NULL_TREE || input_operands != NULL_TREE
731       || clobbers != NULL_TREE)
732       c_expand_asm_operands (string, output_operands,
733                              input_operands, 
734                              clobbers,
735                              cv_qualifier != NULL_TREE,
736                              input_filename, lineno);
737   else
738     expand_asm (string);
739 }
740
741 /* Generate the RTL for a DECL_CLEANUP. */
742
743 void 
744 genrtl_decl_cleanup (decl, cleanup)
745      tree decl;
746      tree cleanup;
747 {
748   if (!decl || (DECL_SIZE (decl) && TREE_TYPE (decl) != error_mark_node))
749     expand_decl_cleanup (decl, cleanup);
750 }
751
752 /* We're about to expand T, a statement.  Set up appropriate context
753    for the substitution.  */
754
755 void
756 prep_stmt (t)
757      tree t;
758 {
759   if (!STMT_LINENO_FOR_FN_P (t))
760     lineno = STMT_LINENO (t);
761   current_stmt_tree ()->stmts_are_full_exprs_p = STMT_IS_FULL_EXPR_P (t);
762 }
763
764 /* Generate the RTL for the statement T, its substatements, and any
765    other statements at its nesting level. */
766
767 void
768 expand_stmt (t)
769      tree t;
770 {
771   while (t && t != error_mark_node)
772     {
773       int saved_stmts_are_full_exprs_p;
774
775       /* Set up context appropriately for handling this statement.  */
776       saved_stmts_are_full_exprs_p = stmts_are_full_exprs_p ();
777       prep_stmt (t);
778
779       switch (TREE_CODE (t))
780         {
781         case RETURN_STMT:
782           genrtl_return_stmt (t);
783           break;
784
785         case EXPR_STMT:
786           genrtl_expr_stmt (EXPR_STMT_EXPR (t));
787           break;
788
789         case DECL_STMT:
790           genrtl_decl_stmt (t);
791           break;
792
793         case FOR_STMT:
794           genrtl_for_stmt (t);
795           break;
796
797         case WHILE_STMT:
798           genrtl_while_stmt (t);
799           break;
800
801         case DO_STMT:
802           genrtl_do_stmt (t);
803           break;
804
805         case IF_STMT:
806           genrtl_if_stmt (t);
807           break;
808
809         case COMPOUND_STMT:
810           genrtl_compound_stmt (t);
811           break;
812
813         case BREAK_STMT:
814           genrtl_break_stmt ();
815           break;
816
817         case CONTINUE_STMT:
818           genrtl_continue_stmt ();
819           break;
820
821         case SWITCH_STMT:
822           genrtl_switch_stmt (t);
823           break;
824
825         case CASE_LABEL:
826           genrtl_case_label (t);
827           break;
828
829         case LABEL_STMT:
830           expand_label (LABEL_STMT_LABEL (t));
831           break;
832
833         case GOTO_STMT:
834           genrtl_goto_stmt (GOTO_DESTINATION (t));
835           break;
836
837         case ASM_STMT:
838           genrtl_asm_stmt (ASM_CV_QUAL (t), ASM_STRING (t),
839                            ASM_OUTPUTS (t), ASM_INPUTS (t), ASM_CLOBBERS (t));
840           break;
841
842         case SCOPE_STMT:
843           genrtl_scope_stmt (t);
844           break;
845
846         default:
847           if (lang_expand_stmt)
848             (*lang_expand_stmt) (t);
849           else 
850             abort ();
851           break;
852         }
853
854       /* Restore saved state.  */
855       current_stmt_tree ()->stmts_are_full_exprs_p = 
856         saved_stmts_are_full_exprs_p;
857
858       /* Go on to the next statement in this scope.  */
859       t = TREE_CHAIN (t);
860     }
861 }
862