+ MethodDescriptor calleeMethodDesc = min.getMethod();
+
+ NameDescriptor baseName = min.getBaseName();
+ boolean isSystemout = false;
+ if (baseName != null) {
+ isSystemout = baseName.getSymbol().equals("System.out");
+ }
+
+ if (!ssjava.isSSJavaUtil(calleeMethodDesc.getClassDesc())
+ && !ssjava.isTrustMethod(calleeMethodDesc) && !calleeMethodDesc.getModifiers().isNative()
+ && !isSystemout) {
+
+ CompositeLocation baseLocation = null;
+ if (min.getExpression() != null) {
+ baseLocation =
+ checkLocationFromExpressionNode(md, nametable, min.getExpression(),
+ new CompositeLocation(), constraint, false);
+ } else {
+ if (min.getMethod().isStatic()) {
+ String globalLocId = ssjava.getMethodLattice(md).getGlobalLoc();
+ if (globalLocId == null) {
+ throw new Error("Method lattice does not define global variable location at "
+ + generateErrorMessage(md.getClassDesc(), min));
+ }
+ baseLocation = new CompositeLocation(new Location(md, globalLocId));
+ } else {
+ String thisLocId = ssjava.getMethodLattice(md).getThisLoc();
+ baseLocation = new CompositeLocation(new Location(md, thisLocId));
+ }
+ }
+
+ // System.out.println("\n#checkLocationFromMethodInvokeNode=" +
+ // min.printNode(0)
+ // + " baseLocation=" + baseLocation + " constraint=" + constraint);
+
+ // setup the location list of caller's arguments
+ List<CompositeLocation> callerArgList = new ArrayList<CompositeLocation>();
+
+ // setup the location list of callee's parameters
+ MethodLattice<String> calleeLattice = ssjava.getMethodLattice(calleeMethodDesc);
+ List<CompositeLocation> calleeParamList = new ArrayList<CompositeLocation>();
+
+ if (min.numArgs() > 0) {
+ if (!calleeMethodDesc.isStatic()) {
+ callerArgList.add(baseLocation);
+ }
+ for (int i = 0; i < min.numArgs(); i++) {
+ ExpressionNode en = min.getArg(i);
+ CompositeLocation callerArgLoc =
+ checkLocationFromExpressionNode(md, nametable, en, new CompositeLocation(),
+ constraint, false);
+ callerArgList.add(callerArgLoc);
+ }
+
+ if (!calleeMethodDesc.isStatic()) {
+ CompositeLocation calleeThisLoc =
+ new CompositeLocation(new Location(calleeMethodDesc, calleeLattice.getThisLoc()));
+ calleeParamList.add(calleeThisLoc);
+ }
+
+ for (int i = 0; i < calleeMethodDesc.numParameters(); i++) {
+ VarDescriptor calleevd = (VarDescriptor) calleeMethodDesc.getParameter(i);
+ CompositeLocation calleeLoc = d2loc.get(calleevd);
+ calleeParamList.add(calleeLoc);
+ }
+ }
+
+ if (constraint != null) {
+ // check whether the PC location is lower than one of the
+ // argument locations. If it is lower, the callee has to have @PCLOC
+ // annotation that declares the program counter that is higher than
+ // corresponding parameter
+
+ CompositeLocation calleePCLOC = ssjava.getPCLocation(calleeMethodDesc);
+
+ for (int idx = 0; idx < callerArgList.size(); idx++) {
+ CompositeLocation argLocation = callerArgList.get(idx);
+
+ // need to check that param is higher than PCLOC
+ if (!argLocation.get(0).isTop()
+ && CompositeLattice.compare(argLocation, constraint, true,
+ generateErrorMessage(cd, min)) == ComparisonResult.GREATER) {
+
+ CompositeLocation paramLocation = calleeParamList.get(idx);
+
+ int paramCompareResult =
+ CompositeLattice.compare(calleePCLOC, paramLocation, true,
+ generateErrorMessage(cd, min));
+
+ if (paramCompareResult == ComparisonResult.GREATER) {
+ throw new Error(
+ "The program counter location "
+ + constraint
+ + " is lower than the argument(idx="
+ + idx
+ + ") location "
+ + argLocation
+ + ". Need to specify that the initial PC location of the callee, which is currently set to "
+ + calleePCLOC + ", is lower than " + paramLocation + " in the method "
+ + calleeMethodDesc.getSymbol() + ":" + min.getNumLine());
+ }
+
+ }
+
+ }
+
+ }
+
+ checkCalleeConstraints(md, nametable, min, baseLocation, constraint);
+
+ // checkCallerArgumentLocationConstraints(md, nametable, min,
+ // baseLocation, constraint);
+
+ 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, constraint);
+
+ if (ceilingLoc == null) {
+ return new CompositeLocation(Location.createTopLocation(md));
+ }
+ return ceilingLoc;
+ }
+ }
+
+ return new CompositeLocation(Location.createTopLocation(md));
+
+ }
+
+ private CompositeLocation translateCallerLocToCalleeLoc(MethodDescriptor calleeMD,
+ CompositeLocation calleeBaseLoc, CompositeLocation constraint) {
+
+ CompositeLocation calleeConstraint = new CompositeLocation();
+
+ // if (constraint.startsWith(calleeBaseLoc)) {
+ // if the first part of constraint loc is matched with callee base loc
+ Location thisLoc = new Location(calleeMD, ssjava.getMethodLattice(calleeMD).getThisLoc());
+ calleeConstraint.addLocation(thisLoc);
+ for (int i = calleeBaseLoc.getSize(); i < constraint.getSize(); i++) {
+ calleeConstraint.addLocation(constraint.get(i));
+ }
+
+ // }
+
+ return calleeConstraint;
+ }
+
+ private void checkCallerArgumentLocationConstraints(MethodDescriptor md, SymbolTable nametable,
+ MethodInvokeNode min, CompositeLocation callerBaseLoc, CompositeLocation constraint) {
+ // if parameter location consists of THIS and FIELD location,
+ // caller should pass an argument that is comparable to the declared
+ // parameter location
+ // and is not lower than the declared parameter location in the field
+ // lattice.
+
+ MethodDescriptor calleemd = min.getMethod();
+
+ List<CompositeLocation> callerArgList = new ArrayList<CompositeLocation>();
+ List<CompositeLocation> calleeParamList = new ArrayList<CompositeLocation>();
+
+ MethodLattice<String> calleeLattice = ssjava.getMethodLattice(calleemd);
+ Location calleeThisLoc = new Location(calleemd, calleeLattice.getThisLoc());
+
+ for (int i = 0; i < min.numArgs(); i++) {
+ ExpressionNode en = min.getArg(i);
+ CompositeLocation callerArgLoc =
+ checkLocationFromExpressionNode(md, nametable, en, new CompositeLocation(), constraint,
+ false);
+ callerArgList.add(callerArgLoc);
+ }
+
+ // setup callee params set
+ for (int i = 0; i < calleemd.numParameters(); i++) {
+ VarDescriptor calleevd = (VarDescriptor) calleemd.getParameter(i);
+ CompositeLocation calleeLoc = d2loc.get(calleevd);
+ calleeParamList.add(calleeLoc);
+ }
+
+ String errorMsg = generateErrorMessage(md.getClassDesc(), min);
+
+ // System.out.println("checkCallerArgumentLocationConstraints=" +
+ // min.printNode(0));
+ // System.out.println("base location=" + callerBaseLoc + " constraint=" +
+ // constraint);
+
+ for (int i = 0; i < calleeParamList.size(); i++) {
+ CompositeLocation calleeParamLoc = calleeParamList.get(i);
+ if (calleeParamLoc.get(0).equals(calleeThisLoc) && calleeParamLoc.getSize() > 1) {
+
+ // callee parameter location has field information
+ CompositeLocation callerArgLoc = callerArgList.get(i);
+
+ CompositeLocation paramLocation =
+ translateCalleeParamLocToCaller(md, calleeParamLoc, callerBaseLoc, errorMsg);
+
+ Set<CompositeLocation> inputGLBSet = new HashSet<CompositeLocation>();
+ if (constraint != null) {
+ inputGLBSet.add(callerArgLoc);
+ inputGLBSet.add(constraint);
+ callerArgLoc =
+ CompositeLattice.calculateGLB(inputGLBSet,
+ generateErrorMessage(md.getClassDesc(), min));
+ }
+
+ if (!CompositeLattice.isGreaterThan(callerArgLoc, paramLocation, errorMsg)) {
+ throw new Error("Caller argument '" + min.getArg(i).printNode(0) + " : " + callerArgLoc
+ + "' should be higher than corresponding callee's parameter : " + paramLocation
+ + " at " + errorMsg);
+ }
+
+ }
+ }
+
+ }
+
+ private CompositeLocation translateCalleeParamLocToCaller(MethodDescriptor md,
+ CompositeLocation calleeParamLoc, CompositeLocation callerBaseLocation, String errorMsg) {
+
+ CompositeLocation translate = new CompositeLocation();
+
+ for (int i = 0; i < callerBaseLocation.getSize(); i++) {
+ translate.addLocation(callerBaseLocation.get(i));
+ }
+
+ for (int i = 1; i < calleeParamLoc.getSize(); i++) {
+ translate.addLocation(calleeParamLoc.get(i));
+ }
+
+ // System.out.println("TRANSLATED=" + translate + " from calleeParamLoc=" +
+ // calleeParamLoc);
+
+ return translate;
+ }
+
+ private CompositeLocation computeCeilingLocationForCaller(MethodDescriptor md,
+ SymbolTable nametable, MethodInvokeNode min, CompositeLocation baseLocation,
+ CompositeLocation constraint) {
+ List<CompositeLocation> argList = new ArrayList<CompositeLocation>();
+
+ // by default, method has a THIS parameter
+ if (!md.isStatic()) {
+ argList.add(baseLocation);
+ }
+
+ for (int i = 0; i < min.numArgs(); i++) {
+ ExpressionNode en = min.getArg(i);
+ CompositeLocation callerArg =
+ checkLocationFromExpressionNode(md, nametable, en, new CompositeLocation(), constraint,
+ false);
+ argList.add(callerArg);
+ }
+
+ // System.out.println("\n## computeReturnLocation=" + min.getMethod() +
+ // " argList=" + argList);
+ CompositeLocation ceilLoc = md2ReturnLocGen.get(min.getMethod()).computeReturnLocation(argList);
+ // System.out.println("## ReturnLocation=" + ceilLoc);
+
+ return ceilLoc;