001: /*
002: * FindBugs - Find Bugs in Java programs
003: * Copyright (C) 2003-2007 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.jsr305;
021:
022: import java.util.Iterator;
023:
024: import javax.annotation.meta.When;
025:
026: import org.apache.bcel.Constants;
027: import org.apache.bcel.generic.ConstantPoolGen;
028: import org.apache.bcel.generic.FieldInstruction;
029: import org.apache.bcel.generic.InvokeInstruction;
030:
031: import edu.umd.cs.findbugs.ba.BlockOrder;
032: import edu.umd.cs.findbugs.ba.CFG;
033: import edu.umd.cs.findbugs.ba.DataflowAnalysisException;
034: import edu.umd.cs.findbugs.ba.DepthFirstSearch;
035: import edu.umd.cs.findbugs.ba.Location;
036: import edu.umd.cs.findbugs.ba.ReversePostOrder;
037: import edu.umd.cs.findbugs.ba.SignatureParser;
038: import edu.umd.cs.findbugs.ba.XFactory;
039: import edu.umd.cs.findbugs.ba.XField;
040: import edu.umd.cs.findbugs.ba.XMethod;
041: import edu.umd.cs.findbugs.ba.vna.ValueNumber;
042: import edu.umd.cs.findbugs.ba.vna.ValueNumberDataflow;
043: import edu.umd.cs.findbugs.ba.vna.ValueNumberFrame;
044:
045: /**
046: * Forward type qualifier dataflow analysis.
047: *
048: * @author David Hovemeyer
049: */
050: public class ForwardTypeQualifierDataflowAnalysis extends
051: TypeQualifierDataflowAnalysis {
052: private final DepthFirstSearch dfs;
053:
054: /**
055: * Constructor.
056: *
057: * @param dfs DepthFirstSearch on the analyzed method
058: * @param xmethod XMethod for the analyzed method
059: * @param cfg CFG of the analyzed method
060: * @param vnaDataflow ValueNumberDataflow on the analyzed method
061: * @param cpg ConstantPoolGen of the analyzed method
062: * @param typeQualifierValue TypeQualifierValue representing type qualifier the analysis should check
063: */
064: public ForwardTypeQualifierDataflowAnalysis(DepthFirstSearch dfs,
065: XMethod xmethod, CFG cfg, ValueNumberDataflow vnaDataflow,
066: ConstantPoolGen cpg, TypeQualifierValue typeQualifierValue) {
067: super (xmethod, cfg, vnaDataflow, cpg, typeQualifierValue);
068: this .dfs = dfs;
069: }
070:
071: /* (non-Javadoc)
072: * @see edu.umd.cs.findbugs.ba.DataflowAnalysis#getBlockOrder(edu.umd.cs.findbugs.ba.CFG)
073: */
074: public BlockOrder getBlockOrder(CFG cfg) {
075: return new ReversePostOrder(cfg, dfs);
076: }
077:
078: /* (non-Javadoc)
079: * @see edu.umd.cs.findbugs.ba.DataflowAnalysis#isForwards()
080: */
081: public boolean isForwards() {
082: return true;
083: }
084:
085: /* (non-Javadoc)
086: * @see edu.umd.cs.findbugs.ba.jsr305.TypeQualifierDataflowAnalysis#registerSourceSinkLocations()
087: */
088: @Override
089: public void registerSourceSinkLocations()
090: throws DataflowAnalysisException {
091: registerParameterSources();
092: registerInstructionSources();
093: }
094:
095: private void registerInstructionSources()
096: throws DataflowAnalysisException {
097: for (Iterator<Location> i = cfg.locationIterator(); i.hasNext();) {
098: Location location = i.next();
099: short opcode = location.getHandle().getInstruction()
100: .getOpcode();
101:
102: if (location.getHandle().getInstruction() instanceof InvokeInstruction) {
103: // Model return value
104: registerReturnValueSource(location);
105: } else if (opcode == Constants.GETFIELD
106: || opcode == Constants.GETSTATIC) {
107: // Model field loads
108: registerFieldLoadSource(location);
109: }
110: }
111: }
112:
113: private void registerReturnValueSource(Location location)
114: throws DataflowAnalysisException {
115: // Nothing to do if called method does not return a reference value
116: InvokeInstruction inv = (InvokeInstruction) location
117: .getHandle().getInstruction();
118: String calledMethodSig = inv.getSignature(cpg);
119: if (!calledMethodSig.endsWith(";")) {
120: return;
121: }
122:
123: XMethod xmethod = XFactory.createXMethod(inv, cpg);
124: if (xmethod.isResolved()) {
125: TypeQualifierAnnotation tqa =
126: //TypeQualifierApplications.getApplicableApplicationConsideringSupertypes(xmethod, typeQualifierValue);
127: TypeQualifierApplications
128: .getEffectiveTypeQualifierAnnotation(xmethod,
129: typeQualifierValue);
130: When when = (tqa != null) ? tqa.when : When.UNKNOWN;
131: registerTopOfStackSource(
132: SourceSinkType.RETURN_VALUE_OF_CALLED_METHOD,
133: location, when);
134: }
135: }
136:
137: private void registerFieldLoadSource(Location location)
138: throws DataflowAnalysisException {
139: XField loadedField = XFactory.createXField(
140: (FieldInstruction) location.getHandle()
141: .getInstruction(), cpg);
142: if (loadedField.isResolved()) {
143: TypeQualifierAnnotation tqa =
144: //TypeQualifierApplications.getApplicableApplicationConsideringSupertypes(loadedField, typeQualifierValue);
145: TypeQualifierApplications
146: .getEffectiveTypeQualifierAnnotation(loadedField,
147: typeQualifierValue);
148: When when = (tqa != null) ? tqa.when : When.UNKNOWN;
149: registerTopOfStackSource(SourceSinkType.FIELD_LOAD,
150: location, when);
151: }
152:
153: }
154:
155: private void registerTopOfStackSource(
156: SourceSinkType sourceSinkType, Location location, When when)
157: throws DataflowAnalysisException {
158: ValueNumberFrame vnaFrameAfterInstruction = vnaDataflow
159: .getFactAfterLocation(location);
160: if (vnaFrameAfterInstruction.isValid()) {
161: ValueNumber tosValue = vnaFrameAfterInstruction
162: .getTopValue();
163: SourceSinkInfo sourceSinkInfo = new SourceSinkInfo(
164: sourceSinkType, location, tosValue, when);
165: registerSourceSink(sourceSinkInfo);
166: }
167: }
168:
169: private void registerParameterSources() {
170: ValueNumberFrame vnaFrameAtEntry = vnaDataflow.getStartFact(cfg
171: .getEntry());
172:
173: SignatureParser sigParser = new SignatureParser(xmethod
174: .getSignature());
175: int firstParamSlot = xmethod.isStatic() ? 0 : 1;
176:
177: int param = 0;
178: int slotOffset = 0;
179:
180: for (Iterator<String> i = sigParser
181: .parameterSignatureIterator(); i.hasNext();) {
182: String paramSig = i.next();
183:
184: // Get the TypeQualifierAnnotation for this parameter
185: SourceSinkInfo info;
186: TypeQualifierAnnotation tqa = TypeQualifierApplications
187: .getEffectiveTypeQualifierAnnotation(xmethod,
188: param, typeQualifierValue);
189: When when = (tqa != null) ? tqa.when : When.UNKNOWN;
190: ValueNumber vn = vnaFrameAtEntry.getValue(slotOffset
191: + firstParamSlot);
192: info = new SourceSinkInfo(SourceSinkType.PARAMETER, cfg
193: .getLocationAtEntry(), vn, when);
194: info.setParameterAndLocal(param, slotOffset
195: + firstParamSlot);
196: registerSourceSink(info);
197:
198: param++;
199: slotOffset += SignatureParser.getNumSlotsForType(paramSig);
200: }
201: }
202:
203: /* (non-Javadoc)
204: * @see edu.umd.cs.findbugs.ba.jsr305.TypeQualifierDataflowAnalysis#propagateAcrossPhiNode(edu.umd.cs.findbugs.ba.jsr305.TypeQualifierValueSet, edu.umd.cs.findbugs.ba.vna.ValueNumber, edu.umd.cs.findbugs.ba.vna.ValueNumber)
205: */
206: @Override
207: protected void propagateAcrossPhiNode(TypeQualifierValueSet fact,
208: ValueNumber sourceVN, ValueNumber targetVN) {
209: // Forward analysis - propagate from source to target
210: fact.propagateAcrossPhiNode(sourceVN, targetVN);
211: }
212: }
|