8169345: javac crash when local from enclosing context is captured multiple times
Captured variables imported from multiple enclosing scopes are not handled correctly Reviewed-by: vromero
This commit is contained in:
parent
e92da5e381
commit
305e51848a
src/jdk.compiler/share/classes/com/sun/tools/javac/comp
test/langtools/tools/javac/8169345
@ -308,8 +308,8 @@ public class Lower extends TreeTranslator {
|
||||
void visitSymbol(Symbol _sym) {
|
||||
Symbol sym = _sym;
|
||||
if (sym.kind == VAR || sym.kind == MTH) {
|
||||
while (sym != null && sym.owner != owner)
|
||||
sym = proxies.findFirst(proxyName(sym.name));
|
||||
if (sym != null && sym.owner != owner)
|
||||
sym = proxies.get(sym);
|
||||
if (sym != null && sym.owner == owner) {
|
||||
VarSymbol v = (VarSymbol)sym;
|
||||
if (v.getConstValue() == null) {
|
||||
@ -1084,7 +1084,7 @@ public class Lower extends TreeTranslator {
|
||||
return makeLit(sym.type, cv);
|
||||
}
|
||||
// Otherwise replace the variable by its proxy.
|
||||
sym = proxies.findFirst(proxyName(sym.name));
|
||||
sym = proxies.get(sym);
|
||||
Assert.check(sym != null && (sym.flags_field & FINAL) != 0);
|
||||
tree = make.at(tree.pos).Ident(sym);
|
||||
}
|
||||
@ -1359,14 +1359,12 @@ public class Lower extends TreeTranslator {
|
||||
* Free variables proxies and this$n
|
||||
*************************************************************************/
|
||||
|
||||
/** A scope containing all free variable proxies for currently translated
|
||||
* class, as well as its this$n symbol (if needed).
|
||||
* Proxy scopes are nested in the same way classes are.
|
||||
* Inside a constructor, proxies and any this$n symbol are duplicated
|
||||
* in an additional innermost scope, where they represent the constructor
|
||||
* parameters.
|
||||
/** A map which allows to retrieve the translated proxy variable for any given symbol of an
|
||||
* enclosing scope that is accessed (the accessed symbol could be the synthetic 'this$n' symbol).
|
||||
* Inside a constructor, the map temporarily overrides entries corresponding to proxies and any
|
||||
* 'this$n' symbols, where they represent the constructor parameters.
|
||||
*/
|
||||
WriteableScope proxies;
|
||||
Map<Symbol, Symbol> proxies;
|
||||
|
||||
/** A scope containing all unnamed resource variables/saved
|
||||
* exception variables for translated TWR blocks
|
||||
@ -1383,8 +1381,12 @@ public class Lower extends TreeTranslator {
|
||||
|
||||
/** The name of a free variable proxy.
|
||||
*/
|
||||
Name proxyName(Name name) {
|
||||
return names.fromString("val" + target.syntheticNameChar() + name);
|
||||
Name proxyName(Name name, int index) {
|
||||
Name proxyName = names.fromString("val" + target.syntheticNameChar() + name);
|
||||
if (index > 0) {
|
||||
proxyName = proxyName.append(names.fromString("" + target.syntheticNameChar() + index));
|
||||
}
|
||||
return proxyName;
|
||||
}
|
||||
|
||||
/** Proxy definitions for all free variables in given list, in reverse order.
|
||||
@ -1400,11 +1402,17 @@ public class Lower extends TreeTranslator {
|
||||
long additionalFlags) {
|
||||
long flags = FINAL | SYNTHETIC | additionalFlags;
|
||||
List<JCVariableDecl> defs = List.nil();
|
||||
Set<Name> proxyNames = new HashSet<>();
|
||||
for (List<VarSymbol> l = freevars; l.nonEmpty(); l = l.tail) {
|
||||
VarSymbol v = l.head;
|
||||
int index = 0;
|
||||
Name proxyName;
|
||||
do {
|
||||
proxyName = proxyName(v.name, index++);
|
||||
} while (!proxyNames.add(proxyName));
|
||||
VarSymbol proxy = new VarSymbol(
|
||||
flags, proxyName(v.name), v.erasure(types), owner);
|
||||
proxies.enter(proxy);
|
||||
flags, proxyName, v.erasure(types), owner);
|
||||
proxies.put(v, proxy);
|
||||
JCVariableDecl vd = make.at(pos).VarDef(proxy, null);
|
||||
vd.vartype = access(vd.vartype);
|
||||
defs = defs.prepend(vd);
|
||||
@ -1843,11 +1851,8 @@ public class Lower extends TreeTranslator {
|
||||
/** Return tree simulating the assignment {@code this.name = name}, where
|
||||
* name is the name of a free variable.
|
||||
*/
|
||||
JCStatement initField(int pos, Name name) {
|
||||
Iterator<Symbol> it = proxies.getSymbolsByName(name).iterator();
|
||||
Symbol rhs = it.next();
|
||||
JCStatement initField(int pos, Symbol rhs, Symbol lhs) {
|
||||
Assert.check(rhs.owner.kind == MTH);
|
||||
Symbol lhs = it.next();
|
||||
Assert.check(rhs.owner.owner == lhs.owner);
|
||||
make.at(pos);
|
||||
return
|
||||
@ -2207,7 +2212,8 @@ public class Lower extends TreeTranslator {
|
||||
|
||||
classdefs.put(currentClass, tree);
|
||||
|
||||
proxies = proxies.dup(currentClass);
|
||||
Map<Symbol, Symbol> prevProxies = proxies;
|
||||
proxies = new HashMap<>(proxies);
|
||||
List<VarSymbol> prevOuterThisStack = outerThisStack;
|
||||
|
||||
// If this is an enum definition
|
||||
@ -2270,7 +2276,7 @@ public class Lower extends TreeTranslator {
|
||||
enterSynthetic(tree.pos(), otdef.sym, currentClass.members());
|
||||
}
|
||||
|
||||
proxies = proxies.leave();
|
||||
proxies = prevProxies;
|
||||
outerThisStack = prevOuterThisStack;
|
||||
|
||||
// Append translated tree to `translated' queue.
|
||||
@ -2488,7 +2494,8 @@ public class Lower extends TreeTranslator {
|
||||
|
||||
// Push a new proxy scope for constructor parameters.
|
||||
// and create definitions for any this$n and proxy parameters.
|
||||
proxies = proxies.dup(m);
|
||||
Map<Symbol, Symbol> prevProxies = proxies;
|
||||
proxies = new HashMap<>(proxies);
|
||||
List<VarSymbol> prevOuterThisStack = outerThisStack;
|
||||
List<VarSymbol> fvs = freevars(currentClass);
|
||||
JCVariableDecl otdef = null;
|
||||
@ -2523,13 +2530,12 @@ public class Lower extends TreeTranslator {
|
||||
if (fvs.nonEmpty()) {
|
||||
List<Type> addedargtypes = List.nil();
|
||||
for (List<VarSymbol> l = fvs; l.nonEmpty(); l = l.tail) {
|
||||
final Name pName = proxyName(l.head.name);
|
||||
m.capturedLocals =
|
||||
m.capturedLocals.prepend((VarSymbol)
|
||||
(proxies.findFirst(pName)));
|
||||
(proxies.get(l.head)));
|
||||
if (TreeInfo.isInitialConstructor(tree)) {
|
||||
added = added.prepend(
|
||||
initField(tree.body.pos, pName));
|
||||
initField(tree.body.pos, proxies.get(l.head), prevProxies.get(l.head)));
|
||||
}
|
||||
addedargtypes = addedargtypes.prepend(l.head.erasure(types));
|
||||
}
|
||||
@ -2547,7 +2553,7 @@ public class Lower extends TreeTranslator {
|
||||
}
|
||||
|
||||
// pop local variables from proxy stack
|
||||
proxies = proxies.leave();
|
||||
proxies = prevProxies;
|
||||
|
||||
// recursively translate following local statements and
|
||||
// combine with this- or super-call
|
||||
@ -3714,7 +3720,7 @@ public class Lower extends TreeTranslator {
|
||||
classdefs = new HashMap<>();
|
||||
actualSymbols = new HashMap<>();
|
||||
freevarCache = new HashMap<>();
|
||||
proxies = WriteableScope.create(syms.noSymbol);
|
||||
proxies = new HashMap<>();
|
||||
twrVars = WriteableScope.create(syms.noSymbol);
|
||||
outerThisStack = List.nil();
|
||||
accessNums = new HashMap<>();
|
||||
|
55
test/langtools/tools/javac/8169345/T8169345a.java
Normal file
55
test/langtools/tools/javac/8169345/T8169345a.java
Normal file
@ -0,0 +1,55 @@
|
||||
/*
|
||||
* Copyright (c) 2017, 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
|
||||
* @bug 8169345
|
||||
* @summary javac crash when local from enclosing context is captured multiple times
|
||||
*/
|
||||
|
||||
public class T8169345a {
|
||||
void test() {
|
||||
Object o = new Object();
|
||||
class Local1 {
|
||||
Object test1() {
|
||||
return o;
|
||||
}
|
||||
}
|
||||
class Local2 {
|
||||
void test2() {
|
||||
Object o = new Object();
|
||||
class Local3 extends Local1 {
|
||||
Object test3() {
|
||||
return o;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public static void main(String[] args) throws Exception {
|
||||
Class.forName("T8169345a$1Local1");
|
||||
Class.forName("T8169345a$1Local2$1Local3");
|
||||
Class.forName("T8169345a$1Local2");
|
||||
}
|
||||
}
|
57
test/langtools/tools/javac/8169345/T8169345b.java
Normal file
57
test/langtools/tools/javac/8169345/T8169345b.java
Normal file
@ -0,0 +1,57 @@
|
||||
/*
|
||||
* Copyright (c) 2017, 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. Oracle designates this
|
||||
* particular file as subject to the "Classpath" exception as provided
|
||||
* by Oracle in the LICENSE file that accompanied this code.
|
||||
*
|
||||
* 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
|
||||
* @bug 8169345
|
||||
* @summary javac crash when local from enclosing context is captured multiple times
|
||||
*/
|
||||
|
||||
public class T8169345b {
|
||||
void test() {
|
||||
Object o = new Object();
|
||||
class Local1 {
|
||||
Object test1() {
|
||||
return o;
|
||||
}
|
||||
}
|
||||
class Local2 {
|
||||
void test2() {
|
||||
Object o = new Object();
|
||||
class Local3 {
|
||||
Object test3() {
|
||||
return o;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public static void main(String[] args) throws Exception {
|
||||
Class.forName("T8169345b$1Local1");
|
||||
Class.forName("T8169345b$1Local2$1Local3");
|
||||
Class.forName("T8169345b$1Local2");
|
||||
}
|
||||
}
|
54
test/langtools/tools/javac/8169345/T8169345c.java
Normal file
54
test/langtools/tools/javac/8169345/T8169345c.java
Normal file
@ -0,0 +1,54 @@
|
||||
/*
|
||||
* Copyright (c) 2017, 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. Oracle designates this
|
||||
* particular file as subject to the "Classpath" exception as provided
|
||||
* by Oracle in the LICENSE file that accompanied this code.
|
||||
*
|
||||
* 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
|
||||
* @bug 8169345
|
||||
* @summary javac crash when local from enclosing context is captured multiple times
|
||||
* @compile T8169345c.java
|
||||
*/
|
||||
|
||||
class T8169345c {
|
||||
void test() {
|
||||
final int b;
|
||||
b = 10;
|
||||
class Local1 {
|
||||
public String toString() {
|
||||
return "" + b;
|
||||
}
|
||||
}
|
||||
class Local2 {
|
||||
void test() {
|
||||
final int b;
|
||||
b = 20;
|
||||
class DeepLocal extends Local1 {
|
||||
public String toString() {
|
||||
return "" + b;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
Loading…
x
Reference in New Issue
Block a user