]>
Commit | Line | Data |
---|---|---|
4f88ccda | 1 | /* Code to test for "definitive [un]assignment". |
f309ff0a | 2 | Copyright (C) 1999, 2000, 2001, 2003 Free Software Foundation, Inc. |
4ba9a1aa | 3 | |
f309ff0a SB |
4 | This file is part of GCC. |
5 | ||
6 | GCC is free software; you can redistribute it and/or modify | |
4ba9a1aa PB |
7 | it under the terms of the GNU General Public License as published by |
8 | the Free Software Foundation; either version 2, or (at your option) | |
9 | any later version. | |
10 | ||
f309ff0a | 11 | GCC is distributed in the hope that it will be useful, |
4ba9a1aa PB |
12 | but WITHOUT ANY WARRANTY; without even the implied warranty of |
13 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
14 | GNU General Public License for more details. | |
15 | ||
16 | You should have received a copy of the GNU General Public License | |
f309ff0a | 17 | along with GCC; see the file COPYING. If not, write to |
4ba9a1aa PB |
18 | the Free Software Foundation, 59 Temple Place - Suite 330, |
19 | Boston, MA 02111-1307, USA. | |
20 | ||
21 | Java and all Java-based marks are trademarks or registered trademarks | |
22 | of Sun Microsystems, Inc. in the United States and other countries. | |
23 | The Free Software Foundation is independent of Sun Microsystems, Inc. */ | |
24 | ||
25 | /* Written by Per Bothner <bothner@cygnus.com>, January 1999. */ | |
26 | ||
27 | #include "config.h" | |
28 | #include "system.h" | |
4977bab6 ZW |
29 | #include "coretypes.h" |
30 | #include "tm.h" | |
4ba9a1aa | 31 | #include "tree.h" |
4009bb7d | 32 | #include "flags.h" /* Needed for optimize. */ |
4ba9a1aa PB |
33 | #include "java-tree.h" |
34 | #include "toplev.h" /* Needed for fatal. */ | |
35 | ||
36 | /* The basic idea is that we assign each local variable declaration | |
4f88ccda PB |
37 | and each blank final field an index, and then we pass around |
38 | bitstrings, where the (2*i)'th bit is set if decl whose DECL_BIT_INDEX | |
39 | is i is definitely assigned, and the the (2*i=1)'th bit is set if | |
40 | decl whose DECL_BIT_INDEX is i is definitely unassigned */ | |
4ba9a1aa PB |
41 | |
42 | /* One segment of a bitstring. */ | |
43 | typedef unsigned int word; | |
44 | ||
45 | /* Pointer to a bitstring. */ | |
46 | typedef word *words; | |
47 | ||
4ba9a1aa | 48 | /* Number of locals variables currently active. */ |
4f88ccda PB |
49 | static int num_current_locals = 0; |
50 | ||
51 | /* The value of num_current_locals when we entered the closest | |
52 | enclosing LOOP_EXPR. */ | |
53 | static int loop_current_locals; | |
4ba9a1aa PB |
54 | |
55 | /* The index of the first local variable in the current block. | |
56 | ||
57 | The variables whose DECL_BIT_INDEX are in the range from | |
58 | start_current_locals (inclusive) up to num_current_locals (exclusive) | |
59 | are declared in the "current" block. If there is a loop or branch | |
60 | form, we set start_current_locals to num_current_locals to indicate | |
61 | there is no current block. | |
62 | ||
63 | The point is that if a variable in the current block is set, | |
64 | there are no other control paths that we have to worry about. | |
65 | Hence, we can remove it from the set of variables we are | |
66 | checking, making its bit index available for some other variable. | |
67 | For simplicity, we only do that if the variable's bit index | |
68 | is (num_current_locals-1); freeing up its bit index is then | |
69 | just a simple matter of decrementing num_current_locals. | |
70 | The reason this is worth doing is that it is simple, and | |
71 | allows us to use short (usually one-word) bit-strings, | |
72 | even for methods with thousands of local variables, as | |
73 | long as most of them are initialized immediately after or in | |
74 | their declaration. */ | |
4f88ccda | 75 | static int start_current_locals = 0; |
4ba9a1aa | 76 | |
4f88ccda | 77 | static int num_current_words; |
4ba9a1aa PB |
78 | |
79 | static tree wfl; | |
80 | ||
81 | #define COPYN(DST, SRC, NWORDS) memcpy (DST, SRC, NWORDS * sizeof(word)) | |
82 | #define COPY(DST, SRC) COPYN (DST, SRC, num_current_words) | |
83 | ||
84 | #define SET_ALL(DST) memset (DST, ~0, num_current_words * sizeof(word)) | |
85 | #define CLEAR_ALL(DST) memset (DST, 0, num_current_words * sizeof(word)) | |
86 | ||
87 | #define INTERSECTN(DST, SRC1, SRC2, N) \ | |
88 | do { int n = N; \ | |
89 | while (--n >= 0) DST[n] = SRC1[n] & SRC2[n]; \ | |
90 | } while (0) | |
91 | ||
92 | #define UNION(DST, SRC1, SRC2) \ | |
93 | UNIONN (DST, SRC1, SRC2, num_current_words) | |
94 | ||
95 | #define UNIONN(DST, SRC1, SRC2, N) \ | |
96 | do { int n = N; \ | |
97 | while (--n >= 0) DST[n] = SRC1[n] | SRC2[n]; \ | |
98 | } while (0) | |
99 | ||
100 | #define INTERSECT(DST, SRC1, SRC2) \ | |
101 | INTERSECTN (DST, SRC1, SRC2, num_current_words) | |
102 | ||
5412ef6b | 103 | #define WORD_SIZE ((unsigned int)(sizeof(word) * BITS_PER_UNIT)) |
4ba9a1aa | 104 | |
d2097937 KG |
105 | static void check_bool_init (tree, words, words, words); |
106 | static void check_init (tree, words); | |
107 | static void check_cond_init (tree, tree, tree, words, words, words); | |
108 | static void check_bool2_init (enum tree_code, tree, tree, words, words, words); | |
c8e7d2e6 | 109 | struct alternatives; |
d2097937 KG |
110 | static void done_alternative (words, struct alternatives *); |
111 | static tree get_variable_decl (tree); | |
112 | static void final_assign_error (tree); | |
113 | static void check_final_reassigned (tree, words); | |
4ba9a1aa | 114 | |
a92cb0c3 | 115 | #define ALLOC_WORDS(NUM) (xmalloc ((NUM) * sizeof (word))) |
4ba9a1aa | 116 | #define FREE_WORDS(PTR) (free (PTR)) |
4f88ccda PB |
117 | |
118 | /* DECLARE_BUFFERS is used to allocate NUMBUFFER bit sets, each of | |
119 | which is an array of length num_current_words number of words. | |
120 | Declares a new local variable BUFFER to hold the result (or rather | |
121 | a pointer to the first of the bit sets). In almost all cases | |
122 | num_current_words will be 1 or at most 2, so we try to stack | |
123 | allocate the arrays in that case, using a stack array | |
124 | named BUFFER##_short. Each DECLARE_BUFFERS must be matched by | |
125 | a corresponding RELEASE_BUFFERS to avoid memory leaks. */ | |
126 | ||
127 | #define DECLARE_BUFFERS(BUFFER, NUMBUFFERS) \ | |
128 | word BUFFER##_short[2 * NUMBUFFERS]; \ | |
129 | words BUFFER = ALLOC_BUFFER(BUFFER##_short, NUMBUFFERS * num_current_words) | |
130 | ||
131 | #define RELEASE_BUFFERS(BUFFER) \ | |
132 | FREE_BUFFER(BUFFER, BUFFER##_short) | |
133 | ||
134 | #define ALLOC_BUFFER(SHORTBUFFER, NUMWORDS) \ | |
135 | ((NUMWORDS) * sizeof(word) <= sizeof(SHORTBUFFER) ? SHORTBUFFER \ | |
136 | : ALLOC_WORDS(NUMWORDS)) | |
137 | ||
138 | #define FREE_BUFFER(BUFFER, SHORTBUFFER) \ | |
139 | if (BUFFER != SHORTBUFFER) FREE_WORDS(BUFFER) | |
4ba9a1aa PB |
140 | |
141 | #define SET_P(WORDS, BIT) \ | |
4f88ccda | 142 | (WORDS[(BIT) / WORD_SIZE] & (1 << ((BIT) % WORD_SIZE))) |
4ba9a1aa PB |
143 | |
144 | #define CLEAR_BIT(WORDS, BIT) \ | |
4f88ccda | 145 | (WORDS[(BIT) / WORD_SIZE] &= ~ (1 << ((BIT) % WORD_SIZE))) |
4ba9a1aa PB |
146 | |
147 | #define SET_BIT(WORDS, BIT) \ | |
4f88ccda | 148 | (WORDS[(BIT) / WORD_SIZE] |= (1 << ((BIT) % WORD_SIZE))) |
4ba9a1aa PB |
149 | |
150 | #define WORDS_NEEDED(BITS) (((BITS)+(WORD_SIZE-1))/(WORD_SIZE)) | |
151 | ||
4f88ccda PB |
152 | #define ASSIGNED_P(WORDS, BIT) SET_P(WORDS, 2 * (BIT)) |
153 | #define UNASSIGNED_P(WORDS, BIT) SET_P(WORDS, 2 * (BIT) + 1) | |
154 | ||
155 | #define SET_ASSIGNED(WORDS, INDEX) SET_BIT (WORDS, 2 * (INDEX)) | |
156 | #define SET_UNASSIGNED(WORDS, INDEX) SET_BIT (WORDS, 2 * (INDEX) + 1) | |
157 | ||
158 | #define CLEAR_ASSIGNED(WORDS, INDEX) CLEAR_BIT (WORDS, 2 * (INDEX)) | |
159 | #define CLEAR_UNASSIGNED(WORDS, INDEX) CLEAR_BIT (WORDS, 2 * (INDEX) + 1) | |
160 | ||
161 | /* Get the "interesting" declaration from a MODIFY_EXPR or COMPONENT_REF. | |
162 | Return the declaration or NULL_TREE if no interesting declaration. */ | |
163 | ||
164 | static tree | |
0a2f0c54 | 165 | get_variable_decl (tree exp) |
4f88ccda PB |
166 | { |
167 | if (TREE_CODE (exp) == VAR_DECL) | |
168 | { | |
169 | if (! TREE_STATIC (exp) || FIELD_FINAL (exp)) | |
170 | return exp; | |
171 | } | |
172 | /* We only care about final parameters. */ | |
173 | else if (TREE_CODE (exp) == PARM_DECL) | |
174 | { | |
175 | if (DECL_FINAL (exp)) | |
176 | return exp; | |
177 | } | |
178 | /* See if exp is this.field. */ | |
179 | else if (TREE_CODE (exp) == COMPONENT_REF) | |
180 | { | |
181 | tree op0 = TREE_OPERAND (exp, 0); | |
182 | tree op1 = TREE_OPERAND (exp, 1); | |
183 | tree mdecl = current_function_decl; | |
184 | if (TREE_CODE (op0) == INDIRECT_REF | |
185 | && TREE_CODE (op1) == FIELD_DECL | |
186 | && ! METHOD_STATIC (mdecl) | |
187 | && FIELD_FINAL (op1)) | |
188 | { | |
189 | op0 = TREE_OPERAND (op0, 0); | |
190 | if (op0 == BLOCK_EXPR_DECLS (DECL_FUNCTION_BODY (mdecl))) | |
191 | return op1; | |
192 | } | |
193 | } | |
194 | return NULL_TREE; | |
195 | } | |
196 | ||
197 | static void | |
0a2f0c54 | 198 | final_assign_error (tree name) |
4f88ccda PB |
199 | { |
200 | static const char format[] | |
1aca9b81 | 201 | = "can't reassign a value to the final variable '%s'"; |
4f88ccda PB |
202 | parse_error_context (wfl, format, IDENTIFIER_POINTER (name)); |
203 | } | |
204 | ||
205 | static void | |
0a2f0c54 | 206 | check_final_reassigned (tree decl, words before) |
4f88ccda PB |
207 | { |
208 | int index = DECL_BIT_INDEX (decl); | |
209 | /* A final local already assigned or a final parameter | |
210 | assigned must be reported as errors */ | |
211 | if (DECL_FINAL (decl) && index != -2 | |
212 | && (index < loop_current_locals /* I.e. -1, or outside current loop. */ | |
213 | || ! UNASSIGNED_P (before, index))) | |
214 | { | |
215 | final_assign_error (DECL_NAME (decl)); | |
216 | } | |
217 | } | |
218 | ||
4ba9a1aa | 219 | /* Check a conditional form (TEST_EXP ? THEN_EXP : ELSE_EXP) for |
4f88ccda | 220 | definite [un]assignment. |
4ba9a1aa PB |
221 | BEFORE, WHEN_FALSE, and WHEN_TRUE are as in check_bool_init. */ |
222 | ||
4bcde32e | 223 | static void |
0a2f0c54 KG |
224 | check_cond_init (tree test_exp, tree then_exp, tree else_exp, |
225 | words before, words when_false, words when_true) | |
4ba9a1aa | 226 | { |
4f88ccda PB |
227 | int save_start_current_locals = start_current_locals; |
228 | DECLARE_BUFFERS(test_false, 6); | |
229 | words test_true = test_false + num_current_words; | |
230 | words then_false = test_true + num_current_words; | |
231 | words then_true = then_false + num_current_words; | |
232 | words else_false = then_true + num_current_words; | |
233 | words else_true = else_false + num_current_words; | |
234 | start_current_locals = num_current_locals; | |
235 | ||
4ba9a1aa PB |
236 | check_bool_init (test_exp, before, test_false, test_true); |
237 | check_bool_init (then_exp, test_true, then_false, then_true); | |
238 | check_bool_init (else_exp, test_false, else_false, else_true); | |
239 | INTERSECT (when_false, then_false, else_false); | |
240 | INTERSECT (when_true, then_true, else_true); | |
4f88ccda PB |
241 | RELEASE_BUFFERS(test_false); |
242 | start_current_locals = save_start_current_locals; | |
4ba9a1aa PB |
243 | } |
244 | ||
245 | /* Check a boolean binary form CODE (EXP0, EXP1), | |
01f76283 | 246 | where CODE is one of EQ_EXPR, BIT_AND_EXPR, or BIT_IOR_EXPR. |
4ba9a1aa PB |
247 | BEFORE, WHEN_FALSE, and WHEN_TRUE are as in check_bool_init. */ |
248 | ||
249 | static void | |
0a2f0c54 KG |
250 | check_bool2_init (enum tree_code code, tree exp0, tree exp1, |
251 | words before, words when_false, words when_true) | |
4ba9a1aa | 252 | { |
4f88ccda PB |
253 | word buf[2*4]; |
254 | words tmp = num_current_words <= 2 ? buf | |
4ba9a1aa PB |
255 | : ALLOC_WORDS (4 * num_current_words); |
256 | words when_false_0 = tmp; | |
257 | words when_false_1 = tmp+num_current_words; | |
258 | words when_true_0 = tmp+2*num_current_words; | |
259 | words when_true_1 = tmp+3*num_current_words; | |
260 | check_bool_init (exp0, before, when_false_0, when_true_0); | |
261 | INTERSECT (before, when_false_0, when_true_0); | |
262 | check_bool_init (exp1, before, when_false_1, when_true_1); | |
263 | ||
264 | INTERSECT (before, when_false_1, when_true_1); | |
265 | ||
266 | if (code == EQ_EXPR) | |
267 | { | |
268 | /* Now set: | |
269 | * when_true = (when_false_1 INTERSECTION when_true_1) | |
270 | * UNION (when_true_0 INTERSECTION when_false_1) | |
271 | * UNION (when_false_0 INTERSECTION when_true_1); | |
272 | * using when_false and before as temporary working areas. */ | |
273 | INTERSECT (when_true, when_true_0, when_false_1); | |
274 | INTERSECT (when_false, when_true_0, when_false_1); | |
275 | UNION (when_true, when_true, when_false); | |
276 | UNION (when_true, when_true, before); | |
277 | ||
278 | /* Now set: | |
279 | * when_false = (when_false_1 INTERSECTION when_true_1) | |
280 | * UNION (when_true_0 INTERSECTION when_true_1) | |
281 | * UNION (when_false_0 INTERSECTION when_false_1); | |
282 | * using before as a temporary working area. */ | |
283 | INTERSECT (when_false, when_true_0, when_true_1); | |
284 | UNION (when_false, when_false, before); | |
285 | INTERSECT (before, when_false_0, when_false_1); | |
286 | UNION (when_false, when_false, before); | |
287 | } | |
f2693f2f | 288 | else if (code == BIT_AND_EXPR || code == TRUTH_AND_EXPR) |
4ba9a1aa PB |
289 | { |
290 | UNION (when_true, when_true_0, when_true_1); | |
291 | INTERSECT (when_false, when_false_0, when_false_1); | |
01f76283 | 292 | UNION (when_false, when_false, before); |
4ba9a1aa | 293 | } |
f2693f2f | 294 | else /* if (code == BIT_IOR_EXPR || code == TRUTH_OR_EXPR) */ |
4ba9a1aa PB |
295 | { |
296 | UNION (when_false, when_false_0, when_false_1); | |
297 | INTERSECT (when_true, when_true_0, when_true_1); | |
01f76283 | 298 | UNION (when_true, when_true, before); |
4ba9a1aa PB |
299 | } |
300 | ||
301 | if (tmp != buf) | |
302 | FREE_WORDS (tmp); | |
303 | } | |
304 | ||
4f88ccda PB |
305 | /* Check a boolean expression EXP for definite [un]assignment. |
306 | BEFORE is the set of variables definitely [un]assigned before the | |
307 | conditional. (This bitstring may be modified arbitrarily in this function.) | |
308 | On output, WHEN_FALSE is the set of variables [un]definitely assigned after | |
4ba9a1aa | 309 | the conditional when the conditional is false. |
4f88ccda | 310 | On output, WHEN_TRUE is the set of variables definitely [un]assigned after |
4ba9a1aa | 311 | the conditional when the conditional is true. |
f6e8b583 | 312 | (WHEN_FALSE and WHEN_TRUE are overwritten with initial values ignored.) |
4ba9a1aa PB |
313 | (None of BEFORE, WHEN_FALSE, or WHEN_TRUE can overlap, as they may |
314 | be used as temporary working areas. */ | |
4ba9a1aa PB |
315 | |
316 | static void | |
0a2f0c54 | 317 | check_bool_init (tree exp, words before, words when_false, words when_true) |
4ba9a1aa PB |
318 | { |
319 | switch (TREE_CODE (exp)) | |
320 | { | |
321 | case COND_EXPR: | |
322 | check_cond_init (TREE_OPERAND (exp, 0), TREE_OPERAND (exp, 1), | |
323 | TREE_OPERAND (exp, 2), | |
324 | before, when_false, when_true); | |
325 | return; | |
326 | ||
327 | case TRUTH_ANDIF_EXPR: | |
328 | check_cond_init (TREE_OPERAND (exp, 0), | |
329 | TREE_OPERAND (exp, 1), boolean_false_node, | |
330 | before, when_false, when_true); | |
331 | return; | |
332 | case TRUTH_ORIF_EXPR: | |
333 | check_cond_init (TREE_OPERAND (exp, 0), | |
334 | boolean_true_node, TREE_OPERAND (exp, 1), | |
335 | before, when_false, when_true); | |
336 | return; | |
337 | case TRUTH_NOT_EXPR: | |
338 | check_bool_init (TREE_OPERAND (exp, 0), before, when_true, when_false); | |
339 | return; | |
340 | case MODIFY_EXPR: | |
341 | { | |
342 | tree tmp = TREE_OPERAND (exp, 0); | |
4f88ccda | 343 | if ((tmp = get_variable_decl (tmp)) != NULL_TREE) |
4ba9a1aa PB |
344 | { |
345 | int index; | |
346 | check_bool_init (TREE_OPERAND (exp, 1), before, | |
347 | when_false, when_true); | |
4f88ccda | 348 | check_final_reassigned (tmp, before); |
4ba9a1aa PB |
349 | index = DECL_BIT_INDEX (tmp); |
350 | if (index >= 0) | |
351 | { | |
4f88ccda PB |
352 | SET_ASSIGNED (when_false, index); |
353 | SET_ASSIGNED (when_true, index); | |
354 | CLEAR_UNASSIGNED (when_false, index); | |
355 | CLEAR_UNASSIGNED (when_true, index); | |
4ba9a1aa PB |
356 | } |
357 | break; | |
358 | } | |
359 | } | |
360 | goto do_default; | |
361 | ||
362 | case BIT_AND_EXPR: | |
01f76283 | 363 | case BIT_IOR_EXPR: |
f2693f2f PB |
364 | case TRUTH_AND_EXPR: |
365 | case TRUTH_OR_EXPR: | |
4ba9a1aa PB |
366 | case EQ_EXPR: |
367 | check_bool2_init (TREE_CODE (exp), | |
368 | TREE_OPERAND (exp, 0), TREE_OPERAND (exp, 1), | |
369 | before, when_false, when_true); | |
370 | return; | |
371 | ||
f2693f2f | 372 | case TRUTH_XOR_EXPR: |
4ba9a1aa PB |
373 | case BIT_XOR_EXPR: |
374 | case NE_EXPR: | |
375 | /* Just like EQ_EXPR, but switch when_true and when_false. */ | |
376 | check_bool2_init (EQ_EXPR, TREE_OPERAND (exp, 0), TREE_OPERAND (exp, 1), | |
377 | before, when_true, when_false); | |
378 | ||
379 | return; | |
380 | ||
381 | case INTEGER_CST: | |
382 | if (integer_zerop (exp)) | |
383 | { | |
384 | SET_ALL (when_true); | |
385 | COPY (when_false, before); | |
386 | } | |
387 | else | |
388 | { | |
389 | SET_ALL (when_false); | |
390 | COPY (when_true, before); | |
391 | } | |
392 | break; | |
393 | default: | |
394 | do_default: | |
395 | check_init (exp, before); | |
396 | COPY (when_false, before); | |
397 | COPY (when_true, before); | |
398 | } | |
399 | } | |
400 | ||
401 | /* Used to keep track of control flow branches. */ | |
402 | ||
403 | struct alternatives | |
404 | { | |
405 | struct alternatives *outer; | |
406 | ||
407 | /* The value of num_current_locals at the start of this compound. */ | |
408 | int num_locals; | |
409 | ||
634661fe | 410 | /* The value of the "before" set at the start of the control structure. |
4ba9a1aa PB |
411 | Used for SWITCH_EXPR but not set for LABELED_BLOCK_EXPR. */ |
412 | words saved; | |
413 | ||
414 | int save_start_current_locals; | |
415 | ||
416 | /* If num_current_words==1, combined==&one_word, for efficiency. */ | |
417 | word one_word; | |
418 | ||
419 | /* The intersection of the "after" sets from previous branches. */ | |
420 | words combined; | |
421 | ||
422 | tree block; | |
423 | }; | |
424 | ||
425 | struct alternatives * alternatives = NULL; | |
426 | ||
4f88ccda PB |
427 | /* Begin handling a control flow branch. |
428 | BEFORE is the state of [un]assigned variables on entry. | |
429 | CURRENT is a struct alt to manage the branch alternatives. */ | |
430 | ||
4ba9a1aa PB |
431 | #define BEGIN_ALTERNATIVES(before, current) \ |
432 | { \ | |
433 | current.saved = NULL; \ | |
434 | current.num_locals = num_current_locals; \ | |
435 | current.combined = num_current_words <= 1 ? ¤t.one_word \ | |
436 | : ALLOC_WORDS (num_current_words); \ | |
437 | SET_ALL (current.combined); \ | |
438 | current.outer = alternatives; \ | |
439 | alternatives = ¤t; \ | |
440 | current.save_start_current_locals = start_current_locals; \ | |
441 | start_current_locals = num_current_locals; \ | |
442 | } | |
443 | ||
4f88ccda PB |
444 | /* We have finished with one branch of branching control flow. |
445 | Store the [un]assigned state, merging (intersecting) it with the state | |
446 | of previous alternative branches. */ | |
447 | ||
4ba9a1aa | 448 | static void |
0a2f0c54 | 449 | done_alternative (words after, struct alternatives *current) |
4ba9a1aa PB |
450 | { |
451 | INTERSECTN (current->combined, current->combined, after, | |
4f88ccda | 452 | WORDS_NEEDED (2 * current->num_locals)); |
4ba9a1aa PB |
453 | } |
454 | ||
4f88ccda PB |
455 | /* Used when we done with a control flow branch and are all merged again. |
456 | * AFTER is the merged state of [un]assigned variables, | |
457 | CURRENT is a struct alt that was passed to BEGIN_ALTERNATIVES. */ | |
458 | ||
4ba9a1aa PB |
459 | #define END_ALTERNATIVES(after, current) \ |
460 | { \ | |
461 | alternatives = current.outer; \ | |
462 | COPY (after, current.combined); \ | |
463 | if (current.combined != ¤t.one_word) \ | |
464 | FREE_WORDS (current.combined); \ | |
465 | start_current_locals = current.save_start_current_locals; \ | |
466 | } | |
467 | ||
c7303e41 | 468 | /* Check for (un)initialized local variables in EXP. */ |
4ba9a1aa PB |
469 | |
470 | static void | |
0a2f0c54 | 471 | check_init (tree exp, words before) |
4ba9a1aa PB |
472 | { |
473 | tree tmp; | |
474 | again: | |
475 | switch (TREE_CODE (exp)) | |
476 | { | |
477 | case VAR_DECL: | |
4f88ccda PB |
478 | case PARM_DECL: |
479 | if (! FIELD_STATIC (exp) && DECL_NAME (exp) != NULL_TREE | |
480 | && DECL_NAME (exp) != this_identifier_node) | |
4ba9a1aa PB |
481 | { |
482 | int index = DECL_BIT_INDEX (exp); | |
4f88ccda PB |
483 | /* We don't want to report and mark as non initialized class |
484 | initialization flags. */ | |
485 | if (! LOCAL_CLASS_INITIALIZATION_FLAG_P (exp) | |
486 | && index >= 0 && ! ASSIGNED_P (before, index)) | |
4ba9a1aa | 487 | { |
c2952b01 APB |
488 | parse_error_context |
489 | (wfl, "Variable `%s' may not have been initialized", | |
490 | IDENTIFIER_POINTER (DECL_NAME (exp))); | |
4ba9a1aa | 491 | /* Suppress further errors. */ |
4f88ccda | 492 | DECL_BIT_INDEX (exp) = -2; |
4ba9a1aa PB |
493 | } |
494 | } | |
495 | break; | |
4f88ccda PB |
496 | |
497 | case COMPONENT_REF: | |
498 | check_init (TREE_OPERAND (exp, 0), before); | |
499 | if ((tmp = get_variable_decl (exp)) != NULL_TREE) | |
500 | { | |
501 | int index = DECL_BIT_INDEX (tmp); | |
502 | if (index >= 0 && ! ASSIGNED_P (before, index)) | |
503 | { | |
504 | parse_error_context | |
505 | (wfl, "variable '%s' may not have been initialized", | |
506 | IDENTIFIER_POINTER (DECL_NAME (tmp))); | |
507 | /* Suppress further errors. */ | |
508 | DECL_BIT_INDEX (tmp) = -2; | |
509 | } | |
510 | } | |
511 | break; | |
512 | ||
4ba9a1aa PB |
513 | case MODIFY_EXPR: |
514 | tmp = TREE_OPERAND (exp, 0); | |
c2952b01 APB |
515 | /* We're interested in variable declaration and parameter |
516 | declaration when they're declared with the `final' modifier. */ | |
4f88ccda | 517 | if ((tmp = get_variable_decl (tmp)) != NULL_TREE) |
4ba9a1aa PB |
518 | { |
519 | int index; | |
520 | check_init (TREE_OPERAND (exp, 1), before); | |
4f88ccda | 521 | check_final_reassigned (tmp, before); |
4ba9a1aa PB |
522 | index = DECL_BIT_INDEX (tmp); |
523 | if (index >= 0) | |
4f88ccda PB |
524 | { |
525 | SET_ASSIGNED (before, index); | |
526 | CLEAR_UNASSIGNED (before, index); | |
527 | } | |
4009bb7d APB |
528 | /* Minor optimization. See comment for start_current_locals. |
529 | If we're optimizing for class initialization, we keep | |
530 | this information to check whether the variable is | |
531 | definitely assigned when once we checked the whole | |
532 | function. */ | |
4f88ccda | 533 | if (! STATIC_CLASS_INIT_OPT_P () /* FIXME */ |
4009bb7d | 534 | && index >= start_current_locals |
4ba9a1aa PB |
535 | && index == num_current_locals - 1) |
536 | { | |
537 | num_current_locals--; | |
538 | DECL_BIT_INDEX (tmp) = -1; | |
539 | } | |
540 | break; | |
541 | } | |
4f88ccda PB |
542 | else if (TREE_CODE (tmp = TREE_OPERAND (exp, 0)) == COMPONENT_REF) |
543 | { | |
544 | tree decl; | |
545 | check_init (tmp, before); | |
546 | check_init (TREE_OPERAND (exp, 1), before); | |
547 | decl = TREE_OPERAND (tmp, 1); | |
548 | if (DECL_FINAL (decl)) | |
549 | final_assign_error (DECL_NAME (decl)); | |
550 | break; | |
551 | } | |
022dcc46 | 552 | else if (TREE_CODE (tmp) == COMPONENT_REF && IS_ARRAY_LENGTH_ACCESS (tmp)) |
4f88ccda PB |
553 | { |
554 | /* We can't emit a more specific message here, because when | |
555 | compiling to bytecodes we don't get here. */ | |
556 | final_assign_error (length_identifier_node); | |
557 | } | |
4ba9a1aa PB |
558 | else |
559 | goto binop; | |
560 | case BLOCK: | |
561 | if (BLOCK_EXPR_BODY (exp)) | |
562 | { | |
563 | tree decl = BLOCK_EXPR_DECLS (exp); | |
564 | int words_needed; | |
565 | word* tmp; | |
566 | int i; | |
567 | int save_start_current_locals = start_current_locals; | |
568 | int save_num_current_words = num_current_words; | |
569 | start_current_locals = num_current_locals; | |
570 | for (; decl != NULL_TREE; decl = TREE_CHAIN (decl)) | |
571 | { | |
572 | DECL_BIT_INDEX (decl) = num_current_locals++; | |
573 | } | |
4f88ccda | 574 | words_needed = WORDS_NEEDED (2 * num_current_locals); |
4ba9a1aa PB |
575 | if (words_needed > num_current_words) |
576 | { | |
577 | tmp = ALLOC_WORDS (words_needed); | |
578 | COPY (tmp, before); | |
579 | num_current_words = words_needed; | |
580 | } | |
581 | else | |
582 | tmp = before; | |
583 | for (i = start_current_locals; i < num_current_locals; i++) | |
4f88ccda PB |
584 | { |
585 | CLEAR_ASSIGNED (tmp, i); | |
586 | SET_UNASSIGNED (tmp, i); | |
587 | } | |
4ba9a1aa | 588 | check_init (BLOCK_EXPR_BODY (exp), tmp); |
5412ef6b PB |
589 | |
590 | /* Re-set DECL_BIT_INDEX since it is also DECL_POINTER_ALIAS_SET. */ | |
591 | for (decl = BLOCK_EXPR_DECLS (exp); | |
592 | decl != NULL_TREE; decl = TREE_CHAIN (decl)) | |
593 | { | |
594 | if (LOCAL_CLASS_INITIALIZATION_FLAG_P (decl)) | |
595 | { | |
596 | int index = DECL_BIT_INDEX (decl); | |
597 | tree fndecl = DECL_CONTEXT (decl); | |
598 | if (fndecl && METHOD_STATIC (fndecl) | |
599 | && (DECL_INITIAL (decl) == boolean_true_node | |
600 | || (index >= 0 && ASSIGNED_P (tmp, index)))) | |
e2500fed GK |
601 | *(htab_find_slot |
602 | (DECL_FUNCTION_INITIALIZED_CLASS_TABLE (fndecl), | |
603 | DECL_FUNCTION_INIT_TEST_CLASS (decl), INSERT)) = | |
604 | DECL_FUNCTION_INIT_TEST_CLASS (decl); | |
5412ef6b PB |
605 | } |
606 | DECL_BIT_INDEX (decl) = -1; | |
607 | } | |
608 | ||
4ba9a1aa PB |
609 | num_current_locals = start_current_locals; |
610 | start_current_locals = save_start_current_locals; | |
611 | if (tmp != before) | |
612 | { | |
613 | num_current_words = save_num_current_words; | |
614 | COPY (before, tmp); | |
615 | FREE_WORDS (tmp); | |
616 | } | |
617 | } | |
618 | break; | |
619 | case LOOP_EXPR: | |
620 | { | |
4f88ccda PB |
621 | /* The JLS 2nd edition discusses a complication determining |
622 | definite unassignment of loop statements. They define a | |
623 | "hypothetical" analysis model. We do something much | |
624 | simpler: We just disallow assignments inside loops to final | |
625 | variables declared outside the loop. This means we may | |
626 | disallow some contrived assignments that the JLS, but I | |
627 | can't see how anything except a very contrived testcase (a | |
628 | do-while whose condition is false?) would care. */ | |
629 | ||
4ba9a1aa | 630 | struct alternatives alt; |
4f88ccda PB |
631 | int save_loop_current_locals = loop_current_locals; |
632 | int save_start_current_locals = start_current_locals; | |
633 | loop_current_locals = num_current_locals; | |
634 | start_current_locals = num_current_locals; | |
4ba9a1aa PB |
635 | BEGIN_ALTERNATIVES (before, alt); |
636 | alt.block = exp; | |
637 | check_init (TREE_OPERAND (exp, 0), before); | |
4ba9a1aa | 638 | END_ALTERNATIVES (before, alt); |
4f88ccda PB |
639 | loop_current_locals = save_loop_current_locals; |
640 | start_current_locals = save_start_current_locals; | |
4ba9a1aa PB |
641 | return; |
642 | } | |
643 | case EXIT_EXPR: | |
644 | { | |
645 | struct alternatives *alt = alternatives; | |
4f88ccda PB |
646 | DECLARE_BUFFERS(when_true, 2); |
647 | words when_false = when_true + num_current_words; | |
9a7ab4b3 | 648 | #ifdef ENABLE_JC1_CHECKING |
4ba9a1aa | 649 | if (TREE_CODE (alt->block) != LOOP_EXPR) |
400500c4 | 650 | abort (); |
4ba9a1aa PB |
651 | #endif |
652 | check_bool_init (TREE_OPERAND (exp, 0), before, when_false, when_true); | |
653 | done_alternative (when_true, alt); | |
654 | COPY (before, when_false); | |
4f88ccda | 655 | RELEASE_BUFFERS(when_true); |
4ba9a1aa PB |
656 | return; |
657 | } | |
658 | case LABELED_BLOCK_EXPR: | |
659 | { | |
660 | struct alternatives alt; | |
661 | BEGIN_ALTERNATIVES (before, alt); | |
662 | alt.block = exp; | |
af8b342a APB |
663 | if (LABELED_BLOCK_BODY (exp)) |
664 | check_init (LABELED_BLOCK_BODY (exp), before); | |
4ba9a1aa PB |
665 | done_alternative (before, &alt); |
666 | END_ALTERNATIVES (before, alt); | |
667 | return; | |
668 | } | |
669 | case EXIT_BLOCK_EXPR: | |
670 | { | |
671 | tree block = TREE_OPERAND (exp, 0); | |
672 | struct alternatives *alt = alternatives; | |
673 | while (alt->block != block) | |
674 | alt = alt->outer; | |
675 | done_alternative (before, alt); | |
676 | SET_ALL (before); | |
677 | return; | |
678 | } | |
679 | case SWITCH_EXPR: | |
680 | { | |
681 | struct alternatives alt; | |
4f88ccda | 682 | word buf[2]; |
4ba9a1aa PB |
683 | check_init (TREE_OPERAND (exp, 0), before); |
684 | BEGIN_ALTERNATIVES (before, alt); | |
4f88ccda | 685 | alt.saved = ALLOC_BUFFER(buf, num_current_words); |
4ba9a1aa PB |
686 | COPY (alt.saved, before); |
687 | alt.block = exp; | |
688 | check_init (TREE_OPERAND (exp, 1), before); | |
689 | done_alternative (before, &alt); | |
3afdfae8 TT |
690 | if (! SWITCH_HAS_DEFAULT (exp)) |
691 | done_alternative (alt.saved, &alt); | |
4f88ccda | 692 | FREE_BUFFER(alt.saved, buf); |
4ba9a1aa PB |
693 | END_ALTERNATIVES (before, alt); |
694 | return; | |
695 | } | |
a5cb134d | 696 | case CASE_EXPR: |
3afdfae8 | 697 | case DEFAULT_EXPR: |
4ba9a1aa PB |
698 | { |
699 | int i; | |
700 | struct alternatives *alt = alternatives; | |
701 | while (TREE_CODE (alt->block) != SWITCH_EXPR) | |
702 | alt = alt->outer; | |
4f88ccda | 703 | COPYN (before, alt->saved, WORDS_NEEDED (2 * alt->num_locals)); |
4ba9a1aa | 704 | for (i = alt->num_locals; i < num_current_locals; i++) |
4f88ccda | 705 | CLEAR_ASSIGNED (before, i); |
4ba9a1aa PB |
706 | break; |
707 | } | |
708 | ||
4ba9a1aa PB |
709 | case TRY_EXPR: |
710 | { | |
711 | tree try_clause = TREE_OPERAND (exp, 0); | |
712 | tree clause = TREE_OPERAND (exp, 1); | |
4f88ccda PB |
713 | word buf[2*2]; |
714 | words tmp = (num_current_words <= 2 ? buf | |
715 | : ALLOC_WORDS (2 * num_current_words)); | |
716 | words save = tmp + num_current_words; | |
4ba9a1aa PB |
717 | struct alternatives alt; |
718 | BEGIN_ALTERNATIVES (before, alt); | |
719 | COPY (save, before); | |
720 | COPY (tmp, save); | |
721 | check_init (try_clause, tmp); | |
722 | done_alternative (tmp, &alt); | |
723 | for ( ; clause != NULL_TREE; clause = TREE_CHAIN (clause)) | |
724 | { | |
725 | tree catch_clause = TREE_OPERAND (clause, 0); | |
726 | COPY (tmp, save); | |
727 | check_init (catch_clause, tmp); | |
728 | done_alternative (tmp, &alt); | |
729 | } | |
4f88ccda PB |
730 | if (tmp != buf) |
731 | { | |
732 | FREE_WORDS (tmp); | |
733 | } | |
4ba9a1aa PB |
734 | END_ALTERNATIVES (before, alt); |
735 | } | |
736 | return; | |
737 | ||
0a3af4d8 PB |
738 | case TRY_FINALLY_EXPR: |
739 | { | |
4f88ccda | 740 | DECLARE_BUFFERS(tmp, 1); |
0a3af4d8 | 741 | COPY (tmp, before); |
4a83be51 PB |
742 | check_init (TREE_OPERAND (exp, 0), before); |
743 | check_init (TREE_OPERAND (exp, 1), tmp); | |
744 | UNION (before, before, tmp); | |
4f88ccda | 745 | RELEASE_BUFFERS(tmp); |
0a3af4d8 PB |
746 | } |
747 | return; | |
748 | ||
4ba9a1aa PB |
749 | case RETURN_EXPR: |
750 | case THROW_EXPR: | |
751 | if (TREE_OPERAND (exp, 0)) | |
752 | check_init (TREE_OPERAND (exp, 0), before); | |
b82daa87 | 753 | goto never_continues; |
4ba9a1aa PB |
754 | |
755 | case ERROR_MARK: | |
b82daa87 | 756 | never_continues: |
4ba9a1aa | 757 | SET_ALL (before); |
b82daa87 | 758 | return; |
4ba9a1aa PB |
759 | |
760 | case COND_EXPR: | |
761 | case TRUTH_ANDIF_EXPR: | |
762 | case TRUTH_ORIF_EXPR: | |
763 | { | |
4f88ccda PB |
764 | DECLARE_BUFFERS(when_true, 2); |
765 | words when_false = when_true + num_current_words; | |
4ba9a1aa PB |
766 | check_bool_init (exp, before, when_false, when_true); |
767 | INTERSECT (before, when_false, when_true); | |
4f88ccda | 768 | RELEASE_BUFFERS(when_true); |
4ba9a1aa PB |
769 | } |
770 | break; | |
4f88ccda PB |
771 | |
772 | case NOP_EXPR: | |
6de9cd9a | 773 | if (IS_EMPTY_STMT (exp)) |
4f88ccda PB |
774 | break; |
775 | /* ... else fall through ... */ | |
4ba9a1aa PB |
776 | case UNARY_PLUS_EXPR: |
777 | case NEGATE_EXPR: | |
f2693f2f PB |
778 | case TRUTH_AND_EXPR: |
779 | case TRUTH_OR_EXPR: | |
780 | case TRUTH_XOR_EXPR: | |
4ba9a1aa PB |
781 | case TRUTH_NOT_EXPR: |
782 | case BIT_NOT_EXPR: | |
783 | case CONVERT_EXPR: | |
458530ee | 784 | case BIT_FIELD_REF: |
4ba9a1aa PB |
785 | case FLOAT_EXPR: |
786 | case FIX_TRUNC_EXPR: | |
787 | case INDIRECT_REF: | |
788 | case ADDR_EXPR: | |
4ba9a1aa PB |
789 | case NON_LVALUE_EXPR: |
790 | case INSTANCEOF_EXPR: | |
d77a712d AH |
791 | case FIX_CEIL_EXPR: |
792 | case FIX_FLOOR_EXPR: | |
793 | case FIX_ROUND_EXPR: | |
d77a712d | 794 | case ABS_EXPR: |
4ba9a1aa PB |
795 | /* Avoid needless recursion. */ |
796 | exp = TREE_OPERAND (exp, 0); | |
797 | goto again; | |
798 | ||
1aca9b81 TT |
799 | case PREDECREMENT_EXPR: |
800 | case PREINCREMENT_EXPR: | |
801 | case POSTDECREMENT_EXPR: | |
802 | case POSTINCREMENT_EXPR: | |
803 | tmp = get_variable_decl (TREE_OPERAND (exp, 0)); | |
804 | if (tmp != NULL_TREE && DECL_FINAL (tmp)) | |
805 | final_assign_error (DECL_NAME (tmp)); | |
806 | ||
807 | /* Avoid needless recursion. */ | |
808 | exp = TREE_OPERAND (exp, 0); | |
809 | goto again; | |
810 | ||
1729c265 APB |
811 | case SAVE_EXPR: |
812 | if (IS_INIT_CHECKED (exp)) | |
813 | return; | |
814 | IS_INIT_CHECKED (exp) = 1; | |
815 | exp = TREE_OPERAND (exp, 0); | |
816 | goto again; | |
817 | ||
4ba9a1aa PB |
818 | case COMPOUND_EXPR: |
819 | case PLUS_EXPR: | |
820 | case MINUS_EXPR: | |
821 | case MULT_EXPR: | |
822 | case TRUNC_DIV_EXPR: | |
823 | case TRUNC_MOD_EXPR: | |
824 | case RDIV_EXPR: | |
825 | case LSHIFT_EXPR: | |
826 | case RSHIFT_EXPR: | |
827 | case URSHIFT_EXPR: | |
828 | case BIT_AND_EXPR: | |
829 | case BIT_XOR_EXPR: | |
830 | case BIT_IOR_EXPR: | |
831 | case EQ_EXPR: | |
832 | case NE_EXPR: | |
833 | case GT_EXPR: | |
834 | case GE_EXPR: | |
835 | case LT_EXPR: | |
836 | case LE_EXPR: | |
1a6d4fb7 | 837 | case MAX_EXPR: |
ac1d97ce | 838 | case MIN_EXPR: |
4ba9a1aa | 839 | case ARRAY_REF: |
d77a712d AH |
840 | case LROTATE_EXPR: |
841 | case RROTATE_EXPR: | |
842 | case CEIL_DIV_EXPR: | |
843 | case FLOOR_DIV_EXPR: | |
844 | case ROUND_DIV_EXPR: | |
845 | case CEIL_MOD_EXPR: | |
846 | case FLOOR_MOD_EXPR: | |
847 | case ROUND_MOD_EXPR: | |
848 | case EXACT_DIV_EXPR: | |
4ba9a1aa PB |
849 | binop: |
850 | check_init (TREE_OPERAND (exp, 0), before); | |
851 | /* Avoid needless recursion, especially for COMPOUND_EXPR. */ | |
852 | exp = TREE_OPERAND (exp, 1); | |
853 | goto again; | |
854 | ||
4ba9a1aa PB |
855 | case RESULT_DECL: |
856 | case FUNCTION_DECL: | |
857 | case INTEGER_CST: | |
858 | case REAL_CST: | |
859 | case STRING_CST: | |
f17f1898 | 860 | case JAVA_EXC_OBJ_EXPR: |
4ba9a1aa PB |
861 | break; |
862 | ||
863 | case NEW_CLASS_EXPR: | |
864 | case CALL_EXPR: | |
865 | { | |
b82daa87 | 866 | tree func = TREE_OPERAND (exp, 0); |
4ba9a1aa | 867 | tree x = TREE_OPERAND (exp, 1); |
b82daa87 PB |
868 | if (TREE_CODE (func) == ADDR_EXPR) |
869 | func = TREE_OPERAND (func, 0); | |
870 | check_init (func, before); | |
871 | ||
4ba9a1aa PB |
872 | for ( ; x != NULL_TREE; x = TREE_CHAIN (x)) |
873 | check_init (TREE_VALUE (x), before); | |
ce1c98ea | 874 | if (func == throw_node) |
b82daa87 | 875 | goto never_continues; |
4ba9a1aa PB |
876 | } |
877 | break; | |
878 | ||
879 | case NEW_ARRAY_INIT: | |
880 | { | |
881 | tree x = CONSTRUCTOR_ELTS (TREE_OPERAND (exp, 0)); | |
882 | for ( ; x != NULL_TREE; x = TREE_CHAIN (x)) | |
883 | check_init (TREE_VALUE (x), before); | |
884 | } | |
885 | break; | |
886 | ||
887 | case EXPR_WITH_FILE_LOCATION: | |
888 | { | |
436fac17 | 889 | location_t saved_location = input_location; |
4ba9a1aa PB |
890 | tree saved_wfl = wfl; |
891 | tree body = EXPR_WFL_NODE (exp); | |
6de9cd9a | 892 | if (IS_EMPTY_STMT (body)) |
4ba9a1aa PB |
893 | break; |
894 | wfl = exp; | |
895 | input_filename = EXPR_WFL_FILENAME (exp); | |
d479d37f | 896 | input_line = EXPR_WFL_LINENO (exp); |
4ba9a1aa | 897 | check_init (body, before); |
436fac17 | 898 | input_location = saved_location; |
4ba9a1aa PB |
899 | wfl = saved_wfl; |
900 | } | |
901 | break; | |
902 | ||
903 | default: | |
400500c4 RK |
904 | internal_error |
905 | ("internal error in check-init: tree code not implemented: %s", | |
906 | tree_code_name [(int) TREE_CODE (exp)]); | |
4ba9a1aa PB |
907 | } |
908 | } | |
909 | ||
4f88ccda | 910 | void |
0a2f0c54 | 911 | check_for_initialization (tree body, tree mdecl) |
4ba9a1aa | 912 | { |
4f88ccda PB |
913 | tree decl; |
914 | word buf[2]; | |
915 | words before = buf; | |
916 | tree owner = DECL_CONTEXT (mdecl); | |
917 | int is_static_method = METHOD_STATIC (mdecl); | |
918 | /* We don't need to check final fields of <init> it it calls this(). */ | |
919 | int is_finit_method = DECL_FINIT_P (mdecl) || DECL_INSTINIT_P (mdecl); | |
920 | int is_init_method | |
921 | = (is_finit_method || DECL_CLINIT_P (mdecl) | |
922 | || (DECL_INIT_P (mdecl) && ! DECL_INIT_CALLS_THIS (mdecl))); | |
923 | ||
924 | start_current_locals = num_current_locals = 0; | |
925 | num_current_words = 2; | |
926 | ||
927 | if (is_init_method) | |
928 | { | |
929 | int words_needed, i; | |
930 | for (decl = TYPE_FIELDS (owner); | |
931 | decl != NULL_TREE; decl = TREE_CHAIN (decl)) | |
932 | { | |
933 | if (DECL_FINAL (decl) && FIELD_STATIC (decl) == is_static_method) | |
934 | { | |
935 | if (DECL_FIELD_FINAL_IUD (decl)) | |
936 | DECL_BIT_INDEX (decl) = -1; | |
937 | else | |
938 | DECL_BIT_INDEX (decl) = num_current_locals++; | |
939 | } | |
940 | } | |
941 | words_needed = WORDS_NEEDED (2 * num_current_locals); | |
942 | if (words_needed > 2) | |
943 | { | |
944 | num_current_words = words_needed; | |
945 | before = ALLOC_WORDS(words_needed); | |
946 | } | |
947 | i = 0; | |
948 | for (decl = TYPE_FIELDS (owner); | |
949 | decl != NULL_TREE; decl = TREE_CHAIN (decl)) | |
950 | { | |
951 | if (FIELD_FINAL (decl) && FIELD_STATIC (decl) == is_static_method) | |
952 | { | |
953 | if (! DECL_FIELD_FINAL_IUD (decl)) | |
954 | { | |
955 | CLEAR_ASSIGNED (before, i); | |
956 | SET_UNASSIGNED (before, i); | |
957 | i++; | |
958 | } | |
959 | } | |
960 | } | |
961 | ||
962 | } | |
963 | ||
964 | check_init (body, before); | |
965 | ||
966 | if (is_init_method) | |
967 | { | |
968 | for (decl = TYPE_FIELDS (owner); | |
969 | decl != NULL_TREE; decl = TREE_CHAIN (decl)) | |
970 | { | |
971 | if (FIELD_FINAL (decl) && FIELD_STATIC (decl) == is_static_method) | |
972 | { | |
973 | int index = DECL_BIT_INDEX (decl); | |
974 | if (index >= 0 && ! ASSIGNED_P (before, index)) | |
975 | { | |
976 | if (! is_finit_method) | |
ddd2d57e RH |
977 | error ("%Jfinal field '%D' may not have been initialized", |
978 | decl, decl); | |
4f88ccda PB |
979 | } |
980 | else if (is_finit_method) | |
981 | DECL_FIELD_FINAL_IUD (decl) = 1; | |
982 | ||
983 | /* Re-set to initial state, since we later may use the | |
984 | same bit for DECL_POINTER_ALIAS_SET. */ | |
985 | DECL_BIT_INDEX (decl) = -1; | |
986 | } | |
987 | } | |
988 | } | |
989 | ||
990 | start_current_locals = num_current_locals = 0; | |
4009bb7d | 991 | } |