@@ -1269,6 +1269,7 @@ class CtorPrologueVisitor extends TreeScanner {
1269
1269
Env <AttrContext > localEnv ;
1270
1270
CtorPrologueVisitor (Env <AttrContext > localEnv ) {
1271
1271
this .localEnv = localEnv ;
1272
+ currentClassSym = localEnv .enclClass .sym ;
1272
1273
}
1273
1274
1274
1275
boolean insideLambdaOrClassDef = false ;
@@ -1284,14 +1285,19 @@ public void visitLambda(JCLambda lambda) {
1284
1285
}
1285
1286
}
1286
1287
1288
+ ClassSymbol currentClassSym ;
1289
+
1287
1290
@ Override
1288
1291
public void visitClassDef (JCClassDecl classDecl ) {
1289
1292
boolean previousInsideLambdaOrClassDef = insideLambdaOrClassDef ;
1293
+ ClassSymbol previousClassSym = currentClassSym ;
1290
1294
try {
1291
1295
insideLambdaOrClassDef = true ;
1296
+ currentClassSym = classDecl .sym ;
1292
1297
super .visitClassDef (classDecl );
1293
1298
} finally {
1294
1299
insideLambdaOrClassDef = previousInsideLambdaOrClassDef ;
1300
+ currentClassSym = previousClassSym ;
1295
1301
}
1296
1302
}
1297
1303
@@ -1384,6 +1390,10 @@ public void visitMethodDef(JCMethodDecl tree) {
1384
1390
1385
1391
void analyzeSymbol (JCTree tree ) {
1386
1392
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
+ }
1387
1397
if (isInLHS && !insideLambdaOrClassDef ) {
1388
1398
// Check instance field assignments that appear in constructor prologues
1389
1399
if (isEarlyReference (localEnv , tree , sym )) {
@@ -1392,7 +1402,6 @@ void analyzeSymbol(JCTree tree) {
1392
1402
log .error (tree , Errors .CantRefBeforeCtorCalled (sym ));
1393
1403
return ;
1394
1404
}
1395
-
1396
1405
// Field may not have an initializer
1397
1406
if ((sym .flags () & HASINIT ) != 0 ) {
1398
1407
log .error (tree , Errors .CantAssignInitializedBeforeCtorCalled (sym ));
@@ -1402,47 +1411,45 @@ void analyzeSymbol(JCTree tree) {
1402
1411
return ;
1403
1412
}
1404
1413
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
1435
1430
*/
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 {
1438
1452
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
- }
1446
1453
}
1447
1454
}
1448
1455
}
@@ -1468,6 +1475,14 @@ private boolean isEarlyReference(Env<AttrContext> env, JCTree tree, Symbol sym)
1468
1475
// Allow "Foo.this.x" when "Foo" is (also) an outer class, as this refers to the outer instance
1469
1476
if (tree instanceof JCFieldAccess fa ) {
1470
1477
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 );
1471
1486
}
1472
1487
return true ;
1473
1488
}
0 commit comments