From e227c7e37d4de0656f013f3a936b1acfa56cc2e0 Mon Sep 17 00:00:00 2001 From: Archie Cobbs Date: Tue, 18 Jun 2024 23:23:39 +0000 Subject: [PATCH] 8334258: Compiler erronousely allows access to instance variable in argument expression of a constructor invocation Reviewed-by: mcimadamore --- .../com/sun/tools/javac/comp/Resolve.java | 23 +++++++++++-------- .../SuperInit/EarlyAssignmentNoPreview1.java | 21 +++++++++++++++++ .../SuperInit/EarlyAssignmentNoPreview1.out | 2 ++ .../SuperInit/EarlyAssignmentNoPreview2.java | 21 +++++++++++++++++ .../SuperInit/EarlyAssignmentNoPreview2.out | 2 ++ .../SuperInit/EarlyAssignmentNoPreview3.java | 21 +++++++++++++++++ .../SuperInit/EarlyAssignmentNoPreview3.out | 2 ++ 7 files changed, 83 insertions(+), 9 deletions(-) create mode 100644 test/langtools/tools/javac/SuperInit/EarlyAssignmentNoPreview1.java create mode 100644 test/langtools/tools/javac/SuperInit/EarlyAssignmentNoPreview1.out create mode 100644 test/langtools/tools/javac/SuperInit/EarlyAssignmentNoPreview2.java create mode 100644 test/langtools/tools/javac/SuperInit/EarlyAssignmentNoPreview2.out create mode 100644 test/langtools/tools/javac/SuperInit/EarlyAssignmentNoPreview3.java create mode 100644 test/langtools/tools/javac/SuperInit/EarlyAssignmentNoPreview3.out diff --git a/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/Resolve.java b/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/Resolve.java index 3dcac0b2646..079a0bc5c6a 100644 --- a/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/Resolve.java +++ b/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/Resolve.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 1999, 2023, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1999, 2024, 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 @@ -100,6 +100,7 @@ public class Resolve { DeferredAttr deferredAttr; Check chk; Infer infer; + Preview preview; ClassFinder finder; ModuleFinder moduleFinder; Types types; @@ -135,7 +136,7 @@ public class Resolve { moduleFinder = ModuleFinder.instance(context); types = Types.instance(context); diags = JCDiagnostic.Factory.instance(context); - Preview preview = Preview.instance(context); + preview = Preview.instance(context); Source source = Source.instance(context); Options options = Options.instance(context); compactMethodDiags = options.isSet(Option.XDIAGS, "compact") || @@ -1480,10 +1481,11 @@ public class Resolve { /** Find unqualified variable or field with given name. * Synthetic fields always skipped. + * @param pos The position to use for error reporting. * @param env The current environment. * @param name The name of the variable or field. */ - Symbol findVar(Env env, Name name) { + Symbol findVar(DiagnosticPosition pos, Env env, Name name) { Symbol bestSoFar = varNotFound; Env env1 = env; boolean staticOnly = false; @@ -1508,7 +1510,7 @@ public class Resolve { (sym.flags() & STATIC) == 0) { if (staticOnly) return new StaticError(sym); - if (env1.info.ctorPrologue && !isAllowedEarlyReference(env1, (VarSymbol)sym)) + if (env1.info.ctorPrologue && !isAllowedEarlyReference(pos, env1, (VarSymbol)sym)) return new RefBeforeCtorCalledError(sym); } return sym; @@ -2421,15 +2423,15 @@ public class Resolve { * (a subset of VAL, TYP, PCK). */ Symbol findIdent(DiagnosticPosition pos, Env env, Name name, KindSelector kind) { - return checkNonExistentType(checkRestrictedType(pos, findIdentInternal(env, name, kind), name)); + return checkNonExistentType(checkRestrictedType(pos, findIdentInternal(pos, env, name, kind), name)); } - Symbol findIdentInternal(Env env, Name name, KindSelector kind) { + Symbol findIdentInternal(DiagnosticPosition pos, Env env, Name name, KindSelector kind) { Symbol bestSoFar = typeNotFound; Symbol sym; if (kind.contains(KindSelector.VAL)) { - sym = findVar(env, name); + sym = findVar(pos, env, name); if (sym.exists()) return sym; else bestSoFar = bestOf(bestSoFar, sym); } @@ -3776,7 +3778,7 @@ public class Resolve { if (sym != null) { if (staticOnly) sym = new StaticError(sym); - else if (env1.info.ctorPrologue && !isAllowedEarlyReference(env1, (VarSymbol)sym)) + else if (env1.info.ctorPrologue && !isAllowedEarlyReference(pos, env1, (VarSymbol)sym)) sym = new RefBeforeCtorCalledError(sym); return accessBase(sym, pos, env.enclClass.sym.type, name, true); @@ -3845,7 +3847,7 @@ public class Resolve { * We also don't verify that the field has no initializer, which is required. * To catch those cases, we rely on similar logic in Attr.checkAssignable(). */ - private boolean isAllowedEarlyReference(Env env, VarSymbol v) { + private boolean isAllowedEarlyReference(DiagnosticPosition pos, Env env, VarSymbol v) { // Check assumptions Assert.check(env.info.ctorPrologue); @@ -3880,6 +3882,9 @@ public class Resolve { if (isEarlyReference(env, base, v) && v.owner != env.enclClass.sym) return false; + // The flexible constructors feature must be enabled + preview.checkSourceLevel(pos, Feature.FLEXIBLE_CONSTRUCTORS); + // OK return true; } diff --git a/test/langtools/tools/javac/SuperInit/EarlyAssignmentNoPreview1.java b/test/langtools/tools/javac/SuperInit/EarlyAssignmentNoPreview1.java new file mode 100644 index 00000000000..abb6bacbc8f --- /dev/null +++ b/test/langtools/tools/javac/SuperInit/EarlyAssignmentNoPreview1.java @@ -0,0 +1,21 @@ +/* + * @test /nodynamiccopyright/ + * @bug 8334258 + * @summary Disallow early assignment if FLEXIBLE_CONSTRUCTORS preview feature is not enabled + * @compile/fail/ref=EarlyAssignmentNoPreview1.out -XDrawDiagnostics EarlyAssignmentNoPreview1.java + */ +public class EarlyAssignmentNoPreview1 { + + Runnable r; + + public EarlyAssignmentNoPreview1() { + this(r = () -> System.out.println("hello")); + } + + public EarlyAssignmentNoPreview1(Runnable r) { + } + + public static void main(String[] args) { + new EarlyAssignmentNoPreview1(); + } +} diff --git a/test/langtools/tools/javac/SuperInit/EarlyAssignmentNoPreview1.out b/test/langtools/tools/javac/SuperInit/EarlyAssignmentNoPreview1.out new file mode 100644 index 00000000000..6c5afbbd12b --- /dev/null +++ b/test/langtools/tools/javac/SuperInit/EarlyAssignmentNoPreview1.out @@ -0,0 +1,2 @@ +EarlyAssignmentNoPreview1.java:12:14: compiler.err.preview.feature.disabled: (compiler.misc.feature.flexible.constructors) +1 error diff --git a/test/langtools/tools/javac/SuperInit/EarlyAssignmentNoPreview2.java b/test/langtools/tools/javac/SuperInit/EarlyAssignmentNoPreview2.java new file mode 100644 index 00000000000..3c33734f42a --- /dev/null +++ b/test/langtools/tools/javac/SuperInit/EarlyAssignmentNoPreview2.java @@ -0,0 +1,21 @@ +/* + * @test /nodynamiccopyright/ + * @bug 8334258 + * @summary Disallow early assignment if FLEXIBLE_CONSTRUCTORS preview feature is not enabled + * @compile/fail/ref=EarlyAssignmentNoPreview2.out -XDrawDiagnostics EarlyAssignmentNoPreview2.java + */ +public class EarlyAssignmentNoPreview2 { + + Runnable r; + + public EarlyAssignmentNoPreview2() { + this(this.r = () -> System.out.println("hello")); + } + + public EarlyAssignmentNoPreview2(Runnable r) { + } + + public static void main(String[] args) { + new EarlyAssignmentNoPreview2(); + } +} diff --git a/test/langtools/tools/javac/SuperInit/EarlyAssignmentNoPreview2.out b/test/langtools/tools/javac/SuperInit/EarlyAssignmentNoPreview2.out new file mode 100644 index 00000000000..38fb885684e --- /dev/null +++ b/test/langtools/tools/javac/SuperInit/EarlyAssignmentNoPreview2.out @@ -0,0 +1,2 @@ +EarlyAssignmentNoPreview2.java:12:14: compiler.err.preview.feature.disabled: (compiler.misc.feature.flexible.constructors) +1 error diff --git a/test/langtools/tools/javac/SuperInit/EarlyAssignmentNoPreview3.java b/test/langtools/tools/javac/SuperInit/EarlyAssignmentNoPreview3.java new file mode 100644 index 00000000000..f6269f2cb1f --- /dev/null +++ b/test/langtools/tools/javac/SuperInit/EarlyAssignmentNoPreview3.java @@ -0,0 +1,21 @@ +/* + * @test /nodynamiccopyright/ + * @bug 8334258 + * @summary Disallow early assignment if FLEXIBLE_CONSTRUCTORS preview feature is not enabled + * @compile/fail/ref=EarlyAssignmentNoPreview3.out -XDrawDiagnostics EarlyAssignmentNoPreview3.java + */ +public class EarlyAssignmentNoPreview3 { + + Runnable r; + + public EarlyAssignmentNoPreview3() { + this(EarlyAssignmentNoPreview3.this.r = () -> System.out.println("hello")); + } + + public EarlyAssignmentNoPreview3(Runnable r) { + } + + public static void main(String[] args) { + new EarlyAssignmentNoPreview3(); + } +} diff --git a/test/langtools/tools/javac/SuperInit/EarlyAssignmentNoPreview3.out b/test/langtools/tools/javac/SuperInit/EarlyAssignmentNoPreview3.out new file mode 100644 index 00000000000..def9f4f3722 --- /dev/null +++ b/test/langtools/tools/javac/SuperInit/EarlyAssignmentNoPreview3.out @@ -0,0 +1,2 @@ +EarlyAssignmentNoPreview3.java:12:39: compiler.err.preview.feature.disabled: (compiler.misc.feature.flexible.constructors) +1 error