Fixed Java-1.1 and finally/synchronized blocks.

git-svn-id: https://svn.code.sf.net/p/jode/code/branches/branch_1_1@1343 379699f6-c40d-0410-875b-85095c16579e
branch_1_1
hoenicke 24 years ago
parent c79f6122f5
commit 03497ae1a2
  1. 35
      jode/ChangeLog
  2. 5
      jode/jode/flow/FlowBlock.java.in
  3. 415
      jode/jode/flow/TransformExceptionHandlers.java.in

@ -1,3 +1,35 @@
2001-08-12 Jochen Hoenicke <jochen@gnu.org>
* jode/flow/FlowBlock.java.in:
(checkConsistent): Allow lastModified in a finally block.
* jode/flow/TransformExceptionHandlers.java.in: Reworked exception
handlers again. This time checked with javac 1.3, javac 1.1 and
jikes.
(checkTryCatchOrder): New method that was previously part of
analyze.
(analyze): Use checkTryCatchOrder. Don't merge try and catch flow
blocks anymore, leave it to the analyzeXXX methods.
(mergeTryCatch): New method.
(analyzeCatchBlock): Get catchFlow as parameter. Call
mergeTryCatch.
(transformSubroutine): Handle POP-only subroutines.
(removeJSR): Don't do special case for catchBlock any more. This
is because catchFlow isn't yet merged when this method is called.
(checkAndRemoveJSR): Likewise.
(checkAndRemoveMonitorExit): Likewise. Merge subroutine only if
we are the only predecessor.
(analyzeSynchronized): Get catchFlow as parameter. Call
mergeTryCatch.
(mergeFinallyBlocks): New method, calls mergeTryCatch and does the
common part of mergeFinally and mergeSpecialFinally.
(analyzeFinally): Simplified, after checking and removing JSR, it
does immediately analyze and transform subroutine to get the
finallyBlock. Then it throws away the catchFlow and calls
mergeFinallyBlocks.
(analyzeSpecialFinally): Simplified, after checking it only handles
the jumps in the try part and then call mergeFinallyBlocks.
2001-08-10 Jochen Hoenicke <jochen@gnu.org>
* configure.in: Changed bash syntax to more compatible (but
@ -32,8 +64,7 @@
2001-07-08 Jochen Hoenicke <jochen@gnu.org>
* jode/bytecode/BytecodeInfo.java.in (calculateMaxStack): Handle
special case for empty method. Previous code would just crash.
* jode/bytecode/BytecodeInfo.java.in (calculateMaxStack): Handle special case for empty method. Previous code would just crash.
2001-06-15 Jochen Hoenicke <jochen@gnu.org>

@ -1,4 +1,4 @@
/* FlowBlock Copyright (C) 1998-1999 Jochen Hoenicke.
/* FlowBlock Copyright (C) 1998-2001 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
@ -748,7 +748,8 @@ public class FlowBlock {
StructuredBlock last = lastModified;
while (last.outer instanceof SequentialBlock
|| last.outer instanceof TryBlock)
|| last.outer instanceof TryBlock
|| last.outer instanceof FinallyBlock)
last = last.outer;
if (last.outer != null)
throw new AssertError("Inconsistency");

@ -99,35 +99,63 @@ public class TransformExceptionHandlers {
}
/* simple try catch block:
/**
* Merge the try flow block with the catch flow block. This is a kind
* of special T2 transformation, as all jumps to the catch block are
* implicit (exception can be thrown everywhere). <br>
*
* try-header
* |- first instruction
* | ...
* | last instruction
* |- optional jump (last+1)
* | ...
* `- catch block
* This method doesn't actually merge the contents of the blocks. The
* caller should do it right afterwards. <br>
*
* The flow block catchFlow mustn't have any predecessors.
* @param tryFlow the flow block containing the try.
* @param catchFlow the flow block containing the catch handler.
*/
static void mergeTryCatch(FlowBlock tryFlow, FlowBlock catchFlow) {
if ((GlobalOptions.debuggingFlags
& GlobalOptions.DEBUG_ANALYZE) != 0)
GlobalOptions.err.println
("mergeTryCatch(" + tryFlow.getAddr()
+ ", " + catchFlow.getAddr() + ")");
tryFlow.updateInOutCatch(catchFlow);
tryFlow.mergeSuccessors(catchFlow);
tryFlow.mergeAddr(catchFlow);
}
/**
* Analyzes a simple try/catch block. The try and catch part are both
* analyzed, the try block is already created, but the catch block
* isn't. <br>
* The catchFlow block mustn't have any predecessors.
*
* @param type The type of the exception which is caught.
* @param tryFlow The flow block containing the try. The contained
* block must be a try block.
* @param catchFlow the flow block containing the catch handler.
*/
static void analyzeCatchBlock(Type type, FlowBlock tryFlow,
StructuredBlock catchBlock) {
FlowBlock catchFlow) {
/* Merge try and catch flow blocks */
mergeTryCatch(tryFlow, catchFlow);
/* Insert catch block into tryFlow */
CatchBlock newBlock = new CatchBlock(type);
((TryBlock)tryFlow.block).addCatchBlock(newBlock);
newBlock.setCatchBlock(catchBlock);
newBlock.setCatchBlock(catchFlow.block);
}
/* And now the complicated parts. */
/**
* This transforms a sub routine, that is checks if the beginning
* local assignment matches the final ret and then returns.
* This transforms a sub routine, i.e. it checks if the beginning
* local assignment matches the final ret and removes both. It also
* accepts sub routines that just pop their return address.
*/
boolean transformSubRoutine(StructuredBlock subRoutine) {
if (!(subRoutine instanceof SequentialBlock))
return false;
SequentialBlock sequBlock = (SequentialBlock) subRoutine;
StructuredBlock firstBlock = sequBlock.getSubBlocks()[0];
boolean transformSubRoutine(StructuredBlock subRoutineBlock) {
StructuredBlock firstBlock = subRoutineBlock;
if (firstBlock instanceof SequentialBlock)
firstBlock = subRoutineBlock.getSubBlocks()[0];
LocalInfo local = null;
if (firstBlock instanceof SpecialBlock) {
@ -152,24 +180,25 @@ public class TransformExceptionHandlers {
} else
return false;
/* We have now committed. Remove the first Statement which
* stores/removes the return address.
/* We are now committed and can start changing code. Remove
* the first Statement which stores/removes the return
* address.
*/
firstBlock.removeBlock();
/* XXX - Replace any RET with a jump to end of this flow block.
/* We don't check if there is a RET in the middle.
*
* This is a complicated task which isn't needed for javac nor
* jikes. We just check if the last instruction is a ret and
* replace this. This will never produce code with wrong semantic,
* remove this. This will never produce code with wrong semantic,
* as long as the bytecode was verified correctly.
*/
while (sequBlock.subBlocks[1] instanceof SequentialBlock)
sequBlock = (SequentialBlock) sequBlock.subBlocks[1];
while (subRoutineBlock instanceof SequentialBlock)
subRoutineBlock = subRoutineBlock.getSubBlocks()[1];
if (sequBlock.subBlocks[1] instanceof RetBlock
&& (((RetBlock) sequBlock.subBlocks[1]).local.equals(local))) {
sequBlock.subBlocks[1].removeBlock();
if (subRoutineBlock instanceof RetBlock
&& (((RetBlock) subRoutineBlock).local.equals(local))) {
subRoutineBlock.removeBlock();
}
return true;
}
@ -199,51 +228,32 @@ public class TransformExceptionHandlers {
}
/**
* Remove the wrongly placed JSRs jumping to the specified
* subRoutine. The right JSRs are already removed, but we have to
* replace the wrong ones with a warning.
* @param tryFlow the FlowBLock of the try block.
* Remove the JSRs jumping to the specified subRoutine. The right
* JSRs are marked and we can just remove them. For the other JSR
* instructions we replace them with a warning.
* @param tryFlow the FlowBlock of the try block.
* @param subRoutine the FlowBlock of the sub routine.
*/
private void removeJSR(FlowBlock tryFlow, StructuredBlock catchBlock,
FlowBlock subRoutine) {
Jump nextJump;
for (Jump jumps = tryFlow.getJumps(subRoutine);
jumps != null; jumps = nextJump) {
private void removeJSR(FlowBlock tryFlow, FlowBlock subRoutine) {
for (Jump jumps = tryFlow.removeJumps(subRoutine);
jumps != null; jumps = jumps.next) {
StructuredBlock prev = jumps.prev;
nextJump = jumps.next;
if (prev instanceof EmptyBlock
&& prev.outer instanceof JsrBlock) {
JsrBlock jsr = (JsrBlock) prev.outer;
if (prev.outer == catchBlock) {
/* This is the mandatory jsr in the catch block */
continue;
}
tryFlow.removeSuccessor(jumps);
prev.removeJump();
if (jsr.isGood()) {
StructuredBlock next = jsr.getNextBlock();
jsr.removeBlock();
if (prev instanceof EmptyBlock
&& prev.outer instanceof JsrBlock
&& ((JsrBlock) prev.outer).isGood()) {
StructuredBlock next = prev.outer.getNextBlock();
prev.outer.removeBlock();
if (next instanceof ReturnBlock)
removeReturnLocal((ReturnBlock) next);
} else {
/* We have a JSR to the subroutine, which is badly placed.
* We complain here.
*/
DescriptionBlock msg
= new DescriptionBlock("ERROR: JSR FINALLY BLOCK!");
msg.replace(prev.outer);
}
} else {
/* We have a jump to the subroutine, that is wrong.
/* We have a jump to the subroutine, that is badly placed.
* We complain here.
*/
DescriptionBlock msg
= new DescriptionBlock("ERROR: GOTO FINALLY BLOCK!");
tryFlow.removeSuccessor(jumps);
prev.removeJump();
DescriptionBlock msg = new DescriptionBlock
("ERROR: invalid jump to finally block!");
prev.appendBlock(msg);
}
}
@ -309,7 +319,6 @@ public class TransformExceptionHandlers {
private void checkAndRemoveJSR(FlowBlock tryFlow,
StructuredBlock catchBlock,
FlowBlock subRoutine,
int startOutExit, int endOutExit) {
Iterator iter = tryFlow.getSuccessors().iterator();
@ -332,8 +341,8 @@ public class TransformExceptionHandlers {
}
if (prev instanceof EmptyBlock
&& prev.outer instanceof JsrBlock) {
/* This jump is really a jsr, since it doesn't
* leave the block forever, we can ignore it.
/* This jump is a jsr, since it doesn't leave the
* block forever, we can ignore it.
*/
continue;
}
@ -384,7 +393,7 @@ public class TransformExceptionHandlers {
* Complain!
*/
DescriptionBlock msg
= new DescriptionBlock("ERROR: NO JSR TO FINALLY");
= new DescriptionBlock("ERROR: no jsr to finally");
if (pred != null)
pred.prependBlock(msg);
else {
@ -394,11 +403,10 @@ public class TransformExceptionHandlers {
}
}
if (tryFlow.getSuccessors().contains(subRoutine))
removeJSR(tryFlow, catchBlock, subRoutine);
removeJSR(tryFlow, subRoutine);
}
private void checkAndRemoveMonitorExit(FlowBlock tryFlow,
StructuredBlock catchBlock,
LocalInfo local,
int start, int end) {
FlowBlock subRoutine = null;
@ -502,7 +510,7 @@ public class TransformExceptionHandlers {
/* Complain!
*/
DescriptionBlock msg
= new DescriptionBlock("ERROR: NO MONITOREXIT");
= new DescriptionBlock("ERROR: no monitorexit");
prev.appendBlock(msg);
msg.moveJump(jumps);
}
@ -510,7 +518,8 @@ public class TransformExceptionHandlers {
if (subRoutine != null) {
if (tryFlow.getSuccessors().contains(subRoutine))
removeJSR(tryFlow, catchBlock, subRoutine);
removeJSR(tryFlow, subRoutine);
if (subRoutine.predecessors.size() == 0)
tryFlow.mergeAddr(subRoutine);
}
}
@ -534,20 +543,25 @@ public class TransformExceptionHandlers {
}
private boolean analyzeSynchronized(FlowBlock tryFlow,
StructuredBlock catchBlock,
FlowBlock catchFlow,
int endHandler) {
/* Check if this is a synchronized block. We mustn't change
* anything until we are sure.
*/
StructuredBlock catchBlock = catchFlow.block;
/* Check for a optional exception store and skip it */
StoreInstruction excStore = getExceptionStore(catchBlock);
if (excStore != null)
catchBlock = catchBlock.getSubBlocks()[1];
/* Check for the monitorexit instruction */
if (!(catchBlock instanceof SequentialBlock
&& catchBlock.getSubBlocks()[0]
instanceof InstructionBlock))
return false;
Expression instr =
((InstructionBlock)catchBlock.getSubBlocks()[0]).getInstruction();
if (!(instr instanceof MonitorExitOperator
&& instr.getFreeOperandCount() == 0
&& (((MonitorExitOperator)instr).getSubExpressions()[0]
@ -592,6 +606,16 @@ public class TransformExceptionHandlers {
* return_n
*/
/* Merge try and catch flow blocks. No need to insert the
* catchFlow.block into the try flow though, since all its
* instruction are synthetic.
*
* Though we need to remove the jump of the throw
* instruction.
*/
catchFlow.removeSuccessor(catchBlock.getSubBlocks()[1].jump);
mergeTryCatch(tryFlow, catchFlow);
MonitorExitOperator monexit = (MonitorExitOperator)
((InstructionBlock) catchBlock.getSubBlocks()[0]).instr;
LocalInfo local =
@ -605,7 +629,7 @@ public class TransformExceptionHandlers {
+ "," + tryFlow.getNextAddr() + "," + endHandler + ")");
checkAndRemoveMonitorExit
(tryFlow, catchBlock, local, tryFlow.getNextAddr(), endHandler);
(tryFlow, local, tryFlow.getNextAddr(), endHandler);
SynchronizedBlock syncBlock = new SynchronizedBlock(local);
TryBlock tryBlock = (TryBlock) tryFlow.block;
@ -617,8 +641,41 @@ public class TransformExceptionHandlers {
return true;
}
/**
* Merge try and finally flow blocks.
* @param tryFlow The try flow block. Its contained block must be
* a try block.
* @param catchFlow The catch flow block that contains the finally
* block.
* @param finallyBlock block that either contains the finally block.
* It is part of the catchFlow. The other parts of catchFlow are
* synthetic and can be removed.
*/
private void mergeFinallyBlock(FlowBlock tryFlow, FlowBlock catchFlow,
StructuredBlock finallyBlock) {
TryBlock tryBlock = (TryBlock) tryFlow.block;
if (tryBlock.getSubBlocks()[0] instanceof TryBlock) {
/* A try { try { } catch {} } finally{} is equivalent
* to a try {} catch {} finally {}
* so remove the surrounding tryBlock.
*/
TryBlock innerTry = (TryBlock)tryBlock.getSubBlocks()[0];
innerTry.gen = tryBlock.gen;
innerTry.replace(tryBlock);
tryBlock = innerTry;
tryFlow.lastModified = tryBlock;
tryFlow.block = tryBlock;
}
/* Now merge try and catch flow blocks */
mergeTryCatch(tryFlow, catchFlow);
FinallyBlock newBlock = new FinallyBlock();
newBlock.setCatchBlock(finallyBlock);
tryBlock.addCatchBlock(newBlock);
}
private boolean analyzeFinally(FlowBlock tryFlow,
StructuredBlock catchBlock, int end) {
FlowBlock catchFlow, int end) {
/* Layout of a try-finally block:
*
@ -640,6 +697,7 @@ public class TransformExceptionHandlers {
* return_n
*/
StructuredBlock catchBlock = catchFlow.block;
StoreInstruction excStore = getExceptionStore(catchBlock);
if (excStore == null)
return false;
@ -651,9 +709,10 @@ public class TransformExceptionHandlers {
StructuredBlock finallyBlock = null;
if (catchBlock.getSubBlocks()[0] instanceof LoopBlock) {
/* In case the try block has no exit (that means, it throws
* an exception), the finallyBlock was already merged with
* the catchBlock. We have to check for this case separately:
/* In case the try block has no exit (that means, it
* throws an exception or loops forever), the finallyBlock
* was already merged with the catchBlock. We have to
* check for this case separately:
*
* do {
* JSR
@ -690,142 +749,151 @@ public class TransformExceptionHandlers {
FlowBlock subRoutine;
if (finallyBlock != null) {
/* Check if the jsr breaks (see two comments above). We don't
/* Check if the jsr breaks (see comment above). We don't
* need to check if it breaks to the right block, because
* we know that there is only one Block around the jsr.
*/
if (!(jsrBlock.innerBlock instanceof BreakBlock))
return false;
/* Check if the try block has no exit (except throws)
* XXX - Unfortunately the try block already has the
* successors of catch block.
/* TODO - Check if the try block has no exit (except throws)
*/
// if (tryFlow.getSuccessors() > 0)
// if (tryFlow.getSuccessors().size() > 0)
// return false;
catchBlock = finallyBlock;
subRoutine = null;
catchFlow.removeSuccessor(throwBlock.jump);
} else {
if (!(jsrBlock.innerBlock instanceof EmptyBlock))
return false;
catchBlock = jsrBlock;
subRoutine = jsrBlock.innerBlock.jump.destination;
checkAndRemoveJSR(tryFlow, catchBlock, subRoutine,
tryFlow.getNextAddr(), subRoutine.getAddr());
}
finallyBlock = jsrBlock.innerBlock;
subRoutine = finallyBlock.jump.destination;
/* Wow that was complicated :-)
* But now we know that the catch block looks
* exactly like it should:
*
* local_n = POP
* catchBlock:
* JSR
* finally
* throw local_n
/* We are committed now and can start changing the blocks.
*/
catchFlow.removeSuccessor(throwBlock.jump);
checkAndRemoveJSR(tryFlow, subRoutine,
tryFlow.getNextAddr(), end);
TryBlock tryBlock = (TryBlock) tryFlow.block;
if (tryBlock.getSubBlocks()[0] instanceof TryBlock) {
/* remove the surrounding tryBlock */
TryBlock innerTry = (TryBlock)tryBlock.getSubBlocks()[0];
innerTry.gen = tryBlock.gen;
innerTry.replace(tryBlock);
tryBlock = innerTry;
tryFlow.lastModified = tryBlock;
tryFlow.block = tryBlock;
}
FinallyBlock newBlock = new FinallyBlock();
newBlock.setCatchBlock(catchBlock);
tryBlock.addCatchBlock(newBlock);
if (subRoutine != null) {
/* Now analyze and transform the subroutine.
*/
while (subRoutine.analyze(tryFlow.getNextAddr(), end));
/* Now check if the subroutine is correct and has only the
* catchFlow as predecessor.
if (subRoutine.predecessors.size() == 1) {
/* catchFlow is synthetic, so we can safely remove it
* here.
*/
if (subRoutine.predecessors.size() == 1
&& transformSubRoutine(subRoutine.block)) {
catchFlow.removeSuccessor(finallyBlock.jump);
subRoutine.mergeAddr(catchFlow);
catchFlow = subRoutine;
tryFlow.removeSuccessor(jsrBlock.innerBlock.jump);
tryFlow.mergeAddr(subRoutine);
tryFlow.mergeSuccessors(subRoutine);
subRoutine.block.replace(catchBlock);
tryFlow.updateInOutCatch(subRoutine);
if (!transformSubRoutine(subRoutine.block)) {
finallyBlock = subRoutine.block;
DescriptionBlock msg = new DescriptionBlock
("ERROR: Missing return address handling");
StructuredBlock subblock = subRoutine.block;
msg.replace(finallyBlock);
msg.appendBlock(finallyBlock);
}
finallyBlock = subRoutine.block;
}
}
/* Now finish it.
*/
mergeFinallyBlock(tryFlow, catchFlow, finallyBlock);
return true;
}
private boolean analyzeSpecialFinally(FlowBlock tryFlow,
StructuredBlock catchBlock,
int end) {
FlowBlock catchFlow, int end) {
StructuredBlock finallyBlock = catchFlow.block;
StructuredBlock firstInstr =
catchBlock instanceof SequentialBlock
? catchBlock.getSubBlocks()[0]: catchBlock;
finallyBlock instanceof SequentialBlock
? finallyBlock.getSubBlocks()[0]: finallyBlock;
if (!(firstInstr instanceof SpecialBlock
&& ((SpecialBlock)firstInstr).type == SpecialBlock.POP
&& ((SpecialBlock)firstInstr).count == 1))
return false;
/* This may be a special try/finally-block, where
/* This is a special try/finally-block, where
* the finally block ends with a break, return or
* similar.
*/
FlowBlock succ = null;
/* remove the pop now */
if (catchBlock instanceof SequentialBlock)
catchBlock = catchBlock.getSubBlocks()[1];
else {
catchBlock = new EmptyBlock();
catchBlock.moveJump(firstInstr.jump);
/* Make sure that resolveJump only works on the inside of the try
*/
tryFlow.lastModified = tryFlow.block.getSubBlocks()[0];
FlowBlock finallyFlow;
if (finallyBlock instanceof SequentialBlock) {
finallyBlock = finallyBlock.getSubBlocks()[1];
finallyFlow = null;
} else {
finallyBlock = new EmptyBlock();
finallyBlock.moveJump(firstInstr.jump);
succ = firstInstr.jump.destination;
/* Handle the jumps in the tryFlow to finallyFlow.
*/
finallyFlow = finallyBlock.jump.destination;
if (tryFlow.getSuccessors().contains(finallyFlow)) {
Jump jumps = tryFlow.removeJumps(finallyFlow);
jumps = tryFlow.resolveSomeJumps(jumps, finallyFlow);
tryFlow.resolveRemaining(jumps);
}
}
// Set trySuccs = tryFlow.getSuccessors();
// if (trySuccs.size() > 1
// || (trySuccs.size() == 1
// && trySuccs.iterator().next() != succ))
// return false;
if (succ != null) {
Jump jumps = tryFlow.removeJumps(succ);
/* Handle the jumps in the tryFlow.
/* Complain about all other jumps in try block */
Set trySuccs = tryFlow.getSuccessors();
for (Iterator i = trySuccs.iterator(); i.hasNext(); ) {
FlowBlock succ = (FlowBlock) i.next();
if (succ != FlowBlock.END_OF_METHOD) {
/* This seems to be a illegal succ in try block that
* doesn't go to the finally block. There is a last
* chance though. If the destination directly jumps
* to the try block, its okay.
*/
jumps = tryFlow.resolveSomeJumps(jumps, succ);
if (succ.block instanceof EmptyBlock
&& succ.block.jump.destination == finallyFlow) {
Jump jumps = tryFlow.removeJumps(succ);
jumps = tryFlow.resolveSomeJumps(jumps, finallyFlow);
tryFlow.resolveRemaining(jumps);
if (succ.predecessors.size() == 0) {
succ.removeJumps(finallyFlow);
tryFlow.mergeAddr(succ);
}
continue;
}
}
for (Jump jumps = tryFlow.getJumps(succ);
jumps != null; jumps = jumps.next) {
if (jumps.prev instanceof ThrowBlock)
continue;
TryBlock tryBlock = (TryBlock)tryFlow.block;
if (tryBlock.getSubBlocks()[0] instanceof TryBlock) {
/* remove the unnecessary tryBlock */
TryBlock innerTry = (TryBlock)tryBlock.getSubBlocks()[0];
innerTry.gen = tryBlock.gen;
innerTry.replace(tryBlock);
tryBlock = innerTry;
tryFlow.lastModified = innerTry;
DescriptionBlock msg =
new DescriptionBlock
("ERROR: doesn't go through finally block!");
if (jumps.prev instanceof ReturnBlock) {
msg.replace(jumps.prev);
msg.appendBlock(jumps.prev);
} else {
jumps.prev.appendBlock(msg);
msg.moveJump(jumps);
}
FinallyBlock newBlock = new FinallyBlock();
tryBlock.addCatchBlock(newBlock);
newBlock.setCatchBlock(catchBlock);
}
}
mergeFinallyBlock(tryFlow, catchFlow, finallyBlock);
/* Following code will work be put inside the finallyBlock */
tryFlow.lastModified = finallyBlock;
return true;
}
/**
* Analyzes all exception handlers to try/catch/finally or
* synchronized blocks.
*/
public void analyze() {
void checkTryCatchOrder() {
/* Check if try/catch ranges are okay. The following succeeds
* for all classes generated by the sun java compiler, but hand
* optimized classes (or generated by other compilers) will fail.
*/
{
Handler last = null;
for (Iterator i = handlers.iterator(); i.hasNext(); ) {
Handler exc = (Handler) i.next();
@ -852,7 +920,13 @@ public class TransformExceptionHandlers {
}
}
{
/**
* Analyzes all exception handlers to try/catch/finally or
* synchronized blocks.
*/
public void analyze() {
checkTryCatchOrder();
Iterator i = handlers.iterator();
Handler exc = null;
Handler next = i.hasNext() ? (Handler) i.next() : null;
@ -923,21 +997,15 @@ public class TransformExceptionHandlers {
while (catchFlow.analyze(catchFlow.getAddr(), endHandler));
}
/* Merge the try-block with the catch-block now */
tryFlow.updateInOutCatch(catchFlow);
tryFlow.mergeSuccessors(catchFlow);
tryFlow.mergeAddr(catchFlow);
if (exc.type != null)
analyzeCatchBlock(exc.type, tryFlow, catchFlow.block);
analyzeCatchBlock(exc.type, tryFlow, catchFlow);
else if (!analyzeSynchronized(tryFlow, catchFlow.block,
endHandler)
&& ! analyzeFinally(tryFlow, catchFlow.block,
endHandler)
&& ! analyzeSpecialFinally(tryFlow, catchFlow.block,
else if (!analyzeSynchronized(tryFlow, catchFlow, endHandler)
&& ! analyzeFinally(tryFlow, catchFlow, endHandler)
&& ! analyzeSpecialFinally(tryFlow, catchFlow,
endHandler))
analyzeCatchBlock(Type.tObject, tryFlow, catchFlow.block);
analyzeCatchBlock(Type.tObject, tryFlow, catchFlow);
tryFlow.checkConsistent();
if ((GlobalOptions.debuggingFlags
@ -948,4 +1016,3 @@ public class TransformExceptionHandlers {
}
}
}
}

Loading…
Cancel
Save