c-semantics.c revision 110611
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	      && DECL_SAVED_INSNS (fn)
619	      && !TREE_ASM_WRITTEN (fn)
620	      && TREE_ADDRESSABLE (fn))
621	    {
622	      push_function_context ();
623	      output_inline_function (fn);
624	      pop_function_context ();
625	    }
626	}
627    }
628}
629
630/* Generate the RTL for T, which is a SWITCH_STMT.  */
631
632void
633genrtl_switch_stmt (t)
634     tree t;
635{
636  tree cond;
637  genrtl_do_pushlevel ();
638
639  cond = expand_cond (SWITCH_COND (t));
640  if (cond == error_mark_node)
641    /* The code is in error, but we don't want expand_end_case to
642       crash.  */
643    cond = boolean_false_node;
644
645  emit_line_note (input_filename, lineno);
646  expand_start_case (1, cond, TREE_TYPE (cond), "switch statement");
647  expand_stmt (SWITCH_BODY (t));
648  expand_end_case_type (cond, SWITCH_TYPE (t));
649}
650
651/* Create a CASE_LABEL tree node and return it.  */
652
653tree
654build_case_label (low_value, high_value, label_decl)
655     tree low_value;
656     tree high_value;
657     tree label_decl;
658{
659  return build_stmt (CASE_LABEL, low_value, high_value, label_decl);
660}
661
662
663/* Generate the RTL for a CASE_LABEL.  */
664
665void
666genrtl_case_label (case_label)
667     tree case_label;
668{
669  tree duplicate;
670  tree cleanup;
671
672  cleanup = last_cleanup_this_contour ();
673  if (cleanup)
674    {
675      static int explained = 0;
676      warning_with_decl (TREE_PURPOSE (cleanup),
677			 "destructor needed for `%#D'");
678      warning ("where case label appears here");
679      if (!explained)
680	{
681	  warning ("(enclose actions of previous case statements requiring destructors in their own scope.)");
682	  explained = 1;
683	}
684    }
685
686  add_case_node (CASE_LOW (case_label), CASE_HIGH (case_label),
687		 CASE_LABEL_DECL (case_label), &duplicate);
688}
689
690/* Generate the RTL for T, which is a COMPOUND_STMT.  */
691
692void
693genrtl_compound_stmt (t)
694    tree t;
695{
696#ifdef ENABLE_CHECKING
697  struct nesting *n = current_nesting_level ();
698#endif
699
700  expand_stmt (COMPOUND_BODY (t));
701
702#ifdef ENABLE_CHECKING
703  /* Make sure that we've pushed and popped the same number of levels.  */
704  if (!COMPOUND_STMT_NO_SCOPE (t) && n != current_nesting_level ())
705    abort ();
706#endif
707}
708
709/* Generate the RTL for an ASM_STMT.  */
710
711void
712genrtl_asm_stmt (cv_qualifier, string, output_operands,
713		 input_operands, clobbers, asm_input_p)
714     tree cv_qualifier;
715     tree string;
716     tree output_operands;
717     tree input_operands;
718     tree clobbers;
719     int asm_input_p;
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 (asm_input_p)
731    expand_asm (string, cv_qualifier != NULL_TREE);
732  else
733    c_expand_asm_operands (string, output_operands, input_operands,
734			   clobbers, cv_qualifier != NULL_TREE,
735			   input_filename, lineno);
736}
737
738/* Generate the RTL for a DECL_CLEANUP.  */
739
740void
741genrtl_decl_cleanup (t)
742     tree t;
743{
744  tree decl = CLEANUP_DECL (t);
745  if (!decl || (DECL_SIZE (decl) && TREE_TYPE (decl) != error_mark_node))
746    expand_decl_cleanup_eh (decl, CLEANUP_EXPR (t), CLEANUP_EH_ONLY (t));
747}
748
749/* We're about to expand T, a statement.  Set up appropriate context
750   for the substitution.  */
751
752void
753prep_stmt (t)
754     tree t;
755{
756  if (!STMT_LINENO_FOR_FN_P (t))
757    lineno = STMT_LINENO (t);
758  current_stmt_tree ()->stmts_are_full_exprs_p = STMT_IS_FULL_EXPR_P (t);
759}
760
761/* Generate the RTL for the statement T, its substatements, and any
762   other statements at its nesting level.  */
763
764void
765expand_stmt (t)
766     tree t;
767{
768  while (t && t != error_mark_node)
769    {
770      int saved_stmts_are_full_exprs_p;
771
772      /* Set up context appropriately for handling this statement.  */
773      saved_stmts_are_full_exprs_p = stmts_are_full_exprs_p ();
774      prep_stmt (t);
775
776      switch (TREE_CODE (t))
777	{
778	case FILE_STMT:
779	  input_filename = FILE_STMT_FILENAME (t);
780	  break;
781
782	case RETURN_STMT:
783	  genrtl_return_stmt (t);
784	  break;
785
786	case EXPR_STMT:
787	  genrtl_expr_stmt_value (EXPR_STMT_EXPR (t), TREE_ADDRESSABLE (t),
788				  TREE_CHAIN (t) == NULL
789				  || (TREE_CODE (TREE_CHAIN (t)) == SCOPE_STMT
790				      && TREE_CHAIN (TREE_CHAIN (t)) == NULL));
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),
844			   ASM_CLOBBERS (t), ASM_INPUT_P (t));
845	  break;
846
847	case SCOPE_STMT:
848	  genrtl_scope_stmt (t);
849	  break;
850
851	case CLEANUP_STMT:
852	  genrtl_decl_cleanup (t);
853	  break;
854
855	default:
856	  if (lang_expand_stmt)
857	    (*lang_expand_stmt) (t);
858	  else
859	    abort ();
860	  break;
861	}
862
863      /* Restore saved state.  */
864      current_stmt_tree ()->stmts_are_full_exprs_p
865	= saved_stmts_are_full_exprs_p;
866
867      /* Go on to the next statement in this scope.  */
868      t = TREE_CHAIN (t);
869    }
870}
871