Skip to content

Commit

Permalink
GROOVY-11362: classgen: catch parameter is Exception for catch (e) {
Browse files Browse the repository at this point in the history
3_0_X backport
  • Loading branch information
eric-milles committed Apr 21, 2024
1 parent c917668 commit fbfdb6c
Show file tree
Hide file tree
Showing 2 changed files with 48 additions and 12 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,6 @@
import org.codehaus.groovy.ast.ClassHelper;
import org.codehaus.groovy.ast.ClassNode;
import org.codehaus.groovy.ast.MethodNode;
import org.codehaus.groovy.ast.Parameter;
import org.codehaus.groovy.ast.expr.ArgumentListExpression;
import org.codehaus.groovy.ast.expr.BooleanExpression;
import org.codehaus.groovy.ast.expr.ClosureListExpression;
Expand Down Expand Up @@ -299,12 +298,11 @@ public void writeDoWhileLoop(final DoWhileStatement statement) {
controller.getAcg().onLineNumber(statement, "visitDoWhileLoop");
writeStatementLabel(statement);

MethodVisitor mv = controller.getMethodVisitor();

controller.getCompileStack().pushLoop(statement.getStatementLabels());
Label continueLabel = controller.getCompileStack().getContinueLabel();
Label breakLabel = controller.getCompileStack().getBreakLabel();

MethodVisitor mv = controller.getMethodVisitor();
mv.visitLabel(continueLabel);

statement.getLoopBlock().visit(controller.getAcg());
Expand Down Expand Up @@ -363,29 +361,26 @@ public void writeTryCatchFinally(final TryCatchStatement statement) {
Label tryEnd = new Label();
mv.visitLabel(tryEnd);
tryBlock.closeRange(tryEnd);
// pop for "makeBlockRecorder(finallyStatement)"
controller.getCompileStack().pop();
// pop for BlockRecorder
compileStack.pop();

BlockRecorder catches = makeBlockRecorder(finallyStatement);
for (CatchStatement catchStatement : statement.getCatchStatements()) {
ClassNode exceptionType = catchStatement.getExceptionType();
String exceptionTypeInternalName = BytecodeHelper.getClassInternalName(exceptionType);

// start catch block, label needed for exception table
Label catchStart = new Label();
mv.visitLabel(catchStart);
catches.startRange(catchStart);

// create exception variable and store the exception
Parameter exceptionVariable = catchStatement.getVariable();
compileStack.pushState();
compileStack.defineVariable(exceptionVariable, true);
ClassNode type = catchStatement.getExceptionType();
compileStack.defineVariable(catchStatement.getVariable(), type, true);
// handle catch body
catchStatement.visit(controller.getAcg());
// place holder to avoid problems with empty catch blocks
mv.visitInsn(NOP);
// pop for the variable
controller.getCompileStack().pop();
compileStack.pop();

// end of catch
Label catchEnd = new Label();
Expand All @@ -394,7 +389,9 @@ public void writeTryCatchFinally(final TryCatchStatement statement) {

// goto finally start
mv.visitJumpInsn(GOTO, finallyStart);
compileStack.writeExceptionTable(tryBlock, catchStart, exceptionTypeInternalName);

String typeName = BytecodeHelper.getClassInternalName(type);
compileStack.writeExceptionTable(tryBlock, catchStart, typeName);
}

// used to handle exceptions in catches and regularly visited finals
Expand Down
39 changes: 39 additions & 0 deletions src/test/groovy/bugs/Groovy11362.groovy
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/
package groovy.bugs

import org.codehaus.groovy.classgen.asm.AbstractBytecodeTestCase

final class Groovy11362 extends AbstractBytecodeTestCase {

void testCatchException() {
def bytecode = compile method:'test', '''
void test() {
try {
print 'f'
} catch (e) {
}
}
'''
assert bytecode.hasSequence([
'LOCALVARIABLE this Lscript;',
'LOCALVARIABLE e Ljava/lang/Exception;' // not Ljava/lang/Object;
])
}
}

0 comments on commit fbfdb6c

Please sign in to comment.