You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@groovy.apache.org by su...@apache.org on 2019/11/22 15:33:52 UTC
[groovy] 01/02: GROOVY-9126: Unreachable line numbers after ARETURN
in bytecode (#1095)
This is an automated email from the ASF dual-hosted git repository.
sunlan pushed a commit to branch GROOVY_2_5_X
in repository https://gitbox.apache.org/repos/asf/groovy.git
commit b4d42b146fb348fae454e39289057e0a350a15df
Author: Daniel.Sun <su...@apache.org>
AuthorDate: Thu Nov 21 15:44:47 2019 +0800
GROOVY-9126: Unreachable line numbers after ARETURN in bytecode (#1095)
(cherry picked from commit ecb6c331edf08a0b41ac3ff4b63aae99b85a4b76)
---
.../groovy/classgen/asm/StatementWriter.java | 23 +++++++++-
src/test/groovy/bugs/Groovy9126.groovy | 51 ++++++++++++++++++++++
2 files changed, 72 insertions(+), 2 deletions(-)
diff --git a/src/main/java/org/codehaus/groovy/classgen/asm/StatementWriter.java b/src/main/java/org/codehaus/groovy/classgen/asm/StatementWriter.java
index 4872e4f..c2bff8c 100644
--- a/src/main/java/org/codehaus/groovy/classgen/asm/StatementWriter.java
+++ b/src/main/java/org/codehaus/groovy/classgen/asm/StatementWriter.java
@@ -20,6 +20,7 @@ package org.codehaus.groovy.classgen.asm;
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;
@@ -88,13 +89,16 @@ public class StatementWriter {
int mark = controller.getOperandStack().getStackLength();
CompileStack compileStack = controller.getCompileStack();
compileStack.pushVariableScope(block.getVariableScope());
- for (Statement statement : block.getStatements()) {
+ List<Statement> statementList = block.getStatements();
+ for (Statement statement : statementList) {
statement.visit(controller.getAcg());
}
compileStack.pop();
// GROOVY-7647
- if (block.getLastLineNumber() > 0) {
+ if (block.getLastLineNumber() > 0
+ && !methodOrConstructorsLastReturnStatementExists(block) // GROOVY-9126
+ ) {
MethodVisitor mv = controller.getMethodVisitor();
Label blockEnd = new Label();
mv.visitLabel(blockEnd);
@@ -104,6 +108,21 @@ public class StatementWriter {
controller.getOperandStack().popDownTo(mark);
}
+ private boolean methodOrConstructorsLastReturnStatementExists(BlockStatement block) {
+ MethodNode methodNode = controller.getMethodNode();
+ if (null == methodNode) {
+ methodNode = controller.getConstructorNode();
+ }
+
+ if (null == methodNode || block != methodNode.getCode()) { // check if the block is method/constructor's code
+ return false;
+ }
+
+ List<Statement> statementList = block.getStatements();
+ final int size = statementList.size();
+ return size > 0 && statementList.get(size - 1) instanceof ReturnStatement;
+ }
+
public void writeForStatement(ForStatement loop) {
Parameter loopVar = loop.getVariable();
if (loopVar == ForStatement.FOR_LOOP_DUMMY) {
diff --git a/src/test/groovy/bugs/Groovy9126.groovy b/src/test/groovy/bugs/Groovy9126.groovy
new file mode 100644
index 0000000..3df9633
--- /dev/null
+++ b/src/test/groovy/bugs/Groovy9126.groovy
@@ -0,0 +1,51 @@
+/*
+ * 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 groovy.transform.CompileStatic
+import org.codehaus.groovy.classgen.asm.AbstractBytecodeTestCase
+import org.junit.Test
+
+import static groovy.test.GroovyAssert.assertScript
+
+@CompileStatic
+final class Groovy9126 extends AbstractBytecodeTestCase {
+
+ @Test
+ void testUnreachableBytecode() {
+ def bytecode = compile([method:'nonVoidMethod'],'''
+ @groovy.transform.CompileStatic
+ int nonVoidMethod() {
+ 1 * 1
+ }
+ ''')
+
+ assert bytecode.hasStrictSequence(
+ ['public nonVoidMethod()I',
+ 'L0',
+ 'LINENUMBER 4 L0',
+ 'ICONST_1',
+ 'ICONST_1',
+ 'IMUL',
+ 'IRETURN',
+ 'L1',
+ 'FRAME FULL [] [java/lang/Throwable]']
+ )
+ }
+}