Skip to content

Commit 5b9932f

Browse files
committed
8338288: Compiler Implementation for Flexible Constructor Bodies (Third Preview)
8322882: Null pointer error when compiling Static initializer in a local class 8334248: Invalid error for early construction local class constructor method reference 8330037: Compiler produces invalid bytecode for method class creation from static method Reviewed-by: jlahoda, vromero
1 parent 0c191f6 commit 5b9932f

18 files changed

+393
-133
lines changed

src/jdk.compiler/share/classes/com/sun/tools/javac/code/Kinds.java

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -70,7 +70,6 @@ public enum Kind {
7070
AMBIGUOUS(Category.RESOLUTION_TARGET), // overloaded target
7171
HIDDEN(Category.RESOLUTION_TARGET), // not overloaded non-target
7272
STATICERR(Category.RESOLUTION_TARGET), // overloaded? target
73-
MISSING_ENCL(Category.RESOLUTION), // not overloaded non-target
7473
BAD_RESTRICTED_TYPE(Category.RESOLUTION), // not overloaded non-target
7574
ABSENT_VAR(Category.RESOLUTION_TARGET, KindName.VAR), // not overloaded non-target
7675
WRONG_MTHS(Category.RESOLUTION_TARGET, KindName.METHOD), // overloaded target

src/jdk.compiler/share/classes/com/sun/tools/javac/comp/Attr.java

Lines changed: 22 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -2590,8 +2590,7 @@ public void visitApply(JCMethodInvocation tree) {
25902590
} else if (methName == names._super) {
25912591
// qualifier omitted; check for existence
25922592
// of an appropriate implicit qualifier.
2593-
rs.resolveImplicitThis(tree.meth.pos(),
2594-
localEnv, site, true);
2593+
checkNewInnerClass(tree.meth.pos(), localEnv, site, true);
25952594
}
25962595
} else if (tree.meth.hasTag(SELECT)) {
25972596
log.error(tree.meth.pos(),
@@ -2798,11 +2797,9 @@ public void visitNewClass(final JCNewClass tree) {
27982797
log.error(tree.encl.pos(), Errors.QualifiedNewOfStaticClass(clazztype.tsym));
27992798
}
28002799
}
2801-
} else if (!clazztype.tsym.isInterface() &&
2802-
(clazztype.tsym.flags_field & NOOUTERTHIS) == 0 &&
2803-
clazztype.getEnclosingType().hasTag(CLASS)) {
2800+
} else {
28042801
// Check for the existence of an apropos outer instance
2805-
rs.resolveImplicitThis(tree.pos(), env, clazztype);
2802+
checkNewInnerClass(tree.pos(), env, clazztype, false);
28062803
}
28072804

28082805
// Attribute constructor arguments.
@@ -3067,6 +3064,24 @@ public void report(DiagnosticPosition _unused, JCDiagnostic details) {
30673064
};
30683065
}
30693066

3067+
void checkNewInnerClass(DiagnosticPosition pos, Env<AttrContext> env, Type type, boolean isSuper) {
3068+
boolean isLocal = type.tsym.owner.kind == MTH;
3069+
if ((type.tsym.flags() & (INTERFACE | ENUM | RECORD)) != 0 ||
3070+
(!isLocal && !type.tsym.isInner()) ||
3071+
(isSuper && env.enclClass.sym.isAnonymous())) {
3072+
// nothing to check
3073+
return;
3074+
}
3075+
Symbol res = isLocal ?
3076+
rs.findLocalClassOwner(env, type.tsym) :
3077+
rs.findSelfContaining(pos, env, type.getEnclosingType().tsym, isSuper);
3078+
if (res.exists()) {
3079+
rs.accessBase(res, pos, env.enclClass.sym.type, names._this, true);
3080+
} else {
3081+
log.error(pos, Errors.EnclClassRequired(type.tsym));
3082+
}
3083+
}
3084+
30703085
/** Make an attributed null check tree.
30713086
*/
30723087
public JCExpression makeNullCheck(JCExpression arg) {
@@ -3639,7 +3654,6 @@ public void visitReference(final JCMemberReference that) {
36393654
boolean targetError;
36403655
switch (refSym.kind) {
36413656
case ABSENT_MTH:
3642-
case MISSING_ENCL:
36433657
targetError = false;
36443658
break;
36453659
case WRONG_MTH:
@@ -3690,11 +3704,7 @@ public void visitReference(final JCMemberReference that) {
36903704
}
36913705

36923706
if (!env.info.attributionMode.isSpeculative && that.getMode() == JCMemberReference.ReferenceMode.NEW) {
3693-
Type enclosingType = exprType.getEnclosingType();
3694-
if (enclosingType != null && enclosingType.hasTag(CLASS)) {
3695-
// Check for the existence of an appropriate outer instance
3696-
rs.resolveImplicitThis(that.pos(), env, exprType);
3697-
}
3707+
checkNewInnerClass(that.pos(), env, exprType, false);
36983708
}
36993709

37003710
if (resultInfo.checkContext.deferredAttrContext().mode == AttrMode.CHECK) {

src/jdk.compiler/share/classes/com/sun/tools/javac/comp/Resolve.java

Lines changed: 85 additions & 94 deletions
Original file line numberDiff line numberDiff line change
@@ -3744,11 +3744,10 @@ class ConstructorReferenceLookupHelper extends ReferenceLookupHelper {
37443744

37453745
@Override
37463746
protected Symbol lookup(Env<AttrContext> env, MethodResolutionPhase phase) {
3747-
Symbol sym = needsInference ?
3747+
return needsInference ?
37483748
findDiamond(env, site, argtypes, typeargtypes, phase.isBoxingRequired(), phase.isVarargsRequired()) :
37493749
findMethod(env, site, name, argtypes, typeargtypes,
37503750
phase.isBoxingRequired(), phase.isVarargsRequired());
3751-
return enclosingInstanceMissing(env, site) ? new BadConstructorReferenceError(sym) : sym;
37523751
}
37533752

37543753
@Override
@@ -3793,6 +3792,63 @@ Symbol lookupMethod(Env<AttrContext> env, DiagnosticPosition pos, Symbol locatio
37933792
}
37943793
}
37953794

3795+
/**
3796+
* Find a "valid" reference to an enclosing 'A.this' such that A is a subclass of the provided class symbol.
3797+
* A reference to an enclosing 'A.this' is "valid" if (a) we're not in the early-construction context for A
3798+
* and (b) if the current class is not an inner class of A.
3799+
*/
3800+
Symbol findSelfContaining(DiagnosticPosition pos,
3801+
Env<AttrContext> env,
3802+
TypeSymbol c,
3803+
boolean isSuper) {
3804+
Env<AttrContext> env1 = isSuper ? env.outer : env;
3805+
boolean staticOnly = false;
3806+
while (env1.outer != null) {
3807+
if (isStatic(env1)) staticOnly = true;
3808+
if (env1.enclClass.sym.isSubClass(c, types)) {
3809+
Symbol sym = env1.info.scope.findFirst(names._this);
3810+
if (sym != null) {
3811+
if (staticOnly) {
3812+
// current class is not an inner class, stop search
3813+
return new StaticError(sym);
3814+
} else if (env1.info.ctorPrologue && !isAllowedEarlyReference(pos, env1, (VarSymbol)sym)) {
3815+
// early construction context, stop search
3816+
return new RefBeforeCtorCalledError(sym);
3817+
} else {
3818+
// found it
3819+
return sym;
3820+
}
3821+
}
3822+
}
3823+
if ((env1.enclClass.sym.flags() & STATIC) != 0) staticOnly = true;
3824+
env1 = env1.outer;
3825+
}
3826+
return varNotFound;
3827+
}
3828+
3829+
/**
3830+
* Resolve the (method) owner of a local class. This can fail if the local class
3831+
* is referenced from a static context nested inside the local class. Effectively,
3832+
* this lookup succeeds if we can access a local variable declared inside the owner
3833+
* method from the provided env.
3834+
*/
3835+
Symbol findLocalClassOwner(Env<AttrContext> env, TypeSymbol c) {
3836+
Symbol owner = c.owner;
3837+
Assert.check(owner.kind == MTH);
3838+
Env<AttrContext> env1 = env;
3839+
boolean staticOnly = false;
3840+
while (env1.outer != null) {
3841+
if (env1.info.scope.owner == owner) {
3842+
return (staticOnly) ?
3843+
new BadLocalClassCreation(c) :
3844+
owner;
3845+
}
3846+
if (isStatic(env1)) staticOnly = true;
3847+
env1 = env1.outer;
3848+
}
3849+
return methodNotFound;
3850+
}
3851+
37963852
/**
37973853
* Resolve `c.name' where name == this or name == super.
37983854
* @param pos The position to use for error reporting.
@@ -3817,15 +3873,15 @@ Symbol resolveSelf(DiagnosticPosition pos,
38173873
else if (env1.info.ctorPrologue && !isAllowedEarlyReference(pos, env1, (VarSymbol)sym))
38183874
sym = new RefBeforeCtorCalledError(sym);
38193875
return accessBase(sym, pos, env.enclClass.sym.type,
3820-
name, true);
3876+
name, true);
38213877
}
38223878
}
38233879
if ((env1.enclClass.sym.flags() & STATIC) != 0) staticOnly = true;
38243880
env1 = env1.outer;
38253881
}
38263882
if (c.isInterface() &&
3827-
name == names._super && !isStatic(env) &&
3828-
types.isDirectSuperInterface(c, env.enclClass.sym)) {
3883+
name == names._super && !isStatic(env) &&
3884+
types.isDirectSuperInterface(c, env.enclClass.sym)) {
38293885
//this might be a default super call if one of the superinterfaces is 'c'
38303886
for (Type t : pruneInterfaces(env.enclClass.type)) {
38313887
if (t.tsym == c) {
@@ -3840,8 +3896,8 @@ else if (env1.info.ctorPrologue && !isAllowedEarlyReference(pos, env1, (VarSymbo
38403896
for (Type i : types.directSupertypes(env.enclClass.type)) {
38413897
if (i.tsym.isSubClass(c, types) && i.tsym != c) {
38423898
log.error(pos,
3843-
Errors.IllegalDefaultSuperCall(c,
3844-
Fragments.RedundantSupertype(c, i)));
3899+
Errors.IllegalDefaultSuperCall(c,
3900+
Fragments.RedundantSupertype(c, i)));
38453901
return syms.errSymbol;
38463902
}
38473903
}
@@ -3948,76 +4004,6 @@ public boolean isEarlyReference(Env<AttrContext> env, JCTree base, VarSymbol v)
39484004
(base == null || TreeInfo.isExplicitThisReference(types, (ClassType)env.enclClass.type, base));
39494005
}
39504006

3951-
/**
3952-
* Resolve `c.this' for an enclosing class c that contains the
3953-
* named member.
3954-
* @param pos The position to use for error reporting.
3955-
* @param env The environment current at the expression.
3956-
* @param member The member that must be contained in the result.
3957-
*/
3958-
Symbol resolveSelfContaining(DiagnosticPosition pos,
3959-
Env<AttrContext> env,
3960-
Symbol member,
3961-
boolean isSuperCall) {
3962-
Symbol sym = resolveSelfContainingInternal(env, member, isSuperCall);
3963-
if (sym == null) {
3964-
log.error(pos, Errors.EnclClassRequired(member));
3965-
return syms.errSymbol;
3966-
} else {
3967-
return accessBase(sym, pos, env.enclClass.sym.type, sym.name, true);
3968-
}
3969-
}
3970-
3971-
boolean enclosingInstanceMissing(Env<AttrContext> env, Type type) {
3972-
if (type.hasTag(CLASS) && type.getEnclosingType().hasTag(CLASS)) {
3973-
Symbol encl = resolveSelfContainingInternal(env, type.tsym, false);
3974-
return encl == null || encl.kind.isResolutionError();
3975-
}
3976-
return false;
3977-
}
3978-
3979-
private Symbol resolveSelfContainingInternal(Env<AttrContext> env,
3980-
Symbol member,
3981-
boolean isSuperCall) {
3982-
Name name = names._this;
3983-
Env<AttrContext> env1 = isSuperCall ? env.outer : env;
3984-
boolean staticOnly = false;
3985-
if (env1 != null) {
3986-
while (env1 != null && env1.outer != null) {
3987-
if (isStatic(env1)) staticOnly = true;
3988-
if (env1.enclClass.sym.isSubClass(member.owner.enclClass(), types)) {
3989-
Symbol sym = env1.info.scope.findFirst(name);
3990-
if (sym != null) {
3991-
if (staticOnly) sym = new StaticError(sym);
3992-
return sym;
3993-
}
3994-
}
3995-
if ((env1.enclClass.sym.flags() & STATIC) != 0)
3996-
staticOnly = true;
3997-
env1 = env1.outer;
3998-
}
3999-
}
4000-
return null;
4001-
}
4002-
4003-
/**
4004-
* Resolve an appropriate implicit this instance for t's container.
4005-
* JLS 8.8.5.1 and 15.9.2
4006-
*/
4007-
Type resolveImplicitThis(DiagnosticPosition pos, Env<AttrContext> env, Type t) {
4008-
return resolveImplicitThis(pos, env, t, false);
4009-
}
4010-
4011-
Type resolveImplicitThis(DiagnosticPosition pos, Env<AttrContext> env, Type t, boolean isSuperCall) {
4012-
Type thisType = (t.tsym.owner.kind.matches(KindSelector.VAL_MTH)
4013-
? resolveSelf(pos, env, t.getEnclosingType().tsym, names._this)
4014-
: resolveSelfContaining(pos, env, t.tsym, isSuperCall)).type;
4015-
if (env.info.ctorPrologue && thisType.tsym == env.enclClass.sym) {
4016-
log.error(pos, Errors.CantRefBeforeCtorCalled(names._this));
4017-
}
4018-
return thisType;
4019-
}
4020-
40214007
/* ***************************************************************************
40224008
* ResolveError classes, indicating error situations when accessing symbols
40234009
****************************************************************************/
@@ -4741,6 +4727,28 @@ JCDiagnostic getDiagnostic(JCDiagnostic.DiagnosticType dkind,
47414727
}
47424728
}
47434729

4730+
/**
4731+
* Specialization of {@link StaticError} for illegal
4732+
* creation of local class instances from a static context.
4733+
*/
4734+
class BadLocalClassCreation extends StaticError {
4735+
BadLocalClassCreation(Symbol sym) {
4736+
super(sym, "bad local class creation");
4737+
}
4738+
4739+
@Override
4740+
JCDiagnostic getDiagnostic(JCDiagnostic.DiagnosticType dkind,
4741+
DiagnosticPosition pos,
4742+
Symbol location,
4743+
Type site,
4744+
Name name,
4745+
List<Type> argtypes,
4746+
List<Type> typeargtypes) {
4747+
return diags.create(dkind, log.currentSource(), pos,
4748+
"local.cant.be.inst.static", kindName(sym), sym);
4749+
}
4750+
}
4751+
47444752
/**
47454753
* Specialization of {@link InvalidSymbolError} for illegal
47464754
* early accesses within a constructor prologue.
@@ -4900,23 +4908,6 @@ JCDiagnostic getDiagnostic(DiagnosticType dkind, DiagnosticPosition pos, Symbol
49004908
}
49014909
}
49024910

4903-
/**
4904-
* BadConstructorReferenceError error class indicating that a constructor reference symbol has been found,
4905-
* but pointing to a class for which an enclosing instance is not available.
4906-
*/
4907-
class BadConstructorReferenceError extends InvalidSymbolError {
4908-
4909-
public BadConstructorReferenceError(Symbol sym) {
4910-
super(MISSING_ENCL, sym, "BadConstructorReferenceError");
4911-
}
4912-
4913-
@Override
4914-
JCDiagnostic getDiagnostic(DiagnosticType dkind, DiagnosticPosition pos, Symbol location, Type site, Name name, List<Type> argtypes, List<Type> typeargtypes) {
4915-
return diags.create(dkind, log.currentSource(), pos,
4916-
"cant.access.inner.cls.constr", site.tsym.name, argtypes, site.getEnclosingType());
4917-
}
4918-
}
4919-
49204911
class BadClassFileError extends InvalidSymbolError {
49214912

49224913
private final CompletionFailure ex;

src/jdk.compiler/share/classes/com/sun/tools/javac/resources/compiler.properties

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1095,11 +1095,6 @@ compiler.misc.not.def.access.class.intf.cant.access.reason=\
10951095
{1}.{0} in package {2} is not accessible\n\
10961096
({3})
10971097

1098-
# 0: symbol, 1: list of type, 2: type
1099-
compiler.misc.cant.access.inner.cls.constr=\
1100-
cannot access constructor {0}({1})\n\
1101-
an enclosing instance of type {2} is not in scope
1102-
11031098
# 0: symbol, 1: symbol
11041099
compiler.err.not.def.public.cant.access=\
11051100
{0} is not public in {1}; cannot be accessed from outside package
@@ -2883,6 +2878,11 @@ compiler.err.abstract.cant.be.accessed.directly=\
28832878
compiler.err.non-static.cant.be.ref=\
28842879
non-static {0} {1} cannot be referenced from a static context
28852880

2881+
## The first argument ({0}) is a "kindname".
2882+
# 0: symbol kind, 1: symbol
2883+
compiler.err.local.cant.be.inst.static=\
2884+
local {0} {1} cannot be instantiated from a static context
2885+
28862886
# 0: symbol kind, 1: symbol
28872887
compiler.misc.bad.static.method.in.unbound.lookup=\
28882888
unexpected static {0} {1} found in unbound lookup
Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,44 @@
1+
/*
2+
* @test /nodynamiccopyright/
3+
* @bug 8322882
4+
* @summary Disallow attempts to access a free variable proxy field from a static method
5+
* @compile/fail/ref=LocalFreeVarStaticInstantiate.out -XDrawDiagnostics LocalFreeVarStaticInstantiate.java
6+
*/
7+
8+
class LocalFreeVarStaticInstantiate {
9+
10+
// local class in method
11+
static void foo(Object there) {
12+
class Local {
13+
{
14+
there.hashCode();
15+
}
16+
17+
static {
18+
new Local(); // can't get there from here
19+
}
20+
21+
static Runnable r = () -> {
22+
new Local(); // can't get there from here
23+
};
24+
}
25+
}
26+
27+
// local class in lambda
28+
static Runnable foo = () -> {
29+
Object there = "";
30+
class Local {
31+
{
32+
there.hashCode();
33+
}
34+
35+
static {
36+
new Local(); // can't get there from here
37+
}
38+
39+
static Runnable r = () -> {
40+
new Local(); // can't get there from here
41+
};
42+
}
43+
};
44+
}
Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
LocalFreeVarStaticInstantiate.java:18:17: compiler.err.local.cant.be.inst.static: kindname.class, Local
2+
LocalFreeVarStaticInstantiate.java:22:17: compiler.err.local.cant.be.inst.static: kindname.class, Local
3+
LocalFreeVarStaticInstantiate.java:36:17: compiler.err.local.cant.be.inst.static: kindname.class, Local
4+
LocalFreeVarStaticInstantiate.java:40:17: compiler.err.local.cant.be.inst.static: kindname.class, Local
5+
4 errors

test/langtools/tools/javac/QualifiedAccess/QualifiedAccess_2.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@
77
*
88
* @compile pack1/P1.java
99
* @compile pack1/P2.java
10-
* @compile/fail/ref=QualifiedAccess_2.out -XDrawDiagnostics QualifiedAccess_2.java
10+
* @compile/fail/ref=QualifiedAccess_2.out -XDdev -XDrawDiagnostics QualifiedAccess_2.java
1111
*/
1212

1313
import pack1.P1;

0 commit comments

Comments
 (0)