use of soot.jimple.NullConstant 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.NullConstant in project soot by Sable.
the class ConstraintChecker method caseIfStmt.
public void caseIfStmt(IfStmt stmt) {
ConditionExpr cond = (ConditionExpr) stmt.getCondition();
BinopExpr expr = cond;
Value lv = expr.getOp1();
Value rv = expr.getOp2();
TypeNode lop = null;
TypeNode rop = null;
// ******** LEFT ********
if (lv instanceof Local) {
if (((Local) lv).getType() instanceof IntegerType) {
lop = ClassHierarchy.v().typeNode(((Local) lv).getType());
}
} else if (lv instanceof DoubleConstant) {
} else if (lv instanceof FloatConstant) {
} else if (lv instanceof IntConstant) {
int value = ((IntConstant) lv).value;
if (value < -32768) {
lop = ClassHierarchy.v().INT;
} else if (value < -128) {
lop = ClassHierarchy.v().SHORT;
} else if (value < 0) {
lop = ClassHierarchy.v().BYTE;
} else if (value < 2) {
lop = ClassHierarchy.v().R0_1;
} else if (value < 128) {
lop = ClassHierarchy.v().R0_127;
} else if (value < 32768) {
lop = ClassHierarchy.v().R0_32767;
} else if (value < 65536) {
lop = ClassHierarchy.v().CHAR;
} else {
lop = ClassHierarchy.v().INT;
}
} else if (lv instanceof LongConstant) {
} else if (lv instanceof NullConstant) {
} else if (lv instanceof StringConstant) {
} else if (lv instanceof ClassConstant) {
} else {
throw new RuntimeException("Unhandled binary expression left operand type: " + lv.getClass());
}
// ******** RIGHT ********
if (rv instanceof Local) {
if (((Local) rv).getType() instanceof IntegerType) {
rop = ClassHierarchy.v().typeNode(((Local) rv).getType());
}
} else if (rv instanceof DoubleConstant) {
} else if (rv instanceof FloatConstant) {
} else if (rv instanceof IntConstant) {
int value = ((IntConstant) rv).value;
if (value < -32768) {
rop = ClassHierarchy.v().INT;
} else if (value < -128) {
rop = ClassHierarchy.v().SHORT;
} else if (value < 0) {
rop = ClassHierarchy.v().BYTE;
} else if (value < 2) {
rop = ClassHierarchy.v().R0_1;
} else if (value < 128) {
rop = ClassHierarchy.v().R0_127;
} else if (value < 32768) {
rop = ClassHierarchy.v().R0_32767;
} else if (value < 65536) {
rop = ClassHierarchy.v().CHAR;
} else {
rop = ClassHierarchy.v().INT;
}
} else if (rv instanceof LongConstant) {
} else if (rv instanceof NullConstant) {
} else if (rv instanceof StringConstant) {
} else if (rv instanceof ClassConstant) {
} else {
throw new RuntimeException("Unhandled binary expression right operand type: " + rv.getClass());
}
if (lop != null && rop != null) {
if (lop.lca_1(rop) == ClassHierarchy.v().TOP) {
if (fix) {
if (!lop.hasAncestor_1(ClassHierarchy.v().INT)) {
expr.setOp1(insertCast(expr.getOp1(), getTypeForCast(lop), getTypeForCast(rop), stmt));
}
if (!rop.hasAncestor_1(ClassHierarchy.v().INT)) {
expr.setOp2(insertCast(expr.getOp2(), getTypeForCast(rop), getTypeForCast(lop), stmt));
}
} else {
error("Type Error(17)");
}
}
}
}
use of soot.jimple.NullConstant in project soot by Sable.
the class OnFlyCallGraphBuilder method addInvokeCallSite.
/*
* How type based reflection resolution works:
*
* In general, for each call to invoke(), we record the local of the receiver
* argument and the argument array. Whenever a new type is added to the points
* to set of the receiver argument we add that type to the reachingBaseTypes and
* try to resolve the reflective method call (see addType, addBaseType, and
* updatedNode() in OnFlyCallGraph).
*
* For added precision, we also record the second argument to invoke. If it is
* always null, this means the invoke() call resolves only to nullary methods.
*
* When the second argument is a variable that must not be null we can narrow
* down the called method based on the possible sizes of the argument array and
* the types it contains. Whenever a new allocation reaches this variable we
* record the possible size of the array (by looking at the allocation site) and
* the possible types stored in the array (see updatedNode in OnFlyCallGraph in
* the branch wantInvokeArg()). If the size of the array isn't statically known,
* the analysis considers methods of all possible arities. In addition, we track
* the PAG node corresponding to the array contents. If a new type reaches this
* node, we update the possible argument types. (see propagate() in PropWorklist
* and the visitor, and updatedFieldRef in OnFlyCallGraph).
*
* For details on the method resolution process, see resolveInvoke()
*
* Finally, for cases like o.invoke(b, foo, bar, baz); it is very easy to
* statically determine precisely which types are in which argument positions.
* This is computed using the ConstantArrayAnalysis and are resolved using
* resolveStaticTypes().
*/
private void addInvokeCallSite(Stmt s, SootMethod container, InstanceInvokeExpr d) {
Local l = (Local) d.getArg(0);
Value argArray = d.getArg(1);
InvokeCallSite ics;
if (argArray instanceof NullConstant) {
ics = new InvokeCallSite(s, container, d, l);
} else {
if (analysisKey != container) {
ExceptionalUnitGraph graph = new ExceptionalUnitGraph(container.getActiveBody());
nullnessCache = new NullnessAnalysis(graph);
arrayCache = new ConstantArrayAnalysis(graph, container.getActiveBody());
analysisKey = container;
}
Local argLocal = (Local) argArray;
int nullnessCode;
if (nullnessCache.isAlwaysNonNullBefore(s, argLocal)) {
nullnessCode = InvokeCallSite.MUST_NOT_BE_NULL;
} else if (nullnessCache.isAlwaysNullBefore(s, argLocal)) {
nullnessCode = InvokeCallSite.MUST_BE_NULL;
} else {
nullnessCode = InvokeCallSite.MAY_BE_NULL;
}
if (nullnessCode != InvokeCallSite.MUST_BE_NULL && arrayCache.isConstantBefore(s, argLocal)) {
ArrayTypes reachingArgTypes = arrayCache.getArrayTypesBefore(s, argLocal);
if (nullnessCode == InvokeCallSite.MAY_BE_NULL) {
reachingArgTypes.possibleSizes.add(0);
}
ics = new InvokeCallSite(s, container, d, l, reachingArgTypes, nullnessCode);
} else {
ics = new InvokeCallSite(s, container, d, l, argLocal, nullnessCode);
invokeArgsToInvokeSite.put(argLocal, ics);
}
}
baseToInvokeSite.put(l, ics);
}
use of soot.jimple.NullConstant in project soot by Sable.
the class ConstantArrayAnalysis method flowThrough.
@Override
protected void flowThrough(ArrayState in, Unit d, ArrayState out) {
out.active.clear();
out.active.or(in.active);
out.state = Arrays.copyOf(in.state, in.state.length);
if (d instanceof DefinitionStmt) {
DefinitionStmt ds = (DefinitionStmt) d;
Value rhs = ds.getRightOp();
Value lhs = ds.getLeftOp();
if (rhs instanceof NewArrayExpr) {
Local l = (Local) lhs;
int varRef = localToInt.get(l);
NewArrayExpr nae = (NewArrayExpr) rhs;
out.active.set(varRef);
if (!(nae.getSize() instanceof IntConstant)) {
out.state[varRef] = null;
} else {
int arraySize = ((IntConstant) nae.getSize()).value;
out.state[varRef] = new ArrayTypesInternal();
out.state[varRef].sizeState.set(sizeToInt.get(arraySize));
out.state[varRef].typeState = new BitSet[arraySize];
out.state[varRef].mustAssign = new BitSet(arraySize);
for (int i = 0; i < arraySize; i++) {
out.state[varRef].typeState[i] = new BitSet(typeSize);
}
}
} else if (lhs instanceof Local && lhs.getType() instanceof ArrayType && rhs instanceof NullConstant) {
int varRef = localToInt.get(lhs);
out.active.clear(varRef);
out.state[varRef] = null;
} else if (lhs instanceof Local && rhs instanceof Local && in.state[localToInt.get(rhs)] != null && in.active.get(localToInt.get(rhs))) {
int lhsRef = localToInt.get(lhs);
int rhsRef = localToInt.get(rhs);
out.active.set(lhsRef);
out.state[lhsRef] = in.state[rhsRef];
out.state[rhsRef] = null;
} else if (lhs instanceof Local && rhs instanceof PhiExpr) {
PhiExpr rPhi = (PhiExpr) rhs;
int lhsRef = localToInt.get(lhs);
out.state[lhsRef] = null;
int i = 0;
List<Value> phiValues = rPhi.getValues();
for (; i < phiValues.size(); i++) {
Value v = phiValues.get(i);
int argRef = localToInt.get(v);
if (!in.active.get(argRef)) {
continue;
}
out.active.set(lhsRef);
// one bottom -> all bottom
if (in.state[argRef] == null) {
out.state[lhsRef] = null;
break;
}
if (out.state[lhsRef] == null) {
out.state[lhsRef] = in.state[argRef];
} else {
out.state[lhsRef] = mergeTypeStates(in.state[argRef], out.state[lhsRef]);
}
out.state[argRef] = null;
}
for (; i < phiValues.size(); i++) {
int argRef = localToInt.get(phiValues.get(i));
out.state[argRef] = null;
}
} else if (lhs instanceof ArrayRef) {
ArrayRef ar = (ArrayRef) lhs;
Value indexVal = ar.getIndex();
int localRef = localToInt.get(ar.getBase());
if (!(indexVal instanceof IntConstant)) {
out.state[localRef] = null;
out.active.set(localRef);
} else if (out.state[localRef] != null) {
Type assignType = rhs.getType();
int index = ((IntConstant) indexVal).value;
assert index < out.state[localRef].typeState.length;
out.deepCloneLocalValueSlot(localRef, index);
assert out.state[localRef].typeState[index] != null : d;
out.state[localRef].typeState[index].set(typeToInt.get(assignType));
out.state[localRef].mustAssign.set(index);
}
} else {
Value leftOp = lhs;
if (leftOp instanceof Local) {
Local defLocal = (Local) leftOp;
int varRef = localToInt.get(defLocal);
out.active.set(varRef);
out.state[varRef] = null;
}
}
for (ValueBox b : rhs.getUseBoxes()) {
if (localToInt.containsKey(b.getValue())) {
int localRef = localToInt.get(b.getValue());
out.state[localRef] = null;
out.active.set(localRef);
}
}
if (localToInt.containsKey(rhs)) {
int localRef = localToInt.get(rhs);
out.state[localRef] = null;
out.active.set(localRef);
}
} else {
for (ValueBox b : d.getUseBoxes()) {
if (localToInt.containsKey(b.getValue())) {
int localRef = localToInt.get(b.getValue());
out.state[localRef] = null;
out.active.set(localRef);
}
}
}
}
use of soot.jimple.NullConstant in project soot by Sable.
the class UseChecker method caseAssignStmt.
public void caseAssignStmt(AssignStmt stmt) {
Value lhs = stmt.getLeftOp();
Value rhs = stmt.getRightOp();
Type tlhs = null;
if (lhs instanceof Local)
tlhs = this.tg.get((Local) lhs);
else if (lhs instanceof ArrayRef) {
ArrayRef aref = (ArrayRef) lhs;
Local base = (Local) aref.getBase();
// Try to force Type integrity. The left side must agree on the
// element type of the right side array reference.
ArrayType at = null;
Type tgType = this.tg.get(base);
if (tgType instanceof ArrayType)
at = (ArrayType) tgType;
else {
// is java.lang.Object
if (tgType == Scene.v().getObjectType() && rhs instanceof Local) {
Type rhsType = this.tg.get((Local) rhs);
if (rhsType instanceof PrimType) {
if (defs == null) {
defs = LocalDefs.Factory.newLocalDefs(jb);
uses = LocalUses.Factory.newLocalUses(jb, defs);
}
// Check the original type of the array from the alloc site
for (Unit defU : defs.getDefsOfAt(base, stmt)) {
if (defU instanceof AssignStmt) {
AssignStmt defUas = (AssignStmt) defU;
if (defUas.getRightOp() instanceof NewArrayExpr) {
at = (ArrayType) defUas.getRightOp().getType();
break;
}
}
}
}
}
if (at == null)
at = tgType.makeArrayType();
}
tlhs = ((ArrayType) at).getElementType();
this.handleArrayRef(aref, stmt);
aref.setBase((Local) this.uv.visit(aref.getBase(), at, stmt));
stmt.setRightOp(this.uv.visit(rhs, tlhs, stmt));
stmt.setLeftOp(this.uv.visit(lhs, tlhs, stmt));
} else if (lhs instanceof FieldRef) {
tlhs = ((FieldRef) lhs).getFieldRef().type();
if (lhs instanceof InstanceFieldRef)
this.handleInstanceFieldRef((InstanceFieldRef) lhs, stmt);
}
// They may have been changed above
lhs = stmt.getLeftOp();
rhs = stmt.getRightOp();
if (rhs instanceof Local)
stmt.setRightOp(this.uv.visit(rhs, tlhs, stmt));
else if (rhs instanceof ArrayRef) {
ArrayRef aref = (ArrayRef) rhs;
Local base = (Local) aref.getBase();
// try to force Type integrity
ArrayType at = null;
Type et = null;
if (this.tg.get(base) instanceof ArrayType)
at = (ArrayType) this.tg.get(base);
else {
Type bt = this.tg.get(base);
// For some fixed type T, we assume that we can fix the array to T[].
if (bt instanceof RefType || bt instanceof NullType) {
RefType rt = bt instanceof NullType ? null : (RefType) bt;
if (rt == null || rt.getSootClass().getName().equals("java.lang.Object") || rt.getSootClass().getName().equals("java.io.Serializable") || rt.getSootClass().getName().equals("java.lang.Cloneable")) {
if (defs == null) {
defs = LocalDefs.Factory.newLocalDefs(jb);
uses = LocalUses.Factory.newLocalUses(jb, defs);
}
outer: for (UnitValueBoxPair usePair : uses.getUsesOf(stmt)) {
Stmt useStmt = (Stmt) usePair.getUnit();
// from the callee's signature=
if (useStmt.containsInvokeExpr()) {
for (int i = 0; i < useStmt.getInvokeExpr().getArgCount(); i++) {
if (useStmt.getInvokeExpr().getArg(i) == usePair.getValueBox().getValue()) {
et = useStmt.getInvokeExpr().getMethod().getParameterType(i);
at = et.makeArrayType();
break outer;
}
}
} else // if the other value is a primitive.
if (useStmt instanceof IfStmt) {
IfStmt ifStmt = (IfStmt) useStmt;
if (ifStmt.getCondition() instanceof EqExpr) {
EqExpr expr = (EqExpr) ifStmt.getCondition();
final Value other;
if (expr.getOp1() == usePair.getValueBox().getValue())
other = expr.getOp2();
else
other = expr.getOp1();
Type newEt = getTargetType(other);
if (newEt != null)
et = newEt;
}
} else if (useStmt instanceof AssignStmt) {
// For binary expressions, we can look for type information in the
// other operands
AssignStmt useAssignStmt = (AssignStmt) useStmt;
if (useAssignStmt.getRightOp() instanceof BinopExpr) {
BinopExpr binOp = (BinopExpr) useAssignStmt.getRightOp();
final Value other;
if (binOp.getOp1() == usePair.getValueBox().getValue())
other = binOp.getOp2();
else
other = binOp.getOp1();
Type newEt = getTargetType(other);
if (newEt != null)
et = newEt;
}
} else if (useStmt instanceof ReturnStmt) {
et = jb.getMethod().getReturnType();
}
}
}
}
if (at == null)
at = et.makeArrayType();
}
Type trhs = ((ArrayType) at).getElementType();
this.handleArrayRef(aref, stmt);
aref.setBase((Local) this.uv.visit(aref.getBase(), at, stmt));
stmt.setRightOp(this.uv.visit(rhs, trhs, stmt));
} else if (rhs instanceof InstanceFieldRef) {
this.handleInstanceFieldRef((InstanceFieldRef) rhs, stmt);
stmt.setRightOp(this.uv.visit(rhs, tlhs, stmt));
} else if (rhs instanceof BinopExpr)
this.handleBinopExpr((BinopExpr) rhs, stmt, tlhs);
else if (rhs instanceof InvokeExpr) {
this.handleInvokeExpr((InvokeExpr) rhs, stmt);
stmt.setRightOp(this.uv.visit(rhs, tlhs, stmt));
} else if (rhs instanceof CastExpr)
stmt.setRightOp(this.uv.visit(rhs, tlhs, stmt));
else if (rhs instanceof InstanceOfExpr) {
InstanceOfExpr ioe = (InstanceOfExpr) rhs;
ioe.setOp(this.uv.visit(ioe.getOp(), RefType.v("java.lang.Object"), stmt));
stmt.setRightOp(this.uv.visit(rhs, tlhs, stmt));
} else if (rhs instanceof NewArrayExpr) {
NewArrayExpr nae = (NewArrayExpr) rhs;
nae.setSize(this.uv.visit(nae.getSize(), IntType.v(), stmt));
stmt.setRightOp(this.uv.visit(rhs, tlhs, stmt));
} else if (rhs instanceof NewMultiArrayExpr) {
NewMultiArrayExpr nmae = (NewMultiArrayExpr) rhs;
for (int i = 0; i < nmae.getSizeCount(); i++) nmae.setSize(i, this.uv.visit(nmae.getSize(i), IntType.v(), stmt));
stmt.setRightOp(this.uv.visit(rhs, tlhs, stmt));
} else if (rhs instanceof LengthExpr) {
stmt.setRightOp(this.uv.visit(rhs, tlhs, stmt));
} else if (rhs instanceof NegExpr) {
((NegExpr) rhs).setOp(this.uv.visit(((NegExpr) rhs).getOp(), tlhs, stmt));
} else if (rhs instanceof Constant)
if (!(rhs instanceof NullConstant))
stmt.setRightOp(this.uv.visit(rhs, tlhs, stmt));
}
Aggregations