226 * may be assigned to even though it is final? |
226 * may be assigned to even though it is final? |
227 * @param v The blank final variable. |
227 * @param v The blank final variable. |
228 * @param env The current environment. |
228 * @param env The current environment. |
229 */ |
229 */ |
230 boolean isAssignableAsBlankFinal(VarSymbol v, Env<AttrContext> env) { |
230 boolean isAssignableAsBlankFinal(VarSymbol v, Env<AttrContext> env) { |
231 Symbol owner = env.info.scope.owner; |
231 Symbol owner = owner(env); |
232 // owner refers to the innermost variable, method or |
232 // owner refers to the innermost variable, method or |
233 // initializer block declaration at this point. |
233 // initializer block declaration at this point. |
234 return |
234 return |
235 v.owner == owner |
235 v.owner == owner |
236 || |
236 || |
239 (owner.flags() & BLOCK) != 0) // i.e. we are in an initializer block |
239 (owner.flags() & BLOCK) != 0) // i.e. we are in an initializer block |
240 && |
240 && |
241 v.owner == owner.owner |
241 v.owner == owner.owner |
242 && |
242 && |
243 ((v.flags() & STATIC) != 0) == Resolve.isStatic(env)); |
243 ((v.flags() & STATIC) != 0) == Resolve.isStatic(env)); |
|
244 } |
|
245 |
|
246 /** |
|
247 * Return the innermost enclosing owner symbol in a given attribution context |
|
248 */ |
|
249 Symbol owner(Env<AttrContext> env) { |
|
250 while (true) { |
|
251 switch (env.tree.getTag()) { |
|
252 case VARDEF: |
|
253 //a field can be owner |
|
254 VarSymbol vsym = ((JCVariableDecl)env.tree).sym; |
|
255 if (vsym.owner.kind == TYP) { |
|
256 return vsym; |
|
257 } |
|
258 break; |
|
259 case METHODDEF: |
|
260 //method def is always an owner |
|
261 return ((JCMethodDecl)env.tree).sym; |
|
262 case CLASSDEF: |
|
263 //class def is always an owner |
|
264 return ((JCClassDecl)env.tree).sym; |
|
265 case BLOCK: |
|
266 //static/instance init blocks are owner |
|
267 Symbol blockSym = env.info.scope.owner; |
|
268 if ((blockSym.flags() & BLOCK) != 0) { |
|
269 return blockSym; |
|
270 } |
|
271 break; |
|
272 case TOPLEVEL: |
|
273 //toplevel is always an owner (for pkge decls) |
|
274 return env.info.scope.owner; |
|
275 } |
|
276 Assert.checkNonNull(env.next); |
|
277 env = env.next; |
|
278 } |
244 } |
279 } |
245 |
280 |
246 /** Check that variable can be assigned to. |
281 /** Check that variable can be assigned to. |
247 * @param pos The current source code position. |
282 * @param pos The current source code position. |
248 * @param v The assigned varaible |
283 * @param v The assigned varaible |
881 env.info.scope.enter(tree.sym); |
916 env.info.scope.enter(tree.sym); |
882 } else { |
917 } else { |
883 memberEnter.memberEnter(tree, env); |
918 memberEnter.memberEnter(tree, env); |
884 annotate.flush(); |
919 annotate.flush(); |
885 } |
920 } |
886 tree.sym.flags_field |= EFFECTIVELY_FINAL; |
|
887 } |
921 } |
888 |
922 |
889 VarSymbol v = tree.sym; |
923 VarSymbol v = tree.sym; |
890 Lint lint = env.info.lint.augment(v.attributes_field, v.flags()); |
924 Lint lint = env.info.lint.augment(v.attributes_field, v.flags()); |
891 Lint prevLint = chk.setLint(lint); |
925 Lint prevLint = chk.setLint(lint); |
2185 |
2219 |
2186 // ..., evaluate its initializer, if it has one, and check for |
2220 // ..., evaluate its initializer, if it has one, and check for |
2187 // illegal forward reference. |
2221 // illegal forward reference. |
2188 checkInit(tree, env, v, false); |
2222 checkInit(tree, env, v, false); |
2189 |
2223 |
2190 // If symbol is a local variable accessed from an embedded |
|
2191 // inner class check that it is final. |
|
2192 if (v.owner.kind == MTH && |
|
2193 v.owner != env.info.scope.owner && |
|
2194 (v.flags_field & FINAL) == 0) { |
|
2195 log.error(tree.pos(), |
|
2196 "local.var.accessed.from.icls.needs.final", |
|
2197 v); |
|
2198 } |
|
2199 |
|
2200 // If we are expecting a variable (as opposed to a value), check |
2224 // If we are expecting a variable (as opposed to a value), check |
2201 // that the variable is assignable in the current environment. |
2225 // that the variable is assignable in the current environment. |
2202 if (pkind() == VAR) |
2226 if (pkind() == VAR) |
2203 checkAssignable(tree.pos(), v, null, env); |
2227 checkAssignable(tree.pos(), v, null, env); |
2204 } |
2228 } |
2588 // This check applies only to class and instance |
2612 // This check applies only to class and instance |
2589 // variables. Local variables follow different scope rules, |
2613 // variables. Local variables follow different scope rules, |
2590 // and are subject to definite assignment checking. |
2614 // and are subject to definite assignment checking. |
2591 if ((env.info.enclVar == v || v.pos > tree.pos) && |
2615 if ((env.info.enclVar == v || v.pos > tree.pos) && |
2592 v.owner.kind == TYP && |
2616 v.owner.kind == TYP && |
2593 canOwnInitializer(env.info.scope.owner) && |
2617 canOwnInitializer(owner(env)) && |
2594 v.owner == env.info.scope.owner.enclClass() && |
2618 v.owner == env.info.scope.owner.enclClass() && |
2595 ((v.flags() & STATIC) != 0) == Resolve.isStatic(env) && |
2619 ((v.flags() & STATIC) != 0) == Resolve.isStatic(env) && |
2596 (!env.tree.hasTag(ASSIGN) || |
2620 (!env.tree.hasTag(ASSIGN) || |
2597 TreeInfo.skipParens(((JCAssign) env.tree).lhs) != tree)) { |
2621 TreeInfo.skipParens(((JCAssign) env.tree).lhs) != tree)) { |
2598 String suffix = (env.info.enclVar == v) ? |
2622 String suffix = (env.info.enclVar == v) ? |