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