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 CompositeLocation leftOpLoc = new CompositeLocation(md.getClassDesc());
367 getLocationFromExpressionNode(md, nametable, on.getLeft(), leftOpLoc);
369 CompositeLocation rightOpLoc = new CompositeLocation(md.getClassDesc());
370 if (on.getRight() != null) {
371 getLocationFromExpressionNode(md, nametable, on.getRight(), rightOpLoc);
374 TypeDescriptor ltd = on.getLeft().getType();
375 TypeDescriptor rtd = on.getRight() != null ? on.getRight().getType() : null;
377 Operation op = on.getOp();
379 switch (op.getOp()) {
381 case Operation.UNARYPLUS:
382 case Operation.UNARYMINUS:
383 case Operation.LOGIC_NOT:
385 on.setType(new TypeDescriptor(TypeDescriptor.BOOLEAN));
388 case Operation.LOGIC_OR:
389 case Operation.LOGIC_AND:
391 case Operation.BIT_OR:
392 case Operation.BIT_XOR:
393 case Operation.BIT_AND:
394 case Operation.ISAVAILABLE:
395 case Operation.EQUAL:
396 case Operation.NOTEQUAL:
406 case Operation.LEFTSHIFT:
407 case Operation.RIGHTSHIFT:
408 case Operation.URIGHTSHIFT:
410 Set<String> operandSet = new HashSet<String>();
411 String leftLoc = ltd.getAnnotationMarkers().get(0).getMarker();
412 String rightLoc = rtd.getAnnotationMarkers().get(0).getMarker();
414 operandSet.add(leftLoc);
415 operandSet.add(rightLoc);
418 // String glbLoc = locOrder.getGLB(operandSet);
419 // on.getType().addAnnotationMarker(new AnnotationDescriptor(glbLoc));
420 // System.out.println(glbLoc + "<-" + leftLoc + " " + rightLoc);
425 throw new Error(op.toString());
429 String lhsLoc = td.getAnnotationMarkers().get(0).getMarker();
430 if (locOrder.isGreaterThan(lhsLoc, on.getType().getAnnotationMarkers().get(0).getMarker())) {
431 throw new Error("The location of LHS is higher than RHS: " + on.printNode(0));
437 protected void getLocationFromExpressionNode(MethodDescriptor md, SymbolTable nametable,
438 ExpressionNode en, CompositeLocation loc) {
442 case Kind.AssignmentNode:
443 getLocationFromAssignmentNode(md, nametable, (AssignmentNode) en, loc);
446 case Kind.FieldAccessNode:
447 getLocationFromFieldAccessNode(md, nametable, (FieldAccessNode) en, loc);
451 getLocationFromNameNode(md, nametable, (NameNode) en, loc);
455 getLocationFromOpNode(md, nametable, (OpNode) en, loc);
456 // checkOpNode(md,nametable,(OpNode)en,td);
460 // checkCastNode(md,nametable,(CastNode)en,td);
463 case Kind.CreateObjectNode:
464 // checkCreateObjectNode(md, nametable, (CreateObjectNode) en, td);
467 case Kind.ArrayAccessNode:
468 // checkArrayAccessNode(md, nametable, (ArrayAccessNode) en, td);
471 case Kind.LiteralNode:
472 getLocationFromLiteralNode(md, nametable, (LiteralNode) en, loc);
475 case Kind.MethodInvokeNode:
476 // checkMethodInvokeNode(md,nametable,(MethodInvokeNode)en,td);
479 case Kind.OffsetNode:
480 // checkOffsetNode(md, nametable, (OffsetNode)en, td);
483 case Kind.TertiaryNode:
484 // checkTertiaryNode(md, nametable, (TertiaryNode)en, td);
487 case Kind.InstanceOfNode:
488 // checkInstanceOfNode(md, nametable, (InstanceOfNode) en, td);
491 case Kind.ArrayInitializerNode:
492 // checkArrayInitializerNode(md, nametable, (ArrayInitializerNode) en,
496 case Kind.ClassTypeNode:
497 // checkClassTypeNode(md, nametable, (ClassTypeNode) en, td);
504 private void getLocationFromOpNode(MethodDescriptor md, SymbolTable nametable, OpNode on,
505 CompositeLocation loc) {
507 Lattice<String> locOrder = (Lattice<String>) state.getCd2LocationOrder().get(md.getClassDesc());
509 ClassDescriptor cd = md.getClassDesc();
510 CompositeLocation leftLoc = new CompositeLocation(cd);
511 getLocationFromExpressionNode(md, nametable, on.getLeft(), leftLoc);
513 CompositeLocation rightLoc = new CompositeLocation(cd);
514 if (on.getRight() != null) {
515 getLocationFromExpressionNode(md, nametable, on.getRight(), rightLoc);
518 System.out.println("checking op node");
519 System.out.println("left loc=" + leftLoc);
520 System.out.println("right loc=" + rightLoc);
522 Operation op = on.getOp();
524 switch (op.getOp()) {
526 case Operation.UNARYPLUS:
527 case Operation.UNARYMINUS:
528 case Operation.LOGIC_NOT:
530 on.setType(new TypeDescriptor(TypeDescriptor.BOOLEAN));
533 case Operation.LOGIC_OR:
534 case Operation.LOGIC_AND:
536 case Operation.BIT_OR:
537 case Operation.BIT_XOR:
538 case Operation.BIT_AND:
539 case Operation.ISAVAILABLE:
540 case Operation.EQUAL:
541 case Operation.NOTEQUAL:
551 case Operation.LEFTSHIFT:
552 case Operation.RIGHTSHIFT:
553 case Operation.URIGHTSHIFT:
555 Set<CompositeLocation> inputSet = new HashSet<CompositeLocation>();
556 inputSet.add(leftLoc);
557 inputSet.add(rightLoc);
558 CompositeLattice.calculateGLB(inputSet, cd, loc);
563 throw new Error(op.toString());
568 private void getLocationFromLiteralNode(MethodDescriptor md, SymbolTable nametable,
569 LiteralNode en, CompositeLocation loc) {
571 // literal value has the top location so that value can be flowed into any
573 Location literalLoc = Location.createTopLocation(md.getClassDesc());
574 loc.addLocation(literalLoc);
578 private void getLocationFromNameNode(MethodDescriptor md, SymbolTable nametable, NameNode nn,
579 CompositeLocation loc) {
581 NameDescriptor nd = nn.getName();
582 if (nd.getBase() != null) {
583 getLocationFromExpressionNode(md, nametable, nn.getExpression(), loc);
586 String varname = nd.toString();
587 Descriptor d = (Descriptor) nametable.get(varname);
589 Location localLoc = null;
590 if (d instanceof VarDescriptor) {
591 VarDescriptor vd = (VarDescriptor) d;
592 localLoc = td2loc.get(vd.getType());
593 } else if (d instanceof FieldDescriptor) {
594 FieldDescriptor fd = (FieldDescriptor) d;
595 localLoc = td2loc.get(fd.getType());
597 assert (localLoc != null);
598 loc.addLocation(localLoc);
603 private void getLocationFromFieldAccessNode(MethodDescriptor md, SymbolTable nametable,
604 FieldAccessNode fan, CompositeLocation loc) {
605 FieldDescriptor fd = fan.getField();
606 Location fieldLoc = td2loc.get(fd.getType());
607 loc.addLocation(fieldLoc);
609 ExpressionNode left = fan.getExpression();
610 getLocationFromExpressionNode(md, nametable, left, loc);
613 private CompositeLocation getLocationFromAssignmentNode(Descriptor md, SymbolTable nametable,
614 AssignmentNode en, CompositeLocation loc) {
615 // TODO Auto-generated method stub
620 private Location createCompositeLocation(FieldAccessNode fan, Location loc) {
622 FieldDescriptor field = fan.getField();
623 ClassDescriptor fieldCD = field.getClassDescriptor();
625 assert (field.getType().getAnnotationMarkers().size() == 1);
627 AnnotationDescriptor locAnnotation = field.getType().getAnnotationMarkers().elementAt(0);
628 if (locAnnotation.getType() == AnnotationDescriptor.SINGLE_ANNOTATION) {
635 // Location localLoc=new Location(field.getClassDescriptor(),field.get)
637 // System.out.println("creatingComposite's field="+field+" localLoc="+localLoc);
638 ExpressionNode leftNode = fan.getExpression();
639 System.out.println("creatingComposite's leftnode=" + leftNode.printNode(0));
644 void checkAssignmentNode(MethodDescriptor md, SymbolTable nametable, AssignmentNode an,
647 CompositeLocation srcLocation = new CompositeLocation(md.getClassDesc());
649 boolean postinc = true;
650 if (an.getOperation().getBaseOp() == null
651 || (an.getOperation().getBaseOp().getOp() != Operation.POSTINC && an.getOperation()
652 .getBaseOp().getOp() != Operation.POSTDEC))
655 // checkExpressionNode(md, nametable, an.getSrc(), td);
656 // calculateLocation(md, nametable, an.getSrc(), td);
657 getLocationFromExpressionNode(md, nametable, an.getSrc(), srcLocation);
660 ClassDescriptor cd = md.getClassDesc();
662 Location destLocation = td2loc.get(an.getDest().getType());
664 if (!CompositeLattice.isGreaterThan(srcLocation, destLocation)) {
665 throw new Error("The value flow from " + srcLocation + " to " + destLocation
666 + " does not respect location hierarchy on the assignment " + an.printNode(0));
671 void checkDeclarationNode(MethodDescriptor md, DeclarationNode dn) {
672 ClassDescriptor cd = md.getClassDesc();
673 VarDescriptor vd = dn.getVarDescriptor();
674 Vector<AnnotationDescriptor> annotationVec = vd.getType().getAnnotationMarkers();
676 // currently enforce every variable to have corresponding location
677 if (annotationVec.size() == 0) {
678 throw new Error("Location is not assigned to variable " + vd.getSymbol() + " in the method "
679 + md.getSymbol() + " of the class " + cd.getSymbol());
682 if (annotationVec.size() > 1) {
683 // variable can have at most one location
684 throw new Error(vd.getSymbol() + " has more than one location.");
687 AnnotationDescriptor ad = annotationVec.elementAt(0);
689 if (ad.getType() == AnnotationDescriptor.MARKER_ANNOTATION) {
691 // check if location is defined
692 String locationID = ad.getMarker();
693 Lattice<String> lattice = (Lattice<String>) state.getCd2LocationOrder().get(cd);
695 if (lattice == null || (!lattice.containsKey(locationID))) {
696 throw new Error("Location " + locationID
697 + " is not defined in the location hierarchy of class " + cd.getSymbol() + ".");
700 Location loc = new Location(cd, locationID);
701 td2loc.put(vd.getType(), loc);
703 } else if (ad.getType() == AnnotationDescriptor.SINGLE_ANNOTATION) {
704 if (ad.getMarker().equals(SSJavaAnalysis.DELTA)) {
706 if (ad.getData().length() == 0) {
707 throw new Error("Delta function of " + vd.getSymbol() + " does not have any locations: "
708 + cd.getSymbol() + ".");
711 StringTokenizer token = new StringTokenizer(ad.getData(), ",");
713 CompositeLocation compLoc = new CompositeLocation(cd);
714 DeltaLocation deltaLoc = new DeltaLocation(cd);
716 while (token.hasMoreTokens()) {
717 String deltaOperand = token.nextToken();
718 ClassDescriptor deltaCD = id2cd.get(deltaOperand);
719 if (deltaCD == null) {
720 // delta operand is not defined in the location hierarchy
721 throw new Error("Delta operand '" + deltaOperand + "' of declaration node '" + vd
722 + "' is not defined by location hierarchies.");
725 Location loc = new Location(deltaCD, deltaOperand);
726 deltaLoc.addDeltaOperand(loc);
728 compLoc.addLocation(deltaLoc);
729 td2loc.put(vd.getType(), compLoc);
735 private void checkClass(ClassDescriptor cd) {
736 // Check to see that methods respects ss property
737 for (Iterator method_it = cd.getMethods(); method_it.hasNext();) {
738 MethodDescriptor md = (MethodDescriptor) method_it.next();
739 checkMethodDeclaration(cd, md);
743 private void checkDeclarationInClass(ClassDescriptor cd) {
744 // Check to see that fields are okay
745 for (Iterator field_it = cd.getFields(); field_it.hasNext();) {
746 FieldDescriptor fd = (FieldDescriptor) field_it.next();
747 checkFieldDeclaration(cd, fd);
751 private void checkMethodDeclaration(ClassDescriptor cd, MethodDescriptor md) {
755 private void checkFieldDeclaration(ClassDescriptor cd, FieldDescriptor fd) {
757 Vector<AnnotationDescriptor> annotationVec = fd.getType().getAnnotationMarkers();
759 // currently enforce every variable to have corresponding location
760 if (annotationVec.size() == 0) {
761 throw new Error("Location is not assigned to the field " + fd.getSymbol() + " of the class "
765 if (annotationVec.size() > 1) {
766 // variable can have at most one location
767 throw new Error("Field " + fd.getSymbol() + " of class " + cd
768 + " has more than one location.");
771 // check if location is defined
772 AnnotationDescriptor ad = annotationVec.elementAt(0);
773 if (ad.getType() == AnnotationDescriptor.MARKER_ANNOTATION) {
774 String locationID = annotationVec.elementAt(0).getMarker();
775 Lattice<String> lattice = (Lattice<String>) state.getCd2LocationOrder().get(cd);
777 if (lattice == null || (!lattice.containsKey(locationID))) {
778 throw new Error("Location " + locationID
779 + " is not defined in the location hierarchy of class " + cd.getSymbol() + ".");
782 Location localLoc = new Location(cd, locationID);
783 td2loc.put(fd.getType(), localLoc);
785 } else if (ad.getType() == AnnotationDescriptor.SINGLE_ANNOTATION) {
786 if (ad.getMarker().equals(SSJavaAnalysis.DELTA)) {
788 if (ad.getData().length() == 0) {
789 throw new Error("Delta function of " + fd.getSymbol() + " does not have any locations: "
790 + cd.getSymbol() + ".");
793 CompositeLocation compLoc = new CompositeLocation(cd);
794 DeltaLocation deltaLoc = new DeltaLocation(cd);
796 StringTokenizer token = new StringTokenizer(ad.getData(), ",");
797 while (token.hasMoreTokens()) {
798 String deltaOperand = token.nextToken();
799 ClassDescriptor deltaCD = id2cd.get(deltaOperand);
800 if (deltaCD == null) {
801 // delta operand is not defined in the location hierarchy
802 throw new Error("Delta operand '" + deltaOperand + "' of field node '" + fd
803 + "' is not defined by location hierarchies.");
806 Location loc = new Location(deltaCD, deltaOperand);
807 deltaLoc.addDeltaOperand(loc);
809 compLoc.addLocation(deltaLoc);
810 td2loc.put(fd.getType(), compLoc);
817 static class CompositeLattice {
819 public static boolean isGreaterThan(Location loc1, Location loc2) {
821 CompositeLocation compLoc1;
822 CompositeLocation compLoc2;
824 if (loc1 instanceof CompositeLocation) {
825 compLoc1 = (CompositeLocation) loc1;
827 // create a bogus composite location for a single location
828 compLoc1 = new CompositeLocation(loc1.getClassDescriptor());
829 compLoc1.addLocation(loc1);
832 if (loc2 instanceof CompositeLocation) {
833 compLoc2 = (CompositeLocation) loc2;
835 // create a bogus composite location for a single location
836 compLoc2 = new CompositeLocation(loc2.getClassDescriptor());
837 compLoc2.addLocation(loc2);
840 // comparing two composite locations
841 System.out.println("compare base location=" + compLoc1 + " ? " + compLoc2);
843 int baseCompareResult = compareBaseLocationSet(compLoc1, compLoc2);
844 if (baseCompareResult == ComparisonResult.EQUAL) {
845 if (compareDelta(compLoc1, compLoc2) == ComparisonResult.GREATER) {
850 } else if (baseCompareResult == ComparisonResult.GREATER) {
858 private static int compareDelta(CompositeLocation compLoc1, CompositeLocation compLoc2) {
860 if (compLoc1.getNumofDelta() < compLoc2.getNumofDelta()) {
861 return ComparisonResult.GREATER;
863 return ComparisonResult.LESS;
867 private static int compareBaseLocationSet(CompositeLocation compLoc1, CompositeLocation compLoc2) {
869 // if compLoc1 is greater than compLoc2, return true
870 // else return false;
872 Map<ClassDescriptor, Location> cd2loc1 = compLoc1.getCd2Loc();
873 Map<ClassDescriptor, Location> cd2loc2 = compLoc2.getCd2Loc();
875 // compare base locations by class descriptor
877 Set<ClassDescriptor> keySet1 = cd2loc1.keySet();
881 for (Iterator iterator = keySet1.iterator(); iterator.hasNext();) {
882 ClassDescriptor cd1 = (ClassDescriptor) iterator.next();
884 Location loc1 = cd2loc1.get(cd1);
885 Location loc2 = cd2loc2.get(cd1);
888 // if comploc2 doesn't have corresponding location, then ignore this
894 Lattice<String> locationOrder = (Lattice<String>) state.getCd2LocationOrder().get(cd1);
895 if (loc1.getLocIdentifier().equals(loc2.getLocIdentifier())) {
896 // have the same level of local hierarchy
898 } else if (!locationOrder.isGreaterThan(loc1.getLocIdentifier(), loc2.getLocIdentifier())) {
899 // if one element of composite location 1 is not higher than composite
901 // then, composite loc 1 is not higher than composite loc 2
903 System.out.println(compLoc1 + " < " + compLoc2);
904 return ComparisonResult.LESS;
909 if (numEqualLoc == compLoc1.getTupleSize()) {
910 System.out.println(compLoc1 + " == " + compLoc2);
911 return ComparisonResult.EQUAL;
914 System.out.println(compLoc1 + " > " + compLoc2);
915 return ComparisonResult.GREATER;
918 public static CompositeLocation calculateGLB(Set<CompositeLocation> inputSet,
919 ClassDescriptor enclosingCD, CompositeLocation loc) {
921 Hashtable<ClassDescriptor, Set<Location>> cd2locSet =
922 new Hashtable<ClassDescriptor, Set<Location>>();
924 // creating mapping from class -> set of locations
925 for (Iterator iterator = inputSet.iterator(); iterator.hasNext();) {
926 CompositeLocation compLoc = (CompositeLocation) iterator.next();
927 Set<Location> baseLocationSet = compLoc.getBaseLocationSet();
928 for (Iterator iterator2 = baseLocationSet.iterator(); iterator2.hasNext();) {
929 Location locElement = (Location) iterator2.next();
930 ClassDescriptor locCD = locElement.getClassDescriptor();
932 Set<Location> locSet = cd2locSet.get(locCD);
933 if (locSet == null) {
934 locSet = new HashSet<Location>();
936 locSet.add(locElement);
938 cd2locSet.put(locCD, locSet);
943 // calculating GLB element for each class
944 for (Iterator<ClassDescriptor> iterator = cd2locSet.keySet().iterator(); iterator.hasNext();) {
945 ClassDescriptor localCD = iterator.next();
947 Set<Location> locSetofClass = cd2locSet.get(localCD);
949 Set<String> locIdentifierSet = new HashSet<String>();
951 for (Iterator<Location> locIterator = locSetofClass.iterator(); locIterator.hasNext();) {
952 Location locElement = locIterator.next();
953 locIdentifierSet.add(locElement.getLocIdentifier());
956 Lattice<String> locOrder = (Lattice<String>) state.getCd2LocationOrder().get(localCD);
957 String glbLocIdentifer = locOrder.getGLB(locIdentifierSet);
959 Location localGLB = new Location(localCD, glbLocIdentifer);
960 loc.addLocation(localGLB);
968 class ComparisonResult {
970 public static final int GREATER = 0;
971 public static final int EQUAL = 1;
972 public static final int LESS = 2;