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 ? ¤t.one_word \ 335 : ALLOC_WORDS (num_current_words); \ 336 SET_ALL (current.combined); \ 337 current.outer = alternatives; \ 338 alternatives = ¤t; \ 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 != ¤t.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