OSDN Git Service

933b24faf312d1a0354c884e159972e22e61fac6
[pf3gnuchains/gcc-fork.git] / gcc / c-gimplify.c
1 /* Tree lowering pass.  This pass gimplifies the tree representation built
2    by the C-based front ends.  The structure of gimplified, or
3    language-independent, trees is dictated by the grammar described in this
4    file.
5    Copyright (C) 2002, 2003 Free Software Foundation, Inc.
6    Lowering of expressions contributed by Sebastian Pop <s.pop@laposte.net>
7    Re-written to support lowering of whole function trees, documentation
8    and miscellaneous cleanups by Diego Novillo <dnovillo@redhat.com>
9
10 This file is part of GCC.
11
12 GCC is free software; you can redistribute it and/or modify it under
13 the terms of the GNU General Public License as published by the Free
14 Software Foundation; either version 2, or (at your option) any later
15 version.
16
17 GCC is distributed in the hope that it will be useful, but WITHOUT ANY
18 WARRANTY; without even the implied warranty of MERCHANTABILITY or
19 FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
20 for more details.
21
22 You should have received a copy of the GNU General Public License
23 along with GCC; see the file COPYING.  If not, write to the Free
24 Software Foundation, 59 Temple Place - Suite 330, Boston, MA
25 02111-1307, USA.  */
26
27 #include "config.h"
28 #include "system.h"
29 #include "coretypes.h"
30 #include "tm.h"
31 #include "tree.h"
32 #include "errors.h"
33 #include "varray.h"
34 #include "c-tree.h"
35 #include "c-common.h"
36 #include "tree-gimple.h"
37 #include "hard-reg-set.h"
38 #include "basic-block.h"
39 #include "tree-flow.h"
40 #include "tree-inline.h"
41 #include "diagnostic.h"
42 #include "langhooks.h"
43 #include "langhooks-def.h"
44 #include "flags.h"
45 #include "rtl.h"
46 #include "toplev.h"
47 #include "tree-dump.h"
48 #include "c-pretty-print.h"
49 #include "cgraph.h"
50
51
52 /*  The gimplification pass converts the language-dependent trees
53     (ld-trees) emitted by the parser into language-independent trees
54     (li-trees) that are the target of SSA analysis and transformations.
55
56     Language-independent trees are based on the SIMPLE intermediate
57     representation used in the McCAT compiler framework:
58
59     "Designing the McCAT Compiler Based on a Family of Structured
60     Intermediate Representations,"
61     L. Hendren, C. Donawa, M. Emami, G. Gao, Justiani, and B. Sridharan,
62     Proceedings of the 5th International Workshop on Languages and
63     Compilers for Parallel Computing, no. 757 in Lecture Notes in
64     Computer Science, New Haven, Connecticut, pp. 406-420,
65     Springer-Verlag, August 3-5, 1992.
66
67     http://www-acaps.cs.mcgill.ca/info/McCAT/McCAT.html
68
69     Basically, we walk down gimplifying the nodes that we encounter.  As we
70     walk back up, we check that they fit our constraints, and copy them
71     into temporaries if not.  */
72
73 /* Local declarations.  */
74
75 static enum gimplify_status gimplify_expr_stmt (tree *);
76 static enum gimplify_status gimplify_decl_stmt (tree *);
77 static enum gimplify_status gimplify_for_stmt (tree *, tree *);
78 static enum gimplify_status gimplify_while_stmt (tree *);
79 static enum gimplify_status gimplify_do_stmt (tree *);
80 static enum gimplify_status gimplify_if_stmt (tree *);
81 static enum gimplify_status gimplify_switch_stmt (tree *);
82 static enum gimplify_status gimplify_return_stmt (tree *);
83 static enum gimplify_status gimplify_compound_literal_expr (tree *);
84 static void gimplify_cleanup_stmts (tree);
85 static tree gimplify_c_loop (tree, tree, tree, bool);
86 static void push_context (void);
87 static void pop_context (void);
88 static void add_block_to_enclosing (tree);
89 static void gimplify_condition (tree *);
90
91 enum bc_t { bc_break = 0, bc_continue = 1 };
92 static tree begin_bc_block (enum bc_t);
93 static tree finish_bc_block (tree, tree);
94 static tree build_bc_goto (enum bc_t);
95
96 static struct c_gimplify_ctx
97 {
98   /* For handling break and continue.  */
99   tree current_bc_label;
100   tree bc_id[2];
101 } *ctxp;
102
103 static void
104 push_context (void)
105 {
106   if (ctxp)
107     abort ();
108   ctxp = (struct c_gimplify_ctx *) xcalloc (1, sizeof (struct c_gimplify_ctx));
109   ctxp->bc_id[bc_continue] = get_identifier ("continue");
110   ctxp->bc_id[bc_break] = get_identifier ("break");
111 }
112
113 static void
114 pop_context (void)
115 {
116   if (!ctxp || ctxp->current_bc_label)
117     abort ();
118   free (ctxp);
119   ctxp = NULL;
120 }
121
122 /* Gimplification of statement trees.  */
123
124 /* Convert the tree representation of FNDECL from C frontend trees to
125    GENERIC.  */
126
127 void
128 c_genericize (tree fndecl)
129 {
130   FILE *dump_file;
131   int local_dump_flags;
132   struct cgraph_node *cgn;
133
134   /* Dump the C-specific tree IR.  */
135   dump_file = dump_begin (TDI_original, &local_dump_flags);
136   if (dump_file)
137     {
138       fprintf (dump_file, "\n;; Function %s",
139                lang_hooks.decl_printable_name (fndecl, 2));
140       fprintf (dump_file, " (%s)\n",
141                IDENTIFIER_POINTER (DECL_ASSEMBLER_NAME (fndecl)));
142       fprintf (dump_file, ";; enabled by -%s\n", dump_flag_name (TDI_original));
143       fprintf (dump_file, "\n");
144
145       if (local_dump_flags & TDF_RAW)
146         dump_node (DECL_SAVED_TREE (fndecl),
147                    TDF_SLIM | local_dump_flags, dump_file);
148       else
149         print_c_tree (dump_file, DECL_SAVED_TREE (fndecl));
150       fprintf (dump_file, "\n");
151
152       dump_end (TDI_original, dump_file);
153     }
154
155   /* Go ahead and gimplify for now.  */
156   push_context ();
157   gimplify_cleanup_stmts (fndecl);
158   gimplify_function_tree (fndecl);
159   pop_context ();
160
161   /* Dump the genericized tree IR.  */
162   dump_function (TDI_generic, fndecl);
163
164   /* Genericize all nested functions now.  We do things in this order so
165      that items like VLA sizes are expanded properly in the context of
166      the correct function.  */
167   cgn = cgraph_node (fndecl);
168   for (cgn = cgn->nested; cgn ; cgn = cgn->next_nested)
169     c_genericize (cgn->decl);
170 }
171
172 /* Genericize a CLEANUP_STMT.  This just turns into a TRY_FINALLY or
173    TRY_CATCH depending on whether it's EH-only.  */
174
175 static tree
176 gimplify_cleanup_stmt (tree *stmt_p, int *walk_subtrees,
177                        void *data ATTRIBUTE_UNUSED)
178 {
179   tree stmt = *stmt_p;
180
181   if (DECL_P (stmt) || TYPE_P (stmt))
182     *walk_subtrees = 0;
183   else if (TREE_CODE (stmt) == CLEANUP_STMT)
184     *stmt_p = build (CLEANUP_EH_ONLY (stmt) ? TRY_CATCH_EXPR : TRY_FINALLY_EXPR,
185                      void_type_node, CLEANUP_BODY (stmt), CLEANUP_EXPR (stmt));
186
187   return NULL;
188 }
189
190 static void
191 gimplify_cleanup_stmts (tree fndecl)
192 {
193   walk_tree (&DECL_SAVED_TREE (fndecl), gimplify_cleanup_stmt, NULL, NULL);
194 }
195
196 /*  Entry point for the tree lowering pass.  Recursively scan
197     *STMT_P and convert it to a GIMPLE tree.  */
198
199 int
200 c_gimplify_stmt (tree *stmt_p)
201 {
202   tree stmt = *stmt_p;
203   tree pre, post;
204   int saved_stmts_are_full_exprs_p;
205   location_t stmt_locus;
206   enum gimplify_status ret;
207
208   /* PRE and POST are tree chains that contain the side-effects of the
209      gimplified tree.  For instance, given the expression tree:
210
211                 c = ++a * 3 + b++;
212
213      After gimplification, the tree will be re-written as:
214
215                 a = a + 1;
216                 t1 = a * 3;     <-- PRE
217                 c = t1 + b;
218                 b = b + 1;      <-- POST  */
219
220   /* Set up context appropriately for handling this statement.  */
221   saved_stmts_are_full_exprs_p = stmts_are_full_exprs_p ();
222   prep_stmt (stmt);
223   stmt_locus = input_location;
224
225   pre = NULL_TREE;
226   post = NULL_TREE;
227
228   switch (TREE_CODE (stmt))
229     {
230     case FOR_STMT:
231       ret = gimplify_for_stmt (&stmt, &pre);
232       break;
233
234     case WHILE_STMT:
235       ret = gimplify_while_stmt (&stmt);
236       break;
237
238     case DO_STMT:
239       ret = gimplify_do_stmt (&stmt);
240       break;
241
242     case IF_STMT:
243       ret = gimplify_if_stmt (&stmt);
244       break;
245
246     case SWITCH_STMT:
247       ret = gimplify_switch_stmt (&stmt);
248       break;
249
250     case EXPR_STMT:
251       ret = gimplify_expr_stmt (&stmt);
252       break;
253
254     case RETURN_STMT:
255       ret = gimplify_return_stmt (&stmt);
256       break;
257
258     case DECL_STMT:
259       ret = gimplify_decl_stmt (&stmt);
260       break;
261
262     case CONTINUE_STMT:
263       stmt = build_bc_goto (bc_continue);
264       ret = GS_OK;
265       break;
266
267     case BREAK_STMT:
268       stmt = build_bc_goto (bc_break);
269       ret = GS_OK;
270       break;
271
272     default:
273       if (lang_gimplify_stmt && (*lang_gimplify_stmt) (&stmt))
274         {
275           ret = GS_OK;
276           break;
277         }
278
279       fprintf (stderr, "unhandled statement node in c_gimplify_stmt:\n");
280       debug_tree (stmt);
281       abort ();
282       break;
283     }
284
285   switch (ret)
286     {
287     case GS_ERROR:
288       goto cont;
289     case GS_OK:
290       gimplify_stmt (&stmt);
291       break;
292     case GS_ALL_DONE:
293       break;
294     default:
295       abort ();
296     }
297
298   /* PRE and POST now contain a list of statements for all the
299      side-effects in STMT.  */
300
301   append_to_statement_list (stmt, &pre);
302   append_to_statement_list (post, &pre);
303   annotate_all_with_locus (&pre, stmt_locus);
304  cont:
305   /* Restore saved state.  */
306   current_stmt_tree ()->stmts_are_full_exprs_p = saved_stmts_are_full_exprs_p;
307   *stmt_p = pre;
308
309   return GS_ALL_DONE;
310 }
311
312 static void
313 add_block_to_enclosing (tree block)
314 {
315   tree enclosing;
316
317   for (enclosing = gimple_current_bind_expr ();
318        enclosing; enclosing = TREE_CHAIN (enclosing))
319     if (BIND_EXPR_BLOCK (enclosing))
320       break;
321
322   enclosing = BIND_EXPR_BLOCK (enclosing);
323   BLOCK_SUBBLOCKS (enclosing) = chainon (BLOCK_SUBBLOCKS (enclosing), block);
324 }
325
326 /* Genericize a scope by creating a new BIND_EXPR.
327    BLOCK is either a BLOCK representing the scope or a chain of _DECLs.
328      In the latter case, we need to create a new BLOCK and add it to the
329      BLOCK_SUBBLOCKS of the enclosing block.
330    BODY is a chain of C _STMT nodes for the contents of the scope, to be
331      genericized.  */
332
333 tree
334 c_build_bind_expr (tree block, tree body)
335 {
336   tree decls, bind;
337
338   if (block == NULL_TREE)
339     decls = NULL_TREE;
340   else if (TREE_CODE (block) == BLOCK)
341     decls = BLOCK_VARS (block);
342   else
343     {
344       decls = block;
345       if (DECL_ARTIFICIAL (decls))
346         block = NULL_TREE;
347       else
348         {
349           block = make_node (BLOCK);
350           BLOCK_VARS (block) = decls;
351           add_block_to_enclosing (block);
352         }
353     }
354
355   if (!body)
356     body = build_empty_stmt ();
357   if (decls || block)
358     {
359       bind = build (BIND_EXPR, void_type_node, decls, body, block);
360       TREE_SIDE_EFFECTS (bind) = 1;
361     }
362   else
363     bind = body;
364
365   return bind;
366 }
367
368 /*  Gimplify an EXPR_STMT node.
369
370     STMT is the statement node.
371
372     PRE_P points to the list where side effects that must happen before
373         STMT should be stored.
374
375     POST_P points to the list where side effects that must happen after
376         STMT should be stored.  */
377
378 static enum gimplify_status
379 gimplify_expr_stmt (tree *stmt_p)
380 {
381   tree stmt = EXPR_STMT_EXPR (*stmt_p);
382
383   if (stmt == error_mark_node)
384     stmt = NULL;
385
386   /* Gimplification of a statement expression will nullify the
387      statement if all its side effects are moved to *PRE_P and *POST_P.
388
389      In this case we will not want to emit the gimplified statement.
390      However, we may still want to emit a warning, so we do that before
391      gimplification.  */
392   if (stmt && (extra_warnings || warn_unused_value))
393     {
394       if (!TREE_SIDE_EFFECTS (stmt))
395         {
396           if (!IS_EMPTY_STMT (stmt)
397               && !VOID_TYPE_P (TREE_TYPE (stmt))
398               && !TREE_NO_WARNING (stmt))
399             warning ("statement with no effect");
400         }
401       else if (warn_unused_value)
402         {
403           /* Kludge for 20020220-2.c.  warn_if_unused_value shouldn't use
404              the stmt file location info.  */
405           set_file_and_line_for_stmt (input_location);
406           warn_if_unused_value (stmt);
407         }
408     }
409
410   if (stmt == NULL_TREE)
411     stmt = build_empty_stmt ();
412   else if (stmts_are_full_exprs_p ())
413     stmt = build1 (CLEANUP_POINT_EXPR, void_type_node, stmt);
414
415   *stmt_p = stmt;
416
417   return GS_OK;
418 }
419
420 /* If the condition for a loop (or the like) is a decl, it will be a
421    TREE_LIST where the TREE_PURPOSE is a DECL_STMT and the TREE_VALUE is
422    a use of the decl.  Turn such a thing into a COMPOUND_EXPR.  */
423
424 static void
425 gimplify_condition (tree *cond_p)
426 {
427   tree cond = *cond_p;
428   if (cond && TREE_CODE (cond) == TREE_LIST)
429     {
430       tree decl = TREE_PURPOSE (cond);
431       tree value = TREE_VALUE (cond);
432       gimplify_stmt (&decl);
433       *cond_p = build (COMPOUND_EXPR, TREE_TYPE (value), decl, value);
434     }
435 }
436
437 /* Begin a scope which can be exited by a break or continue statement.  BC
438    indicates which.
439
440    Just creates a label and pushes it into the current context.  */
441
442 static tree
443 begin_bc_block (enum bc_t bc)
444 {
445   tree label = create_artificial_label ();
446   DECL_NAME (label) = ctxp->bc_id[bc];
447   TREE_CHAIN (label) = ctxp->current_bc_label;
448   ctxp->current_bc_label = label;
449   return label;
450 }
451
452 /* Finish a scope which can be exited by a break or continue statement.
453    LABEL was returned from the most recent call to begin_bc_block.  BODY is
454    an expression for the contents of the scope.
455
456    If we saw a break (or continue) in the scope, append a LABEL_EXPR to
457    body.  Otherwise, just forget the label.  */
458
459 static tree
460 finish_bc_block (tree label, tree body)
461 {
462   if (label != ctxp->current_bc_label)
463     abort ();
464
465   if (TREE_USED (label))
466     {
467       tree t, sl = NULL;
468
469       /* Clear the name so flow can delete the label.  */
470       DECL_NAME (label) = NULL_TREE;
471       t = build1 (LABEL_EXPR, void_type_node, label);
472
473       append_to_statement_list (body, &sl);
474       append_to_statement_list (t, &sl);
475       body = sl;
476     }
477
478   ctxp->current_bc_label = TREE_CHAIN (label);
479   TREE_CHAIN (label) = NULL_TREE;
480   return body;
481 }
482
483 /* Build a GOTO_EXPR to represent a break or continue statement.  BC
484    indicates which.  */
485
486 static tree
487 build_bc_goto (enum bc_t bc)
488 {
489   tree label;
490   tree target_name = ctxp->bc_id[bc];
491
492   /* Look for the appropriate type of label.  */
493   for (label = ctxp->current_bc_label;
494        label;
495        label = TREE_CHAIN (label))
496     if (DECL_NAME (label) == target_name)
497       break;
498
499   if (label == NULL_TREE)
500     {
501       if (bc == bc_break)
502         error ("break statement not within loop or switch");
503       else
504         error ("continue statement not within loop or switch");
505
506       return NULL_TREE;
507     }
508
509   /* Mark the label used for finish_bc_block.  */
510   TREE_USED (label) = 1;
511   return build1 (GOTO_EXPR, void_type_node, label);
512 }
513
514 /* Build a generic representation of one of the C loop forms.  COND is the
515    loop condition or NULL_TREE.  BODY is the (possibly compound) statement
516    controlled by the loop.  INCR is the increment expression of a for-loop,
517    or NULL_TREE.  COND_IS_FIRST indicates whether the condition is
518    evaluated before the loop body as in while and for loops, or after the
519    loop body as in do-while loops.  */
520
521 static tree
522 gimplify_c_loop (tree cond, tree body, tree incr, bool cond_is_first)
523 {
524   tree top, entry, exit, cont_block, break_block, stmt_list, t;
525   location_t stmt_locus;
526
527   stmt_locus = input_location;
528
529   /* Detect do { ... } while (0) and don't generate loop construct.  */
530   if (!cond_is_first && cond && integer_zerop (cond))
531     top = cond = NULL;
532   else
533     {
534       /* If we use a LOOP_EXPR here, we have to feed the whole thing
535          back through the main gimplifier to lower it.  Given that we
536          have to gimplify the loop body NOW so that we can resolve
537          break/continue stmts, seems easier to just expand to gotos.  */
538       top = build1 (LABEL_EXPR, void_type_node, NULL_TREE);
539     }
540
541   break_block = begin_bc_block (bc_break);
542
543   if (top)
544     {
545       /* If we have an exit condition, then we build an IF with gotos either
546          out of the loop, or to the top of it.  If there's no exit condition,
547          then we just build a jump back to the top.  */
548       exit = build_and_jump (&LABEL_EXPR_LABEL (top));
549       if (cond)
550         {
551           gimplify_condition (&cond);
552           t = build_bc_goto (bc_break);
553           exit = build (COND_EXPR, void_type_node, cond, exit, t);
554           exit = fold (exit);
555           gimplify_stmt (&exit);
556         }
557     }
558   else
559     exit = NULL_TREE;
560
561   cont_block = begin_bc_block (bc_continue);
562
563   gimplify_stmt (&body);
564   if (incr && stmts_are_full_exprs_p ())
565     incr = fold (build1 (CLEANUP_POINT_EXPR, void_type_node, incr));
566   gimplify_stmt (&incr);
567
568   body = finish_bc_block (cont_block, body);
569
570   stmt_list = NULL;
571
572   if (cond_is_first && cond)
573     {
574       entry = build1 (LABEL_EXPR, void_type_node, NULL_TREE);
575       t = build_and_jump (&LABEL_EXPR_LABEL (entry));
576       append_to_statement_list (t, &stmt_list);
577     }
578   else
579     entry = NULL_TREE;
580
581   append_to_statement_list (top, &stmt_list);
582   append_to_statement_list (body, &stmt_list);
583   append_to_statement_list (incr, &stmt_list);
584   append_to_statement_list (entry, &stmt_list);
585   append_to_statement_list (exit, &stmt_list);
586
587   annotate_all_with_locus (&stmt_list, stmt_locus);
588
589   return finish_bc_block (break_block, stmt_list);
590 }
591
592 /* Gimplify a FOR_STMT node.  Move the stuff in the for-init-stmt into the
593    prequeue and hand off to gimplify_c_loop.  */
594
595 static enum gimplify_status
596 gimplify_for_stmt (tree *stmt_p, tree *pre_p)
597 {
598   tree stmt = *stmt_p;
599
600   if (FOR_INIT_STMT (stmt))
601     {
602       gimplify_stmt (&FOR_INIT_STMT (stmt));
603       append_to_statement_list (FOR_INIT_STMT (stmt), pre_p);
604     }
605   *stmt_p = gimplify_c_loop (FOR_COND (stmt), FOR_BODY (stmt),
606                              FOR_EXPR (stmt), 1);
607
608   return GS_ALL_DONE;
609 }
610
611 /* Gimplify a WHILE_STMT node.  */
612
613 static enum gimplify_status
614 gimplify_while_stmt (tree *stmt_p)
615 {
616   tree stmt = *stmt_p;
617   *stmt_p = gimplify_c_loop (WHILE_COND (stmt), WHILE_BODY (stmt),
618                              NULL_TREE, 1);
619   return GS_ALL_DONE;
620 }
621
622 /* Gimplify a DO_STMT node.  */
623
624 static enum gimplify_status
625 gimplify_do_stmt (tree *stmt_p)
626 {
627   tree stmt = *stmt_p;
628   *stmt_p = gimplify_c_loop (DO_COND (stmt), DO_BODY (stmt),
629                              NULL_TREE, 0);
630   return GS_ALL_DONE;
631 }
632
633 /* Genericize an IF_STMT by turning it into a COND_EXPR.  */
634
635 static enum gimplify_status
636 gimplify_if_stmt (tree *stmt_p)
637 {
638   tree stmt, then_, else_;
639
640   stmt = *stmt_p;
641   then_ = THEN_CLAUSE (stmt);
642   else_ = ELSE_CLAUSE (stmt);
643
644   if (!then_)
645     then_ = build_empty_stmt ();
646   if (!else_)
647     else_ = build_empty_stmt ();
648
649   stmt = build (COND_EXPR, void_type_node, IF_COND (stmt), then_, else_);
650   gimplify_condition (& TREE_OPERAND (stmt, 0));
651   *stmt_p = stmt;
652
653   return GS_OK;
654 }
655
656 /* Genericize a SWITCH_STMT by turning it into a SWITCH_EXPR.  */
657
658 static enum gimplify_status
659 gimplify_switch_stmt (tree *stmt_p)
660 {
661   tree stmt = *stmt_p;
662   tree break_block, body;
663   location_t stmt_locus = input_location;
664
665   break_block = begin_bc_block (bc_break);
666
667   gimplify_condition (&SWITCH_COND (stmt));
668
669   body = SWITCH_BODY (stmt);
670   if (!body)
671     body = build_empty_stmt ();
672
673   *stmt_p = build (SWITCH_EXPR, SWITCH_TYPE (stmt), SWITCH_COND (stmt),
674                    body, NULL_TREE);
675   annotate_with_locus (*stmt_p, stmt_locus);
676   gimplify_stmt (stmt_p);
677
678   *stmt_p = finish_bc_block (break_block, *stmt_p);
679   return GS_ALL_DONE;
680 }
681
682 /* Genericize a RETURN_STMT by turning it into a RETURN_EXPR.  */
683
684 static enum gimplify_status
685 gimplify_return_stmt (tree *stmt_p)
686 {
687   tree expr = RETURN_STMT_EXPR (*stmt_p);
688   expr = build1 (RETURN_EXPR, void_type_node, expr);
689   if (stmts_are_full_exprs_p ())
690     expr = build1 (CLEANUP_POINT_EXPR, void_type_node, expr);
691   *stmt_p = expr;
692   return GS_OK;
693 }
694
695 /* Gimplifies a DECL_STMT node *STMT_P by making any necessary allocation
696    and initialization explicit.  */
697
698 static enum gimplify_status
699 gimplify_decl_stmt (tree *stmt_p)
700 {
701   tree stmt = *stmt_p;
702   tree decl = DECL_STMT_DECL (stmt);
703   tree pre = NULL_TREE;
704   tree post = NULL_TREE;
705
706   if (TREE_TYPE (decl) == error_mark_node)
707     {
708       *stmt_p = NULL;
709       return GS_ERROR;
710     }
711     
712   if (TREE_CODE (decl) == TYPE_DECL)
713     {
714       tree type = TREE_TYPE (decl);
715       if (TYPE_SIZE_UNIT (type)
716           && !TREE_CONSTANT (TYPE_SIZE_UNIT (type)))
717         {
718           /* This is a variable-sized array type.  Simplify its size.  */
719           tree temp = TYPE_SIZE_UNIT (type);
720           gimplify_expr (&temp, &pre, &post, is_gimple_val, fb_rvalue);
721         }
722     }
723
724   if (TREE_CODE (decl) == VAR_DECL && !DECL_EXTERNAL (decl))
725     {
726       tree init = DECL_INITIAL (decl);
727
728       if (!TREE_CONSTANT (DECL_SIZE (decl)))
729         {
730           tree pt_type = build_pointer_type (TREE_TYPE (decl));
731           tree alloc, size;
732
733           /* This is a variable-sized decl.  Simplify its size and mark it
734              for deferred expansion.  Note that mudflap depends on the format
735              of the emitted code: see mx_register_decls().  */
736
737           size = get_initialized_tmp_var (DECL_SIZE_UNIT (decl), &pre, &post);
738           DECL_DEFER_OUTPUT (decl) = 1;
739           alloc = build_function_call_expr
740             (implicit_built_in_decls[BUILT_IN_STACK_ALLOC],
741              tree_cons (NULL_TREE,
742                         build1 (ADDR_EXPR, pt_type, decl),
743                         tree_cons (NULL_TREE, size, NULL_TREE)));
744           append_to_compound_expr (alloc, &pre);
745         }
746
747       if (init && init != error_mark_node)
748         {
749           if (!TREE_STATIC (decl))
750             {
751               /* Do not warn about int x = x; as it is a GCC extension
752                  to turn off this warning but only if warn_init_self
753                  is zero.  */
754               if (init == decl && !warn_init_self)
755                 TREE_NO_WARNING (decl) = 1;
756               
757               DECL_INITIAL (decl) = NULL_TREE;
758               init = build (MODIFY_EXPR, void_type_node, decl, init);
759               if (stmts_are_full_exprs_p ())
760                 init = build1 (CLEANUP_POINT_EXPR, void_type_node, init);
761               append_to_compound_expr (init, &pre);
762             }
763           else
764             {
765               /* We must still examine initializers for static variables
766                  as they may contain a label address.  */
767               walk_tree (&init, force_labels_r, NULL, NULL);
768             }
769         }
770
771       /* This decl isn't mentioned in the enclosing block, so add it to the
772          list of temps.  FIXME it seems a bit of a kludge to say that
773          anonymous artificial vars aren't pushed, but everything else is.  */
774       if (DECL_ARTIFICIAL (decl) && DECL_NAME (decl) == NULL_TREE)
775         gimple_add_tmp_var (decl);
776     }
777
778   append_to_compound_expr (post, &pre);
779   *stmt_p = pre;
780   return GS_OK;
781 }
782
783 /* Gimplification of expression trees.  */
784
785 /* Gimplify a C99 compound literal expression.  This just means adding the
786    DECL_STMT before the current EXPR_STMT and using its anonymous decl
787    instead.  */
788
789 static enum gimplify_status
790 gimplify_compound_literal_expr (tree *expr_p)
791 {
792   tree decl_s = COMPOUND_LITERAL_EXPR_DECL_STMT (*expr_p);
793   tree decl = DECL_STMT_DECL (decl_s);
794
795   /* This decl isn't mentioned in the enclosing block, so add it to the
796      list of temps.  FIXME it seems a bit of a kludge to say that
797      anonymous artificial vars aren't pushed, but everything else is.  */
798   if (DECL_NAME (decl) == NULL_TREE)
799     gimple_add_tmp_var (decl);
800
801   gimplify_decl_stmt (&decl_s);
802   *expr_p = decl_s ? decl_s : decl;
803   return GS_OK;
804 }
805
806 /* Do C-specific gimplification.  Args are as for gimplify_expr.  */
807
808 int
809 c_gimplify_expr (tree *expr_p, tree *pre_p ATTRIBUTE_UNUSED,
810                  tree *post_p ATTRIBUTE_UNUSED)
811 {
812   enum tree_code code = TREE_CODE (*expr_p);
813
814   if (STATEMENT_CODE_P (code))
815     return c_gimplify_stmt (expr_p);
816
817   switch (code)
818     {
819     case COMPOUND_LITERAL_EXPR:
820       return gimplify_compound_literal_expr (expr_p);
821
822     default:
823       return GS_UNHANDLED;
824     }
825 }