8334258: Compiler erronousely allows access to instance variable in argument expression of a constructor invocation
Reviewed-by: mcimadamore
This commit is contained in:
parent
2ce85d9635
commit
e227c7e37d
@ -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.
|
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||||
*
|
*
|
||||||
* This code is free software; you can redistribute it and/or modify it
|
* This code is free software; you can redistribute it and/or modify it
|
||||||
@ -100,6 +100,7 @@ public class Resolve {
|
|||||||
DeferredAttr deferredAttr;
|
DeferredAttr deferredAttr;
|
||||||
Check chk;
|
Check chk;
|
||||||
Infer infer;
|
Infer infer;
|
||||||
|
Preview preview;
|
||||||
ClassFinder finder;
|
ClassFinder finder;
|
||||||
ModuleFinder moduleFinder;
|
ModuleFinder moduleFinder;
|
||||||
Types types;
|
Types types;
|
||||||
@ -135,7 +136,7 @@ public class Resolve {
|
|||||||
moduleFinder = ModuleFinder.instance(context);
|
moduleFinder = ModuleFinder.instance(context);
|
||||||
types = Types.instance(context);
|
types = Types.instance(context);
|
||||||
diags = JCDiagnostic.Factory.instance(context);
|
diags = JCDiagnostic.Factory.instance(context);
|
||||||
Preview preview = Preview.instance(context);
|
preview = Preview.instance(context);
|
||||||
Source source = Source.instance(context);
|
Source source = Source.instance(context);
|
||||||
Options options = Options.instance(context);
|
Options options = Options.instance(context);
|
||||||
compactMethodDiags = options.isSet(Option.XDIAGS, "compact") ||
|
compactMethodDiags = options.isSet(Option.XDIAGS, "compact") ||
|
||||||
@ -1480,10 +1481,11 @@ public class Resolve {
|
|||||||
|
|
||||||
/** Find unqualified variable or field with given name.
|
/** Find unqualified variable or field with given name.
|
||||||
* Synthetic fields always skipped.
|
* Synthetic fields always skipped.
|
||||||
|
* @param pos The position to use for error reporting.
|
||||||
* @param env The current environment.
|
* @param env The current environment.
|
||||||
* @param name The name of the variable or field.
|
* @param name The name of the variable or field.
|
||||||
*/
|
*/
|
||||||
Symbol findVar(Env<AttrContext> env, Name name) {
|
Symbol findVar(DiagnosticPosition pos, Env<AttrContext> env, Name name) {
|
||||||
Symbol bestSoFar = varNotFound;
|
Symbol bestSoFar = varNotFound;
|
||||||
Env<AttrContext> env1 = env;
|
Env<AttrContext> env1 = env;
|
||||||
boolean staticOnly = false;
|
boolean staticOnly = false;
|
||||||
@ -1508,7 +1510,7 @@ public class Resolve {
|
|||||||
(sym.flags() & STATIC) == 0) {
|
(sym.flags() & STATIC) == 0) {
|
||||||
if (staticOnly)
|
if (staticOnly)
|
||||||
return new StaticError(sym);
|
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 new RefBeforeCtorCalledError(sym);
|
||||||
}
|
}
|
||||||
return sym;
|
return sym;
|
||||||
@ -2421,15 +2423,15 @@ public class Resolve {
|
|||||||
* (a subset of VAL, TYP, PCK).
|
* (a subset of VAL, TYP, PCK).
|
||||||
*/
|
*/
|
||||||
Symbol findIdent(DiagnosticPosition pos, Env<AttrContext> env, Name name, KindSelector kind) {
|
Symbol findIdent(DiagnosticPosition pos, Env<AttrContext> 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<AttrContext> env, Name name, KindSelector kind) {
|
Symbol findIdentInternal(DiagnosticPosition pos, Env<AttrContext> env, Name name, KindSelector kind) {
|
||||||
Symbol bestSoFar = typeNotFound;
|
Symbol bestSoFar = typeNotFound;
|
||||||
Symbol sym;
|
Symbol sym;
|
||||||
|
|
||||||
if (kind.contains(KindSelector.VAL)) {
|
if (kind.contains(KindSelector.VAL)) {
|
||||||
sym = findVar(env, name);
|
sym = findVar(pos, env, name);
|
||||||
if (sym.exists()) return sym;
|
if (sym.exists()) return sym;
|
||||||
else bestSoFar = bestOf(bestSoFar, sym);
|
else bestSoFar = bestOf(bestSoFar, sym);
|
||||||
}
|
}
|
||||||
@ -3776,7 +3778,7 @@ public class Resolve {
|
|||||||
if (sym != null) {
|
if (sym != null) {
|
||||||
if (staticOnly)
|
if (staticOnly)
|
||||||
sym = new StaticError(sym);
|
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);
|
sym = new RefBeforeCtorCalledError(sym);
|
||||||
return accessBase(sym, pos, env.enclClass.sym.type,
|
return accessBase(sym, pos, env.enclClass.sym.type,
|
||||||
name, true);
|
name, true);
|
||||||
@ -3845,7 +3847,7 @@ public class Resolve {
|
|||||||
* We also don't verify that the field has no initializer, which is required.
|
* 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().
|
* To catch those cases, we rely on similar logic in Attr.checkAssignable().
|
||||||
*/
|
*/
|
||||||
private boolean isAllowedEarlyReference(Env<AttrContext> env, VarSymbol v) {
|
private boolean isAllowedEarlyReference(DiagnosticPosition pos, Env<AttrContext> env, VarSymbol v) {
|
||||||
|
|
||||||
// Check assumptions
|
// Check assumptions
|
||||||
Assert.check(env.info.ctorPrologue);
|
Assert.check(env.info.ctorPrologue);
|
||||||
@ -3880,6 +3882,9 @@ public class Resolve {
|
|||||||
if (isEarlyReference(env, base, v) && v.owner != env.enclClass.sym)
|
if (isEarlyReference(env, base, v) && v.owner != env.enclClass.sym)
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
|
// The flexible constructors feature must be enabled
|
||||||
|
preview.checkSourceLevel(pos, Feature.FLEXIBLE_CONSTRUCTORS);
|
||||||
|
|
||||||
// OK
|
// OK
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
@ -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();
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,2 @@
|
|||||||
|
EarlyAssignmentNoPreview1.java:12:14: compiler.err.preview.feature.disabled: (compiler.misc.feature.flexible.constructors)
|
||||||
|
1 error
|
@ -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();
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,2 @@
|
|||||||
|
EarlyAssignmentNoPreview2.java:12:14: compiler.err.preview.feature.disabled: (compiler.misc.feature.flexible.constructors)
|
||||||
|
1 error
|
@ -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();
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,2 @@
|
|||||||
|
EarlyAssignmentNoPreview3.java:12:39: compiler.err.preview.feature.disabled: (compiler.misc.feature.flexible.constructors)
|
||||||
|
1 error
|
Loading…
Reference in New Issue
Block a user