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 2022/11/06 17:36:09 UTC

[groovy] branch GROOVY_4_0_X updated: GROOVY-9857: error for implicit `super()` without matching constructor

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

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


The following commit(s) were added to refs/heads/GROOVY_4_0_X by this push:
     new 67a694c2a8 GROOVY-9857: error for implicit `super()` without matching constructor
67a694c2a8 is described below

commit 67a694c2a8c6507b5e9ad44ac0410f004a22886a
Author: Eric Milles <er...@thomsonreuters.com>
AuthorDate: Sun Nov 6 10:58:42 2022 -0600

    GROOVY-9857: error for implicit `super()` without matching constructor
---
 .../groovy/classgen/AsmClassGenerator.java         | 12 ++++++++++-
 .../invocation/ConstructorDelegationTest.groovy    | 24 ++++++++++++++++++++++
 .../groovy/text/markup/TemplateASTTransformer.java |  1 +
 3 files changed, 36 insertions(+), 1 deletion(-)

diff --git a/src/main/java/org/codehaus/groovy/classgen/AsmClassGenerator.java b/src/main/java/org/codehaus/groovy/classgen/AsmClassGenerator.java
index 5d5c35c1cf..2999348420 100644
--- a/src/main/java/org/codehaus/groovy/classgen/AsmClassGenerator.java
+++ b/src/main/java/org/codehaus/groovy/classgen/AsmClassGenerator.java
@@ -575,10 +575,11 @@ public class AsmClassGenerator extends ClassGenerator {
         controller.getCompileStack().init(node.getVariableScope(), parameters);
         controller.getCallSiteWriter().makeSiteEntry();
 
+        ClassNode cn = controller.getClassNode();
         MethodVisitor mv = controller.getMethodVisitor();
         if (isConstructor && (code == null || !((ConstructorNode) node).firstStatementIsSpecialConstructorCall())) {
             boolean hasCallToSuper = false;
-            if (code != null && controller.getClassNode().getOuterClass() != null) {
+            if (code != null && cn.getOuterClass() != null) {
                 // GROOVY-4471: if the class is an inner class node, there are chances that
                 // the call to super is already added so we must ensure not to add it twice
                 if (code instanceof BlockStatement) {
@@ -591,6 +592,15 @@ public class AsmClassGenerator extends ClassGenerator {
                 if (code != null) { // GROOVY-9373
                     controller.visitLineNumber(code.getLineNumber());
                 }
+                if (cn.getSuperClass().getDeclaredConstructor(Parameter.EMPTY_ARRAY) == null) { ASTNode where = node; // GROOVY-9857
+                    String error = "Implicit super constructor " + cn.getSuperClass().getNameWithoutPackage() + "() is undefined";
+                    if (node.getLineNumber() > 0) error += ". Must explicitly invoke another constructor.";
+                    else {
+                        error += " for generated constructor. Must define an explicit constructor.";
+                        where = cn;
+                    }
+                    addError(error, where);
+                }
                 // add call to "super()"
                 mv.visitVarInsn(ALOAD, 0);
                 mv.visitMethodInsn(INVOKESPECIAL, controller.getInternalBaseClassName(), "<init>", "()V", false);
diff --git a/src/test/gls/invocation/ConstructorDelegationTest.groovy b/src/test/gls/invocation/ConstructorDelegationTest.groovy
index 496e222f6a..1334b8599e 100644
--- a/src/test/gls/invocation/ConstructorDelegationTest.groovy
+++ b/src/test/gls/invocation/ConstructorDelegationTest.groovy
@@ -81,6 +81,30 @@ final class ConstructorDelegationTest {
         '''
     }
 
+    @Test // GROOVY-9857
+    void testImplicitSuperConstructorCallChecks() {
+        String base = '''
+            abstract class A {
+                A(boolean b) {
+                }
+            }
+        '''
+
+        def err = shouldFail CompilationFailedException, base + '''
+            class C extends A {
+                C() {
+                }
+            }
+        '''
+        assert err =~ /Implicit super constructor A\(\) is undefined. Must explicitly invoke another constructor./
+
+        err = shouldFail CompilationFailedException, base + '''
+            class C extends A {
+            }
+        '''
+        assert err =~ /Implicit super constructor A\(\) is undefined for generated constructor. Must define an explicit constructor./
+    }
+
     @Test
     void testConstructorDelegationWithThisOrSuperInArgs() {
         // all 4 cases below were compiling earlier but giving VerifyError at runtime
diff --git a/subprojects/groovy-templates/src/main/groovy/groovy/text/markup/TemplateASTTransformer.java b/subprojects/groovy-templates/src/main/groovy/groovy/text/markup/TemplateASTTransformer.java
index 1d2135272c..a022a860a5 100644
--- a/subprojects/groovy-templates/src/main/groovy/groovy/text/markup/TemplateASTTransformer.java
+++ b/subprojects/groovy-templates/src/main/groovy/groovy/text/markup/TemplateASTTransformer.java
@@ -65,6 +65,7 @@ class TemplateASTTransformer extends CompilationCustomizer {
     public void call(final SourceUnit source, final GeneratorContext context, final ClassNode classNode) throws CompilationFailedException {
         if (classNode.isScriptBody()) {
             classNode.setSuperClass(ClassHelper.make(config.getBaseTemplateClass()));
+            classNode.getDeclaredConstructors().clear();
             createConstructor(classNode);
             transformRunMethod(classNode, source);
             VariableScopeVisitor visitor = new VariableScopeVisitor(source);