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