X-Git-Url: http://plrg.eecs.uci.edu/git/?p=IRC.git;a=blobdiff_plain;f=Robust%2Fsrc%2FAnalysis%2FSSJava%2FFlowDownCheck.java;h=3d2459662bfe54f1be6895cd14a97d5fd91035b2;hp=d1a70727d2c4ae731a90f6aa7d82b658ff102aaa;hb=8d750e51bc5fa6b54ed568859dd8a6a25ad9e4c4;hpb=bd047bd68decd098b44ab8e7ed1cf9813f099789 diff --git a/Robust/src/Analysis/SSJava/FlowDownCheck.java b/Robust/src/Analysis/SSJava/FlowDownCheck.java index d1a70727..3d245966 100644 --- a/Robust/src/Analysis/SSJava/FlowDownCheck.java +++ b/Robust/src/Analysis/SSJava/FlowDownCheck.java @@ -23,7 +23,9 @@ import IR.Operation; import IR.State; import IR.SymbolTable; import IR.TypeDescriptor; +import IR.TypeExtension; import IR.VarDescriptor; +import IR.Flat.FlatNode; import IR.Tree.ArrayAccessNode; import IR.Tree.AssignmentNode; import IR.Tree.BlockExpressionNode; @@ -136,7 +138,7 @@ public class FlowDownCheck { toanalyzeList.addAll(classtable.getValueSet()); Collections.sort(toanalyzeList, new Comparator() { public int compare(ClassDescriptor o1, ClassDescriptor o2) { - return o1.getClassName().compareTo(o2.getClassName()); + return o1.getClassName().compareToIgnoreCase(o2.getClassName()); } }); } else { @@ -153,7 +155,7 @@ public class FlowDownCheck { toanalyzeMethodList.addAll(methodtable.getValueSet()); Collections.sort(toanalyzeMethodList, new Comparator() { public int compare(MethodDescriptor o1, MethodDescriptor o2) { - return o1.getSymbol().compareTo(o2.getSymbol()); + return o1.getSymbol().compareToIgnoreCase(o2.getSymbol()); } }); } else { @@ -221,8 +223,11 @@ public class FlowDownCheck { while (!toAnalyzeMethodIsEmpty()) { MethodDescriptor md = toAnalyzeMethodNext(); if (ssjava.needTobeAnnotated(md)) { - System.out.println("SSJAVA: Checking assignments: " + md); - checkMethodBody(cd, md); + if (state.SSJAVADEBUG) { + System.out.println("SSJAVA: Checking Flow-down Rules: " + md); + } + CompositeLocation calleePCLOC = ssjava.getPCLocation(md); + checkMethodBody(cd, md, calleePCLOC); } } } @@ -297,38 +302,43 @@ public class FlowDownCheck { for (int i = 0; i < md.numParameters(); i++) { // process annotations on method parameters VarDescriptor vd = (VarDescriptor) md.getParameter(i); - assignLocationOfVarDescriptor(vd, md, md.getParameterTable(), bn); + assignLocationOfVarDescriptor(vd, md, md.getParameterTable(), null); paramList.add(d2loc.get(vd)); } Vector methodAnnotations = md.getModifiers().getAnnotations(); - // second, check return location annotation - if (!md.getReturnType().isVoid()) { - CompositeLocation returnLocComp = null; + CompositeLocation returnLocComp = null; + + boolean hasReturnLocDeclaration = false; + if (methodAnnotations != null) { + for (int i = 0; i < methodAnnotations.size(); i++) { + AnnotationDescriptor an = methodAnnotations.elementAt(i); + if (an.getMarker().equals(ssjava.RETURNLOC)) { + // this case, developer explicitly defines method lattice + String returnLocDeclaration = an.getValue(); + returnLocComp = parseLocationDeclaration(md, null, returnLocDeclaration); + hasReturnLocDeclaration = true; + } else if (an.getMarker().equals(ssjava.THISLOC)) { + String thisLoc = an.getValue(); + ssjava.getMethodLattice(md).setThisLoc(thisLoc); + } else if (an.getMarker().equals(ssjava.GLOBALLOC)) { + String globalLoc = an.getValue(); + ssjava.getMethodLattice(md).setGlobalLoc(globalLoc); + } else if (an.getMarker().equals(ssjava.PCLOC)) { + String pcLocDeclaration = an.getValue(); + ssjava.setPCLocation(md, parseLocationDeclaration(md, null, pcLocDeclaration)); + } + } + } - String rtrStr = ssjava.getMethodLattice(md).getReturnLoc(); - if (rtrStr != null) { - returnLocComp = new CompositeLocation(new Location(md, rtrStr)); - } else { - if (methodAnnotations != null) { - for (int i = 0; i < methodAnnotations.size(); i++) { - AnnotationDescriptor an = methodAnnotations.elementAt(i); - if (an.getMarker().equals(ssjava.RETURNLOC)) { - // this case, developer explicitly defines method lattice - String returnLocDeclaration = an.getValue(); - returnLocComp = parseLocationDeclaration(md, null, returnLocDeclaration); - } - } - } else { - // if developer does not define method lattice - // search return location in the method default lattice - if (returnLocComp == null) { - MethodLattice methodDefaultLattice = ssjava.getMethodDefaultLattice(cd); - if (methodDefaultLattice.getReturnLoc() != null) { - returnLocComp = - parseLocationDeclaration(md, null, methodDefaultLattice.getReturnLoc()); - } - } + // second, check return location annotation + if (!md.getReturnType().isVoid() && !ssjava.getMethodContainingSSJavaLoop().equals(md)) { + if (!hasReturnLocDeclaration) { + // if developer does not define method lattice + // search return location in the method default lattice + String rtrStr = ssjava.getMethodLattice(md).getReturnLoc(); + if (rtrStr != null) { + returnLocComp = new CompositeLocation(new Location(md, rtrStr)); } } @@ -339,20 +349,26 @@ public class FlowDownCheck { md2ReturnLoc.put(md, returnLocComp); - // check this location + } + + if (!md.getReturnType().isVoid() && !ssjava.getMethodContainingSSJavaLoop().equals(md)) { MethodLattice methodLattice = ssjava.getMethodLattice(md); String thisLocId = methodLattice.getThisLoc(); - if (thisLocId == null) { - throw new Error("Method '" + md + "' does not have the definition of 'this' location at " - + md.getClassDesc().getSourceFileName()); + if ((!md.isStatic())) { + + if (thisLocId == null) { + throw new Error("Method '" + md + "' does not have the definition of 'this' location at " + + md.getClassDesc().getSourceFileName()); + } + + CompositeLocation thisLoc = new CompositeLocation(new Location(md, thisLocId)); + paramList.add(0, thisLoc); + } - CompositeLocation thisLoc = new CompositeLocation(new Location(md, thisLocId)); - paramList.add(0, thisLoc); - System.out.println("### ReturnLocGenerator="+md); - System.out.println("### md2ReturnLoc.get(md)="+md2ReturnLoc.get(md)); - md2ReturnLocGen.put(md, new ReturnLocGenerator(md2ReturnLoc.get(md), paramList, md + " of " - + cd.getSourceFileName())); + md2ReturnLocGen.put(md, new ReturnLocGenerator(md2ReturnLoc.get(md), md, paramList, md + + " of " + cd.getSourceFileName())); + } // fourth, check declarations inside of method @@ -437,9 +453,10 @@ public class FlowDownCheck { checkDeclarationInBlockNode(md, nametable, ln.getBody()); } - private void checkMethodBody(ClassDescriptor cd, MethodDescriptor md) { + private void checkMethodBody(ClassDescriptor cd, MethodDescriptor md, + CompositeLocation constraints) { BlockNode bn = state.getMethodBody(md); - checkLocationFromBlockNode(md, md.getParameterTable(), bn, null); + checkLocationFromBlockNode(md, md.getParameterTable(), bn, constraints); } private String generateErrorMessage(ClassDescriptor cd, TreeNode tn) { @@ -535,30 +552,72 @@ public class FlowDownCheck { private CompositeLocation checkLocationFromReturnNode(MethodDescriptor md, SymbolTable nametable, ReturnNode rn, CompositeLocation constraint) { + if (ssjava.getMethodContainingSSJavaLoop().equals(md)) { + return new CompositeLocation(); + } + ExpressionNode returnExp = rn.getReturnExpression(); + CompositeLocation declaredReturnLoc = md2ReturnLoc.get(md); + CompositeLocation returnValueLoc; if (returnExp != null) { returnValueLoc = checkLocationFromExpressionNode(md, nametable, returnExp, new CompositeLocation(), constraint, false); + // System.out.println("# RETURN VALUE LOC=" + returnValueLoc + + // " with constraint=" + constraint); + + // TODO: do we need to check here? // if this return statement is inside branch, return value has an implicit // flow from conditional location + // if (constraint != null) { + // Set inputGLB = new HashSet(); + // inputGLB.add(returnValueLoc); + // inputGLB.add(constraint); + // returnValueLoc = + // CompositeLattice.calculateGLB(inputGLB, + // generateErrorMessage(md.getClassDesc(), rn)); + // } + if (constraint != null) { - Set inputGLB = new HashSet(); - inputGLB.add(returnValueLoc); - inputGLB.add(constraint); - returnValueLoc = - CompositeLattice.calculateGLB(inputGLB, generateErrorMessage(md.getClassDesc(), rn)); + + // Set inputGLB = new HashSet(); + // inputGLB.add(returnValueLoc); + // inputGLB.add(constraint); + // returnValueLoc = + // CompositeLattice.calculateGLB(inputGLB, + // generateErrorMessage(md.getClassDesc(), rn)); + + // if (!returnValueLoc.get(returnValueLoc.getSize() - 1).isTop()) { + // if (!CompositeLattice.isGreaterThan(constraint, returnValueLoc, + // generateErrorMessage(md.getClassDesc(), rn))) { + // System.out.println("returnValueLoc.get(returnValueLoc.getSize() - 1).isTop()=" + // + returnValueLoc.get(returnValueLoc.getSize() - 1).isTop()); + // throw new Error("The value flow from " + constraint + " to " + + // returnValueLoc + // + " does not respect location hierarchy on the assignment " + + // rn.printNode(0) + // + " at " + md.getClassDesc().getSourceFileName() + "::" + + // rn.getNumLine()); + // } + // } + + if (!CompositeLattice.isGreaterThan(constraint, declaredReturnLoc, + generateErrorMessage(md.getClassDesc(), rn))) { + throw new Error("The value flow from " + constraint + " to " + declaredReturnLoc + + " does not respect location hierarchy on the assignment " + rn.printNode(0) + + " at " + md.getClassDesc().getSourceFileName() + "::" + rn.getNumLine()); + } + } // check if return value is equal or higher than RETRUNLOC of method // declaration annotation - CompositeLocation declaredReturnLoc = md2ReturnLoc.get(md); int compareResult = - CompositeLattice.compare(returnValueLoc, declaredReturnLoc, + CompositeLattice.compare(returnValueLoc, declaredReturnLoc, false, generateErrorMessage(md.getClassDesc(), rn)); if (compareResult == ComparisonResult.LESS || compareResult == ComparisonResult.INCOMPARABLE) { @@ -588,7 +647,7 @@ public class FlowDownCheck { CompositeLocation condLoc = checkLocationFromExpressionNode(md, nametable, ln.getCondition(), new CompositeLocation(), constraint, false); - addLocationType(ln.getCondition().getType(), (condLoc)); + // addLocationType(ln.getCondition().getType(), (condLoc)); constraint = generateNewConstraint(constraint, condLoc); checkLocationFromBlockNode(md, nametable, ln.getBody(), constraint); @@ -599,12 +658,18 @@ public class FlowDownCheck { // check 'for loop' case BlockNode bn = ln.getInitializer(); bn.getVarTable().setParent(nametable); + // need to check initialization node + // checkLocationFromBlockNode(md, bn.getVarTable(), bn, constraint); + for (int i = 0; i < bn.size(); i++) { + BlockStatementNode bsn = bn.get(i); + checkLocationFromBlockStatementNode(md, bn.getVarTable(), bsn, constraint); + } // calculate glb location of condition and update statements CompositeLocation condLoc = checkLocationFromExpressionNode(md, bn.getVarTable(), ln.getCondition(), new CompositeLocation(), constraint, false); - addLocationType(ln.getCondition().getType(), condLoc); + // addLocationType(ln.getCondition().getType(), condLoc); constraint = generateNewConstraint(constraint, condLoc); @@ -642,13 +707,14 @@ public class FlowDownCheck { private CompositeLocation checkLocationFromIfStatementNode(MethodDescriptor md, SymbolTable nametable, IfStatementNode isn, CompositeLocation constraint) { + System.out.println("\n\ncheckLocationFromIfStatementNode=" + isn.printNode(0)); CompositeLocation condLoc = checkLocationFromExpressionNode(md, nametable, isn.getCondition(), new CompositeLocation(), constraint, false); - addLocationType(isn.getCondition().getType(), condLoc); - + System.out.println("-######old constraint=" + constraint); constraint = generateNewConstraint(constraint, condLoc); + System.out.println("-######new constraint=" + constraint); checkLocationFromBlockNode(md, nametable, isn.getTrueBlock(), constraint); if (isn.getFalseBlock() != null) { @@ -658,6 +724,32 @@ public class FlowDownCheck { return new CompositeLocation(); } + private void checkOwnership(MethodDescriptor md, TreeNode tn, ExpressionNode srcExpNode) { + + if (srcExpNode.kind() == Kind.NameNode || srcExpNode.kind() == Kind.FieldAccessNode) { + if (srcExpNode.getType().isPtr() && !srcExpNode.getType().isNull()) { + // first, check the linear type + // RHS reference should be owned by the current method + FieldDescriptor fd = getFieldDescriptorFromExpressionNode(srcExpNode); + boolean isOwned; + if (fd == null) { + // local var case + isOwned = ((SSJavaType) srcExpNode.getType().getExtension()).isOwned(); + } else { + // field case + isOwned = ssjava.isOwnedByMethod(md, fd); + } + if (!isOwned) { + throw new Error( + "It is not allowed to create the reference alias from the reference not owned by the method at " + + generateErrorMessage(md.getClassDesc(), tn)); + } + + } + } + + } + private CompositeLocation checkLocationFromDeclarationNode(MethodDescriptor md, SymbolTable nametable, DeclarationNode dn, CompositeLocation constraint) { @@ -666,12 +758,16 @@ public class FlowDownCheck { CompositeLocation destLoc = d2loc.get(vd); if (dn.getExpression() != null) { + + checkOwnership(md, dn, dn.getExpression()); + CompositeLocation expressionLoc = checkLocationFromExpressionNode(md, nametable, dn.getExpression(), new CompositeLocation(), constraint, false); // addTypeLocation(dn.getExpression().getType(), expressionLoc); if (expressionLoc != null) { + // checking location order if (!CompositeLattice.isGreaterThan(expressionLoc, destLoc, generateErrorMessage(md.getClassDesc(), dn))) { @@ -692,11 +788,12 @@ public class FlowDownCheck { private void checkDeclarationInSubBlockNode(MethodDescriptor md, SymbolTable nametable, SubBlockNode sbn) { - checkDeclarationInBlockNode(md, nametable.getParent(), sbn.getBlockNode()); + checkDeclarationInBlockNode(md, nametable, sbn.getBlockNode()); } private CompositeLocation checkLocationFromBlockExpressionNode(MethodDescriptor md, SymbolTable nametable, BlockExpressionNode ben, CompositeLocation constraint) { + CompositeLocation compLoc = checkLocationFromExpressionNode(md, nametable, ben.getExpression(), null, constraint, false); // addTypeLocation(ben.getExpression().getType(), compLoc); @@ -796,70 +893,324 @@ public class FlowDownCheck { CompositeLocation condLoc = checkLocationFromExpressionNode(md, nametable, tn.getCond(), new CompositeLocation(), constraint, false); - addLocationType(tn.getCond().getType(), condLoc); + // addLocationType(tn.getCond().getType(), condLoc); CompositeLocation trueLoc = checkLocationFromExpressionNode(md, nametable, tn.getTrueExpr(), new CompositeLocation(), constraint, false); - addLocationType(tn.getTrueExpr().getType(), trueLoc); + // addLocationType(tn.getTrueExpr().getType(), trueLoc); CompositeLocation falseLoc = checkLocationFromExpressionNode(md, nametable, tn.getFalseExpr(), new CompositeLocation(), constraint, false); - addLocationType(tn.getFalseExpr().getType(), falseLoc); + // 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! - // 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 true expression at " - + cd.getSourceFileName() + ":" + tn.getCond().getNumLine()); - } + // 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); + + // we don't need to check that 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 glbInputSet = new HashSet(); + glbInputSet.add(condLoc); glbInputSet.add(trueLoc); glbInputSet.add(falseLoc); - return CompositeLattice.calculateGLB(glbInputSet, generateErrorMessage(cd, tn)); + 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) { - CompositeLocation baseLocation = null; - if (min.getExpression() != null) { - baseLocation = - checkLocationFromExpressionNode(md, nametable, min.getExpression(), - new CompositeLocation(), constraint, false); - } else { - String thisLocId = ssjava.getMethodLattice(md).getThisLoc(); - baseLocation = new CompositeLocation(new Location(md, thisLocId)); + 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 callerArgList = new ArrayList(); + + // setup the location list of callee's parameters + MethodLattice calleeLattice = ssjava.getMethodLattice(calleeMethodDesc); + List calleeParamList = new ArrayList(); + + 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.GREATER) { + + 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 argument(idx=" + + idx + + ") location " + + argLocation + + "is higher than the caller program counter location " + + constraint + + ". Need to specify that the initial PC location of the callee, which is currently set to " + + calleePCLOC + ", is not higher 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; + } } - checkCalleeConstraints(md, nametable, min, baseLocation, constraint); + return new CompositeLocation(Location.createTopLocation(md)); + + } + + private CompositeLocation translateCallerLocToCalleeLoc(MethodDescriptor calleeMD, + CompositeLocation calleeBaseLoc, CompositeLocation constraint) { + + CompositeLocation calleeConstraint = new CompositeLocation(); - 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; + // 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 new CompositeLocation(); + // } + + 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 callerArgList = new ArrayList(); + List calleeParamList = new ArrayList(); + + MethodLattice 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 inputGLBSet = new HashSet(); + 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)); + } + + // System.out.println("TRANSLATED=" + translate + " from calleeParamLoc=" + + // calleeParamLoc); + + return translate; } private CompositeLocation computeCeilingLocationForCaller(MethodDescriptor md, @@ -868,7 +1219,9 @@ public class FlowDownCheck { List argList = new ArrayList(); // by default, method has a THIS parameter - argList.add(baseLocation); + if (!min.getMethod().isStatic()) { + argList.add(baseLocation); + } for (int i = 0; i < min.numArgs(); i++) { ExpressionNode en = min.getArg(i); @@ -878,12 +1231,11 @@ public class FlowDownCheck { argList.add(callerArg); } - System.out.println("\n## computeReturnLocation=" + min.getMethod() + " argList=" + argList); - CompositeLocation compLoc = md2ReturnLocGen.get(min.getMethod()).computeReturnLocation(argList); - DeltaLocation delta = new DeltaLocation(compLoc, 1); - System.out.println("##computeReturnLocation=" + delta); + // System.out.println("\n## computeReturnLocation=" + min.getMethod() + " argList=" + argList); + CompositeLocation ceilLoc = md2ReturnLocGen.get(min.getMethod()).computeReturnLocation(argList); + // System.out.println("## ReturnLocation=" + ceilLoc); - return delta; + return ceilLoc; } @@ -893,8 +1245,9 @@ public class FlowDownCheck { MethodDescriptor calleemd = min.getMethod(); MethodLattice calleeLattice = ssjava.getMethodLattice(calleemd); - CompositeLocation calleeThisLoc = - new CompositeLocation(new Location(calleemd, calleeLattice.getThisLoc())); + + System.out.println("checkCalleeConstraints=" + calleemd + " calleeLattice.getThisLoc()=" + + calleeLattice.getThisLoc()); List callerArgList = new ArrayList(); List calleeParamList = new ArrayList(); @@ -905,7 +1258,8 @@ public class FlowDownCheck { // setup caller args set // first, add caller's base(this) location - callerArgList.add(callerBaseLoc); + if (!calleemd.isStatic()) + callerArgList.add(callerBaseLoc); // second, add caller's arguments for (int i = 0; i < min.numArgs(); i++) { ExpressionNode en = min.getArg(i); @@ -917,17 +1271,22 @@ public class FlowDownCheck { // setup callee params set // first, add callee's this location - calleeParamList.add(calleeThisLoc); + if (!calleemd.isStatic()) { + CompositeLocation calleeThisLoc = + new CompositeLocation(new Location(calleemd, calleeLattice.getThisLoc())); + 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); + // System.out.println("calleevd=" + calleevd + " loc=" + calleeLoc); calleeParamList.add(calleeLoc); } // here, check if ordering relations among caller's args respect // ordering relations in-between callee's args - for (int i = 0; i < calleeParamList.size(); i++) { + CHECK: for (int i = 0; i < calleeParamList.size(); i++) { CompositeLocation calleeLoc1 = calleeParamList.get(i); CompositeLocation callerLoc1 = callerArgList.get(i); @@ -936,12 +1295,32 @@ public class FlowDownCheck { CompositeLocation calleeLoc2 = calleeParamList.get(j); CompositeLocation callerLoc2 = callerArgList.get(j); + if (callerLoc1.get(callerLoc1.getSize() - 1).isTop() + || callerLoc2.get(callerLoc2.getSize() - 1).isTop()) { + continue CHECK; + } + + // System.out.println("calleeLoc1=" + calleeLoc1); + // System.out.println("calleeLoc2=" + calleeLoc2 + + // "calleeParamList=" + calleeParamList); + int callerResult = - CompositeLattice.compare(callerLoc1, callerLoc2, + CompositeLattice.compare(callerLoc1, callerLoc2, true, generateErrorMessage(md.getClassDesc(), min)); + // System.out.println("callerResult=" + callerResult); int calleeResult = - CompositeLattice.compare(calleeLoc1, calleeLoc2, + CompositeLattice.compare(calleeLoc1, calleeLoc2, true, generateErrorMessage(md.getClassDesc(), min)); + // System.out.println("calleeResult=" + calleeResult); + + if (callerResult == ComparisonResult.EQUAL) { + if (ssjava.isSharedLocation(callerLoc1.get(callerLoc1.getSize() - 1)) + && ssjava.isSharedLocation(callerLoc2.get(callerLoc2.getSize() - 1))) { + // if both of them are shared locations, promote them to + // "GREATER relation" + callerResult = ComparisonResult.GREATER; + } + } if (calleeResult == ComparisonResult.GREATER && callerResult != ComparisonResult.GREATER) { @@ -951,16 +1330,24 @@ public class FlowDownCheck { String paramName1, paramName2; - if (i == 0) { - paramName1 = "'THIS'"; + if (!calleemd.isStatic()) { + if (i == 0) { + paramName1 = "'THIS'"; + } else { + paramName1 = "'parameter " + calleemd.getParamName(i - 1) + "'"; + } } else { - paramName1 = "'parameter " + calleemd.getParamName(i - 1) + "'"; + paramName1 = "'parameter " + calleemd.getParamName(i) + "'"; } - if (j == 0) { - paramName2 = "'THIS'"; + if (!calleemd.isStatic()) { + if (j == 0 && !calleemd.isStatic()) { + paramName2 = "'THIS'"; + } else { + paramName2 = "'parameter " + calleemd.getParamName(j - 1) + "'"; + } } else { - paramName2 = "'parameter " + calleemd.getParamName(j - 1) + "'"; + paramName2 = "'parameter " + calleemd.getParamName(j) + "'"; } throw new Error( @@ -979,17 +1366,19 @@ public class FlowDownCheck { private CompositeLocation checkLocationFromArrayAccessNode(MethodDescriptor md, SymbolTable nametable, ArrayAccessNode aan, CompositeLocation constraint, boolean isLHS) { - + System.out.println("aan=" + aan.printNode(0) + " line#=" + aan.getNumLine()); ClassDescriptor cd = md.getClassDesc(); - + System.out.println("aan.getExpression()=" + aan.getExpression().getClass()); CompositeLocation arrayLoc = checkLocationFromExpressionNode(md, nametable, aan.getExpression(), new CompositeLocation(), constraint, isLHS); + System.out.println("HERE?"); // addTypeLocation(aan.getExpression().getType(), arrayLoc); CompositeLocation indexLoc = checkLocationFromExpressionNode(md, nametable, aan.getIndex(), new CompositeLocation(), constraint, isLHS); // addTypeLocation(aan.getIndex().getType(), indexLoc); + System.out.println("HERE2?"); if (isLHS) { if (!CompositeLattice.isGreaterThan(indexLoc, arrayLoc, generateErrorMessage(cd, aan))) { @@ -1001,7 +1390,11 @@ public class FlowDownCheck { Set inputGLB = new HashSet(); inputGLB.add(arrayLoc); inputGLB.add(indexLoc); - return CompositeLattice.calculateGLB(inputGLB, generateErrorMessage(cd, aan)); + System.out.println("arrayLoc=" + arrayLoc + " indexLoc=" + indexLoc); + CompositeLocation comp = + CompositeLattice.calculateGLB(inputGLB, generateErrorMessage(cd, aan)); + System.out.println("---aan=" + aan.printNode(0) + " compLoc=" + comp); + return comp; } } @@ -1033,11 +1426,10 @@ public class FlowDownCheck { // addTypeLocation(on.getRight().getType(), rightLoc); } - System.out.println("\n# OP NODE=" + on.printNode(0)); - System.out.println("# left loc=" + leftLoc + " from " + on.getLeft().getClass()); - if (on.getRight() != null) { - System.out.println("# right loc=" + rightLoc + " from " + on.getRight().getClass()); - } + // System.out.println("# left loc=" + leftLoc + " from " + on.getLeft().getClass()); + // if (on.getRight() != null) { + // System.out.println("# right loc=" + rightLoc + " from " + on.getRight().getClass()); + // } Operation op = on.getOp(); @@ -1076,7 +1468,6 @@ public class FlowDownCheck { inputSet.add(rightLoc); CompositeLocation glbCompLoc = CompositeLattice.calculateGLB(inputSet, generateErrorMessage(cd, on)); - System.out.println("# glbCompLoc=" + glbCompLoc); return glbCompLoc; default: @@ -1099,6 +1490,7 @@ public class FlowDownCheck { private CompositeLocation checkLocationFromNameNode(MethodDescriptor md, SymbolTable nametable, NameNode nn, CompositeLocation loc, CompositeLocation constraint) { + // System.out.println("checkLocationFromNameNode nn=" + nn.printNode(0)); NameDescriptor nd = nn.getName(); if (nd.getBase() != null) { loc = @@ -1126,10 +1518,11 @@ public class FlowDownCheck { VarDescriptor vd = (VarDescriptor) d; // localLoc = d2loc.get(vd); // the type of var descriptor has a composite location! - loc = ((CompositeLocation) vd.getType().getExtension()).clone(); + loc = ((SSJavaType) vd.getType().getExtension()).getCompLoc().clone(); } else if (d instanceof FieldDescriptor) { // the type of field descriptor has a location! FieldDescriptor fd = (FieldDescriptor) d; + // System.out.println("fd=" + fd); if (fd.isStatic()) { if (fd.isFinal()) { // if it is 'static final', the location has TOP since no one can @@ -1137,6 +1530,7 @@ public class FlowDownCheck { loc.addLocation(Location.createTopLocation(md)); return loc; } else { + // if 'static', the location has pre-assigned global loc MethodLattice localLattice = ssjava.getMethodLattice(md); String globalLocId = localLattice.getGlobalLoc(); @@ -1144,7 +1538,7 @@ public class FlowDownCheck { throw new Error("Global location element is not defined in the method " + md); } Location globalLoc = new Location(md, globalLocId); - + System.out.println("static=" + globalLoc); loc.addLocation(globalLoc); } } else { @@ -1158,25 +1552,25 @@ public class FlowDownCheck { Location fieldLoc = (Location) fd.getType().getExtension(); loc.addLocation(fieldLoc); } else if (d == null) { - - // check if the var is a static field of the class + // access static field FieldDescriptor fd = nn.getField(); - ClassDescriptor cd = nn.getClassDesc(); - if (fd != null && cd != null) { - - if (fd.isStatic() && fd.isFinal()) { - loc.addLocation(Location.createTopLocation(md)); - return loc; - } else { - MethodLattice localLattice = ssjava.getMethodLattice(md); - Location fieldLoc = new Location(md, localLattice.getThisLoc()); - loc.addLocation(fieldLoc); - } + MethodLattice localLattice = ssjava.getMethodLattice(md); + String globalLocId = localLattice.getGlobalLoc(); + if (globalLocId == null) { + throw new Error("Method lattice does not define global variable location at " + + generateErrorMessage(md.getClassDesc(), nn)); } + loc.addLocation(new Location(md, globalLocId)); + + Location fieldLoc = (Location) fd.getType().getExtension(); + loc.addLocation(fieldLoc); + + return loc; } } + return loc; } @@ -1203,17 +1597,38 @@ public class FlowDownCheck { } } + Set inputGLB = new HashSet(); + if (left instanceof ArrayAccessNode) { + ArrayAccessNode aan = (ArrayAccessNode) left; + CompositeLocation indexLoc = + checkLocationFromExpressionNode(md, nametable, aan.getIndex(), loc, constraint, false); + inputGLB.add(indexLoc); + } + loc = checkLocationFromExpressionNode(md, nametable, left, loc, constraint, false); + if (!left.getType().isPrimitive()) { - Location fieldLoc = getFieldLocation(fd); - loc.addLocation(fieldLoc); + + if (!fd.getSymbol().equals("length")) { + // array.length access, return the location of the array + Location fieldLoc = getFieldLocation(fd); + loc.addLocation(fieldLoc); + } + } + inputGLB.add(loc); + loc = CompositeLattice.calculateGLB(inputGLB, generateErrorMessage(md.getClassDesc(), fan)); + return loc; } private Location getFieldLocation(FieldDescriptor fd) { + // System.out.println("### getFieldLocation=" + fd); + // System.out.println("### fd.getType().getExtension()=" + + // fd.getType().getExtension()); + Location fieldLoc = (Location) fd.getType().getExtension(); // handle the case that method annotation checking skips checking field @@ -1226,10 +1641,30 @@ public class FlowDownCheck { } + private FieldDescriptor getFieldDescriptorFromExpressionNode(ExpressionNode en) { + + if (en.kind() == Kind.NameNode) { + NameNode nn = (NameNode) en; + if (nn.getField() != null) { + return nn.getField(); + } + + if (nn.getName() != null && nn.getName().getBase() != null) { + return getFieldDescriptorFromExpressionNode(nn.getExpression()); + } + + } else if (en.kind() == Kind.FieldAccessNode) { + FieldAccessNode fan = (FieldAccessNode) en; + return fan.getField(); + } + + return null; + } + private CompositeLocation checkLocationFromAssignmentNode(MethodDescriptor md, SymbolTable nametable, AssignmentNode an, CompositeLocation loc, CompositeLocation constraint) { - System.out.println("\n# ASSIGNMENTNODE=" + an.printNode(0)); + System.out.println("\n\ncheckLocationFromAssignmentNode=" + an.printNode(0)); ClassDescriptor cd = md.getClassDesc(); @@ -1251,26 +1686,59 @@ public class FlowDownCheck { CompositeLocation srcLocation; if (!postinc) { + + checkOwnership(md, an, an.getSrc()); + rhsLocation = checkLocationFromExpressionNode(md, nametable, an.getSrc(), new CompositeLocation(), constraint, false); - System.out.println("dstLocation=" + destLocation); - System.out.println("rhsLocation=" + rhsLocation); - System.out.println("constraint=" + constraint); - - if (constraint != null) { - inputGLBSet.add(rhsLocation); - inputGLBSet.add(constraint); - srcLocation = CompositeLattice.calculateGLB(inputGLBSet, generateErrorMessage(cd, an)); + if (an.getOperation().getOp() >= 2 && an.getOperation().getOp() <= 12) { + // if assignment contains OP+EQ operator, need to merge location types + // of LHS & RHS into the RHS + Set srcGLBSet = new HashSet(); + srcGLBSet.add(rhsLocation); + srcGLBSet.add(destLocation); + srcLocation = CompositeLattice.calculateGLB(srcGLBSet, generateErrorMessage(cd, an)); } else { srcLocation = rhsLocation; } + if (constraint != null) { + + if (!CompositeLattice.isGreaterThan(constraint, destLocation, generateErrorMessage(cd, an))) { + throw new Error("The value flow from " + constraint + " to " + destLocation + + " does not respect location hierarchy on the assignment " + an.printNode(0) + + " at " + cd.getSourceFileName() + "::" + an.getNumLine()); + } + // inputGLBSet.add(srcLocation); + // inputGLBSet.add(constraint); + // srcLocation = CompositeLattice.calculateGLB(inputGLBSet, + // generateErrorMessage(cd, an)); + } + + System.out.println("src=" + srcLocation + " dest=" + destLocation + " const=" + constraint); + if (!CompositeLattice.isGreaterThan(srcLocation, destLocation, generateErrorMessage(cd, an))) { + + String context = ""; + if (constraint != null) { + context = " and the current context constraint is " + constraint; + } + throw new Error("The value flow from " + srcLocation + " to " + destLocation - + " does not respect location hierarchy on the assignment " + an.printNode(0) + " at " - + cd.getSourceFileName() + "::" + an.getNumLine()); + + " does not respect location hierarchy on the assignment " + an.printNode(0) + context + + " at " + cd.getSourceFileName() + "::" + an.getNumLine()); + } + + if (srcLocation.equals(destLocation)) { + // keep it for definitely written analysis + Set flatNodeSet = ssjava.getBuildFlat().getFlatNodeSet(an); + for (Iterator iterator = flatNodeSet.iterator(); iterator.hasNext();) { + FlatNode fn = (FlatNode) iterator.next(); + ssjava.addSameHeightWriteFlatNode(fn); + } + } } else { @@ -1280,21 +1748,42 @@ public class FlowDownCheck { constraint, false); if (constraint != null) { - inputGLBSet.add(rhsLocation); - inputGLBSet.add(constraint); - srcLocation = CompositeLattice.calculateGLB(inputGLBSet, generateErrorMessage(cd, an)); + + if (!CompositeLattice.isGreaterThan(constraint, destLocation, generateErrorMessage(cd, an))) { + throw new Error("The value flow from " + constraint + " to " + destLocation + + " does not respect location hierarchy on the assignment " + an.printNode(0) + + " at " + cd.getSourceFileName() + "::" + an.getNumLine()); + } + // inputGLBSet.add(rhsLocation); + // inputGLBSet.add(constraint); + // srcLocation = CompositeLattice.calculateGLB(inputGLBSet, + // generateErrorMessage(cd, an)); + srcLocation = rhsLocation; } else { srcLocation = rhsLocation; } - System.out.println("srcLocation=" + srcLocation); - System.out.println("rhsLocation=" + rhsLocation); - System.out.println("constraint=" + constraint); - if (!CompositeLattice.isGreaterThan(srcLocation, destLocation, generateErrorMessage(cd, an))) { - throw new Error("Location " + destLocation - + " is not allowed to have the value flow that moves within the same location at " - + cd.getSourceFileName() + "::" + an.getNumLine()); + + if (srcLocation.equals(destLocation)) { + throw new Error("Location " + srcLocation + + " is not allowed to have the value flow that moves within the same location at '" + + an.printNode(0) + "' of " + cd.getSourceFileName() + "::" + an.getNumLine()); + } else { + throw new Error("The value flow from " + srcLocation + " to " + destLocation + + " does not respect location hierarchy on the assignment " + an.printNode(0) + + " at " + cd.getSourceFileName() + "::" + an.getNumLine()); + } + + } + + if (srcLocation.equals(destLocation)) { + // keep it for definitely written analysis + Set flatNodeSet = ssjava.getBuildFlat().getFlatNodeSet(an); + for (Iterator iterator = flatNodeSet.iterator(); iterator.hasNext();) { + FlatNode fn = (FlatNode) iterator.next(); + ssjava.addSameHeightWriteFlatNode(fn); + } } } @@ -1310,37 +1799,41 @@ public class FlowDownCheck { // currently enforce every variable to have corresponding location if (annotationVec.size() == 0) { - throw new Error("Location is not assigned to variable " + vd.getSymbol() + " in the method " - + md.getSymbol() + " of the class " + cd.getSymbol()); + throw new Error("Location is not assigned to variable '" + vd.getSymbol() + + "' in the method '" + md + "' of the class " + cd.getSymbol() + " at " + + generateErrorMessage(cd, n)); } - if (annotationVec.size() > 1) { // variable can have at most one location - throw new Error(vd.getSymbol() + " has more than one location."); - } + int locDecCount = 0; + for (int i = 0; i < annotationVec.size(); i++) { + AnnotationDescriptor ad = annotationVec.elementAt(i); - AnnotationDescriptor ad = annotationVec.elementAt(0); + if (ad.getType() == AnnotationDescriptor.SINGLE_ANNOTATION) { - if (ad.getType() == AnnotationDescriptor.SINGLE_ANNOTATION) { + if (ad.getMarker().equals(SSJavaAnalysis.LOC)) { + locDecCount++; + if (locDecCount > 1) {// variable can have at most one location + throw new Error(vd.getSymbol() + " has more than one location declaration."); + } + String locDec = ad.getValue(); // check if location is defined - if (ad.getMarker().equals(SSJavaAnalysis.LOC)) { - String locDec = ad.getValue(); // check if location is defined + if (locDec.startsWith(SSJavaAnalysis.DELTA)) { + DeltaLocation deltaLoc = parseDeltaDeclaration(md, n, locDec); + d2loc.put(vd, deltaLoc); + addLocationType(vd.getType(), deltaLoc); + } else { + CompositeLocation compLoc = parseLocationDeclaration(md, n, locDec); - if (locDec.startsWith(SSJavaAnalysis.DELTA)) { - DeltaLocation deltaLoc = parseDeltaDeclaration(md, n, locDec); - d2loc.put(vd, deltaLoc); - addLocationType(vd.getType(), deltaLoc); - } else { - CompositeLocation compLoc = parseLocationDeclaration(md, n, locDec); + Location lastElement = compLoc.get(compLoc.getSize() - 1); + if (ssjava.isSharedLocation(lastElement)) { + ssjava.mapSharedLocation2Descriptor(lastElement, vd); + } - Location lastElement = compLoc.get(compLoc.getSize() - 1); - if (ssjava.isSharedLocation(lastElement)) { - ssjava.mapSharedLocation2Descriptor(lastElement, vd); + d2loc.put(vd, compLoc); + addLocationType(vd.getType(), compLoc); } - d2loc.put(vd, compLoc); - addLocationType(vd.getType(), compLoc); } - } } @@ -1376,7 +1869,8 @@ public class FlowDownCheck { Descriptor d = state.getClassSymbolTable().get(className); if (d == null) { - System.out.println("state.getClassSymbolTable()=" + state.getClassSymbolTable()); + // System.out.println("state.getClassSymbolTable()=" + + // state.getClassSymbolTable()); throw new Error("The class in the location declaration '" + decl + "' does not exist at " + msg); } @@ -1412,7 +1906,6 @@ public class FlowDownCheck { SSJavaLattice localLattice = CompositeLattice.getLatticeByDescriptor(md); Location localLoc = new Location(md, localLocId); if (localLattice == null || (!localLattice.containsKey(localLocId))) { - System.out.println("locDec=" + locDec); throw new Error("Location " + localLocId + " is not defined in the local variable lattice at " + md.getClassDesc().getSourceFileName() + "::" + (n != null ? n.getNumLine() : md) + "."); @@ -1500,7 +1993,15 @@ public class FlowDownCheck { private void addLocationType(TypeDescriptor type, CompositeLocation loc) { if (type != null) { - type.setExtension(loc); + TypeExtension te = type.getExtension(); + SSJavaType ssType; + if (te != null) { + ssType = (SSJavaType) te; + ssType.setCompLoc(loc); + } else { + ssType = new SSJavaType(loc); + type.setExtension(ssType); + } } } @@ -1514,8 +2015,9 @@ public class FlowDownCheck { public static boolean isGreaterThan(CompositeLocation loc1, CompositeLocation loc2, String msg) { - System.out.println("\nisGreaterThan=" + loc1 + " " + loc2 + " msg=" + msg); - int baseCompareResult = compareBaseLocationSet(loc1, loc2, true, msg); + // System.out.println("\nisGreaterThan=" + loc1 + " " + loc2 + " msg=" + + // msg); + int baseCompareResult = compareBaseLocationSet(loc1, loc2, true, false, msg); if (baseCompareResult == ComparisonResult.EQUAL) { if (compareDelta(loc1, loc2) == ComparisonResult.GREATER) { return true; @@ -1530,10 +2032,11 @@ public class FlowDownCheck { } - public static int compare(CompositeLocation loc1, CompositeLocation loc2, String msg) { + public static int compare(CompositeLocation loc1, CompositeLocation loc2, boolean ignore, + String msg) { - System.out.println("compare=" + loc1 + " " + loc2); - int baseCompareResult = compareBaseLocationSet(loc1, loc2, false, msg); + // System.out.println("compare=" + loc1 + " " + loc2); + int baseCompareResult = compareBaseLocationSet(loc1, loc2, false, ignore, msg); if (baseCompareResult == ComparisonResult.EQUAL) { return compareDelta(loc1, loc2); @@ -1565,7 +2068,7 @@ public class FlowDownCheck { } private static int compareBaseLocationSet(CompositeLocation compLoc1, - CompositeLocation compLoc2, boolean awareSharedLoc, String msg) { + CompositeLocation compLoc2, boolean awareSharedLoc, boolean ignore, String msg) { // if compLoc1 is greater than compLoc2, return true // else return false; @@ -1575,93 +2078,30 @@ public class FlowDownCheck { for (int i = 0; i < compLoc1.getSize(); i++) { Location loc1 = compLoc1.get(i); if (i >= compLoc2.getSize()) { - throw new Error("Failed to compare two locations of " + compLoc1 + " and " + compLoc2 - + " because they are not comparable at " + msg); - } - Location loc2 = compLoc2.get(i); - - Descriptor d1 = loc1.getDescriptor(); - Descriptor d2 = loc2.getDescriptor(); - - Descriptor descriptor; - - if (d1 instanceof ClassDescriptor && d2 instanceof ClassDescriptor) { - - if (d1.equals(d2)) { - descriptor = d1; + if (ignore) { + return ComparisonResult.INCOMPARABLE; } else { - // identifying which one is parent class - Set d1SubClassesSet = ssjava.tu.getSubClasses((ClassDescriptor) d1); - Set d2SubClassesSet = ssjava.tu.getSubClasses((ClassDescriptor) d2); - - if (d1 == null && d2 == null) { - throw new Error("Failed to compare two locations of " + compLoc1 + " and " + compLoc2 - + " because they are not comparable at " + msg); - } else if (d1SubClassesSet != null && d1SubClassesSet.contains(d2)) { - descriptor = d1; - } else if (d2SubClassesSet != null && d2SubClassesSet.contains(d1)) { - descriptor = d2; - } else { - throw new Error("Failed to compare two locations of " + compLoc1 + " and " + compLoc2 - + " because they are not comparable at " + msg); - } - } - - } else if (d1 instanceof MethodDescriptor && d2 instanceof MethodDescriptor) { - - if (d1.equals(d2)) { - descriptor = d1; - } else { - - // identifying which one is parent class - MethodDescriptor md1 = (MethodDescriptor) d1; - MethodDescriptor md2 = (MethodDescriptor) d2; - - if (!md1.matches(md2)) { - throw new Error("Failed to compare two locations of " + compLoc1 + " and " + compLoc2 - + " because they are not comparable at " + msg); - } - - Set d1SubClassesSet = - ssjava.tu.getSubClasses(((MethodDescriptor) d1).getClassDesc()); - Set d2SubClassesSet = - ssjava.tu.getSubClasses(((MethodDescriptor) d2).getClassDesc()); - - if (d1 == null && d2 == null) { - throw new Error("Failed to compare two locations of " + compLoc1 + " and " + compLoc2 - + " because they are not comparable at " + msg); - } else if (d1 != null && d1SubClassesSet.contains(d2)) { - descriptor = d1; - } else if (d2 != null && d2SubClassesSet.contains(d1)) { - descriptor = d2; - } else { - throw new Error("Failed to compare two locations of " + compLoc1 + " and " + compLoc2 - + " because they are not comparable at " + msg); - } + throw new Error("Failed to compare two locations of " + compLoc1 + " and " + compLoc2 + + " because they are not comparable at " + msg); } - - } else { - throw new Error("Failed to compare two locations of " + compLoc1 + " and " + compLoc2 - + " because they are not comparable at " + msg); } + Location loc2 = compLoc2.get(i); - // SSJavaLattice lattice1 = getLatticeByDescriptor(d1); - // SSJavaLattice lattice2 = getLatticeByDescriptor(d2); - + Descriptor descriptor = getCommonParentDescriptor(loc1, loc2, msg); SSJavaLattice lattice = getLatticeByDescriptor(descriptor); - // check if the spin location is appeared only at the end of the + // check if the shared location is appeared only at the end of the // composite location - if (lattice.getSpinLocSet().contains(loc1.getLocIdentifier())) { + if (lattice.getSharedLocSet().contains(loc1.getLocIdentifier())) { if (i != (compLoc1.getSize() - 1)) { throw new Error("The shared location " + loc1.getLocIdentifier() + " cannot be appeared in the middle of composite location at" + msg); } } - if (lattice.getSpinLocSet().contains(loc2.getLocIdentifier())) { + if (lattice.getSharedLocSet().contains(loc2.getLocIdentifier())) { if (i != (compLoc2.getSize() - 1)) { - throw new Error("The spin location " + loc2.getLocIdentifier() + throw new Error("The shared location " + loc2.getLocIdentifier() + " cannot be appeared in the middle of composite location at " + msg); } } @@ -1678,14 +2118,18 @@ public class FlowDownCheck { // note that the spinning location only can be appeared in the last // part of the composite location if (awareSharedLoc && numOfTie == compLoc1.getSize() - && lattice.getSpinLocSet().contains(loc1.getLocIdentifier())) { + && lattice.getSharedLocSet().contains(loc1.getLocIdentifier())) { return ComparisonResult.GREATER; } continue; } else if (lattice.isGreaterThan(loc1.getLocIdentifier(), loc2.getLocIdentifier())) { return ComparisonResult.GREATER; } else { - return ComparisonResult.LESS; + if (lattice.isComparable(loc1.getLocIdentifier(), loc2.getLocIdentifier())) { + return ComparisonResult.LESS; + } else { + return ComparisonResult.INCOMPARABLE; + } } } @@ -1693,8 +2137,14 @@ public class FlowDownCheck { if (numOfTie == compLoc1.getSize()) { if (numOfTie != compLoc2.getSize()) { - throw new Error("Failed to compare two locations of " + compLoc1 + " and " + compLoc2 - + " because they are not comparable at " + msg); + + if (ignore) { + return ComparisonResult.INCOMPARABLE; + } else { + throw new Error("Failed to compare two locations of " + compLoc1 + " and " + compLoc2 + + " because they are not comparable at " + msg); + } + } return ComparisonResult.EQUAL; @@ -1719,6 +2169,7 @@ public class FlowDownCheck { // composite location int maxTupleSize = 0; + int minTupleSize = 0; CompositeLocation maxCompLoc = null; Location prevPriorityLoc = null; @@ -1728,6 +2179,9 @@ public class FlowDownCheck { maxTupleSize = compLoc.getSize(); maxCompLoc = compLoc; } + if (minTupleSize == 0 || compLoc.getSize() < minTupleSize) { + minTupleSize = compLoc.getSize(); + } Location priorityLoc = compLoc.get(0); String priorityLocId = priorityLoc.getLocIdentifier(); priorityLocIdentifierSet.add(priorityLocId); @@ -1755,7 +2209,6 @@ public class FlowDownCheck { SSJavaLattice locOrder = getLatticeByDescriptor(priorityDescriptor); String glbOfPriorityLoc = locOrder.getGLB(priorityLocIdentifierSet); - glbCompLoc.addLocation(new Location(priorityDescriptor, glbOfPriorityLoc)); Set compSet = locId2CompLocSet.get(glbOfPriorityLoc); @@ -1766,7 +2219,8 @@ public class FlowDownCheck { // in this case, do not take care about delta // CompositeLocation inputComp = inputSet.iterator().next(); - for (int i = 1; i < maxTupleSize; i++) { + // for (int i = 1; i < maxTupleSize; i++) { + for (int i = 1; i < minTupleSize; i++) { glbCompLoc.addLocation(Location.createTopLocation(maxCompLoc.get(i).getDescriptor())); } } else { @@ -1816,6 +2270,7 @@ public class FlowDownCheck { } if (innerGLBInput.size() > 0) { + // System.out.println("######innerGLBInput=" + innerGLBInput); CompositeLocation innerGLB = CompositeLattice.calculateGLB(innerGLBInput, errMsg); for (int idx = 0; idx < innerGLB.getSize(); idx++) { glbCompLoc.addLocation(innerGLB.get(idx)); @@ -1952,50 +2407,82 @@ class ReturnLocGenerator { public static final int PARAMISSAME = 1; public static final int IGNORE = 2; - Hashtable paramIdx2paramType; + private Hashtable paramIdx2paramType; - public ReturnLocGenerator(CompositeLocation returnLoc, List params, String msg) { - // creating mappings - paramIdx2paramType = new Hashtable(); - for (int i = 0; i < params.size(); i++) { - CompositeLocation param = params.get(i); - int compareResult = CompositeLattice.compare(param, returnLoc, msg); + private CompositeLocation declaredReturnLoc = null; - int type; - if (compareResult == ComparisonResult.GREATER) { - type = 0; - } else if (compareResult == ComparisonResult.EQUAL) { - type = 1; - } else { - type = 2; + public ReturnLocGenerator(CompositeLocation returnLoc, MethodDescriptor md, + List 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(); + 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)); } - paramIdx2paramType.put(new Integer(i), new Integer(type)); } } public CompositeLocation computeReturnLocation(List args) { - // compute the highest possible location in caller's side - assert paramIdx2paramType.keySet().size() == args.size(); + 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); - Set inputGLB = new HashSet(); - 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); + 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 inputGLB = new HashSet(); + for (int i = 0; i < args.size(); i++) { + int type = (paramIdx2paramType.get(new Integer(i))).intValue(); + CompositeLocation argLoc = args.get(i); + if (type == PARAMISHIGHER || type == PARAMISSAME) { + // return loc is equal to or lower than param + inputGLB.add(argLoc); + } + } + + // compute GLB of arguments subset that are same or higher than return + // location + if (inputGLB.isEmpty()) { + if (args.size() == 0) { + return null; + } + CompositeLocation rtr = + new CompositeLocation(Location.createTopLocation(args.get(0).get(0).getDescriptor())); + return rtr; + } else { + CompositeLocation glb = CompositeLattice.calculateGLB(inputGLB, ""); + return glb; } } - // compute GLB of arguments subset that are same or higher than return - // location - CompositeLocation glb = CompositeLattice.calculateGLB(inputGLB, ""); - return glb; } }