+ // addTypeLocation(en.getType(), compLoc);
+ return compLoc;
+
+ }
+
+ private CompositeLocation checkLocationFromCastNode(MethodDescriptor md, SymbolTable nametable,
+ CastNode cn) {
+
+ ExpressionNode en = cn.getExpression();
+ return checkLocationFromExpressionNode(md, nametable, en, new CompositeLocation());
+
+ }
+
+ private CompositeLocation checkLocationFromTertiaryNode(MethodDescriptor md,
+ SymbolTable nametable, TertiaryNode tn) {
+ ClassDescriptor cd = md.getClassDesc();
+
+ CompositeLocation condLoc =
+ checkLocationFromExpressionNode(md, nametable, tn.getCond(), new CompositeLocation());
+ addTypeLocation(tn.getCond().getType(), condLoc);
+ CompositeLocation trueLoc =
+ checkLocationFromExpressionNode(md, nametable, tn.getTrueExpr(), new CompositeLocation());
+ addTypeLocation(tn.getTrueExpr().getType(), trueLoc);
+ CompositeLocation falseLoc =
+ checkLocationFromExpressionNode(md, nametable, tn.getFalseExpr(), new CompositeLocation());
+ addTypeLocation(tn.getFalseExpr().getType(), falseLoc);
+
+ // check if condLoc is higher than trueLoc & falseLoc
+ if (!CompositeLattice.isGreaterThan(condLoc, trueLoc)) {
+ throw new Error(
+ "The location of the condition expression is lower than the true expression at "
+ + cd.getSourceFileName() + ":" + tn.getCond().getNumLine());
+ }
+
+ if (!CompositeLattice.isGreaterThan(condLoc, falseLoc)) {
+ throw new Error(
+ "The location of the condition expression is lower than the true expression at "
+ + cd.getSourceFileName() + ":" + tn.getCond().getNumLine());
+ }
+
+ // then, return glb of trueLoc & falseLoc
+ Set<CompositeLocation> glbInputSet = new HashSet<CompositeLocation>();
+ glbInputSet.add(trueLoc);
+ glbInputSet.add(falseLoc);
+
+ return CompositeLattice.calculateGLB(glbInputSet);
+ }
+
+ private CompositeLocation checkLocationFromMethodInvokeNode(MethodDescriptor md,
+ SymbolTable nametable, MethodInvokeNode min, CompositeLocation loc) {
+
+ checkCalleeConstraints(md, nametable, min);
+
+ CompositeLocation baseLocation = null;
+ if (min.getExpression() != null) {
+ baseLocation =
+ checkLocationFromExpressionNode(md, nametable, min.getExpression(),
+ new CompositeLocation());
+ } else {
+ String thisLocId = ssjava.getMethodLattice(md).getThisLoc();
+ baseLocation = new CompositeLocation(new Location(md, thisLocId));
+ }
+
+ if (!min.getMethod().getReturnType().isVoid()) {
+ // If method has a return value, compute the highest possible return
+ // location in the caller's perspective
+ CompositeLocation ceilingLoc =
+ computeCeilingLocationForCaller(md, nametable, min, baseLocation);
+ return ceilingLoc;
+ }
+
+ return new CompositeLocation();
+
+ }
+
+ private CompositeLocation computeCeilingLocationForCaller(MethodDescriptor md,
+ SymbolTable nametable, MethodInvokeNode min, CompositeLocation baseLocation) {
+ List<CompositeLocation> argList = new ArrayList<CompositeLocation>();
+
+ // by default, method has a THIS parameter
+ argList.add(baseLocation);
+
+ for (int i = 0; i < min.numArgs(); i++) {
+ ExpressionNode en = min.getArg(i);
+ CompositeLocation callerArg =
+ checkLocationFromExpressionNode(md, nametable, en, new CompositeLocation());
+ argList.add(callerArg);
+ }
+
+ return md2ReturnLocGen.get(min.getMethod()).computeReturnLocation(argList);
+
+ }
+
+ private void checkCalleeConstraints(MethodDescriptor md, SymbolTable nametable,
+ MethodInvokeNode min) {
+
+ if (min.numArgs() > 1) {
+ // caller needs to guarantee that it passes arguments in regarding to
+ // callee's hierarchy
+ for (int i = 0; i < min.numArgs(); i++) {
+ ExpressionNode en = min.getArg(i);
+ CompositeLocation callerArg1 =
+ checkLocationFromExpressionNode(md, nametable, en, new CompositeLocation());
+
+ ClassDescriptor calleecd = min.getMethod().getClassDesc();
+ VarDescriptor calleevd = (VarDescriptor) min.getMethod().getParameter(i);
+ CompositeLocation calleeLoc1 = d2loc.get(calleevd);
+
+ if (!callerArg1.get(0).isTop()) {
+ // here, check if ordering relations among caller's args respect
+ // ordering relations in-between callee's args
+ for (int currentIdx = 0; currentIdx < min.numArgs(); currentIdx++) {
+ if (currentIdx != i) { // skip itself
+ ExpressionNode argExp = min.getArg(currentIdx);
+
+ CompositeLocation callerArg2 =
+ checkLocationFromExpressionNode(md, nametable, argExp, new CompositeLocation());
+
+ VarDescriptor calleevd2 = (VarDescriptor) min.getMethod().getParameter(currentIdx);
+ CompositeLocation calleeLoc2 = d2loc.get(calleevd2);
+
+ boolean callerResult = CompositeLattice.isGreaterThan(callerArg1, callerArg2);
+ boolean calleeResult = CompositeLattice.isGreaterThan(calleeLoc1, calleeLoc2);
+
+ if (calleeResult && !callerResult) {
+ // If calleeLoc1 is higher than calleeLoc2
+ // then, caller should have same ordering relation in-bet
+ // callerLoc1 & callerLoc2
+
+ throw new Error("Caller doesn't respect ordering relations among method arguments:"
+ + md.getClassDesc().getSourceFileName() + ":" + min.getNumLine());
+ }
+
+ }
+ }
+ }
+
+ }
+
+ }
+
+ }
+
+ private CompositeLocation checkLocationFromArrayAccessNode(MethodDescriptor md,
+ SymbolTable nametable, ArrayAccessNode aan) {
+
+ // return glb location of array itself and index
+
+ ClassDescriptor cd = md.getClassDesc();
+
+ Set<CompositeLocation> glbInputSet = new HashSet<CompositeLocation>();
+
+ CompositeLocation arrayLoc =
+ checkLocationFromExpressionNode(md, nametable, aan.getExpression(), new CompositeLocation());
+ // addTypeLocation(aan.getExpression().getType(), arrayLoc);
+ glbInputSet.add(arrayLoc);
+ CompositeLocation indexLoc =
+ checkLocationFromExpressionNode(md, nametable, aan.getIndex(), new CompositeLocation());
+ glbInputSet.add(indexLoc);
+ // addTypeLocation(aan.getIndex().getType(), indexLoc);
+
+ CompositeLocation glbLoc = CompositeLattice.calculateGLB(glbInputSet);
+ return glbLoc;
+ }
+
+ private CompositeLocation checkLocationFromCreateObjectNode(MethodDescriptor md,
+ SymbolTable nametable, CreateObjectNode con) {
+
+ ClassDescriptor cd = md.getClassDesc();
+
+ // check arguments
+ Set<CompositeLocation> glbInputSet = new HashSet<CompositeLocation>();
+ for (int i = 0; i < con.numArgs(); i++) {
+ ExpressionNode en = con.getArg(i);
+ CompositeLocation argLoc =
+ checkLocationFromExpressionNode(md, nametable, en, new CompositeLocation());
+ glbInputSet.add(argLoc);
+ addTypeLocation(en.getType(), argLoc);
+ }
+
+ // check array initializers
+ // if ((con.getArrayInitializer() != null)) {
+ // checkLocationFromArrayInitializerNode(md, nametable,
+ // con.getArrayInitializer());
+ // }
+
+ if (glbInputSet.size() > 0) {
+ return CompositeLattice.calculateGLB(glbInputSet);
+ }
+
+ CompositeLocation compLoc = new CompositeLocation();
+ compLoc.addLocation(Location.createTopLocation(md));
+ return compLoc;