@@ -937,6 +937,8 @@ public void visitClassDef(JCClassDecl tree) {
937
937
Optional <ArgumentAttr .LocalCacheContext > localCacheContext =
938
938
Optional .ofNullable (env .info .attributionMode .isSpeculative ?
939
939
argumentAttr .withLocalCacheContext () : null );
940
+ boolean ctorProloguePrev = env .info .ctorPrologue ;
941
+ env .info .ctorPrologue = false ;
940
942
try {
941
943
// Local and anonymous classes have not been entered yet, so we need to
942
944
// do it now.
@@ -959,19 +961,18 @@ public void visitClassDef(JCClassDecl tree) {
959
961
// make sure class has been completed:
960
962
c .complete ();
961
963
962
- // If this class appears as an anonymous class
963
- // in a superclass constructor call
964
- // disable implicit outer instance from being passed.
964
+ // If this class appears as an anonymous class in a constructor
965
+ // prologue, disable implicit outer instance from being passed.
965
966
// (This would be an illegal access to "this before super").
966
- if (env .info .isSelfCall &&
967
- env .tree .hasTag (NEWCLASS )) {
967
+ if (ctorProloguePrev && env .tree .hasTag (NEWCLASS )) {
968
968
c .flags_field |= NOOUTERTHIS ;
969
969
}
970
970
attribClass (tree .pos (), c );
971
971
result = tree .type = c .type ;
972
972
}
973
973
} finally {
974
974
localCacheContext .ifPresent (LocalCacheContext ::leave );
975
+ env .info .ctorPrologue = ctorProloguePrev ;
975
976
}
976
977
}
977
978
@@ -981,6 +982,8 @@ public void visitMethodDef(JCMethodDecl tree) {
981
982
982
983
Lint lint = env .info .lint .augment (m );
983
984
Lint prevLint = chk .setLint (lint );
985
+ boolean ctorProloguePrev = env .info .ctorPrologue ;
986
+ env .info .ctorPrologue = false ;
984
987
MethodSymbol prevMethod = chk .setMethod (m );
985
988
try {
986
989
deferredLintHandler .flush (tree .pos ());
@@ -1044,6 +1047,9 @@ public void visitMethodDef(JCMethodDecl tree) {
1044
1047
chk .validate (tree .recvparam , newEnv );
1045
1048
}
1046
1049
1050
+ // Is this method a constructor?
1051
+ boolean isConstructor = TreeInfo .isConstructor (tree );
1052
+
1047
1053
if (env .enclClass .sym .isRecord () && tree .sym .owner .kind == TYP ) {
1048
1054
// lets find if this method is an accessor
1049
1055
Optional <? extends RecordComponent > recordComponent = env .enclClass .sym .getRecordComponents ().stream ()
@@ -1071,14 +1077,11 @@ public void visitMethodDef(JCMethodDecl tree) {
1071
1077
}
1072
1078
}
1073
1079
1074
- if (tree . name == names . init ) {
1080
+ if (isConstructor ) {
1075
1081
// if this a constructor other than the canonical one
1076
1082
if ((tree .sym .flags_field & RECORD ) == 0 ) {
1077
- JCMethodInvocation app = TreeInfo .firstConstructorCall (tree );
1078
- if (app == null ||
1079
- TreeInfo .name (app .meth ) != names ._this ||
1080
- !checkFirstConstructorStat (app , tree , false )) {
1081
- log .error (tree , Errors .FirstStatementMustBeCallToAnotherConstructor (env .enclClass .sym ));
1083
+ if (!TreeInfo .hasConstructorCall (tree , names ._this )) {
1084
+ log .error (tree , Errors .NonCanonicalConstructorInvokeAnotherConstructor (env .enclClass .sym ));
1082
1085
}
1083
1086
} else {
1084
1087
// but if it is the canonical:
@@ -1104,11 +1107,7 @@ public void visitMethodDef(JCMethodDecl tree) {
1104
1107
);
1105
1108
}
1106
1109
1107
- JCMethodInvocation app = TreeInfo .firstConstructorCall (tree );
1108
- if (app != null &&
1109
- (TreeInfo .name (app .meth ) == names ._this ||
1110
- TreeInfo .name (app .meth ) == names ._super ) &&
1111
- checkFirstConstructorStat (app , tree , false )) {
1110
+ if (TreeInfo .hasAnyConstructorCall (tree )) {
1112
1111
log .error (tree , Errors .InvalidCanonicalConstructorInRecord (
1113
1112
Fragments .Canonical , env .enclClass .sym .name ,
1114
1113
Fragments .CanonicalMustNotContainExplicitConstructorInvocation ));
@@ -1186,16 +1185,14 @@ public void visitMethodDef(JCMethodDecl tree) {
1186
1185
// Add an implicit super() call unless an explicit call to
1187
1186
// super(...) or this(...) is given
1188
1187
// or we are compiling class java.lang.Object.
1189
- if (tree .name == names .init && owner .type != syms .objectType ) {
1190
- JCBlock body = tree .body ;
1191
- if (body .stats .isEmpty () ||
1192
- TreeInfo .getConstructorInvocationName (body .stats , names ) == names .empty ) {
1193
- JCStatement supCall = make .at (body .pos ).Exec (make .Apply (List .nil (),
1188
+ if (isConstructor && owner .type != syms .objectType ) {
1189
+ if (!TreeInfo .hasAnyConstructorCall (tree )) {
1190
+ JCStatement supCall = make .at (tree .body .pos ).Exec (make .Apply (List .nil (),
1194
1191
make .Ident (names ._super ), make .Idents (List .nil ())));
1195
- body .stats = body .stats .prepend (supCall );
1192
+ tree . body .stats = tree . body .stats .prepend (supCall );
1196
1193
} else if ((env .enclClass .sym .flags () & ENUM ) != 0 &&
1197
1194
(tree .mods .flags & GENERATEDCONSTR ) == 0 &&
1198
- TreeInfo .isSuperCall ( body . stats . head )) {
1195
+ TreeInfo .hasConstructorCall ( tree , names . _super )) {
1199
1196
// enum constructors are not allowed to call super
1200
1197
// directly, so make sure there aren't any super calls
1201
1198
// in enum constructors, except in the compiler
@@ -1225,6 +1222,9 @@ public void visitMethodDef(JCMethodDecl tree) {
1225
1222
annotate .queueScanTreeAndTypeAnnotate (tree .body , localEnv , m , null );
1226
1223
annotate .flush ();
1227
1224
1225
+ // Start of constructor prologue
1226
+ localEnv .info .ctorPrologue = isConstructor ;
1227
+
1228
1228
// Attribute method body.
1229
1229
attribStat (tree .body , localEnv );
1230
1230
}
@@ -1234,6 +1234,7 @@ public void visitMethodDef(JCMethodDecl tree) {
1234
1234
} finally {
1235
1235
chk .setLint (prevLint );
1236
1236
chk .setMethod (prevMethod );
1237
+ env .info .ctorPrologue = ctorProloguePrev ;
1237
1238
}
1238
1239
}
1239
1240
@@ -2518,21 +2519,15 @@ public void visitApply(JCMethodInvocation tree) {
2518
2519
2519
2520
ListBuffer <Type > argtypesBuf = new ListBuffer <>();
2520
2521
if (isConstructorCall ) {
2521
- // We are seeing a ...this(...) or ...super(...) call.
2522
- // Check that this is the first statement in a constructor.
2523
- checkFirstConstructorStat (tree , env .enclMethod , true );
2524
-
2525
- // Record the fact
2526
- // that this is a constructor call (using isSelfCall).
2527
- localEnv .info .isSelfCall = true ;
2528
2522
2529
2523
// Attribute arguments, yielding list of argument types.
2530
- localEnv .info .constructorArgs = true ;
2531
2524
KindSelector kind = attribArgs (KindSelector .MTH , tree .args , localEnv , argtypesBuf );
2532
- localEnv .info .constructorArgs = false ;
2533
2525
argtypes = argtypesBuf .toList ();
2534
2526
typeargtypes = attribTypes (tree .typeargs , localEnv );
2535
2527
2528
+ // Done with this()/super() parameters. End of constructor prologue.
2529
+ env .info .ctorPrologue = false ;
2530
+
2536
2531
// Variable `site' points to the class in which the called
2537
2532
// constructor is defined.
2538
2533
Type site = env .enclClass .sym .type ;
@@ -2661,26 +2656,6 @@ Type adjustMethodReturnType(Symbol msym, Type qualifierType, Name methodName, Li
2661
2656
}
2662
2657
}
2663
2658
2664
- /** Check that given application node appears as first statement
2665
- * in a constructor call.
2666
- * @param tree The application node
2667
- * @param enclMethod The enclosing method of the application.
2668
- * @param error Should an error be issued?
2669
- */
2670
- boolean checkFirstConstructorStat (JCMethodInvocation tree , JCMethodDecl enclMethod , boolean error ) {
2671
- if (enclMethod != null && enclMethod .name == names .init ) {
2672
- JCBlock body = enclMethod .body ;
2673
- if (body .stats .head .hasTag (EXEC ) &&
2674
- ((JCExpressionStatement ) body .stats .head ).expr == tree )
2675
- return true ;
2676
- }
2677
- if (error ) {
2678
- log .error (tree .pos (),
2679
- Errors .CallMustBeFirstStmtInCtor (TreeInfo .name (tree .meth )));
2680
- }
2681
- return false ;
2682
- }
2683
-
2684
2659
/** Obtain a method type with given argument types.
2685
2660
*/
2686
2661
Type newMethodTemplate (Type restype , List <Type > argtypes , List <Type > typeargtypes ) {
@@ -4353,16 +4328,6 @@ public void visitIdent(JCIdent tree) {
4353
4328
checkAssignable (tree .pos (), v , null , env );
4354
4329
}
4355
4330
4356
- // In a constructor body,
4357
- // if symbol is a field or instance method, check that it is
4358
- // not accessed before the supertype constructor is called.
4359
- if (symEnv .info .isSelfCall &&
4360
- sym .kind .matches (KindSelector .VAL_MTH ) &&
4361
- sym .owner .kind == TYP &&
4362
- (sym .flags () & STATIC ) == 0 ) {
4363
- chk .earlyRefError (tree .pos (), sym .kind == VAR ?
4364
- sym : thisSym (tree .pos (), env ));
4365
- }
4366
4331
Env <AttrContext > env1 = env ;
4367
4332
if (sym .kind != ERR && sym .kind != TYP &&
4368
4333
sym .owner != null && sym .owner != env1 .enclClass .sym ) {
@@ -4474,18 +4439,7 @@ public void visitSelect(JCFieldAccess tree) {
4474
4439
}
4475
4440
4476
4441
if (isType (sitesym )) {
4477
- if (sym .name == names ._this || sym .name == names ._super ) {
4478
- // If `C' is the currently compiled class, check that
4479
- // `C.this' does not appear in an explicit call to a constructor
4480
- // also make sure that `super` is not used in constructor invocations
4481
- if (env .info .isSelfCall &&
4482
- ((sym .name == names ._this &&
4483
- site .tsym == env .enclClass .sym ) ||
4484
- sym .name == names ._super && env .info .constructorArgs &&
4485
- (sitesym .isInterface () || site .tsym == env .enclClass .sym ))) {
4486
- chk .earlyRefError (tree .pos (), sym );
4487
- }
4488
- } else {
4442
+ if (sym .name != names ._this && sym .name != names ._super ) {
4489
4443
// Check if type-qualified fields or methods are static (JLS)
4490
4444
if ((sym .flags () & STATIC ) == 0 &&
4491
4445
sym .name != names ._super &&
@@ -5674,6 +5628,9 @@ private void attribClassBody(Env<AttrContext> env, ClassSymbol c) {
5674
5628
}
5675
5629
}
5676
5630
5631
+ // Check for proper placement of super()/this() calls.
5632
+ chk .checkSuperInitCalls (tree );
5633
+
5677
5634
// Check for cycles among non-initial constructors.
5678
5635
chk .checkCyclicConstructors (tree );
5679
5636
1 commit comments
openjdk-notifier[bot] commentedon Nov 27, 2023
Review
Issues