/*
* FindBugs - Find Bugs in Java programs
* Copyright (C) 2003-2007 University of Maryland
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
package edu.umd.cs.findbugs.ba.jsr305;
import java.util.Iterator;
import javax.annotation.meta.When;
import org.apache.bcel.generic.ConstantPoolGen;
import org.apache.bcel.generic.Instruction;
import org.apache.bcel.generic.InstructionHandle;
import org.apache.bcel.generic.RETURN;
import org.apache.bcel.generic.ReturnInstruction;
import edu.umd.cs.findbugs.ba.CFG;
import edu.umd.cs.findbugs.ba.ClassContext;
import edu.umd.cs.findbugs.ba.DataflowAnalysisException;
import edu.umd.cs.findbugs.ba.DepthFirstSearch;
import edu.umd.cs.findbugs.ba.Location;
import edu.umd.cs.findbugs.ba.XMethod;
import edu.umd.cs.findbugs.ba.vna.ValueNumber;
import edu.umd.cs.findbugs.ba.vna.ValueNumberDataflow;
import edu.umd.cs.findbugs.ba.vna.ValueNumberFrame;
import edu.umd.cs.findbugs.classfile.CheckedAnalysisException;
import edu.umd.cs.findbugs.classfile.Global;
import edu.umd.cs.findbugs.classfile.IAnalysisCache;
import edu.umd.cs.findbugs.classfile.MethodDescriptor;
/**
* Factory for producing ForwardTypeQualifierDataflow objects for various kinds
* of type qualifiers.
*
* @author David Hovemeyer
*/
public class ForwardTypeQualifierDataflowFactory extends
TypeQualifierDataflowFactory<ForwardTypeQualifierDataflowAnalysis, ForwardTypeQualifierDataflow> {
/**
* Constructor.
*
* @param methodDescriptor
* MethodDescriptor of method being analyzed
*/
public ForwardTypeQualifierDataflowFactory(MethodDescriptor methodDescriptor) {
super(methodDescriptor);
}
@Override
protected ForwardTypeQualifierDataflow getDataflow(DepthFirstSearch dfs, XMethod xmethod, CFG cfg,
ValueNumberDataflow vnaDataflow, ConstantPoolGen cpg, IAnalysisCache analysisCache,
MethodDescriptor methodDescriptor, TypeQualifierValue<?> typeQualifierValue) throws DataflowAnalysisException {
ForwardTypeQualifierDataflowAnalysis analysis = new ForwardTypeQualifierDataflowAnalysis(dfs, xmethod, cfg, vnaDataflow,
cpg, typeQualifierValue);
analysis.registerSourceSinkLocations();
ForwardTypeQualifierDataflow dataflow = new ForwardTypeQualifierDataflow(cfg, analysis);
dataflow.execute();
if (ClassContext.DUMP_DATAFLOW_ANALYSIS) {
dataflow.dumpDataflow(analysis);
}
return dataflow;
}
@Override
protected void populateDatabase(ForwardTypeQualifierDataflow dataflow, ValueNumberDataflow vnaDataflow, XMethod xmethod,
TypeQualifierValue<?> tqv) throws CheckedAnalysisException {
assert TypeQualifierDatabase.USE_DATABASE;
if (xmethod.getSignature().endsWith(")V")) {
return;
}
// If there is no effective type qualifier annotation
// on the method's return value, and we computed an
// "interesting" (ALWAYS or NEVER) value for the return
// value, add it to the database.
TypeQualifierAnnotation tqa = TypeQualifierApplications.getEffectiveTypeQualifierAnnotation(xmethod, tqv);
if (tqa == null) {
// Find the meet of the flow values at all instructions
// which return a value.
FlowValue effectiveFlowValue = null;
CFG cfg = dataflow.getCFG();
Iterator<Location> i = cfg.locationIterator();
while (i.hasNext()) {
Location loc = i.next();
InstructionHandle handle = loc.getHandle();
Instruction ins = handle.getInstruction();
if (ins instanceof ReturnInstruction && !(ins instanceof RETURN)) {
ValueNumberFrame vnaFrame = vnaDataflow.getFactAtLocation(loc);
ValueNumber topVN = vnaFrame.getTopValue();
TypeQualifierValueSet flowSet = dataflow.getFactAtLocation(loc);
FlowValue topFlowValue = flowSet.getValue(topVN);
if (topFlowValue != null) {
if (TypeQualifierDatabase.DEBUG) {
System.out.println("at pc " + handle.getPosition() + " of " + xmethod + ", return value for " + tqv
+ " is " + topFlowValue);
}
if (effectiveFlowValue == null) {
effectiveFlowValue = topFlowValue;
} else {
effectiveFlowValue = FlowValue.meet(effectiveFlowValue, topFlowValue);
}
}
}
}
if (effectiveFlowValue == FlowValue.ALWAYS || effectiveFlowValue == FlowValue.NEVER) {
TypeQualifierDatabase tqdb = Global.getAnalysisCache().getDatabase(TypeQualifierDatabase.class);
if (TypeQualifierDatabase.DEBUG) {
System.out.println("inferring return value for " + xmethod + " of" + tqv + " : " + effectiveFlowValue);
}
tqa = TypeQualifierAnnotation.getValue(tqv, effectiveFlowValue == FlowValue.ALWAYS ? When.ALWAYS : When.NEVER);
tqdb.setReturnValue(xmethod.getMethodDescriptor(), tqv, tqa);
}
}
}
}