@@ -937,6 +937,8 @@ public void visitClassDef(JCClassDecl tree) {
937937 Optional <ArgumentAttr .LocalCacheContext > localCacheContext =
938938 Optional .ofNullable (env .info .attributionMode .isSpeculative ?
939939 argumentAttr .withLocalCacheContext () : null );
940+ boolean ctorProloguePrev = env .info .ctorPrologue ;
941+ env .info .ctorPrologue = false ;
940942 try {
941943 // Local and anonymous classes have not been entered yet, so we need to
942944 // do it now.
@@ -959,19 +961,18 @@ public void visitClassDef(JCClassDecl tree) {
959961 // make sure class has been completed:
960962 c .complete ();
961963
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.
965966 // (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 )) {
968968 c .flags_field |= NOOUTERTHIS ;
969969 }
970970 attribClass (tree .pos (), c );
971971 result = tree .type = c .type ;
972972 }
973973 } finally {
974974 localCacheContext .ifPresent (LocalCacheContext ::leave );
975+ env .info .ctorPrologue = ctorProloguePrev ;
975976 }
976977 }
977978
@@ -981,6 +982,8 @@ public void visitMethodDef(JCMethodDecl tree) {
981982
982983 Lint lint = env .info .lint .augment (m );
983984 Lint prevLint = chk .setLint (lint );
985+ boolean ctorProloguePrev = env .info .ctorPrologue ;
986+ env .info .ctorPrologue = false ;
984987 MethodSymbol prevMethod = chk .setMethod (m );
985988 try {
986989 deferredLintHandler .flush (tree .pos ());
@@ -1044,6 +1047,9 @@ public void visitMethodDef(JCMethodDecl tree) {
10441047 chk .validate (tree .recvparam , newEnv );
10451048 }
10461049
1050+ // Is this method a constructor?
1051+ boolean isConstructor = TreeInfo .isConstructor (tree );
1052+
10471053 if (env .enclClass .sym .isRecord () && tree .sym .owner .kind == TYP ) {
10481054 // lets find if this method is an accessor
10491055 Optional <? extends RecordComponent > recordComponent = env .enclClass .sym .getRecordComponents ().stream ()
@@ -1071,14 +1077,11 @@ public void visitMethodDef(JCMethodDecl tree) {
10711077 }
10721078 }
10731079
1074- if (tree . name == names . init ) {
1080+ if (isConstructor ) {
10751081 // if this a constructor other than the canonical one
10761082 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 ));
10821085 }
10831086 } else {
10841087 // but if it is the canonical:
@@ -1104,11 +1107,7 @@ public void visitMethodDef(JCMethodDecl tree) {
11041107 );
11051108 }
11061109
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 )) {
11121111 log .error (tree , Errors .InvalidCanonicalConstructorInRecord (
11131112 Fragments .Canonical , env .enclClass .sym .name ,
11141113 Fragments .CanonicalMustNotContainExplicitConstructorInvocation ));
@@ -1186,16 +1185,14 @@ public void visitMethodDef(JCMethodDecl tree) {
11861185 // Add an implicit super() call unless an explicit call to
11871186 // super(...) or this(...) is given
11881187 // 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 (),
11941191 make .Ident (names ._super ), make .Idents (List .nil ())));
1195- body .stats = body .stats .prepend (supCall );
1192+ tree . body .stats = tree . body .stats .prepend (supCall );
11961193 } else if ((env .enclClass .sym .flags () & ENUM ) != 0 &&
11971194 (tree .mods .flags & GENERATEDCONSTR ) == 0 &&
1198- TreeInfo .isSuperCall ( body . stats . head )) {
1195+ TreeInfo .hasConstructorCall ( tree , names . _super )) {
11991196 // enum constructors are not allowed to call super
12001197 // directly, so make sure there aren't any super calls
12011198 // in enum constructors, except in the compiler
@@ -1225,6 +1222,9 @@ public void visitMethodDef(JCMethodDecl tree) {
12251222 annotate .queueScanTreeAndTypeAnnotate (tree .body , localEnv , m , null );
12261223 annotate .flush ();
12271224
1225+ // Start of constructor prologue
1226+ localEnv .info .ctorPrologue = isConstructor ;
1227+
12281228 // Attribute method body.
12291229 attribStat (tree .body , localEnv );
12301230 }
@@ -1234,6 +1234,7 @@ public void visitMethodDef(JCMethodDecl tree) {
12341234 } finally {
12351235 chk .setLint (prevLint );
12361236 chk .setMethod (prevMethod );
1237+ env .info .ctorPrologue = ctorProloguePrev ;
12371238 }
12381239 }
12391240
@@ -2518,21 +2519,15 @@ public void visitApply(JCMethodInvocation tree) {
25182519
25192520 ListBuffer <Type > argtypesBuf = new ListBuffer <>();
25202521 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 ;
25282522
25292523 // Attribute arguments, yielding list of argument types.
2530- localEnv .info .constructorArgs = true ;
25312524 KindSelector kind = attribArgs (KindSelector .MTH , tree .args , localEnv , argtypesBuf );
2532- localEnv .info .constructorArgs = false ;
25332525 argtypes = argtypesBuf .toList ();
25342526 typeargtypes = attribTypes (tree .typeargs , localEnv );
25352527
2528+ // Done with this()/super() parameters. End of constructor prologue.
2529+ env .info .ctorPrologue = false ;
2530+
25362531 // Variable `site' points to the class in which the called
25372532 // constructor is defined.
25382533 Type site = env .enclClass .sym .type ;
@@ -2661,26 +2656,6 @@ Type adjustMethodReturnType(Symbol msym, Type qualifierType, Name methodName, Li
26612656 }
26622657 }
26632658
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-
26842659 /** Obtain a method type with given argument types.
26852660 */
26862661 Type newMethodTemplate (Type restype , List <Type > argtypes , List <Type > typeargtypes ) {
@@ -4353,16 +4328,6 @@ public void visitIdent(JCIdent tree) {
43534328 checkAssignable (tree .pos (), v , null , env );
43544329 }
43554330
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- }
43664331 Env <AttrContext > env1 = env ;
43674332 if (sym .kind != ERR && sym .kind != TYP &&
43684333 sym .owner != null && sym .owner != env1 .enclClass .sym ) {
@@ -4474,18 +4439,7 @@ public void visitSelect(JCFieldAccess tree) {
44744439 }
44754440
44764441 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 ) {
44894443 // Check if type-qualified fields or methods are static (JLS)
44904444 if ((sym .flags () & STATIC ) == 0 &&
44914445 sym .name != names ._super &&
@@ -5674,6 +5628,9 @@ private void attribClassBody(Env<AttrContext> env, ClassSymbol c) {
56745628 }
56755629 }
56765630
5631+ // Check for proper placement of super()/this() calls.
5632+ chk .checkSuperInitCalls (tree );
5633+
56775634 // Check for cycles among non-initial constructors.
56785635 chk .checkCyclicConstructors (tree );
56795636
0 commit comments