From 3ea65cc7b8fd9e28ebd27d0a80dbb3877d6a6ce7 Mon Sep 17 00:00:00 2001 From: Maurizio Cimadamore Date: Fri, 14 Jun 2024 15:31:59 +0100 Subject: [PATCH] Fix enclosing instance chain to take into account inaccessible enclosing instances --- .../com/sun/tools/javac/code/Symbol.java | 14 ++++- .../com/sun/tools/javac/comp/Lower.java | 51 ++----------------- .../javac/MethodParameters/LocalClassTest.out | 2 +- 3 files changed, 16 insertions(+), 51 deletions(-) diff --git a/src/jdk.compiler/share/classes/com/sun/tools/javac/code/Symbol.java b/src/jdk.compiler/share/classes/com/sun/tools/javac/code/Symbol.java index ca420eecdc5e5..eacdb6c10761e 100644 --- a/src/jdk.compiler/share/classes/com/sun/tools/javac/code/Symbol.java +++ b/src/jdk.compiler/share/classes/com/sun/tools/javac/code/Symbol.java @@ -358,7 +358,7 @@ public Type erasure(Types types) { public Type externalType(Types types) { Type t = erasure(types); if (name == name.table.names.init && owner.hasOuterInstance()) { - Type outerThisType = types.erasure(owner.type.getEnclosingType()); + Type outerThisType = types.erasure(owner.innermostAccessibleEnclosingType()); return new MethodType(t.getParameterTypes().prepend(outerThisType), t.getReturnType(), t.getThrownTypes(), @@ -506,7 +506,17 @@ public boolean isInner() { */ public boolean hasOuterInstance() { return - type.getEnclosingType().hasTag(CLASS) && (flags() & (INTERFACE | ENUM | RECORD | NOOUTERTHIS)) == 0; + type.getEnclosingType().hasTag(CLASS) && (flags() & (INTERFACE | ENUM | RECORD)) == 0 && + ((flags() & NOOUTERTHIS) == 0 || type.getEnclosingType().tsym.hasOuterInstance()); + } + + public Type innermostAccessibleEnclosingType() { + Assert.check(enclClass().hasOuterInstance()); + Type current = enclClass().type; + while ((current.tsym.flags() & NOOUTERTHIS) != 0) { + current = current.getEnclosingType(); + } + return current.getEnclosingType(); } /** The closest enclosing class of this symbol's declaration. diff --git a/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/Lower.java b/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/Lower.java index d060763cc7372..283f895340e19 100644 --- a/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/Lower.java +++ b/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/Lower.java @@ -372,52 +372,7 @@ void visitSymbol(Symbol sym) { } } } - if (sym.kind == VAR || sym.kind == MTH) { - if (outerThisStack.head != null && - outerThisStack.head != sym) - visitSymbol(outerThisStack.head); - } - } - - /** If tree refers to a class instance creation expression - * add all free variables of the freshly created class. - */ - public void visitNewClass(JCNewClass tree) { - ClassSymbol c = (ClassSymbol)tree.constructor.owner; - if (tree.encl == null && - c.hasOuterInstance() && - outerThisStack.head != null) - visitSymbol(outerThisStack.head); - super.visitNewClass(tree); - } - - /** If tree refers to a qualified this or super expression - * for anything but the current class, add the outer this - * stack as a free variable. - */ - public void visitSelect(JCFieldAccess tree) { - if ((tree.name == names._this || tree.name == names._super) && - tree.selected.type.tsym != clazz && - outerThisStack.head != null) - visitSymbol(outerThisStack.head); - super.visitSelect(tree); } - - /** If tree refers to a superclass constructor call, - * add all free variables of the superclass. - */ - public void visitApply(JCMethodInvocation tree) { - if (TreeInfo.name(tree.meth) == names._super) { - Symbol constructor = TreeInfo.symbol(tree.meth); - ClassSymbol c = (ClassSymbol)constructor.owner; - if (c.hasOuterInstance() && - !tree.meth.hasTag(SELECT) && - outerThisStack.head != null) - visitSymbol(outerThisStack.head); - } - super.visitApply(tree); - } - } ClassSymbol ownerToCopyFreeVarsFrom(ClassSymbol c) { @@ -1591,7 +1546,7 @@ Name outerThisName(Type type, Symbol owner) { } private VarSymbol makeOuterThisVarSymbol(Symbol owner, long flags) { - Type target = types.erasure(owner.enclClass().type.getEnclosingType()); + Type target = types.erasure(owner.innermostAccessibleEnclosingType()); // Set NOOUTERTHIS for all synthetic outer instance variables, and unset // it when the variable is accessed. If the variable is never accessed, // we skip creating an outer instance field and saving the constructor @@ -3102,7 +3057,7 @@ public void visitNewClass(JCNewClass tree) { thisArg.type = tree.encl.type; } else if (c.isDirectlyOrIndirectlyLocal()) { // local class - thisArg = makeThis(tree.pos(), c.type.getEnclosingType().tsym); + thisArg = makeThis(tree.pos(), c.innermostAccessibleEnclosingType().tsym); } else { // nested class thisArg = makeOwnerThis(tree.pos(), c, false); @@ -3308,7 +3263,7 @@ public void visitApply(JCMethodInvocation tree) { ((JCIdent) tree.meth).name = methName; } else if (c.isDirectlyOrIndirectlyLocal() || methName == names._this){ // local class or this() call - thisArg = makeThis(tree.meth.pos(), c.type.getEnclosingType().tsym); + thisArg = makeThis(tree.meth.pos(), c.innermostAccessibleEnclosingType().tsym); } else if (currentClass.isStatic()) { // super() call from static nested class - invalid log.error(tree.pos(), diff --git a/test/langtools/tools/javac/MethodParameters/LocalClassTest.out b/test/langtools/tools/javac/MethodParameters/LocalClassTest.out index bd25ff3a6be50..3b95739e74a5e 100644 --- a/test/langtools/tools/javac/MethodParameters/LocalClassTest.out +++ b/test/langtools/tools/javac/MethodParameters/LocalClassTest.out @@ -1,7 +1,7 @@ class LocalClassTest$1 -- anon LocalClassTest$1.(final this$0/*implicit*/, final j, final val$i/*synthetic*/) class LocalClassTest$1CapturingLocal$1 -- anon -LocalClassTest$1CapturingLocal$1.(final val$this$0/*synthetic*/, final val$val$i/*synthetic*/) +LocalClassTest$1CapturingLocal$1.(final this$0/*implicit*/, final val$val$i/*synthetic*/) LocalClassTest$1CapturingLocal$1.test() class LocalClassTest$1CapturingLocal -- inner LocalClassTest$1CapturingLocal.(final this$0/*implicit*/, final j, final val$i/*synthetic*/)