OSDN Git Service

* Makefile.in (C_AND_OBJC_OBJS): Add c-dump.o.
[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_ASSEMBLER_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     {
491       expand_start_null_loop ();
492       expand_stmt (DO_BODY (t));
493       expand_end_null_loop ();
494     }
495   else
496     {
497       emit_nop ();
498       emit_line_note (input_filename, lineno);
499       expand_start_loop_continue_elsewhere (1);
500
501       expand_stmt (DO_BODY (t));
502
503       expand_loop_continue_here ();
504       cond = expand_cond (cond);
505       emit_line_note (input_filename, lineno);
506       expand_exit_loop_if_false (0, cond);
507       expand_end_loop ();
508     }
509 }
510
511 /* Build the node for a return statement and return it. */
512
513 tree
514 build_return_stmt (expr)
515      tree expr;
516 {
517   return (build_stmt (RETURN_STMT, expr));
518 }
519
520 /* Generate the RTL for STMT, which is a RETURN_STMT. */
521
522 void
523 genrtl_return_stmt (stmt)
524      tree stmt;
525 {
526   tree expr = RETURN_EXPR (stmt);
527
528   emit_line_note (input_filename, lineno);
529   if (!expr)
530     expand_null_return ();
531   else
532     {
533       expand_start_target_temps ();
534       expand_return (expr);
535       expand_end_target_temps ();
536     }
537 }
538
539 /* Generate the RTL for T, which is a FOR_STMT. */
540
541 void
542 genrtl_for_stmt (t)
543      tree t;
544 {
545   tree cond;
546   const char *saved_filename;
547   int saved_lineno;
548
549   if (NEW_FOR_SCOPE_P (t))
550     genrtl_do_pushlevel ();
551
552   expand_stmt (FOR_INIT_STMT (t));
553
554   /* Expand the initialization.  */
555   emit_nop ();
556   emit_line_note (input_filename, lineno);
557   expand_start_loop_continue_elsewhere (1); 
558   genrtl_do_pushlevel ();
559   cond = expand_cond (FOR_COND (t));
560
561   /* Save the filename and line number so that we expand the FOR_EXPR
562      we can reset them back to the saved values.  */
563   saved_filename = input_filename;
564   saved_lineno = lineno;
565
566   /* Expand the condition.  */
567   emit_line_note (input_filename, lineno);
568   if (cond)
569     expand_exit_loop_if_false (0, cond);
570
571   /* Expand the body.  */
572   genrtl_do_pushlevel ();
573   expand_stmt (FOR_BODY (t));
574
575   /* Expand the increment expression.  */
576   input_filename = saved_filename;
577   lineno = saved_lineno;
578   emit_line_note (input_filename, lineno);
579   expand_loop_continue_here ();
580   if (FOR_EXPR (t))
581     genrtl_expr_stmt (FOR_EXPR (t));
582   expand_end_loop ();
583 }
584
585 /* Build a break statement node and return it. */
586
587 tree
588 build_break_stmt ()
589 {
590   return (build_stmt (BREAK_STMT));
591 }
592
593 /* Generate the RTL for a BREAK_STMT. */
594
595 void
596 genrtl_break_stmt ()
597 {
598   emit_line_note (input_filename, lineno);
599   if ( ! expand_exit_something ())
600     error ("break statement not within loop or switch");
601 }
602
603 /* Build a continue statement node and return it. */
604
605 tree
606 build_continue_stmt ()
607 {
608   return (build_stmt (CONTINUE_STMT));
609 }
610
611 /* Generate the RTL for a CONTINUE_STMT. */
612
613 void
614 genrtl_continue_stmt ()
615 {
616   emit_line_note (input_filename, lineno);
617   if (! expand_continue_loop (0))
618     error ("continue statement not within a loop");   
619 }
620
621 /* Generate the RTL for T, which is a SCOPE_STMT. */
622
623 void
624 genrtl_scope_stmt (t)
625      tree t;
626 {
627   if (!SCOPE_NO_CLEANUPS_P (t))
628     {
629       if (SCOPE_BEGIN_P (t))
630         expand_start_bindings_and_block (2 * SCOPE_NULLIFIED_P (t),
631                                          SCOPE_STMT_BLOCK (t));
632       else if (SCOPE_END_P (t))
633         expand_end_bindings (NULL_TREE, !SCOPE_NULLIFIED_P (t), 0);
634     }
635   else if (!SCOPE_NULLIFIED_P (t))
636     {
637       rtx note = emit_note (NULL,
638                             (SCOPE_BEGIN_P (t) 
639                              ? NOTE_INSN_BLOCK_BEG
640                              : NOTE_INSN_BLOCK_END));
641       NOTE_BLOCK (note) = SCOPE_STMT_BLOCK (t);
642     }
643 }
644
645 /* Generate the RTL for T, which is a SWITCH_STMT. */
646
647 void
648 genrtl_switch_stmt (t)
649      tree t;
650 {
651   tree cond;
652   genrtl_do_pushlevel ();
653  
654   cond = expand_cond (SWITCH_COND (t));
655   if (cond == error_mark_node)
656     /* The code is in error, but we don't want expand_end_case to
657        crash. */
658     cond = boolean_false_node;
659
660   emit_line_note (input_filename, lineno);
661   expand_start_case (1, cond, TREE_TYPE (cond), "switch statement");
662   expand_stmt (SWITCH_BODY (t));
663   expand_end_case (cond);
664 }
665
666 /* Create a CASE_LABEL tree node and return it. */
667
668 tree
669 build_case_label (low_value, high_value, label_decl)
670      tree low_value;
671      tree high_value;
672      tree label_decl;
673 {
674   return build_stmt (CASE_LABEL, low_value, high_value, label_decl);
675 }
676
677
678 /* Generate the RTL for a CASE_LABEL. */
679
680 void 
681 genrtl_case_label (case_label)
682      tree case_label;
683 {
684   tree duplicate;
685   tree cleanup;
686
687   cleanup = last_cleanup_this_contour ();
688   if (cleanup)
689     {
690       static int explained = 0;
691       warning_with_decl (TREE_PURPOSE (cleanup), 
692                          "destructor needed for `%#D'");
693       warning ("where case label appears here");
694       if (!explained)
695         {
696           warning ("(enclose actions of previous case statements requiring destructors in their own scope.)");
697           explained = 1;
698         }
699     }
700
701   add_case_node (CASE_LOW (case_label), CASE_HIGH (case_label), 
702                  CASE_LABEL_DECL (case_label), &duplicate);
703 }
704
705 /* Generate the RTL for T, which is a COMPOUND_STMT. */
706
707 void
708 genrtl_compound_stmt (t)
709     tree t;
710 {
711   expand_stmt (COMPOUND_BODY (t));
712 }
713
714 /* Generate the RTL for an ASM_STMT. */
715
716 void
717 genrtl_asm_stmt (cv_qualifier, string, output_operands,
718                  input_operands, clobbers)
719      tree cv_qualifier;
720      tree string;
721      tree output_operands;
722      tree input_operands;
723      tree clobbers;
724 {
725   if (cv_qualifier != NULL_TREE
726       && cv_qualifier != ridpointers[(int) RID_VOLATILE])
727     {
728       warning ("%s qualifier ignored on asm",
729                IDENTIFIER_POINTER (cv_qualifier));
730       cv_qualifier = NULL_TREE;
731     }
732
733   emit_line_note (input_filename, lineno);
734   if (output_operands != NULL_TREE || input_operands != NULL_TREE
735       || clobbers != NULL_TREE)
736       c_expand_asm_operands (string, output_operands,
737                              input_operands, 
738                              clobbers,
739                              cv_qualifier != NULL_TREE,
740                              input_filename, lineno);
741   else
742     expand_asm (string);
743 }
744
745 /* Generate the RTL for a DECL_CLEANUP. */
746
747 void 
748 genrtl_decl_cleanup (decl, cleanup)
749      tree decl;
750      tree cleanup;
751 {
752   if (!decl || (DECL_SIZE (decl) && TREE_TYPE (decl) != error_mark_node))
753     expand_decl_cleanup (decl, cleanup);
754 }
755
756 /* We're about to expand T, a statement.  Set up appropriate context
757    for the substitution.  */
758
759 void
760 prep_stmt (t)
761      tree t;
762 {
763   if (!STMT_LINENO_FOR_FN_P (t))
764     lineno = STMT_LINENO (t);
765   current_stmt_tree ()->stmts_are_full_exprs_p = STMT_IS_FULL_EXPR_P (t);
766 }
767
768 /* Generate the RTL for the statement T, its substatements, and any
769    other statements at its nesting level. */
770
771 void
772 expand_stmt (t)
773      tree t;
774 {
775   while (t && t != error_mark_node)
776     {
777       int saved_stmts_are_full_exprs_p;
778
779       /* Set up context appropriately for handling this statement.  */
780       saved_stmts_are_full_exprs_p = stmts_are_full_exprs_p ();
781       prep_stmt (t);
782
783       switch (TREE_CODE (t))
784         {
785         case RETURN_STMT:
786           genrtl_return_stmt (t);
787           break;
788
789         case EXPR_STMT:
790           genrtl_expr_stmt (EXPR_STMT_EXPR (t));
791           break;
792
793         case DECL_STMT:
794           genrtl_decl_stmt (t);
795           break;
796
797         case FOR_STMT:
798           genrtl_for_stmt (t);
799           break;
800
801         case WHILE_STMT:
802           genrtl_while_stmt (t);
803           break;
804
805         case DO_STMT:
806           genrtl_do_stmt (t);
807           break;
808
809         case IF_STMT:
810           genrtl_if_stmt (t);
811           break;
812
813         case COMPOUND_STMT:
814           genrtl_compound_stmt (t);
815           break;
816
817         case BREAK_STMT:
818           genrtl_break_stmt ();
819           break;
820
821         case CONTINUE_STMT:
822           genrtl_continue_stmt ();
823           break;
824
825         case SWITCH_STMT:
826           genrtl_switch_stmt (t);
827           break;
828
829         case CASE_LABEL:
830           genrtl_case_label (t);
831           break;
832
833         case LABEL_STMT:
834           expand_label (LABEL_STMT_LABEL (t));
835           break;
836
837         case GOTO_STMT:
838           genrtl_goto_stmt (GOTO_DESTINATION (t));
839           break;
840
841         case ASM_STMT:
842           genrtl_asm_stmt (ASM_CV_QUAL (t), ASM_STRING (t),
843                            ASM_OUTPUTS (t), ASM_INPUTS (t), ASM_CLOBBERS (t));
844           break;
845
846         case SCOPE_STMT:
847           genrtl_scope_stmt (t);
848           break;
849
850         default:
851           if (lang_expand_stmt)
852             (*lang_expand_stmt) (t);
853           else 
854             abort ();
855           break;
856         }
857
858       /* Restore saved state.  */
859       current_stmt_tree ()->stmts_are_full_exprs_p = 
860         saved_stmts_are_full_exprs_p;
861
862       /* Go on to the next statement in this scope.  */
863       t = TREE_CHAIN (t);
864     }
865 }
866