提交 85085369 编写于 作者: M mcimadamore

7175538: Integrate efectively final check with DA/DU analysis

Summary: Allow generalized effectively-final analysis for all local variables
Reviewed-by: jjg, dlsmith
上级 69c74446
......@@ -200,6 +200,9 @@ public enum Source {
public boolean allowMethodReferences() {
return compareTo(JDK1_8) >= 0;
}
public boolean allowEffectivelyFinalInInnerClasses() {
return compareTo(JDK1_8) >= 0;
}
public static SourceVersion toSourceVersion(Source source) {
switch(source) {
case JDK1_2:
......
......@@ -228,7 +228,7 @@ public class Attr extends JCTree.Visitor {
* @param env The current environment.
*/
boolean isAssignableAsBlankFinal(VarSymbol v, Env<AttrContext> env) {
Symbol owner = env.info.scope.owner;
Symbol owner = owner(env);
// owner refers to the innermost variable, method or
// initializer block declaration at this point.
return
......@@ -243,6 +243,41 @@ public class Attr extends JCTree.Visitor {
((v.flags() & STATIC) != 0) == Resolve.isStatic(env));
}
/**
* Return the innermost enclosing owner symbol in a given attribution context
*/
Symbol owner(Env<AttrContext> env) {
while (true) {
switch (env.tree.getTag()) {
case VARDEF:
//a field can be owner
VarSymbol vsym = ((JCVariableDecl)env.tree).sym;
if (vsym.owner.kind == TYP) {
return vsym;
}
break;
case METHODDEF:
//method def is always an owner
return ((JCMethodDecl)env.tree).sym;
case CLASSDEF:
//class def is always an owner
return ((JCClassDecl)env.tree).sym;
case BLOCK:
//static/instance init blocks are owner
Symbol blockSym = env.info.scope.owner;
if ((blockSym.flags() & BLOCK) != 0) {
return blockSym;
}
break;
case TOPLEVEL:
//toplevel is always an owner (for pkge decls)
return env.info.scope.owner;
}
Assert.checkNonNull(env.next);
env = env.next;
}
}
/** Check that variable can be assigned to.
* @param pos The current source code position.
* @param v The assigned varaible
......@@ -883,7 +918,6 @@ public class Attr extends JCTree.Visitor {
memberEnter.memberEnter(tree, env);
annotate.flush();
}
tree.sym.flags_field |= EFFECTIVELY_FINAL;
}
VarSymbol v = tree.sym;
......@@ -2187,16 +2221,6 @@ public class Attr extends JCTree.Visitor {
// illegal forward reference.
checkInit(tree, env, v, false);
// If symbol is a local variable accessed from an embedded
// inner class check that it is final.
if (v.owner.kind == MTH &&
v.owner != env.info.scope.owner &&
(v.flags_field & FINAL) == 0) {
log.error(tree.pos(),
"local.var.accessed.from.icls.needs.final",
v);
}
// If we are expecting a variable (as opposed to a value), check
// that the variable is assignable in the current environment.
if (pkind() == VAR)
......@@ -2590,7 +2614,7 @@ public class Attr extends JCTree.Visitor {
// and are subject to definite assignment checking.
if ((env.info.enclVar == v || v.pos > tree.pos) &&
v.owner.kind == TYP &&
canOwnInitializer(env.info.scope.owner) &&
canOwnInitializer(owner(env)) &&
v.owner == env.info.scope.owner.enclClass() &&
((v.flags() & STATIC) != 0) == Resolve.isStatic(env) &&
(!env.tree.hasTag(ASSIGN) ||
......
......@@ -113,9 +113,9 @@ public class JavacParser implements Parser {
this.allowMulticatch = source.allowMulticatch();
this.allowStringFolding = fac.options.getBoolean("allowStringFolding", true);
this.allowLambda = source.allowLambda() &&
fac.options.isSet("allowLambda");
fac.options.isSet("allowLambda"); //pre-lambda guard
this.allowMethodReferences = source.allowMethodReferences() &&
fac.options.isSet("allowMethodReferences");
fac.options.isSet("allowMethodReferences"); //pre-lambda guard
this.keepDocComments = keepDocComments;
docComments = newDocCommentTable(keepDocComments);
this.keepLineMap = keepLineMap;
......
......@@ -168,6 +168,14 @@ compiler.err.cant.apply.symbols=\
compiler.err.cant.assign.val.to.final.var=\
cannot assign a value to final variable {0}
# 0: symbol, 1: message segment
compiler.err.cant.ref.non.effectively.final.var=\
local variables referenced from {1} must be final or effectively final
compiler.misc.inner.cls=\
an inner class
# 0: type
compiler.err.cant.deref=\
{0} cannot be dereferenced
......
/*
* Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
// key: compiler.err.cant.ref.non.effectively.final.var
// key: compiler.misc.inner.cls
// options: -XDallowEffectivelyFinalInInnerClasses
class CantRefNonEffectivelyFinalVar {
void test() {
int i = 0;
new Object() { int j = i; };
i = 2;
}
}
/*
* Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
/*
* @test
* @summary Integrate efectively final check with DA/DU analysis
* @compile/fail/ref=EffectivelyFinalTest01.out -XDallowEffectivelyFinalInInnerClasses -XDrawDiagnostics EffectivelyFinalTest.java
* @compile/fail/ref=EffectivelyFinalTest02.out -source 7 -Xlint:-options -XDrawDiagnostics EffectivelyFinalTest.java
*/
class EffectivelyFinalTest {
void m1(int x) {
int y = 1;
new Object() { { System.out.println(x+y); } }; //ok - both x and y are EF
}
void m2(int x) {
int y;
y = 1;
new Object() { { System.out.println(x+y); } }; //ok - both x and y are EF
}
void m3(int x, boolean cond) {
int y;
if (cond) y = 1;
new Object() { { System.out.println(x+y); } }; //error - y not DA
}
void m4(int x, boolean cond) {
int y;
if (cond) y = 1;
else y = 2;
new Object() { { System.out.println(x+y); } }; //ok - both x and y are EF
}
void m5(int x, boolean cond) {
int y;
if (cond) y = 1;
y = 2;
new Object() { { System.out.println(x+y); } }; //error - y not EF
}
void m6(int x) {
new Object() { { System.out.println(x+1); } }; //error - x not EF
x++;
}
void m7(int x) {
new Object() { { System.out.println(x=1); } }; //error - x not EF
}
void m8() {
int y;
new Object() { { System.out.println(y=1); } }; //error - y not EF
}
}
EffectivelyFinalTest.java:46:47: compiler.err.var.might.not.have.been.initialized: y
EffectivelyFinalTest.java:60:47: compiler.err.cant.ref.non.effectively.final.var: y, (compiler.misc.inner.cls)
EffectivelyFinalTest.java:64:45: compiler.err.cant.ref.non.effectively.final.var: x, (compiler.misc.inner.cls)
EffectivelyFinalTest.java:69:45: compiler.err.cant.ref.non.effectively.final.var: x, (compiler.misc.inner.cls)
EffectivelyFinalTest.java:74:45: compiler.err.cant.ref.non.effectively.final.var: y, (compiler.misc.inner.cls)
5 errors
EffectivelyFinalTest.java:46:47: compiler.err.var.might.not.have.been.initialized: y
EffectivelyFinalTest.java:34:45: compiler.err.local.var.accessed.from.icls.needs.final: x
EffectivelyFinalTest.java:34:47: compiler.err.local.var.accessed.from.icls.needs.final: y
EffectivelyFinalTest.java:40:45: compiler.err.local.var.accessed.from.icls.needs.final: x
EffectivelyFinalTest.java:40:47: compiler.err.local.var.accessed.from.icls.needs.final: y
EffectivelyFinalTest.java:46:45: compiler.err.local.var.accessed.from.icls.needs.final: x
EffectivelyFinalTest.java:53:45: compiler.err.local.var.accessed.from.icls.needs.final: x
EffectivelyFinalTest.java:53:47: compiler.err.local.var.accessed.from.icls.needs.final: y
EffectivelyFinalTest.java:60:45: compiler.err.local.var.accessed.from.icls.needs.final: x
EffectivelyFinalTest.java:60:47: compiler.err.local.var.accessed.from.icls.needs.final: y
EffectivelyFinalTest.java:64:45: compiler.err.local.var.accessed.from.icls.needs.final: x
EffectivelyFinalTest.java:69:45: compiler.err.local.var.accessed.from.icls.needs.final: x
EffectivelyFinalTest.java:74:45: compiler.err.local.var.accessed.from.icls.needs.final: y
13 errors
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册