From 8d9cb2efe655cc3945b3fe51a5e7d90f48b688e6 Mon Sep 17 00:00:00 2001 From: Adam Sotona Date: Thu, 2 Dec 2021 15:29:26 +0000 Subject: [PATCH] 8278078: Cannot reference super before supertype constructor has been called Reviewed-by: mcimadamore --- .../com/sun/tools/javac/comp/Attr.java | 3 +- ...validThisAndSuperInConstructorArgTest.java | 68 ++++++++++++++++ ...nvalidThisAndSuperInConstructorArgTest.out | 14 ++++ ...ValidThisAndSuperInConstructorArgTest.java | 78 +++++++++++++++++++ 4 files changed, 162 insertions(+), 1 deletion(-) create mode 100644 test/langtools/tools/javac/8278078/InvalidThisAndSuperInConstructorArgTest.java create mode 100644 test/langtools/tools/javac/8278078/InvalidThisAndSuperInConstructorArgTest.out create mode 100644 test/langtools/tools/javac/8278078/ValidThisAndSuperInConstructorArgTest.java diff --git a/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/Attr.java b/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/Attr.java index 4b22fb1b17fda..7bd813cddb73a 100644 --- a/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/Attr.java +++ b/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/Attr.java @@ -4348,7 +4348,8 @@ public void visitSelect(JCFieldAccess tree) { if (env.info.isSelfCall && ((sym.name == names._this && site.tsym == env.enclClass.sym) || - sym.name == names._super && env.info.constructorArgs)) { + sym.name == names._super && env.info.constructorArgs && + (sitesym.isInterface() || site.tsym == env.enclClass.sym))) { chk.earlyRefError(tree.pos(), sym); } } else { diff --git a/test/langtools/tools/javac/8278078/InvalidThisAndSuperInConstructorArgTest.java b/test/langtools/tools/javac/8278078/InvalidThisAndSuperInConstructorArgTest.java new file mode 100644 index 0000000000000..eee79e2d5e989 --- /dev/null +++ b/test/langtools/tools/javac/8278078/InvalidThisAndSuperInConstructorArgTest.java @@ -0,0 +1,68 @@ + +import java.util.function.Supplier; + +/** + * @test /nodynamiccopyright/ + * @bug 8278078 + * @summary error: cannot reference super before supertype constructor has been called + * @compile/fail/ref=InvalidThisAndSuperInConstructorArgTest.out -XDrawDiagnostics InvalidThisAndSuperInConstructorArgTest.java + */ +public class InvalidThisAndSuperInConstructorArgTest { + + interface InterfaceWithDefault { + default String get() { + return ""; + } + } + + InvalidThisAndSuperInConstructorArgTest(String s) { + } + + class InnerClass extends AssertionError implements InterfaceWithDefault { + InnerClass() { + super(InnerClass.super.toString()); + } + InnerClass(int i) { + this(InnerClass.super.toString()); + } + InnerClass(boolean b) { + super(InnerClass.this.toString()); + } + InnerClass(double d) { + this(InnerClass.this.toString()); + } + InnerClass(float f) { + super(AssertionError.super.toString()); + } + InnerClass(char ch) { + this(AssertionError.super.toString()); + } + InnerClass(byte b) { + super(AssertionError.this.toString()); + } + InnerClass(Object o) { + this(AssertionError.this.toString()); + } + InnerClass(int[] ii) { + this(InterfaceWithDefault.super.get()); + } + InnerClass(boolean[] bb) { + super(InterfaceWithDefault.this.get()); + } + InnerClass(double[] dd) { + this(InterfaceWithDefault.this.get()); + } + InnerClass(float[] ff) { + super(InterfaceWithDefault.super.get()); + } + InnerClass(char[] chch) { + this(InnerClass.this::toString); + } + InnerClass(String s) { + super(s); + } + InnerClass(Supplier sup) { + super(sup); + } + } +} diff --git a/test/langtools/tools/javac/8278078/InvalidThisAndSuperInConstructorArgTest.out b/test/langtools/tools/javac/8278078/InvalidThisAndSuperInConstructorArgTest.out new file mode 100644 index 0000000000000..1109eb0fdc46b --- /dev/null +++ b/test/langtools/tools/javac/8278078/InvalidThisAndSuperInConstructorArgTest.out @@ -0,0 +1,14 @@ +InvalidThisAndSuperInConstructorArgTest.java:23:29: compiler.err.cant.ref.before.ctor.called: super +InvalidThisAndSuperInConstructorArgTest.java:26:28: compiler.err.cant.ref.before.ctor.called: super +InvalidThisAndSuperInConstructorArgTest.java:29:29: compiler.err.cant.ref.before.ctor.called: this +InvalidThisAndSuperInConstructorArgTest.java:32:28: compiler.err.cant.ref.before.ctor.called: this +InvalidThisAndSuperInConstructorArgTest.java:35:33: compiler.err.not.encl.class: java.lang.AssertionError +InvalidThisAndSuperInConstructorArgTest.java:38:32: compiler.err.not.encl.class: java.lang.AssertionError +InvalidThisAndSuperInConstructorArgTest.java:41:33: compiler.err.not.encl.class: java.lang.AssertionError +InvalidThisAndSuperInConstructorArgTest.java:44:32: compiler.err.not.encl.class: java.lang.AssertionError +InvalidThisAndSuperInConstructorArgTest.java:47:38: compiler.err.cant.ref.before.ctor.called: super +InvalidThisAndSuperInConstructorArgTest.java:50:39: compiler.err.not.encl.class: InvalidThisAndSuperInConstructorArgTest.InterfaceWithDefault +InvalidThisAndSuperInConstructorArgTest.java:53:38: compiler.err.not.encl.class: InvalidThisAndSuperInConstructorArgTest.InterfaceWithDefault +InvalidThisAndSuperInConstructorArgTest.java:56:39: compiler.err.cant.ref.before.ctor.called: super +InvalidThisAndSuperInConstructorArgTest.java:59:28: compiler.err.cant.ref.before.ctor.called: this +13 errors diff --git a/test/langtools/tools/javac/8278078/ValidThisAndSuperInConstructorArgTest.java b/test/langtools/tools/javac/8278078/ValidThisAndSuperInConstructorArgTest.java new file mode 100644 index 0000000000000..2fe1388420c26 --- /dev/null +++ b/test/langtools/tools/javac/8278078/ValidThisAndSuperInConstructorArgTest.java @@ -0,0 +1,78 @@ +/* + * Copyright (c) 2021, 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 8278078 + * @summary error: cannot reference super before supertype constructor has been called + * @compile ValidThisAndSuperInConstructorArgTest.java + * @run main ValidThisAndSuperInConstructorArgTest + */ +public class ValidThisAndSuperInConstructorArgTest { + + static final String SUPER = "unexpected super call"; + static final String THIS = "unexpected this call"; + + public String get() { + return SUPER; + } + + static class StaticSubClass extends ValidThisAndSuperInConstructorArgTest { + @Override + public String get() { + return THIS; + } + + class InnerClass extends AssertionError { + InnerClass() { + super(StaticSubClass.super.get()); + } + InnerClass(int i) { + this(StaticSubClass.super.get()); + } + InnerClass(boolean b) { + super(StaticSubClass.this.get()); + } + InnerClass(double d) { + this(StaticSubClass.this.get()); + } + InnerClass(String s) { + super(s); + } + void assertThis() { + if (!THIS.equals(getMessage())) throw this; + } + void assertSuper() { + if (!SUPER.equals(getMessage())) throw this; + } + } + } + + public static void main(String...args) { + var test = new StaticSubClass(); + test.new InnerClass().assertSuper(); + test.new InnerClass(1).assertSuper(); + test.new InnerClass(true).assertThis(); + test.new InnerClass(1.0).assertThis(); + } +}