# HG changeset patch # User jlahoda # Date 1385476392 -3600 # Node ID 756ae3791c459f7512808aa89f31094cd3423219 # Parent 8acb838c9b79d3c742096e8d65c89c867db5e5b5 8027789: Access method for Outer.super.m() references indirect superclass Summary: Internally convert the qualified super access to an equivalent of an unqualified super access inside the access method. Reviewed-by: vromero, jjg diff -r 8acb838c9b79 -r 756ae3791c45 src/share/classes/com/sun/tools/javac/comp/Lower.java --- a/src/share/classes/com/sun/tools/javac/comp/Lower.java Tue Nov 26 15:27:19 2013 +0100 +++ b/src/share/classes/com/sun/tools/javac/comp/Lower.java Tue Nov 26 15:33:12 2013 +0100 @@ -1378,11 +1378,14 @@ ref = make.Ident(sym); args = make.Idents(md.params); } else { - Symbol msym = sym; - if (sym.owner.isInterface()) { - msym = msym.clone(types.supertype(accessor.owner.type).tsym); + JCExpression site = make.Ident(md.params.head); + if (acode % 2 != 0) { + //odd access codes represent qualified super accesses - need to + //emit reference to the direct superclass, even if the refered + //member is from an indirect superclass (JLS 13.1) + site.setType(types.erasure(types.supertype(vsym.owner.enclClass().type))); } - ref = make.Select(make.Ident(md.params.head), msym); + ref = make.Select(site, sym); args = make.Idents(md.params.tail); } JCStatement stat; // The statement accessing the private symbol. diff -r 8acb838c9b79 -r 756ae3791c45 src/share/classes/com/sun/tools/javac/jvm/Gen.java --- a/src/share/classes/com/sun/tools/javac/jvm/Gen.java Tue Nov 26 15:27:19 2013 +0100 +++ b/src/share/classes/com/sun/tools/javac/jvm/Gen.java Tue Nov 26 15:33:12 2013 +0100 @@ -2420,7 +2420,7 @@ if (isInvokeDynamic(sym)) { result = items.makeDynamicItem(sym); return; - } else if (!accessSuper) { + } else { sym = binaryQualifier(sym, tree.selected.type); } if ((sym.flags() & STATIC) != 0) { diff -r 8acb838c9b79 -r 756ae3791c45 test/tools/javac/expression/_super/NonDirectSuper/Base.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/tools/javac/expression/_super/NonDirectSuper/Base.java Tue Nov 26 15:33:12 2013 +0100 @@ -0,0 +1,45 @@ +/* + * Copyright (c) 2013, 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. + */ + +package base; + +public class Base extends PackagePrivate { } + +class PackagePrivate { + protected int refTobaseBase() { + return 0; + } + protected int refTotestOtherPackageTest() { + return 0; + } + protected int refTotestTarget11() { + return 0; + } + protected int refTotestCurPackagePrivateExt11() { + return 0; + } + protected int refTobaseBase; + protected int refTotestOtherPackageTest; + protected int refTotestTarget11; + protected int refTotestCurPackagePrivateExt11; +} diff -r 8acb838c9b79 -r 756ae3791c45 test/tools/javac/expression/_super/NonDirectSuper/NonDirectSuper.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/tools/javac/expression/_super/NonDirectSuper/NonDirectSuper.java Tue Nov 26 15:33:12 2013 +0100 @@ -0,0 +1,179 @@ +/* + * Copyright (c) 2013, 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 8027789 + * @summary check that the direct superclass is used as the site when calling + * a superclass' method + * @compile Base.java NonDirectSuper.java + * @compile -source 1.2 -target 1.1 Target11.java + * @run main test.NonDirectSuper + */ + +package test; + +import java.io.File; + +import com.sun.tools.classfile.Attribute; +import com.sun.tools.classfile.ClassFile; +import com.sun.tools.classfile.Code_attribute; +import com.sun.tools.classfile.ConstantPool.CPRefInfo; +import com.sun.tools.classfile.Instruction; +import com.sun.tools.classfile.Method; +import com.sun.tools.classfile.Opcode; + +public class NonDirectSuper { + public static void main(String... args) { + new NonDirectSuper().run(); + } + + void run() { + String workDir = System.getProperty("test.classes"); + File testPackage = new File(workDir, "test"); + + for (File clazz : testPackage.listFiles()) { + if ("NonDirectSuper.class".equals(clazz.getName())) continue; + verifyInvokeSpecialRefToObject(clazz); + } + } + + void verifyInvokeSpecialRefToObject(File clazz) { + try { + final ClassFile cf = ClassFile.read(clazz); + for (Method m : cf.methods) { + Code_attribute codeAttr = (Code_attribute)m.attributes.get(Attribute.Code); + for (Instruction instr : codeAttr.getInstructions()) { + if (instr.getOpcode() == Opcode.INVOKESPECIAL || + instr.getOpcode() == Opcode.INVOKEVIRTUAL) { + int pc_index = instr.getShort(1); + CPRefInfo ref = (CPRefInfo)cf.constant_pool.get(pc_index); + String className = ref.getClassName(); + String methodName = ref.getNameAndTypeInfo().getName(); + if (methodName.equals("toString")) { + if (!className.equals("java/lang/Object")) + throw new IllegalStateException("Must directly refer to j.l.Object"); + } else if (methodName.startsWith("refTo")) { + String expectedClass = methodName.substring("refTo".length()); + if (!className.replace("/", "").equals(expectedClass)) { + throw new IllegalStateException("Unexpected reference to: " + + className + ", should be " + expectedClass); + } + } + } + if (instr.getOpcode() == Opcode.GETFIELD || + instr.getOpcode() == Opcode.PUTFIELD) { + int pc_index = instr.getShort(1); + CPRefInfo ref = (CPRefInfo)cf.constant_pool.get(pc_index); + String className = ref.getClassName(); + String fieldName = ref.getNameAndTypeInfo().getName(); + if (fieldName.startsWith("refTo")) { + String expectedClass = fieldName.substring("refTo".length()); + if (!className.replace("/", "").equals(expectedClass)) { + throw new IllegalStateException("Unexpected reference to: " + + className + ", should be " + expectedClass); + } + } + } + } + } + } catch (Exception e) { + e.printStackTrace(); + throw new Error("error reading " + clazz +": " + e); + } + } +} + +class OtherPackageTest extends base.Base { + void run() { + new Runnable() { + public void run() { + OtherPackageTest.super.refTobaseBase(); + OtherPackageTest.super.refTobaseBase = OtherPackageTest.super.refTobaseBase + 1; + OtherPackageTest.super.toString(); + refTotestOtherPackageTest(); + refTotestOtherPackageTest = refTotestOtherPackageTest + 1; + OtherPackageTest.this.refTotestOtherPackageTest(); + OtherPackageTest.this.refTotestOtherPackageTest = + OtherPackageTest.this.refTotestOtherPackageTest + 1; + } + }.run(); + super.refTobaseBase(); + super.refTobaseBase = super.refTobaseBase + 1; + super.toString(); + OtherPackageTest.super.refTobaseBase(); + OtherPackageTest.super.refTobaseBase = OtherPackageTest.super.refTobaseBase + 1; + OtherPackageTest.super.toString(); + refTotestOtherPackageTest(); + refTotestOtherPackageTest = refTotestOtherPackageTest + 1; + } + + static class InnerBase { + private void refTotestOtherPackageTest$InnerBase() { } + } + static class InnerTest extends InnerBase { + void run() { + new Runnable() { + public void run() { + InnerTest.super.refTotestOtherPackageTest$InnerBase(); + } + }.run(); + super.refTotestOtherPackageTest$InnerBase(); + InnerTest.super.refTotestOtherPackageTest$InnerBase(); + } + } +} + +class CurPackagePrivateBase { + void refTotestCurPackagePrivateExt() { } + void refTotestCurPackagePrivateTest() { } + int refTotestCurPackagePrivateExt; + int refTotestCurPackagePrivateTest; +} + +class CurPackagePrivateExt extends CurPackagePrivateBase { +} + +class CurPackagePrivateTest extends CurPackagePrivateExt { + void run() { + new Runnable() { + public void run() { + CurPackagePrivateTest.super.refTotestCurPackagePrivateExt(); + CurPackagePrivateTest.super.refTotestCurPackagePrivateExt = + CurPackagePrivateTest.super.refTotestCurPackagePrivateExt + 1; + CurPackagePrivateTest.this.refTotestCurPackagePrivateTest(); + CurPackagePrivateTest.this.refTotestCurPackagePrivateTest = + CurPackagePrivateTest.this.refTotestCurPackagePrivateTest + 1; + refTotestCurPackagePrivateTest(); + refTotestCurPackagePrivateTest = refTotestCurPackagePrivateTest + 1; + } + }.run(); + super.refTotestCurPackagePrivateExt(); + super.refTotestCurPackagePrivateExt = super.refTotestCurPackagePrivateExt + 1; + CurPackagePrivateTest.super.refTotestCurPackagePrivateExt(); + CurPackagePrivateTest.super.refTotestCurPackagePrivateExt = + CurPackagePrivateTest.super.refTotestCurPackagePrivateExt + 1; + refTotestCurPackagePrivateTest(); + refTotestCurPackagePrivateTest = refTotestCurPackagePrivateTest + 1; + } +} diff -r 8acb838c9b79 -r 756ae3791c45 test/tools/javac/expression/_super/NonDirectSuper/Target11.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/tools/javac/expression/_super/NonDirectSuper/Target11.java Tue Nov 26 15:33:12 2013 +0100 @@ -0,0 +1,76 @@ +/* + * Copyright (c) 2013, 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. + */ + +package test; + +class Target11 extends CurPackagePrivateExt11 { + void run() { + new Runnable() { + public void run() { + Target11.super.refTotestCurPackagePrivateBase11(); + Target11.super.refTotestCurPackagePrivateBase11 = + Target11.super.refTotestCurPackagePrivateBase11 + 1; + Target11.super.refTotestCurPackagePrivateExt11(); + Target11.super.refTotestCurPackagePrivateExt11 = + Target11.super.refTotestCurPackagePrivateExt11 + 1; + Target11.super.toString(); + refTotestCurPackagePrivateBase11(); + refTotestCurPackagePrivateBase11 = + refTotestCurPackagePrivateBase11 + 1; + refTotestTarget11(); + refTotestTarget11 = refTotestTarget11 + 1; + Target11.this.refTotestCurPackagePrivateBase11(); + Target11.this.refTotestCurPackagePrivateBase11 = + Target11.this.refTotestCurPackagePrivateBase11 + 1; + Target11.this.refTotestTarget11(); + Target11.this.refTotestTarget11 = + Target11.this.refTotestTarget11 + 1; + } + }.run(); + super.refTotestCurPackagePrivateBase11(); + super.refTotestCurPackagePrivateBase11 = + super.refTotestCurPackagePrivateBase11 + 1; + super.refTotestCurPackagePrivateExt11(); + super.refTotestCurPackagePrivateExt11 = + super.refTotestCurPackagePrivateExt11 + 1; + super.toString(); + + Target11.super.refTotestCurPackagePrivateBase11(); + Target11.super.refTotestCurPackagePrivateBase11 = + Target11.super.refTotestCurPackagePrivateBase11 + 1; + Target11.super.refTotestCurPackagePrivateExt11(); + Target11.super.refTotestCurPackagePrivateExt11 = + Target11.super.refTotestCurPackagePrivateExt11 + 1; + + refTotestCurPackagePrivateBase11(); + refTotestCurPackagePrivateBase11 = refTotestCurPackagePrivateBase11 + 1; + refTotestTarget11 = refTotestTarget11 + 1; + } +} + +class CurPackagePrivateBase11 extends base.Base { + protected void refTotestCurPackagePrivateBase11() {} + protected int refTotestCurPackagePrivateBase11; +} + +class CurPackagePrivateExt11 extends CurPackagePrivateBase11 { }