SootMethod container = guard.container;
Stmt insertionPoint = guard.stmt;
if(!container.hasActiveBody()) {
G.v().out.println("WARNING: Tried to insert guard into "+container+" but couldn't because method has no body.");
} else {
Body body = container.getActiveBody();
//exc = new Error
RefType runtimeExceptionType = RefType.v("java.lang.Error");
NewExpr newExpr = Jimple.v().newNewExpr(runtimeExceptionType);
LocalGenerator lg = new LocalGenerator(body);
Local exceptionLocal = lg.generateLocal(runtimeExceptionType);
AssignStmt assignStmt = Jimple.v().newAssignStmt(exceptionLocal, newExpr);
body.getUnits().insertBefore(assignStmt, insertionPoint);
//exc.<init>(message)
SootMethodRef cref = runtimeExceptionType.getSootClass().getMethod("<init>", Collections.singletonList(RefType.v("java.lang.String"))).makeRef();
SpecialInvokeExpr constructorInvokeExpr = Jimple.v().newSpecialInvokeExpr(exceptionLocal, cref, StringConstant.v(guard.message));
InvokeStmt initStmt = Jimple.v().newInvokeStmt(constructorInvokeExpr);
body.getUnits().insertAfter(initStmt, assignStmt);
if(options.guards().equals("print")) {
//exc.printStackTrace();
VirtualInvokeExpr printStackTraceExpr = Jimple.v().newVirtualInvokeExpr(exceptionLocal, Scene.v().getSootClass("java.lang.Throwable").getMethod("printStackTrace", Collections.emptyList()).makeRef());
InvokeStmt printStackTraceStmt = Jimple.v().newInvokeStmt(printStackTraceExpr);
body.getUnits().insertAfter(printStackTraceStmt, initStmt);
} else if(options.guards().equals("throw")) {
body.getUnits().insertAfter(Jimple.v().newThrowStmt(exceptionLocal), initStmt);
} else {
throw new RuntimeException("Invalid value for phase option (guarding): "+options.guards());
}
}
}