+
+class ReturnLocGenerator {
+
+ public static final int PARAMISHIGHER = 0;
+ public static final int PARAMISSAME = 1;
+ public static final int IGNORE = 2;
+
+ private Hashtable<Integer, Integer> paramIdx2paramType;
+
+ private CompositeLocation declaredReturnLoc = null;
+
+ public ReturnLocGenerator(CompositeLocation returnLoc, MethodDescriptor md,
+ List<CompositeLocation> params, String msg) {
+
+ CompositeLocation thisLoc = params.get(0);
+ if (returnLoc.get(0).equals(thisLoc.get(0)) && returnLoc.getSize() > 1) {
+ // if the declared return location consists of THIS and field location,
+ // return location for the caller's side has to have same field element
+ this.declaredReturnLoc = returnLoc;
+ } else {
+ // creating mappings
+ paramIdx2paramType = new Hashtable<Integer, Integer>();
+ for (int i = 0; i < params.size(); i++) {
+ CompositeLocation param = params.get(i);
+ int compareResult = CompositeLattice.compare(param, returnLoc, true, msg);
+
+ int type;
+ if (compareResult == ComparisonResult.GREATER) {
+ type = 0;
+ } else if (compareResult == ComparisonResult.EQUAL) {
+ type = 1;
+ } else {
+ type = 2;
+ }
+ paramIdx2paramType.put(new Integer(i), new Integer(type));
+ }
+ }
+
+ }
+
+ public CompositeLocation computeReturnLocation(List<CompositeLocation> args) {
+
+ if (declaredReturnLoc != null) {
+ // when developer specify that the return value is [THIS,field]
+ // needs to translate to the caller's location
+ CompositeLocation callerLoc = new CompositeLocation();
+ CompositeLocation callerBaseLocation = args.get(0);
+
+ for (int i = 0; i < callerBaseLocation.getSize(); i++) {
+ callerLoc.addLocation(callerBaseLocation.get(i));
+ }
+ for (int i = 1; i < declaredReturnLoc.getSize(); i++) {
+ callerLoc.addLocation(declaredReturnLoc.get(i));
+ }
+ return callerLoc;
+ } else {
+ // compute the highest possible location in caller's side
+ assert paramIdx2paramType.keySet().size() == args.size();
+
+ Set<CompositeLocation> inputGLB = new HashSet<CompositeLocation>();
+ for (int i = 0; i < args.size(); i++) {
+ int type = (paramIdx2paramType.get(new Integer(i))).intValue();
+ CompositeLocation argLoc = args.get(i);
+ if (type == PARAMISHIGHER) {
+ // return loc is lower than param
+ DeltaLocation delta = new DeltaLocation(argLoc, 1);
+ inputGLB.add(delta);
+ } else if (type == PARAMISSAME) {
+ // return loc is equal or lower than param
+ inputGLB.add(argLoc);
+ }
+ }
+
+ // compute GLB of arguments subset that are same or higher than return
+ // location
+ CompositeLocation glb = CompositeLattice.calculateGLB(inputGLB, "");
+ return glb;
+ }
+
+ }
+}