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 2021/11/26 21:04:01 UTC

[groovy] branch master updated: GROOVY-8693: SC - override default method: no `super.m()` stack overflow

This is an automated email from the ASF dual-hosted git repository.

emilles pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/groovy.git


The following commit(s) were added to refs/heads/master by this push:
     new 538374a  GROOVY-8693: SC - override default method: no `super.m()` stack overflow
538374a is described below

commit 538374a1799947912496bf3a9aa8590cf5e38a75
Author: Eric Milles <er...@thomsonreuters.com>
AuthorDate: Fri Nov 26 14:44:25 2021 -0600

    GROOVY-8693: SC - override default method: no `super.m()` stack overflow
---
 .../codehaus/groovy/classgen/asm/InvocationWriter.java   | 10 ++++++----
 .../groovy/classgen/asm/sc/BugsStaticCompileTest.groovy  | 16 ++++++++++++++++
 2 files changed, 22 insertions(+), 4 deletions(-)

diff --git a/src/main/java/org/codehaus/groovy/classgen/asm/InvocationWriter.java b/src/main/java/org/codehaus/groovy/classgen/asm/InvocationWriter.java
index c7786c5..c8af4b5 100644
--- a/src/main/java/org/codehaus/groovy/classgen/asm/InvocationWriter.java
+++ b/src/main/java/org/codehaus/groovy/classgen/asm/InvocationWriter.java
@@ -168,16 +168,18 @@ public class InvocationWriter {
         int opcode;
         if (target.isStatic()) {
             opcode = INVOKESTATIC;
+        } else if (isSuperExpression(receiver)) {
+            opcode = INVOKESPECIAL;
         } else if (declaringClass.isInterface()) {
             opcode = INVOKEINTERFACE;
-        } else if (target.isPrivate() || isSuperExpression(receiver)) {
-            opcode = INVOKESPECIAL;
         } else {
             opcode = INVOKEVIRTUAL;
         }
 
         ClassNode ownerClass = declaringClass;
-        if (opcode == INVOKEVIRTUAL && isObjectType(declaringClass)) {
+        if (opcode == INVOKESPECIAL) {
+            ownerClass = receiverType; // GROOVY-8693
+        } else if (opcode == INVOKEVIRTUAL && isObjectType(declaringClass)) {
             // avoid using a narrowed type if the method is defined on Object, because it can interfere
             // with delegate type inference in static compilation mode and trigger a ClassCastException
         } else if (opcode == INVOKEVIRTUAL
@@ -190,7 +192,7 @@ public class InvocationWriter {
             if (!receiverType.equals(operandStack.getTopOperand())) {
                 mv.visitTypeInsn(CHECKCAST, BytecodeHelper.getClassInternalName(ownerClass));
             }
-        } else if (opcode != INVOKESPECIAL && (declaringClass.getModifiers() & (ACC_FINAL | ACC_PUBLIC)) == 0 && !receiverType.equals(declaringClass)
+        } else if ((declaringClass.getModifiers() & (ACC_FINAL | ACC_PUBLIC)) == 0 && !receiverType.equals(declaringClass)
                 && (declaringClass.isInterface() ? receiverType.implementsInterface(declaringClass) : receiverType.isDerivedFrom(declaringClass))) {
             // GROOVY-6962, GROOVY-9955, GROOVY-10380: method declared by inaccessible class or interface
             if (declaringClass.isInterface() && !receiverType.isInterface()) opcode = INVOKEVIRTUAL;
diff --git a/src/test/org/codehaus/groovy/classgen/asm/sc/BugsStaticCompileTest.groovy b/src/test/org/codehaus/groovy/classgen/asm/sc/BugsStaticCompileTest.groovy
index 5576b16..77abc66 100644
--- a/src/test/org/codehaus/groovy/classgen/asm/sc/BugsStaticCompileTest.groovy
+++ b/src/test/org/codehaus/groovy/classgen/asm/sc/BugsStaticCompileTest.groovy
@@ -1524,4 +1524,20 @@ println someInt
             test()
         '''
     }
+
+    // GROOVY-8693
+    void testInvokeDefaultMethodFromPackagePrivateInterface2() {
+        assertScript '''
+            class C extends groovy.transform.stc.Groovy10380 {
+                @Override String m() {
+                    super.m() // default method
+                }
+                void test() {
+                    String result = this.m()
+                    assert result == 'works'
+                }
+            }
+            new C().test()
+        '''
+    }
 }