1 package Analysis.SSJava;
3 import java.util.HashSet;
4 import java.util.Hashtable;
5 import java.util.Iterator;
8 import java.util.StringTokenizer;
9 import java.util.Vector;
11 import IR.AnnotationDescriptor;
12 import IR.ClassDescriptor;
14 import IR.FieldDescriptor;
15 import IR.MethodDescriptor;
16 import IR.NameDescriptor;
19 import IR.SymbolTable;
20 import IR.TypeDescriptor;
21 import IR.VarDescriptor;
22 import IR.Flat.FlatFieldNode;
23 import IR.Tree.ArrayAccessNode;
24 import IR.Tree.ArrayInitializerNode;
25 import IR.Tree.AssignmentNode;
26 import IR.Tree.BlockExpressionNode;
27 import IR.Tree.BlockNode;
28 import IR.Tree.BlockStatementNode;
29 import IR.Tree.CastNode;
30 import IR.Tree.ClassTypeNode;
31 import IR.Tree.CreateObjectNode;
32 import IR.Tree.DeclarationNode;
33 import IR.Tree.ExpressionNode;
34 import IR.Tree.FieldAccessNode;
35 import IR.Tree.InstanceOfNode;
37 import IR.Tree.LiteralNode;
38 import IR.Tree.MethodInvokeNode;
39 import IR.Tree.NameNode;
40 import IR.Tree.OffsetNode;
41 import IR.Tree.OpNode;
42 import IR.Tree.SubBlockNode;
43 import IR.Tree.TertiaryNode;
46 public class FlowDownCheck {
50 Hashtable<TypeDescriptor, Location> td2loc; // mapping from 'type descriptor'
52 Hashtable<String, ClassDescriptor> id2cd; // mapping from 'locID' to 'class
56 public FlowDownCheck(State state) {
58 this.toanalyze = new HashSet();
59 this.td2loc = new Hashtable<TypeDescriptor, Location>();
64 id2cd = new Hashtable<String, ClassDescriptor>();
65 Hashtable cd2lattice = state.getCd2LocationOrder();
67 Set cdSet = cd2lattice.keySet();
68 for (Iterator iterator = cdSet.iterator(); iterator.hasNext();) {
69 ClassDescriptor cd = (ClassDescriptor) iterator.next();
70 Lattice<String> lattice = (Lattice<String>) cd2lattice.get(cd);
72 Set<String> locIdSet = lattice.getKeySet();
73 for (Iterator iterator2 = locIdSet.iterator(); iterator2.hasNext();) {
74 String locID = (String) iterator2.next();
81 public void flowDownCheck() {
82 SymbolTable classtable = state.getClassSymbolTable();
84 // phase 1 : checking declaration node and creating mapping of 'type
85 // desciptor' & 'location'
86 toanalyze.addAll(classtable.getValueSet());
87 toanalyze.addAll(state.getTaskSymbolTable().getValueSet());
88 while (!toanalyze.isEmpty()) {
89 Object obj = toanalyze.iterator().next();
90 ClassDescriptor cd = (ClassDescriptor) obj;
92 if (cd.isClassLibrary()) {
93 // doesn't care about class libraries now
96 checkDeclarationInClass(cd);
97 for (Iterator method_it = cd.getMethods(); method_it.hasNext();) {
98 MethodDescriptor md = (MethodDescriptor) method_it.next();
100 checkDeclarationInMethodBody(cd, md);
102 System.out.println("Error in " + md);
108 // phase2 : checking assignments
109 toanalyze.addAll(classtable.getValueSet());
110 toanalyze.addAll(state.getTaskSymbolTable().getValueSet());
111 while (!toanalyze.isEmpty()) {
112 Object obj = toanalyze.iterator().next();
113 ClassDescriptor cd = (ClassDescriptor) obj;
114 toanalyze.remove(cd);
115 if (cd.isClassLibrary()) {
116 // doesn't care about class libraries now
120 for (Iterator method_it = cd.getMethods(); method_it.hasNext();) {
121 MethodDescriptor md = (MethodDescriptor) method_it.next();
123 checkMethodBody(cd, md);
125 System.out.println("Error in " + md);
133 private void checkDeclarationInMethodBody(ClassDescriptor cd, MethodDescriptor md) {
134 BlockNode bn = state.getMethodBody(md);
135 checkDeclarationInBlockNode(md, md.getParameterTable(), bn);
138 public void checkDeclarationInBlockNode(MethodDescriptor md, SymbolTable nametable, BlockNode bn) {
139 bn.getVarTable().setParent(nametable);
140 for (int i = 0; i < bn.size(); i++) {
141 BlockStatementNode bsn = bn.get(i);
142 checkDeclarationInBlockStatementNode(md, bn.getVarTable(), bsn);
146 private void checkDeclarationInBlockStatementNode(MethodDescriptor md, SymbolTable nametable,
147 BlockStatementNode bsn) {
149 switch (bsn.kind()) {
150 case Kind.SubBlockNode:
151 checkDeclarationInSubBlockNode(md, nametable, (SubBlockNode) bsn);
153 case Kind.DeclarationNode:
154 checkDeclarationNode(md, (DeclarationNode) bsn);
159 public void checkMethodBody(ClassDescriptor cd, MethodDescriptor md) {
160 BlockNode bn = state.getMethodBody(md);
161 checkBlockNode(md, md.getParameterTable(), bn);
164 public void checkBlockNode(MethodDescriptor md, SymbolTable nametable, BlockNode bn) {
165 /* Link in the naming environment */
166 bn.getVarTable().setParent(nametable);
167 for (int i = 0; i < bn.size(); i++) {
168 BlockStatementNode bsn = bn.get(i);
169 checkBlockStatementNode(md, bn.getVarTable(), bsn);
173 public void checkBlockStatementNode(MethodDescriptor md, SymbolTable nametable,
174 BlockStatementNode bsn) {
176 switch (bsn.kind()) {
177 case Kind.BlockExpressionNode:
178 checkBlockExpressionNode(md, nametable, (BlockExpressionNode) bsn);
183 * switch (bsn.kind()) { case Kind.BlockExpressionNode:
184 * checkBlockExpressionNode(md, nametable, (BlockExpressionNode) bsn);
187 * case Kind.DeclarationNode: checkDeclarationNode(md, nametable,
188 * (DeclarationNode) bsn); return;
190 * case Kind.TagDeclarationNode: checkTagDeclarationNode(md, nametable,
191 * (TagDeclarationNode) bsn); return;
193 * case Kind.IfStatementNode: checkIfStatementNode(md, nametable,
194 * (IfStatementNode) bsn); return;
196 * case Kind.SwitchStatementNode: checkSwitchStatementNode(md, nametable,
197 * (SwitchStatementNode) bsn); return;
199 * case Kind.LoopNode: checkLoopNode(md, nametable, (LoopNode) bsn); return;
201 * case Kind.ReturnNode: checkReturnNode(md, nametable, (ReturnNode) bsn);
204 * case Kind.TaskExitNode: checkTaskExitNode(md, nametable, (TaskExitNode)
207 * case Kind.SubBlockNode: checkSubBlockNode(md, nametable, (SubBlockNode)
210 * case Kind.AtomicNode: checkAtomicNode(md, nametable, (AtomicNode) bsn);
213 * case Kind.SynchronizedNode: checkSynchronizedNode(md, nametable,
214 * (SynchronizedNode) bsn); return;
216 * case Kind.ContinueBreakNode: checkContinueBreakNode(md, nametable,
217 * (ContinueBreakNode) bsn); return;
219 * case Kind.SESENode: case Kind.GenReachNode: // do nothing, no semantic
220 * check for SESEs return; }
222 // throw new Error();
225 private void checkDeclarationInSubBlockNode(MethodDescriptor md, SymbolTable nametable,
227 checkDeclarationInBlockNode(md, nametable, sbn.getBlockNode());
230 void checkBlockExpressionNode(MethodDescriptor md, SymbolTable nametable, BlockExpressionNode ben) {
231 checkExpressionNode(md, nametable, ben.getExpression(), null);
234 void checkExpressionNode(MethodDescriptor md, SymbolTable nametable, ExpressionNode en,
238 case Kind.AssignmentNode:
239 checkAssignmentNode(md, nametable, (AssignmentNode) en, td);
243 checkOpNode(md, nametable, (OpNode) en, td);
246 case Kind.FieldAccessNode:
247 checkFieldAccessNode(md, nametable, (FieldAccessNode) en, td);
251 checkNameNode(md, nametable, (NameNode) en, td);
257 * switch(en.kind()) { case Kind.AssignmentNode:
258 * checkAssignmentNode(md,nametable,(AssignmentNode)en,td); return;
260 * case Kind.CastNode: checkCastNode(md,nametable,(CastNode)en,td); return;
262 * case Kind.CreateObjectNode:
263 * checkCreateObjectNode(md,nametable,(CreateObjectNode)en,td); return;
265 * case Kind.FieldAccessNode:
266 * checkFieldAccessNode(md,nametable,(FieldAccessNode)en,td); return;
268 * case Kind.ArrayAccessNode:
269 * checkArrayAccessNode(md,nametable,(ArrayAccessNode)en,td); return;
271 * case Kind.LiteralNode: checkLiteralNode(md,nametable,(LiteralNode)en,td);
274 * case Kind.MethodInvokeNode:
275 * checkMethodInvokeNode(md,nametable,(MethodInvokeNode)en,td); return;
277 * case Kind.NameNode: checkNameNode(md,nametable,(NameNode)en,td); return;
279 * case Kind.OpNode: checkOpNode(md,nametable,(OpNode)en,td); return;
281 * case Kind.OffsetNode: checkOffsetNode(md, nametable, (OffsetNode)en, td);
284 * case Kind.TertiaryNode: checkTertiaryNode(md, nametable,
285 * (TertiaryNode)en, td); return;
287 * case Kind.InstanceOfNode: checkInstanceOfNode(md, nametable,
288 * (InstanceOfNode) en, td); return;
290 * case Kind.ArrayInitializerNode: checkArrayInitializerNode(md, nametable,
291 * (ArrayInitializerNode) en, td); return;
293 * case Kind.ClassTypeNode: checkClassTypeNode(md, nametable,
294 * (ClassTypeNode) en, td); return; }
298 void checkNameNode(MethodDescriptor md, SymbolTable nametable, NameNode nn, TypeDescriptor td) {
300 NameDescriptor nd = nn.getName();
301 System.out.println("checkNameNode=" + nn);
302 System.out.println("nn.expression=" + nn.getExpression().printNode(0));
304 if (nd.getBase() != null) {
306 /* Rewrite NameNode */
307 ExpressionNode en = translateNameDescriptorintoExpression(nd);
308 System.out.println("base=" + nd.getBase() + " field=" + nn.getField() + " en="
310 nn.setExpression(en);
311 System.out.println("checking expression node=" + en.printNode(0) + " with td=" + td);
312 checkExpressionNode(md, nametable, en, td);
314 System.out.println("base=" + nd.getBase() + " field=" + nn.getField());
318 // ExpressionNode en=nn.getExpression();
319 // if(en instanceof FieldAccessNode){
320 // FieldAccessNode fan=(FieldAccessNode)en;
321 // System.out.println("base="+nd.getBase()+" field="+fan.getFieldName());
324 // checkExpressionNode(md, nametable, nn.getExpression(), td);
325 // NameDescriptor nd = nn.getName();
326 // if (nd.getBase() != null) {
327 // System.out.println("nd.getBase()="+nd.getBase());
329 // /* Rewrite NameNode */
330 // ExpressionNode en = translateNameDescriptorintoExpression(nd);
331 // System.out.println("expressionsNode="+en);
332 // nn.setExpression(en);
333 // checkExpressionNode(md, nametable, en, td);
338 ExpressionNode translateNameDescriptorintoExpression(NameDescriptor nd) {
339 String id = nd.getIdentifier();
340 NameDescriptor base = nd.getBase();
342 NameNode nn = new NameNode(nd);
345 FieldAccessNode fan = new FieldAccessNode(translateNameDescriptorintoExpression(base), id);
350 void checkFieldAccessNode(MethodDescriptor md, SymbolTable nametable, FieldAccessNode fan,
353 System.out.println("fan=" + fan + " field=" + fan.getFieldName());
354 ExpressionNode left = fan.getExpression();
355 System.out.println("checking expression from fan=" + left.printNode(0) + " with td=" + td);
356 checkExpressionNode(md, nametable, left, null);
357 TypeDescriptor ltd = left.getType();
358 String fieldname = fan.getFieldName();
362 void checkOpNode(MethodDescriptor md, SymbolTable nametable, OpNode on, TypeDescriptor td) {
364 Lattice<String> locOrder = (Lattice<String>) state.getCd2LocationOrder().get(md.getClassDesc());
366 checkExpressionNode(md, nametable, on.getLeft(), null);
367 if (on.getRight() != null)
368 checkExpressionNode(md, nametable, on.getRight(), null);
370 TypeDescriptor ltd = on.getLeft().getType();
371 TypeDescriptor rtd = on.getRight() != null ? on.getRight().getType() : null;
373 if (ltd.getAnnotationMarkers().size() == 0) {
376 // ltd.addAnnotationMarker(new AnnotationDescriptor(Lattice.TOP));
378 if (rtd != null && rtd.getAnnotationMarkers().size() == 0) {
381 // rtd.addAnnotationMarker(new AnnotationDescriptor(Lattice.TOP));
384 System.out.println("checking op node");
385 System.out.println("td=" + td);
386 System.out.println("ltd=" + ltd);
387 System.out.println("rtd=" + rtd);
389 Operation op = on.getOp();
391 switch (op.getOp()) {
393 case Operation.UNARYPLUS:
394 case Operation.UNARYMINUS:
395 case Operation.LOGIC_NOT:
397 on.setType(new TypeDescriptor(TypeDescriptor.BOOLEAN));
400 case Operation.LOGIC_OR:
401 case Operation.LOGIC_AND:
403 case Operation.BIT_OR:
404 case Operation.BIT_XOR:
405 case Operation.BIT_AND:
406 case Operation.ISAVAILABLE:
407 case Operation.EQUAL:
408 case Operation.NOTEQUAL:
418 case Operation.LEFTSHIFT:
419 case Operation.RIGHTSHIFT:
420 case Operation.URIGHTSHIFT:
422 Set<String> operandSet = new HashSet<String>();
423 String leftLoc = ltd.getAnnotationMarkers().get(0).getMarker();
424 String rightLoc = rtd.getAnnotationMarkers().get(0).getMarker();
426 operandSet.add(leftLoc);
427 operandSet.add(rightLoc);
430 // String glbLoc = locOrder.getGLB(operandSet);
431 // on.getType().addAnnotationMarker(new AnnotationDescriptor(glbLoc));
432 // System.out.println(glbLoc + "<-" + leftLoc + " " + rightLoc);
437 throw new Error(op.toString());
441 String lhsLoc = td.getAnnotationMarkers().get(0).getMarker();
442 if (locOrder.isGreaterThan(lhsLoc, on.getType().getAnnotationMarkers().get(0).getMarker())) {
443 throw new Error("The location of LHS is higher than RHS: " + on.printNode(0));
449 protected void getLocationFromExpressionNode(MethodDescriptor md, SymbolTable nametable,
450 ExpressionNode en, CompositeLocation loc) {
454 case Kind.AssignmentNode:
455 getLocationFromAssignmentNode(md, nametable, (AssignmentNode) en, loc);
458 case Kind.FieldAccessNode:
459 getLocationFromFieldAccessNode(md, nametable, (FieldAccessNode) en, loc);
463 getLocationFromNameNode(md, nametable, (NameNode) en, loc);
467 getLocationFromOpNode(md, nametable, (OpNode) en, loc);
468 // checkOpNode(md,nametable,(OpNode)en,td);
472 // checkCastNode(md,nametable,(CastNode)en,td);
475 case Kind.CreateObjectNode:
476 // checkCreateObjectNode(md, nametable, (CreateObjectNode) en, td);
479 case Kind.ArrayAccessNode:
480 // checkArrayAccessNode(md, nametable, (ArrayAccessNode) en, td);
483 case Kind.LiteralNode:
484 getLocationFromLiteralNode(md, nametable, (LiteralNode) en, loc);
487 case Kind.MethodInvokeNode:
488 // checkMethodInvokeNode(md,nametable,(MethodInvokeNode)en,td);
491 case Kind.OffsetNode:
492 // checkOffsetNode(md, nametable, (OffsetNode)en, td);
495 case Kind.TertiaryNode:
496 // checkTertiaryNode(md, nametable, (TertiaryNode)en, td);
499 case Kind.InstanceOfNode:
500 // checkInstanceOfNode(md, nametable, (InstanceOfNode) en, td);
503 case Kind.ArrayInitializerNode:
504 // checkArrayInitializerNode(md, nametable, (ArrayInitializerNode) en,
508 case Kind.ClassTypeNode:
509 // checkClassTypeNode(md, nametable, (ClassTypeNode) en, td);
516 private void getLocationFromOpNode(MethodDescriptor md, SymbolTable nametable, OpNode on,
517 CompositeLocation loc) {
519 Lattice<String> locOrder = (Lattice<String>) state.getCd2LocationOrder().get(md.getClassDesc());
521 ClassDescriptor cd = md.getClassDesc();
522 CompositeLocation leftLoc = new CompositeLocation(cd);
523 getLocationFromExpressionNode(md, nametable, on.getLeft(), leftLoc);
525 CompositeLocation rightLoc = new CompositeLocation(cd);
526 if (on.getRight() != null) {
527 getLocationFromExpressionNode(md, nametable, on.getRight(), rightLoc);
530 System.out.println("checking op node");
531 System.out.println("left loc=" + leftLoc);
532 System.out.println("right loc=" + rightLoc);
534 Operation op = on.getOp();
536 switch (op.getOp()) {
538 case Operation.UNARYPLUS:
539 case Operation.UNARYMINUS:
540 case Operation.LOGIC_NOT:
542 on.setType(new TypeDescriptor(TypeDescriptor.BOOLEAN));
545 case Operation.LOGIC_OR:
546 case Operation.LOGIC_AND:
548 case Operation.BIT_OR:
549 case Operation.BIT_XOR:
550 case Operation.BIT_AND:
551 case Operation.ISAVAILABLE:
552 case Operation.EQUAL:
553 case Operation.NOTEQUAL:
563 case Operation.LEFTSHIFT:
564 case Operation.RIGHTSHIFT:
565 case Operation.URIGHTSHIFT:
567 // Set<String> operandSet = new HashSet<String>();
568 // String leftLoc = ltd.getAnnotationMarkers().get(0).getMarker();
569 // String rightLoc = rtd.getAnnotationMarkers().get(0).getMarker();
571 // operandSet.add(leftLoc);
572 // operandSet.add(rightLoc);
575 // String glbLoc = locOrder.getGLB(operandSet);
576 // on.getType().addAnnotationMarker(new AnnotationDescriptor(glbLoc));
577 // System.out.println(glbLoc + "<-" + leftLoc + " " + rightLoc);
582 throw new Error(op.toString());
586 // String lhsLoc = td.getAnnotationMarkers().get(0).getMarker();
587 // if (locOrder.isGreaterThan(lhsLoc,
588 // on.getType().getAnnotationMarkers().get(0).getMarker())) {
589 // throw new Error("The location of LHS is higher than RHS: " +
596 private void getLocationFromLiteralNode(MethodDescriptor md, SymbolTable nametable,
597 LiteralNode en, CompositeLocation loc) {
599 // literal value has the top location so that value can be flowed into any
601 Location literalLoc = Location.createTopLocation(md.getClassDesc());
602 loc.addLocation(literalLoc);
606 private void getLocationFromNameNode(MethodDescriptor md, SymbolTable nametable, NameNode nn,
607 CompositeLocation loc) {
609 NameDescriptor nd = nn.getName();
610 if (nd.getBase() != null) {
611 getLocationFromExpressionNode(md, nametable, nn.getExpression(), loc);
614 String varname = nd.toString();
615 Descriptor d = (Descriptor) nametable.get(varname);
617 Location localLoc = null;
618 if (d instanceof VarDescriptor) {
619 VarDescriptor vd = (VarDescriptor) d;
620 localLoc = td2loc.get(vd.getType());
621 } else if (d instanceof FieldDescriptor) {
622 FieldDescriptor fd = (FieldDescriptor) d;
623 localLoc = td2loc.get(fd.getType());
625 assert (localLoc != null);
626 loc.addLocation(localLoc);
631 private void getLocationFromFieldAccessNode(MethodDescriptor md, SymbolTable nametable,
632 FieldAccessNode fan, CompositeLocation loc) {
633 FieldDescriptor fd = fan.getField();
634 Location fieldLoc = td2loc.get(fd.getType());
635 loc.addLocation(fieldLoc);
637 ExpressionNode left = fan.getExpression();
638 getLocationFromExpressionNode(md, nametable, left, loc);
641 private CompositeLocation getLocationFromAssignmentNode(Descriptor md, SymbolTable nametable,
642 AssignmentNode en, CompositeLocation loc) {
643 // TODO Auto-generated method stub
648 private Location createCompositeLocation(FieldAccessNode fan, Location loc) {
650 FieldDescriptor field = fan.getField();
651 ClassDescriptor fieldCD = field.getClassDescriptor();
653 assert (field.getType().getAnnotationMarkers().size() == 1);
655 AnnotationDescriptor locAnnotation = field.getType().getAnnotationMarkers().elementAt(0);
656 if (locAnnotation.getType() == AnnotationDescriptor.SINGLE_ANNOTATION) {
663 // Location localLoc=new Location(field.getClassDescriptor(),field.get)
665 // System.out.println("creatingComposite's field="+field+" localLoc="+localLoc);
666 ExpressionNode leftNode = fan.getExpression();
667 System.out.println("creatingComposite's leftnode=" + leftNode.printNode(0));
672 void checkAssignmentNode(MethodDescriptor md, SymbolTable nametable, AssignmentNode an,
675 CompositeLocation srcLocation = new CompositeLocation(md.getClassDesc());
677 boolean postinc = true;
678 if (an.getOperation().getBaseOp() == null
679 || (an.getOperation().getBaseOp().getOp() != Operation.POSTINC && an.getOperation()
680 .getBaseOp().getOp() != Operation.POSTDEC))
683 // checkExpressionNode(md, nametable, an.getSrc(), td);
684 // calculateLocation(md, nametable, an.getSrc(), td);
685 getLocationFromExpressionNode(md, nametable, an.getSrc(), srcLocation);
688 ClassDescriptor cd = md.getClassDesc();
689 Lattice<String> locOrder = (Lattice<String>) state.getCd2LocationOrder().get(cd);
691 Location destLocation = td2loc.get(an.getDest().getType());
693 if (!CompositeLattice.isGreaterThan(srcLocation, destLocation)) {
694 throw new Error("The value flow from " + srcLocation + " to " + destLocation
695 + " does not respect location hierarchy on the assignment " + an.printNode(0));
700 void checkDeclarationNode(MethodDescriptor md, DeclarationNode dn) {
701 ClassDescriptor cd = md.getClassDesc();
702 VarDescriptor vd = dn.getVarDescriptor();
703 Vector<AnnotationDescriptor> annotationVec = vd.getType().getAnnotationMarkers();
705 // currently enforce every variable to have corresponding location
706 if (annotationVec.size() == 0) {
707 throw new Error("Location is not assigned to variable " + vd.getSymbol() + " in the method "
708 + md.getSymbol() + " of the class " + cd.getSymbol());
711 if (annotationVec.size() > 1) {
712 // variable can have at most one location
713 throw new Error(vd.getSymbol() + " has more than one location.");
716 AnnotationDescriptor ad = annotationVec.elementAt(0);
718 if (ad.getType() == AnnotationDescriptor.MARKER_ANNOTATION) {
720 // check if location is defined
721 String locationID = ad.getMarker();
722 Lattice<String> lattice = (Lattice<String>) state.getCd2LocationOrder().get(cd);
724 if (lattice == null || (!lattice.containsKey(locationID))) {
725 throw new Error("Location " + locationID
726 + " is not defined in the location hierarchy of class " + cd.getSymbol() + ".");
729 Location loc = new Location(cd, locationID);
730 td2loc.put(vd.getType(), loc);
732 } else if (ad.getType() == AnnotationDescriptor.SINGLE_ANNOTATION) {
733 if (ad.getMarker().equals(SSJavaAnalysis.DELTA)) {
735 if (ad.getData().length() == 0) {
736 throw new Error("Delta function of " + vd.getSymbol() + " does not have any locations: "
737 + cd.getSymbol() + ".");
740 StringTokenizer token = new StringTokenizer(ad.getData(), ",");
742 CompositeLocation compLoc = new CompositeLocation(cd);
743 DeltaLocation deltaLoc = new DeltaLocation(cd);
745 while (token.hasMoreTokens()) {
746 String deltaOperand = token.nextToken();
747 ClassDescriptor deltaCD = id2cd.get(deltaOperand);
748 if (deltaCD == null) {
749 // delta operand is not defined in the location hierarchy
750 throw new Error("Delta operand '" + deltaOperand + "' of declaration node '" + vd
751 + "' is not defined by location hierarchies.");
754 Location loc = new Location(deltaCD, deltaOperand);
755 deltaLoc.addDeltaOperand(loc);
757 compLoc.addLocation(deltaLoc);
758 td2loc.put(vd.getType(), compLoc);
764 private void checkClass(ClassDescriptor cd) {
765 // Check to see that methods respects ss property
766 for (Iterator method_it = cd.getMethods(); method_it.hasNext();) {
767 MethodDescriptor md = (MethodDescriptor) method_it.next();
768 checkMethodDeclaration(cd, md);
772 private void checkDeclarationInClass(ClassDescriptor cd) {
773 // Check to see that fields are okay
774 for (Iterator field_it = cd.getFields(); field_it.hasNext();) {
775 FieldDescriptor fd = (FieldDescriptor) field_it.next();
776 checkFieldDeclaration(cd, fd);
780 private void checkMethodDeclaration(ClassDescriptor cd, MethodDescriptor md) {
784 private void checkFieldDeclaration(ClassDescriptor cd, FieldDescriptor fd) {
786 Vector<AnnotationDescriptor> annotationVec = fd.getType().getAnnotationMarkers();
788 // currently enforce every variable to have corresponding location
789 if (annotationVec.size() == 0) {
790 throw new Error("Location is not assigned to the field " + fd.getSymbol() + " of the class "
794 if (annotationVec.size() > 1) {
795 // variable can have at most one location
796 throw new Error("Field " + fd.getSymbol() + " of class " + cd
797 + " has more than one location.");
800 // check if location is defined
801 AnnotationDescriptor ad = annotationVec.elementAt(0);
802 if (ad.getType() == AnnotationDescriptor.MARKER_ANNOTATION) {
803 String locationID = annotationVec.elementAt(0).getMarker();
804 Lattice<String> lattice = (Lattice<String>) state.getCd2LocationOrder().get(cd);
806 if (lattice == null || (!lattice.containsKey(locationID))) {
807 throw new Error("Location " + locationID
808 + " is not defined in the location hierarchy of class " + cd.getSymbol() + ".");
811 Location localLoc = new Location(cd, locationID);
812 td2loc.put(fd.getType(), localLoc);
814 } else if (ad.getType() == AnnotationDescriptor.SINGLE_ANNOTATION) {
815 if (ad.getMarker().equals(SSJavaAnalysis.DELTA)) {
817 if (ad.getData().length() == 0) {
818 throw new Error("Delta function of " + fd.getSymbol() + " does not have any locations: "
819 + cd.getSymbol() + ".");
822 CompositeLocation compLoc = new CompositeLocation(cd);
823 DeltaLocation deltaLoc = new DeltaLocation(cd);
825 StringTokenizer token = new StringTokenizer(ad.getData(), ",");
826 while (token.hasMoreTokens()) {
827 String deltaOperand = token.nextToken();
828 ClassDescriptor deltaCD = id2cd.get(deltaOperand);
829 if (deltaCD == null) {
830 // delta operand is not defined in the location hierarchy
831 throw new Error("Delta operand '" + deltaOperand + "' of field node '" + fd
832 + "' is not defined by location hierarchies.");
835 Location loc = new Location(deltaCD, deltaOperand);
836 deltaLoc.addDeltaOperand(loc);
838 compLoc.addLocation(deltaLoc);
839 td2loc.put(fd.getType(), compLoc);
846 static class CompositeLattice {
848 public static boolean isGreaterThan(Location loc1, Location loc2) {
850 CompositeLocation compLoc1;
851 CompositeLocation compLoc2;
853 if (loc1 instanceof CompositeLocation) {
854 compLoc1 = (CompositeLocation) loc1;
856 // create a bogus composite location for a single location
857 compLoc1 = new CompositeLocation(loc1.getClassDescriptor());
858 compLoc1.addLocation(loc1);
861 if (loc2 instanceof CompositeLocation) {
862 compLoc2 = (CompositeLocation) loc2;
864 // create a bogus composite location for a single location
865 compLoc2 = new CompositeLocation(loc2.getClassDescriptor());
866 compLoc2.addLocation(loc2);
869 // comparing two composite locations
870 System.out.println("compare base location=" + compLoc1 + " ? " + compLoc2);
872 int baseCompareResult = compareBaseLocationSet(compLoc1, compLoc2);
873 if (baseCompareResult == ComparisonResult.EQUAL) {
875 // need to compare # of delta operand
876 } else if (baseCompareResult == ComparisonResult.GREATER) {
885 private static int compareBaseLocationSet(CompositeLocation compLoc1, CompositeLocation compLoc2) {
887 // if compLoc1 is greater than compLoc2, return true
888 // else return false;
890 Map<ClassDescriptor, Location> cd2loc1 = compLoc1.getCd2Loc();
891 Map<ClassDescriptor, Location> cd2loc2 = compLoc2.getCd2Loc();
893 // compare base locations by class descriptor
895 Set<ClassDescriptor> keySet1 = cd2loc1.keySet();
899 for (Iterator iterator = keySet1.iterator(); iterator.hasNext();) {
900 ClassDescriptor cd1 = (ClassDescriptor) iterator.next();
902 Location loc1 = cd2loc1.get(cd1);
903 Location loc2 = cd2loc2.get(cd1);
906 // if comploc2 doesn't have corresponding location, then ignore this
912 Lattice<String> locationOrder = (Lattice<String>) state.getCd2LocationOrder().get(cd1);
913 if (loc1.getLocIdentifier().equals(loc2.getLocIdentifier())) {
914 // have the same level of local hierarchy
916 } else if (!locationOrder.isGreaterThan(loc1.getLocIdentifier(), loc2.getLocIdentifier())) {
917 // if one element of composite location 1 is not higher than composite
919 // then, composite loc 1 is not higher than composite loc 2
921 System.out.println(compLoc1 + " < " + compLoc2);
922 return ComparisonResult.LESS;
927 if (numEqualLoc == compLoc1.getTupleSize()) {
928 System.out.println(compLoc1 + " == " + compLoc2);
929 return ComparisonResult.EQUAL;
932 System.out.println(compLoc1 + " > " + compLoc2);
933 return ComparisonResult.GREATER;
938 class ComparisonResult {
940 public static final int GREATER = 0;
941 public static final int EQUAL = 1;
942 public static final int LESS = 2;