changes toward intraprocedural analysis
[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
1040           Location lastElement = compLoc.get(compLoc.getSize() - 1);
1041           if (ssjava.isSharedLocation(lastElement)) {
1042             ssjava.mapSharedLocation2Descriptor(lastElement, vd);
1043           }
1044
1045           d2loc.put(vd, compLoc);
1046           addLocationType(vd.getType(), compLoc);
1047         }
1048
1049       }
1050     }
1051
1052   }
1053
1054   private DeltaLocation parseDeltaDeclaration(MethodDescriptor md, TreeNode n, String locDec) {
1055
1056     int deltaCount = 0;
1057     int dIdx = locDec.indexOf(SSJavaAnalysis.DELTA);
1058     while (dIdx >= 0) {
1059       deltaCount++;
1060       int beginIdx = dIdx + 6;
1061       locDec = locDec.substring(beginIdx, locDec.length() - 1);
1062       dIdx = locDec.indexOf(SSJavaAnalysis.DELTA);
1063     }
1064
1065     CompositeLocation compLoc = parseLocationDeclaration(md, n, locDec);
1066     DeltaLocation deltaLoc = new DeltaLocation(compLoc, deltaCount);
1067
1068     return deltaLoc;
1069   }
1070
1071   private Location parseFieldLocDeclaraton(String decl) {
1072
1073     int idx = decl.indexOf(".");
1074     String className = decl.substring(0, idx);
1075     String fieldName = decl.substring(idx + 1);
1076
1077     Descriptor d = state.getClassSymbolTable().get(className);
1078
1079     assert (d instanceof ClassDescriptor);
1080     SSJavaLattice<String> lattice = ssjava.getClassLattice((ClassDescriptor) d);
1081     if (!lattice.containsKey(fieldName)) {
1082       throw new Error("The location " + fieldName + " is not defined in the field lattice of '"
1083           + className + "'.");
1084     }
1085
1086     return new Location(d, fieldName);
1087   }
1088
1089   private CompositeLocation parseLocationDeclaration(MethodDescriptor md, TreeNode n, String locDec) {
1090
1091     CompositeLocation compLoc = new CompositeLocation();
1092
1093     StringTokenizer tokenizer = new StringTokenizer(locDec, ",");
1094     List<String> locIdList = new ArrayList<String>();
1095     while (tokenizer.hasMoreTokens()) {
1096       String locId = tokenizer.nextToken();
1097       locIdList.add(locId);
1098     }
1099
1100     // at least,one location element needs to be here!
1101     assert (locIdList.size() > 0);
1102
1103     // assume that loc with idx 0 comes from the local lattice
1104     // loc with idx 1 comes from the field lattice
1105
1106     String localLocId = locIdList.get(0);
1107     SSJavaLattice<String> localLattice = CompositeLattice.getLatticeByDescriptor(md);
1108     Location localLoc = new Location(md, localLocId);
1109     if (localLattice == null || (!localLattice.containsKey(localLocId))) {
1110       throw new Error("Location " + localLocId
1111           + " is not defined in the local variable lattice at "
1112           + md.getClassDesc().getSourceFileName() + "::" + (n != null ? n.getNumLine() : "") + ".");
1113     }
1114     compLoc.addLocation(localLoc);
1115
1116     for (int i = 1; i < locIdList.size(); i++) {
1117       String locName = locIdList.get(i);
1118
1119       Location fieldLoc = parseFieldLocDeclaraton(locName);
1120       // ClassDescriptor cd = fieldLocName2cd.get(locName);
1121       // SSJavaLattice<String> fieldLattice =
1122       // CompositeLattice.getLatticeByDescriptor(cd);
1123       //
1124       // if (fieldLattice == null || (!fieldLattice.containsKey(locName))) {
1125       // throw new Error("Location " + locName +
1126       // " is not defined in the field lattice at "
1127       // + cd.getSourceFileName() + ".");
1128       // }
1129       // Location fieldLoc = new Location(cd, locName);
1130       compLoc.addLocation(fieldLoc);
1131     }
1132
1133     return compLoc;
1134
1135   }
1136
1137   private void checkDeclarationNode(MethodDescriptor md, SymbolTable nametable, DeclarationNode dn) {
1138     VarDescriptor vd = dn.getVarDescriptor();
1139     assignLocationOfVarDescriptor(vd, md, nametable, dn);
1140   }
1141
1142   private void checkClass(ClassDescriptor cd) {
1143     // Check to see that methods respects ss property
1144     for (Iterator method_it = cd.getMethods(); method_it.hasNext();) {
1145       MethodDescriptor md = (MethodDescriptor) method_it.next();
1146       checkMethodDeclaration(cd, md);
1147     }
1148   }
1149
1150   private void checkDeclarationInClass(ClassDescriptor cd) {
1151     // Check to see that fields are okay
1152     for (Iterator field_it = cd.getFields(); field_it.hasNext();) {
1153       FieldDescriptor fd = (FieldDescriptor) field_it.next();
1154       checkFieldDeclaration(cd, fd);
1155     }
1156   }
1157
1158   private void checkMethodDeclaration(ClassDescriptor cd, MethodDescriptor md) {
1159     // TODO
1160   }
1161
1162   private void checkFieldDeclaration(ClassDescriptor cd, FieldDescriptor fd) {
1163
1164     Vector<AnnotationDescriptor> annotationVec = fd.getType().getAnnotationMarkers();
1165
1166     // currently enforce every field to have corresponding location
1167     if (annotationVec.size() == 0) {
1168       throw new Error("Location is not assigned to the field '" + fd.getSymbol()
1169           + "' of the class " + cd.getSymbol() + " at " + cd.getSourceFileName());
1170     }
1171
1172     if (annotationVec.size() > 1) {
1173       // variable can have at most one location
1174       throw new Error("Field " + fd.getSymbol() + " of class " + cd
1175           + " has more than one location.");
1176     }
1177
1178     AnnotationDescriptor ad = annotationVec.elementAt(0);
1179
1180     if (ad.getType() == AnnotationDescriptor.SINGLE_ANNOTATION) {
1181
1182       if (ad.getMarker().equals(SSJavaAnalysis.LOC)) {
1183         String locationID = ad.getValue();
1184         // check if location is defined
1185         SSJavaLattice<String> lattice = ssjava.getClassLattice(cd);
1186         if (lattice == null || (!lattice.containsKey(locationID))) {
1187           throw new Error("Location " + locationID
1188               + " is not defined in the field lattice of class " + cd.getSymbol() + " at"
1189               + cd.getSourceFileName() + ".");
1190         }
1191         Location loc = new Location(cd, locationID);
1192
1193         if (ssjava.isSharedLocation(loc)) {
1194           ssjava.mapSharedLocation2Descriptor(loc, fd);
1195         }
1196
1197         addLocationType(fd.getType(), loc);
1198
1199       }
1200     }
1201
1202   }
1203
1204   private void addLocationType(TypeDescriptor type, CompositeLocation loc) {
1205     if (type != null) {
1206       type.setExtension(loc);
1207     }
1208   }
1209
1210   private void addLocationType(TypeDescriptor type, Location loc) {
1211     if (type != null) {
1212       type.setExtension(loc);
1213     }
1214   }
1215
1216   static class CompositeLattice {
1217
1218     public static boolean isGreaterThan(CompositeLocation loc1, CompositeLocation loc2) {
1219
1220       int baseCompareResult = compareBaseLocationSet(loc1, loc2, true);
1221       if (baseCompareResult == ComparisonResult.EQUAL) {
1222         if (compareDelta(loc1, loc2) == ComparisonResult.GREATER) {
1223           return true;
1224         } else {
1225           return false;
1226         }
1227       } else if (baseCompareResult == ComparisonResult.GREATER) {
1228         return true;
1229       } else {
1230         return false;
1231       }
1232
1233     }
1234
1235     public static int compare(CompositeLocation loc1, CompositeLocation loc2) {
1236
1237       // System.out.println("compare=" + loc1 + " " + loc2);
1238       int baseCompareResult = compareBaseLocationSet(loc1, loc2, false);
1239
1240       if (baseCompareResult == ComparisonResult.EQUAL) {
1241         return compareDelta(loc1, loc2);
1242       } else {
1243         return baseCompareResult;
1244       }
1245
1246     }
1247
1248     private static int compareDelta(CompositeLocation dLoc1, CompositeLocation dLoc2) {
1249
1250       int deltaCount1 = 0;
1251       int deltaCount2 = 0;
1252       if (dLoc1 instanceof DeltaLocation) {
1253         deltaCount1 = ((DeltaLocation) dLoc1).getNumDelta();
1254       }
1255
1256       if (dLoc2 instanceof DeltaLocation) {
1257         deltaCount2 = ((DeltaLocation) dLoc2).getNumDelta();
1258       }
1259       if (deltaCount1 < deltaCount2) {
1260         return ComparisonResult.GREATER;
1261       } else if (deltaCount1 == deltaCount2) {
1262         return ComparisonResult.EQUAL;
1263       } else {
1264         return ComparisonResult.LESS;
1265       }
1266
1267     }
1268
1269     private static int compareBaseLocationSet(CompositeLocation compLoc1,
1270         CompositeLocation compLoc2, boolean awareSharedLoc) {
1271
1272       // if compLoc1 is greater than compLoc2, return true
1273       // else return false;
1274
1275       // compare one by one in according to the order of the tuple
1276       int numOfTie = 0;
1277       for (int i = 0; i < compLoc1.getSize(); i++) {
1278         Location loc1 = compLoc1.get(i);
1279         if (i >= compLoc2.getSize()) {
1280           throw new Error("Failed to compare two locations of " + compLoc1 + " and " + compLoc2
1281               + " because they are not comparable.");
1282         }
1283         Location loc2 = compLoc2.get(i);
1284
1285         if (!loc1.getDescriptor().equals(loc2.getDescriptor())) {
1286           throw new Error("Failed to compare two locations of " + compLoc1 + " and " + compLoc2
1287               + " because they are not comparable.");
1288         }
1289
1290         Descriptor d1 = loc1.getDescriptor();
1291         Descriptor d2 = loc2.getDescriptor();
1292
1293         SSJavaLattice<String> lattice1 = getLatticeByDescriptor(d1);
1294         SSJavaLattice<String> lattice2 = getLatticeByDescriptor(d2);
1295
1296         // check if the spin location is appeared only at the end of the
1297         // composite location
1298         if (lattice1.getSpinLocSet().contains(loc1.getLocIdentifier())) {
1299           if (i != (compLoc1.getSize() - 1)) {
1300             throw new Error("The spin location " + loc1.getLocIdentifier()
1301                 + " cannot be appeared in the middle of composite location.");
1302           }
1303         }
1304
1305         if (lattice2.getSpinLocSet().contains(loc2.getLocIdentifier())) {
1306           if (i != (compLoc2.getSize() - 1)) {
1307             throw new Error("The spin location " + loc2.getLocIdentifier()
1308                 + " cannot be appeared in the middle of composite location.");
1309           }
1310         }
1311
1312         if (!lattice1.equals(lattice2)) {
1313           throw new Error("Failed to compare two locations of " + compLoc1 + " and " + compLoc2
1314               + " because they are not comparable.");
1315         }
1316
1317         if (loc1.getLocIdentifier().equals(loc2.getLocIdentifier())) {
1318           numOfTie++;
1319           // check if the current location is the spinning location
1320           // note that the spinning location only can be appeared in the last
1321           // part of the composite location
1322           if (awareSharedLoc && numOfTie == compLoc1.getSize()
1323               && lattice1.getSpinLocSet().contains(loc1.getLocIdentifier())) {
1324             return ComparisonResult.GREATER;
1325           }
1326           continue;
1327         } else if (lattice1.isGreaterThan(loc1.getLocIdentifier(), loc2.getLocIdentifier())) {
1328           return ComparisonResult.GREATER;
1329         } else {
1330           return ComparisonResult.LESS;
1331         }
1332
1333       }
1334
1335       if (numOfTie == compLoc1.getSize()) {
1336
1337         if (numOfTie != compLoc2.getSize()) {
1338           throw new Error("Failed to compare two locations of " + compLoc1 + " and " + compLoc2
1339               + " because they are not comparable.");
1340         }
1341
1342         return ComparisonResult.EQUAL;
1343       }
1344
1345       return ComparisonResult.LESS;
1346
1347     }
1348
1349     public static CompositeLocation calculateGLB(Set<CompositeLocation> inputSet) {
1350
1351       // System.out.println("Calculating GLB=" + inputSet);
1352       CompositeLocation glbCompLoc = new CompositeLocation();
1353
1354       // calculate GLB of the first(priority) element
1355       Set<String> priorityLocIdentifierSet = new HashSet<String>();
1356       Descriptor priorityDescriptor = null;
1357
1358       Hashtable<String, Set<CompositeLocation>> locId2CompLocSet =
1359           new Hashtable<String, Set<CompositeLocation>>();
1360       // mapping from the priority loc ID to its full representation by the
1361       // composite location
1362
1363       int maxTupleSize = 0;
1364       CompositeLocation maxCompLoc = null;
1365
1366       for (Iterator iterator = inputSet.iterator(); iterator.hasNext();) {
1367         CompositeLocation compLoc = (CompositeLocation) iterator.next();
1368         if (compLoc.getSize() > maxTupleSize) {
1369           maxTupleSize = compLoc.getSize();
1370           maxCompLoc = compLoc;
1371         }
1372         Location priorityLoc = compLoc.get(0);
1373         String priorityLocId = priorityLoc.getLocIdentifier();
1374         priorityLocIdentifierSet.add(priorityLocId);
1375
1376         if (locId2CompLocSet.containsKey(priorityLocId)) {
1377           locId2CompLocSet.get(priorityLocId).add(compLoc);
1378         } else {
1379           Set<CompositeLocation> newSet = new HashSet<CompositeLocation>();
1380           newSet.add(compLoc);
1381           locId2CompLocSet.put(priorityLocId, newSet);
1382         }
1383
1384         // check if priority location are coming from the same lattice
1385         if (priorityDescriptor == null) {
1386           priorityDescriptor = priorityLoc.getDescriptor();
1387         } else if (!priorityDescriptor.equals(priorityLoc.getDescriptor())) {
1388           throw new Error("Failed to calculate GLB of " + inputSet
1389               + " because they are from different lattices.");
1390         }
1391       }
1392
1393       SSJavaLattice<String> locOrder = getLatticeByDescriptor(priorityDescriptor);
1394       String glbOfPriorityLoc = locOrder.getGLB(priorityLocIdentifierSet);
1395
1396       glbCompLoc.addLocation(new Location(priorityDescriptor, glbOfPriorityLoc));
1397       Set<CompositeLocation> compSet = locId2CompLocSet.get(glbOfPriorityLoc);
1398
1399       // here find out composite location that has a maximum length tuple
1400       // if we have three input set: [A], [A,B], [A,B,C]
1401       // maximum length tuple will be [A,B,C]
1402       int max = 0;
1403       CompositeLocation maxFromCompSet = null;
1404       for (Iterator iterator = compSet.iterator(); iterator.hasNext();) {
1405         CompositeLocation c = (CompositeLocation) iterator.next();
1406         if (c.getSize() > max) {
1407           max = c.getSize();
1408           maxFromCompSet = c;
1409         }
1410       }
1411
1412       if (compSet == null) {
1413         // when GLB(x1,x2)!=x1 and !=x2 : GLB case 4
1414         // mean that the result is already lower than <x1,y1> and <x2,y2>
1415         // assign TOP to the rest of the location elements
1416
1417         // in this case, do not take care about delta
1418         // CompositeLocation inputComp = inputSet.iterator().next();
1419         CompositeLocation inputComp = maxCompLoc;
1420         for (int i = 1; i < inputComp.getSize(); i++) {
1421           glbCompLoc.addLocation(Location.createTopLocation(inputComp.get(i).getDescriptor()));
1422         }
1423       } else {
1424         if (compSet.size() == 1) {
1425
1426           // if GLB(x1,x2)==x1 or x2 : GLB case 2,3
1427           CompositeLocation comp = compSet.iterator().next();
1428           for (int i = 1; i < comp.getSize(); i++) {
1429             glbCompLoc.addLocation(comp.get(i));
1430           }
1431
1432           // if input location corresponding to glb is a delta, need to apply
1433           // delta to glb result
1434           if (comp instanceof DeltaLocation) {
1435             glbCompLoc = new DeltaLocation(glbCompLoc, 1);
1436           }
1437
1438         } else {
1439           // when GLB(x1,x2)==x1 and x2 : GLB case 1
1440           // if more than one location shares the same priority GLB
1441           // need to calculate the rest of GLB loc
1442
1443           // int compositeLocSize = compSet.iterator().next().getSize();
1444           int compositeLocSize = maxFromCompSet.getSize();
1445
1446           Set<String> glbInputSet = new HashSet<String>();
1447           Descriptor currentD = null;
1448           for (int i = 1; i < compositeLocSize; i++) {
1449             for (Iterator iterator = compSet.iterator(); iterator.hasNext();) {
1450               CompositeLocation compositeLocation = (CompositeLocation) iterator.next();
1451               if (compositeLocation.getSize() > i) {
1452                 Location currentLoc = compositeLocation.get(i);
1453                 currentD = currentLoc.getDescriptor();
1454                 // making set of the current location sharing the same idx
1455                 glbInputSet.add(currentLoc.getLocIdentifier());
1456               }
1457             }
1458             // calculate glb for the current lattice
1459
1460             SSJavaLattice<String> currentLattice = getLatticeByDescriptor(currentD);
1461             String currentGLBLocId = currentLattice.getGLB(glbInputSet);
1462             glbCompLoc.addLocation(new Location(currentD, currentGLBLocId));
1463           }
1464
1465           // if input location corresponding to glb is a delta, need to apply
1466           // delta to glb result
1467
1468           for (Iterator iterator = compSet.iterator(); iterator.hasNext();) {
1469             CompositeLocation compLoc = (CompositeLocation) iterator.next();
1470             if (compLoc instanceof DeltaLocation) {
1471               if (glbCompLoc.equals(compLoc)) {
1472                 glbCompLoc = new DeltaLocation(glbCompLoc, 1);
1473                 break;
1474               }
1475             }
1476           }
1477
1478         }
1479       }
1480
1481       return glbCompLoc;
1482
1483     }
1484
1485     static SSJavaLattice<String> getLatticeByDescriptor(Descriptor d) {
1486
1487       SSJavaLattice<String> lattice = null;
1488
1489       if (d instanceof ClassDescriptor) {
1490         lattice = ssjava.getCd2lattice().get(d);
1491       } else if (d instanceof MethodDescriptor) {
1492         if (ssjava.getMd2lattice().containsKey(d)) {
1493           lattice = ssjava.getMd2lattice().get(d);
1494         } else {
1495           // use default lattice for the method
1496           lattice = ssjava.getCd2methodDefault().get(((MethodDescriptor) d).getClassDesc());
1497         }
1498       }
1499
1500       return lattice;
1501     }
1502
1503   }
1504
1505   class ComparisonResult {
1506
1507     public static final int GREATER = 0;
1508     public static final int EQUAL = 1;
1509     public static final int LESS = 2;
1510     public static final int INCOMPARABLE = 3;
1511     int result;
1512
1513   }
1514
1515 }
1516
1517 class ReturnLocGenerator {
1518
1519   public static final int PARAMISHIGHER = 0;
1520   public static final int PARAMISSAME = 1;
1521   public static final int IGNORE = 2;
1522
1523   Hashtable<Integer, Integer> paramIdx2paramType;
1524
1525   public ReturnLocGenerator(CompositeLocation returnLoc, List<CompositeLocation> params) {
1526     // creating mappings
1527
1528     paramIdx2paramType = new Hashtable<Integer, Integer>();
1529     for (int i = 0; i < params.size(); i++) {
1530       CompositeLocation param = params.get(i);
1531       int compareResult = CompositeLattice.compare(param, returnLoc);
1532
1533       int type;
1534       if (compareResult == ComparisonResult.GREATER) {
1535         type = 0;
1536       } else if (compareResult == ComparisonResult.EQUAL) {
1537         type = 1;
1538       } else {
1539         type = 2;
1540       }
1541       paramIdx2paramType.put(new Integer(i), new Integer(type));
1542     }
1543
1544   }
1545
1546   public CompositeLocation computeReturnLocation(List<CompositeLocation> args) {
1547
1548     // compute the highest possible location in caller's side
1549     assert paramIdx2paramType.keySet().size() == args.size();
1550
1551     Set<CompositeLocation> inputGLB = new HashSet<CompositeLocation>();
1552     for (int i = 0; i < args.size(); i++) {
1553       int type = (paramIdx2paramType.get(new Integer(i))).intValue();
1554       CompositeLocation argLoc = args.get(i);
1555       if (type == PARAMISHIGHER) {
1556         // return loc is lower than param
1557         DeltaLocation delta = new DeltaLocation(argLoc, 1);
1558         inputGLB.add(delta);
1559       } else if (type == PARAMISSAME) {
1560         // return loc is equal or lower than param
1561         inputGLB.add(argLoc);
1562       }
1563     }
1564
1565     // compute GLB of arguments subset that are same or higher than return
1566     // location
1567     CompositeLocation glb = CompositeLattice.calculateGLB(inputGLB);
1568     return glb;
1569   }
1570 }