bring recent changes before starting to implement definitely written analysis for...
[IRC.git] / Robust / src / Analysis / SSJava / FlowDownCheck.java
1 package Analysis.SSJava;
2
3 import java.util.ArrayList;
4 import java.util.HashSet;
5 import java.util.Hashtable;
6 import java.util.Iterator;
7 import java.util.List;
8 import java.util.Set;
9 import java.util.StringTokenizer;
10 import java.util.Vector;
11
12 import Analysis.SSJava.FlowDownCheck.ComparisonResult;
13 import Analysis.SSJava.FlowDownCheck.CompositeLattice;
14 import IR.AnnotationDescriptor;
15 import IR.ClassDescriptor;
16 import IR.Descriptor;
17 import IR.FieldDescriptor;
18 import IR.MethodDescriptor;
19 import IR.NameDescriptor;
20 import IR.Operation;
21 import IR.State;
22 import IR.SymbolTable;
23 import IR.TypeDescriptor;
24 import IR.VarDescriptor;
25 import IR.Tree.ArrayAccessNode;
26 import IR.Tree.AssignmentNode;
27 import IR.Tree.BlockExpressionNode;
28 import IR.Tree.BlockNode;
29 import IR.Tree.BlockStatementNode;
30 import IR.Tree.CastNode;
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.Kind;
37 import IR.Tree.LiteralNode;
38 import IR.Tree.LoopNode;
39 import IR.Tree.MethodInvokeNode;
40 import IR.Tree.NameNode;
41 import IR.Tree.OpNode;
42 import IR.Tree.ReturnNode;
43 import IR.Tree.SubBlockNode;
44 import IR.Tree.TertiaryNode;
45 import IR.Tree.TreeNode;
46 import Util.Pair;
47
48 public class FlowDownCheck {
49
50   State state;
51   static SSJavaAnalysis ssjava;
52
53   HashSet toanalyze;
54
55   // mapping from 'descriptor' to 'composite location'
56   Hashtable<Descriptor, CompositeLocation> d2loc;
57
58   Hashtable<MethodDescriptor, CompositeLocation> md2ReturnLoc;
59   Hashtable<MethodDescriptor, ReturnLocGenerator> md2ReturnLocGen;
60
61   // mapping from 'locID' to 'class descriptor'
62   Hashtable<String, ClassDescriptor> fieldLocName2cd;
63
64   public FlowDownCheck(SSJavaAnalysis ssjava, State state) {
65     this.ssjava = ssjava;
66     this.state = state;
67     this.toanalyze = new HashSet();
68     this.d2loc = new Hashtable<Descriptor, CompositeLocation>();
69     this.fieldLocName2cd = new Hashtable<String, ClassDescriptor>();
70     this.md2ReturnLoc = new Hashtable<MethodDescriptor, CompositeLocation>();
71     this.md2ReturnLocGen = new Hashtable<MethodDescriptor, ReturnLocGenerator>();
72   }
73
74   public void init() {
75
76     // construct mapping from the location name to the class descriptor
77     // assume that the location name is unique through the whole program
78
79     Set<ClassDescriptor> cdSet = ssjava.getCd2lattice().keySet();
80     for (Iterator iterator = cdSet.iterator(); iterator.hasNext();) {
81       ClassDescriptor cd = (ClassDescriptor) iterator.next();
82       SSJavaLattice<String> lattice = ssjava.getCd2lattice().get(cd);
83       Set<String> fieldLocNameSet = lattice.getKeySet();
84
85       for (Iterator iterator2 = fieldLocNameSet.iterator(); iterator2.hasNext();) {
86         String fieldLocName = (String) iterator2.next();
87         fieldLocName2cd.put(fieldLocName, cd);
88       }
89
90     }
91
92   }
93
94   public void flowDownCheck() {
95     SymbolTable classtable = state.getClassSymbolTable();
96
97     // phase 1 : checking declaration node and creating mapping of 'type
98     // desciptor' & 'location'
99     toanalyze.addAll(classtable.getValueSet());
100     toanalyze.addAll(state.getTaskSymbolTable().getValueSet());
101     while (!toanalyze.isEmpty()) {
102       Object obj = toanalyze.iterator().next();
103       ClassDescriptor cd = (ClassDescriptor) obj;
104       toanalyze.remove(cd);
105
106       if (!cd.isInterface()) {
107
108         ClassDescriptor superDesc = cd.getSuperDesc();
109         if (superDesc != null && (!superDesc.isInterface())
110             && (!superDesc.getSymbol().equals("Object"))) {
111           checkOrderingInheritance(superDesc, cd);
112         }
113
114         checkDeclarationInClass(cd);
115         for (Iterator method_it = cd.getMethods(); method_it.hasNext();) {
116           MethodDescriptor md = (MethodDescriptor) method_it.next();
117           if (ssjava.needTobeAnnotated(md)) {
118             checkDeclarationInMethodBody(cd, md);
119           }
120         }
121       }
122
123     }
124
125     // phase2 : checking assignments
126     toanalyze.addAll(classtable.getValueSet());
127     toanalyze.addAll(state.getTaskSymbolTable().getValueSet());
128     while (!toanalyze.isEmpty()) {
129       Object obj = toanalyze.iterator().next();
130       ClassDescriptor cd = (ClassDescriptor) obj;
131       toanalyze.remove(cd);
132
133       checkClass(cd);
134       for (Iterator method_it = cd.getMethods(); method_it.hasNext();) {
135         MethodDescriptor md = (MethodDescriptor) method_it.next();
136         if (ssjava.needTobeAnnotated(md)) {
137           checkMethodBody(cd, md);
138         }
139       }
140     }
141
142   }
143
144   private void checkOrderingInheritance(ClassDescriptor superCd, ClassDescriptor cd) {
145     // here, we're going to check that sub class keeps same relative orderings
146     // in respect to super class
147
148     SSJavaLattice<String> superLattice = ssjava.getClassLattice(superCd);
149     SSJavaLattice<String> subLattice = ssjava.getClassLattice(cd);
150
151     if (superLattice != null && subLattice == null) {
152       throw new Error("If a parent class '" + superCd + "' has a ordering lattice, its subclass '"
153           + cd + "' should have one.");
154     }
155
156     Set<Pair<String, String>> superPairSet = superLattice.getOrderingPairSet();
157     Set<Pair<String, String>> subPairSet = subLattice.getOrderingPairSet();
158
159     for (Iterator iterator = superPairSet.iterator(); iterator.hasNext();) {
160       Pair<String, String> pair = (Pair<String, String>) iterator.next();
161
162       if (!subPairSet.contains(pair)) {
163         throw new Error("Subclass '" + cd + "' does not have the relative ordering '"
164             + pair.getSecond() + " < " + pair.getFirst() + "' that is defined by its superclass '"
165             + superCd + "'.");
166       }
167     }
168
169   }
170
171   public Hashtable getMap() {
172     return d2loc;
173   }
174
175   private void checkDeclarationInMethodBody(ClassDescriptor cd, MethodDescriptor md) {
176     BlockNode bn = state.getMethodBody(md);
177
178     // parsing returnloc annotation
179     if (ssjava.needTobeAnnotated(md)) {
180
181       Vector<AnnotationDescriptor> methodAnnotations = md.getModifiers().getAnnotations();
182       if (methodAnnotations != null) {
183         for (int i = 0; i < methodAnnotations.size(); i++) {
184           AnnotationDescriptor an = methodAnnotations.elementAt(i);
185           if (an.getMarker().equals(ssjava.RETURNLOC)) {
186             // developer explicitly defines method lattice
187             String returnLocDeclaration = an.getValue();
188             CompositeLocation returnLocComp =
189                 parseLocationDeclaration(md, null, returnLocDeclaration);
190             md2ReturnLoc.put(md, returnLocComp);
191           }
192         }
193
194         if (!md.getReturnType().isVoid() && !md2ReturnLoc.containsKey(md)) {
195           throw new Error("Return location is not specified for the method " + md + " at "
196               + cd.getSourceFileName());
197         }
198
199       }
200     }
201
202     List<CompositeLocation> paramList = new ArrayList<CompositeLocation>();
203
204     boolean hasReturnValue = (!md.getReturnType().isVoid());
205     if (hasReturnValue) {
206       MethodLattice<String> methodLattice = ssjava.getMethodLattice(md);
207       String thisLocId = methodLattice.getThisLoc();
208       CompositeLocation thisLoc = new CompositeLocation(new Location(md, thisLocId));
209       paramList.add(thisLoc);
210     }
211
212     for (int i = 0; i < md.numParameters(); i++) {
213       // process annotations on method parameters
214       VarDescriptor vd = (VarDescriptor) md.getParameter(i);
215       assignLocationOfVarDescriptor(vd, md, md.getParameterTable(), bn);
216       if (hasReturnValue) {
217         paramList.add(d2loc.get(vd));
218       }
219     }
220
221     if (hasReturnValue) {
222       md2ReturnLocGen.put(md, new ReturnLocGenerator(md2ReturnLoc.get(md), paramList));
223     }
224
225     checkDeclarationInBlockNode(md, md.getParameterTable(), bn);
226   }
227
228   private void checkDeclarationInBlockNode(MethodDescriptor md, SymbolTable nametable, BlockNode bn) {
229     bn.getVarTable().setParent(nametable);
230     for (int i = 0; i < bn.size(); i++) {
231       BlockStatementNode bsn = bn.get(i);
232       checkDeclarationInBlockStatementNode(md, bn.getVarTable(), bsn);
233     }
234   }
235
236   private void checkDeclarationInBlockStatementNode(MethodDescriptor md, SymbolTable nametable,
237       BlockStatementNode bsn) {
238
239     switch (bsn.kind()) {
240     case Kind.SubBlockNode:
241       checkDeclarationInSubBlockNode(md, nametable, (SubBlockNode) bsn);
242       return;
243
244     case Kind.DeclarationNode:
245       checkDeclarationNode(md, nametable, (DeclarationNode) bsn);
246       break;
247
248     case Kind.LoopNode:
249       checkDeclarationInLoopNode(md, nametable, (LoopNode) bsn);
250       break;
251     }
252   }
253
254   private void checkDeclarationInLoopNode(MethodDescriptor md, SymbolTable nametable, LoopNode ln) {
255
256     if (ln.getType() == LoopNode.FORLOOP) {
257       // check for loop case
258       ClassDescriptor cd = md.getClassDesc();
259       BlockNode bn = ln.getInitializer();
260       for (int i = 0; i < bn.size(); i++) {
261         BlockStatementNode bsn = bn.get(i);
262         checkDeclarationInBlockStatementNode(md, nametable, bsn);
263       }
264     }
265
266     // check loop body
267     checkDeclarationInBlockNode(md, nametable, ln.getBody());
268   }
269
270   private void checkMethodBody(ClassDescriptor cd, MethodDescriptor md) {
271     BlockNode bn = state.getMethodBody(md);
272     checkLocationFromBlockNode(md, md.getParameterTable(), bn);
273   }
274
275   private CompositeLocation checkLocationFromBlockNode(MethodDescriptor md, SymbolTable nametable,
276       BlockNode bn) {
277
278     bn.getVarTable().setParent(nametable);
279     // it will return the lowest location in the block node
280     CompositeLocation lowestLoc = null;
281
282     for (int i = 0; i < bn.size(); i++) {
283       BlockStatementNode bsn = bn.get(i);
284       CompositeLocation bLoc = checkLocationFromBlockStatementNode(md, bn.getVarTable(), bsn);
285       if (!bLoc.isEmpty()) {
286         if (lowestLoc == null) {
287           lowestLoc = bLoc;
288         } else {
289           if (CompositeLattice.isGreaterThan(lowestLoc, bLoc)) {
290             lowestLoc = bLoc;
291           }
292         }
293       }
294
295     }
296
297     if (lowestLoc == null) {
298       lowestLoc = new CompositeLocation(Location.createBottomLocation(md));
299     }
300
301     return lowestLoc;
302   }
303
304   private CompositeLocation checkLocationFromBlockStatementNode(MethodDescriptor md,
305       SymbolTable nametable, BlockStatementNode bsn) {
306
307     CompositeLocation compLoc = null;
308     switch (bsn.kind()) {
309     case Kind.BlockExpressionNode:
310       compLoc = checkLocationFromBlockExpressionNode(md, nametable, (BlockExpressionNode) bsn);
311       break;
312
313     case Kind.DeclarationNode:
314       compLoc = checkLocationFromDeclarationNode(md, nametable, (DeclarationNode) bsn);
315       break;
316
317     case Kind.IfStatementNode:
318       compLoc = checkLocationFromIfStatementNode(md, nametable, (IfStatementNode) bsn);
319       break;
320
321     case Kind.LoopNode:
322       compLoc = checkLocationFromLoopNode(md, nametable, (LoopNode) bsn);
323       break;
324
325     case Kind.ReturnNode:
326       compLoc = checkLocationFromReturnNode(md, nametable, (ReturnNode) bsn);
327       break;
328
329     case Kind.SubBlockNode:
330       compLoc = checkLocationFromSubBlockNode(md, nametable, (SubBlockNode) bsn);
331       break;
332
333     case Kind.ContinueBreakNode:
334       compLoc = new CompositeLocation();
335       break;
336
337     }
338     return compLoc;
339   }
340
341   private CompositeLocation checkLocationFromReturnNode(MethodDescriptor md, SymbolTable nametable,
342       ReturnNode rn) {
343
344     ExpressionNode returnExp = rn.getReturnExpression();
345
346     CompositeLocation expLoc;
347     if (returnExp != null) {
348       expLoc = checkLocationFromExpressionNode(md, nametable, returnExp, new CompositeLocation());
349       // check if return value is equal or higher than RETRUNLOC of method
350       // declaration annotation
351       CompositeLocation returnLocAt = md2ReturnLoc.get(md);
352
353       if (CompositeLattice.isGreaterThan(returnLocAt, expLoc)) {
354         throw new Error(
355             "Return value location is not equal or higher than the declaraed return location at "
356                 + md.getClassDesc().getSourceFileName() + "::" + rn.getNumLine());
357       }
358     }
359
360     return new CompositeLocation();
361   }
362
363   private boolean hasOnlyLiteralValue(ExpressionNode en) {
364     if (en.kind() == Kind.LiteralNode) {
365       return true;
366     } else {
367       return false;
368     }
369   }
370
371   private CompositeLocation checkLocationFromLoopNode(MethodDescriptor md, SymbolTable nametable,
372       LoopNode ln) {
373
374     ClassDescriptor cd = md.getClassDesc();
375     if (ln.getType() == LoopNode.WHILELOOP || ln.getType() == LoopNode.DOWHILELOOP) {
376
377       CompositeLocation condLoc =
378           checkLocationFromExpressionNode(md, nametable, ln.getCondition(), new CompositeLocation());
379       addLocationType(ln.getCondition().getType(), (condLoc));
380
381       CompositeLocation bodyLoc = checkLocationFromBlockNode(md, nametable, ln.getBody());
382
383       if (!CompositeLattice.isGreaterThan(condLoc, bodyLoc)) {
384         // loop condition should be higher than loop body
385         throw new Error(
386             "The location of the while-condition statement is lower than the loop body at "
387                 + cd.getSourceFileName() + ":" + ln.getCondition().getNumLine());
388       }
389
390       return bodyLoc;
391
392     } else {
393       // check for loop case
394       BlockNode bn = ln.getInitializer();
395       bn.getVarTable().setParent(nametable);
396
397       // calculate glb location of condition and update statements
398       CompositeLocation condLoc =
399           checkLocationFromExpressionNode(md, bn.getVarTable(), ln.getCondition(),
400               new CompositeLocation());
401       addLocationType(ln.getCondition().getType(), condLoc);
402
403       CompositeLocation updateLoc =
404           checkLocationFromBlockNode(md, bn.getVarTable(), ln.getUpdate());
405
406       Set<CompositeLocation> glbInputSet = new HashSet<CompositeLocation>();
407       glbInputSet.add(condLoc);
408 //      glbInputSet.add(updateLoc);
409
410       CompositeLocation glbLocOfForLoopCond = CompositeLattice.calculateGLB(glbInputSet);
411
412       // check location of 'forloop' body
413       CompositeLocation blockLoc = checkLocationFromBlockNode(md, bn.getVarTable(), ln.getBody());
414
415       // compute glb of body including loop body and update statement
416       glbInputSet.clear();
417       
418       if (blockLoc == null) {
419         // when there is no statement in the loop body
420         
421         if(updateLoc==null){
422           // also there is no update statement in the loop body
423           return glbLocOfForLoopCond;
424         }
425         glbInputSet.add(updateLoc);
426         
427       }else{
428         glbInputSet.add(blockLoc);
429         glbInputSet.add(updateLoc);
430       }
431       
432       CompositeLocation loopBodyLoc = CompositeLattice.calculateGLB(glbInputSet);
433
434       if (!CompositeLattice.isGreaterThan(glbLocOfForLoopCond, loopBodyLoc)) {
435         throw new Error(
436             "The location of the for-condition statement is lower than the for-loop body at "
437                 + cd.getSourceFileName() + ":" + ln.getCondition().getNumLine());
438       }
439       return blockLoc;
440     }
441
442   }
443
444   private CompositeLocation checkLocationFromSubBlockNode(MethodDescriptor md,
445       SymbolTable nametable, SubBlockNode sbn) {
446     CompositeLocation compLoc = checkLocationFromBlockNode(md, nametable, sbn.getBlockNode());
447     return compLoc;
448   }
449
450   private CompositeLocation checkLocationFromIfStatementNode(MethodDescriptor md,
451       SymbolTable nametable, IfStatementNode isn) {
452
453     ClassDescriptor localCD = md.getClassDesc();
454     Set<CompositeLocation> glbInputSet = new HashSet<CompositeLocation>();
455
456     CompositeLocation condLoc =
457         checkLocationFromExpressionNode(md, nametable, isn.getCondition(), new CompositeLocation());
458
459     addLocationType(isn.getCondition().getType(), condLoc);
460     glbInputSet.add(condLoc);
461
462     CompositeLocation locTrueBlock = checkLocationFromBlockNode(md, nametable, isn.getTrueBlock());
463     if (locTrueBlock != null) {
464       glbInputSet.add(locTrueBlock);
465       // here, the location of conditional block should be higher than the
466       // location of true/false blocks
467       if (locTrueBlock != null && !CompositeLattice.isGreaterThan(condLoc, locTrueBlock)) {
468         // error
469         throw new Error(
470             "The location of the if-condition statement is lower than the conditional block at "
471                 + localCD.getSourceFileName() + ":" + isn.getCondition().getNumLine());
472       }
473     }
474
475     if (isn.getFalseBlock() != null) {
476       CompositeLocation locFalseBlock =
477           checkLocationFromBlockNode(md, nametable, isn.getFalseBlock());
478
479       if (locFalseBlock != null) {
480         glbInputSet.add(locFalseBlock);
481
482         if (!CompositeLattice.isGreaterThan(condLoc, locFalseBlock)) {
483           // error
484           throw new Error(
485               "The location of the if-condition statement is lower than the conditional block at "
486                   + localCD.getSourceFileName() + ":" + isn.getCondition().getNumLine());
487         }
488       }
489
490     }
491
492     // return GLB location of condition, true, and false block
493     CompositeLocation glbLoc = CompositeLattice.calculateGLB(glbInputSet);
494
495     return glbLoc;
496   }
497
498   private CompositeLocation checkLocationFromDeclarationNode(MethodDescriptor md,
499       SymbolTable nametable, DeclarationNode dn) {
500
501     VarDescriptor vd = dn.getVarDescriptor();
502
503     CompositeLocation destLoc = d2loc.get(vd);
504
505     if (dn.getExpression() != null) {
506       CompositeLocation expressionLoc =
507           checkLocationFromExpressionNode(md, nametable, dn.getExpression(),
508               new CompositeLocation());
509       // addTypeLocation(dn.getExpression().getType(), expressionLoc);
510
511       if (expressionLoc != null) {
512         // checking location order
513         if (!CompositeLattice.isGreaterThan(expressionLoc, destLoc)) {
514           throw new Error("The value flow from " + expressionLoc + " to " + destLoc
515               + " does not respect location hierarchy on the assignment " + dn.printNode(0)
516               + " at " + md.getClassDesc().getSourceFileName() + "::" + dn.getNumLine());
517         }
518       }
519       return expressionLoc;
520
521     } else {
522
523       return new CompositeLocation();
524
525     }
526
527   }
528
529   private void checkDeclarationInSubBlockNode(MethodDescriptor md, SymbolTable nametable,
530       SubBlockNode sbn) {
531     checkDeclarationInBlockNode(md, nametable.getParent(), sbn.getBlockNode());
532   }
533
534   private CompositeLocation checkLocationFromBlockExpressionNode(MethodDescriptor md,
535       SymbolTable nametable, BlockExpressionNode ben) {
536     CompositeLocation compLoc =
537         checkLocationFromExpressionNode(md, nametable, ben.getExpression(), null);
538     // addTypeLocation(ben.getExpression().getType(), compLoc);
539     return compLoc;
540   }
541
542   private CompositeLocation checkLocationFromExpressionNode(MethodDescriptor md,
543       SymbolTable nametable, ExpressionNode en, CompositeLocation loc) {
544
545     CompositeLocation compLoc = null;
546     switch (en.kind()) {
547
548     case Kind.AssignmentNode:
549       compLoc = checkLocationFromAssignmentNode(md, nametable, (AssignmentNode) en, loc);
550       break;
551
552     case Kind.FieldAccessNode:
553       compLoc = checkLocationFromFieldAccessNode(md, nametable, (FieldAccessNode) en, loc);
554       break;
555
556     case Kind.NameNode:
557       compLoc = checkLocationFromNameNode(md, nametable, (NameNode) en, loc);
558       break;
559
560     case Kind.OpNode:
561       compLoc = checkLocationFromOpNode(md, nametable, (OpNode) en);
562       break;
563
564     case Kind.CreateObjectNode:
565       compLoc = checkLocationFromCreateObjectNode(md, nametable, (CreateObjectNode) en);
566       break;
567
568     case Kind.ArrayAccessNode:
569       compLoc = checkLocationFromArrayAccessNode(md, nametable, (ArrayAccessNode) en);
570       break;
571
572     case Kind.LiteralNode:
573       compLoc = checkLocationFromLiteralNode(md, nametable, (LiteralNode) en, loc);
574       break;
575
576     case Kind.MethodInvokeNode:
577       compLoc = checkLocationFromMethodInvokeNode(md, nametable, (MethodInvokeNode) en, loc);
578       break;
579
580     case Kind.TertiaryNode:
581       compLoc = checkLocationFromTertiaryNode(md, nametable, (TertiaryNode) en);
582       break;
583
584     case Kind.CastNode:
585       compLoc = checkLocationFromCastNode(md, nametable, (CastNode) en);
586       break;
587
588     // case Kind.InstanceOfNode:
589     // checkInstanceOfNode(md, nametable, (InstanceOfNode) en, td);
590     // return null;
591
592     // case Kind.ArrayInitializerNode:
593     // checkArrayInitializerNode(md, nametable, (ArrayInitializerNode) en,
594     // td);
595     // return null;
596
597     // case Kind.ClassTypeNode:
598     // checkClassTypeNode(md, nametable, (ClassTypeNode) en, td);
599     // return null;
600
601     // case Kind.OffsetNode:
602     // checkOffsetNode(md, nametable, (OffsetNode)en, td);
603     // return null;
604
605     default:
606       return null;
607
608     }
609     // addTypeLocation(en.getType(), compLoc);
610     return compLoc;
611
612   }
613
614   private CompositeLocation checkLocationFromCastNode(MethodDescriptor md, SymbolTable nametable,
615       CastNode cn) {
616
617     ExpressionNode en = cn.getExpression();
618     return checkLocationFromExpressionNode(md, nametable, en, new CompositeLocation());
619
620   }
621
622   private CompositeLocation checkLocationFromTertiaryNode(MethodDescriptor md,
623       SymbolTable nametable, TertiaryNode tn) {
624     ClassDescriptor cd = md.getClassDesc();
625
626     CompositeLocation condLoc =
627         checkLocationFromExpressionNode(md, nametable, tn.getCond(), new CompositeLocation());
628     addLocationType(tn.getCond().getType(), condLoc);
629     CompositeLocation trueLoc =
630         checkLocationFromExpressionNode(md, nametable, tn.getTrueExpr(), new CompositeLocation());
631     addLocationType(tn.getTrueExpr().getType(), trueLoc);
632     CompositeLocation falseLoc =
633         checkLocationFromExpressionNode(md, nametable, tn.getFalseExpr(), new CompositeLocation());
634     addLocationType(tn.getFalseExpr().getType(), falseLoc);
635
636     // check if condLoc is higher than trueLoc & falseLoc
637     if (!CompositeLattice.isGreaterThan(condLoc, trueLoc)) {
638       throw new Error(
639           "The location of the condition expression is lower than the true expression at "
640               + cd.getSourceFileName() + ":" + tn.getCond().getNumLine());
641     }
642
643     if (!CompositeLattice.isGreaterThan(condLoc, falseLoc)) {
644       throw new Error(
645           "The location of the condition expression is lower than the true expression at "
646               + cd.getSourceFileName() + ":" + tn.getCond().getNumLine());
647     }
648
649     // then, return glb of trueLoc & falseLoc
650     Set<CompositeLocation> glbInputSet = new HashSet<CompositeLocation>();
651     glbInputSet.add(trueLoc);
652     glbInputSet.add(falseLoc);
653
654     return CompositeLattice.calculateGLB(glbInputSet);
655   }
656
657   private CompositeLocation checkLocationFromMethodInvokeNode(MethodDescriptor md,
658       SymbolTable nametable, MethodInvokeNode min, CompositeLocation loc) {
659
660     checkCalleeConstraints(md, nametable, min);
661
662     CompositeLocation baseLocation = null;
663     if (min.getExpression() != null) {
664       baseLocation =
665           checkLocationFromExpressionNode(md, nametable, min.getExpression(),
666               new CompositeLocation());
667     } else {
668       String thisLocId = ssjava.getMethodLattice(md).getThisLoc();
669       baseLocation = new CompositeLocation(new Location(md, thisLocId));
670     }
671
672     if (!min.getMethod().getReturnType().isVoid()) {
673       // If method has a return value, compute the highest possible return
674       // location in the caller's perspective
675       CompositeLocation ceilingLoc =
676           computeCeilingLocationForCaller(md, nametable, min, baseLocation);
677       return ceilingLoc;
678     }
679
680     return new CompositeLocation();
681
682   }
683
684   private CompositeLocation computeCeilingLocationForCaller(MethodDescriptor md,
685       SymbolTable nametable, MethodInvokeNode min, CompositeLocation baseLocation) {
686     List<CompositeLocation> argList = new ArrayList<CompositeLocation>();
687
688     // by default, method has a THIS parameter
689     argList.add(baseLocation);
690
691     for (int i = 0; i < min.numArgs(); i++) {
692       ExpressionNode en = min.getArg(i);
693       CompositeLocation callerArg =
694           checkLocationFromExpressionNode(md, nametable, en, new CompositeLocation());
695       argList.add(callerArg);
696     }
697
698     return md2ReturnLocGen.get(min.getMethod()).computeReturnLocation(argList);
699
700   }
701
702   private void checkCalleeConstraints(MethodDescriptor md, SymbolTable nametable,
703       MethodInvokeNode min) {
704
705     if (min.numArgs() > 1) {
706       // caller needs to guarantee that it passes arguments in regarding to
707       // callee's hierarchy
708       for (int i = 0; i < min.numArgs(); i++) {
709         ExpressionNode en = min.getArg(i);
710         CompositeLocation callerArg1 =
711             checkLocationFromExpressionNode(md, nametable, en, new CompositeLocation());
712
713         ClassDescriptor calleecd = min.getMethod().getClassDesc();
714         VarDescriptor calleevd = (VarDescriptor) min.getMethod().getParameter(i);
715         CompositeLocation calleeLoc1 = d2loc.get(calleevd);
716
717         if (!callerArg1.get(0).isTop()) {
718           // here, check if ordering relations among caller's args respect
719           // ordering relations in-between callee's args
720           for (int currentIdx = 0; currentIdx < min.numArgs(); currentIdx++) {
721             if (currentIdx != i) { // skip itself
722               ExpressionNode argExp = min.getArg(currentIdx);
723
724               CompositeLocation callerArg2 =
725                   checkLocationFromExpressionNode(md, nametable, argExp, new CompositeLocation());
726
727               VarDescriptor calleevd2 = (VarDescriptor) min.getMethod().getParameter(currentIdx);
728               CompositeLocation calleeLoc2 = d2loc.get(calleevd2);
729
730               int callerResult = CompositeLattice.compare(callerArg1, callerArg2);
731               int calleeResult = CompositeLattice.compare(calleeLoc1, calleeLoc2);
732               if (calleeResult == ComparisonResult.GREATER
733                   && callerResult != ComparisonResult.GREATER) {
734                 // If calleeLoc1 is higher than calleeLoc2
735                 // then, caller should have same ordering relation in-bet
736                 // callerLoc1 & callerLoc2
737
738                 throw new Error("Caller doesn't respect ordering relations among method arguments:"
739                     + md.getClassDesc().getSourceFileName() + ":" + min.getNumLine());
740               }
741
742             }
743           }
744         }
745
746       }
747
748     }
749
750   }
751
752   private CompositeLocation checkLocationFromArrayAccessNode(MethodDescriptor md,
753       SymbolTable nametable, ArrayAccessNode aan) {
754
755     // return glb location of array itself and index
756
757     ClassDescriptor cd = md.getClassDesc();
758
759     Set<CompositeLocation> glbInputSet = new HashSet<CompositeLocation>();
760
761     CompositeLocation arrayLoc =
762         checkLocationFromExpressionNode(md, nametable, aan.getExpression(), new CompositeLocation());
763     // addTypeLocation(aan.getExpression().getType(), arrayLoc);
764     glbInputSet.add(arrayLoc);
765     CompositeLocation indexLoc =
766         checkLocationFromExpressionNode(md, nametable, aan.getIndex(), new CompositeLocation());
767     glbInputSet.add(indexLoc);
768     // addTypeLocation(aan.getIndex().getType(), indexLoc);
769
770     CompositeLocation glbLoc = CompositeLattice.calculateGLB(glbInputSet);
771     return glbLoc;
772   }
773
774   private CompositeLocation checkLocationFromCreateObjectNode(MethodDescriptor md,
775       SymbolTable nametable, CreateObjectNode con) {
776
777     ClassDescriptor cd = md.getClassDesc();
778
779     // check arguments
780     Set<CompositeLocation> glbInputSet = new HashSet<CompositeLocation>();
781     for (int i = 0; i < con.numArgs(); i++) {
782       ExpressionNode en = con.getArg(i);
783       CompositeLocation argLoc =
784           checkLocationFromExpressionNode(md, nametable, en, new CompositeLocation());
785       glbInputSet.add(argLoc);
786       addLocationType(en.getType(), argLoc);
787     }
788
789     // check array initializers
790     // if ((con.getArrayInitializer() != null)) {
791     // checkLocationFromArrayInitializerNode(md, nametable,
792     // con.getArrayInitializer());
793     // }
794
795     if (glbInputSet.size() > 0) {
796       return CompositeLattice.calculateGLB(glbInputSet);
797     }
798
799     CompositeLocation compLoc = new CompositeLocation();
800     compLoc.addLocation(Location.createTopLocation(md));
801     return compLoc;
802
803   }
804
805   private CompositeLocation checkLocationFromOpNode(MethodDescriptor md, SymbolTable nametable,
806       OpNode on) {
807
808     ClassDescriptor cd = md.getClassDesc();
809     CompositeLocation leftLoc = new CompositeLocation();
810     leftLoc = checkLocationFromExpressionNode(md, nametable, on.getLeft(), leftLoc);
811     // addTypeLocation(on.getLeft().getType(), leftLoc);
812
813     CompositeLocation rightLoc = new CompositeLocation();
814     if (on.getRight() != null) {
815       rightLoc = checkLocationFromExpressionNode(md, nametable, on.getRight(), rightLoc);
816       // addTypeLocation(on.getRight().getType(), rightLoc);
817     }
818
819     // System.out.println("checking op node=" + on.printNode(0));
820     // System.out.println("left loc=" + leftLoc + " from " +
821     // on.getLeft().getClass());
822     // System.out.println("right loc=" + rightLoc + " from " +
823     // on.getRight().getClass());
824
825     Operation op = on.getOp();
826
827     switch (op.getOp()) {
828
829     case Operation.UNARYPLUS:
830     case Operation.UNARYMINUS:
831     case Operation.LOGIC_NOT:
832       // single operand
833       return leftLoc;
834
835     case Operation.LOGIC_OR:
836     case Operation.LOGIC_AND:
837     case Operation.COMP:
838     case Operation.BIT_OR:
839     case Operation.BIT_XOR:
840     case Operation.BIT_AND:
841     case Operation.ISAVAILABLE:
842     case Operation.EQUAL:
843     case Operation.NOTEQUAL:
844     case Operation.LT:
845     case Operation.GT:
846     case Operation.LTE:
847     case Operation.GTE:
848     case Operation.ADD:
849     case Operation.SUB:
850     case Operation.MULT:
851     case Operation.DIV:
852     case Operation.MOD:
853     case Operation.LEFTSHIFT:
854     case Operation.RIGHTSHIFT:
855     case Operation.URIGHTSHIFT:
856
857       Set<CompositeLocation> inputSet = new HashSet<CompositeLocation>();
858       inputSet.add(leftLoc);
859       inputSet.add(rightLoc);
860       CompositeLocation glbCompLoc = CompositeLattice.calculateGLB(inputSet);
861       return glbCompLoc;
862
863     default:
864       throw new Error(op.toString());
865     }
866
867   }
868
869   private CompositeLocation checkLocationFromLiteralNode(MethodDescriptor md,
870       SymbolTable nametable, LiteralNode en, CompositeLocation loc) {
871
872     // literal value has the top location so that value can be flowed into any
873     // location
874     Location literalLoc = Location.createTopLocation(md);
875     loc.addLocation(literalLoc);
876     return loc;
877
878   }
879
880   private CompositeLocation checkLocationFromNameNode(MethodDescriptor md, SymbolTable nametable,
881       NameNode nn, CompositeLocation loc) {
882
883     NameDescriptor nd = nn.getName();
884     if (nd.getBase() != null) {
885
886       loc = checkLocationFromExpressionNode(md, nametable, nn.getExpression(), loc);
887       // addTypeLocation(nn.getExpression().getType(), loc);
888     } else {
889       String varname = nd.toString();
890
891       if (varname.equals("this")) {
892         // 'this' itself!
893         MethodLattice<String> methodLattice = ssjava.getMethodLattice(md);
894         String thisLocId = methodLattice.getThisLoc();
895         if (thisLocId == null) {
896           throw new Error("The location for 'this' is not defined at "
897               + md.getClassDesc().getSourceFileName() + "::" + nn.getNumLine());
898         }
899         Location locElement = new Location(md, thisLocId);
900         loc.addLocation(locElement);
901         return loc;
902       }
903       Descriptor d = (Descriptor) nametable.get(varname);
904
905       // CompositeLocation localLoc = null;
906       if (d instanceof VarDescriptor) {
907         VarDescriptor vd = (VarDescriptor) d;
908         // localLoc = d2loc.get(vd);
909         // the type of var descriptor has a composite location!
910         loc = ((CompositeLocation) vd.getType().getExtension()).clone();
911       } else if (d instanceof FieldDescriptor) {
912         // the type of field descriptor has a location!
913         FieldDescriptor fd = (FieldDescriptor) d;
914
915         if (fd.isStatic()) {
916           if (fd.isFinal()) {
917             // if it is 'static final', the location has TOP since no one can
918             // change its value
919             loc.addLocation(Location.createTopLocation(md));
920           } else {
921             // if 'static', the location has pre-assigned global loc
922             MethodLattice<String> localLattice = ssjava.getMethodLattice(md);
923             String globalLocId = localLattice.getGlobalLoc();
924             if (globalLocId == null) {
925               throw new Error("Global location element is not defined in the method " + md);
926             }
927             Location globalLoc = new Location(md, globalLocId);
928
929             loc.addLocation(globalLoc);
930           }
931         } else {
932           // the location of field access starts from this, followed by field
933           // location
934           MethodLattice<String> localLattice = ssjava.getMethodLattice(md);
935           Location thisLoc = new Location(md, localLattice.getThisLoc());
936           loc.addLocation(thisLoc);
937         }
938
939         Location fieldLoc = (Location) fd.getType().getExtension();
940         loc.addLocation(fieldLoc);
941       }
942     }
943     return loc;
944   }
945
946   private CompositeLocation checkLocationFromFieldAccessNode(MethodDescriptor md,
947       SymbolTable nametable, FieldAccessNode fan, CompositeLocation loc) {
948
949     ExpressionNode left = fan.getExpression();
950     loc = checkLocationFromExpressionNode(md, nametable, left, loc);
951
952     if (!left.getType().isPrimitive()) {
953       FieldDescriptor fd = fan.getField();
954       Location fieldLoc = (Location) fd.getType().getExtension();
955       loc.addLocation(fieldLoc);
956     }
957
958     return loc;
959   }
960
961   private CompositeLocation checkLocationFromAssignmentNode(MethodDescriptor md,
962       SymbolTable nametable, AssignmentNode an, CompositeLocation loc) {
963
964     ClassDescriptor cd = md.getClassDesc();
965
966     boolean postinc = true;
967     if (an.getOperation().getBaseOp() == null
968         || (an.getOperation().getBaseOp().getOp() != Operation.POSTINC && an.getOperation()
969             .getBaseOp().getOp() != Operation.POSTDEC))
970       postinc = false;
971
972     CompositeLocation destLocation =
973         checkLocationFromExpressionNode(md, nametable, an.getDest(), new CompositeLocation());
974
975     CompositeLocation srcLocation = new CompositeLocation();
976
977     if (!postinc) {
978       if (hasOnlyLiteralValue(an.getSrc())) {
979         // if source is literal value, src location is TOP. so do not need to
980         // compare!
981         return destLocation;
982       }
983       srcLocation = new CompositeLocation();
984       srcLocation = checkLocationFromExpressionNode(md, nametable, an.getSrc(), srcLocation);
985       // System.out.println(" an= " + an.printNode(0) + " an.getSrc()=" +
986       // an.getSrc().getClass()
987       // + " at " + cd.getSourceFileName() + "::" + an.getNumLine());
988       // System.out.println("srcLocation=" + srcLocation);
989       // System.out.println("dstLocation=" + destLocation);
990       if (!CompositeLattice.isGreaterThan(srcLocation, destLocation)) {
991         throw new Error("The value flow from " + srcLocation + " to " + destLocation
992             + " does not respect location hierarchy on the assignment " + an.printNode(0) + " at "
993             + cd.getSourceFileName() + "::" + an.getNumLine());
994       }
995     } else {
996       destLocation =
997           srcLocation = checkLocationFromExpressionNode(md, nametable, an.getDest(), srcLocation);
998
999       if (!CompositeLattice.isGreaterThan(srcLocation, destLocation)) {
1000         throw new Error("Location " + destLocation
1001             + " is not allowed to have the value flow that moves within the same location at "
1002             + cd.getSourceFileName() + "::" + an.getNumLine());
1003       }
1004
1005     }
1006
1007     return destLocation;
1008   }
1009
1010   private void assignLocationOfVarDescriptor(VarDescriptor vd, MethodDescriptor md,
1011       SymbolTable nametable, TreeNode n) {
1012
1013     ClassDescriptor cd = md.getClassDesc();
1014     Vector<AnnotationDescriptor> annotationVec = vd.getType().getAnnotationMarkers();
1015
1016     // currently enforce every variable to have corresponding location
1017     if (annotationVec.size() == 0) {
1018       throw new Error("Location is not assigned to variable " + vd.getSymbol() + " in the method "
1019           + md.getSymbol() + " of the class " + cd.getSymbol());
1020     }
1021
1022     if (annotationVec.size() > 1) { // variable can have at most one location
1023       throw new Error(vd.getSymbol() + " has more than one location.");
1024     }
1025
1026     AnnotationDescriptor ad = annotationVec.elementAt(0);
1027
1028     if (ad.getType() == AnnotationDescriptor.SINGLE_ANNOTATION) {
1029
1030       if (ad.getMarker().equals(SSJavaAnalysis.LOC)) {
1031         String locDec = ad.getValue(); // check if location is defined
1032
1033         if (locDec.startsWith(SSJavaAnalysis.DELTA)) {
1034           DeltaLocation deltaLoc = parseDeltaDeclaration(md, n, locDec);
1035           d2loc.put(vd, deltaLoc);
1036           addLocationType(vd.getType(), deltaLoc);
1037         } else {
1038           CompositeLocation compLoc = parseLocationDeclaration(md, n, locDec);
1039           d2loc.put(vd, compLoc);
1040           addLocationType(vd.getType(), compLoc);
1041         }
1042
1043       }
1044     }
1045
1046   }
1047
1048   private DeltaLocation parseDeltaDeclaration(MethodDescriptor md, TreeNode n, String locDec) {
1049
1050     int deltaCount = 0;
1051     int dIdx = locDec.indexOf(SSJavaAnalysis.DELTA);
1052     while (dIdx >= 0) {
1053       deltaCount++;
1054       int beginIdx = dIdx + 6;
1055       locDec = locDec.substring(beginIdx, locDec.length() - 1);
1056       dIdx = locDec.indexOf(SSJavaAnalysis.DELTA);
1057     }
1058
1059     CompositeLocation compLoc = parseLocationDeclaration(md, n, locDec);
1060     DeltaLocation deltaLoc = new DeltaLocation(compLoc, deltaCount);
1061
1062     return deltaLoc;
1063   }
1064
1065   private Location parseFieldLocDeclaraton(String decl) {
1066
1067     int idx = decl.indexOf(".");
1068     String className = decl.substring(0, idx);
1069     String fieldName = decl.substring(idx + 1);
1070
1071     Descriptor d = state.getClassSymbolTable().get(className);
1072
1073     assert (d instanceof ClassDescriptor);
1074     SSJavaLattice<String> lattice = ssjava.getClassLattice((ClassDescriptor) d);
1075     if (!lattice.containsKey(fieldName)) {
1076       throw new Error("The location " + fieldName + " is not defined in the field lattice of '"
1077           + className + "'.");
1078     }
1079
1080     return new Location(d, fieldName);
1081   }
1082
1083   private CompositeLocation parseLocationDeclaration(MethodDescriptor md, TreeNode n, String locDec) {
1084
1085     CompositeLocation compLoc = new CompositeLocation();
1086
1087     StringTokenizer tokenizer = new StringTokenizer(locDec, ",");
1088     List<String> locIdList = new ArrayList<String>();
1089     while (tokenizer.hasMoreTokens()) {
1090       String locId = tokenizer.nextToken();
1091       locIdList.add(locId);
1092     }
1093
1094     // at least,one location element needs to be here!
1095     assert (locIdList.size() > 0);
1096
1097     // assume that loc with idx 0 comes from the local lattice
1098     // loc with idx 1 comes from the field lattice
1099
1100     String localLocId = locIdList.get(0);
1101     SSJavaLattice<String> localLattice = CompositeLattice.getLatticeByDescriptor(md);
1102     Location localLoc = new Location(md, localLocId);
1103     if (localLattice == null || (!localLattice.containsKey(localLocId))) {
1104       throw new Error("Location " + localLocId
1105           + " is not defined in the local variable lattice at "
1106           + md.getClassDesc().getSourceFileName() + "::" + (n != null ? n.getNumLine() : "") + ".");
1107     }
1108     compLoc.addLocation(localLoc);
1109
1110     for (int i = 1; i < locIdList.size(); i++) {
1111       String locName = locIdList.get(i);
1112
1113       Location fieldLoc = parseFieldLocDeclaraton(locName);
1114       // ClassDescriptor cd = fieldLocName2cd.get(locName);
1115       // SSJavaLattice<String> fieldLattice =
1116       // CompositeLattice.getLatticeByDescriptor(cd);
1117       //
1118       // if (fieldLattice == null || (!fieldLattice.containsKey(locName))) {
1119       // throw new Error("Location " + locName +
1120       // " is not defined in the field lattice at "
1121       // + cd.getSourceFileName() + ".");
1122       // }
1123       // Location fieldLoc = new Location(cd, locName);
1124       compLoc.addLocation(fieldLoc);
1125     }
1126
1127     return compLoc;
1128
1129   }
1130
1131   private void checkDeclarationNode(MethodDescriptor md, SymbolTable nametable, DeclarationNode dn) {
1132     VarDescriptor vd = dn.getVarDescriptor();
1133     assignLocationOfVarDescriptor(vd, md, nametable, dn);
1134   }
1135
1136   private void checkClass(ClassDescriptor cd) {
1137     // Check to see that methods respects ss property
1138     for (Iterator method_it = cd.getMethods(); method_it.hasNext();) {
1139       MethodDescriptor md = (MethodDescriptor) method_it.next();
1140       checkMethodDeclaration(cd, md);
1141     }
1142   }
1143
1144   private void checkDeclarationInClass(ClassDescriptor cd) {
1145     // Check to see that fields are okay
1146     for (Iterator field_it = cd.getFields(); field_it.hasNext();) {
1147       FieldDescriptor fd = (FieldDescriptor) field_it.next();
1148       checkFieldDeclaration(cd, fd);
1149     }
1150   }
1151
1152   private void checkMethodDeclaration(ClassDescriptor cd, MethodDescriptor md) {
1153     // TODO
1154   }
1155
1156   private void checkFieldDeclaration(ClassDescriptor cd, FieldDescriptor fd) {
1157
1158     Vector<AnnotationDescriptor> annotationVec = fd.getType().getAnnotationMarkers();
1159
1160     // currently enforce every field to have corresponding location
1161     if (annotationVec.size() == 0) {
1162       throw new Error("Location is not assigned to the field '" + fd.getSymbol()
1163           + "' of the class " + cd.getSymbol() + " at " + cd.getSourceFileName());
1164     }
1165
1166     if (annotationVec.size() > 1) {
1167       // variable can have at most one location
1168       throw new Error("Field " + fd.getSymbol() + " of class " + cd
1169           + " has more than one location.");
1170     }
1171
1172     AnnotationDescriptor ad = annotationVec.elementAt(0);
1173
1174     if (ad.getType() == AnnotationDescriptor.SINGLE_ANNOTATION) {
1175
1176       if (ad.getMarker().equals(SSJavaAnalysis.LOC)) {
1177         String locationID = ad.getValue();
1178         // check if location is defined
1179         SSJavaLattice<String> lattice = ssjava.getClassLattice(cd);
1180         if (lattice == null || (!lattice.containsKey(locationID))) {
1181           throw new Error("Location " + locationID
1182               + " is not defined in the field lattice of class " + cd.getSymbol() + " at"
1183               + cd.getSourceFileName() + ".");
1184         }
1185         Location loc = new Location(cd, locationID);
1186         addLocationType(fd.getType(), loc);
1187
1188       }
1189     }
1190
1191   }
1192
1193   private void addLocationType(TypeDescriptor type, CompositeLocation loc) {
1194     if (type != null) {
1195       type.setExtension(loc);
1196     }
1197   }
1198
1199   private void addLocationType(TypeDescriptor type, Location loc) {
1200     if (type != null) {
1201       type.setExtension(loc);
1202     }
1203   }
1204
1205   static class CompositeLattice {
1206
1207     public static boolean isGreaterThan(CompositeLocation loc1, CompositeLocation loc2) {
1208
1209       int baseCompareResult = compareBaseLocationSet(loc1, loc2, true);
1210       if (baseCompareResult == ComparisonResult.EQUAL) {
1211         if (compareDelta(loc1, loc2) == ComparisonResult.GREATER) {
1212           return true;
1213         } else {
1214           return false;
1215         }
1216       } else if (baseCompareResult == ComparisonResult.GREATER) {
1217         return true;
1218       } else {
1219         return false;
1220       }
1221
1222     }
1223
1224     public static int compare(CompositeLocation loc1, CompositeLocation loc2) {
1225
1226       // System.out.println("compare=" + loc1 + " " + loc2);
1227       int baseCompareResult = compareBaseLocationSet(loc1, loc2, false);
1228
1229       if (baseCompareResult == ComparisonResult.EQUAL) {
1230         return compareDelta(loc1, loc2);
1231       } else {
1232         return baseCompareResult;
1233       }
1234
1235     }
1236
1237     private static int compareDelta(CompositeLocation dLoc1, CompositeLocation dLoc2) {
1238
1239       int deltaCount1 = 0;
1240       int deltaCount2 = 0;
1241       if (dLoc1 instanceof DeltaLocation) {
1242         deltaCount1 = ((DeltaLocation) dLoc1).getNumDelta();
1243       }
1244
1245       if (dLoc2 instanceof DeltaLocation) {
1246         deltaCount2 = ((DeltaLocation) dLoc2).getNumDelta();
1247       }
1248       if (deltaCount1 < deltaCount2) {
1249         return ComparisonResult.GREATER;
1250       } else if (deltaCount1 == deltaCount2) {
1251         return ComparisonResult.EQUAL;
1252       } else {
1253         return ComparisonResult.LESS;
1254       }
1255
1256     }
1257
1258     private static int compareBaseLocationSet(CompositeLocation compLoc1,
1259         CompositeLocation compLoc2, boolean awareSharedLoc) {
1260
1261       // if compLoc1 is greater than compLoc2, return true
1262       // else return false;
1263
1264       // compare one by one in according to the order of the tuple
1265       int numOfTie = 0;
1266       for (int i = 0; i < compLoc1.getSize(); i++) {
1267         Location loc1 = compLoc1.get(i);
1268         if (i >= compLoc2.getSize()) {
1269           throw new Error("Failed to compare two locations of " + compLoc1 + " and " + compLoc2
1270               + " because they are not comparable.");
1271         }
1272         Location loc2 = compLoc2.get(i);
1273
1274         if (!loc1.getDescriptor().equals(loc2.getDescriptor())) {
1275           throw new Error("Failed to compare two locations of " + compLoc1 + " and " + compLoc2
1276               + " because they are not comparable.");
1277         }
1278
1279         Descriptor d1 = loc1.getDescriptor();
1280         Descriptor d2 = loc2.getDescriptor();
1281
1282         SSJavaLattice<String> lattice1 = getLatticeByDescriptor(d1);
1283         SSJavaLattice<String> lattice2 = getLatticeByDescriptor(d2);
1284
1285         // check if the spin location is appeared only at the end of the
1286         // composite location
1287         if (lattice1.getSpinLocSet().contains(loc1.getLocIdentifier())) {
1288           if (i != (compLoc1.getSize() - 1)) {
1289             throw new Error("The spin location " + loc1.getLocIdentifier()
1290                 + " cannot be appeared in the middle of composite location.");
1291           }
1292         }
1293
1294         if (lattice2.getSpinLocSet().contains(loc2.getLocIdentifier())) {
1295           if (i != (compLoc2.getSize() - 1)) {
1296             throw new Error("The spin location " + loc2.getLocIdentifier()
1297                 + " cannot be appeared in the middle of composite location.");
1298           }
1299         }
1300
1301         if (!lattice1.equals(lattice2)) {
1302           throw new Error("Failed to compare two locations of " + compLoc1 + " and " + compLoc2
1303               + " because they are not comparable.");
1304         }
1305
1306         if (loc1.getLocIdentifier().equals(loc2.getLocIdentifier())) {
1307           numOfTie++;
1308           // check if the current location is the spinning location
1309           // note that the spinning location only can be appeared in the last
1310           // part of the composite location
1311           if (awareSharedLoc && numOfTie == compLoc1.getSize()
1312               && lattice1.getSpinLocSet().contains(loc1.getLocIdentifier())) {
1313             return ComparisonResult.GREATER;
1314           }
1315           continue;
1316         } else if (lattice1.isGreaterThan(loc1.getLocIdentifier(), loc2.getLocIdentifier())) {
1317           return ComparisonResult.GREATER;
1318         } else {
1319           return ComparisonResult.LESS;
1320         }
1321
1322       }
1323
1324       if (numOfTie == compLoc1.getSize()) {
1325
1326         if (numOfTie != compLoc2.getSize()) {
1327           throw new Error("Failed to compare two locations of " + compLoc1 + " and " + compLoc2
1328               + " because they are not comparable.");
1329         }
1330
1331         return ComparisonResult.EQUAL;
1332       }
1333
1334       return ComparisonResult.LESS;
1335
1336     }
1337
1338     public static CompositeLocation calculateGLB(Set<CompositeLocation> inputSet) {
1339
1340       // System.out.println("Calculating GLB=" + inputSet);
1341       CompositeLocation glbCompLoc = new CompositeLocation();
1342
1343       // calculate GLB of the first(priority) element
1344       Set<String> priorityLocIdentifierSet = new HashSet<String>();
1345       Descriptor priorityDescriptor = null;
1346
1347       Hashtable<String, Set<CompositeLocation>> locId2CompLocSet =
1348           new Hashtable<String, Set<CompositeLocation>>();
1349       // mapping from the priority loc ID to its full representation by the
1350       // composite location
1351
1352       int maxTupleSize = 0;
1353       CompositeLocation maxCompLoc = null;
1354
1355       for (Iterator iterator = inputSet.iterator(); iterator.hasNext();) {
1356         CompositeLocation compLoc = (CompositeLocation) iterator.next();
1357         if (compLoc.getSize() > maxTupleSize) {
1358           maxTupleSize = compLoc.getSize();
1359           maxCompLoc = compLoc;
1360         }
1361         Location priorityLoc = compLoc.get(0);
1362         String priorityLocId = priorityLoc.getLocIdentifier();
1363         priorityLocIdentifierSet.add(priorityLocId);
1364
1365         if (locId2CompLocSet.containsKey(priorityLocId)) {
1366           locId2CompLocSet.get(priorityLocId).add(compLoc);
1367         } else {
1368           Set<CompositeLocation> newSet = new HashSet<CompositeLocation>();
1369           newSet.add(compLoc);
1370           locId2CompLocSet.put(priorityLocId, newSet);
1371         }
1372
1373         // check if priority location are coming from the same lattice
1374         if (priorityDescriptor == null) {
1375           priorityDescriptor = priorityLoc.getDescriptor();
1376         } else if (!priorityDescriptor.equals(priorityLoc.getDescriptor())) {
1377           throw new Error("Failed to calculate GLB of " + inputSet
1378               + " because they are from different lattices.");
1379         }
1380       }
1381
1382       SSJavaLattice<String> locOrder = getLatticeByDescriptor(priorityDescriptor);
1383       String glbOfPriorityLoc = locOrder.getGLB(priorityLocIdentifierSet);
1384
1385       glbCompLoc.addLocation(new Location(priorityDescriptor, glbOfPriorityLoc));
1386       Set<CompositeLocation> compSet = locId2CompLocSet.get(glbOfPriorityLoc);
1387
1388       // here find out composite location that has a maximum length tuple
1389       // if we have three input set: [A], [A,B], [A,B,C]
1390       // maximum length tuple will be [A,B,C]
1391       int max = 0;
1392       CompositeLocation maxFromCompSet = null;
1393       for (Iterator iterator = compSet.iterator(); iterator.hasNext();) {
1394         CompositeLocation c = (CompositeLocation) iterator.next();
1395         if (c.getSize() > max) {
1396           max = c.getSize();
1397           maxFromCompSet = c;
1398         }
1399       }
1400
1401       if (compSet == null) {
1402         // when GLB(x1,x2)!=x1 and !=x2 : GLB case 4
1403         // mean that the result is already lower than <x1,y1> and <x2,y2>
1404         // assign TOP to the rest of the location elements
1405
1406         // in this case, do not take care about delta
1407         // CompositeLocation inputComp = inputSet.iterator().next();
1408         CompositeLocation inputComp = maxCompLoc;
1409         for (int i = 1; i < inputComp.getSize(); i++) {
1410           glbCompLoc.addLocation(Location.createTopLocation(inputComp.get(i).getDescriptor()));
1411         }
1412       } else {
1413         if (compSet.size() == 1) {
1414
1415           // if GLB(x1,x2)==x1 or x2 : GLB case 2,3
1416           CompositeLocation comp = compSet.iterator().next();
1417           for (int i = 1; i < comp.getSize(); i++) {
1418             glbCompLoc.addLocation(comp.get(i));
1419           }
1420
1421           // if input location corresponding to glb is a delta, need to apply
1422           // delta to glb result
1423           if (comp instanceof DeltaLocation) {
1424             glbCompLoc = new DeltaLocation(glbCompLoc, 1);
1425           }
1426
1427         } else {
1428           // when GLB(x1,x2)==x1 and x2 : GLB case 1
1429           // if more than one location shares the same priority GLB
1430           // need to calculate the rest of GLB loc
1431
1432           // int compositeLocSize = compSet.iterator().next().getSize();
1433           int compositeLocSize = maxFromCompSet.getSize();
1434
1435           Set<String> glbInputSet = new HashSet<String>();
1436           Descriptor currentD = null;
1437           for (int i = 1; i < compositeLocSize; i++) {
1438             for (Iterator iterator = compSet.iterator(); iterator.hasNext();) {
1439               CompositeLocation compositeLocation = (CompositeLocation) iterator.next();
1440               if (compositeLocation.getSize() > i) {
1441                 Location currentLoc = compositeLocation.get(i);
1442                 currentD = currentLoc.getDescriptor();
1443                 // making set of the current location sharing the same idx
1444                 glbInputSet.add(currentLoc.getLocIdentifier());
1445               }
1446             }
1447             // calculate glb for the current lattice
1448
1449             SSJavaLattice<String> currentLattice = getLatticeByDescriptor(currentD);
1450             String currentGLBLocId = currentLattice.getGLB(glbInputSet);
1451             glbCompLoc.addLocation(new Location(currentD, currentGLBLocId));
1452           }
1453
1454           // if input location corresponding to glb is a delta, need to apply
1455           // delta to glb result
1456
1457           for (Iterator iterator = compSet.iterator(); iterator.hasNext();) {
1458             CompositeLocation compLoc = (CompositeLocation) iterator.next();
1459             if (compLoc instanceof DeltaLocation) {
1460               if (glbCompLoc.equals(compLoc)) {
1461                 glbCompLoc = new DeltaLocation(glbCompLoc, 1);
1462                 break;
1463               }
1464             }
1465           }
1466
1467         }
1468       }
1469
1470       return glbCompLoc;
1471
1472     }
1473
1474     static SSJavaLattice<String> getLatticeByDescriptor(Descriptor d) {
1475
1476       SSJavaLattice<String> lattice = null;
1477
1478       if (d instanceof ClassDescriptor) {
1479         lattice = ssjava.getCd2lattice().get(d);
1480       } else if (d instanceof MethodDescriptor) {
1481         if (ssjava.getMd2lattice().containsKey(d)) {
1482           lattice = ssjava.getMd2lattice().get(d);
1483         } else {
1484           // use default lattice for the method
1485           lattice = ssjava.getCd2methodDefault().get(((MethodDescriptor) d).getClassDesc());
1486         }
1487       }
1488
1489       return lattice;
1490     }
1491
1492   }
1493
1494   class ComparisonResult {
1495
1496     public static final int GREATER = 0;
1497     public static final int EQUAL = 1;
1498     public static final int LESS = 2;
1499     public static final int INCOMPARABLE = 3;
1500     int result;
1501
1502   }
1503
1504 }
1505
1506 class ReturnLocGenerator {
1507
1508   public static final int PARAMISHIGHER = 0;
1509   public static final int PARAMISSAME = 1;
1510   public static final int IGNORE = 2;
1511
1512   Hashtable<Integer, Integer> paramIdx2paramType;
1513
1514   public ReturnLocGenerator(CompositeLocation returnLoc, List<CompositeLocation> params) {
1515     // creating mappings
1516
1517     paramIdx2paramType = new Hashtable<Integer, Integer>();
1518     for (int i = 0; i < params.size(); i++) {
1519       CompositeLocation param = params.get(i);
1520       int compareResult = CompositeLattice.compare(param, returnLoc);
1521
1522       int type;
1523       if (compareResult == ComparisonResult.GREATER) {
1524         type = 0;
1525       } else if (compareResult == ComparisonResult.EQUAL) {
1526         type = 1;
1527       } else {
1528         type = 2;
1529       }
1530       paramIdx2paramType.put(new Integer(i), new Integer(type));
1531     }
1532
1533   }
1534
1535   public CompositeLocation computeReturnLocation(List<CompositeLocation> args) {
1536
1537     // compute the highest possible location in caller's side
1538     assert paramIdx2paramType.keySet().size() == args.size();
1539
1540     Set<CompositeLocation> inputGLB = new HashSet<CompositeLocation>();
1541     for (int i = 0; i < args.size(); i++) {
1542       int type = (paramIdx2paramType.get(new Integer(i))).intValue();
1543       CompositeLocation argLoc = args.get(i);
1544       if (type == PARAMISHIGHER) {
1545         // return loc is lower than param
1546         DeltaLocation delta = new DeltaLocation(argLoc, 1);
1547         inputGLB.add(delta);
1548       } else if (type == PARAMISSAME) {
1549         // return loc is equal or lower than param
1550         inputGLB.add(argLoc);
1551       }
1552     }
1553
1554     // compute GLB of arguments subset that are same or higher than return
1555     // location
1556     CompositeLocation glb = CompositeLattice.calculateGLB(inputGLB);
1557     return glb;
1558   }
1559 }