001: /*
002: * Bytecode Analysis Framework
003: * Copyright (C) 2003,2004 University of Maryland
004: *
005: * This library is free software; you can redistribute it and/or
006: * modify it under the terms of the GNU Lesser General Public
007: * License as published by the Free Software Foundation; either
008: * version 2.1 of the License, or (at your option) any later version.
009: *
010: * This library is distributed in the hope that it will be useful,
011: * but WITHOUT ANY WARRANTY; without even the implied warranty of
012: * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
013: * Lesser General Public License for more details.
014: *
015: * You should have received a copy of the GNU Lesser General Public
016: * License along with this library; if not, write to the Free Software
017: * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
018: */
019:
020: package edu.umd.cs.findbugs.ba;
021:
022: import java.util.Iterator;
023: import java.util.LinkedList;
024:
025: import org.apache.bcel.generic.ATHROW;
026: import org.apache.bcel.generic.ConstantPoolGen;
027: import org.apache.bcel.generic.GotoInstruction;
028: import org.apache.bcel.generic.INVOKESTATIC;
029: import org.apache.bcel.generic.IfInstruction;
030: import org.apache.bcel.generic.InstructionHandle;
031: import org.apache.bcel.generic.ReturnInstruction;
032: import org.apache.bcel.generic.Select;
033:
034: /**
035: * Visitor to find all of the targets of an instruction
036: * whose InstructionHandle is given.
037: * Note that we don't consider exception edges.
038: *
039: * @author David Hovemeyer
040: * @author Chadd Williams
041: */
042: public class TargetEnumeratingVisitor extends
043: org.apache.bcel.generic.EmptyVisitor implements EdgeTypes {
044:
045: private InstructionHandle handle;
046: private ConstantPoolGen constPoolGen;
047: private LinkedList<Target> targetList;
048: private boolean isBranch, isReturn, isThrow, isExit;
049:
050: /**
051: * Constructor.
052: *
053: * @param handle the handle of the instruction whose targets should be enumerated
054: * @param constPoolGen the ConstantPoolGen object for the class
055: */
056: public TargetEnumeratingVisitor(InstructionHandle handle,
057: ConstantPoolGen constPoolGen) {
058: this .handle = handle;
059: this .constPoolGen = constPoolGen;
060: targetList = new LinkedList<Target>();
061: isBranch = isReturn = isThrow = isExit = false;
062:
063: handle.getInstruction().accept(this );
064: }
065:
066: /**
067: * Is the instruction the end of a basic block?
068: */
069: public boolean isEndOfBasicBlock() {
070: return isBranch || isReturn || isThrow || isExit;
071: }
072:
073: /**
074: * Is the analyzed instruction a method return?
075: */
076: public boolean instructionIsReturn() {
077: return isReturn;
078: }
079:
080: /**
081: * Is the analyzed instruction an explicit throw?
082: */
083: public boolean instructionIsThrow() {
084: return isThrow;
085: }
086:
087: /**
088: * Is the analyzed instruction an exit (call to System.exit())?
089: */
090: public boolean instructionIsExit() {
091: return isExit;
092: }
093:
094: /**
095: * Iterate over Target objects representing control flow targets
096: * and their edge types.
097: */
098: public Iterator<Target> targetIterator() {
099: return targetList.iterator();
100: }
101:
102: @Override
103: public void visitGotoInstruction(GotoInstruction ins) {
104: isBranch = true;
105: InstructionHandle target = ins.getTarget();
106: if (target == null)
107: throw new IllegalStateException();
108: targetList.add(new Target(target, GOTO_EDGE));
109: }
110:
111: @Override
112: public void visitIfInstruction(IfInstruction ins) {
113: isBranch = true;
114: InstructionHandle target = ins.getTarget();
115: if (target == null)
116: throw new IllegalStateException();
117: targetList.add(new Target(target, IFCMP_EDGE));
118: InstructionHandle fallThrough = handle.getNext();
119: targetList.add(new Target(fallThrough, FALL_THROUGH_EDGE));
120: }
121:
122: @Override
123: public void visitSelect(Select ins) {
124: isBranch = true;
125:
126: // Add non-default switch edges.
127: InstructionHandle[] targets = ins.getTargets();
128: for (InstructionHandle target : targets) {
129: targetList.add(new Target(target, SWITCH_EDGE));
130: }
131:
132: // Add default switch edge.
133: InstructionHandle defaultTarget = ins.getTarget();
134: if (defaultTarget == null) {
135: throw new IllegalStateException();
136: }
137: targetList.add(new Target(defaultTarget, SWITCH_DEFAULT_EDGE));
138: }
139:
140: @Override
141: public void visitReturnInstruction(ReturnInstruction ins) {
142: isReturn = true;
143: }
144:
145: @Override
146: public void visitATHROW(ATHROW ins) {
147: isThrow = true;
148: }
149:
150: @Override
151: public void visitINVOKESTATIC(INVOKESTATIC ins) {
152: // Find calls to System.exit(), since this effectively terminates the basic block.
153:
154: String className = ins.getClassName(constPoolGen);
155: String methodName = ins.getName(constPoolGen);
156: String methodSig = ins.getSignature(constPoolGen);
157:
158: if (className.equals("java.lang.System")
159: && methodName.equals("exit")
160: && methodSig.equals("(I)V"))
161: isExit = true;
162: }
163:
164: }
|