Skip to content

Commit 04efe5c

Browse files
author
Vicente Romero
committed
8367323: [lworld] javac is rejecting valid code after fix for JDK-8359370
Reviewed-by: liach, mcimadamore
1 parent e40fde6 commit 04efe5c

File tree

4 files changed

+73
-44
lines changed

4 files changed

+73
-44
lines changed

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

Lines changed: 55 additions & 40 deletions
Original file line numberDiff line numberDiff line change
@@ -1269,6 +1269,7 @@ class CtorPrologueVisitor extends TreeScanner {
12691269
Env<AttrContext> localEnv;
12701270
CtorPrologueVisitor(Env<AttrContext> localEnv) {
12711271
this.localEnv = localEnv;
1272+
currentClassSym = localEnv.enclClass.sym;
12721273
}
12731274

12741275
boolean insideLambdaOrClassDef = false;
@@ -1284,14 +1285,19 @@ public void visitLambda(JCLambda lambda) {
12841285
}
12851286
}
12861287

1288+
ClassSymbol currentClassSym;
1289+
12871290
@Override
12881291
public void visitClassDef(JCClassDecl classDecl) {
12891292
boolean previousInsideLambdaOrClassDef = insideLambdaOrClassDef;
1293+
ClassSymbol previousClassSym = currentClassSym;
12901294
try {
12911295
insideLambdaOrClassDef = true;
1296+
currentClassSym = classDecl.sym;
12921297
super.visitClassDef(classDecl);
12931298
} finally {
12941299
insideLambdaOrClassDef = previousInsideLambdaOrClassDef;
1300+
currentClassSym = previousClassSym;
12951301
}
12961302
}
12971303

@@ -1384,6 +1390,10 @@ public void visitMethodDef(JCMethodDecl tree) {
13841390

13851391
void analyzeSymbol(JCTree tree) {
13861392
Symbol sym = TreeInfo.symbolFor(tree);
1393+
// make sure that there is a symbol and it is not static
1394+
if (sym == null || sym.isStatic()) {
1395+
return;
1396+
}
13871397
if (isInLHS && !insideLambdaOrClassDef) {
13881398
// Check instance field assignments that appear in constructor prologues
13891399
if (isEarlyReference(localEnv, tree, sym)) {
@@ -1392,7 +1402,6 @@ void analyzeSymbol(JCTree tree) {
13921402
log.error(tree, Errors.CantRefBeforeCtorCalled(sym));
13931403
return;
13941404
}
1395-
13961405
// Field may not have an initializer
13971406
if ((sym.flags() & HASINIT) != 0) {
13981407
log.error(tree, Errors.CantAssignInitializedBeforeCtorCalled(sym));
@@ -1402,47 +1411,45 @@ void analyzeSymbol(JCTree tree) {
14021411
return;
14031412
}
14041413
tree = TreeInfo.skipParens(tree);
1405-
if (sym != null) {
1406-
if (!sym.isStatic() && sym.kind == VAR && sym.owner.kind == TYP) {
1407-
if (sym.name == names._this || sym.name == names._super) {
1408-
// are we seeing something like `this` or `CurrentClass.this` or `SuperClass.super::foo`?
1409-
if (TreeInfo.isExplicitThisReference(
1410-
types,
1411-
(ClassType)localEnv.enclClass.sym.type,
1412-
tree)) {
1413-
reportPrologueError(tree, sym);
1414-
}
1415-
} else if (sym.kind == VAR && sym.owner.kind == TYP) { // now fields only
1416-
if (sym.owner != localEnv.enclClass.sym) {
1417-
if (localEnv.enclClass.sym.isSubClass(sym.owner, types) &&
1418-
sym.isInheritedIn(localEnv.enclClass.sym, types)) {
1419-
/* if we are dealing with a field that doesn't belong to the current class, but the
1420-
* field is inherited, this is an error. Unless, the super class is also an outer
1421-
* class and the field's qualifier refers to the outer class
1422-
*/
1423-
if (tree.hasTag(IDENT) ||
1424-
TreeInfo.isExplicitThisReference(
1425-
types,
1426-
(ClassType)localEnv.enclClass.sym.type,
1427-
((JCFieldAccess)tree).selected)) {
1428-
reportPrologueError(tree, sym);
1429-
}
1430-
}
1431-
} else if (isEarlyReference(localEnv, tree, sym)) {
1432-
/* now this is a `proper` instance field of the current class
1433-
* references to fields of identity classes which happen to have initializers are
1434-
* not allowed in the prologue
1414+
if (sym.kind == VAR && sym.owner.kind == TYP) {
1415+
if (sym.name == names._this || sym.name == names._super) {
1416+
// are we seeing something like `this` or `CurrentClass.this` or `SuperClass.super::foo`?
1417+
if (TreeInfo.isExplicitThisReference(
1418+
types,
1419+
(ClassType)localEnv.enclClass.sym.type,
1420+
tree)) {
1421+
reportPrologueError(tree, sym);
1422+
}
1423+
} else if (sym.kind == VAR && sym.owner.kind == TYP) { // now fields only
1424+
if (sym.owner != localEnv.enclClass.sym) {
1425+
if (localEnv.enclClass.sym.isSubClass(sym.owner, types) &&
1426+
sym.isInheritedIn(localEnv.enclClass.sym, types)) {
1427+
/* if we are dealing with a field that doesn't belong to the current class, but the
1428+
* field is inherited, this is an error. Unless, the super class is also an outer
1429+
* class and the field's qualifier refers to the outer class
14351430
*/
1436-
if (insideLambdaOrClassDef ||
1437-
(!localEnv.enclClass.sym.isValueClass() && (sym.flags_field & HASINIT) != 0))
1431+
if (tree.hasTag(IDENT) ||
1432+
TreeInfo.isExplicitThisReference(
1433+
types,
1434+
(ClassType)localEnv.enclClass.sym.type,
1435+
((JCFieldAccess)tree).selected)) {
1436+
reportPrologueError(tree, sym);
1437+
}
1438+
}
1439+
} else if (isEarlyReference(localEnv, tree, sym)) {
1440+
/* now this is a `proper` instance field of the current class
1441+
* references to fields of identity classes which happen to have initializers are
1442+
* not allowed in the prologue
1443+
*/
1444+
if (insideLambdaOrClassDef ||
1445+
(!localEnv.enclClass.sym.isValueClass() && (sym.flags_field & HASINIT) != 0))
1446+
reportPrologueError(tree, sym);
1447+
// we will need to generate a proxy for this field later on
1448+
if (!isInLHS) {
1449+
if (allowValueClasses) {
1450+
localProxyVarsGen.addFieldReadInPrologue(localEnv.enclMethod, sym);
1451+
} else {
14381452
reportPrologueError(tree, sym);
1439-
// we will need to generate a proxy for this field later on
1440-
if (!isInLHS) {
1441-
if (allowValueClasses) {
1442-
localProxyVarsGen.addFieldReadInPrologue(localEnv.enclMethod, sym);
1443-
} else {
1444-
reportPrologueError(tree, sym);
1445-
}
14461453
}
14471454
}
14481455
}
@@ -1468,6 +1475,14 @@ private boolean isEarlyReference(Env<AttrContext> env, JCTree tree, Symbol sym)
14681475
// Allow "Foo.this.x" when "Foo" is (also) an outer class, as this refers to the outer instance
14691476
if (tree instanceof JCFieldAccess fa) {
14701477
return TreeInfo.isExplicitThisReference(types, (ClassType)env.enclClass.type, fa.selected);
1478+
} else if (currentClassSym != env.enclClass.sym) {
1479+
/* so we are inside a class, CI, in the prologue of an outer class, CO, and the symbol being
1480+
* analyzed has no qualifier. So if the symbol is a member of CI the reference is allowed,
1481+
* otherwise it is not.
1482+
* It could be that the reference to CI's member happens inside CI's own prologue, but that
1483+
* will be checked separately, when CI's prologue is analyzed.
1484+
*/
1485+
return !sym.isMemberOf(currentClassSym, types);
14711486
}
14721487
return true;
14731488
}

test/langtools/tools/javac/SuperInit/SuperInitFails.java

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -192,9 +192,9 @@ public SuperInitFails(double[][] x) {
192192
SuperInitFails(short[][] ignore) {
193193
int i = new SuperInitFails(){
194194
void foo() {
195-
System.err.println(xx); // this should fail
195+
System.err.println(xx); // this one is OK, reading field `xx` in the anonymous class
196196
}
197-
}.xx; // this one is OK though
197+
}.xx; // this one is OK too, field of a fully constructed class
198198
super(null);
199199
}
200200

test/langtools/tools/javac/SuperInit/SuperInitFails.out

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,6 @@ SuperInitFails.java:172:17: compiler.err.cant.ref.before.ctor.called: x
1818
SuperInitFails.java:176:24: compiler.err.cant.ref.before.ctor.called: x
1919
SuperInitFails.java:180:18: compiler.err.cant.ref.before.ctor.called: x
2020
SuperInitFails.java:186:32: compiler.err.cant.ref.before.ctor.called: x
21-
SuperInitFails.java:195:36: compiler.err.cant.ref.before.ctor.called: xx
2221
SuperInitFails.java:206:25: compiler.err.return.before.superclass.initialized
2322
SuperInitFails.java:211:33: compiler.err.ctor.calls.not.allowed.here
2423
SuperInitFails.java:216:29: compiler.err.redundant.superclass.init
@@ -34,4 +33,4 @@ SuperInitFails.java:53:32: compiler.err.call.must.only.appear.in.ctor
3433
SuperInitFails.java:83:18: compiler.err.ctor.calls.not.allowed.here
3534
SuperInitFails.java:89:13: compiler.err.return.before.superclass.initialized
3635
SuperInitFails.java:150:18: compiler.err.call.must.only.appear.in.ctor
37-
36 errors
36+
35 errors

test/langtools/tools/javac/SuperInit/SuperInitGood.java

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -512,6 +512,20 @@ class Sub extends Test24 {
512512
}
513513
}
514514

515+
public static class Test25 {
516+
public Test25(Object o) {}
517+
518+
class Sub extends Test25 {
519+
public Sub() {
520+
super(new Object() {
521+
void foo() {
522+
getClass();
523+
}
524+
});
525+
}
526+
}
527+
}
528+
515529
public static void main(String[] args) {
516530
new Test0();
517531
new Test1();
@@ -559,5 +573,6 @@ public static void main(String[] args) {
559573
new Test22('x');
560574
new Test23();
561575
new Test24();
576+
new Test25(null);
562577
}
563578
}

0 commit comments

Comments
 (0)