changes.
[IRC.git] / Robust / src / Analysis / SSJava / FlowDownCheck.java
1 package Analysis.SSJava;
2
3 import java.util.HashSet;
4 import java.util.Hashtable;
5 import java.util.Iterator;
6 import java.util.Map;
7 import java.util.Set;
8 import java.util.StringTokenizer;
9 import java.util.Vector;
10
11 import IR.AnnotationDescriptor;
12 import IR.ClassDescriptor;
13 import IR.Descriptor;
14 import IR.FieldDescriptor;
15 import IR.MethodDescriptor;
16 import IR.NameDescriptor;
17 import IR.Operation;
18 import IR.State;
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.IfStatementNode;
36 import IR.Tree.InstanceOfNode;
37 import IR.Tree.Kind;
38 import IR.Tree.LiteralNode;
39 import IR.Tree.MethodInvokeNode;
40 import IR.Tree.NameNode;
41 import IR.Tree.OffsetNode;
42 import IR.Tree.OpNode;
43 import IR.Tree.SubBlockNode;
44 import IR.Tree.TertiaryNode;
45 import Util.Lattice;
46
47 public class FlowDownCheck {
48
49   static State state;
50   HashSet toanalyze;
51   Hashtable<TypeDescriptor, Location> td2loc; // mapping from 'type descriptor'
52   // to 'location'
53   Hashtable<String, ClassDescriptor> id2cd; // mapping from 'locID' to 'class
54
55   // descriptor'
56
57   public FlowDownCheck(State state) {
58     this.state = state;
59     this.toanalyze = new HashSet();
60     this.td2loc = new Hashtable<TypeDescriptor, Location>();
61     init();
62   }
63
64   public void init() {
65     id2cd = new Hashtable<String, ClassDescriptor>();
66     Hashtable cd2lattice = state.getCd2LocationOrder();
67
68     Set cdSet = cd2lattice.keySet();
69     for (Iterator iterator = cdSet.iterator(); iterator.hasNext();) {
70       ClassDescriptor cd = (ClassDescriptor) iterator.next();
71       Lattice<String> lattice = (Lattice<String>) cd2lattice.get(cd);
72
73       Set<String> locIdSet = lattice.getKeySet();
74       for (Iterator iterator2 = locIdSet.iterator(); iterator2.hasNext();) {
75         String locID = (String) iterator2.next();
76         id2cd.put(locID, cd);
77       }
78     }
79
80   }
81
82   public void flowDownCheck() {
83     SymbolTable classtable = state.getClassSymbolTable();
84
85     // phase 1 : checking declaration node and creating mapping of 'type
86     // desciptor' & 'location'
87     toanalyze.addAll(classtable.getValueSet());
88     toanalyze.addAll(state.getTaskSymbolTable().getValueSet());
89     while (!toanalyze.isEmpty()) {
90       Object obj = toanalyze.iterator().next();
91       ClassDescriptor cd = (ClassDescriptor) obj;
92       toanalyze.remove(cd);
93       if (cd.isClassLibrary()) {
94         // doesn't care about class libraries now
95         continue;
96       }
97       checkDeclarationInClass(cd);
98       for (Iterator method_it = cd.getMethods(); method_it.hasNext();) {
99         MethodDescriptor md = (MethodDescriptor) method_it.next();
100         try {
101           checkDeclarationInMethodBody(cd, md);
102         } catch (Error e) {
103           System.out.println("Error in " + md);
104           throw e;
105         }
106       }
107     }
108
109     // post-processing for delta location
110     // for a nested delta location, assigning a concrete reference to delta
111     // operand
112     Set<TypeDescriptor> tdSet = td2loc.keySet();
113     for (Iterator iterator = tdSet.iterator(); iterator.hasNext();) {
114       TypeDescriptor td = (TypeDescriptor) iterator.next();
115       Location loc = td2loc.get(td);
116
117       if (loc.getType() == Location.DELTA) {
118         // if it contains delta reference pointing to another location element
119         CompositeLocation compLoc = (CompositeLocation) loc;
120
121         Location locElement = compLoc.getTuple().at(0);
122         assert (locElement instanceof DeltaLocation);
123
124         DeltaLocation delta = (DeltaLocation) locElement;
125         TypeDescriptor refType = delta.getRefLocationId();
126         if (refType != null) {
127           Location refLoc = td2loc.get(refType);
128
129           assert (refLoc instanceof CompositeLocation);
130           CompositeLocation refCompLoc = (CompositeLocation) refLoc;
131
132           assert (refCompLoc.getTuple().at(0) instanceof DeltaLocation);
133           DeltaLocation refDelta = (DeltaLocation) refCompLoc.getTuple().at(0);
134
135           delta.addDeltaOperand(refDelta);
136           // compLoc.addLocation(refDelta);
137         }
138
139       }
140     }
141
142     // phase2 : checking assignments
143     toanalyze.addAll(classtable.getValueSet());
144     toanalyze.addAll(state.getTaskSymbolTable().getValueSet());
145     while (!toanalyze.isEmpty()) {
146       Object obj = toanalyze.iterator().next();
147       ClassDescriptor cd = (ClassDescriptor) obj;
148       toanalyze.remove(cd);
149       if (cd.isClassLibrary()) {
150         // doesn't care about class libraries now
151         continue;
152       }
153       checkClass(cd);
154       for (Iterator method_it = cd.getMethods(); method_it.hasNext();) {
155         MethodDescriptor md = (MethodDescriptor) method_it.next();
156         try {
157           checkMethodBody(cd, md);
158         } catch (Error e) {
159           System.out.println("Error in " + md);
160           throw e;
161         }
162       }
163     }
164
165   }
166
167   private void checkDeclarationInMethodBody(ClassDescriptor cd, MethodDescriptor md) {
168     BlockNode bn = state.getMethodBody(md);
169     checkDeclarationInBlockNode(md, md.getParameterTable(), bn);
170   }
171
172   private void checkDeclarationInBlockNode(MethodDescriptor md, SymbolTable nametable, BlockNode bn) {
173     bn.getVarTable().setParent(nametable);
174     for (int i = 0; i < bn.size(); i++) {
175       BlockStatementNode bsn = bn.get(i);
176       checkDeclarationInBlockStatementNode(md, bn.getVarTable(), bsn);
177     }
178   }
179
180   private void checkDeclarationInBlockStatementNode(MethodDescriptor md, SymbolTable nametable,
181       BlockStatementNode bsn) {
182
183     switch (bsn.kind()) {
184     case Kind.SubBlockNode:
185       checkDeclarationInSubBlockNode(md, nametable, (SubBlockNode) bsn);
186       return;
187     case Kind.DeclarationNode:
188       checkDeclarationNode(md, nametable, (DeclarationNode) bsn);
189       break;
190     }
191   }
192
193   private void checkMethodBody(ClassDescriptor cd, MethodDescriptor md) {
194     BlockNode bn = state.getMethodBody(md);
195     checkBlockNode(md, md.getParameterTable(), bn);
196   }
197
198   private void checkBlockNode(MethodDescriptor md, SymbolTable nametable, BlockNode bn) {
199     bn.getVarTable().setParent(nametable);
200     for (int i = 0; i < bn.size(); i++) {
201       BlockStatementNode bsn = bn.get(i);
202       checkBlockStatementNode(md, bn.getVarTable(), bsn);
203     }
204   }
205
206   private void checkBlockStatementNode(MethodDescriptor md, SymbolTable nametable,
207       BlockStatementNode bsn) {
208
209     switch (bsn.kind()) {
210     case Kind.BlockExpressionNode:
211       checkLocationFromBlockExpressionNode(md, nametable, (BlockExpressionNode) bsn);
212       return;
213
214     case Kind.DeclarationNode:
215       checkLocationFromDeclarationNode(md, nametable, (DeclarationNode) bsn);
216       return;
217
218     case Kind.IfStatementNode:
219       // checkLocationFromIfStatementNode(md, nametable, (IfStatementNode) bsn);
220       return;
221
222     case Kind.LoopNode:
223       // checkLocationFromLoopNode(md, nametable, (LoopNode) bsn);
224       return;
225
226     case Kind.ReturnNode:
227       // checkLocationFromReturnNode(md, nametable, (ReturnNode) bsn);
228       return;
229
230     case Kind.SubBlockNode:
231       // checkLocationFromSubBlockNode(md, nametable, (SubBlockNode) bsn);
232       return;
233
234     case Kind.ContinueBreakNode:
235       // checkLocationFromContinueBreakNode(md, nametable,(ContinueBreakNode)
236       // bsn);
237       return;
238     }
239   }
240
241   private void checkLocationFromDeclarationNode(MethodDescriptor md, SymbolTable nametable,
242       DeclarationNode dn) {
243     VarDescriptor vd = dn.getVarDescriptor();
244
245     Location destLoc = td2loc.get(vd.getType());
246
247     ClassDescriptor localCD = md.getClassDesc();
248     if (dn.getExpression() != null) {
249       CompositeLocation expressionLoc = new CompositeLocation(localCD);
250       expressionLoc =
251           checkLocationFromExpressionNode(md, nametable, dn.getExpression(), expressionLoc);
252
253       if (expressionLoc != null) {
254         System.out.println("expressionLoc=" + expressionLoc + " and destLoc=" + destLoc);
255
256         // checking location order
257
258         if (!CompositeLattice.isGreaterThan(expressionLoc, destLoc, localCD)) {
259           throw new Error("The value flow from " + expressionLoc + " to " + destLoc
260               + " does not respect location hierarchy on the assignment " + dn.printNode(0));
261         }
262
263       }
264
265     }
266
267   }
268
269   private void checkDeclarationInSubBlockNode(MethodDescriptor md, SymbolTable nametable,
270       SubBlockNode sbn) {
271     checkDeclarationInBlockNode(md, nametable, sbn.getBlockNode());
272   }
273
274   private void checkLocationFromBlockExpressionNode(MethodDescriptor md, SymbolTable nametable,
275       BlockExpressionNode ben) {
276     checkLocationFromExpressionNode(md, nametable, ben.getExpression(), null);
277   }
278
279   private CompositeLocation checkLocationFromExpressionNode(MethodDescriptor md,
280       SymbolTable nametable, ExpressionNode en, CompositeLocation loc) {
281
282     switch (en.kind()) {
283
284     case Kind.AssignmentNode:
285       return checkLocationFromAssignmentNode(md, nametable, (AssignmentNode) en, loc);
286
287     case Kind.FieldAccessNode:
288       return checkLocationFromFieldAccessNode(md, nametable, (FieldAccessNode) en, loc);
289
290     case Kind.NameNode:
291       return checkLocationFromNameNode(md, nametable, (NameNode) en, loc);
292
293     case Kind.OpNode:
294       return checkLocationFromOpNode(md, nametable, (OpNode) en);
295
296     case Kind.CreateObjectNode:
297       // checkCreateObjectNode(md, nametable, (CreateObjectNode) en, td);
298       return null;
299
300     case Kind.ArrayAccessNode:
301       // checkArrayAccessNode(md, nametable, (ArrayAccessNode) en, td);
302       return null;
303
304     case Kind.LiteralNode:
305       return checkLocationFromLiteralNode(md, nametable, (LiteralNode) en, loc);
306
307     case Kind.MethodInvokeNode:
308       // checkMethodInvokeNode(md,nametable,(MethodInvokeNode)en,td);
309       return null;
310
311     case Kind.OffsetNode:
312       // checkOffsetNode(md, nametable, (OffsetNode)en, td);
313       return null;
314
315     case Kind.TertiaryNode:
316       // checkTertiaryNode(md, nametable, (TertiaryNode)en, td);
317       return null;
318
319     case Kind.InstanceOfNode:
320       // checkInstanceOfNode(md, nametable, (InstanceOfNode) en, td);
321       return null;
322
323     case Kind.ArrayInitializerNode:
324       // checkArrayInitializerNode(md, nametable, (ArrayInitializerNode) en,
325       // td);
326       return null;
327
328     case Kind.ClassTypeNode:
329       // checkClassTypeNode(md, nametable, (ClassTypeNode) en, td);
330       return null;
331
332     default:
333       return null;
334
335     }
336
337   }
338
339   private CompositeLocation checkLocationFromOpNode(MethodDescriptor md, SymbolTable nametable,
340       OpNode on) {
341
342     Lattice<String> locOrder = (Lattice<String>) state.getCd2LocationOrder().get(md.getClassDesc());
343
344     ClassDescriptor cd = md.getClassDesc();
345     CompositeLocation leftLoc = new CompositeLocation(cd);
346     leftLoc = checkLocationFromExpressionNode(md, nametable, on.getLeft(), leftLoc);
347
348     CompositeLocation rightLoc = new CompositeLocation(cd);
349     if (on.getRight() != null) {
350       rightLoc = checkLocationFromExpressionNode(md, nametable, on.getRight(), rightLoc);
351     }
352
353     System.out.println("checking op node");
354     System.out.println("left loc=" + leftLoc);
355     System.out.println("right loc=" + rightLoc);
356
357     Operation op = on.getOp();
358
359     switch (op.getOp()) {
360
361     case Operation.UNARYPLUS:
362     case Operation.UNARYMINUS:
363     case Operation.LOGIC_NOT:
364       // single operand
365       on.setType(new TypeDescriptor(TypeDescriptor.BOOLEAN));
366       break;
367
368     case Operation.LOGIC_OR:
369     case Operation.LOGIC_AND:
370     case Operation.COMP:
371     case Operation.BIT_OR:
372     case Operation.BIT_XOR:
373     case Operation.BIT_AND:
374     case Operation.ISAVAILABLE:
375     case Operation.EQUAL:
376     case Operation.NOTEQUAL:
377     case Operation.LT:
378     case Operation.GT:
379     case Operation.LTE:
380     case Operation.GTE:
381     case Operation.ADD:
382     case Operation.SUB:
383     case Operation.MULT:
384     case Operation.DIV:
385     case Operation.MOD:
386     case Operation.LEFTSHIFT:
387     case Operation.RIGHTSHIFT:
388     case Operation.URIGHTSHIFT:
389
390       Set<CompositeLocation> inputSet = new HashSet<CompositeLocation>();
391       inputSet.add(leftLoc);
392       inputSet.add(rightLoc);
393       CompositeLocation glbCompLoc = CompositeLattice.calculateGLB(cd, inputSet, cd);
394       return glbCompLoc;
395
396     default:
397       throw new Error(op.toString());
398     }
399
400     return null;
401
402   }
403
404   private CompositeLocation checkLocationFromLiteralNode(MethodDescriptor md,
405       SymbolTable nametable, LiteralNode en, CompositeLocation loc) {
406
407     // literal value has the top location so that value can be flowed into any
408     // location
409     Location literalLoc = Location.createTopLocation(md.getClassDesc());
410     loc.addLocation(literalLoc);
411     return loc;
412
413   }
414
415   private CompositeLocation checkLocationFromNameNode(MethodDescriptor md, SymbolTable nametable,
416       NameNode nn, CompositeLocation loc) {
417
418     NameDescriptor nd = nn.getName();
419     if (nd.getBase() != null) {
420       loc = checkLocationFromExpressionNode(md, nametable, nn.getExpression(), loc);
421     } else {
422
423       String varname = nd.toString();
424       Descriptor d = (Descriptor) nametable.get(varname);
425
426       Location localLoc = null;
427       if (d instanceof VarDescriptor) {
428         VarDescriptor vd = (VarDescriptor) d;
429         localLoc = td2loc.get(vd.getType());
430       } else if (d instanceof FieldDescriptor) {
431         FieldDescriptor fd = (FieldDescriptor) d;
432         localLoc = td2loc.get(fd.getType());
433       }
434       assert (localLoc != null);
435
436       if (localLoc instanceof CompositeLocation) {
437         loc = (CompositeLocation) localLoc;
438       } else {
439         loc.addLocation(localLoc);
440       }
441     }
442
443     return loc;
444   }
445
446   private CompositeLocation checkLocationFromFieldAccessNode(MethodDescriptor md,
447       SymbolTable nametable, FieldAccessNode fan, CompositeLocation loc) {
448     FieldDescriptor fd = fan.getField();
449     Location fieldLoc = td2loc.get(fd.getType());
450     loc.addLocation(fieldLoc);
451
452     ExpressionNode left = fan.getExpression();
453     return checkLocationFromExpressionNode(md, nametable, left, loc);
454   }
455
456   private CompositeLocation checkLocationFromAssignmentNode(MethodDescriptor md,
457       SymbolTable nametable, AssignmentNode an, CompositeLocation loc) {
458     System.out.println("checkAssignmentNode=" + an.printNode(0));
459
460     ClassDescriptor localCD = md.getClassDesc();
461     CompositeLocation srcLocation = new CompositeLocation(md.getClassDesc());
462     CompositeLocation destLocation = new CompositeLocation(md.getClassDesc());
463
464     boolean postinc = true;
465     if (an.getOperation().getBaseOp() == null
466         || (an.getOperation().getBaseOp().getOp() != Operation.POSTINC && an.getOperation()
467             .getBaseOp().getOp() != Operation.POSTDEC))
468       postinc = false;
469     if (!postinc) {
470       srcLocation = checkLocationFromExpressionNode(md, nametable, an.getSrc(), srcLocation);
471     }
472
473     destLocation = checkLocationFromExpressionNode(md, nametable, an.getDest(), destLocation);
474
475     if (!CompositeLattice.isGreaterThan(srcLocation, destLocation, localCD)) {
476       throw new Error("The value flow from " + srcLocation + " to " + destLocation
477           + " does not respect location hierarchy on the assignment " + an.printNode(0));
478     }
479
480     return destLocation;
481   }
482
483   private Location createCompositeLocation(FieldAccessNode fan, Location loc) {
484
485     FieldDescriptor field = fan.getField();
486     ClassDescriptor fieldCD = field.getClassDescriptor();
487
488     assert (field.getType().getAnnotationMarkers().size() == 1);
489
490     AnnotationDescriptor locAnnotation = field.getType().getAnnotationMarkers().elementAt(0);
491     if (locAnnotation.getType() == AnnotationDescriptor.SINGLE_ANNOTATION) {
492       // single location
493
494     } else {
495       // delta location
496     }
497
498     // Location localLoc=new Location(field.getClassDescriptor(),field.get)
499
500     // System.out.println("creatingComposite's field="+field+" localLoc="+localLoc);
501     ExpressionNode leftNode = fan.getExpression();
502     System.out.println("creatingComposite's leftnode=" + leftNode.printNode(0));
503
504     return loc;
505   }
506
507   private void checkDeclarationNode(MethodDescriptor md, SymbolTable nametable, DeclarationNode dn) {
508
509     System.out.println("*** Check declarationNode=" + dn.printNode(0));
510
511     ClassDescriptor cd = md.getClassDesc();
512     VarDescriptor vd = dn.getVarDescriptor();
513     Vector<AnnotationDescriptor> annotationVec = vd.getType().getAnnotationMarkers();
514
515     // currently enforce every variable to have corresponding location
516     if (annotationVec.size() == 0) {
517       throw new Error("Location is not assigned to variable " + vd.getSymbol() + " in the method "
518           + md.getSymbol() + " of the class " + cd.getSymbol());
519     }
520
521     if (annotationVec.size() > 1) {
522       // variable can have at most one location
523       throw new Error(vd.getSymbol() + " has more than one location.");
524     }
525
526     AnnotationDescriptor ad = annotationVec.elementAt(0);
527     System.out.println("its ad=" + ad);
528
529     if (ad.getType() == AnnotationDescriptor.MARKER_ANNOTATION) {
530
531       // check if location is defined
532       String locationID = ad.getMarker();
533       Lattice<String> lattice = (Lattice<String>) state.getCd2LocationOrder().get(cd);
534
535       if (lattice == null || (!lattice.containsKey(locationID))) {
536         throw new Error("Location " + locationID
537             + " is not defined in the location hierarchy of class " + cd.getSymbol() + ".");
538       }
539
540       Location loc = new Location(cd, locationID);
541       td2loc.put(vd.getType(), loc);
542
543     } else if (ad.getType() == AnnotationDescriptor.SINGLE_ANNOTATION) {
544       if (ad.getMarker().equals(SSJavaAnalysis.DELTA)) {
545
546         CompositeLocation compLoc = new CompositeLocation(cd);
547
548         if (ad.getData().length() == 0) {
549           throw new Error("Delta function of " + vd.getSymbol() + " does not have any locations: "
550               + cd.getSymbol() + ".");
551         }
552
553         String deltaStr = ad.getData();
554         if (deltaStr.startsWith("LOC(")) {
555
556           if (!deltaStr.endsWith(")")) {
557             throw new Error("The declaration of the delta location is wrong at "
558                 + cd.getSourceFileName() + ":" + dn.getNumLine());
559           }
560           String locationOperand = deltaStr.substring(4, deltaStr.length() - 1);
561
562           nametable.get(locationOperand);
563           Descriptor d = (Descriptor) nametable.get(locationOperand);
564
565           if (d instanceof VarDescriptor) {
566             VarDescriptor varDescriptor = (VarDescriptor) d;
567             DeltaLocation deltaLoc = new DeltaLocation(cd, varDescriptor.getType());
568             // td2loc.put(vd.getType(), compLoc);
569             compLoc.addLocation(deltaLoc);
570           } else if (d instanceof FieldDescriptor) {
571             throw new Error("Applying delta operation to the field " + locationOperand
572                 + " is not allowed at " + cd.getSourceFileName() + ":" + dn.getNumLine());
573           }
574         } else {
575           StringTokenizer token = new StringTokenizer(deltaStr, ",");
576           DeltaLocation deltaLoc = new DeltaLocation(cd);
577
578           while (token.hasMoreTokens()) {
579             String deltaOperand = token.nextToken();
580             ClassDescriptor deltaCD = id2cd.get(deltaOperand);
581             if (deltaCD == null) {
582               // delta operand is not defined in the location hierarchy
583               throw new Error("Delta operand '" + deltaOperand + "' of declaration node '" + vd
584                   + "' is not defined by location hierarchies.");
585             }
586
587             Location loc = new Location(deltaCD, deltaOperand);
588             deltaLoc.addDeltaOperand(loc);
589           }
590           compLoc.addLocation(deltaLoc);
591
592         }
593
594         td2loc.put(vd.getType(), compLoc);
595         System.out.println("vd=" + vd + " is assigned by " + compLoc);
596
597       }
598     }
599
600   }
601
602   private void checkClass(ClassDescriptor cd) {
603     // Check to see that methods respects ss property
604     for (Iterator method_it = cd.getMethods(); method_it.hasNext();) {
605       MethodDescriptor md = (MethodDescriptor) method_it.next();
606       checkMethodDeclaration(cd, md);
607     }
608   }
609
610   private void checkDeclarationInClass(ClassDescriptor cd) {
611     // Check to see that fields are okay
612     for (Iterator field_it = cd.getFields(); field_it.hasNext();) {
613       FieldDescriptor fd = (FieldDescriptor) field_it.next();
614       checkFieldDeclaration(cd, fd);
615     }
616   }
617
618   private void checkMethodDeclaration(ClassDescriptor cd, MethodDescriptor md) {
619     // TODO
620   }
621
622   private void checkFieldDeclaration(ClassDescriptor cd, FieldDescriptor fd) {
623
624     Vector<AnnotationDescriptor> annotationVec = fd.getType().getAnnotationMarkers();
625
626     // currently enforce every variable to have corresponding location
627     if (annotationVec.size() == 0) {
628       throw new Error("Location is not assigned to the field " + fd.getSymbol() + " of the class "
629           + cd.getSymbol());
630     }
631
632     if (annotationVec.size() > 1) {
633       // variable can have at most one location
634       throw new Error("Field " + fd.getSymbol() + " of class " + cd
635           + " has more than one location.");
636     }
637
638     // check if location is defined
639     AnnotationDescriptor ad = annotationVec.elementAt(0);
640     if (ad.getType() == AnnotationDescriptor.MARKER_ANNOTATION) {
641       String locationID = annotationVec.elementAt(0).getMarker();
642       Lattice<String> lattice = (Lattice<String>) state.getCd2LocationOrder().get(cd);
643
644       if (lattice == null || (!lattice.containsKey(locationID))) {
645         throw new Error("Location " + locationID
646             + " is not defined in the location hierarchy of class " + cd.getSymbol() + ".");
647       }
648
649       Location localLoc = new Location(cd, locationID);
650       td2loc.put(fd.getType(), localLoc);
651
652     } else if (ad.getType() == AnnotationDescriptor.SINGLE_ANNOTATION) {
653       if (ad.getMarker().equals(SSJavaAnalysis.DELTA)) {
654
655         if (ad.getData().length() == 0) {
656           throw new Error("Delta function of " + fd.getSymbol() + " does not have any locations: "
657               + cd.getSymbol() + ".");
658         }
659
660         CompositeLocation compLoc = new CompositeLocation(cd);
661         DeltaLocation deltaLoc = new DeltaLocation(cd);
662
663         StringTokenizer token = new StringTokenizer(ad.getData(), ",");
664         while (token.hasMoreTokens()) {
665           String deltaOperand = token.nextToken();
666           ClassDescriptor deltaCD = id2cd.get(deltaOperand);
667           if (deltaCD == null) {
668             // delta operand is not defined in the location hierarchy
669             throw new Error("Delta operand '" + deltaOperand + "' of field node '" + fd
670                 + "' is not defined by location hierarchies.");
671           }
672
673           Location loc = new Location(deltaCD, deltaOperand);
674           deltaLoc.addDeltaOperand(loc);
675         }
676         compLoc.addLocation(deltaLoc);
677         td2loc.put(fd.getType(), compLoc);
678
679       }
680     }
681
682   }
683
684   static class CompositeLattice {
685
686     public static boolean isGreaterThan(Location loc1, Location loc2, ClassDescriptor priorityCD) {
687
688       System.out.println("isGreaterThan=" + loc1 + " ? " + loc2);
689       CompositeLocation compLoc1;
690       CompositeLocation compLoc2;
691
692       if (loc1 instanceof CompositeLocation) {
693         compLoc1 = (CompositeLocation) loc1;
694       } else {
695         // create a bogus composite location for a single location
696         compLoc1 = new CompositeLocation(loc1.getClassDescriptor());
697         compLoc1.addLocation(loc1);
698       }
699
700       if (loc2 instanceof CompositeLocation) {
701         compLoc2 = (CompositeLocation) loc2;
702       } else {
703         // create a bogus composite location for a single location
704         compLoc2 = new CompositeLocation(loc2.getClassDescriptor());
705         compLoc2.addLocation(loc2);
706       }
707
708       // comparing two composite locations
709       System.out.println("compare base location=" + compLoc1 + " ? " + compLoc2);
710
711       int baseCompareResult = compareBaseLocationSet(compLoc1, compLoc2);
712       if (baseCompareResult == ComparisonResult.EQUAL) {
713         if (compareDelta(compLoc1, compLoc2) == ComparisonResult.GREATER) {
714           return true;
715         } else {
716           return false;
717         }
718       } else if (baseCompareResult == ComparisonResult.GREATER) {
719         return true;
720       } else {
721         return false;
722       }
723
724     }
725
726     private static int compareDelta(CompositeLocation compLoc1, CompositeLocation compLoc2) {
727
728       if (compLoc1.getNumofDelta() < compLoc2.getNumofDelta()) {
729         return ComparisonResult.GREATER;
730       } else {
731         return ComparisonResult.LESS;
732       }
733     }
734
735     private static int compareBaseLocationSet(CompositeLocation compLoc1, CompositeLocation compLoc2) {
736
737       // if compLoc1 is greater than compLoc2, return true
738       // else return false;
739
740       Map<ClassDescriptor, Location> cd2loc1 = compLoc1.getCd2Loc();
741       Map<ClassDescriptor, Location> cd2loc2 = compLoc2.getCd2Loc();
742
743       // start to compare the first item of tuples:
744       // assumes that the first item has priority than other items.
745
746       NTuple<Location> locTuple1 = compLoc1.getBaseLocationTuple();
747       NTuple<Location> locTuple2 = compLoc2.getBaseLocationTuple();
748
749       Location priorityLoc1 = locTuple1.at(0);
750       Location priorityLoc2 = locTuple2.at(0);
751
752       assert (priorityLoc1.getClassDescriptor().equals(priorityLoc2.getClassDescriptor()));
753
754       ClassDescriptor cd = priorityLoc1.getClassDescriptor();
755       Lattice<String> locationOrder = (Lattice<String>) state.getCd2LocationOrder().get(cd);
756
757       if (priorityLoc1.getLocIdentifier().equals(priorityLoc2.getLocIdentifier())) {
758         // have the same level of local hierarchy
759       } else if (locationOrder.isGreaterThan(priorityLoc1.getLocIdentifier(), priorityLoc2
760           .getLocIdentifier())) {
761         // if priority loc of compLoc1 is higher than compLoc2
762         // then, compLoc 1 is higher than compLoc2
763         return ComparisonResult.GREATER;
764       } else {
765         // if priority loc of compLoc1 is NOT higher than compLoc2
766         // then, compLoc 1 is NOT higher than compLoc2
767         return ComparisonResult.LESS;
768       }
769
770       // compare base locations except priority by class descriptor
771       Set<ClassDescriptor> keySet1 = cd2loc1.keySet();
772       int numEqualLoc = 0;
773
774       for (Iterator iterator = keySet1.iterator(); iterator.hasNext();) {
775         ClassDescriptor cd1 = (ClassDescriptor) iterator.next();
776
777         Location loc1 = cd2loc1.get(cd1);
778         Location loc2 = cd2loc2.get(cd1);
779
780         if (priorityLoc1.equals(loc1)) {
781           continue;
782         }
783
784         if (loc2 == null) {
785           // if comploc2 doesn't have corresponding location,
786           // then we determines that comploc1 is lower than comploc 2
787           return ComparisonResult.LESS;
788         }
789
790         System.out.println("lattice comparison:" + loc1.getLocIdentifier() + " ? "
791             + loc2.getLocIdentifier());
792         locationOrder = (Lattice<String>) state.getCd2LocationOrder().get(cd1);
793         if (loc1.getLocIdentifier().equals(loc2.getLocIdentifier())) {
794           // have the same level of local hierarchy
795           numEqualLoc++;
796         } else if (!locationOrder.isGreaterThan(loc1.getLocIdentifier(), loc2.getLocIdentifier())) {
797           // if one element of composite location 1 is not higher than composite
798           // location 2
799           // then, composite loc 1 is not higher than composite loc 2
800
801           System.out.println(compLoc1 + " < " + compLoc2);
802           return ComparisonResult.LESS;
803         }
804
805       }
806
807       if (numEqualLoc == compLoc1.getBaseLocationSize()) {
808         System.out.println(compLoc1 + " == " + compLoc2);
809         return ComparisonResult.EQUAL;
810       }
811
812       System.out.println(compLoc1 + " > " + compLoc2);
813       return ComparisonResult.GREATER;
814     }
815
816     public static CompositeLocation calculateGLB(ClassDescriptor cd,
817         Set<CompositeLocation> inputSet, ClassDescriptor priorityCD) {
818
819       CompositeLocation glbCompLoc = new CompositeLocation(cd);
820       int maxDeltaFunction = 0;
821
822       // calculate GLB of priority element first
823
824       Hashtable<ClassDescriptor, Set<Location>> cd2locSet =
825           new Hashtable<ClassDescriptor, Set<Location>>();
826
827       // creating mapping from class to set of locations
828       for (Iterator iterator = inputSet.iterator(); iterator.hasNext();) {
829         CompositeLocation compLoc = (CompositeLocation) iterator.next();
830
831         int numOfDelta = compLoc.getNumofDelta();
832         if (numOfDelta > maxDeltaFunction) {
833           maxDeltaFunction = numOfDelta;
834         }
835
836         Set<Location> baseLocationSet = compLoc.getBaseLocationSet();
837         for (Iterator iterator2 = baseLocationSet.iterator(); iterator2.hasNext();) {
838           Location locElement = (Location) iterator2.next();
839           ClassDescriptor locCD = locElement.getClassDescriptor();
840
841           Set<Location> locSet = cd2locSet.get(locCD);
842           if (locSet == null) {
843             locSet = new HashSet<Location>();
844           }
845           locSet.add(locElement);
846
847           cd2locSet.put(locCD, locSet);
848
849         }
850       }
851
852       Set<Location> locSetofClass = cd2locSet.get(priorityCD);
853       Set<String> locIdentifierSet = new HashSet<String>();
854
855       for (Iterator<Location> locIterator = locSetofClass.iterator(); locIterator.hasNext();) {
856         Location locElement = locIterator.next();
857         locIdentifierSet.add(locElement.getLocIdentifier());
858       }
859
860       Lattice<String> locOrder = (Lattice<String>) state.getCd2LocationOrder().get(priorityCD);
861       String glbLocIdentifer = locOrder.getGLB(locIdentifierSet);
862
863       Location priorityGLB = new Location(priorityCD, glbLocIdentifer);
864
865       Set<CompositeLocation> sameGLBLoc = new HashSet<CompositeLocation>();
866
867       for (Iterator<CompositeLocation> iterator = inputSet.iterator(); iterator.hasNext();) {
868         CompositeLocation inputComploc = iterator.next();
869         Location locElement = inputComploc.getLocation(priorityCD);
870
871         if (locElement.equals(priorityGLB)) {
872           sameGLBLoc.add(inputComploc);
873         }
874       }
875       glbCompLoc.addLocation(priorityGLB);
876       if (sameGLBLoc.size() > 0) {
877         // if more than one location shares the same priority GLB
878         // need to calculate the rest of GLB loc
879
880         Set<Location> glbElementSet = new HashSet<Location>();
881
882         for (Iterator<ClassDescriptor> iterator = cd2locSet.keySet().iterator(); iterator.hasNext();) {
883           ClassDescriptor localCD = iterator.next();
884           if (!localCD.equals(priorityCD)) {
885             Set<Location> localLocSet = cd2locSet.get(localCD);
886             Set<String> LocalLocIdSet = new HashSet<String>();
887
888             for (Iterator<Location> locIterator = localLocSet.iterator(); locIterator.hasNext();) {
889               Location locElement = locIterator.next();
890               LocalLocIdSet.add(locElement.getLocIdentifier());
891             }
892
893             Lattice<String> localOrder = (Lattice<String>) state.getCd2LocationOrder().get(localCD);
894             Location localGLBLoc = new Location(localCD, localOrder.getGLB(LocalLocIdSet));
895             glbCompLoc.addLocation(localGLBLoc);
896           }
897         }
898       } else {
899         // if priority glb loc is lower than all of input loc
900         // assign top location to the rest of loc element
901
902         for (Iterator<ClassDescriptor> iterator = cd2locSet.keySet().iterator(); iterator.hasNext();) {
903           ClassDescriptor localCD = iterator.next();
904           if (!localCD.equals(priorityCD)) {
905             Location localGLBLoc = Location.createTopLocation(localCD);
906             glbCompLoc.addLocation(localGLBLoc);
907           }
908
909         }
910
911       }
912
913       return glbCompLoc;
914
915     }
916
917   }
918
919   class ComparisonResult {
920
921     public static final int GREATER = 0;
922     public static final int EQUAL = 1;
923     public static final int LESS = 2;
924     int result;
925
926   }
927
928 }