+ if (!falseLoc.get(0).isTop()
+ && !CompositeLattice.isGreaterThan(condLoc, falseLoc,
+ generateErrorMessage(cd, tn.getCond()))) {
+ throw new Error(
+ "The location of the condition expression is lower than the false 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);
+
+ if (glbInputSet.size() == 1) {
+ return trueLoc;
+ } else {
+ return CompositeLattice.calculateGLB(glbInputSet, generateErrorMessage(cd, tn));
+ }
+
+ }
+
+ private CompositeLocation checkLocationFromMethodInvokeNode(MethodDescriptor md,
+ SymbolTable nametable, MethodInvokeNode min, CompositeLocation loc,
+ CompositeLocation constraint) {
+
+ ClassDescriptor cd = md.getClassDesc();
+ 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);
+
+ // if the PC location is lower than an argument location
+ // then, need to check that the callee's the initial location for the PC is also lower
+ // than the corresponding parameter location
+
+ if (!argLocation.get(0).isTop()
+ && CompositeLattice.compare(argLocation, constraint, true,
+ generateErrorMessage(cd, min)) == ComparisonResult.LESS) {
+
+ CompositeLocation paramLocation = calleeParamList.get(idx);
+
+ int paramCompareResult =
+ CompositeLattice.compare(paramLocation, calleePCLOC, true,
+ generateErrorMessage(cd, min));
+ // CompositeLattice.compare(calleePCLOC, paramLocation, true,
+ // generateErrorMessage(cd, min));
+
+ System.out.println("-CHECKPCLOC:");
+ System.out.println("---ARG LOC="
+ + argLocation
+ + " callerPCLOC="
+ + constraint
+ + " result="
+ + CompositeLattice.compare(argLocation, constraint, true,
+ generateErrorMessage(cd, min)));
+ System.out.println("---PARAM LOC=" + paramLocation + " calleePCLOC=" + calleePCLOC
+ + " paramCompareResult=" + paramCompareResult);
+
+ if (!(paramLocation.get(0).equals(calleePCLOC.get(0)) && calleePCLOC.getSize() > 1)
+ && paramCompareResult != ComparisonResult.LESS) {
+ 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();
+
+ if (calleemd.isStatic()) {
+ return;
+ }
+
+ 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));
+ }
+
+ Location argLastLoc = callerArgLoc.get(callerArgLoc.getSize() - 1);
+ Location paramLastLoc = paramLocation.get(paramLocation.getSize() - 1);
+
+ if (argLastLoc.equals(paramLastLoc) && ssjava.isSharedLocation(argLastLoc)
+ && ssjava.isSharedLocation(paramLastLoc)) {
+ continue;
+ }
+
+ // if (!CompositeLattice.isGreaterThan(callerArgLoc, paramLocation, errorMsg)) {
+ if (CompositeLattice.compare(callerArgLoc, paramLocation, true, errorMsg) == ComparisonResult.LESS) {
+ 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));