/* Soot - a J*va Optimization Framework
* Copyright (C) 2006 Nomair A. Naeem (nomair.naeem@mail.mcgill.ca)
*
* 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.
*/
/*
* Maintained by Nomair A. Naeem
*/
/*
* CHANGE LOG: * 30th Jan 2006 Class Created (used atleast by FinalFieldDefinition)
*
*
*/
package soot.dava.toolkits.base.AST.structuredAnalysis;
import soot.*;
import soot.dava.*;
import java.util.*;
import soot.jimple.*;
//import soot.dava.internal.javaRep.*;
import soot.dava.internal.AST.*;
/*
* The analysis stores all defs of Locals/SootField. The user can then ask whether a local or SootField
isMustInitialized or isMayInitialized
*
MustInitialize/MayInitialize
Step 1:
Set of initialized locals/SootField
Step 2:
A local or SootField is MUST initialized at a program point p if on all paths from the start to this
point the local or SootField is assigned a value.
Similarly a local or SootField is MAY initialized at a program point p if there is a path from the start
to this point on wich the local or SootField is assigned
Step 3:
Forward Analysis
Step 4:
Intersection/Union
Step 5:
x = expr
kill = {}
if x is a local or SootField, gen(x) = {x}
Step 6:
out(start) = {}
newInitialFlow: No copies are available. an empty flow set
remember new InitialFlow is ONLY used for input to catchBodies
*
*
*/
public class MustMayInitialize extends StructuredAnalysis{
HashMap<Object, List> mapping;
DavaFlowSet finalResult;
public static final int MUST=0;
public static final int MAY=1;
int MUSTMAY;
public MustMayInitialize(Object analyze,int MUSTorMAY){
super();
mapping = new HashMap<Object, List>();
MUSTMAY=MUSTorMAY;
//System.out.println("MustOrMay value is"+MUSTorMAY);
setMergeType();
//the input to the process method is an empty DavaFlow Set meaning out(start) ={} (no var initialized)
finalResult = (DavaFlowSet)process(analyze,new DavaFlowSet());
//finalResult contains the flowSet of having processed the whole of the method
}
public DavaFlowSet emptyFlowSet(){
return new DavaFlowSet();
}
public void setMergeType(){
//System.out.println("here"+MUSTMAY);
if(MUSTMAY == MUST){
MERGETYPE=INTERSECTION;
//System.out.println("MERGETYPE set to intersection");
}
else if(MUSTMAY == MAY){
MERGETYPE=UNION;
//System.out.println("MERGETYPE set to union");
}
else
throw new DavaFlowAnalysisException("Only allowed 0 or 1 for MUST or MAY values");
}
/*
* newInitialFlow set is used only for start of catch bodies and here we assume that no var
* is ever being initialized
*/
public Object newInitialFlow(){
return new DavaFlowSet();
}
public Object cloneFlowSet(Object flowSet){
if(flowSet instanceof DavaFlowSet){
return ((DavaFlowSet)flowSet).clone();
}
else
throw new RuntimeException("cloneFlowSet not implemented for other flowSet types");
}
/*
* By construction conditions never have assignment statements.
* Hence processing a condition has no effect on this analysis
*/
public Object processUnaryBinaryCondition(ASTUnaryBinaryCondition cond, Object input){
if(!(input instanceof DavaFlowSet)){
throw new DavaFlowAnalysisException("processCondition is not implemented for other flowSet types");
}
return input;
}
/*
* By construction the synchronized Local is a Value and can definetly not have an assignment stmt
* Processing a synch local has no effect on this analysis
*/
public Object processSynchronizedLocal(Local local,Object input){
if(!(input instanceof DavaFlowSet)){
throw new RuntimeException("processCondition is not implemented for other flowSet types");
}
return input;
}
/*
* The switch key is stored as a value and hence can never have an assignment stmt
* Processing the switch key has no effect on the analysis
*/
public Object processSwitchKey(Value key,Object input){
if(!(input instanceof DavaFlowSet)){
throw new RuntimeException("processCondition is not implemented for other flowSet types");
}
return input;
}
/*
* This method internally invoked by the process method decides which Statement
* specialized method to call
*/
public Object processStatement(Stmt s, Object input){
if(!(input instanceof DavaFlowSet)){
throw new RuntimeException("processStatement is not implemented for other flowSet types");
}
DavaFlowSet inSet = (DavaFlowSet)input;
/*
If this path will not be taken return no path straightaway
*/
if(inSet == NOPATH){
return inSet;
}
if(s instanceof DefinitionStmt){
DavaFlowSet toReturn = (DavaFlowSet)cloneFlowSet(inSet);
// x = expr;
Value leftOp = ((DefinitionStmt)s).getLeftOp();
SootField field = null;;
if(leftOp instanceof Local){
toReturn.add(leftOp);
/*
* Gather more information just in case someone might need the def points
*/
Object temp = mapping.get(leftOp);
List<Stmt> defs;
if(temp == null){
//first definition
defs = new ArrayList<Stmt>();
}
else{
defs = (ArrayList<Stmt>)temp;
}
defs.add(s);
mapping.put(leftOp,defs);
}
else if(leftOp instanceof FieldRef){
field = ((FieldRef)leftOp).getField();
toReturn.add(field);
/*
* Gather more information just in case someone might need the def points
*/
Object temp = mapping.get(field);
List<Stmt> defs;
if(temp == null){
//first definition
defs = new ArrayList<Stmt>();
}
else{
defs = (ArrayList<Stmt>)temp;
}
defs.add(s);
mapping.put(field,defs);
}
return toReturn;
}
return input;
}
public boolean isMayInitialized(SootField field){
if(MUSTMAY == MAY){
Object temp = mapping.get(field);
if(temp == null)
return false;
else{
List list = (List)temp;
if(list.size()==0)
return false;
else
return true;
}
}
else
throw new RuntimeException("Cannot invoke isMayInitialized for a MUST analysis");
}
public boolean isMayInitialized(Value local){
if(MUSTMAY == MAY){
Object temp = mapping.get(local);
if(temp == null)
return false;
else{
List list = (List)temp;
if(list.size()==0)
return false;
else
return true;
}
}
else
throw new RuntimeException("Cannot invoke isMayInitialized for a MUST analysis");
}
public boolean isMustInitialized(SootField field){
if(MUSTMAY == MUST){
if(finalResult.contains(field))
return true;
return false;
}
else
throw new RuntimeException("Cannot invoke isMustinitialized for a MAY analysis");
}
public boolean isMustInitialized(Value local){
if(MUSTMAY == MUST){
if(finalResult.contains(local))
return true;
return false;
}
else
throw new RuntimeException("Cannot invoke isMustinitialized for a MAY analysis");
}
/*
* Given a local ask for all def positions
* Notice this could be null in the case there was no definition
*/
public List getDefs(Value local){
Object temp = mapping.get(local);
if(temp == null)
return null;
else
return (List)temp;
}
/*
* Given a field ask for all def positions
* Notice this could be null in the case there was no definition
*/
public List getDefs(SootField field){
Object temp = mapping.get(field);
if(temp == null)
return null;
else
return (List)temp;
}
}