use of soot.jimple.AbstractStmtSwitch in project soot by Sable.
the class MethodNodeFactory method handleStmt.
/**
* Adds the edges required for this statement to the graph.
*/
public final void handleStmt(Stmt s) {
// We only consider reflective class creation when it is enabled
if (s.containsInvokeExpr()) {
if (!pag.getCGOpts().types_for_invoke())
return;
InvokeExpr iexpr = s.getInvokeExpr();
if (iexpr instanceof VirtualInvokeExpr) {
if (!isReflectionNewInstance(iexpr))
return;
} else if (!(iexpr instanceof StaticInvokeExpr))
return;
}
s.apply(new AbstractStmtSwitch() {
@Override
public final void caseAssignStmt(AssignStmt as) {
Value l = as.getLeftOp();
Value r = as.getRightOp();
if (!(l.getType() instanceof RefLikeType))
return;
assert r.getType() instanceof RefLikeType : "Type mismatch in assignment " + as + " in method " + method.getSignature();
l.apply(MethodNodeFactory.this);
Node dest = getNode();
r.apply(MethodNodeFactory.this);
Node src = getNode();
if (l instanceof InstanceFieldRef) {
((InstanceFieldRef) l).getBase().apply(MethodNodeFactory.this);
pag.addDereference((VarNode) getNode());
}
if (r instanceof InstanceFieldRef) {
((InstanceFieldRef) r).getBase().apply(MethodNodeFactory.this);
pag.addDereference((VarNode) getNode());
} else if (r instanceof StaticFieldRef) {
StaticFieldRef sfr = (StaticFieldRef) r;
SootFieldRef s = sfr.getFieldRef();
if (pag.getOpts().empties_as_allocs()) {
if (s.declaringClass().getName().equals("java.util.Collections")) {
if (s.name().equals("EMPTY_SET")) {
src = pag.makeAllocNode(RefType.v("java.util.HashSet"), RefType.v("java.util.HashSet"), method);
} else if (s.name().equals("EMPTY_MAP")) {
src = pag.makeAllocNode(RefType.v("java.util.HashMap"), RefType.v("java.util.HashMap"), method);
} else if (s.name().equals("EMPTY_LIST")) {
src = pag.makeAllocNode(RefType.v("java.util.LinkedList"), RefType.v("java.util.LinkedList"), method);
}
} else if (s.declaringClass().getName().equals("java.util.Hashtable")) {
if (s.name().equals("emptyIterator")) {
src = pag.makeAllocNode(RefType.v("java.util.Hashtable$EmptyIterator"), RefType.v("java.util.Hashtable$EmptyIterator"), method);
} else if (s.name().equals("emptyEnumerator")) {
src = pag.makeAllocNode(RefType.v("java.util.Hashtable$EmptyEnumerator"), RefType.v("java.util.Hashtable$EmptyEnumerator"), method);
}
}
}
}
mpag.addInternalEdge(src, dest);
}
@Override
public final void caseReturnStmt(ReturnStmt rs) {
if (!(rs.getOp().getType() instanceof RefLikeType))
return;
rs.getOp().apply(MethodNodeFactory.this);
Node retNode = getNode();
mpag.addInternalEdge(retNode, caseRet());
}
@Override
public final void caseIdentityStmt(IdentityStmt is) {
if (!(is.getLeftOp().getType() instanceof RefLikeType))
return;
Value leftOp = is.getLeftOp();
Value rightOp = is.getRightOp();
leftOp.apply(MethodNodeFactory.this);
Node dest = getNode();
rightOp.apply(MethodNodeFactory.this);
Node src = getNode();
mpag.addInternalEdge(src, dest);
// in case library mode is activated add allocations to any
// possible type of this local and
// parameters of accessible methods
int libOption = pag.getCGOpts().library();
if (libOption != CGOptions.library_disabled && (accessibilityOracle.isAccessible(method))) {
if (rightOp instanceof IdentityRef) {
Type rt = rightOp.getType();
rt.apply(new SparkLibraryHelper(pag, src, method));
}
}
}
@Override
public final void caseThrowStmt(ThrowStmt ts) {
ts.getOp().apply(MethodNodeFactory.this);
mpag.addOutEdge(getNode(), pag.nodeFactory().caseThrow());
}
});
}
use of soot.jimple.AbstractStmtSwitch in project soot by Sable.
the class DexNumTransformer method internalTransform.
@Override
protected void internalTransform(final Body body, String phaseName, Map<String, String> options) {
final DexDefUseAnalysis localDefs = new DexDefUseAnalysis(body);
for (Local loc : getNumCandidates(body)) {
usedAsFloatingPoint = false;
Set<Unit> defs = localDefs.collectDefinitionsWithAliases(loc);
// process normally
doBreak = false;
for (Unit u : defs) {
// put correct local in l
final Local l = u instanceof DefinitionStmt ? (Local) ((DefinitionStmt) u).getLeftOp() : null;
// check defs
u.apply(new AbstractStmtSwitch() {
@Override
public void caseAssignStmt(AssignStmt stmt) {
Value r = stmt.getRightOp();
if (r instanceof BinopExpr && !(r instanceof CmpExpr)) {
usedAsFloatingPoint = examineBinopExpr(stmt);
doBreak = true;
} else if (r instanceof FieldRef) {
usedAsFloatingPoint = isFloatingPointLike(((FieldRef) r).getFieldRef().type());
doBreak = true;
} else if (r instanceof NewArrayExpr) {
NewArrayExpr nae = (NewArrayExpr) r;
Type t = nae.getType();
usedAsFloatingPoint = isFloatingPointLike(t);
doBreak = true;
} else if (r instanceof ArrayRef) {
ArrayRef ar = (ArrayRef) r;
Type arType = ar.getType();
if (arType instanceof UnknownType) {
Type t = findArrayType(localDefs, stmt, 0, // TODO:
Collections.<Unit>emptySet());
// check
// where
// else
// to
// update
// if(ArrayRef...
usedAsFloatingPoint = isFloatingPointLike(t);
} else {
usedAsFloatingPoint = isFloatingPointLike(ar.getType());
}
doBreak = true;
} else if (r instanceof CastExpr) {
usedAsFloatingPoint = isFloatingPointLike(((CastExpr) r).getCastType());
doBreak = true;
} else if (r instanceof InvokeExpr) {
usedAsFloatingPoint = isFloatingPointLike(((InvokeExpr) r).getType());
doBreak = true;
} else if (r instanceof LengthExpr) {
usedAsFloatingPoint = false;
doBreak = true;
}
}
@Override
public void caseIdentityStmt(IdentityStmt stmt) {
if (stmt.getLeftOp() == l) {
usedAsFloatingPoint = isFloatingPointLike(stmt.getRightOp().getType());
doBreak = true;
}
}
});
if (doBreak) {
break;
}
// check uses
for (Unit use : localDefs.getUsesOf(l)) {
use.apply(new AbstractStmtSwitch() {
private boolean examineInvokeExpr(InvokeExpr e) {
List<Value> args = e.getArgs();
List<Type> argTypes = e.getMethodRef().parameterTypes();
assert args.size() == argTypes.size();
for (int i = 0; i < args.size(); i++) {
if (args.get(i) == l && isFloatingPointLike(argTypes.get(i))) {
return true;
}
}
return false;
}
@Override
public void caseInvokeStmt(InvokeStmt stmt) {
InvokeExpr e = stmt.getInvokeExpr();
usedAsFloatingPoint = examineInvokeExpr(e);
}
@Override
public void caseAssignStmt(AssignStmt stmt) {
// only case where 'l' could be on the left side is
// arrayRef with 'l' as the index
Value left = stmt.getLeftOp();
if (left instanceof ArrayRef) {
ArrayRef ar = (ArrayRef) left;
if (ar.getIndex() == l) {
doBreak = true;
return;
}
}
// from this point, we only check the right hand
// side of the assignment
Value r = stmt.getRightOp();
if (r instanceof ArrayRef) {
if (((ArrayRef) r).getIndex() == l) {
doBreak = true;
return;
}
} else if (r instanceof InvokeExpr) {
usedAsFloatingPoint = examineInvokeExpr((InvokeExpr) r);
doBreak = true;
return;
} else if (r instanceof BinopExpr) {
usedAsFloatingPoint = examineBinopExpr(stmt);
doBreak = true;
return;
} else if (r instanceof CastExpr) {
usedAsFloatingPoint = stmt.hasTag("FloatOpTag") || stmt.hasTag("DoubleOpTag");
doBreak = true;
return;
} else if (r instanceof Local && r == l) {
if (left instanceof FieldRef) {
FieldRef fr = (FieldRef) left;
if (isFloatingPointLike(fr.getType())) {
usedAsFloatingPoint = true;
}
doBreak = true;
return;
} else if (left instanceof ArrayRef) {
ArrayRef ar = (ArrayRef) left;
Type arType = ar.getType();
if (arType instanceof UnknownType) {
arType = findArrayType(localDefs, stmt, 0, Collections.<Unit>emptySet());
}
usedAsFloatingPoint = isFloatingPointLike(arType);
doBreak = true;
return;
}
}
}
@Override
public void caseReturnStmt(ReturnStmt stmt) {
usedAsFloatingPoint = stmt.getOp() == l && isFloatingPointLike(body.getMethod().getReturnType());
doBreak = true;
return;
}
});
if (doBreak)
break;
}
// for uses
if (doBreak)
break;
}
// change values
if (usedAsFloatingPoint) {
for (Unit u : defs) {
replaceWithFloatingPoint(u);
}
}
// end if
}
}
use of soot.jimple.AbstractStmtSwitch in project soot by Sable.
the class DexNullTransformer method internalTransform.
@Override
protected void internalTransform(final Body body, String phaseName, Map<String, String> options) {
final DexDefUseAnalysis localDefs = new DexDefUseAnalysis(body);
AbstractStmtSwitch checkDef = new // Alex: should also end as
AbstractStmtSwitch() {
// soon as detected as not
// used as an object
@Override
public void caseAssignStmt(AssignStmt stmt) {
Value r = stmt.getRightOp();
if (r instanceof FieldRef) {
usedAsObject = isObject(((FieldRef) r).getFieldRef().type());
doBreak = true;
return;
} else if (r instanceof ArrayRef) {
ArrayRef ar = (ArrayRef) r;
if (ar.getType() instanceof UnknownType) {
// isObject
usedAsObject = stmt.hasTag("ObjectOpTag");
// (findArrayType
// (g,
// localDefs,
// localUses,
// stmt));
} else {
usedAsObject = isObject(ar.getType());
}
doBreak = true;
return;
} else if (r instanceof StringConstant || r instanceof NewExpr || r instanceof NewArrayExpr) {
usedAsObject = true;
doBreak = true;
return;
} else if (r instanceof CastExpr) {
usedAsObject = isObject(((CastExpr) r).getCastType());
doBreak = true;
return;
} else if (r instanceof InvokeExpr) {
usedAsObject = isObject(((InvokeExpr) r).getType());
doBreak = true;
return;
} else if (r instanceof LengthExpr) {
usedAsObject = false;
doBreak = true;
return;
// introduces alias
}
}
@Override
public void caseIdentityStmt(IdentityStmt stmt) {
if (stmt.getLeftOp() == l) {
usedAsObject = isObject(stmt.getRightOp().getType());
doBreak = true;
return;
}
}
};
AbstractStmtSwitch checkUse = new AbstractStmtSwitch() {
private boolean examineInvokeExpr(InvokeExpr e) {
List<Value> args = e.getArgs();
List<Type> argTypes = e.getMethodRef().parameterTypes();
assert args.size() == argTypes.size();
for (int i = 0; i < args.size(); i++) {
if (args.get(i) == l && isObject(argTypes.get(i))) {
return true;
}
}
// check for base
SootMethodRef sm = e.getMethodRef();
if (!sm.isStatic()) {
if (e instanceof AbstractInvokeExpr) {
AbstractInstanceInvokeExpr aiiexpr = (AbstractInstanceInvokeExpr) e;
Value b = aiiexpr.getBase();
if (b == l) {
return true;
}
}
}
return false;
}
@Override
public void caseInvokeStmt(InvokeStmt stmt) {
InvokeExpr e = stmt.getInvokeExpr();
usedAsObject = examineInvokeExpr(e);
doBreak = true;
return;
}
@Override
public void caseAssignStmt(AssignStmt stmt) {
Value left = stmt.getLeftOp();
Value r = stmt.getRightOp();
if (left instanceof ArrayRef) {
ArrayRef ar = (ArrayRef) left;
if (ar.getIndex() == l) {
doBreak = true;
return;
} else if (ar.getBase() == l) {
usedAsObject = true;
doBreak = true;
return;
}
}
if (left instanceof InstanceFieldRef) {
InstanceFieldRef ifr = (InstanceFieldRef) left;
if (ifr.getBase() == l) {
usedAsObject = true;
doBreak = true;
return;
}
}
// used to assign
if (stmt.getRightOp() == l) {
Value l = stmt.getLeftOp();
if (l instanceof StaticFieldRef && isObject(((StaticFieldRef) l).getFieldRef().type())) {
usedAsObject = true;
doBreak = true;
return;
} else if (l instanceof InstanceFieldRef && isObject(((InstanceFieldRef) l).getFieldRef().type())) {
usedAsObject = true;
doBreak = true;
return;
} else if (l instanceof ArrayRef) {
Type aType = ((ArrayRef) l).getType();
if (aType instanceof UnknownType) {
usedAsObject = stmt.hasTag(// isObject(
"ObjectOpTag");
// findArrayType(g,
// localDefs,
// localUses,
// stmt));
} else {
usedAsObject = isObject(aType);
}
doBreak = true;
return;
}
}
// is used as value (does not exclude assignment)
if (r instanceof FieldRef) {
// isObject(((FieldRef)
usedAsObject = true;
// r).getFieldRef().type());
doBreak = true;
return;
} else if (r instanceof ArrayRef) {
ArrayRef ar = (ArrayRef) r;
if (ar.getBase() == l) {
usedAsObject = true;
} else {
// used as index
usedAsObject = false;
}
doBreak = true;
return;
} else if (r instanceof StringConstant || r instanceof NewExpr) {
throw new RuntimeException("NOT POSSIBLE StringConstant or NewExpr at " + stmt);
} else if (r instanceof NewArrayExpr) {
usedAsObject = false;
doBreak = true;
return;
} else if (r instanceof CastExpr) {
usedAsObject = isObject(((CastExpr) r).getCastType());
doBreak = true;
return;
} else if (r instanceof InvokeExpr) {
usedAsObject = examineInvokeExpr((InvokeExpr) stmt.getRightOp());
doBreak = true;
return;
} else if (r instanceof LengthExpr) {
usedAsObject = true;
doBreak = true;
return;
} else if (r instanceof BinopExpr) {
usedAsObject = false;
doBreak = true;
return;
}
}
@Override
public void caseIdentityStmt(IdentityStmt stmt) {
if (stmt.getLeftOp() == l)
throw new RuntimeException("IMPOSSIBLE 0");
}
@Override
public void caseEnterMonitorStmt(EnterMonitorStmt stmt) {
usedAsObject = stmt.getOp() == l;
doBreak = true;
return;
}
@Override
public void caseExitMonitorStmt(ExitMonitorStmt stmt) {
usedAsObject = stmt.getOp() == l;
doBreak = true;
return;
}
@Override
public void caseReturnStmt(ReturnStmt stmt) {
usedAsObject = stmt.getOp() == l && isObject(body.getMethod().getReturnType());
doBreak = true;
return;
}
@Override
public void caseThrowStmt(ThrowStmt stmt) {
usedAsObject = stmt.getOp() == l;
doBreak = true;
return;
}
};
for (Local loc : getNullCandidates(body)) {
usedAsObject = false;
Set<Unit> defs = localDefs.collectDefinitionsWithAliases(loc);
// process normally
doBreak = false;
for (Unit u : defs) {
// put correct local in l
if (u instanceof DefinitionStmt) {
l = (Local) ((DefinitionStmt) u).getLeftOp();
} else if (u instanceof IfStmt) {
throw new RuntimeException("ERROR: def can not be something else than Assign or Identity statement! (def: " + u + " class: " + u.getClass() + "");
}
// check defs
u.apply(checkDef);
if (doBreak)
break;
// check uses
for (Unit use : localDefs.getUsesOf(l)) {
use.apply(checkUse);
if (doBreak)
break;
}
// for uses
if (doBreak)
break;
}
// change values
if (usedAsObject) {
for (Unit u : defs) {
replaceWithNull(u);
Set<Value> defLocals = new HashSet<Value>();
for (ValueBox vb : u.getDefBoxes()) defLocals.add(vb.getValue());
Local l = (Local) ((DefinitionStmt) u).getLeftOp();
for (Unit uuse : localDefs.getUsesOf(l)) {
Stmt use = (Stmt) uuse;
// If we have a[x] = 0 and a is an object, we may not conclude 0 -> null
if (!use.containsArrayRef() || !defLocals.contains(use.getArrayRef().getBase()))
replaceWithNull(use);
}
}
}
// end if
}
// Check for inlined zero values
AbstractStmtSwitch inlinedZeroValues = new AbstractStmtSwitch() {
final NullConstant nullConstant = NullConstant.v();
@Override
public void caseAssignStmt(AssignStmt stmt) {
// Case a = 0 with a being an object
if (isObject(stmt.getLeftOp().getType()) && isConstZero(stmt.getRightOp())) {
stmt.setRightOp(nullConstant);
return;
}
// Case a = (Object) 0
if (stmt.getRightOp() instanceof CastExpr) {
CastExpr ce = (CastExpr) stmt.getRightOp();
if (isObject(ce.getCastType()) && isConstZero(ce.getOp())) {
stmt.setRightOp(nullConstant);
}
}
// Case a[0] = 0
if (stmt.getLeftOp() instanceof ArrayRef && isConstZero(stmt.getRightOp())) {
ArrayRef ar = (ArrayRef) stmt.getLeftOp();
if (isObjectArray(ar.getBase(), body) || stmt.hasTag("ObjectOpTag")) {
stmt.setRightOp(nullConstant);
}
}
}
private boolean isConstZero(Value rightOp) {
if (rightOp instanceof IntConstant && ((IntConstant) rightOp).value == 0)
return true;
if (rightOp instanceof LongConstant && ((LongConstant) rightOp).value == 0)
return true;
return false;
}
@Override
public void caseReturnStmt(ReturnStmt stmt) {
if (stmt.getOp() instanceof IntConstant && isObject(body.getMethod().getReturnType())) {
IntConstant iconst = (IntConstant) stmt.getOp();
assert iconst.value == 0;
stmt.setOp(nullConstant);
}
}
@Override
public void caseEnterMonitorStmt(EnterMonitorStmt stmt) {
if (stmt.getOp() instanceof IntConstant && ((IntConstant) stmt.getOp()).value == 0)
stmt.setOp(nullConstant);
}
@Override
public void caseExitMonitorStmt(ExitMonitorStmt stmt) {
if (stmt.getOp() instanceof IntConstant && ((IntConstant) stmt.getOp()).value == 0)
stmt.setOp(nullConstant);
}
};
final NullConstant nullConstant = NullConstant.v();
for (Unit u : body.getUnits()) {
u.apply(inlinedZeroValues);
if (u instanceof Stmt) {
Stmt stmt = (Stmt) u;
if (stmt.containsInvokeExpr()) {
InvokeExpr invExpr = stmt.getInvokeExpr();
for (int i = 0; i < invExpr.getArgCount(); i++) if (isObject(invExpr.getMethodRef().parameterType(i)))
if (invExpr.getArg(i) instanceof IntConstant) {
IntConstant iconst = (IntConstant) invExpr.getArg(i);
assert iconst.value == 0;
invExpr.setArg(i, nullConstant);
}
}
}
}
}
use of soot.jimple.AbstractStmtSwitch in project soot by Sable.
the class DexIfTransformer method internalTransform.
@Override
protected void internalTransform(final Body body, String phaseName, Map<String, String> options) {
final DexDefUseAnalysis localDefs = new DexDefUseAnalysis(body);
Set<IfStmt> ifSet = getNullIfCandidates(body);
for (IfStmt ifs : ifSet) {
ConditionExpr ifCondition = (ConditionExpr) ifs.getCondition();
Local[] twoIfLocals = new Local[] { (Local) ifCondition.getOp1(), (Local) ifCondition.getOp2() };
usedAsObject = false;
for (Local loc : twoIfLocals) {
Set<Unit> defs = localDefs.collectDefinitionsWithAliases(loc);
// process normally
doBreak = false;
for (Unit u : defs) {
// put correct local in l
if (u instanceof DefinitionStmt) {
l = (Local) ((DefinitionStmt) u).getLeftOp();
} else {
throw new RuntimeException("ERROR: def can not be something else than Assign or Identity statement! (def: " + u + " class: " + u.getClass() + "");
}
// check defs
u.apply(new // Alex: should also end
AbstractStmtSwitch() {
// as soon as detected
// as not used as an
// object
@Override
public void caseAssignStmt(AssignStmt stmt) {
Value r = stmt.getRightOp();
if (r instanceof FieldRef) {
usedAsObject = isObject(((FieldRef) r).getFieldRef().type());
if (usedAsObject)
doBreak = true;
return;
} else if (r instanceof ArrayRef) {
ArrayRef ar = (ArrayRef) r;
if (ar.getType() instanceof UnknownType) {
// isObject
usedAsObject = stmt.hasTag("ObjectOpTag");
// (findArrayType
// (g,
// localDefs,
// localUses,
// stmt));
} else {
usedAsObject = isObject(ar.getType());
}
if (usedAsObject)
doBreak = true;
return;
} else if (r instanceof StringConstant || r instanceof NewExpr || r instanceof NewArrayExpr) {
usedAsObject = true;
if (usedAsObject)
doBreak = true;
return;
} else if (r instanceof CastExpr) {
usedAsObject = isObject(((CastExpr) r).getCastType());
if (usedAsObject)
doBreak = true;
return;
} else if (r instanceof InvokeExpr) {
usedAsObject = isObject(((InvokeExpr) r).getType());
if (usedAsObject)
doBreak = true;
return;
} else if (r instanceof LengthExpr) {
usedAsObject = false;
if (usedAsObject)
doBreak = true;
return;
}
}
@Override
public void caseIdentityStmt(IdentityStmt stmt) {
if (stmt.getLeftOp() == l) {
usedAsObject = isObject(stmt.getRightOp().getType());
if (usedAsObject)
doBreak = true;
return;
}
}
});
if (doBreak)
break;
// check uses
for (Unit use : localDefs.getUsesOf(l)) {
use.apply(new AbstractStmtSwitch() {
private boolean examineInvokeExpr(InvokeExpr e) {
List<Value> args = e.getArgs();
List<Type> argTypes = e.getMethodRef().parameterTypes();
assert args.size() == argTypes.size();
for (int i = 0; i < args.size(); i++) {
if (args.get(i) == l && isObject(argTypes.get(i))) {
return true;
}
}
// check for base
SootMethodRef sm = e.getMethodRef();
if (!sm.isStatic()) {
if (e instanceof AbstractInvokeExpr) {
AbstractInstanceInvokeExpr aiiexpr = (AbstractInstanceInvokeExpr) e;
Value b = aiiexpr.getBase();
if (b == l) {
return true;
}
}
}
return false;
}
@Override
public void caseInvokeStmt(InvokeStmt stmt) {
InvokeExpr e = stmt.getInvokeExpr();
usedAsObject = examineInvokeExpr(e);
if (usedAsObject)
doBreak = true;
return;
}
@Override
public void caseAssignStmt(AssignStmt stmt) {
Value left = stmt.getLeftOp();
Value r = stmt.getRightOp();
if (left instanceof ArrayRef) {
if (((ArrayRef) left).getIndex() == l) {
// doBreak = true;
return;
}
}
// used to assign
if (stmt.getRightOp() == l) {
Value l = stmt.getLeftOp();
if (l instanceof StaticFieldRef && isObject(((StaticFieldRef) l).getFieldRef().type())) {
usedAsObject = true;
if (usedAsObject)
doBreak = true;
return;
} else if (l instanceof InstanceFieldRef && isObject(((InstanceFieldRef) l).getFieldRef().type())) {
usedAsObject = true;
if (usedAsObject)
doBreak = true;
return;
} else if (l instanceof ArrayRef) {
Type aType = ((ArrayRef) l).getType();
if (aType instanceof UnknownType) {
// isObject(
usedAsObject = stmt.hasTag("ObjectOpTag");
// findArrayType(g,
// localDefs,
// localUses,
// stmt));
} else {
usedAsObject = isObject(aType);
}
if (usedAsObject)
doBreak = true;
return;
}
}
// assignment)
if (r instanceof FieldRef) {
// isObject(((FieldRef)
usedAsObject = true;
// r).getFieldRef().type());
if (usedAsObject)
doBreak = true;
return;
} else if (r instanceof ArrayRef) {
ArrayRef ar = (ArrayRef) r;
if (ar.getBase() == l) {
usedAsObject = true;
} else {
// used as index
usedAsObject = false;
}
if (usedAsObject)
doBreak = true;
return;
} else if (r instanceof StringConstant || r instanceof NewExpr) {
throw new RuntimeException("NOT POSSIBLE StringConstant or NewExpr at " + stmt);
} else if (r instanceof NewArrayExpr) {
usedAsObject = false;
if (usedAsObject)
doBreak = true;
return;
} else if (r instanceof CastExpr) {
usedAsObject = isObject(((CastExpr) r).getCastType());
if (usedAsObject)
doBreak = true;
return;
} else if (r instanceof InvokeExpr) {
usedAsObject = examineInvokeExpr((InvokeExpr) stmt.getRightOp());
if (usedAsObject)
doBreak = true;
return;
} else if (r instanceof LengthExpr) {
usedAsObject = true;
if (usedAsObject)
doBreak = true;
return;
} else if (r instanceof BinopExpr) {
usedAsObject = false;
if (usedAsObject)
doBreak = true;
return;
}
}
@Override
public void caseIdentityStmt(IdentityStmt stmt) {
if (stmt.getLeftOp() == l)
throw new RuntimeException("IMPOSSIBLE 0");
}
@Override
public void caseEnterMonitorStmt(EnterMonitorStmt stmt) {
usedAsObject = stmt.getOp() == l;
if (usedAsObject)
doBreak = true;
return;
}
@Override
public void caseExitMonitorStmt(ExitMonitorStmt stmt) {
usedAsObject = stmt.getOp() == l;
if (usedAsObject)
doBreak = true;
return;
}
@Override
public void caseReturnStmt(ReturnStmt stmt) {
usedAsObject = stmt.getOp() == l && isObject(body.getMethod().getReturnType());
if (usedAsObject)
doBreak = true;
return;
}
@Override
public void caseThrowStmt(ThrowStmt stmt) {
usedAsObject = stmt.getOp() == l;
if (usedAsObject)
doBreak = true;
return;
}
});
if (doBreak)
break;
}
// for uses
if (doBreak)
break;
}
if (// as soon as one def or use refers to an object
doBreak)
// be updated
break;
}
// change values
if (usedAsObject) {
Set<Unit> defsOp1 = localDefs.collectDefinitionsWithAliases(twoIfLocals[0]);
Set<Unit> defsOp2 = localDefs.collectDefinitionsWithAliases(twoIfLocals[1]);
defsOp1.addAll(defsOp2);
for (Unit u : defsOp1) {
Stmt s = (Stmt) u;
// If we have a[x] = 0 and a is an object, we may not conclude 0 -> null
if (!s.containsArrayRef() || (!defsOp1.contains(s.getArrayRef().getBase()) && !defsOp2.contains(s.getArrayRef().getBase())))
replaceWithNull(u);
Local l = (Local) ((DefinitionStmt) u).getLeftOp();
for (Unit uuse : localDefs.getUsesOf(l)) {
Stmt use = (Stmt) uuse;
// If we have a[x] = 0 and a is an object, we may not conclude 0 -> null
if (!use.containsArrayRef() || (twoIfLocals[0] != use.getArrayRef().getBase()) && twoIfLocals[1] != use.getArrayRef().getBase())
replaceWithNull(use);
}
}
}
// end if
}
// for if statements
}
Aggregations