package Analysis.SSJava;
import java.util.ArrayList;
+import java.util.Collections;
+import java.util.Comparator;
import java.util.HashSet;
import java.util.Hashtable;
import java.util.Iterator;
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;
import IR.Tree.SubBlockNode;
import IR.Tree.SwitchBlockNode;
import IR.Tree.SwitchStatementNode;
+import IR.Tree.SynchronizedNode;
import IR.Tree.TertiaryNode;
import IR.Tree.TreeNode;
import Util.Pair;
State state;
static SSJavaAnalysis ssjava;
- HashSet toanalyze;
+ Set<ClassDescriptor> toanalyze;
+ List<ClassDescriptor> toanalyzeList;
+
+ Set<MethodDescriptor> toanalyzeMethod;
+ List<MethodDescriptor> toanalyzeMethodList;
// mapping from 'descriptor' to 'composite location'
Hashtable<Descriptor, CompositeLocation> d2loc;
// mapping from 'locID' to 'class descriptor'
Hashtable<String, ClassDescriptor> fieldLocName2cd;
+ boolean deterministic = true;
+
public FlowDownCheck(SSJavaAnalysis ssjava, State state) {
this.ssjava = ssjava;
this.state = state;
- this.toanalyze = new HashSet();
+ if (deterministic) {
+ this.toanalyzeList = new ArrayList<ClassDescriptor>();
+ } else {
+ this.toanalyze = new HashSet<ClassDescriptor>();
+ }
+ if (deterministic) {
+ this.toanalyzeMethodList = new ArrayList<MethodDescriptor>();
+ } else {
+ this.toanalyzeMethod = new HashSet<MethodDescriptor>();
+ }
this.d2loc = new Hashtable<Descriptor, CompositeLocation>();
this.fieldLocName2cd = new Hashtable<String, ClassDescriptor>();
this.md2ReturnLoc = new Hashtable<MethodDescriptor, CompositeLocation>();
}
- public void flowDownCheck() {
+ public boolean toAnalyzeIsEmpty() {
+ if (deterministic) {
+ return toanalyzeList.isEmpty();
+ } else {
+ return toanalyze.isEmpty();
+ }
+ }
+
+ public ClassDescriptor toAnalyzeNext() {
+ if (deterministic) {
+ return toanalyzeList.remove(0);
+ } else {
+ ClassDescriptor cd = toanalyze.iterator().next();
+ toanalyze.remove(cd);
+ return cd;
+ }
+ }
+
+ public void setupToAnalyze() {
SymbolTable classtable = state.getClassSymbolTable();
+ if (deterministic) {
+ toanalyzeList.clear();
+ toanalyzeList.addAll(classtable.getValueSet());
+ Collections.sort(toanalyzeList, new Comparator<ClassDescriptor>() {
+ public int compare(ClassDescriptor o1, ClassDescriptor o2) {
+ return o1.getClassName().compareToIgnoreCase(o2.getClassName());
+ }
+ });
+ } else {
+ toanalyze.clear();
+ toanalyze.addAll(classtable.getValueSet());
+ }
+ }
+
+ public void setupToAnalazeMethod(ClassDescriptor cd) {
+
+ SymbolTable methodtable = cd.getMethodTable();
+ if (deterministic) {
+ toanalyzeMethodList.clear();
+ toanalyzeMethodList.addAll(methodtable.getValueSet());
+ Collections.sort(toanalyzeMethodList, new Comparator<MethodDescriptor>() {
+ public int compare(MethodDescriptor o1, MethodDescriptor o2) {
+ return o1.getSymbol().compareToIgnoreCase(o2.getSymbol());
+ }
+ });
+ } else {
+ toanalyzeMethod.clear();
+ toanalyzeMethod.addAll(methodtable.getValueSet());
+ }
+ }
+
+ public boolean toAnalyzeMethodIsEmpty() {
+ if (deterministic) {
+ return toanalyzeMethodList.isEmpty();
+ } else {
+ return toanalyzeMethod.isEmpty();
+ }
+ }
+
+ public MethodDescriptor toAnalyzeMethodNext() {
+ if (deterministic) {
+ return toanalyzeMethodList.remove(0);
+ } else {
+ MethodDescriptor md = toanalyzeMethod.iterator().next();
+ toanalyzeMethod.remove(md);
+ return md;
+ }
+ }
+
+ public void flowDownCheck() {
// phase 1 : checking declaration node and creating mapping of 'type
// desciptor' & 'location'
- toanalyze.addAll(classtable.getValueSet());
- toanalyze.addAll(state.getTaskSymbolTable().getValueSet());
+ setupToAnalyze();
- while (!toanalyze.isEmpty()) {
- Object obj = toanalyze.iterator().next();
- ClassDescriptor cd = (ClassDescriptor) obj;
- toanalyze.remove(cd);
+ while (!toAnalyzeIsEmpty()) {
+ ClassDescriptor cd = toAnalyzeNext();
if (ssjava.needToBeAnnoated(cd)) {
}
checkDeclarationInClass(cd);
- for (Iterator method_it = cd.getMethods(); method_it.hasNext();) {
- MethodDescriptor md = (MethodDescriptor) method_it.next();
+
+ setupToAnalazeMethod(cd);
+ while (!toAnalyzeMethodIsEmpty()) {
+ MethodDescriptor md = toAnalyzeMethodNext();
if (ssjava.needTobeAnnotated(md)) {
checkDeclarationInMethodBody(cd, md);
}
}
+
}
}
// phase2 : checking assignments
- toanalyze.addAll(classtable.getValueSet());
- toanalyze.addAll(state.getTaskSymbolTable().getValueSet());
- while (!toanalyze.isEmpty()) {
- Object obj = toanalyze.iterator().next();
- ClassDescriptor cd = (ClassDescriptor) obj;
- toanalyze.remove(cd);
+ setupToAnalyze();
- checkClass(cd);
- for (Iterator method_it = cd.getMethods(); method_it.hasNext();) {
- MethodDescriptor md = (MethodDescriptor) method_it.next();
+ while (!toAnalyzeIsEmpty()) {
+ ClassDescriptor cd = toAnalyzeNext();
+
+ setupToAnalazeMethod(cd);
+ while (!toAnalyzeMethodIsEmpty()) {
+ MethodDescriptor md = toAnalyzeMethodNext();
if (ssjava.needTobeAnnotated(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);
}
}
}
private void checkDeclarationInMethodBody(ClassDescriptor cd, MethodDescriptor md) {
BlockNode bn = state.getMethodBody(md);
- if (ssjava.needTobeAnnotated(md)) {
-
- // parsing returnloc annotation
- Vector<AnnotationDescriptor> methodAnnotations = md.getModifiers().getAnnotations();
- if (methodAnnotations != null) {
- for (int i = 0; i < methodAnnotations.size(); i++) {
- AnnotationDescriptor an = methodAnnotations.elementAt(i);
- if (an.getMarker().equals(ssjava.RETURNLOC)) {
- // developer explicitly defines method lattice
- String returnLocDeclaration = an.getValue();
- CompositeLocation returnLocComp =
- parseLocationDeclaration(md, null, returnLocDeclaration);
- md2ReturnLoc.put(md, returnLocComp);
- }
- }
- if (!md.getReturnType().isVoid() && !md2ReturnLoc.containsKey(md)) {
- throw new Error("Return location is not specified for the method " + md + " at "
- + cd.getSourceFileName());
+ // first, check annotations on method parameters
+ List<CompositeLocation> paramList = new ArrayList<CompositeLocation>();
+ for (int i = 0; i < md.numParameters(); i++) {
+ // process annotations on method parameters
+ VarDescriptor vd = (VarDescriptor) md.getParameter(i);
+ assignLocationOfVarDescriptor(vd, md, md.getParameterTable(), null);
+ paramList.add(d2loc.get(vd));
+ }
+ Vector<AnnotationDescriptor> methodAnnotations = md.getModifiers().getAnnotations();
+
+ 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));
}
}
+ }
- List<CompositeLocation> paramList = new ArrayList<CompositeLocation>();
-
- boolean hasReturnValue = (!md.getReturnType().isVoid());
- if (hasReturnValue) {
- MethodLattice<String> 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());
+ // second, check return location annotation
+ if (!md.getReturnType().isVoid()) {
+ 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));
}
- CompositeLocation thisLoc = new CompositeLocation(new Location(md, thisLocId));
- paramList.add(thisLoc);
}
- 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);
- if (hasReturnValue) {
- paramList.add(d2loc.get(vd));
- }
+ if (returnLocComp == null) {
+ throw new Error("Return location is not specified for the method " + md + " at "
+ + cd.getSourceFileName());
}
- if (hasReturnValue) {
- md2ReturnLocGen.put(md, new ReturnLocGenerator(md2ReturnLoc.get(md), paramList,
- generateErrorMessage(cd, null)));
+ md2ReturnLoc.put(md, returnLocComp);
+
+ }
+
+ if (!md.getReturnType().isVoid()) {
+ MethodLattice<String> methodLattice = ssjava.getMethodLattice(md);
+ String thisLocId = methodLattice.getThisLoc();
+ if ((!md.isStatic()) && thisLocId == null) {
+ throw new Error("Method '" + md + "' does not have the definition of 'this' location at "
+ + md.getClassDesc().getSourceFileName());
}
- checkDeclarationInBlockNode(md, md.getParameterTable(), bn);
+ CompositeLocation thisLoc = new CompositeLocation(new Location(md, thisLocId));
+ paramList.add(0, thisLoc);
+ md2ReturnLocGen.put(md, new ReturnLocGenerator(md2ReturnLoc.get(md), md, paramList, md
+ + " of " + cd.getSourceFileName()));
}
+ // fourth, check declarations inside of method
+
+ checkDeclarationInBlockNode(md, md.getParameterTable(), bn);
+
}
private void checkDeclarationInBlockNode(MethodDescriptor md, SymbolTable nametable, BlockNode bn) {
case Kind.LoopNode:
checkDeclarationInLoopNode(md, nametable, (LoopNode) bsn);
break;
+
+ case Kind.IfStatementNode:
+ checkDeclarationInIfStatementNode(md, nametable, (IfStatementNode) bsn);
+ return;
+
+ case Kind.SwitchStatementNode:
+ checkDeclarationInSwitchStatementNode(md, nametable, (SwitchStatementNode) bsn);
+ return;
+
+ case Kind.SynchronizedNode:
+ checkDeclarationInSynchronizedNode(md, nametable, (SynchronizedNode) bsn);
+ return;
+
+ }
+ }
+
+ private void checkDeclarationInSynchronizedNode(MethodDescriptor md, SymbolTable nametable,
+ SynchronizedNode sbn) {
+ checkDeclarationInBlockNode(md, nametable, sbn.getBlockNode());
+ }
+
+ private void checkDeclarationInSwitchStatementNode(MethodDescriptor md, SymbolTable nametable,
+ SwitchStatementNode ssn) {
+ BlockNode sbn = ssn.getSwitchBody();
+ for (int i = 0; i < sbn.size(); i++) {
+ SwitchBlockNode node = (SwitchBlockNode) sbn.get(i);
+ checkDeclarationInBlockNode(md, nametable, node.getSwitchBlockStatement());
}
}
+ private void checkDeclarationInIfStatementNode(MethodDescriptor md, SymbolTable nametable,
+ IfStatementNode isn) {
+ checkDeclarationInBlockNode(md, nametable, isn.getTrueBlock());
+ if (isn.getFalseBlock() != null)
+ checkDeclarationInBlockNode(md, nametable, isn.getFalseBlock());
+ }
+
private void checkDeclarationInLoopNode(MethodDescriptor md, SymbolTable nametable, LoopNode ln) {
if (ln.getType() == LoopNode.FORLOOP) {
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);
+ checkLocationFromBlockNode(md, md.getParameterTable(), bn, constraints);
}
private String generateErrorMessage(ClassDescriptor cd, TreeNode tn) {
}
private CompositeLocation checkLocationFromBlockNode(MethodDescriptor md, SymbolTable nametable,
- BlockNode bn) {
+ BlockNode bn, CompositeLocation constraint) {
bn.getVarTable().setParent(nametable);
- // it will return the lowest location in the block node
- CompositeLocation lowestLoc = null;
-
for (int i = 0; i < bn.size(); i++) {
BlockStatementNode bsn = bn.get(i);
- CompositeLocation bLoc = checkLocationFromBlockStatementNode(md, bn.getVarTable(), bsn);
- if (!bLoc.isEmpty()) {
- if (lowestLoc == null) {
- lowestLoc = bLoc;
- } else {
- if (CompositeLattice.isGreaterThan(lowestLoc, bLoc,
- generateErrorMessage(md.getClassDesc(), bn))) {
- lowestLoc = bLoc;
- }
- }
- }
-
- }
-
- if (lowestLoc == null) {
- lowestLoc = new CompositeLocation(Location.createBottomLocation(md));
+ checkLocationFromBlockStatementNode(md, bn.getVarTable(), bsn, constraint);
}
+ return new CompositeLocation();
- return lowestLoc;
}
private CompositeLocation checkLocationFromBlockStatementNode(MethodDescriptor md,
- SymbolTable nametable, BlockStatementNode bsn) {
+ SymbolTable nametable, BlockStatementNode bsn, CompositeLocation constraint) {
CompositeLocation compLoc = null;
switch (bsn.kind()) {
case Kind.BlockExpressionNode:
- compLoc = checkLocationFromBlockExpressionNode(md, nametable, (BlockExpressionNode) bsn);
+ compLoc =
+ checkLocationFromBlockExpressionNode(md, nametable, (BlockExpressionNode) bsn, constraint);
break;
case Kind.DeclarationNode:
- compLoc = checkLocationFromDeclarationNode(md, nametable, (DeclarationNode) bsn);
+ compLoc = checkLocationFromDeclarationNode(md, nametable, (DeclarationNode) bsn, constraint);
break;
case Kind.IfStatementNode:
- compLoc = checkLocationFromIfStatementNode(md, nametable, (IfStatementNode) bsn);
+ compLoc = checkLocationFromIfStatementNode(md, nametable, (IfStatementNode) bsn, constraint);
break;
case Kind.LoopNode:
- compLoc = checkLocationFromLoopNode(md, nametable, (LoopNode) bsn);
+ compLoc = checkLocationFromLoopNode(md, nametable, (LoopNode) bsn, constraint);
break;
case Kind.ReturnNode:
- compLoc = checkLocationFromReturnNode(md, nametable, (ReturnNode) bsn);
+ compLoc = checkLocationFromReturnNode(md, nametable, (ReturnNode) bsn, constraint);
break;
case Kind.SubBlockNode:
- compLoc = checkLocationFromSubBlockNode(md, nametable, (SubBlockNode) bsn);
+ compLoc = checkLocationFromSubBlockNode(md, nametable, (SubBlockNode) bsn, constraint);
break;
case Kind.ContinueBreakNode:
break;
case Kind.SwitchStatementNode:
- compLoc = checkLocationFromSwitchStatementNode(md, nametable, (SwitchStatementNode) bsn);
+ compLoc =
+ checkLocationFromSwitchStatementNode(md, nametable, (SwitchStatementNode) bsn, constraint);
}
return compLoc;
}
private CompositeLocation checkLocationFromSwitchStatementNode(MethodDescriptor md,
- SymbolTable nametable, SwitchStatementNode ssn) {
+ SymbolTable nametable, SwitchStatementNode ssn, CompositeLocation constraint) {
ClassDescriptor cd = md.getClassDesc();
CompositeLocation condLoc =
- checkLocationFromExpressionNode(md, nametable, ssn.getCondition(), new CompositeLocation());
+ checkLocationFromExpressionNode(md, nametable, ssn.getCondition(), new CompositeLocation(),
+ constraint, false);
BlockNode sbn = ssn.getSwitchBody();
- Set<CompositeLocation> blockLocSet = new HashSet<CompositeLocation>();
- for (int i = 0; i < sbn.size(); i++) {
- CompositeLocation blockLoc =
- checkLocationFromSwitchBlockNode(md, nametable, (SwitchBlockNode) sbn.get(i));
- if (!CompositeLattice.isGreaterThan(condLoc, blockLoc,
- generateErrorMessage(cd, ssn.getCondition()))) {
- throw new Error(
- "The location of the switch-condition statement is lower than the conditional body at "
- + cd.getSourceFileName() + ":" + ssn.getCondition().getNumLine());
- }
+ constraint = generateNewConstraint(constraint, condLoc);
- blockLocSet.add(blockLoc);
+ for (int i = 0; i < sbn.size(); i++) {
+ checkLocationFromSwitchBlockNode(md, nametable, (SwitchBlockNode) sbn.get(i), constraint);
}
- return CompositeLattice.calculateGLB(blockLocSet);
+ return new CompositeLocation();
}
private CompositeLocation checkLocationFromSwitchBlockNode(MethodDescriptor md,
- SymbolTable nametable, SwitchBlockNode sbn) {
+ SymbolTable nametable, SwitchBlockNode sbn, CompositeLocation constraint) {
CompositeLocation blockLoc =
- checkLocationFromBlockNode(md, nametable, sbn.getSwitchBlockStatement());
+ checkLocationFromBlockNode(md, nametable, sbn.getSwitchBlockStatement(), constraint);
return blockLoc;
}
private CompositeLocation checkLocationFromReturnNode(MethodDescriptor md, SymbolTable nametable,
- ReturnNode rn) {
+ ReturnNode rn, CompositeLocation constraint) {
ExpressionNode returnExp = rn.getReturnExpression();
CompositeLocation returnValueLoc;
if (returnExp != null) {
returnValueLoc =
- checkLocationFromExpressionNode(md, nametable, returnExp, new CompositeLocation());
+ 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<CompositeLocation> inputGLB = new HashSet<CompositeLocation>();
+ // inputGLB.add(returnValueLoc);
+ // inputGLB.add(constraint);
+ // returnValueLoc =
+ // CompositeLattice.calculateGLB(inputGLB,
+ // generateErrorMessage(md.getClassDesc(), rn));
+ // }
// check if return value is equal or higher than RETRUNLOC of method
// declaration annotation
CompositeLocation declaredReturnLoc = md2ReturnLoc.get(md);
- System.out.println("\nreturnLocAt=" + declaredReturnLoc);
- System.out.println("returnValueLoc=" + returnValueLoc);
- System.out.println("COMPARE RESULT="
- + CompositeLattice.compare(declaredReturnLoc, returnValueLoc,
- generateErrorMessage(md.getClassDesc(), rn)));
-
int compareResult =
- CompositeLattice.compare(returnValueLoc, declaredReturnLoc,
+ CompositeLattice.compare(returnValueLoc, declaredReturnLoc, false,
generateErrorMessage(md.getClassDesc(), rn));
if (compareResult == ComparisonResult.LESS || compareResult == ComparisonResult.INCOMPARABLE) {
}
private CompositeLocation checkLocationFromLoopNode(MethodDescriptor md, SymbolTable nametable,
- LoopNode ln) {
+ LoopNode ln, CompositeLocation constraint) {
ClassDescriptor cd = md.getClassDesc();
if (ln.getType() == LoopNode.WHILELOOP || ln.getType() == LoopNode.DOWHILELOOP) {
CompositeLocation condLoc =
- checkLocationFromExpressionNode(md, nametable, ln.getCondition(), new CompositeLocation());
- addLocationType(ln.getCondition().getType(), (condLoc));
-
- CompositeLocation bodyLoc = checkLocationFromBlockNode(md, nametable, ln.getBody());
+ checkLocationFromExpressionNode(md, nametable, ln.getCondition(),
+ new CompositeLocation(), constraint, false);
+ // addLocationType(ln.getCondition().getType(), (condLoc));
- if (!CompositeLattice.isGreaterThan(condLoc, bodyLoc, generateErrorMessage(cd, ln))) {
- // loop condition should be higher than loop body
- throw new Error(
- "The location of the while-condition statement is lower than the loop body at "
- + cd.getSourceFileName() + ":" + ln.getCondition().getNumLine());
- }
+ constraint = generateNewConstraint(constraint, condLoc);
+ checkLocationFromBlockNode(md, nametable, ln.getBody(), constraint);
- return bodyLoc;
+ return new CompositeLocation();
} else {
- // check for loop case
+ // 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());
- addLocationType(ln.getCondition().getType(), condLoc);
-
- CompositeLocation updateLoc =
- checkLocationFromBlockNode(md, bn.getVarTable(), ln.getUpdate());
-
- Set<CompositeLocation> glbInputSet = new HashSet<CompositeLocation>();
- glbInputSet.add(condLoc);
- // glbInputSet.add(updateLoc);
-
- CompositeLocation glbLocOfForLoopCond = CompositeLattice.calculateGLB(glbInputSet);
-
- // check location of 'forloop' body
- CompositeLocation blockLoc = checkLocationFromBlockNode(md, bn.getVarTable(), ln.getBody());
-
- // compute glb of body including loop body and update statement
- glbInputSet.clear();
+ new CompositeLocation(), constraint, false);
+ // addLocationType(ln.getCondition().getType(), condLoc);
- if (blockLoc == null) {
- // when there is no statement in the loop body
+ constraint = generateNewConstraint(constraint, condLoc);
- if (updateLoc == null) {
- // also there is no update statement in the loop body
- return glbLocOfForLoopCond;
- }
- glbInputSet.add(updateLoc);
-
- } else {
- glbInputSet.add(blockLoc);
- glbInputSet.add(updateLoc);
- }
+ checkLocationFromBlockNode(md, bn.getVarTable(), ln.getUpdate(), constraint);
+ checkLocationFromBlockNode(md, bn.getVarTable(), ln.getBody(), constraint);
- CompositeLocation loopBodyLoc = CompositeLattice.calculateGLB(glbInputSet);
+ return new CompositeLocation();
- if (!CompositeLattice.isGreaterThan(glbLocOfForLoopCond, loopBodyLoc,
- generateErrorMessage(cd, ln))) {
- throw new Error(
- "The location of the for-condition statement is lower than the for-loop body at "
- + cd.getSourceFileName() + ":" + ln.getCondition().getNumLine());
- }
- return blockLoc;
}
}
private CompositeLocation checkLocationFromSubBlockNode(MethodDescriptor md,
- SymbolTable nametable, SubBlockNode sbn) {
- CompositeLocation compLoc = checkLocationFromBlockNode(md, nametable, sbn.getBlockNode());
+ SymbolTable nametable, SubBlockNode sbn, CompositeLocation constraint) {
+ CompositeLocation compLoc =
+ checkLocationFromBlockNode(md, nametable, sbn.getBlockNode(), constraint);
return compLoc;
}
- private CompositeLocation checkLocationFromIfStatementNode(MethodDescriptor md,
- SymbolTable nametable, IfStatementNode isn) {
+ private CompositeLocation generateNewConstraint(CompositeLocation currentCon,
+ CompositeLocation newCon) {
- ClassDescriptor localCD = md.getClassDesc();
- Set<CompositeLocation> glbInputSet = new HashSet<CompositeLocation>();
+ if (currentCon == null) {
+ return newCon;
+ } else {
+ // compute GLB of current constraint and new constraint
+ Set<CompositeLocation> inputSet = new HashSet<CompositeLocation>();
+ inputSet.add(currentCon);
+ inputSet.add(newCon);
+ return CompositeLattice.calculateGLB(inputSet, "");
+ }
+
+ }
+
+ private CompositeLocation checkLocationFromIfStatementNode(MethodDescriptor md,
+ SymbolTable nametable, IfStatementNode isn, CompositeLocation constraint) {
CompositeLocation condLoc =
- checkLocationFromExpressionNode(md, nametable, isn.getCondition(), new CompositeLocation());
-
- addLocationType(isn.getCondition().getType(), condLoc);
- glbInputSet.add(condLoc);
-
- CompositeLocation locTrueBlock = checkLocationFromBlockNode(md, nametable, isn.getTrueBlock());
- if (locTrueBlock != null) {
- glbInputSet.add(locTrueBlock);
- // here, the location of conditional block should be higher than the
- // location of true/false blocks
- if (locTrueBlock != null
- && !CompositeLattice.isGreaterThan(condLoc, locTrueBlock,
- generateErrorMessage(localCD, isn.getCondition()))) {
- // error
- throw new Error(
- "The location of the if-condition statement is lower than the conditional block at "
- + localCD.getSourceFileName() + ":" + isn.getCondition().getNumLine());
- }
- }
+ checkLocationFromExpressionNode(md, nametable, isn.getCondition(), new CompositeLocation(),
+ constraint, false);
+
+ // addLocationType(isn.getCondition().getType(), condLoc);
+
+ constraint = generateNewConstraint(constraint, condLoc);
+ checkLocationFromBlockNode(md, nametable, isn.getTrueBlock(), constraint);
if (isn.getFalseBlock() != null) {
- CompositeLocation locFalseBlock =
- checkLocationFromBlockNode(md, nametable, isn.getFalseBlock());
+ checkLocationFromBlockNode(md, nametable, isn.getFalseBlock(), constraint);
+ }
- if (locFalseBlock != null) {
- glbInputSet.add(locFalseBlock);
+ return new CompositeLocation();
+ }
- if (!CompositeLattice.isGreaterThan(condLoc, locFalseBlock,
- generateErrorMessage(localCD, isn.getCondition()))) {
- // error
+ 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(
- "The location of the if-condition statement is lower than the conditional block at "
- + localCD.getSourceFileName() + ":" + isn.getCondition().getNumLine());
+ "It is not allowed to create the reference alias from the reference not owned by the method at "
+ + generateErrorMessage(md.getClassDesc(), tn));
}
- }
+ }
}
- // return GLB location of condition, true, and false block
- CompositeLocation glbLoc = CompositeLattice.calculateGLB(glbInputSet);
-
- return glbLoc;
}
private CompositeLocation checkLocationFromDeclarationNode(MethodDescriptor md,
- SymbolTable nametable, DeclarationNode dn) {
-
- System.out.println("##DeclarationNode=" + dn.printNode(0) + " "
- + generateErrorMessage(md.getClassDesc(), dn));
+ SymbolTable nametable, DeclarationNode dn, CompositeLocation constraint) {
VarDescriptor vd = dn.getVarDescriptor();
CompositeLocation destLoc = d2loc.get(vd);
- System.out.println("##DeclarationNode destLoc=" + destLoc + " of vd=" + vd + " of md=" + md);
-
if (dn.getExpression() != null) {
+
+ checkOwnership(md, dn, dn.getExpression());
+
CompositeLocation expressionLoc =
checkLocationFromExpressionNode(md, nametable, dn.getExpression(),
- new CompositeLocation());
+ new CompositeLocation(), constraint, false);
// addTypeLocation(dn.getExpression().getType(), expressionLoc);
if (expressionLoc != null) {
+
// checking location order
if (!CompositeLattice.isGreaterThan(expressionLoc, destLoc,
generateErrorMessage(md.getClassDesc(), dn))) {
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) {
+ SymbolTable nametable, BlockExpressionNode ben, CompositeLocation constraint) {
+
CompositeLocation compLoc =
- checkLocationFromExpressionNode(md, nametable, ben.getExpression(), null);
+ checkLocationFromExpressionNode(md, nametable, ben.getExpression(), null, constraint, false);
// addTypeLocation(ben.getExpression().getType(), compLoc);
return compLoc;
}
private CompositeLocation checkLocationFromExpressionNode(MethodDescriptor md,
- SymbolTable nametable, ExpressionNode en, CompositeLocation loc) {
+ SymbolTable nametable, ExpressionNode en, CompositeLocation loc,
+ CompositeLocation constraint, boolean isLHS) {
CompositeLocation compLoc = null;
switch (en.kind()) {
case Kind.AssignmentNode:
- compLoc = checkLocationFromAssignmentNode(md, nametable, (AssignmentNode) en, loc);
+ compLoc =
+ checkLocationFromAssignmentNode(md, nametable, (AssignmentNode) en, loc, constraint);
break;
case Kind.FieldAccessNode:
- compLoc = checkLocationFromFieldAccessNode(md, nametable, (FieldAccessNode) en, loc);
+ compLoc =
+ checkLocationFromFieldAccessNode(md, nametable, (FieldAccessNode) en, loc, constraint);
break;
case Kind.NameNode:
- compLoc = checkLocationFromNameNode(md, nametable, (NameNode) en, loc);
+ compLoc = checkLocationFromNameNode(md, nametable, (NameNode) en, loc, constraint);
break;
case Kind.OpNode:
- compLoc = checkLocationFromOpNode(md, nametable, (OpNode) en);
+ compLoc = checkLocationFromOpNode(md, nametable, (OpNode) en, constraint);
break;
case Kind.CreateObjectNode:
break;
case Kind.ArrayAccessNode:
- compLoc = checkLocationFromArrayAccessNode(md, nametable, (ArrayAccessNode) en);
+ compLoc =
+ checkLocationFromArrayAccessNode(md, nametable, (ArrayAccessNode) en, constraint, isLHS);
break;
case Kind.LiteralNode:
break;
case Kind.MethodInvokeNode:
- compLoc = checkLocationFromMethodInvokeNode(md, nametable, (MethodInvokeNode) en, loc);
+ compLoc =
+ checkLocationFromMethodInvokeNode(md, nametable, (MethodInvokeNode) en, loc, constraint);
break;
case Kind.TertiaryNode:
- compLoc = checkLocationFromTertiaryNode(md, nametable, (TertiaryNode) en);
+ compLoc = checkLocationFromTertiaryNode(md, nametable, (TertiaryNode) en, constraint);
break;
case Kind.CastNode:
- compLoc = checkLocationFromCastNode(md, nametable, (CastNode) en);
+ compLoc = checkLocationFromCastNode(md, nametable, (CastNode) en, constraint);
break;
// case Kind.InstanceOfNode:
}
private CompositeLocation checkLocationFromCastNode(MethodDescriptor md, SymbolTable nametable,
- CastNode cn) {
+ CastNode cn, CompositeLocation constraint) {
ExpressionNode en = cn.getExpression();
- return checkLocationFromExpressionNode(md, nametable, en, new CompositeLocation());
+ return checkLocationFromExpressionNode(md, nametable, en, new CompositeLocation(), constraint,
+ false);
}
private CompositeLocation checkLocationFromTertiaryNode(MethodDescriptor md,
- SymbolTable nametable, TertiaryNode tn) {
+ SymbolTable nametable, TertiaryNode tn, CompositeLocation constraint) {
ClassDescriptor cd = md.getClassDesc();
CompositeLocation condLoc =
- checkLocationFromExpressionNode(md, nametable, tn.getCond(), new CompositeLocation());
- addLocationType(tn.getCond().getType(), condLoc);
+ checkLocationFromExpressionNode(md, nametable, tn.getCond(), new CompositeLocation(),
+ constraint, false);
+ // addLocationType(tn.getCond().getType(), condLoc);
CompositeLocation trueLoc =
- checkLocationFromExpressionNode(md, nametable, tn.getTrueExpr(), new CompositeLocation());
- addLocationType(tn.getTrueExpr().getType(), trueLoc);
+ checkLocationFromExpressionNode(md, nametable, tn.getTrueExpr(), new CompositeLocation(),
+ constraint, false);
+ // addLocationType(tn.getTrueExpr().getType(), trueLoc);
CompositeLocation falseLoc =
- checkLocationFromExpressionNode(md, nametable, tn.getFalseExpr(), new CompositeLocation());
- addLocationType(tn.getFalseExpr().getType(), 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))) {
&& !CompositeLattice.isGreaterThan(condLoc, falseLoc,
generateErrorMessage(cd, tn.getCond()))) {
throw new Error(
- "The location of the condition expression is lower than the true expression at "
+ "The location of the condition expression is lower than the false expression at "
+ cd.getSourceFileName() + ":" + tn.getCond().getNumLine());
}
glbInputSet.add(trueLoc);
glbInputSet.add(falseLoc);
- return CompositeLattice.calculateGLB(glbInputSet);
+ 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) {
+ SymbolTable nametable, MethodInvokeNode min, CompositeLocation loc,
+ CompositeLocation constraint) {
+
+ ClassDescriptor cd = md.getClassDesc();
+ MethodDescriptor calleeMethodDesc = min.getMethod();
- checkCalleeConstraints(md, nametable, min);
+ NameDescriptor baseName = min.getBaseName();
+ boolean isSystemout = false;
+ if (baseName != null) {
+ isSystemout = baseName.getSymbol().equals("System.out");
+ }
- 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 (!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);
+ return ceilingLoc;
+ }
}
- 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(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 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();
+
+ 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) {
+ SymbolTable nametable, MethodInvokeNode min, CompositeLocation baseLocation,
+ CompositeLocation constraint) {
List<CompositeLocation> argList = new ArrayList<CompositeLocation>();
// by default, method has a THIS parameter
for (int i = 0; i < min.numArgs(); i++) {
ExpressionNode en = min.getArg(i);
CompositeLocation callerArg =
- checkLocationFromExpressionNode(md, nametable, en, new CompositeLocation());
+ checkLocationFromExpressionNode(md, nametable, en, new CompositeLocation(), constraint,
+ false);
argList.add(callerArg);
}
- System.out.println("##");
- System.out.println("min.getMethod()=" + min.getMethod() + " argList=" + argList);
- System.out.println("computeReturnLocation="
- + md2ReturnLocGen.get(min.getMethod()).computeReturnLocation(argList));
+ // System.out.println("\n## computeReturnLocation=" + min.getMethod() +
+ // " argList=" + argList);
+ CompositeLocation ceilLoc = md2ReturnLocGen.get(min.getMethod()).computeReturnLocation(argList);
+ // System.out.println("## ReturnLocation=" + ceilLoc);
- return md2ReturnLocGen.get(min.getMethod()).computeReturnLocation(argList);
+ return ceilLoc;
}
private void checkCalleeConstraints(MethodDescriptor md, SymbolTable nametable,
- MethodInvokeNode min) {
+ MethodInvokeNode min, CompositeLocation callerBaseLoc, CompositeLocation constraint) {
+
+ // System.out.println("checkCalleeConstraints=" + min.printNode(0));
- System.out.println("checkCalleeConstraints " + generateErrorMessage(md.getClassDesc(), min));
+ MethodDescriptor calleemd = min.getMethod();
- if (min.numArgs() > 1) {
+ MethodLattice<String> calleeLattice = ssjava.getMethodLattice(calleemd);
+ CompositeLocation calleeThisLoc =
+ new CompositeLocation(new Location(calleemd, calleeLattice.getThisLoc()));
+
+ List<CompositeLocation> callerArgList = new ArrayList<CompositeLocation>();
+ List<CompositeLocation> calleeParamList = new ArrayList<CompositeLocation>();
+
+ if (min.numArgs() > 0) {
// caller needs to guarantee that it passes arguments in regarding to
// callee's hierarchy
+
+ // setup caller args set
+ // first, add caller's base(this) location
+ callerArgList.add(callerBaseLoc);
+ // second, add caller's arguments
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);
-
- System.out.println("#callerResult=" + callerArg1 + " " + callerArg2);
- System.out.println("#calleeResult=" + calleeLoc1 + " " + calleeLoc2);
-
- int callerResult =
- CompositeLattice.compare(callerArg1, callerArg2,
- generateErrorMessage(md.getClassDesc(), min));
- int calleeResult =
- CompositeLattice.compare(calleeLoc1, calleeLoc2,
- generateErrorMessage(md.getClassDesc(), min));
-
- if (calleeResult == ComparisonResult.GREATER
- && callerResult != ComparisonResult.GREATER) {
- // 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());
+ CompositeLocation callerArgLoc =
+ checkLocationFromExpressionNode(md, nametable, en, new CompositeLocation(), constraint,
+ false);
+ callerArgList.add(callerArgLoc);
+ }
+
+ // setup callee params set
+ // 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);
+ // 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
+ CHECK: for (int i = 0; i < calleeParamList.size(); i++) {
+ CompositeLocation calleeLoc1 = calleeParamList.get(i);
+ CompositeLocation callerLoc1 = callerArgList.get(i);
+
+ for (int j = 0; j < calleeParamList.size(); j++) {
+ if (i != j) {
+ 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, true,
+ generateErrorMessage(md.getClassDesc(), min));
+ // System.out.println("callerResult=" + callerResult);
+ int calleeResult =
+ 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) {
+ // If calleeLoc1 is higher than calleeLoc2
+ // then, caller should have same ordering relation in-bet
+ // callerLoc1 & callerLoc2
+
+ String paramName1, paramName2;
+
+ if (i == 0) {
+ paramName1 = "'THIS'";
+ } else {
+ paramName1 = "'parameter " + calleemd.getParamName(i - 1) + "'";
+ }
+
+ if (j == 0) {
+ paramName2 = "'THIS'";
+ } else {
+ paramName2 = "'parameter " + calleemd.getParamName(j - 1) + "'";
}
+ throw new Error(
+ "Caller doesn't respect an ordering relation among method arguments: callee expects that "
+ + paramName1 + " should be higher than " + paramName2 + " in " + calleemd
+ + " at " + md.getClassDesc().getSourceFileName() + ":" + min.getNumLine());
}
}
- }
+ }
}
}
}
private CompositeLocation checkLocationFromArrayAccessNode(MethodDescriptor md,
- SymbolTable nametable, ArrayAccessNode aan) {
-
- // return glb location of array itself and index
+ SymbolTable nametable, ArrayAccessNode aan, CompositeLocation constraint, boolean isLHS) {
ClassDescriptor cd = md.getClassDesc();
- Set<CompositeLocation> glbInputSet = new HashSet<CompositeLocation>();
-
CompositeLocation arrayLoc =
- checkLocationFromExpressionNode(md, nametable, aan.getExpression(), new CompositeLocation());
+ checkLocationFromExpressionNode(md, nametable, aan.getExpression(),
+ new CompositeLocation(), constraint, isLHS);
+
// addTypeLocation(aan.getExpression().getType(), arrayLoc);
- glbInputSet.add(arrayLoc);
CompositeLocation indexLoc =
- checkLocationFromExpressionNode(md, nametable, aan.getIndex(), new CompositeLocation());
- glbInputSet.add(indexLoc);
+ checkLocationFromExpressionNode(md, nametable, aan.getIndex(), new CompositeLocation(),
+ constraint, isLHS);
// addTypeLocation(aan.getIndex().getType(), indexLoc);
- CompositeLocation glbLoc = CompositeLattice.calculateGLB(glbInputSet);
- return glbLoc;
+ if (isLHS) {
+ if (!CompositeLattice.isGreaterThan(indexLoc, arrayLoc, generateErrorMessage(cd, aan))) {
+ throw new Error("Array index value is not higher than array location at "
+ + generateErrorMessage(cd, aan));
+ }
+ return arrayLoc;
+ } else {
+ Set<CompositeLocation> inputGLB = new HashSet<CompositeLocation>();
+ inputGLB.add(arrayLoc);
+ inputGLB.add(indexLoc);
+ return CompositeLattice.calculateGLB(inputGLB, generateErrorMessage(cd, aan));
+ }
+
}
private CompositeLocation checkLocationFromCreateObjectNode(MethodDescriptor md,
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);
- addLocationType(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;
}
private CompositeLocation checkLocationFromOpNode(MethodDescriptor md, SymbolTable nametable,
- OpNode on) {
+ OpNode on, CompositeLocation constraint) {
ClassDescriptor cd = md.getClassDesc();
CompositeLocation leftLoc = new CompositeLocation();
- leftLoc = checkLocationFromExpressionNode(md, nametable, on.getLeft(), leftLoc);
+ leftLoc =
+ checkLocationFromExpressionNode(md, nametable, on.getLeft(), leftLoc, constraint, false);
// addTypeLocation(on.getLeft().getType(), leftLoc);
CompositeLocation rightLoc = new CompositeLocation();
if (on.getRight() != null) {
- rightLoc = checkLocationFromExpressionNode(md, nametable, on.getRight(), rightLoc);
+ rightLoc =
+ checkLocationFromExpressionNode(md, nametable, on.getRight(), rightLoc, constraint, false);
// addTypeLocation(on.getRight().getType(), rightLoc);
}
- System.out.println("checking op node=" + on.printNode(0)
- + generateErrorMessage(md.getClassDesc(), on));
- System.out.println("left loc=" + leftLoc + " from " + on.getLeft().getClass());
- if (on.getRight() != null) {
- System.out.println("right loc=" + rightLoc + " from " + on.getRight().kind());
- }
+ // 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());
+ // }
Operation op = on.getOp();
Set<CompositeLocation> inputSet = new HashSet<CompositeLocation>();
inputSet.add(leftLoc);
inputSet.add(rightLoc);
- CompositeLocation glbCompLoc = CompositeLattice.calculateGLB(inputSet);
+ CompositeLocation glbCompLoc =
+ CompositeLattice.calculateGLB(inputSet, generateErrorMessage(cd, on));
return glbCompLoc;
default:
}
private CompositeLocation checkLocationFromNameNode(MethodDescriptor md, SymbolTable nametable,
- NameNode nn, CompositeLocation loc) {
+ NameNode nn, CompositeLocation loc, CompositeLocation constraint) {
NameDescriptor nd = nn.getName();
if (nd.getBase() != null) {
- loc = checkLocationFromExpressionNode(md, nametable, nn.getExpression(), loc);
+ loc =
+ checkLocationFromExpressionNode(md, nametable, nn.getExpression(), loc, constraint, false);
} else {
String varname = nd.toString();
if (varname.equals("this")) {
Location locElement = new Location(md, thisLocId);
loc.addLocation(locElement);
return loc;
+
}
+
Descriptor d = (Descriptor) nametable.get(varname);
// CompositeLocation localLoc = null;
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;
// if it is 'static final', the location has TOP since no one can
// change its value
loc.addLocation(Location.createTopLocation(md));
+ return loc;
} else {
// if 'static', the location has pre-assigned global loc
MethodLattice<String> localLattice = ssjava.getMethodLattice(md);
Location fieldLoc = (Location) fd.getType().getExtension();
loc.addLocation(fieldLoc);
+ } else if (d == null) {
+ // access static field
+ FieldDescriptor fd = nn.getField();
+
+ MethodLattice<String> 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;
}
private CompositeLocation checkLocationFromFieldAccessNode(MethodDescriptor md,
- SymbolTable nametable, FieldAccessNode fan, CompositeLocation loc) {
+ SymbolTable nametable, FieldAccessNode fan, CompositeLocation loc,
+ CompositeLocation constraint) {
ExpressionNode left = fan.getExpression();
TypeDescriptor ltd = left.getType();
FieldDescriptor fd = fan.getField();
- if (ltd.isClassNameRef()) {
- // using a class name directly
+ String varName = null;
+ if (left.kind() == Kind.NameNode) {
+ NameDescriptor nd = ((NameNode) left).getName();
+ varName = nd.toString();
+ }
+
+ if (ltd.isClassNameRef() || (varName != null && varName.equals("this"))) {
+ // using a class name directly or access using this
if (fd.isStatic() && fd.isFinal()) {
loc.addLocation(Location.createTopLocation(md));
return loc;
}
}
- loc = checkLocationFromExpressionNode(md, nametable, left, loc);
+ if (left instanceof ArrayAccessNode) {
+ ArrayAccessNode aan = (ArrayAccessNode) left;
+ left = aan.getExpression();
+ }
+
+ loc = checkLocationFromExpressionNode(md, nametable, left, loc, constraint, false);
+ // System.out.println("### checkLocationFromFieldAccessNode=" +
+ // fan.printNode(0));
+ // System.out.println("### left=" + left.printNode(0));
+
if (!left.getType().isPrimitive()) {
+
+ if (fd.getSymbol().equals("length")) {
+ // array.length access, return the location of the array
+ return loc;
+ }
+
Location fieldLoc = getFieldLocation(fd);
loc.addLocation(fieldLoc);
}
-
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
}
+ 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) {
+ SymbolTable nametable, AssignmentNode an, CompositeLocation loc, CompositeLocation constraint) {
ClassDescriptor cd = md.getClassDesc();
+ Set<CompositeLocation> inputGLBSet = new HashSet<CompositeLocation>();
+
boolean postinc = true;
if (an.getOperation().getBaseOp() == null
|| (an.getOperation().getBaseOp().getOp() != Operation.POSTINC && an.getOperation()
.getBaseOp().getOp() != Operation.POSTDEC))
postinc = false;
+ // if LHS is array access node, need to check if array index is higher
+ // than array itself
CompositeLocation destLocation =
- checkLocationFromExpressionNode(md, nametable, an.getDest(), new CompositeLocation());
+ checkLocationFromExpressionNode(md, nametable, an.getDest(), new CompositeLocation(),
+ constraint, true);
- CompositeLocation srcLocation = new CompositeLocation();
+ CompositeLocation rhsLocation;
+ CompositeLocation srcLocation;
if (!postinc) {
- if (hasOnlyLiteralValue(an.getSrc())) {
- // if source is literal value, src location is TOP. so do not need to
- // compare!
- return destLocation;
+
+ checkOwnership(md, an, an.getSrc());
+
+ rhsLocation =
+ checkLocationFromExpressionNode(md, nametable, an.getSrc(), new CompositeLocation(),
+ constraint, false);
+
+ 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<CompositeLocation> srcGLBSet = new HashSet<CompositeLocation>();
+ srcGLBSet.add(rhsLocation);
+ srcGLBSet.add(destLocation);
+ srcLocation = CompositeLattice.calculateGLB(srcGLBSet, generateErrorMessage(cd, an));
+ } else {
+ srcLocation = rhsLocation;
}
- srcLocation = new CompositeLocation();
- srcLocation = checkLocationFromExpressionNode(md, nametable, an.getSrc(), srcLocation);
- // System.out.println(" an= " + an.printNode(0) + " an.getSrc()=" +
- // an.getSrc().getClass()
- // + " at " + cd.getSourceFileName() + "::" + an.getNumLine());
- // System.out.println("srcLocation=" + srcLocation);
- // System.out.println("dstLocation=" + destLocation);
+ if (constraint != null) {
+ inputGLBSet.add(srcLocation);
+ inputGLBSet.add(constraint);
+ srcLocation = CompositeLattice.calculateGLB(inputGLBSet, generateErrorMessage(cd, an));
+ }
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<FlatNode> flatNodeSet = ssjava.getBuildFlat().getFlatNodeSet(an);
+ for (Iterator iterator = flatNodeSet.iterator(); iterator.hasNext();) {
+ FlatNode fn = (FlatNode) iterator.next();
+ ssjava.addSameHeightWriteFlatNode(fn);
+ }
+
}
+
} else {
destLocation =
- srcLocation = checkLocationFromExpressionNode(md, nametable, an.getDest(), srcLocation);
+ rhsLocation =
+ checkLocationFromExpressionNode(md, nametable, an.getDest(), new CompositeLocation(),
+ constraint, false);
+
+ if (constraint != null) {
+ inputGLBSet.add(rhsLocation);
+ inputGLBSet.add(constraint);
+ srcLocation = CompositeLattice.calculateGLB(inputGLBSet, generateErrorMessage(cd, an));
+ } else {
+ srcLocation = rhsLocation;
+ }
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<FlatNode> flatNodeSet = ssjava.getBuildFlat().getFlatNodeSet(an);
+ for (Iterator iterator = flatNodeSet.iterator(); iterator.hasNext();) {
+ FlatNode fn = (FlatNode) iterator.next();
+ ssjava.addSameHeightWriteFlatNode(fn);
+ }
}
}
// 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);
}
-
}
}
return deltaLoc;
}
- private Location parseFieldLocDeclaraton(String decl, String msg) {
+ private Location parseFieldLocDeclaraton(String decl, String msg) throws Exception {
int idx = decl.indexOf(".");
+
String className = decl.substring(0, idx);
String fieldName = decl.substring(idx + 1);
Descriptor d = state.getClassSymbolTable().get(className);
if (d == null) {
+ // System.out.println("state.getClassSymbolTable()=" +
+ // state.getClassSymbolTable());
throw new Error("The class in the location declaration '" + decl + "' does not exist at "
+ msg);
}
if (localLattice == null || (!localLattice.containsKey(localLocId))) {
throw new Error("Location " + localLocId
+ " is not defined in the local variable lattice at "
- + md.getClassDesc().getSourceFileName() + "::" + (n != null ? n.getNumLine() : "") + ".");
+ + md.getClassDesc().getSourceFileName() + "::" + (n != null ? n.getNumLine() : md) + ".");
}
compLoc.addLocation(localLoc);
for (int i = 1; i < locIdList.size(); i++) {
String locName = locIdList.get(i);
-
- Location fieldLoc =
- parseFieldLocDeclaraton(locName, generateErrorMessage(md.getClassDesc(), n));
- // ClassDescriptor cd = fieldLocName2cd.get(locName);
- // SSJavaLattice<String> fieldLattice =
- // CompositeLattice.getLatticeByDescriptor(cd);
- //
- // if (fieldLattice == null || (!fieldLattice.containsKey(locName))) {
- // throw new Error("Location " + locName +
- // " is not defined in the field lattice at "
- // + cd.getSourceFileName() + ".");
- // }
- // Location fieldLoc = new Location(cd, locName);
- compLoc.addLocation(fieldLoc);
+ try {
+ Location fieldLoc =
+ parseFieldLocDeclaraton(locName, generateErrorMessage(md.getClassDesc(), n));
+ compLoc.addLocation(fieldLoc);
+ } catch (Exception e) {
+ throw new Error("The location declaration '" + locName + "' is wrong at "
+ + generateErrorMessage(md.getClassDesc(), n));
+ }
}
return compLoc;
assignLocationOfVarDescriptor(vd, md, nametable, dn);
}
- private void checkClass(ClassDescriptor cd) {
- // Check to see that methods respects ss property
- for (Iterator method_it = cd.getMethods(); method_it.hasNext();) {
- MethodDescriptor md = (MethodDescriptor) method_it.next();
- checkMethodDeclaration(cd, md);
- }
- }
-
private void checkDeclarationInClass(ClassDescriptor cd) {
// Check to see that fields are okay
for (Iterator field_it = cd.getFields(); field_it.hasNext();) {
}
}
- private void checkMethodDeclaration(ClassDescriptor cd, MethodDescriptor md) {
- // TODO
- }
-
private Location checkFieldDeclaration(ClassDescriptor cd, FieldDescriptor fd) {
Vector<AnnotationDescriptor> annotationVec = fd.getType().getAnnotationMarkers();
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);
+ }
}
}
public static boolean isGreaterThan(CompositeLocation loc1, CompositeLocation loc2, String msg) {
- System.out.println("isGreaterThan=" + 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;
}
- 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);
}
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;
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.");
+ 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);
+ }
}
Location loc2 = compLoc2.get(i);
- if (!loc1.getDescriptor().equals(loc2.getDescriptor())) {
- throw new Error("Failed to compare two locations of " + compLoc1 + " and " + compLoc2
- + " because they are not comparable at " + msg);
- }
-
- Descriptor d1 = loc1.getDescriptor();
- Descriptor d2 = loc2.getDescriptor();
-
- SSJavaLattice<String> lattice1 = getLatticeByDescriptor(d1);
- SSJavaLattice<String> lattice2 = getLatticeByDescriptor(d2);
+ Descriptor descriptor = getCommonParentDescriptor(loc1, loc2, msg);
+ SSJavaLattice<String> 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 (lattice1.getSpinLocSet().contains(loc1.getLocIdentifier())) {
+ if (lattice.getSharedLocSet().contains(loc1.getLocIdentifier())) {
if (i != (compLoc1.getSize() - 1)) {
- throw new Error("The spin location " + loc1.getLocIdentifier()
+ throw new Error("The shared location " + loc1.getLocIdentifier()
+ " cannot be appeared in the middle of composite location at" + msg);
}
}
- if (lattice2.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);
}
}
- if (!lattice1.equals(lattice2)) {
- throw new Error("Failed to compare two locations of " + compLoc1 + " and " + compLoc2
- + " because they are not comparable at " + msg);
- }
+ // if (!lattice1.equals(lattice2)) {
+ // throw new Error("Failed to compare two locations of " + compLoc1 +
+ // " and " + compLoc2
+ // + " because they are not comparable at " + msg);
+ // }
if (loc1.getLocIdentifier().equals(loc2.getLocIdentifier())) {
numOfTie++;
// note that the spinning location only can be appeared in the last
// part of the composite location
if (awareSharedLoc && numOfTie == compLoc1.getSize()
- && lattice1.getSpinLocSet().contains(loc1.getLocIdentifier())) {
+ && lattice.getSharedLocSet().contains(loc1.getLocIdentifier())) {
return ComparisonResult.GREATER;
}
continue;
- } else if (lattice1.isGreaterThan(loc1.getLocIdentifier(), loc2.getLocIdentifier())) {
+ } else if (lattice.isGreaterThan(loc1.getLocIdentifier(), loc2.getLocIdentifier())) {
return ComparisonResult.GREATER;
} else {
return ComparisonResult.LESS;
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;
}
- public static CompositeLocation calculateGLB(Set<CompositeLocation> inputSet) {
+ public static CompositeLocation calculateGLB(Set<CompositeLocation> inputSet, String errMsg) {
// System.out.println("Calculating GLB=" + inputSet);
CompositeLocation glbCompLoc = new CompositeLocation();
int maxTupleSize = 0;
CompositeLocation maxCompLoc = null;
+ Location prevPriorityLoc = null;
for (Iterator iterator = inputSet.iterator(); iterator.hasNext();) {
CompositeLocation compLoc = (CompositeLocation) iterator.next();
if (compLoc.getSize() > maxTupleSize) {
// check if priority location are coming from the same lattice
if (priorityDescriptor == null) {
priorityDescriptor = priorityLoc.getDescriptor();
- } else if (!priorityDescriptor.equals(priorityLoc.getDescriptor())) {
- throw new Error("Failed to calculate GLB of " + inputSet
- + " because they are from different lattices.");
+ } else {
+ priorityDescriptor = getCommonParentDescriptor(priorityLoc, prevPriorityLoc, errMsg);
}
+ prevPriorityLoc = priorityLoc;
+ // else if (!priorityDescriptor.equals(priorityLoc.getDescriptor())) {
+ // throw new Error("Failed to calculate GLB of " + inputSet
+ // + " because they are from different lattices.");
+ // }
}
SSJavaLattice<String> locOrder = getLatticeByDescriptor(priorityDescriptor);
}
if (compSet.size() == 1) {
-
// if GLB(x1,x2)==x1 or x2 : GLB case 2,3
CompositeLocation comp = compSet.iterator().next();
for (int i = 1; i < comp.getSize(); i++) {
// if more than one location shares the same priority GLB
// need to calculate the rest of GLB loc
- // int compositeLocSize = compSet.iterator().next().getSize();
- int compositeLocSize = maxFromCompSet.getSize();
-
- Set<String> glbInputSet = new HashSet<String>();
- Descriptor currentD = null;
- for (int i = 1; i < compositeLocSize; i++) {
- for (Iterator iterator = compSet.iterator(); iterator.hasNext();) {
- CompositeLocation compositeLocation = (CompositeLocation) iterator.next();
- if (compositeLocation.getSize() > i) {
- Location currentLoc = compositeLocation.get(i);
- currentD = currentLoc.getDescriptor();
- // making set of the current location sharing the same idx
- glbInputSet.add(currentLoc.getLocIdentifier());
- }
+ // setup input set starting from the second tuple item
+ Set<CompositeLocation> innerGLBInput = new HashSet<CompositeLocation>();
+ for (Iterator iterator = compSet.iterator(); iterator.hasNext();) {
+ CompositeLocation compLoc = (CompositeLocation) iterator.next();
+ CompositeLocation innerCompLoc = new CompositeLocation();
+ for (int idx = 1; idx < compLoc.getSize(); idx++) {
+ innerCompLoc.addLocation(compLoc.get(idx));
+ }
+ if (innerCompLoc.getSize() > 0) {
+ innerGLBInput.add(innerCompLoc);
}
- // calculate glb for the current lattice
+ }
- SSJavaLattice<String> currentLattice = getLatticeByDescriptor(currentD);
- String currentGLBLocId = currentLattice.getGLB(glbInputSet);
- glbCompLoc.addLocation(new Location(currentD, currentGLBLocId));
+ if (innerGLBInput.size() > 0) {
+ CompositeLocation innerGLB = CompositeLattice.calculateGLB(innerGLBInput, errMsg);
+ for (int idx = 0; idx < innerGLB.getSize(); idx++) {
+ glbCompLoc.addLocation(innerGLB.get(idx));
+ }
}
// if input location corresponding to glb is a delta, need to apply
}
}
+ // System.out.println("GLB=" + glbCompLoc);
return glbCompLoc;
}
return lattice;
}
+ static Descriptor getCommonParentDescriptor(Location loc1, Location loc2, String msg) {
+
+ Descriptor d1 = loc1.getDescriptor();
+ Descriptor d2 = loc2.getDescriptor();
+
+ Descriptor descriptor;
+
+ if (d1 instanceof ClassDescriptor && d2 instanceof ClassDescriptor) {
+
+ if (d1.equals(d2)) {
+ descriptor = d1;
+ } else {
+ // identifying which one is parent class
+ Set<Descriptor> d1SubClassesSet = ssjava.tu.getSubClasses((ClassDescriptor) d1);
+ Set<Descriptor> d2SubClassesSet = ssjava.tu.getSubClasses((ClassDescriptor) d2);
+
+ if (d1 == null && d2 == null) {
+ throw new Error("Failed to compare two locations of " + loc1 + " and " + loc2
+ + " 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 " + loc1 + " and " + loc2
+ + " 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 " + loc1 + " and " + loc2
+ + " because they are not comparable at " + msg);
+ }
+
+ Set<Descriptor> d1SubClassesSet =
+ ssjava.tu.getSubClasses(((MethodDescriptor) d1).getClassDesc());
+ Set<Descriptor> d2SubClassesSet =
+ ssjava.tu.getSubClasses(((MethodDescriptor) d2).getClassDesc());
+
+ if (d1 == null && d2 == null) {
+ throw new Error("Failed to compare two locations of " + loc1 + " and " + loc2
+ + " 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 " + loc1 + " and " + loc2
+ + " because they are not comparable at " + msg);
+ }
+ }
+
+ } else {
+ throw new Error("Failed to compare two locations of " + loc1 + " and " + loc2
+ + " because they are not comparable at " + msg);
+ }
+
+ return descriptor;
+
+ }
+
}
class ComparisonResult {
public static final int PARAMISSAME = 1;
public static final int IGNORE = 2;
- Hashtable<Integer, Integer> paramIdx2paramType;
+ private Hashtable<Integer, Integer> paramIdx2paramType;
- public ReturnLocGenerator(CompositeLocation returnLoc, List<CompositeLocation> params, String msg) {
- // creating mappings
- paramIdx2paramType = new Hashtable<Integer, Integer>();
- 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<CompositeLocation> 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<Integer, Integer>();
+ 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<CompositeLocation> args) {
- // compute the highest possible location in caller's side
- assert paramIdx2paramType.keySet().size() == args.size();
-
- Set<CompositeLocation> inputGLB = new HashSet<CompositeLocation>();
- 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);
- }
- }
+ 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);
- // compute GLB of arguments subset that are same or higher than return
- // location
- CompositeLocation glb = CompositeLattice.calculateGLB(inputGLB);
+ 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<CompositeLocation> inputGLB = new HashSet<CompositeLocation>();
+ 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);
+ }
+ }
- System.out.println("### computeReturnLocation");
- System.out.println("### args=" + args);
- System.out.println("### calculateGLB=" + inputGLB);
- System.out.println("### glb=" + glb);
+ // compute GLB of arguments subset that are same or higher than return
+ // location
+ if (inputGLB.isEmpty()) {
+ CompositeLocation rtr =
+ new CompositeLocation(Location.createTopLocation(args.get(0).get(0).getDescriptor()));
+ return rtr;
+ } else {
+ CompositeLocation glb = CompositeLattice.calculateGLB(inputGLB, "");
+ return glb;
+ }
+ }
- return glb;
}
}