+ private CompositeLocation checkLocationFromCastNode(MethodDescriptor md, SymbolTable nametable,
+ CastNode cn, CompositeLocation constraint) {
+
+ ExpressionNode en = cn.getExpression();
+ return checkLocationFromExpressionNode(md, nametable, en, new CompositeLocation(), constraint,
+ false);
+
+ }
+
+ private CompositeLocation checkLocationFromTertiaryNode(MethodDescriptor md,
+ SymbolTable nametable, TertiaryNode tn, CompositeLocation constraint) {
+ ClassDescriptor cd = md.getClassDesc();
+
+ CompositeLocation condLoc =
+ checkLocationFromExpressionNode(md, nametable, tn.getCond(), new CompositeLocation(),
+ constraint, false);
+ // addLocationType(tn.getCond().getType(), condLoc);
+ CompositeLocation trueLoc =
+ checkLocationFromExpressionNode(md, nametable, tn.getTrueExpr(), new CompositeLocation(),
+ constraint, false);
+ // addLocationType(tn.getTrueExpr().getType(), trueLoc);
+ CompositeLocation falseLoc =
+ checkLocationFromExpressionNode(md, nametable, tn.getFalseExpr(), new CompositeLocation(),
+ constraint, false);
+ // addLocationType(tn.getFalseExpr().getType(), falseLoc);
+
+ // locations from true/false branches can be TOP when there are only literal
+ // values
+ // in this case, we don't need to check flow down rule!
+
+ // System.out.println("\n#tertiary cond=" + tn.getCond().printNode(0) +
+ // " Loc=" + condLoc);
+ // System.out.println("# true=" + tn.getTrueExpr().printNode(0) + " Loc=" +
+ // trueLoc);
+ // System.out.println("# false=" + tn.getFalseExpr().printNode(0) + " Loc="
+ // + falseLoc);
+
+ // check if condLoc is higher than trueLoc & falseLoc
+ if (!trueLoc.get(0).isTop()
+ && !CompositeLattice.isGreaterThan(condLoc, trueLoc, generateErrorMessage(cd, tn))) {
+ throw new Error(
+ "The location of the condition expression is lower than the true expression at "
+ + cd.getSourceFileName() + ":" + tn.getCond().getNumLine());
+ }
+
+ 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 calleeMD = min.getMethod();
+
+ NameDescriptor baseName = min.getBaseName();
+ boolean isSystemout = false;
+ if (baseName != null) {
+ isSystemout = baseName.getSymbol().equals("System.out");
+ }
+
+ if (!ssjava.isSSJavaUtil(calleeMD.getClassDesc()) && !ssjava.isTrustMethod(calleeMD)
+ && !calleeMD.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>();
+
+ if (min.numArgs() > 0) {
+ // setup caller args set
+ // first, add caller's base(this) location
+ callerArgList.add(baseLocation);
+ // second, add caller's arguments
+ 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 the location list of callee's parameters
+ MethodDescriptor calleemd = min.getMethod();
+ MethodLattice<String> calleeLattice = ssjava.getMethodLattice(calleemd);
+ CompositeLocation calleeThisLoc =
+ new CompositeLocation(new Location(calleemd, calleeLattice.getThisLoc()));
+ List<CompositeLocation> calleeParamList = new ArrayList<CompositeLocation>();
+ // first, add callee's this location
+ calleeParamList.add(calleeThisLoc);
+ // second, add callee's parameters
+ for (int i = 0; i < calleemd.numParameters(); i++) {
+ VarDescriptor calleevd = (VarDescriptor) calleemd.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(calleemd);
+
+ for (int idx = 0; idx < callerArgList.size(); idx++) {
+ CompositeLocation argLocation = callerArgList.get(idx);
+
+ int compareResult =
+ CompositeLattice
+ .compare(argLocation, constraint, true, generateErrorMessage(cd, min));
+
+ // need to check that param is higher than PCLOC
+ if (compareResult == 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 "
+ + calleeMD.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);
+ 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;
+ }