c-semantics.c revision 132718
190075Sobrien/* This file contains the definitions and documentation for the common
290075Sobrien   tree codes used in the GNU C and C++ compilers (see c-common.def
3132718Skan   for the standard codes).
4132718Skan   Copyright (C) 2000, 2001, 2002, 2003, 2004 Free Software Foundation, Inc.
590075Sobrien   Written by Benjamin Chelf (chelf@codesourcery.com).
690075Sobrien
790075SobrienThis file is part of GCC.
890075Sobrien
990075SobrienGCC is free software; you can redistribute it and/or modify it under
1090075Sobrienthe terms of the GNU General Public License as published by the Free
1190075SobrienSoftware Foundation; either version 2, or (at your option) any later
1290075Sobrienversion.
1390075Sobrien
1490075SobrienGCC is distributed in the hope that it will be useful, but WITHOUT ANY
1590075SobrienWARRANTY; without even the implied warranty of MERCHANTABILITY or
1690075SobrienFITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
1790075Sobrienfor more details.
1890075Sobrien
1990075SobrienYou should have received a copy of the GNU General Public License
2090075Sobrienalong with GCC; see the file COPYING.  If not, write to the Free
2190075SobrienSoftware Foundation, 59 Temple Place - Suite 330, Boston, MA
2290075Sobrien02111-1307, USA.  */
2390075Sobrien
2490075Sobrien#include "config.h"
2590075Sobrien#include "system.h"
26132718Skan#include "coretypes.h"
27132718Skan#include "tm.h"
2890075Sobrien#include "tree.h"
2990075Sobrien#include "function.h"
3090075Sobrien#include "splay-tree.h"
3190075Sobrien#include "varray.h"
3290075Sobrien#include "c-common.h"
3390075Sobrien#include "except.h"
34132718Skan/* In order for the format checking to accept the C frontend
35132718Skan   diagnostic framework extensions, you must define this token before
36132718Skan   including toplev.h.  */
37132718Skan#define GCC_DIAG_STYLE __gcc_cdiag__
3890075Sobrien#include "toplev.h"
3990075Sobrien#include "flags.h"
4090075Sobrien#include "ggc.h"
4190075Sobrien#include "rtl.h"
4290075Sobrien#include "expr.h"
4390075Sobrien#include "output.h"
4490075Sobrien#include "timevar.h"
45117395Skan#include "predict.h"
46132718Skan#include "tree-inline.h"
4790075Sobrien
4890075Sobrien/* If non-NULL, the address of a language-specific function for
4990075Sobrien   expanding statements.  */
50132718Skanvoid (*lang_expand_stmt) (tree);
5190075Sobrien
5290075Sobrien/* If non-NULL, the address of a language-specific function for
5390075Sobrien   expanding a DECL_STMT.  After the language-independent cases are
5490075Sobrien   handled, this function will be called.  If this function is not
5590075Sobrien   defined, it is assumed that declarations other than those for
5690075Sobrien   variables and labels do not require any RTL generation.  */
57132718Skanvoid (*lang_expand_decl_stmt) (tree);
5890075Sobrien
59132718Skanstatic tree find_reachable_label_1 (tree *, int *, void *);
60132718Skanstatic tree find_reachable_label (tree);
61132718Skanstatic bool expand_unreachable_if_stmt (tree);
62132718Skanstatic tree expand_unreachable_stmt (tree, int);
63132718Skanstatic void genrtl_do_stmt_1 (tree, tree);
64132718Skan
6590075Sobrien/* Create an empty statement tree rooted at T.  */
6690075Sobrien
6790075Sobrienvoid
68132718Skanbegin_stmt_tree (tree *t)
6990075Sobrien{
7090075Sobrien  /* We create a trivial EXPR_STMT so that last_tree is never NULL in
7190075Sobrien     what follows.  We remove the extraneous statement in
7290075Sobrien     finish_stmt_tree.  */
7390075Sobrien  *t = build_nt (EXPR_STMT, void_zero_node);
7490075Sobrien  last_tree = *t;
7590075Sobrien  last_expr_type = NULL_TREE;
7690075Sobrien  last_expr_filename = input_filename;
7790075Sobrien}
7890075Sobrien
7990075Sobrien/* T is a statement.  Add it to the statement-tree.  */
8090075Sobrien
8190075Sobrientree
82132718Skanadd_stmt (tree t)
8390075Sobrien{
8490075Sobrien  if (input_filename != last_expr_filename)
8590075Sobrien    {
8690075Sobrien      /* If the filename has changed, also add in a FILE_STMT.  Do a string
8790075Sobrien	 compare first, though, as it might be an equivalent string.  */
8890075Sobrien      int add = (strcmp (input_filename, last_expr_filename) != 0);
8990075Sobrien      last_expr_filename = input_filename;
9090075Sobrien      if (add)
9190075Sobrien	{
9290075Sobrien	  tree pos = build_nt (FILE_STMT, get_identifier (input_filename));
9390075Sobrien	  add_stmt (pos);
9490075Sobrien	}
9590075Sobrien    }
9690075Sobrien
9790075Sobrien  /* Add T to the statement-tree.  */
9890075Sobrien  TREE_CHAIN (last_tree) = t;
9990075Sobrien  last_tree = t;
100132718Skan
10190075Sobrien  /* When we expand a statement-tree, we must know whether or not the
10290075Sobrien     statements are full-expressions.  We record that fact here.  */
10390075Sobrien  STMT_IS_FULL_EXPR_P (last_tree) = stmts_are_full_exprs_p ();
10490075Sobrien
10590075Sobrien  return t;
10690075Sobrien}
10790075Sobrien
10890075Sobrien/* Create a declaration statement for the declaration given by the
10990075Sobrien   DECL.  */
11090075Sobrien
11190075Sobrienvoid
112132718Skanadd_decl_stmt (tree decl)
11390075Sobrien{
11490075Sobrien  tree decl_stmt;
11590075Sobrien
11690075Sobrien  /* We need the type to last until instantiation time.  */
11790075Sobrien  decl_stmt = build_stmt (DECL_STMT, decl);
118132718Skan  add_stmt (decl_stmt);
11990075Sobrien}
12090075Sobrien
12190075Sobrien/* Add a scope-statement to the statement-tree.  BEGIN_P indicates
12290075Sobrien   whether this statements opens or closes a scope.  PARTIAL_P is true
12390075Sobrien   for a partial scope, i.e, the scope that begins after a label when
12490075Sobrien   an object that needs a cleanup is created.  If BEGIN_P is nonzero,
12590075Sobrien   returns a new TREE_LIST representing the top of the SCOPE_STMT
12690075Sobrien   stack.  The TREE_PURPOSE is the new SCOPE_STMT.  If BEGIN_P is
12790075Sobrien   zero, returns a TREE_LIST whose TREE_VALUE is the new SCOPE_STMT,
12890075Sobrien   and whose TREE_PURPOSE is the matching SCOPE_STMT with
12990075Sobrien   SCOPE_BEGIN_P set.  */
13090075Sobrien
13190075Sobrientree
132132718Skanadd_scope_stmt (int begin_p, int partial_p)
13390075Sobrien{
13490075Sobrien  tree *stack_ptr = current_scope_stmt_stack ();
13590075Sobrien  tree ss;
13690075Sobrien  tree top = *stack_ptr;
13790075Sobrien
13890075Sobrien  /* Build the statement.  */
13990075Sobrien  ss = build_stmt (SCOPE_STMT, NULL_TREE);
14090075Sobrien  SCOPE_BEGIN_P (ss) = begin_p;
14190075Sobrien  SCOPE_PARTIAL_P (ss) = partial_p;
14290075Sobrien
14390075Sobrien  /* Keep the scope stack up to date.  */
14490075Sobrien  if (begin_p)
14590075Sobrien    {
14690075Sobrien      top = tree_cons (ss, NULL_TREE, top);
14790075Sobrien      *stack_ptr = top;
14890075Sobrien    }
14990075Sobrien  else
15090075Sobrien    {
151132718Skan      if (partial_p != SCOPE_PARTIAL_P (TREE_PURPOSE (top)))
152132718Skan	abort ();
15390075Sobrien      TREE_VALUE (top) = ss;
15490075Sobrien      *stack_ptr = TREE_CHAIN (top);
15590075Sobrien    }
15690075Sobrien
15790075Sobrien  /* Add the new statement to the statement-tree.  */
15890075Sobrien  add_stmt (ss);
15990075Sobrien
16090075Sobrien  return top;
16190075Sobrien}
16290075Sobrien
16390075Sobrien/* Finish the statement tree rooted at T.  */
16490075Sobrien
16590075Sobrienvoid
166132718Skanfinish_stmt_tree (tree *t)
16790075Sobrien{
16890075Sobrien  tree stmt;
169132718Skan
17090075Sobrien  /* Remove the fake extra statement added in begin_stmt_tree.  */
17190075Sobrien  stmt = TREE_CHAIN (*t);
17290075Sobrien  *t = stmt;
17390075Sobrien  last_tree = NULL_TREE;
17490075Sobrien
17590075Sobrien  if (cfun && stmt)
17690075Sobrien    {
17790075Sobrien      /* The line-number recorded in the outermost statement in a function
17890075Sobrien	 is the line number of the end of the function.  */
179132718Skan      STMT_LINENO (stmt) = input_line;
18090075Sobrien      STMT_LINENO_FOR_FN_P (stmt) = 1;
18190075Sobrien    }
18290075Sobrien}
18390075Sobrien
18490075Sobrien/* Build a generic statement based on the given type of node and
18590075Sobrien   arguments. Similar to `build_nt', except that we set
18690075Sobrien   STMT_LINENO to be the current line number.  */
18790075Sobrien/* ??? This should be obsolete with the lineno_stmt productions
18890075Sobrien   in the grammar.  */
18990075Sobrien
19090075Sobrientree
191132718Skanbuild_stmt (enum tree_code code, ...)
19290075Sobrien{
19390075Sobrien  tree t;
19490075Sobrien  int length;
19590075Sobrien  int i;
196132718Skan  va_list p;
19790075Sobrien
198132718Skan  va_start (p, code);
19990075Sobrien
20090075Sobrien  t = make_node (code);
20190075Sobrien  length = TREE_CODE_LENGTH (code);
202132718Skan  STMT_LINENO (t) = input_line;
20390075Sobrien
20490075Sobrien  for (i = 0; i < length; i++)
20590075Sobrien    TREE_OPERAND (t, i) = va_arg (p, tree);
20690075Sobrien
207132718Skan  va_end (p);
20890075Sobrien  return t;
20990075Sobrien}
21090075Sobrien
21190075Sobrien/* Some statements, like for-statements or if-statements, require a
21290075Sobrien   condition.  This condition can be a declaration.  If T is such a
21390075Sobrien   declaration it is processed, and an expression appropriate to use
21490075Sobrien   as the condition is returned.  Otherwise, T itself is returned.  */
21590075Sobrien
21690075Sobrientree
217132718Skanexpand_cond (tree t)
21890075Sobrien{
21990075Sobrien  if (t && TREE_CODE (t) == TREE_LIST)
22090075Sobrien    {
22190075Sobrien      expand_stmt (TREE_PURPOSE (t));
22290075Sobrien      return TREE_VALUE (t);
22390075Sobrien    }
224132718Skan  else
22590075Sobrien    return t;
22690075Sobrien}
22790075Sobrien
22890075Sobrien/* Create RTL for the local static variable DECL.  */
22990075Sobrien
23090075Sobrienvoid
231132718Skanmake_rtl_for_local_static (tree decl)
23290075Sobrien{
23390075Sobrien  const char *asmspec = NULL;
23490075Sobrien
23590075Sobrien  /* If we inlined this variable, we could see it's declaration
23690075Sobrien     again.  */
23790075Sobrien  if (TREE_ASM_WRITTEN (decl))
23890075Sobrien    return;
23990075Sobrien
24090075Sobrien  /* If the DECL_ASSEMBLER_NAME is not the same as the DECL_NAME, then
24190075Sobrien     either we already created RTL for this DECL (and since it was a
24290075Sobrien     local variable, its DECL_ASSEMBLER_NAME got hacked up to prevent
24390075Sobrien     clashes with other local statics with the same name by a previous
24490075Sobrien     call to make_decl_rtl), or the user explicitly requested a
24590075Sobrien     particular assembly name for this variable, using the GNU
24690075Sobrien     extension for this purpose:
24790075Sobrien
24890075Sobrien       int i asm ("j");
24990075Sobrien
25090075Sobrien     There's no way to know which case we're in, here.  But, it turns
25190075Sobrien     out we're safe.  If there's already RTL, then
25290075Sobrien     rest_of_decl_compilation ignores the ASMSPEC parameter, so we
25390075Sobrien     may as well not pass it in.  If there isn't RTL, then we didn't
25490075Sobrien     already create RTL, which means that the modification to
25590075Sobrien     DECL_ASSEMBLER_NAME came only via the explicit extension.  */
25690075Sobrien  if (DECL_ASSEMBLER_NAME (decl) != DECL_NAME (decl)
25790075Sobrien      && !DECL_RTL_SET_P (decl))
25890075Sobrien    asmspec = IDENTIFIER_POINTER (DECL_ASSEMBLER_NAME (decl));
25990075Sobrien
26090075Sobrien  rest_of_decl_compilation (decl, asmspec, /*top_level=*/0, /*at_end=*/0);
26190075Sobrien}
26290075Sobrien
26390075Sobrien/* Let the back-end know about DECL.  */
26490075Sobrien
26590075Sobrienvoid
266132718Skanemit_local_var (tree decl)
26790075Sobrien{
26890075Sobrien  /* Create RTL for this variable.  */
26990075Sobrien  if (!DECL_RTL_SET_P (decl))
27090075Sobrien    {
27190075Sobrien      if (DECL_C_HARD_REGISTER (decl))
27290075Sobrien	/* The user specified an assembler name for this variable.
27390075Sobrien	   Set that up now.  */
27490075Sobrien	rest_of_decl_compilation
27590075Sobrien	  (decl, IDENTIFIER_POINTER (DECL_ASSEMBLER_NAME (decl)),
27690075Sobrien	   /*top_level=*/0, /*at_end=*/0);
27790075Sobrien      else
27890075Sobrien	expand_decl (decl);
27990075Sobrien    }
28090075Sobrien
281132718Skan  if (DECL_INITIAL (decl))
282132718Skan    {
283132718Skan      /* Actually do the initialization.  */
284132718Skan      if (stmts_are_full_exprs_p ())
285132718Skan	expand_start_target_temps ();
28690075Sobrien
287132718Skan      expand_decl_init (decl);
28890075Sobrien
289132718Skan      if (stmts_are_full_exprs_p ())
290132718Skan	expand_end_target_temps ();
291132718Skan    }
29290075Sobrien}
29390075Sobrien
29490075Sobrien/* Helper for generating the RTL at the beginning of a scope.  */
29590075Sobrien
29690075Sobrienvoid
297132718Skangenrtl_do_pushlevel (void)
29890075Sobrien{
299132718Skan  emit_line_note (input_location);
30090075Sobrien  clear_last_expr ();
30190075Sobrien}
30290075Sobrien
30390075Sobrien/* Generate the RTL for DESTINATION, which is a GOTO_STMT.  */
30490075Sobrien
30590075Sobrienvoid
306132718Skangenrtl_goto_stmt (tree destination)
30790075Sobrien{
30890075Sobrien  if (TREE_CODE (destination) == IDENTIFIER_NODE)
30990075Sobrien    abort ();
310132718Skan
31190075Sobrien  /* We warn about unused labels with -Wunused.  That means we have to
31290075Sobrien     mark the used labels as used.  */
31390075Sobrien  if (TREE_CODE (destination) == LABEL_DECL)
31490075Sobrien    TREE_USED (destination) = 1;
315132718Skan
316132718Skan  emit_line_note (input_location);
317132718Skan
31890075Sobrien  if (TREE_CODE (destination) == LABEL_DECL)
31990075Sobrien    {
32090075Sobrien      label_rtx (destination);
321132718Skan      expand_goto (destination);
32290075Sobrien    }
32390075Sobrien  else
32490075Sobrien    expand_computed_goto (destination);
32590075Sobrien}
32690075Sobrien
32790075Sobrien/* Generate the RTL for EXPR, which is an EXPR_STMT.  Provided just
32890075Sobrien   for backward compatibility.  genrtl_expr_stmt_value() should be
32990075Sobrien   used for new code.  */
33090075Sobrien
33190075Sobrienvoid
332132718Skangenrtl_expr_stmt (tree expr)
33390075Sobrien{
33490075Sobrien  genrtl_expr_stmt_value (expr, -1, 1);
33590075Sobrien}
33690075Sobrien
33790075Sobrien/* Generate the RTL for EXPR, which is an EXPR_STMT.  WANT_VALUE tells
33890075Sobrien   whether to (1) save the value of the expression, (0) discard it or
33990075Sobrien   (-1) use expr_stmts_for_value to tell.  The use of -1 is
34090075Sobrien   deprecated, and retained only for backward compatibility.
341117395Skan   MAYBE_LAST is nonzero if this EXPR_STMT might be the last statement
34290075Sobrien   in expression statement.  */
34390075Sobrien
344132718Skanvoid
345132718Skangenrtl_expr_stmt_value (tree expr, int want_value, int maybe_last)
34690075Sobrien{
34790075Sobrien  if (expr != NULL_TREE)
34890075Sobrien    {
349132718Skan      emit_line_note (input_location);
350132718Skan
35190075Sobrien      if (stmts_are_full_exprs_p ())
35290075Sobrien	expand_start_target_temps ();
353132718Skan
35490075Sobrien      if (expr != error_mark_node)
35590075Sobrien	expand_expr_stmt_value (expr, want_value, maybe_last);
356132718Skan
35790075Sobrien      if (stmts_are_full_exprs_p ())
35890075Sobrien	expand_end_target_temps ();
35990075Sobrien    }
36090075Sobrien}
36190075Sobrien
36290075Sobrien/* Generate the RTL for T, which is a DECL_STMT.  */
36390075Sobrien
36490075Sobrienvoid
365132718Skangenrtl_decl_stmt (tree t)
36690075Sobrien{
36790075Sobrien  tree decl;
368132718Skan  emit_line_note (input_location);
36990075Sobrien  decl = DECL_STMT_DECL (t);
37090075Sobrien  /* If this is a declaration for an automatic local
37190075Sobrien     variable, initialize it.  Note that we might also see a
37290075Sobrien     declaration for a namespace-scope object (declared with
37390075Sobrien     `extern').  We don't have to handle the initialization
37490075Sobrien     of those objects here; they can only be declarations,
37590075Sobrien     rather than definitions.  */
376132718Skan  if (TREE_CODE (decl) == VAR_DECL
37790075Sobrien      && !TREE_STATIC (decl)
37890075Sobrien      && !DECL_EXTERNAL (decl))
37990075Sobrien    {
38090075Sobrien      /* Let the back-end know about this variable.  */
38190075Sobrien      if (!anon_aggr_type_p (TREE_TYPE (decl)))
38290075Sobrien	emit_local_var (decl);
38390075Sobrien      else
384132718Skan	expand_anon_union_decl (decl, NULL_TREE,
38590075Sobrien				DECL_ANON_UNION_ELEMS (decl));
38690075Sobrien    }
38790075Sobrien  else if (TREE_CODE (decl) == VAR_DECL && TREE_STATIC (decl))
38890075Sobrien    make_rtl_for_local_static (decl);
389132718Skan  else if (TREE_CODE (decl) == LABEL_DECL
39090075Sobrien	   && C_DECLARED_LABEL_FLAG (decl))
39190075Sobrien    declare_nonlocal_label (decl);
39290075Sobrien  else if (lang_expand_decl_stmt)
39390075Sobrien    (*lang_expand_decl_stmt) (t);
39490075Sobrien}
39590075Sobrien
39690075Sobrien/* Generate the RTL for T, which is an IF_STMT.  */
39790075Sobrien
39890075Sobrienvoid
399132718Skangenrtl_if_stmt (tree t)
40090075Sobrien{
40190075Sobrien  tree cond;
40290075Sobrien  genrtl_do_pushlevel ();
40390075Sobrien  cond = expand_cond (IF_COND (t));
404132718Skan  emit_line_note (input_location);
40590075Sobrien  expand_start_cond (cond, 0);
40690075Sobrien  if (THEN_CLAUSE (t))
407132718Skan    {
408132718Skan      tree nextt = THEN_CLAUSE (t);
409132718Skan
410132718Skan      if (cond && integer_zerop (cond))
411132718Skan	nextt = expand_unreachable_stmt (nextt, warn_notreached);
412132718Skan      expand_stmt (nextt);
413132718Skan    }
414132718Skan
41590075Sobrien  if (ELSE_CLAUSE (t))
41690075Sobrien    {
417132718Skan      tree nextt = ELSE_CLAUSE (t);
41890075Sobrien      expand_start_else ();
419132718Skan      if (cond && integer_nonzerop (cond))
420132718Skan	nextt = expand_unreachable_stmt (nextt, warn_notreached);
421132718Skan      expand_stmt (nextt);
42290075Sobrien    }
42390075Sobrien  expand_end_cond ();
42490075Sobrien}
42590075Sobrien
42690075Sobrien/* Generate the RTL for T, which is a WHILE_STMT.  */
42790075Sobrien
42890075Sobrienvoid
429132718Skangenrtl_while_stmt (tree t)
43090075Sobrien{
431132718Skan  tree cond = WHILE_COND (t);
432132718Skan
433132718Skan  emit_line_note (input_location);
434132718Skan  expand_start_loop (1);
43590075Sobrien  genrtl_do_pushlevel ();
43690075Sobrien
437132718Skan  if (cond && !integer_nonzerop (cond))
438132718Skan    {
439132718Skan      cond = expand_cond (cond);
440132718Skan      emit_line_note (input_location);
441132718Skan      expand_exit_loop_top_cond (0, cond);
442132718Skan      genrtl_do_pushlevel ();
443132718Skan    }
444132718Skan
44590075Sobrien  expand_stmt (WHILE_BODY (t));
44690075Sobrien
44790075Sobrien  expand_end_loop ();
44890075Sobrien}
44990075Sobrien
450132718Skan/* Generate the RTL for a DO_STMT with condition COND and loop BODY
451132718Skan   body.  This is reused for expanding unreachable WHILE_STMTS.  */
45290075Sobrien
453132718Skanstatic void
454132718Skangenrtl_do_stmt_1 (tree cond, tree body)
45590075Sobrien{
45690075Sobrien  /* Recognize the common special-case of do { ... } while (0) and do
45790075Sobrien     not emit the loop widgetry in this case.  In particular this
45890075Sobrien     avoids cluttering the rtl with dummy loop notes, which can affect
459117395Skan     alignment of adjacent labels.  COND can be NULL due to parse
460117395Skan     errors.  */
461117395Skan  if (!cond || integer_zerop (cond))
46290075Sobrien    {
46390075Sobrien      expand_start_null_loop ();
464132718Skan      expand_stmt (body);
46590075Sobrien      expand_end_null_loop ();
46690075Sobrien    }
467132718Skan  else if (integer_nonzerop (cond))
468132718Skan    {
469132718Skan      emit_line_note (input_location);
470132718Skan      expand_start_loop (1);
471132718Skan
472132718Skan      expand_stmt (body);
473132718Skan
474132718Skan      emit_line_note (input_location);
475132718Skan      expand_end_loop ();
476132718Skan    }
47790075Sobrien  else
47890075Sobrien    {
479132718Skan      emit_line_note (input_location);
48090075Sobrien      expand_start_loop_continue_elsewhere (1);
48190075Sobrien
482132718Skan      expand_stmt (body);
48390075Sobrien
48490075Sobrien      expand_loop_continue_here ();
48590075Sobrien      cond = expand_cond (cond);
486132718Skan      emit_line_note (input_location);
48790075Sobrien      expand_exit_loop_if_false (0, cond);
48890075Sobrien      expand_end_loop ();
48990075Sobrien    }
49090075Sobrien}
49190075Sobrien
492132718Skan/* Generate the RTL for T, which is a DO_STMT.  */
493132718Skan
494132718Skanvoid
495132718Skangenrtl_do_stmt (tree t)
496132718Skan{
497132718Skan  genrtl_do_stmt_1 (DO_COND (t), DO_BODY (t));
498132718Skan}
499132718Skan
50090075Sobrien/* Build the node for a return statement and return it.  */
50190075Sobrien
50290075Sobrientree
503132718Skanbuild_return_stmt (tree expr)
50490075Sobrien{
50590075Sobrien  return (build_stmt (RETURN_STMT, expr));
50690075Sobrien}
50790075Sobrien
50890075Sobrien/* Generate the RTL for STMT, which is a RETURN_STMT.  */
50990075Sobrien
51090075Sobrienvoid
511132718Skangenrtl_return_stmt (tree stmt)
51290075Sobrien{
51390075Sobrien  tree expr;
51490075Sobrien
515117395Skan  expr = RETURN_STMT_EXPR (stmt);
51690075Sobrien
517132718Skan  emit_line_note (input_location);
51890075Sobrien  if (!expr)
51990075Sobrien    expand_null_return ();
52090075Sobrien  else
52190075Sobrien    {
52290075Sobrien      expand_start_target_temps ();
52390075Sobrien      expand_return (expr);
52490075Sobrien      expand_end_target_temps ();
52590075Sobrien    }
52690075Sobrien}
52790075Sobrien
52890075Sobrien/* Generate the RTL for T, which is a FOR_STMT.  */
52990075Sobrien
53090075Sobrienvoid
531132718Skangenrtl_for_stmt (tree t)
53290075Sobrien{
533132718Skan  tree cond = FOR_COND (t);
534132718Skan  location_t saved_loc;
53590075Sobrien
53690075Sobrien  if (NEW_FOR_SCOPE_P (t))
53790075Sobrien    genrtl_do_pushlevel ();
53890075Sobrien
53990075Sobrien  expand_stmt (FOR_INIT_STMT (t));
54090075Sobrien
54190075Sobrien  /* Expand the initialization.  */
542132718Skan  emit_line_note (input_location);
543132718Skan  if (FOR_EXPR (t))
544132718Skan    expand_start_loop_continue_elsewhere (1);
545132718Skan  else
546132718Skan    expand_start_loop (1);
54790075Sobrien  genrtl_do_pushlevel ();
54890075Sobrien
54990075Sobrien  /* Save the filename and line number so that we expand the FOR_EXPR
55090075Sobrien     we can reset them back to the saved values.  */
551132718Skan  saved_loc = input_location;
55290075Sobrien
55390075Sobrien  /* Expand the condition.  */
554132718Skan  if (cond && !integer_nonzerop (cond))
555132718Skan    {
556132718Skan      cond = expand_cond (cond);
557132718Skan      emit_line_note (input_location);
558132718Skan      expand_exit_loop_top_cond (0, cond);
559132718Skan      genrtl_do_pushlevel ();
560132718Skan    }
56190075Sobrien
56290075Sobrien  /* Expand the body.  */
56390075Sobrien  expand_stmt (FOR_BODY (t));
56490075Sobrien
56590075Sobrien  /* Expand the increment expression.  */
566132718Skan  input_location = saved_loc;
567132718Skan  emit_line_note (input_location);
56890075Sobrien  if (FOR_EXPR (t))
569132718Skan    {
570132718Skan      expand_loop_continue_here ();
571132718Skan      genrtl_expr_stmt (FOR_EXPR (t));
572132718Skan    }
57390075Sobrien  expand_end_loop ();
57490075Sobrien}
57590075Sobrien
57690075Sobrien/* Build a break statement node and return it.  */
57790075Sobrien
57890075Sobrientree
579132718Skanbuild_break_stmt (void)
58090075Sobrien{
58190075Sobrien  return (build_stmt (BREAK_STMT));
58290075Sobrien}
58390075Sobrien
58490075Sobrien/* Generate the RTL for a BREAK_STMT.  */
58590075Sobrien
58690075Sobrienvoid
587132718Skangenrtl_break_stmt (void)
58890075Sobrien{
589132718Skan  emit_line_note (input_location);
59090075Sobrien  if ( ! expand_exit_something ())
591132718Skan    abort ();
59290075Sobrien}
59390075Sobrien
59490075Sobrien/* Build a continue statement node and return it.  */
59590075Sobrien
59690075Sobrientree
597132718Skanbuild_continue_stmt (void)
59890075Sobrien{
59990075Sobrien  return (build_stmt (CONTINUE_STMT));
60090075Sobrien}
60190075Sobrien
60290075Sobrien/* Generate the RTL for a CONTINUE_STMT.  */
60390075Sobrien
60490075Sobrienvoid
605132718Skangenrtl_continue_stmt (void)
60690075Sobrien{
607132718Skan  emit_line_note (input_location);
60890075Sobrien  if (! expand_continue_loop (0))
609132718Skan    abort ();
61090075Sobrien}
61190075Sobrien
61290075Sobrien/* Generate the RTL for T, which is a SCOPE_STMT.  */
61390075Sobrien
61490075Sobrienvoid
615132718Skangenrtl_scope_stmt (tree t)
61690075Sobrien{
61790075Sobrien  tree block = SCOPE_STMT_BLOCK (t);
61890075Sobrien
61990075Sobrien  if (!SCOPE_NO_CLEANUPS_P (t))
62090075Sobrien    {
62190075Sobrien      if (SCOPE_BEGIN_P (t))
62290075Sobrien	expand_start_bindings_and_block (2 * SCOPE_NULLIFIED_P (t), block);
62390075Sobrien      else if (SCOPE_END_P (t))
62490075Sobrien	expand_end_bindings (NULL_TREE, !SCOPE_NULLIFIED_P (t), 0);
62590075Sobrien    }
62690075Sobrien  else if (!SCOPE_NULLIFIED_P (t))
62790075Sobrien    {
628132718Skan      rtx note = emit_note (SCOPE_BEGIN_P (t)
629132718Skan			    ? NOTE_INSN_BLOCK_BEG : NOTE_INSN_BLOCK_END);
63090075Sobrien      NOTE_BLOCK (note) = block;
63190075Sobrien    }
63290075Sobrien
63390075Sobrien  /* If we're at the end of a scope that contains inlined nested
63490075Sobrien     functions, we have to decide whether or not to write them out.  */
63590075Sobrien  if (block && SCOPE_END_P (t))
63690075Sobrien    {
63790075Sobrien      tree fn;
63890075Sobrien
63990075Sobrien      for (fn = BLOCK_VARS (block); fn; fn = TREE_CHAIN (fn))
64090075Sobrien	{
641132718Skan	  if (TREE_CODE (fn) == FUNCTION_DECL
64290075Sobrien	      && DECL_CONTEXT (fn) == current_function_decl
643110611Skan	      && DECL_SAVED_INSNS (fn)
644132718Skan	      && DECL_SAVED_INSNS (fn)->saved_for_inline
64590075Sobrien	      && !TREE_ASM_WRITTEN (fn)
64690075Sobrien	      && TREE_ADDRESSABLE (fn))
64790075Sobrien	    {
64890075Sobrien	      push_function_context ();
64990075Sobrien	      output_inline_function (fn);
65090075Sobrien	      pop_function_context ();
65190075Sobrien	    }
65290075Sobrien	}
65390075Sobrien    }
65490075Sobrien}
65590075Sobrien
65690075Sobrien/* Generate the RTL for T, which is a SWITCH_STMT.  */
65790075Sobrien
65890075Sobrienvoid
659132718Skangenrtl_switch_stmt (tree t)
66090075Sobrien{
66190075Sobrien  tree cond;
66290075Sobrien  genrtl_do_pushlevel ();
663132718Skan
66490075Sobrien  cond = expand_cond (SWITCH_COND (t));
66590075Sobrien  if (cond == error_mark_node)
66690075Sobrien    /* The code is in error, but we don't want expand_end_case to
66790075Sobrien       crash.  */
668132718Skan    cond = truthvalue_false_node;
66990075Sobrien
670132718Skan  emit_line_note (input_location);
67190075Sobrien  expand_start_case (1, cond, TREE_TYPE (cond), "switch statement");
672132718Skan  expand_stmt (expand_unreachable_stmt (SWITCH_BODY (t), warn_notreached));
67396263Sobrien  expand_end_case_type (cond, SWITCH_TYPE (t));
67490075Sobrien}
67590075Sobrien
67690075Sobrien/* Create a CASE_LABEL tree node and return it.  */
67790075Sobrien
67890075Sobrientree
679132718Skanbuild_case_label (tree low_value, tree high_value, tree label_decl)
68090075Sobrien{
68190075Sobrien  return build_stmt (CASE_LABEL, low_value, high_value, label_decl);
68290075Sobrien}
68390075Sobrien
68490075Sobrien
68590075Sobrien/* Generate the RTL for a CASE_LABEL.  */
68690075Sobrien
687132718Skanvoid
688132718Skangenrtl_case_label (tree case_label)
68990075Sobrien{
69090075Sobrien  tree duplicate;
69190075Sobrien  tree cleanup;
69290075Sobrien
69390075Sobrien  cleanup = last_cleanup_this_contour ();
69490075Sobrien  if (cleanup)
69590075Sobrien    {
69690075Sobrien      static int explained = 0;
697132718Skan      warning ("destructor needed for `%D'", (TREE_PURPOSE (cleanup)));
69890075Sobrien      warning ("where case label appears here");
69990075Sobrien      if (!explained)
70090075Sobrien	{
70190075Sobrien	  warning ("(enclose actions of previous case statements requiring destructors in their own scope.)");
70290075Sobrien	  explained = 1;
70390075Sobrien	}
70490075Sobrien    }
70590075Sobrien
706132718Skan  add_case_node (CASE_LOW (case_label), CASE_HIGH (case_label),
70790075Sobrien		 CASE_LABEL_DECL (case_label), &duplicate);
70890075Sobrien}
70990075Sobrien
71090075Sobrien/* Generate the RTL for T, which is a COMPOUND_STMT.  */
71190075Sobrien
71290075Sobrienvoid
713132718Skangenrtl_compound_stmt (tree t)
71490075Sobrien{
71590075Sobrien#ifdef ENABLE_CHECKING
71690075Sobrien  struct nesting *n = current_nesting_level ();
71790075Sobrien#endif
71890075Sobrien
71990075Sobrien  expand_stmt (COMPOUND_BODY (t));
72090075Sobrien
72190075Sobrien#ifdef ENABLE_CHECKING
72290075Sobrien  /* Make sure that we've pushed and popped the same number of levels.  */
72390075Sobrien  if (!COMPOUND_STMT_NO_SCOPE (t) && n != current_nesting_level ())
72490075Sobrien    abort ();
72590075Sobrien#endif
72690075Sobrien}
72790075Sobrien
72890075Sobrien/* Generate the RTL for an ASM_STMT.  */
72990075Sobrien
73090075Sobrienvoid
731132718Skangenrtl_asm_stmt (tree cv_qualifier, tree string, tree output_operands,
732132718Skan		 tree input_operands, tree clobbers, int asm_input_p)
73390075Sobrien{
73490075Sobrien  if (cv_qualifier != NULL_TREE
73590075Sobrien      && cv_qualifier != ridpointers[(int) RID_VOLATILE])
73690075Sobrien    {
73790075Sobrien      warning ("%s qualifier ignored on asm",
73890075Sobrien	       IDENTIFIER_POINTER (cv_qualifier));
73990075Sobrien      cv_qualifier = NULL_TREE;
74090075Sobrien    }
74190075Sobrien
742132718Skan  emit_line_note (input_location);
74390075Sobrien  if (asm_input_p)
744110611Skan    expand_asm (string, cv_qualifier != NULL_TREE);
74590075Sobrien  else
746132718Skan    c_expand_asm_operands (string, output_operands, input_operands,
74790075Sobrien			   clobbers, cv_qualifier != NULL_TREE,
748132718Skan			   input_location);
74990075Sobrien}
75090075Sobrien
751132718Skan/* Generate the RTL for a CLEANUP_STMT.  */
75290075Sobrien
753132718Skanvoid
754132718Skangenrtl_cleanup_stmt (tree t)
75590075Sobrien{
75696263Sobrien  tree decl = CLEANUP_DECL (t);
757132718Skan  if (!decl || !DECL_P (decl)
758132718Skan      || (DECL_SIZE (decl) && TREE_TYPE (decl) != error_mark_node))
75996263Sobrien    expand_decl_cleanup_eh (decl, CLEANUP_EXPR (t), CLEANUP_EH_ONLY (t));
76090075Sobrien}
76190075Sobrien
76290075Sobrien/* We're about to expand T, a statement.  Set up appropriate context
76390075Sobrien   for the substitution.  */
76490075Sobrien
76590075Sobrienvoid
766132718Skanprep_stmt (tree t)
76790075Sobrien{
76890075Sobrien  if (!STMT_LINENO_FOR_FN_P (t))
769132718Skan    input_line = STMT_LINENO (t);
77090075Sobrien  current_stmt_tree ()->stmts_are_full_exprs_p = STMT_IS_FULL_EXPR_P (t);
77190075Sobrien}
77290075Sobrien
77390075Sobrien/* Generate the RTL for the statement T, its substatements, and any
77490075Sobrien   other statements at its nesting level.  */
77590075Sobrien
77690075Sobrienvoid
777132718Skanexpand_stmt (tree t)
77890075Sobrien{
77990075Sobrien  while (t && t != error_mark_node)
78090075Sobrien    {
78190075Sobrien      int saved_stmts_are_full_exprs_p;
78290075Sobrien
78390075Sobrien      /* Set up context appropriately for handling this statement.  */
78490075Sobrien      saved_stmts_are_full_exprs_p = stmts_are_full_exprs_p ();
78590075Sobrien      prep_stmt (t);
78690075Sobrien
78790075Sobrien      switch (TREE_CODE (t))
78890075Sobrien	{
78990075Sobrien	case FILE_STMT:
79090075Sobrien	  input_filename = FILE_STMT_FILENAME (t);
79190075Sobrien	  break;
79290075Sobrien
79390075Sobrien	case RETURN_STMT:
79490075Sobrien	  genrtl_return_stmt (t);
795132718Skan	  t = expand_unreachable_stmt (TREE_CHAIN (t), warn_notreached);
796132718Skan	  goto process_t;
79790075Sobrien
79890075Sobrien	case EXPR_STMT:
79990075Sobrien	  genrtl_expr_stmt_value (EXPR_STMT_EXPR (t), TREE_ADDRESSABLE (t),
80090075Sobrien				  TREE_CHAIN (t) == NULL
80190075Sobrien				  || (TREE_CODE (TREE_CHAIN (t)) == SCOPE_STMT
80290075Sobrien				      && TREE_CHAIN (TREE_CHAIN (t)) == NULL));
80390075Sobrien	  break;
80490075Sobrien
80590075Sobrien	case DECL_STMT:
80690075Sobrien	  genrtl_decl_stmt (t);
80790075Sobrien	  break;
80890075Sobrien
80990075Sobrien	case FOR_STMT:
81090075Sobrien	  genrtl_for_stmt (t);
81190075Sobrien	  break;
81290075Sobrien
81390075Sobrien	case WHILE_STMT:
81490075Sobrien	  genrtl_while_stmt (t);
81590075Sobrien	  break;
81690075Sobrien
81790075Sobrien	case DO_STMT:
81890075Sobrien	  genrtl_do_stmt (t);
81990075Sobrien	  break;
82090075Sobrien
82190075Sobrien	case IF_STMT:
82290075Sobrien	  genrtl_if_stmt (t);
82390075Sobrien	  break;
82490075Sobrien
82590075Sobrien	case COMPOUND_STMT:
82690075Sobrien	  genrtl_compound_stmt (t);
82790075Sobrien	  break;
82890075Sobrien
82990075Sobrien	case BREAK_STMT:
83090075Sobrien	  genrtl_break_stmt ();
831132718Skan	  t = expand_unreachable_stmt (TREE_CHAIN (t), warn_notreached);
832132718Skan	  goto process_t;
83390075Sobrien
83490075Sobrien	case CONTINUE_STMT:
83590075Sobrien	  genrtl_continue_stmt ();
836132718Skan	  t = expand_unreachable_stmt (TREE_CHAIN (t), warn_notreached);
837132718Skan	  goto process_t;
83890075Sobrien
83990075Sobrien	case SWITCH_STMT:
84090075Sobrien	  genrtl_switch_stmt (t);
84190075Sobrien	  break;
84290075Sobrien
84390075Sobrien	case CASE_LABEL:
84490075Sobrien	  genrtl_case_label (t);
84590075Sobrien	  break;
84690075Sobrien
84790075Sobrien	case LABEL_STMT:
84890075Sobrien	  expand_label (LABEL_STMT_LABEL (t));
84990075Sobrien	  break;
85090075Sobrien
85190075Sobrien	case GOTO_STMT:
852117395Skan	  /* Emit information for branch prediction.  */
853117395Skan	  if (!GOTO_FAKE_P (t)
854117395Skan	      && TREE_CODE (GOTO_DESTINATION (t)) == LABEL_DECL
855117395Skan	      && flag_guess_branch_prob)
856117395Skan	    {
857132718Skan	      rtx note = emit_note (NOTE_INSN_PREDICTION);
858117395Skan
859117395Skan	      NOTE_PREDICTION (note) = NOTE_PREDICT (PRED_GOTO, NOT_TAKEN);
860117395Skan	    }
86190075Sobrien	  genrtl_goto_stmt (GOTO_DESTINATION (t));
862132718Skan	  t = expand_unreachable_stmt (TREE_CHAIN (t), warn_notreached);
863132718Skan	  goto process_t;
86490075Sobrien
86590075Sobrien	case ASM_STMT:
86690075Sobrien	  genrtl_asm_stmt (ASM_CV_QUAL (t), ASM_STRING (t),
86790075Sobrien			   ASM_OUTPUTS (t), ASM_INPUTS (t),
86890075Sobrien			   ASM_CLOBBERS (t), ASM_INPUT_P (t));
86990075Sobrien	  break;
87090075Sobrien
87190075Sobrien	case SCOPE_STMT:
87290075Sobrien	  genrtl_scope_stmt (t);
87390075Sobrien	  break;
87490075Sobrien
87596263Sobrien	case CLEANUP_STMT:
876132718Skan	  genrtl_cleanup_stmt (t);
87796263Sobrien	  break;
87896263Sobrien
87990075Sobrien	default:
88090075Sobrien	  if (lang_expand_stmt)
88190075Sobrien	    (*lang_expand_stmt) (t);
882132718Skan	  else
88390075Sobrien	    abort ();
88490075Sobrien	  break;
88590075Sobrien	}
88690075Sobrien
887132718Skan      /* Go on to the next statement in this scope.  */
888132718Skan      t = TREE_CHAIN (t);
889132718Skan
890132718Skan    process_t:
89190075Sobrien      /* Restore saved state.  */
89290075Sobrien      current_stmt_tree ()->stmts_are_full_exprs_p
89390075Sobrien	= saved_stmts_are_full_exprs_p;
894132718Skan    }
895132718Skan}
896132718Skan
897132718Skan/* If *TP is a potentially reachable label, return nonzero.  */
89890075Sobrien
899132718Skanstatic tree
900132718Skanfind_reachable_label_1 (tree *tp, int *walk_subtrees ATTRIBUTE_UNUSED,
901132718Skan			void *data ATTRIBUTE_UNUSED)
902132718Skan{
903132718Skan  switch (TREE_CODE (*tp))
904132718Skan    {
905132718Skan    case LABEL_STMT:
906132718Skan    case CASE_LABEL:
907132718Skan      return *tp;
908132718Skan
909132718Skan    default:
910132718Skan      break;
911132718Skan    }
912132718Skan  return NULL_TREE;
913132718Skan}
914132718Skan
915132718Skan/* Determine whether expression EXP contains a potentially
916132718Skan   reachable label.  */
917132718Skanstatic tree
918132718Skanfind_reachable_label (tree exp)
919132718Skan{
920132718Skan  location_t saved_loc = input_location;
921132718Skan  tree ret = walk_tree_without_duplicates
922132718Skan		(&exp, find_reachable_label_1, NULL);
923132718Skan  input_location = saved_loc;
924132718Skan  return ret;
925132718Skan}
926132718Skan
927132718Skan/* Expand an unreachable if statement, T.  This function returns
928132718Skan   true if the IF_STMT contains a potentially reachable code_label.  */
929132718Skanstatic bool
930132718Skanexpand_unreachable_if_stmt (tree t)
931132718Skan{
932132718Skan  tree n;
933132718Skan
934132718Skan  if (find_reachable_label (IF_COND (t)) != NULL_TREE)
935132718Skan    {
936132718Skan      genrtl_if_stmt (t);
937132718Skan      return true;
938132718Skan    }
939132718Skan
940132718Skan  if (THEN_CLAUSE (t) && ELSE_CLAUSE (t))
941132718Skan    {
942132718Skan      n = expand_unreachable_stmt (THEN_CLAUSE (t), 0);
943132718Skan
944132718Skan      if (n != NULL_TREE)
945132718Skan	{
946132718Skan	  rtx label;
947132718Skan	  expand_stmt (n);
948132718Skan	  label = gen_label_rtx ();
949132718Skan	  emit_jump (label);
950132718Skan	  expand_stmt (expand_unreachable_stmt (ELSE_CLAUSE (t), 0));
951132718Skan	  emit_label (label);
952132718Skan	  return true;
953132718Skan	}
954132718Skan      else
955132718Skan	n = expand_unreachable_stmt (ELSE_CLAUSE (t), 0);
956132718Skan    }
957132718Skan  else if (THEN_CLAUSE (t))
958132718Skan    n = expand_unreachable_stmt (THEN_CLAUSE (t), 0);
959132718Skan  else if (ELSE_CLAUSE (t))
960132718Skan    n = expand_unreachable_stmt (ELSE_CLAUSE (t), 0);
961132718Skan  else
962132718Skan    n = NULL_TREE;
963132718Skan
964132718Skan  expand_stmt (n);
965132718Skan
966132718Skan  return n != NULL_TREE;
967132718Skan}
968132718Skan
969132718Skan/* Expand an unreachable statement list.  This function skips all
970132718Skan   statements preceding the first potentially reachable label and
971132718Skan   then returns the label (or, in same cases, the statement after
972132718Skan   one containing the label).  */
973132718Skanstatic tree
974132718Skanexpand_unreachable_stmt (tree t, int warn)
975132718Skan{
976132718Skan  int saved;
977132718Skan
978132718Skan  while (t && t != error_mark_node)
979132718Skan    {
980132718Skan      if (warn)
981132718Skan	switch (TREE_CODE (t))
982132718Skan	  {
983132718Skan	  case BREAK_STMT:
984132718Skan	  case CONTINUE_STMT:
985132718Skan	  case EXPR_STMT:
986132718Skan	  case GOTO_STMT:
987132718Skan	  case IF_STMT:
988132718Skan	  case RETURN_STMT:
989132718Skan	    if (!STMT_LINENO_FOR_FN_P (t))
990132718Skan	      input_line = STMT_LINENO (t);
991132718Skan	    warning("will never be executed");
992132718Skan	    warn = false;
993132718Skan	    break;
994132718Skan
995132718Skan	  default:
996132718Skan	    break;
997132718Skan	  }
998132718Skan
999132718Skan      switch (TREE_CODE (t))
1000132718Skan	{
1001132718Skan	case GOTO_STMT:
1002132718Skan	case CONTINUE_STMT:
1003132718Skan	case BREAK_STMT:
1004132718Skan	  break;
1005132718Skan
1006132718Skan	case FILE_STMT:
1007132718Skan	  input_filename = FILE_STMT_FILENAME (t);
1008132718Skan	  break;
1009132718Skan
1010132718Skan	case RETURN_STMT:
1011132718Skan	  if (find_reachable_label (RETURN_STMT_EXPR (t)) != NULL_TREE)
1012132718Skan	    return t;
1013132718Skan	  break;
1014132718Skan
1015132718Skan	case EXPR_STMT:
1016132718Skan	  if (find_reachable_label (EXPR_STMT_EXPR (t)) != NULL_TREE)
1017132718Skan	    return t;
1018132718Skan	  break;
1019132718Skan
1020132718Skan	case IF_STMT:
1021132718Skan	  if (expand_unreachable_if_stmt (t))
1022132718Skan	    return TREE_CHAIN (t);
1023132718Skan	  break;
1024132718Skan
1025132718Skan	case WHILE_STMT:
1026132718Skan	  /* If the start of a while statement is unreachable, there is
1027132718Skan	     no need to rotate the loop, instead the WHILE_STMT can be
1028132718Skan	     expanded like a DO_STMT.  */
1029132718Skan	  genrtl_do_stmt_1 (WHILE_COND (t), WHILE_BODY (t));
1030132718Skan	  return TREE_CHAIN (t);
1031132718Skan
1032132718Skan	case COMPOUND_STMT:
1033132718Skan	  {
1034132718Skan	    tree n;
1035132718Skan	    n = expand_unreachable_stmt (COMPOUND_BODY (t), warn);
1036132718Skan	    if (n != NULL_TREE)
1037132718Skan	      {
1038132718Skan		expand_stmt (n);
1039132718Skan		return TREE_CHAIN (t);
1040132718Skan	      }
1041132718Skan	    warn = false;
1042132718Skan	    break;
1043132718Skan	  }
1044132718Skan
1045132718Skan	case SCOPE_STMT:
1046132718Skan	  saved = stmts_are_full_exprs_p ();
1047132718Skan	  prep_stmt (t);
1048132718Skan	  genrtl_scope_stmt (t);
1049132718Skan	  current_stmt_tree ()->stmts_are_full_exprs_p = saved;
1050132718Skan	  break;
1051132718Skan
1052132718Skan	default:
1053132718Skan	  return t;
1054132718Skan	}
105590075Sobrien      t = TREE_CHAIN (t);
105690075Sobrien    }
1057132718Skan  return NULL_TREE;
105890075Sobrien}
1059