KickJava   Java API By Example, From Geeks To Geeks.

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


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

20
21 package edu.umd.cs.findbugs.detect;
22
23 import edu.umd.cs.findbugs.*;
24 import java.util.*;
25 import org.apache.bcel.classfile.Code;
26
27 public class FindFloatEquality extends BytecodeScanningDetector implements StatelessDetector
28 {
29     private static final int SAW_NOTHING = 0;
30     private static final int SAW_COMP = 1;
31     private int priority;
32     private BugReporter bugReporter;
33     private OpcodeStack opStack = new OpcodeStack();
34     private int state;
35
36     public FindFloatEquality(BugReporter bugReporter) {
37         this.bugReporter = bugReporter;
38     }
39     
40
41     Collection<SourceLineAnnotation> found = new LinkedList<SourceLineAnnotation>();
42         
43     @Override JavaDoc
44          public void visit(Code obj) {
45         found.clear();
46         priority = LOW_PRIORITY;
47
48         
49         opStack.resetForMethodEntry(this);
50         state = SAW_NOTHING;
51     
52         super.visit(obj);
53         if (!found.isEmpty()) {
54                 BugInstance bug = new BugInstance(this, "FE_FLOATING_POINT_EQUALITY", priority)
55                         .addClassAndMethod(this);
56
57                 for(SourceLineAnnotation s : found)
58                     bug.add(s);
59                 bugReporter.reportBug(bug);
60                 
61                 found.clear();
62         }
63     }
64     
65     public boolean okValueToCompareAgainst(Number JavaDoc n) {
66         if (n == null) return false;
67         double v = n.doubleValue();
68         if (Double.isInfinite(v) || Double.isNaN(v)) return true;
69         v = v - Math.floor(v);
70         return v == 0.0;
71     }
72     @Override JavaDoc
73          public void sawOpcode(int seen) {
74         if (false) System.out.println(OPCODE_NAMES[seen] + " " + state);
75         opStack.mergeJumps(this);
76         try {
77             switch ( seen ) {
78                 case FCMPG:
79                 case FCMPL:
80                 case DCMPG:
81                 case DCMPL:
82                     if (opStack.getStackDepth() >= 2) {
83                         OpcodeStack.Item first = opStack.getStackItem(0);
84                         OpcodeStack.Item second = opStack.getStackItem(1);
85
86                         Number JavaDoc n1 = (Number JavaDoc)first.getConstant();
87                         Number JavaDoc n2 = (Number JavaDoc)second.getConstant();
88                         if (n1 != null && Double.isNaN(n1.doubleValue())
89                                 || n2 != null && Double.isNaN(n2.doubleValue()) ) {
90                             BugInstance bug = new BugInstance(this, "FE_TEST_IF_EQUAL_TO_NOT_A_NUMBER", HIGH_PRIORITY)
91                             .addClassAndMethod(this).addSourceLine(this);
92                             bugReporter.reportBug(bug);
93                             state = SAW_NOTHING;
94                             break;
95                         }
96                         if (first.getSpecialKind() == OpcodeStack.Item.FLOAT_MATH && !okValueToCompareAgainst(n2)
97                                 || second.getSpecialKind() == OpcodeStack.Item.FLOAT_MATH && !okValueToCompareAgainst(n1)) {
98                             if (priority != HIGH_PRIORITY) found.clear();
99                             priority = HIGH_PRIORITY;
100                             state = SAW_COMP;
101                             break;
102                         }
103                         if (priority == HIGH_PRIORITY) break;
104                         if (first.isInitialParameter() && n2 != null) break;
105                         if (second.isInitialParameter() && n1 != null) break;
106                         if (first.getRegisterNumber() == second.getRegisterNumber()) break;
107                         if (first.isInitialParameter() && second.isInitialParameter()) break;
108                         if (n1 != null && n2 != null) break;
109                         
110                         if (okValueToCompareAgainst(n1) || okValueToCompareAgainst(n2)) break;
111                         if (n1 != null || n2 != null) {
112                             if (priority == LOW_PRIORITY) found.clear();
113                             priority = NORMAL_PRIORITY;
114                             
115                         }
116                         else if (priority == NORMAL_PRIORITY) break;
117                         state = SAW_COMP;
118                     }
119                 break;
120                 
121                 case IFEQ:
122                 case IFNE:
123                     if (state == SAW_COMP) {
124                         SourceLineAnnotation sourceLineAnnotation =
125                             SourceLineAnnotation.fromVisitedInstruction(getClassContext(), this, getPC());
126                         if (sourceLineAnnotation != null) {
127                             found.add(sourceLineAnnotation);
128                         }
129                     }
130                     state = SAW_NOTHING;
131                 break;
132                 
133                 default:
134                     state = SAW_NOTHING;
135                 break;
136             }
137         }
138         finally {
139             opStack.sawOpcode(this, seen);
140         }
141     }
142 }
143
Popular Tags