OSDN Git Service

Added Java 1.1 language features.
[pf3gnuchains/gcc-fork.git] / gcc / java / check-init.c
1 /* Code to test for "definitive assignment".
2
3    Copyright (C) 1999, 2000  Free Software Foundation, Inc.
4
5 This program is free software; you can redistribute it and/or modify
6 it under the terms of the GNU General Public License as published by
7 the Free Software Foundation; either version 2, or (at your option)
8 any later version.
9
10 This program is distributed in the hope that it will be useful,
11 but WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13 GNU General Public License for more details.
14
15 You should have received a copy of the GNU General Public License
16 along with GNU CC; see the file COPYING.  If not, write to
17 the Free Software Foundation, 59 Temple Place - Suite 330,
18 Boston, MA 02111-1307, USA.  
19
20 Java and all Java-based marks are trademarks or registered trademarks
21 of Sun Microsystems, Inc. in the United States and other countries.
22 The Free Software Foundation is independent of Sun Microsystems, Inc.  */
23
24 /* Written by Per Bothner <bothner@cygnus.com>, January 1999. */
25
26 #include "config.h"
27 #include "system.h"
28 #include "tree.h"
29 #include "java-tree.h"
30 #include "toplev.h" /* Needed for fatal. */
31
32 /* The basic idea is that we assign each local variable declaration
33    an index, and then we pass around bitstrings, where the i'th bit
34    is set if decl whose DECL_BIT_INDEX is i is definitely assigned. */
35
36 /* One segment of a bitstring. */
37 typedef unsigned int word;
38
39 /* Pointer to a bitstring. */
40 typedef word *words;
41
42 /* Number of locals variables currently active. */
43 int num_current_locals = 0;
44
45 /* The index of the first local variable in the current block.
46
47    The variables whose DECL_BIT_INDEX are in the range from
48    start_current_locals (inclusive) up to num_current_locals (exclusive)
49    are declared in the "current" block.  If there is a loop or branch
50    form, we set start_current_locals to num_current_locals to indicate
51    there is no current block.
52
53    The point is that if a variable in the current block is set,
54    there are no other control paths that we have to worry about.
55    Hence, we can remove it from the set of variables we are
56    checking, making its bit index available for some other variable.
57    For simplicity, we only do that if the variable's bit index
58    is (num_current_locals-1);  freeing up its bit index is then
59    just a simple matter of decrementing num_current_locals.
60    The reason this is worth doing is that it is simple, and
61    allows us to use short (usually one-word) bit-strings,
62    even for methods with thousands of local variables, as
63    long as most of them are initialized immediately after or in
64    their declaration. */
65 int start_current_locals = 0;
66
67 int num_current_words = 1;
68
69 static tree wfl;
70
71 #define COPYN(DST, SRC, NWORDS) memcpy (DST, SRC, NWORDS * sizeof(word))
72 #define COPY(DST, SRC) COPYN (DST, SRC, num_current_words)
73
74 #define SET_ALL(DST) memset (DST, ~0, num_current_words * sizeof(word))
75 #define CLEAR_ALL(DST) memset (DST, 0, num_current_words * sizeof(word))
76
77 #define INTERSECTN(DST, SRC1, SRC2, N) \
78   do { int n = N; \
79   while (--n >= 0) DST[n] = SRC1[n] & SRC2[n]; \
80   } while (0)
81
82 #define UNION(DST, SRC1, SRC2) \
83   UNIONN (DST, SRC1, SRC2, num_current_words)
84
85 #define UNIONN(DST, SRC1, SRC2, N) \
86   do { int n = N; \
87   while (--n >= 0) DST[n] = SRC1[n] | SRC2[n]; \
88   } while (0)
89
90 #define INTERSECT(DST, SRC1, SRC2) \
91   INTERSECTN (DST, SRC1, SRC2, num_current_words)
92
93 #define WORD_SIZE  ((unsigned int)(sizeof(word) * 8))
94
95 static void check_bool_init PARAMS ((tree, words, words, words));
96 static void check_init PARAMS ((tree, words));
97 static void check_cond_init PARAMS ((tree, tree, tree, words, words, words));
98 static void check_bool2_init PARAMS ((enum tree_code, tree, tree, words, words, words));
99 struct alternatives;
100 static void done_alternative PARAMS ((words, struct alternatives *));
101
102 #if 0
103 #define ALLOC_WORDS(NUM) ((word*) xmalloc ((NUM) * sizeof (word)))
104 #define FREE_WORDS(PTR) (free (PTR))
105 #else
106 #define ALLOC_WORDS(NUM) ((word*)alloca ((NUM) * sizeof (word)))
107 #define FREE_WORDS(PTR) ((void)0)
108 #endif
109
110 #define SET_P(WORDS, BIT) \
111   (WORDS[BIT / WORD_SIZE] & (1 << (BIT % WORD_SIZE)))
112
113 #define CLEAR_BIT(WORDS, BIT) \
114   (WORDS[BIT / WORD_SIZE] &= ~ (1 << (BIT % WORD_SIZE)))
115
116 #define SET_BIT(WORDS, BIT) \
117   (WORDS[BIT / WORD_SIZE] |= (1 << (BIT % WORD_SIZE)))
118
119 #define WORDS_NEEDED(BITS) (((BITS)+(WORD_SIZE-1))/(WORD_SIZE))
120
121 /* Check a conditional form (TEST_EXP ? THEN_EXP : ELSE_EXP) for
122    definite assignment.
123    BEFORE, WHEN_FALSE, and WHEN_TRUE are as in check_bool_init. */
124
125 static void
126 check_cond_init (test_exp, then_exp, else_exp,
127                  before, when_false, when_true)
128      tree test_exp, then_exp, else_exp;
129      words before, when_false, when_true;
130 {
131   words tmp = ALLOC_WORDS (6 * num_current_words);
132   words test_false = tmp;
133   words test_true = tmp + num_current_words;
134   words then_false = tmp + 2 * num_current_words;
135   words then_true = tmp + 3 * num_current_words;
136   words else_false = tmp + 4 * num_current_words;
137   words else_true = tmp + 5 * num_current_words;
138   check_bool_init (test_exp, before, test_false, test_true);
139   check_bool_init (then_exp, test_true, then_false, then_true);
140   check_bool_init (else_exp, test_false, else_false, else_true);
141   INTERSECT (when_false, then_false, else_false);
142   INTERSECT (when_true, then_true, else_true);
143   FREE_WORDS (tmp);
144 }
145
146 /* Check a boolean binary form CODE (EXP0, EXP1),
147    where CODE is one of EQ_EXPR, BIT_AND_EXPR, or BIT_IOR_EXPR.
148    BEFORE, WHEN_FALSE, and WHEN_TRUE are as in check_bool_init. */
149
150 static void
151 check_bool2_init (code, exp0, exp1, before, when_false, when_true)
152      enum tree_code code;  tree exp0, exp1;
153      words before, when_false, when_true;
154 {
155   word buf[4];
156   words tmp = num_current_words <= 1 ? buf
157     : ALLOC_WORDS (4 * num_current_words);
158   words when_false_0 = tmp;
159   words when_false_1 = tmp+num_current_words;
160   words when_true_0 = tmp+2*num_current_words;
161   words when_true_1 = tmp+3*num_current_words;
162   check_bool_init (exp0, before, when_false_0, when_true_0);
163   INTERSECT (before, when_false_0, when_true_0);
164   check_bool_init (exp1, before, when_false_1, when_true_1);
165
166   INTERSECT (before, when_false_1, when_true_1);
167
168   if (code == EQ_EXPR)
169     {
170       /* Now set:
171        * when_true = (when_false_1 INTERSECTION when_true_1)
172        *   UNION (when_true_0 INTERSECTION when_false_1)
173        *   UNION (when_false_0 INTERSECTION when_true_1);
174        * using when_false and before as temporary working areas.  */
175       INTERSECT (when_true, when_true_0, when_false_1);
176       INTERSECT (when_false, when_true_0, when_false_1);
177       UNION (when_true, when_true, when_false);
178       UNION (when_true, when_true, before);
179
180       /* Now set:
181        * when_false = (when_false_1 INTERSECTION when_true_1)
182        *   UNION (when_true_0 INTERSECTION when_true_1)
183        *   UNION (when_false_0 INTERSECTION when_false_1);
184        * using before as a temporary working area.  */
185       INTERSECT (when_false, when_true_0, when_true_1);
186       UNION (when_false, when_false, before);
187       INTERSECT (before, when_false_0, when_false_1);
188       UNION (when_false, when_false, before);
189     }
190   else if (code == BIT_AND_EXPR || code == TRUTH_AND_EXPR)
191     {
192       UNION (when_true, when_true_0, when_true_1);
193       INTERSECT (when_false, when_false_0, when_false_1);
194       UNION (when_false, when_false, before);
195     }
196   else /* if (code == BIT_IOR_EXPR || code == TRUTH_OR_EXPR) */
197     {
198       UNION (when_false, when_false_0, when_false_1);
199       INTERSECT (when_true, when_true_0, when_true_1);
200       UNION (when_true, when_true, before);
201     }
202
203   if (tmp != buf)
204     FREE_WORDS (tmp);
205 }
206
207 /* Check a boolean expression EXP for definite assignment.
208    BEFORE is the set of variables definitely assigned before the conditional.
209    (This bitstring may be modified arbitrarily in this function.)
210    On output, WHEN_FALSE is the set of variables definitely assigned after
211    the conditional when the conditional is false.
212    On output, WHEN_TRUE is the set of variables definitely assigned after
213    the conditional when the conditional is true.
214    (WHEN_FALSE and WHEN_TRUE are overwritten with initial values ignored.)
215    (None of BEFORE, WHEN_FALSE, or WHEN_TRUE can overlap, as they may
216    be used as temporary working areas. */
217
218 static void
219 check_bool_init (exp, before, when_false, when_true)
220      tree exp;
221      words before, when_false, when_true;
222 {
223   switch (TREE_CODE (exp))
224     {
225     case COND_EXPR:
226       check_cond_init (TREE_OPERAND (exp, 0), TREE_OPERAND (exp, 1),
227                        TREE_OPERAND (exp, 2),
228                        before, when_false, when_true);
229       return;
230
231     case TRUTH_ANDIF_EXPR:
232       check_cond_init (TREE_OPERAND (exp, 0),
233                        TREE_OPERAND (exp, 1), boolean_false_node,
234                        before, when_false, when_true);
235       return;
236     case TRUTH_ORIF_EXPR:
237       check_cond_init (TREE_OPERAND (exp, 0),
238                        boolean_true_node, TREE_OPERAND (exp, 1),
239                        before, when_false, when_true);
240       return;
241     case TRUTH_NOT_EXPR:
242       check_bool_init (TREE_OPERAND (exp, 0), before, when_true, when_false);
243       return;
244     case MODIFY_EXPR:
245       {
246         tree tmp = TREE_OPERAND (exp, 0);
247         if (TREE_CODE (tmp) == VAR_DECL && ! FIELD_STATIC (tmp))
248           {
249             int index;
250             check_bool_init (TREE_OPERAND (exp, 1), before,
251                              when_false, when_true);
252             index = DECL_BIT_INDEX (tmp);
253             if (index >= 0)
254               {
255                 SET_BIT (when_false, index);
256                 SET_BIT (when_true, index);
257               }
258             break;
259           }
260       }
261       goto do_default;
262
263     case BIT_AND_EXPR:
264     case BIT_IOR_EXPR:
265     case TRUTH_AND_EXPR:
266     case TRUTH_OR_EXPR:
267     case EQ_EXPR:
268       check_bool2_init (TREE_CODE (exp),
269                         TREE_OPERAND (exp, 0), TREE_OPERAND (exp, 1),
270                         before, when_false, when_true);
271       return;
272
273     case TRUTH_XOR_EXPR:
274     case BIT_XOR_EXPR:
275     case NE_EXPR:
276       /* Just like EQ_EXPR, but switch when_true and when_false. */
277       check_bool2_init (EQ_EXPR, TREE_OPERAND (exp, 0), TREE_OPERAND (exp, 1),
278                         before, when_true, when_false);
279
280       return;
281
282     case INTEGER_CST:
283       if (integer_zerop (exp))
284         {
285           SET_ALL (when_true);
286           COPY (when_false, before);
287         }
288       else
289         {
290           SET_ALL (when_false);
291           COPY (when_true, before);
292         }
293       break;
294     default:
295     do_default:
296       check_init (exp, before);
297       COPY (when_false, before);
298       COPY (when_true, before);
299     }
300 }
301
302 /* Used to keep track of control flow branches. */
303
304 struct alternatives
305 {
306   struct alternatives *outer;
307
308   /* The value of num_current_locals at the start of this compound. */
309   int num_locals;
310
311   /* The value of the "before" set at the start of the control stucture.
312    Used for SWITCH_EXPR but not set for LABELED_BLOCK_EXPR. */
313   words saved;
314
315   int save_start_current_locals;
316
317   /* If num_current_words==1, combined==&one_word, for efficiency. */
318   word one_word;
319
320   /* The intersection of the "after" sets from previous branches. */
321   words combined;
322
323   tree block;
324 };
325
326 struct alternatives * alternatives = NULL;
327
328 #define BEGIN_ALTERNATIVES(before, current) \
329 { \
330   current.saved = NULL; \
331   current.num_locals = num_current_locals; \
332   current.combined = num_current_words <= 1 ? &current.one_word \
333     : ALLOC_WORDS (num_current_words); \
334   SET_ALL (current.combined); \
335   current.outer = alternatives; \
336   alternatives = &current; \
337   current.save_start_current_locals = start_current_locals; \
338   start_current_locals = num_current_locals; \
339 }
340
341 static void
342 done_alternative (after, current)
343      words after;
344      struct alternatives *current; 
345 {
346   INTERSECTN (current->combined, current->combined, after,
347               WORDS_NEEDED (current->num_locals));
348 }
349
350 #define END_ALTERNATIVES(after, current) \
351 { \
352   alternatives = current.outer; \
353   COPY (after, current.combined); \
354   if (current.combined != &current.one_word) \
355     FREE_WORDS (current.combined); \
356   start_current_locals = current.save_start_current_locals; \
357 }
358
359 /* Check for (un)initialized local variables in EXP.
360 */
361
362 static void
363 check_init (exp, before)
364      tree exp;
365      words before;
366 {
367   tree tmp;
368  again:
369   switch (TREE_CODE (exp))
370     {
371     case VAR_DECL:
372       if (! FIELD_STATIC (exp) && DECL_NAME (exp) != NULL_TREE)
373         {
374           int index = DECL_BIT_INDEX (exp);
375           if (index >= 0 && ! SET_P (before, index))
376             {
377               parse_error_context 
378                 (wfl, "Variable `%s' may not have been initialized",
379                  IDENTIFIER_POINTER (DECL_NAME (exp)));
380               /* Suppress further errors. */
381               DECL_BIT_INDEX (exp) = -1;
382             }
383         }
384       break;
385     case MODIFY_EXPR:
386       tmp = TREE_OPERAND (exp, 0);
387       /* We're interested in variable declaration and parameter
388          declaration when they're declared with the `final' modifier. */
389       if ((TREE_CODE (tmp) == VAR_DECL && ! FIELD_STATIC (tmp))
390           || (TREE_CODE (tmp) == PARM_DECL && LOCAL_FINAL (tmp)))
391         {
392           int index;
393           check_init (TREE_OPERAND (exp, 1), before);
394           index = DECL_BIT_INDEX (tmp);
395           /* A final local already assigned or a final parameter
396              assigned must be reported as errors */
397           if (LOCAL_FINAL (tmp) 
398               && (index == -1 || TREE_CODE (tmp) == PARM_DECL))
399             parse_error_context (wfl, "Can't assign here a value to the `final' variable `%s'", IDENTIFIER_POINTER (DECL_NAME (tmp)));
400
401           if (index >= 0)
402             SET_BIT (before, index);
403           /* Minor optimization.  See comment for start_current_locals. */
404           if (index >= start_current_locals
405               && index == num_current_locals - 1)
406             {
407               num_current_locals--;
408               DECL_BIT_INDEX (tmp) = -1;
409             }
410          break;
411        }
412      else
413        goto binop;
414     case BLOCK:
415       if (BLOCK_EXPR_BODY (exp))
416         {
417           tree decl = BLOCK_EXPR_DECLS (exp);
418           int words_needed;
419           word* tmp;
420           int i;
421           int save_start_current_locals = start_current_locals;
422           int save_num_current_words = num_current_words;
423           start_current_locals = num_current_locals;
424           for (;  decl != NULL_TREE;  decl = TREE_CHAIN (decl))
425             {
426               DECL_BIT_INDEX (decl) = num_current_locals++;
427             }
428           words_needed = WORDS_NEEDED (num_current_locals);
429           if (words_needed > num_current_words)
430             {
431               tmp = ALLOC_WORDS (words_needed);
432               COPY (tmp, before);
433               num_current_words = words_needed;
434             }
435           else
436             tmp = before;
437           for (i = start_current_locals;  i < num_current_locals;  i++)
438             CLEAR_BIT (tmp, i);
439           check_init (BLOCK_EXPR_BODY (exp), tmp);
440           num_current_locals = start_current_locals;
441           start_current_locals = save_start_current_locals;
442           if (tmp != before)
443             {
444               num_current_words = save_num_current_words;
445               COPY (before, tmp);
446               FREE_WORDS (tmp);
447             }
448         }
449       break;
450     case LOOP_EXPR:
451       {
452         struct alternatives alt;
453         BEGIN_ALTERNATIVES (before, alt);
454         alt.block = exp;
455         check_init (TREE_OPERAND (exp, 0), before);
456         done_alternative (before, &alt);
457         END_ALTERNATIVES (before, alt);
458         return;
459       }
460     case EXIT_EXPR:
461       {
462         struct alternatives *alt = alternatives;
463         words tmp = ALLOC_WORDS (2 * num_current_words);
464         words when_true = tmp;
465         words when_false = tmp + num_current_words;
466 #ifdef ENABLE_CHECKING
467         if (TREE_CODE (alt->block) != LOOP_EXPR)
468           fatal ("internal error in check-init:  EXIT_EXPR not in LOOP_EXPR");
469 #endif
470         check_bool_init (TREE_OPERAND (exp, 0), before, when_false, when_true);
471         done_alternative (when_true, alt);
472         COPY (before, when_false);
473         FREE_WORDS (tmp);
474         return;
475       }
476     case LABELED_BLOCK_EXPR:
477       {
478         struct alternatives alt;
479         BEGIN_ALTERNATIVES (before, alt);
480         alt.block = exp;
481         if (LABELED_BLOCK_BODY (exp))
482           check_init (LABELED_BLOCK_BODY (exp), before);
483         done_alternative (before, &alt);
484         END_ALTERNATIVES (before, alt);
485         return;
486       }
487     case EXIT_BLOCK_EXPR:
488       {
489         tree block = TREE_OPERAND (exp, 0);
490         struct alternatives *alt = alternatives;
491         while (alt->block != block)
492           alt = alt->outer;
493         done_alternative (before, alt);
494         SET_ALL (before);
495         return;
496       }
497     case SWITCH_EXPR:
498       {
499         struct alternatives alt;
500         check_init (TREE_OPERAND (exp, 0), before);
501         BEGIN_ALTERNATIVES (before, alt);
502         alt.saved = ALLOC_WORDS (num_current_words);
503         COPY (alt.saved, before);
504         alt.block = exp;
505         check_init (TREE_OPERAND (exp, 1), before);
506         done_alternative (before, &alt);
507         FREE_WORDS (alt.saved);
508         END_ALTERNATIVES (before, alt);
509         return;
510       }
511     case CASE_EXPR:
512     case DEFAULT_EXPR:
513       {
514         int i;
515         struct alternatives *alt = alternatives;
516         while (TREE_CODE (alt->block) != SWITCH_EXPR)
517           alt = alt->outer;
518         COPYN (before, alt->saved, WORDS_NEEDED (alt->num_locals));
519         for (i = alt->num_locals;  i < num_current_locals;  i++)
520           CLEAR_BIT (before, i);
521         break;
522       }
523
524     case CLEANUP_POINT_EXPR:
525       {
526         struct alternatives alt;
527         BEGIN_ALTERNATIVES (before, alt);
528         CLEAR_ALL (alt.combined);
529         check_init (TREE_OPERAND (exp, 0), before); 
530         UNION (alt.combined, alt.combined, before);
531         END_ALTERNATIVES (before, alt);
532       }
533       return;
534     case WITH_CLEANUP_EXPR:
535       {
536         struct alternatives *alt = alternatives;        
537 #ifdef ENABLE_CHECKING
538         if (TREE_CODE (alt->block) != CLEANUP_POINT_EXPR)
539           fatal ("internal error in check-init:  WITH_CLEANUP_EXPR not in CLEANUP_POINT_EXPR");
540 #endif
541         check_init (TREE_OPERAND (exp, 0), before);
542         UNION (alt->combined, alt->combined, before);
543         check_init (TREE_OPERAND (exp, 2), alt->combined);
544         return;
545       }
546
547     case TRY_EXPR:
548       {
549         tree try_clause = TREE_OPERAND (exp, 0);
550         tree clause = TREE_OPERAND (exp, 1);
551         words save = ALLOC_WORDS (num_current_words);
552         words tmp = ALLOC_WORDS (num_current_words);
553         struct alternatives alt;
554         BEGIN_ALTERNATIVES (before, alt);
555         COPY (save, before);
556         COPY (tmp, save);
557         check_init (try_clause, tmp);
558         done_alternative (tmp, &alt);
559         for ( ; clause != NULL_TREE;  clause = TREE_CHAIN (clause))
560           {
561             tree catch_clause = TREE_OPERAND (clause, 0);
562             COPY (tmp, save);
563             check_init (catch_clause, tmp);
564             done_alternative (tmp, &alt);
565           }
566         FREE_WORDS (tmp);
567         FREE_WORDS (save);
568         END_ALTERNATIVES (before, alt);
569       }
570     return;
571
572     case TRY_FINALLY_EXPR:
573       {
574         words tmp = ALLOC_WORDS (num_current_words);
575         COPY (tmp, before);
576         check_init (TREE_OPERAND (exp, 0), tmp);
577         check_init (TREE_OPERAND (exp, 1), before);
578         FREE_WORDS (tmp);
579       }
580       return;
581
582     case RETURN_EXPR:
583     case THROW_EXPR:
584       if (TREE_OPERAND (exp, 0))
585         check_init (TREE_OPERAND (exp, 0), before);
586       goto never_continues;
587
588     case ERROR_MARK:
589     never_continues:
590       SET_ALL (before);
591       return;
592       
593     case COND_EXPR:
594     case TRUTH_ANDIF_EXPR:
595     case TRUTH_ORIF_EXPR:
596       {
597         words tmp = ALLOC_WORDS (2 * num_current_words);
598         words when_true = tmp;
599         words when_false = tmp + num_current_words;
600         check_bool_init (exp, before, when_false, when_true);
601         INTERSECT (before, when_false, when_true);
602         FREE_WORDS (tmp);
603       }
604       break;
605     case UNARY_PLUS_EXPR:
606     case NEGATE_EXPR:
607     case TRUTH_AND_EXPR:
608     case TRUTH_OR_EXPR:
609     case TRUTH_XOR_EXPR:
610     case TRUTH_NOT_EXPR:
611     case BIT_NOT_EXPR:
612     case CONVERT_EXPR:
613     case COMPONENT_REF:
614     case NOP_EXPR:
615     case FLOAT_EXPR:
616     case FIX_TRUNC_EXPR:
617     case INDIRECT_REF:
618     case ADDR_EXPR:
619     case PREDECREMENT_EXPR:
620     case PREINCREMENT_EXPR:
621     case POSTDECREMENT_EXPR:
622     case POSTINCREMENT_EXPR:
623     case NON_LVALUE_EXPR:
624     case INSTANCEOF_EXPR:
625       /* Avoid needless recursion. */
626       exp = TREE_OPERAND (exp, 0);
627       goto again;
628
629     case SAVE_EXPR:
630       if (IS_INIT_CHECKED (exp))
631         return;
632       IS_INIT_CHECKED (exp) = 1;
633       exp = TREE_OPERAND (exp, 0);
634       goto again;
635
636     case COMPOUND_EXPR:
637     case PLUS_EXPR:
638     case MINUS_EXPR:
639     case MULT_EXPR:
640     case TRUNC_DIV_EXPR:
641     case TRUNC_MOD_EXPR:
642     case RDIV_EXPR:
643     case LSHIFT_EXPR:
644     case RSHIFT_EXPR:
645     case URSHIFT_EXPR:
646     case BIT_AND_EXPR:
647     case BIT_XOR_EXPR:
648     case BIT_IOR_EXPR:
649     case EQ_EXPR: 
650     case NE_EXPR:
651     case GT_EXPR:
652     case GE_EXPR:
653     case LT_EXPR:
654     case LE_EXPR:
655     case MAX_EXPR:
656     case MIN_EXPR:
657     case ARRAY_REF:
658     binop:
659       check_init (TREE_OPERAND (exp, 0), before);
660       /* Avoid needless recursion, especially for COMPOUND_EXPR. */
661       exp = TREE_OPERAND (exp, 1);
662       goto again;
663
664     case PARM_DECL:
665     case RESULT_DECL:
666     case FUNCTION_DECL:
667     case INTEGER_CST:
668     case REAL_CST:
669     case STRING_CST:
670       break;
671
672     case NEW_CLASS_EXPR:
673     case CALL_EXPR:
674       {
675         tree func = TREE_OPERAND (exp, 0);
676         tree x = TREE_OPERAND (exp, 1);
677         if (TREE_CODE (func) == ADDR_EXPR)
678           func = TREE_OPERAND (func, 0);
679         check_init (func, before);
680
681         for ( ;  x != NULL_TREE;  x = TREE_CHAIN (x))
682           check_init (TREE_VALUE (x), before);
683         if (func == throw_node[0]
684             || func == throw_node[1])
685           goto never_continues;
686       }
687       break;
688
689     case NEW_ARRAY_INIT:
690       {
691         tree x = CONSTRUCTOR_ELTS (TREE_OPERAND (exp, 0));
692         for ( ;  x != NULL_TREE;  x = TREE_CHAIN (x))
693           check_init (TREE_VALUE (x), before);
694       }
695       break;
696
697     case EXPR_WITH_FILE_LOCATION:
698       {
699         char *saved_input_filename = input_filename;
700         tree saved_wfl = wfl;
701         tree body = EXPR_WFL_NODE (exp);
702         int saved_lineno = lineno;
703         if (body == empty_stmt_node)
704           break;
705         wfl = exp;
706         input_filename = EXPR_WFL_FILENAME (exp);
707         lineno = EXPR_WFL_LINENO (exp);
708         check_init (body, before);
709         input_filename = saved_input_filename;
710         lineno = saved_lineno;
711         wfl = saved_wfl;
712       }
713       break;
714       
715     default:
716       fatal ("internal error in check-init: tree code not implemented: %s",
717             tree_code_name [(int) TREE_CODE (exp)]);
718     }
719 }
720
721 void
722 check_for_initialization (body)
723      tree body;
724 {
725   word before = 0;
726   check_init (body, &before);
727 }