From e73c8d8a01a34e12711ed6d0514474bfbe28345f Mon Sep 17 00:00:00 2001 From: Vicente Romero Date: Fri, 7 Nov 2025 12:05:40 -0500 Subject: [PATCH 1/5] 8371382: [lworld] Javac accepts field initializer that refers to a superclass field --- .../classes/com/sun/tools/javac/comp/Attr.java | 14 +++++++------- .../javac/SuperInit/ValueClassSuperInitFails.java | 5 ++++- .../javac/SuperInit/ValueClassSuperInitFails.out | 3 ++- 3 files changed, 13 insertions(+), 9 deletions(-) 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 4840750a40d..a94dab7255c 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 @@ -1642,13 +1642,13 @@ public void visitVarDef(JCVariableDecl tree) { chk.checkDeprecatedAnnotation(tree.pos(), v); if (tree.init != null) { + Env initEnv = memberEnter.initEnv(tree, env); if ((v.flags_field & FINAL) == 0 || !memberEnter.needsLazyConstValue(tree.init)) { // Not a compile-time constant // Attribute initializer in a new environment // with the declared variable as owner. // Check that initializer conforms to variable's declared type. - Env initEnv = memberEnter.initEnv(tree, env); initEnv.info.lint = lint; // In order to catch self-references, we set the variable's // declaration position to maximal possible value, effectively @@ -1665,16 +1665,16 @@ public void visitVarDef(JCVariableDecl tree) { //fixup local variable type v.type = chk.checkLocalVarType(tree, tree.init.type, tree.name); } - if (allowValueClasses && v.owner.kind == TYP && !v.isStatic()) { - // strict field initializers are inlined in constructor's prologues - CtorPrologueVisitor ctorPrologueVisitor = new CtorPrologueVisitor(initEnv, - !v.isStrict() ? PrologueVisitorMode.WARNINGS_ONLY : PrologueVisitorMode.SUPER_CONSTRUCTOR); - ctorPrologueVisitor.scan(tree.init); - } } finally { initEnv.info.ctorPrologue = previousCtorPrologue; } } + if (allowValueClasses && v.owner.kind == TYP && !v.isStatic()) { + // strict field initializers are inlined in constructor's prologues + CtorPrologueVisitor ctorPrologueVisitor = new CtorPrologueVisitor(initEnv, + !v.isStrict() ? PrologueVisitorMode.WARNINGS_ONLY : PrologueVisitorMode.SUPER_CONSTRUCTOR); + ctorPrologueVisitor.scan(tree.init); + } if (tree.isImplicitlyTyped()) { setSyntheticVariableType(tree, v.type); } diff --git a/test/langtools/tools/javac/SuperInit/ValueClassSuperInitFails.java b/test/langtools/tools/javac/SuperInit/ValueClassSuperInitFails.java index 6c4a1de0818..d83a82855d1 100644 --- a/test/langtools/tools/javac/SuperInit/ValueClassSuperInitFails.java +++ b/test/langtools/tools/javac/SuperInit/ValueClassSuperInitFails.java @@ -7,9 +7,9 @@ */ import java.util.function.Function; abstract value class AR implements java.io.Serializable { + int b = 5; public AR(V initialValue) { } - public AR() { } } @@ -178,4 +178,7 @@ public ValueClassSuperInitFails(int[][] z) { public ValueClassSuperInitFails(long[][] z) { super(new Inner1()); // this should FAIL } + + // this should FAIL + int a = b; } diff --git a/test/langtools/tools/javac/SuperInit/ValueClassSuperInitFails.out b/test/langtools/tools/javac/SuperInit/ValueClassSuperInitFails.out index 9ce5ced7c4d..95dc5d0910d 100644 --- a/test/langtools/tools/javac/SuperInit/ValueClassSuperInitFails.out +++ b/test/langtools/tools/javac/SuperInit/ValueClassSuperInitFails.out @@ -14,6 +14,7 @@ ValueClassSuperInitFails.java:148:9: compiler.err.non.canonical.constructor.invo ValueClassSuperInitFails.java:161:46: compiler.err.cant.ref.before.ctor.called: hashCode() ValueClassSuperInitFails.java:175:49: compiler.err.cant.ref.before.ctor.called: x ValueClassSuperInitFails.java:179:15: compiler.err.cant.ref.before.ctor.called: ValueClassSuperInitFails +ValueClassSuperInitFails.java:183:13: compiler.err.cant.ref.before.ctor.called: b ValueClassSuperInitFails.java:43:13: compiler.err.call.must.only.appear.in.ctor ValueClassSuperInitFails.java:47:14: compiler.err.call.must.only.appear.in.ctor ValueClassSuperInitFails.java:51:14: compiler.err.call.must.only.appear.in.ctor @@ -25,4 +26,4 @@ ValueClassSuperInitFails.java:99:13: compiler.err.return.before.superclass.initi ValueClassSuperInitFails.java:170:18: compiler.err.call.must.only.appear.in.ctor - compiler.note.preview.filename: ValueClassSuperInitFails.java, DEFAULT - compiler.note.preview.recompile -25 errors +26 errors From e0aa3646ebd0ea02d3623871f44e43c701f3ee88 Mon Sep 17 00:00:00 2001 From: Vicente Romero Date: Fri, 7 Nov 2025 14:15:32 -0500 Subject: [PATCH 2/5] additional test --- .../tools/javac/SuperInit/ValueClassSuperInitFails.java | 3 ++- .../tools/javac/SuperInit/ValueClassSuperInitFails.out | 3 ++- 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/test/langtools/tools/javac/SuperInit/ValueClassSuperInitFails.java b/test/langtools/tools/javac/SuperInit/ValueClassSuperInitFails.java index d83a82855d1..e896aa97791 100644 --- a/test/langtools/tools/javac/SuperInit/ValueClassSuperInitFails.java +++ b/test/langtools/tools/javac/SuperInit/ValueClassSuperInitFails.java @@ -179,6 +179,7 @@ public ValueClassSuperInitFails(long[][] z) { super(new Inner1()); // this should FAIL } - // this should FAIL + // these two should FAIL int a = b; + int aa = super.b; } diff --git a/test/langtools/tools/javac/SuperInit/ValueClassSuperInitFails.out b/test/langtools/tools/javac/SuperInit/ValueClassSuperInitFails.out index 95dc5d0910d..8698f62a505 100644 --- a/test/langtools/tools/javac/SuperInit/ValueClassSuperInitFails.out +++ b/test/langtools/tools/javac/SuperInit/ValueClassSuperInitFails.out @@ -15,6 +15,7 @@ ValueClassSuperInitFails.java:161:46: compiler.err.cant.ref.before.ctor.called: ValueClassSuperInitFails.java:175:49: compiler.err.cant.ref.before.ctor.called: x ValueClassSuperInitFails.java:179:15: compiler.err.cant.ref.before.ctor.called: ValueClassSuperInitFails ValueClassSuperInitFails.java:183:13: compiler.err.cant.ref.before.ctor.called: b +ValueClassSuperInitFails.java:184:19: compiler.err.cant.ref.before.ctor.called: b ValueClassSuperInitFails.java:43:13: compiler.err.call.must.only.appear.in.ctor ValueClassSuperInitFails.java:47:14: compiler.err.call.must.only.appear.in.ctor ValueClassSuperInitFails.java:51:14: compiler.err.call.must.only.appear.in.ctor @@ -26,4 +27,4 @@ ValueClassSuperInitFails.java:99:13: compiler.err.return.before.superclass.initi ValueClassSuperInitFails.java:170:18: compiler.err.call.must.only.appear.in.ctor - compiler.note.preview.filename: ValueClassSuperInitFails.java, DEFAULT - compiler.note.preview.recompile -26 errors +27 errors From 9ba227c596707271570334cf78860c158962d6dc Mon Sep 17 00:00:00 2001 From: Vicente Romero Date: Fri, 14 Nov 2025 19:31:37 -0500 Subject: [PATCH 3/5] fixing bug --- .../classes/com/sun/tools/javac/comp/Attr.java | 14 ++++++++++---- 1 file changed, 10 insertions(+), 4 deletions(-) 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 a94dab7255c..1092d1dc9fc 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 @@ -1258,7 +1258,8 @@ public void visitMethodDef(JCMethodDecl tree) { PrologueVisitorMode.WARNINGS_ONLY : thisInvocation ? PrologueVisitorMode.THIS_CONSTRUCTOR : - PrologueVisitorMode.SUPER_CONSTRUCTOR); + PrologueVisitorMode.SUPER_CONSTRUCTOR, + false); ctorPrologueVisitor.scan(prologueCode.toList()); } } @@ -1282,11 +1283,13 @@ enum PrologueVisitorMode { class CtorPrologueVisitor extends TreeScanner { Env localEnv; PrologueVisitorMode mode; + boolean isInitializer; - CtorPrologueVisitor(Env localEnv, PrologueVisitorMode mode) { + CtorPrologueVisitor(Env localEnv, PrologueVisitorMode mode, boolean isInitializer) { this.localEnv = localEnv; currentClassSym = localEnv.enclClass.sym; this.mode = mode; + this.isInitializer = isInitializer; } boolean insideLambdaOrClassDef = false; @@ -1515,7 +1518,9 @@ void analyzeSymbol(JCTree tree) { * not allowed in the prologue */ if (insideLambdaOrClassDef || - (!localEnv.enclClass.sym.isValueClass() && (sym.flags_field & HASINIT) != 0)) + (!localEnv.enclClass.sym.isValueClass() && + (sym.flags_field & HASINIT) != 0 && + !isInitializer)) reportPrologueError(tree, sym); // we will need to generate a proxy for this field later on if (!isInLHS) { @@ -1672,7 +1677,8 @@ public void visitVarDef(JCVariableDecl tree) { if (allowValueClasses && v.owner.kind == TYP && !v.isStatic()) { // strict field initializers are inlined in constructor's prologues CtorPrologueVisitor ctorPrologueVisitor = new CtorPrologueVisitor(initEnv, - !v.isStrict() ? PrologueVisitorMode.WARNINGS_ONLY : PrologueVisitorMode.SUPER_CONSTRUCTOR); + !v.isStrict() ? PrologueVisitorMode.WARNINGS_ONLY : PrologueVisitorMode.SUPER_CONSTRUCTOR, + true); ctorPrologueVisitor.scan(tree.init); } if (tree.isImplicitlyTyped()) { From 65b1b12e8a280a3a57c6ed49a2008bf8feade0f1 Mon Sep 17 00:00:00 2001 From: Vicente Romero Date: Sat, 15 Nov 2025 09:21:48 -0500 Subject: [PATCH 4/5] adding test --- test/langtools/tools/javac/SuperInit/EarlyAssignments.java | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/test/langtools/tools/javac/SuperInit/EarlyAssignments.java b/test/langtools/tools/javac/SuperInit/EarlyAssignments.java index fdc9eb27d60..07ebf888a79 100644 --- a/test/langtools/tools/javac/SuperInit/EarlyAssignments.java +++ b/test/langtools/tools/javac/SuperInit/EarlyAssignments.java @@ -180,4 +180,9 @@ public static class Inner9 { super(); } } + + public static class Inner10 { + int x = 1; + int y = x + 1; // no warning expected here + } } From c9a1fee0510ddde8a22fd3d091309c60f9c80e60 Mon Sep 17 00:00:00 2001 From: Vicente Romero Date: Sat, 15 Nov 2025 09:33:28 -0500 Subject: [PATCH 5/5] adding some documentation --- .../share/classes/com/sun/tools/javac/comp/Attr.java | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) 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 1092d1dc9fc..fdb9753c14f 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 @@ -1515,7 +1515,9 @@ void analyzeSymbol(JCTree tree) { } else if (isEarlyReference(localEnv, tree, sym)) { /* now this is a `proper` instance field of the current class * references to fields of identity classes which happen to have initializers are - * not allowed in the prologue + * not allowed in the prologue. + * But it is OK for a field with initializer to refer to another field with initializer, + * so no warning or error if we are analyzing a field initializer. */ if (insideLambdaOrClassDef || (!localEnv.enclClass.sym.isValueClass() &&