Skip to content

Commit

Permalink
GROOVY-11485: default constructor: error for super constructor not found
Browse files Browse the repository at this point in the history
  • Loading branch information
eric-milles committed Sep 27, 2024
1 parent cd9377f commit a98c525
Show file tree
Hide file tree
Showing 4 changed files with 163 additions and 72 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,7 @@
import org.objectweb.asm.MethodVisitor;

import java.util.List;
import java.util.StringJoiner;
import java.util.function.BiConsumer;

import static org.apache.groovy.ast.tools.AnnotatedNodeUtils.hasAnnotation;
Expand Down Expand Up @@ -394,6 +395,15 @@ private void addThisReference(ConstructorNode node) {
addFieldInit(thisZero, thisField, newCode);
ConstructorCallExpression cce = getFirstIfSpecialConstructorCall(block);
if (cce == null) {
ClassNode superClass = classNode.getSuperClass();
Parameter[] implicit = Parameter.EMPTY_ARRAY; // signature of the super class constuctor
if (superClass.getOuterClass() != null && (superClass.getModifiers() & ACC_STATIC) == 0)
implicit = new Parameter[]{new Parameter(superClass.getOuterClass(), "outerClass")};
if (superClass.getDeclaredConstructor(implicit) == null && !superClass.getDeclaredConstructors().isEmpty()) { // GROOVY-11485
var joiner = new StringJoiner(", ", superClass.getNameWithoutPackage() + "(", ")");
for (var parameter : implicit) joiner.add(parameter.getType().getNameWithoutPackage());
addError("An explicit constructor is required because the implicit super constructor " + joiner.toString() + " is undefined", classNode);
}
cce = ctorSuperX(new TupleExpression());
block.getStatements().add(0, stmt(cce));
}
Expand All @@ -414,17 +424,18 @@ private void addThisReference(ConstructorNode node) {

private boolean shouldImplicitlyPassThisZero(ConstructorCallExpression cce) {
boolean pass = false;
ClassNode superCN = classNode.getSuperClass();
if (cce.isThisCall()) {
pass = true;
} else if (cce.isSuperCall()) {
// if the super class is another non-static inner class in the same outer class hierarchy, implicit this
// needs to be passed
if (!superCN.isEnum() && !superCN.isInterface() && superCN instanceof InnerClassNode) {
InnerClassNode superInnerCN = (InnerClassNode) superCN;
if (!isStatic(superInnerCN) && classNode.getOuterClass().isDerivedFrom(superCN.getOuterClass())) {
pass = true;
}
// if the super class is another non-static inner class in the same
// outer class hierarchy, implicit this needs to be passed
ClassNode superClass = classNode.getSuperClass();
if (!superClass.isEnum()
&& !superClass.isInterface()
&& superClass instanceof InnerClassNode
&& !isStatic((InnerClassNode) superClass)
&& classNode.getOuterClass().isDerivedFrom(superClass.getOuterClass())) {
pass = true;
}
}
return pass;
Expand Down
3 changes: 1 addition & 2 deletions src/main/java/org/codehaus/groovy/vmplugin/v8/Selector.java
Original file line number Diff line number Diff line change
Expand Up @@ -96,7 +96,6 @@
import static org.codehaus.groovy.vmplugin.v8.IndyInterface.CallType;
import static org.codehaus.groovy.vmplugin.v8.IndyInterface.LOG;
import static org.codehaus.groovy.vmplugin.v8.IndyInterface.LOG_ENABLED;
import static org.codehaus.groovy.vmplugin.v8.IndyInterface.LOOKUP;
import static org.codehaus.groovy.vmplugin.v8.IndyInterface.switchPoint;

public abstract class Selector {
Expand Down Expand Up @@ -436,7 +435,7 @@ public void setHandleForMetaMethod() {
isVargs = mc.isVargsMethod();
Constructor<?> con = mc.getCachedConstrcutor().getCachedConstructor();
try {
handle = LOOKUP.unreflectConstructor(con);
handle = this.callSite.getLookup().unreflectConstructor(con);
if (LOG_ENABLED) LOG.info("successfully unreflected constructor");
} catch (IllegalAccessException e) {
throw new GroovyBugError(e);
Expand Down
Loading

0 comments on commit a98c525

Please # to comment.