/* TryBlock Copyright (C) 1998-1999 Jochen Hoenicke. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2, or (at your option) * any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; see the file COPYING. If not, write to * the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. * * $Id$ */ package net.sf.jode.flow; import net.sf.jode.decompiler.TabbedPrintWriter; import net.sf.jode.type.*; import net.sf.jode.expr.Expression; import net.sf.jode.expr.InvokeOperator; import net.sf.jode.expr.LocalLoadOperator; /** * A TryBlock is created for each exception in the * ExceptionHandlers attribute.
* * For each catch block (there may be more than one catch block * appending a single try block) and for each finally and each * synchronized block such a TryBlock is created. The * finally/synchronized-blocks have a null exception type so that they * are easily distinguishable from the catch blocks.
* * A TryBlock may be converted later into a SynchronizedBlock. * * @date 1998/09/16 * @author Jochen Hoenicke * @see CatchBlock * @see FinallyBlock * @see SynchronizedBlock */ public class TryBlock extends StructuredBlock { VariableSet gen; StructuredBlock[] subBlocks = new StructuredBlock[1]; public TryBlock(FlowBlock tryFlow) { this.gen = (VariableSet) tryFlow.used.clone(); this.flowBlock = tryFlow; StructuredBlock bodyBlock = tryFlow.block; replace(bodyBlock); this.subBlocks = new StructuredBlock[] { bodyBlock }; bodyBlock.outer = this; tryFlow.lastModified = this; tryFlow.checkConsistent(); } public void addCatchBlock(StructuredBlock catchBlock) { StructuredBlock[] newSubBlocks = new StructuredBlock[subBlocks.length+1]; System.arraycopy(subBlocks, 0, newSubBlocks, 0, subBlocks.length); newSubBlocks[subBlocks.length] = catchBlock; subBlocks = newSubBlocks; catchBlock.outer = this; catchBlock.setFlowBlock(flowBlock); } /** * Replaces the given sub block with a new block. * @param oldBlock the old sub block. * @param newBlock the new sub block. * @return false, if oldBlock wasn't a direct sub block. */ public boolean replaceSubBlock(StructuredBlock oldBlock, StructuredBlock newBlock) { for (int i=0; i * try { * PUSH ARRAY.clone() * } catch (CloneNotSupportedException ex) { * throw new InternalError(ex.getMessage()); * } * * which is simply transformed to the content of the try block. */ public boolean checkJikesArrayClone() { if (subBlocks.length != 2 || !(subBlocks[0] instanceof InstructionBlock) || !(subBlocks[1] instanceof CatchBlock)) return false; Expression instr = ((InstructionBlock)subBlocks[0]).getInstruction(); CatchBlock catchBlock = (CatchBlock) subBlocks[1]; if (instr.isVoid() || instr.getFreeOperandCount() != 0 || !(instr instanceof InvokeOperator) || !(catchBlock.catchBlock instanceof ThrowBlock) || !(((ClassType) catchBlock.exceptionType).getClassName().equals ("java.lang.CloneNotSupportedException"))) return false; InvokeOperator arrayClone = (InvokeOperator) instr; if (!arrayClone.getMethodName().equals("clone") || arrayClone.isStatic() || !(arrayClone.getMethodType().getTypeSignature() .equals("()Ljava/lang/Object;")) || !(arrayClone.getSubExpressions()[0] .getType().isOfType(Type.tArray(Type.tUnknown)))) return false; Expression throwExpr = ((ThrowBlock) catchBlock.catchBlock).getInstruction(); if (throwExpr.getFreeOperandCount() != 0 || !(throwExpr instanceof InvokeOperator)) return false; InvokeOperator throwOp = (InvokeOperator) throwExpr; if (!throwOp.isConstructor() || !(throwOp.getClassType() instanceof ClassType) || !(((ClassType) throwOp.getClassType()).getClassName() .equals("java.lang.InternalError")) || throwOp.getMethodType().getParameterTypes().length != 1) return false; Expression getMethodExpr = throwOp.getSubExpressions()[1]; if (!(getMethodExpr instanceof InvokeOperator)) return false; InvokeOperator invoke = (InvokeOperator) getMethodExpr; if (!invoke.getMethodName().equals("getMessage") || invoke.isStatic() || (invoke.getMethodType().getParameterTypes() .length != 0) || (invoke.getMethodType().getReturnType() != Type.tString)) return false; Expression exceptExpr = invoke.getSubExpressions()[0]; if (!(exceptExpr instanceof LocalLoadOperator) || !(((LocalLoadOperator) exceptExpr).getLocalInfo() .equals(catchBlock.exceptionLocal))) return false; subBlocks[0].replace(this); if (flowBlock.lastModified == this) flowBlock.lastModified = subBlocks[0]; return true; } public boolean doTransformations() { return checkJikesArrayClone(); } }