KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > edu > umd > cs > findbugs > detect > FindNonShortCircuit


1 /*
2  * FindBugs - Find bugs in Java programs
3  * Copyright (C) 2003-2005 University of Maryland
4  *
5  * This library is free software; you can redistribute it and/or
6  * modify it under the terms of the GNU Lesser General Public
7  * License as published by the Free Software Foundation; either
8  * version 2.1 of the License, or (at your option) any later version.
9  *
10  * This library is distributed in the hope that it will be useful,
11  * but WITHOUT ANY WARRANTY; without even the implied warranty of
12  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13  * Lesser General Public License for more details.
14  *
15  * You should have received a copy of the GNU Lesser General Public
16  * License along with this library; if not, write to the Free Software
17  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
18  */

19
20 package edu.umd.cs.findbugs.detect;
21
22 import edu.umd.cs.findbugs.*;
23
24 import org.apache.bcel.classfile.Method;
25
26 public class FindNonShortCircuit extends BytecodeScanningDetector implements
27         StatelessDetector {
28
29     int stage1 = 0;
30     int stage2 = 0;
31     int distance = 0;
32     int operator;
33
34     boolean sawDanger;
35     boolean sawNullTestOld;
36     boolean sawNullTestVeryOld;
37     boolean sawNullTest;
38     boolean sawDangerOld;
39     boolean sawArrayIndex;
40     boolean sawArrayIndexOld;
41     boolean sawNumericTest, sawNumericTestOld, sawNumericTestVeryOld;
42     boolean sawArrayDanger, sawArrayDangerOld;
43
44     private BugReporter bugReporter;
45
46     public FindNonShortCircuit(BugReporter bugReporter) {
47         this.bugReporter = bugReporter;
48     }
49
50     OpcodeStack stack = new OpcodeStack();
51
52     @Override JavaDoc
53     public void visit(Method obj) {
54         stack.resetForMethodEntry(this);
55         stage1 = 0;
56         stage2 = 0;
57         distance = 1000000;
58         sawArrayDanger = sawArrayDangerOld = false;
59         sawDanger = sawDangerOld = false;
60         sawNullTest = sawNullTestOld = sawNullTestVeryOld = false;
61         sawNumericTest = sawNumericTestOld = sawNumericTestVeryOld = false;
62         prevOpcode = NOP;
63     }
64
65     int prevOpcode;
66     @Override JavaDoc
67     public void sawOpcode(int seen) {
68         stack.mergeJumps(this);
69         // System.out.println(getPC() + " " + OPCODE_NAMES[seen] + " " + stage1 + " " + stage2);
70
// System.out.println(stack);
71
distance++;
72         scanForBooleanValue(seen);
73         scanForDanger(seen);
74         scanForShortCircuit(seen);
75         stack.sawOpcode(this, seen);
76         prevOpcode = seen;
77     }
78
79     private void scanForDanger(int seen) {
80         switch (seen) {
81         case AALOAD:
82         case BALOAD:
83         case SALOAD:
84         case CALOAD:
85         case IALOAD:
86         case LALOAD:
87         case FALOAD:
88         case DALOAD:
89             sawArrayDanger = true;
90             sawDanger = true;
91             break;
92             
93         case INVOKEINTERFACE:
94         case INVOKESPECIAL:
95         case INVOKEVIRTUAL:
96         case INVOKESTATIC:
97         case ARRAYLENGTH:
98         case IDIV:
99         case IREM:
100         case GETFIELD:
101             sawDanger = true;
102             break;
103         default:
104             break;
105         }
106
107     }
108
109     private void scanForShortCircuit(int seen) {
110         switch (seen) {
111         case IAND:
112         case IOR:
113             // System.out.println("Saw IOR or IAND at distance " + distance);
114
OpcodeStack.Item item0 = stack.getStackItem(0);
115             OpcodeStack.Item item1 = stack.getStackItem(1);
116             if (item0.getConstant() == null && item1.getConstant() == null && distance < 4) {
117                 operator = seen;
118                 stage2 = 1;
119             } else
120                 stage2 = 0;
121             break;
122         case IFEQ:
123         case IFNE:
124             if (stage2 == 1) {
125                 // System.out.println("Found nsc");
126
reportBug();
127             }
128             stage2 = 0;
129             break;
130         case PUTFIELD:
131         case PUTSTATIC:
132         case IRETURN:
133             if (operator == IAND && stage2 == 1) {
134                 reportBug();
135             }
136             stage2 = 0;
137             break;
138         default:
139             stage2 = 0;
140             break;
141         }
142     }
143
144     private void reportBug() {
145         int priority = LOW_PRIORITY;
146         if (sawDangerOld)
147             if (sawNullTestVeryOld) priority = HIGH_PRIORITY;
148             else if (sawNumericTestVeryOld && sawArrayDangerOld) priority = HIGH_PRIORITY;
149             else priority = NORMAL_PRIORITY;
150
151         bugReporter.reportBug(new BugInstance(this, "NS_NON_SHORT_CIRCUIT",
152                 priority)
153         .addClassAndMethod(this).addSourceLine(this, getPC()));
154     }
155
156
157     private void scanForBooleanValue(int seen) {
158         switch (seen) {
159
160         case ICONST_1:
161             stage1 = 1;
162             switch(prevOpcode) {
163             case IFNONNULL:
164             case IFNULL:
165                 sawNullTest = true;
166                 break;
167             case IF_ICMPGT:
168             case IF_ICMPGE:
169             case IF_ICMPLT:
170             case IF_ICMPLE:
171                 sawNumericTest = true;
172             break;
173             }
174
175             break;
176         case GOTO:
177             if (stage1 == 1)
178                 stage1 = 2;
179             else
180                 stage1 = 0;
181             break;
182         case ICONST_0:
183             if (stage1 == 2)
184                 sawBooleanValue();
185             stage1 = 0;
186             break;
187         case INVOKEINTERFACE:
188         case INVOKEVIRTUAL:
189         case INVOKESPECIAL:
190         case INVOKESTATIC:
191             String JavaDoc sig = getSigConstantOperand();
192             if (sig.endsWith(")Z"))
193                 sawBooleanValue();
194             stage1 = 0;
195             break;
196         default:
197             stage1 = 0;
198         }
199     }
200
201     private void sawBooleanValue() {
202         sawDangerOld = sawDanger;
203         sawArrayDangerOld = sawArrayDanger;
204         sawNullTestVeryOld = sawNullTestOld;
205         sawNullTestOld = sawNullTest;
206         sawNumericTestVeryOld = sawNumericTestOld;
207         sawNumericTestOld = sawNumericTest;
208         sawNumericTest = false;
209         sawDanger = false;
210         sawArrayDanger = false;
211         distance = 0;
212         stage1 = 0;
213
214     }
215 }
216
Popular Tags