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