You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@groovy.apache.org by em...@apache.org on 2020/05/23 16:52:29 UTC
[groovy] branch GROOVY-9569 updated: GROOVY-5259: refactor handling
of "this" reference in special ctor call
This is an automated email from the ASF dual-hosted git repository.
emilles pushed a commit to branch GROOVY-9569
in repository https://gitbox.apache.org/repos/asf/groovy.git
The following commit(s) were added to refs/heads/GROOVY-9569 by this push:
new afb9a3e GROOVY-5259: refactor handling of "this" reference in special ctor call
afb9a3e is described below
commit afb9a3e7deea247c604575fd450be0c3db4df536
Author: Eric Milles <er...@thomsonreuters.com>
AuthorDate: Sat May 23 11:34:20 2020 -0500
GROOVY-5259: refactor handling of "this" reference in special ctor call
---
.../groovy/classgen/AsmClassGenerator.java | 64 ++++++++++------------
src/test/gls/innerClass/InnerClassTest.groovy | 28 +++++-----
2 files changed, 43 insertions(+), 49 deletions(-)
diff --git a/src/main/java/org/codehaus/groovy/classgen/AsmClassGenerator.java b/src/main/java/org/codehaus/groovy/classgen/AsmClassGenerator.java
index 0f23e08..15fe90d 100644
--- a/src/main/java/org/codehaus/groovy/classgen/AsmClassGenerator.java
+++ b/src/main/java/org/codehaus/groovy/classgen/AsmClassGenerator.java
@@ -1078,7 +1078,7 @@ public class AsmClassGenerator extends ClassGenerator {
} else {
field = classNode.getDeclaredField(name);
if (field == null && !isValidFieldNodeForByteCodeAccess(classNode.getField(name), classNode)) {
- // GROOVY-5259, GROOVY-9501, GROOVY-9569
+ // GROOVY-9501, GROOVY-9569
if (checkStaticOuterField(expression, name)) return;
}
}
@@ -1275,28 +1275,29 @@ public class AsmClassGenerator extends ClassGenerator {
@Override
public void visitVariableExpression(final VariableExpression expression) {
- String variableName = expression.getName();
-
- //-----------------------------------------------------------------------
- // SPECIAL CASES
-
- // "this" for static methods is the Class instance
- ClassNode classNode = controller.getClassNode();
+ final String variableName = expression.getName();
if (expression.isThisExpression()) {
- if (controller.isStaticMethod() || (!controller.getCompileStack().isImplicitThis() && controller.isStaticContext())) {
- if (controller.isInGeneratedFunction()) classNode = controller.getOutermostClass();
- visitClassExpression(new ClassExpression(classNode));
+ // "this" in static context is Class instance
+ if (controller.isStaticMethod() || controller.getCompileStack().isInSpecialConstructorCall()
+ || (!controller.getCompileStack().isImplicitThis() && controller.isStaticContext())) {
+ ClassNode thisType = controller.getClassNode();
+ if (controller.isInGeneratedFunction()) {
+ do { thisType = thisType.getOuterClass();
+ } while (ClassHelper.isGeneratedFunction(thisType));
+ }
+ classX(thisType).visit(this);
} else {
loadThis(expression);
}
return;
}
- // "super" also requires special handling
if (expression.isSuperExpression()) {
+ // "super" in static context is Class instance
if (controller.isStaticMethod()) {
- visitClassExpression(new ClassExpression(classNode.getSuperClass()));
+ ClassNode superType = controller.getClassNode().getSuperClass();
+ classX(superType).visit(this);
} else {
loadThis(expression);
}
@@ -1304,11 +1305,22 @@ public class AsmClassGenerator extends ClassGenerator {
}
BytecodeVariable variable = controller.getCompileStack().getVariable(variableName, false);
- if (variable == null) {
- processClassVariable(expression);
- } else {
+ if (variable != null) {
controller.getOperandStack().loadOrStoreVariable(variable, expression.isUseReferenceDirectly());
+ } else if (passingParams && controller.isInScriptBody()) {
+ MethodVisitor mv = controller.getMethodVisitor();
+ mv.visitTypeInsn(NEW, "org/codehaus/groovy/runtime/ScriptReference");
+ mv.visitInsn(DUP);
+ loadThisOrOwner();
+ mv.visitLdcInsn(variableName);
+ mv.visitMethodInsn(INVOKESPECIAL, "org/codehaus/groovy/runtime/ScriptReference", "<init>", "(Lgroovy/lang/Script;Ljava/lang/String;)V", false);
+ } else {
+ PropertyExpression pexp = thisPropX(true, variableName);
+ pexp.getObjectExpression().setSourcePosition(expression);
+ pexp.getProperty().setSourcePosition(expression);
+ pexp.visit(this);
}
+
if (!controller.getCompileStack().isLHS()) {
controller.getAssertionWriter().record(expression);
}
@@ -1331,26 +1343,6 @@ public class AsmClassGenerator extends ClassGenerator {
}
}
- private void processClassVariable(final VariableExpression expression) {
- if (passingParams && controller.isInScriptBody()) {
- // TODO: check if this part is actually used
- MethodVisitor mv = controller.getMethodVisitor();
- // create a ScriptReference to pass into the closure
- mv.visitTypeInsn(NEW, "org/codehaus/groovy/runtime/ScriptReference");
- mv.visitInsn(DUP);
-
- loadThisOrOwner();
- mv.visitLdcInsn(expression.getName());
-
- mv.visitMethodInsn(INVOKESPECIAL, "org/codehaus/groovy/runtime/ScriptReference", "<init>", "(Lgroovy/lang/Script;Ljava/lang/String;)V", false);
- } else {
- PropertyExpression pexp = thisPropX(true, expression.getName());
- pexp.getObjectExpression().setSourcePosition(expression);
- pexp.getProperty().setSourcePosition(expression);
- visitPropertyExpression(pexp);
- }
- }
-
protected void createInterfaceSyntheticStaticFields() {
ClassNode icl = controller.getInterfaceClassLoadingClass();
diff --git a/src/test/gls/innerClass/InnerClassTest.groovy b/src/test/gls/innerClass/InnerClassTest.groovy
index 9b5fa33..44b5ad2 100644
--- a/src/test/gls/innerClass/InnerClassTest.groovy
+++ b/src/test/gls/innerClass/InnerClassTest.groovy
@@ -594,31 +594,33 @@ final class InnerClassTest {
'''
}
- /*@Test
+ @Test
void testUsageOfOuterField_WrongCallToSuper() {
shouldFail '''
- class InnerAccessOuter {
+ class Outer {
protected static final String OUTER_CONSTANT = 'Constant Value'
- class InnerClass {
- InnerClass() {
- // there's no Object#<init>(String) method, but it throws a VerifyError when a new instance
- // is created, meaning a wrong super call is generated
+ class Inner {
+ Inner() {
+ // there is no Object#<init>(String) method, but it throws a VerifyError for uninitialized this
super(OUTER_CONSTANT)
}
- String m() {
- OUTER_CONSTANT
+
+ String access() {
+ return OUTER_CONSTANT
}
}
- void testInnerClassAccessOuter() {
- def inner = new InnerClass()
- inner.m()
+ void testInnerClassAccessOuterConst() {
+ def inner = new Inner()
+ inner.access()
}
}
- new InnerAccessOuter().testInnerClassAccessOuter()
+
+ def outer = new Outer()
+ outer.testInnerClassAccessOuterConst()
'''
- }*/
+ }
@Test
void testUsageOfOuterFieldOverridden() {