1 package Analysis.SSJava;
3 import java.io.FileWriter;
4 import java.io.IOException;
5 import java.io.PrintWriter;
6 import java.util.ArrayList;
7 import java.util.Collections;
8 import java.util.Comparator;
9 import java.util.HashSet;
10 import java.util.Hashtable;
11 import java.util.Iterator;
12 import java.util.List;
15 import IR.ClassDescriptor;
17 import IR.FieldDescriptor;
18 import IR.MethodDescriptor;
19 import IR.NameDescriptor;
22 import IR.SymbolTable;
23 import IR.VarDescriptor;
24 import IR.Tree.AssignmentNode;
25 import IR.Tree.BlockExpressionNode;
26 import IR.Tree.BlockNode;
27 import IR.Tree.BlockStatementNode;
28 import IR.Tree.DeclarationNode;
29 import IR.Tree.ExpressionNode;
30 import IR.Tree.IfStatementNode;
32 import IR.Tree.LiteralNode;
33 import IR.Tree.LoopNode;
34 import IR.Tree.NameNode;
35 import IR.Tree.OpNode;
36 import IR.Tree.ReturnNode;
37 import IR.Tree.SubBlockNode;
39 public class SSJavaInferenceEngine {
42 static SSJavaAnalysis ssjava;
44 Set<ClassDescriptor> toanalyze;
45 List<ClassDescriptor> toanalyzeList;
47 Set<MethodDescriptor> toanalyzeMethod;
48 List<MethodDescriptor> toanalyzeMethodList;
50 // mapping from 'descriptor' to 'composite location'
51 Hashtable<Descriptor, CompositeLocation> d2loc;
53 Hashtable<MethodDescriptor, CompositeLocation> md2ReturnLoc;
54 Hashtable<MethodDescriptor, ReturnLocGenerator> md2ReturnLocGen;
56 // mapping from 'locID' to 'class descriptor'
57 Hashtable<String, ClassDescriptor> fieldLocName2cd;
59 private Set<ImplicitTuple> implicitFlowSet; /*
61 * hashtable<ExpressionNode
64 private RelationSet rSet;
66 boolean deterministic = true;
68 public SSJavaInferenceEngine(SSJavaAnalysis ssjava, State state) {
72 this.toanalyzeList = new ArrayList<ClassDescriptor>();
74 this.toanalyze = new HashSet<ClassDescriptor>();
77 this.toanalyzeMethodList = new ArrayList<MethodDescriptor>();
79 this.toanalyzeMethod = new HashSet<MethodDescriptor>();
81 this.d2loc = new Hashtable<Descriptor, CompositeLocation>();
82 this.fieldLocName2cd = new Hashtable<String, ClassDescriptor>();
83 this.md2ReturnLoc = new Hashtable<MethodDescriptor, CompositeLocation>();
84 this.md2ReturnLocGen = new Hashtable<MethodDescriptor, ReturnLocGenerator>();
85 this.implicitFlowSet = new HashSet<ImplicitTuple>();
86 this.rSet = new RelationSet();
91 // construct mapping from the location name to the class descriptor
92 // assume that the location name is unique through the whole program
94 Set<ClassDescriptor> cdSet = ssjava.getCd2lattice().keySet();
95 for (Iterator iterator = cdSet.iterator(); iterator.hasNext();) {
96 ClassDescriptor cd = (ClassDescriptor) iterator.next();
97 SSJavaLattice<String> lattice = ssjava.getCd2lattice().get(cd);
98 Set<String> fieldLocNameSet = lattice.getKeySet();
100 for (Iterator iterator2 = fieldLocNameSet.iterator(); iterator2.hasNext();) {
101 String fieldLocName = (String) iterator2.next();
102 fieldLocName2cd.put(fieldLocName, cd);
109 public boolean toAnalyzeIsEmpty() {
111 return toanalyzeList.isEmpty();
113 return toanalyze.isEmpty();
117 public ClassDescriptor toAnalyzeNext() {
119 return toanalyzeList.remove(0);
121 ClassDescriptor cd = toanalyze.iterator().next();
122 toanalyze.remove(cd);
127 public void setupToAnalyze() {
128 SymbolTable classtable = state.getClassSymbolTable();
130 toanalyzeList.clear();
131 toanalyzeList.addAll(classtable.getValueSet());
132 Collections.sort(toanalyzeList, new Comparator<ClassDescriptor>() {
133 public int compare(ClassDescriptor o1, ClassDescriptor o2) {
134 return o1.getClassName().compareTo(o2.getClassName());
139 toanalyze.addAll(classtable.getValueSet());
143 public void setupToAnalazeMethod(ClassDescriptor cd) {
145 SymbolTable methodtable = cd.getMethodTable();
147 toanalyzeMethodList.clear();
148 toanalyzeMethodList.addAll(methodtable.getValueSet());
149 Collections.sort(toanalyzeMethodList, new Comparator<MethodDescriptor>() {
150 public int compare(MethodDescriptor o1, MethodDescriptor o2) {
151 return o1.getSymbol().compareTo(o2.getSymbol());
155 toanalyzeMethod.clear();
156 toanalyzeMethod.addAll(methodtable.getValueSet());
160 public boolean toAnalyzeMethodIsEmpty() {
162 return toanalyzeMethodList.isEmpty();
164 return toanalyzeMethod.isEmpty();
168 public MethodDescriptor toAnalyzeMethodNext() {
170 return toanalyzeMethodList.remove(0);
172 MethodDescriptor md = toanalyzeMethod.iterator().next();
173 toanalyzeMethod.remove(md);
178 public void inference() {
179 FileWriter latticeFile;
180 PrintWriter latticeOut;
183 while (!toAnalyzeIsEmpty()) {
184 ClassDescriptor cd = toAnalyzeNext();
186 latticeFile = new FileWriter(cd.getClassName() + ".lat");
187 } catch (IOException e) {
188 System.out.println("File Fail");
191 latticeOut = new PrintWriter(latticeFile);
192 if (ssjava.needToBeAnnoated(cd)) {
193 setupToAnalazeMethod(cd);
194 while (!toAnalyzeMethodIsEmpty()) {
195 MethodDescriptor md = toAnalyzeMethodNext();
196 if (ssjava.needTobeAnnotated(md)) {
197 inferRelationsFromBlockNode(md, md.getParameterTable(), state.getMethodBody(md));
198 latticeOut.println(md.getClassMethodName() + "\n");
199 latticeOut.println(rSet.toString());
200 rSet = new RelationSet();
209 private void inferRelationsFromBlockNode(MethodDescriptor md, SymbolTable nametable, BlockNode bn) {
211 bn.getVarTable().setParent(nametable);
212 for (int i = 0; i < bn.size(); i++) {
213 BlockStatementNode bsn = bn.get(i);
214 inferRelationsFromBlockStatementNode(md, bn.getVarTable(), bsn);
219 private void inferRelationsFromBlockStatementNode(MethodDescriptor md, SymbolTable nametable,
220 BlockStatementNode bsn) {
222 switch (bsn.kind()) {
223 case Kind.BlockExpressionNode:
224 inferRelationsFromBlockExpressionNode(md, nametable, (BlockExpressionNode) bsn);
227 case Kind.DeclarationNode:
228 inferRelationsFromDeclarationNode(md, nametable, (DeclarationNode) bsn);
231 case Kind.IfStatementNode:
232 inferRelationsFromIfStatementNode(md, nametable, (IfStatementNode) bsn);
236 inferRelationsFromLoopNode(md, nametable, (LoopNode) bsn);
239 case Kind.ReturnNode:
240 inferRelationsFromReturnNode(md, nametable, (ReturnNode) bsn);
243 case Kind.SubBlockNode:
244 inferRelationsFromSubBlockNode(md, nametable, (SubBlockNode) bsn);
247 * case Kind.ContinueBreakNode: compLoc = new CompositeLocation(); break;
249 * case Kind.SwitchStatementNode: inferRelationsFromSwitchStatementNode(md,
250 * nametable, (SwitchStatementNode) bsn, constraint); break;
253 System.out.println(bsn.kind() + " not handled...");
259 * private CompositeLocation
260 * inferRelationsFromSwitchStatementNode(MethodDescriptor md, SymbolTable
261 * nametable, SwitchStatementNode ssn, CompositeLocation constraint) {
263 * ClassDescriptor cd = md.getClassDesc(); CompositeLocation condLoc =
264 * inferRelationsFromExpressionNode(md, nametable, ssn.getCondition(), new
265 * CompositeLocation(), constraint, false); BlockNode sbn =
266 * ssn.getSwitchBody();
268 * constraint = generateNewConstraint(constraint, condLoc);
270 * for (int i = 0; i < sbn.size(); i++) {
271 * inferRelationsFromSwitchBlockNode(md, nametable, (SwitchBlockNode)
272 * sbn.get(i), constraint); } return new CompositeLocation(); }
274 * private void inferRelationsFromSwitchBlockNode(MethodDescriptor md,
275 * SymbolTable nametable, SwitchBlockNode sbn) {
277 * CompositeLocation blockLoc = inferRelationsFromBlockNode(md, nametable,
278 * sbn.getSwitchBlockStatement(), constraint);
284 private void inferRelationsFromReturnNode(MethodDescriptor md, SymbolTable nametable,
287 ExpressionNode returnExp = rn.getReturnExpression();
290 VarID returnID = new VarID(md);
291 returnID.setReturn();
292 if (returnExp != null) {
293 inferRelationsFromExpressionNode(md, nametable, returnExp, returnID, null, false);
297 private void inferRelationsFromLoopNode(MethodDescriptor md, SymbolTable nametable, LoopNode ln) {
299 ClassDescriptor cd = md.getClassDesc();
300 if (ln.getType() == LoopNode.WHILELOOP || ln.getType() == LoopNode.DOWHILELOOP) {
302 inferRelationsFromExpressionNode(md, nametable, ln.getCondition(), null, ln, false);
304 inferRelationsFromBlockNode(md, nametable, ln.getBody());
306 for (ImplicitTuple tuple : implicitFlowSet) {
307 if (tuple.isFromBranch(ln)) {
308 implicitFlowSet.remove(tuple);
313 // check 'for loop' case
314 BlockNode bn = ln.getInitializer();
315 bn.getVarTable().setParent(nametable);
317 inferRelationsFromBlockNode(md, nametable, bn);
318 inferRelationsFromExpressionNode(md, bn.getVarTable(), ln.getCondition(), null, ln, false);
320 inferRelationsFromBlockNode(md, bn.getVarTable(), ln.getUpdate());
321 inferRelationsFromBlockNode(md, bn.getVarTable(), ln.getBody());
323 for (ImplicitTuple tuple : implicitFlowSet) {
324 if (tuple.isFromBranch(ln)) {
325 implicitFlowSet.remove(tuple);
333 private void inferRelationsFromSubBlockNode(MethodDescriptor md, SymbolTable nametable,
335 inferRelationsFromBlockNode(md, nametable, sbn.getBlockNode());
338 private void inferRelationsFromIfStatementNode(MethodDescriptor md, SymbolTable nametable,
339 IfStatementNode isn) {
341 inferRelationsFromExpressionNode(md, nametable, isn.getCondition(), null, isn, false);
343 inferRelationsFromBlockNode(md, nametable, isn.getTrueBlock());
345 if (isn.getFalseBlock() != null) {
346 inferRelationsFromBlockNode(md, nametable, isn.getFalseBlock());
349 for (ImplicitTuple tuple : implicitFlowSet) {
350 if (tuple.isFromBranch(isn)) {
351 implicitFlowSet.remove(tuple);
356 private void inferRelationsFromDeclarationNode(MethodDescriptor md, SymbolTable nametable,
357 DeclarationNode dn) {
361 * private void inferRelationsFromSubBlockNode(MethodDescriptor md,
362 * SymbolTable nametable, SubBlockNode sbn) { inferRelationsFromBlockNode(md,
363 * nametable.getParent(), sbn.getBlockNode()); }
366 private void inferRelationsFromBlockExpressionNode(MethodDescriptor md, SymbolTable nametable,
367 BlockExpressionNode ben) {
368 inferRelationsFromExpressionNode(md, nametable, ben.getExpression(), null, null, false);
369 // addTypeLocation(ben.getExpression().getType(), compLoc);
372 private VarID inferRelationsFromExpressionNode(MethodDescriptor md, SymbolTable nametable,
373 ExpressionNode en, VarID flowTo, BlockStatementNode implicitTag, boolean isLHS) {
378 case Kind.AssignmentNode:
380 inferRelationsFromAssignmentNode(md, nametable, (AssignmentNode) en, flowTo, implicitTag);
383 // case Kind.FieldAccessNode:
385 // inferRelationsFromFieldAccessNode(md, nametable, (FieldAccessNode) en,
390 var = inferRelationsFromNameNode(md, nametable, (NameNode) en, flowTo, implicitTag);
394 var = inferRelationsFromOpNode(md, nametable, (OpNode) en, flowTo, implicitTag);
397 * case Kind.CreateObjectNode: var = inferRelationsFromCreateObjectNode(md,
398 * nametable, (CreateObjectNode) en); break;
400 * case Kind.ArrayAccessNode: var = inferRelationsFromArrayAccessNode(md,
401 * nametable, (ArrayAccessNode) en, flowTo, isLHS); break;
403 case Kind.LiteralNode:
404 var = inferRelationsFromLiteralNode(md, nametable, (LiteralNode) en);
407 * case Kind.MethodInvokeNode: var = inferRelationsFromMethodInvokeNode(md,
408 * nametable, (MethodInvokeNode) en, flowTo); break;
410 * case Kind.TertiaryNode: var = inferRelationsFromTertiaryNode(md,
411 * nametable, (TertiaryNode) en); break;
413 * case Kind.CastNode: var = inferRelationsFromCastNode(md, nametable,
414 * (CastNode) en); break;
416 // case Kind.InstanceOfNode:
417 // checkInstanceOfNode(md, nametable, (InstanceOfNode) en, td);
420 // case Kind.ArrayInitializerNode:
421 // checkArrayInitializerNode(md, nametable, (ArrayInitializerNode) en,
425 // case Kind.ClassTypeNode:
426 // checkClassTypeNode(md, nametable, (ClassTypeNode) en, td);
429 // case Kind.OffsetNode:
430 // checkOffsetNode(md, nametable, (OffsetNode)en, td);
434 System.out.println("expressionnode not handled...");
438 // addTypeLocation(en.getType(), compLoc);
444 * private CompositeLocation inferRelationsFromCastNode(MethodDescriptor md,
445 * SymbolTable nametable, CastNode cn, CompositeLocation constraint) {
447 * ExpressionNode en = cn.getExpression(); return
448 * inferRelationsFromExpressionNode(md, nametable, en, new
449 * CompositeLocation(), constraint, false);
453 * private CompositeLocation inferRelationsFromTertiaryNode(MethodDescriptor
454 * md, SymbolTable nametable, TertiaryNode tn, CompositeLocation constraint) {
455 * ClassDescriptor cd = md.getClassDesc();
457 * CompositeLocation condLoc = inferRelationsFromExpressionNode(md, nametable,
458 * tn.getCond(), new CompositeLocation(), constraint, false); //
459 * addLocationType(tn.getCond().getType(), condLoc); CompositeLocation trueLoc
460 * = inferRelationsFromExpressionNode(md, nametable, tn.getTrueExpr(), new
461 * CompositeLocation(), constraint, false); //
462 * addLocationType(tn.getTrueExpr().getType(), trueLoc); CompositeLocation
463 * falseLoc = inferRelationsFromExpressionNode(md, nametable,
464 * tn.getFalseExpr(), new CompositeLocation(), constraint, false); //
465 * addLocationType(tn.getFalseExpr().getType(), falseLoc);
467 * // locations from true/false branches can be TOP when there are only
468 * literal // values // in this case, we don't need to check flow down rule!
470 * // check if condLoc is higher than trueLoc & falseLoc if
471 * (!trueLoc.get(0).isTop() && !CompositeLattice.isGreaterThan(condLoc,
472 * trueLoc, generateErrorMessage(cd, tn))) { throw new Error(
473 * "The location of the condition expression is lower than the true expression at "
474 * + cd.getSourceFileName() + ":" + tn.getCond().getNumLine()); }
476 * if (!falseLoc.get(0).isTop() && !CompositeLattice.isGreaterThan(condLoc,
477 * falseLoc, generateErrorMessage(cd, tn.getCond()))) { throw new Error(
478 * "The location of the condition expression is lower than the true expression at "
479 * + cd.getSourceFileName() + ":" + tn.getCond().getNumLine()); }
481 * // then, return glb of trueLoc & falseLoc Set<CompositeLocation>
482 * glbInputSet = new HashSet<CompositeLocation>(); glbInputSet.add(trueLoc);
483 * glbInputSet.add(falseLoc);
485 * return CompositeLattice.calculateGLB(glbInputSet, generateErrorMessage(cd,
488 * private CompositeLocation
489 * inferRelationsFromMethodInvokeNode(MethodDescriptor md, SymbolTable
490 * nametable, MethodInvokeNode min, CompositeLocation loc, CompositeLocation
493 * CompositeLocation baseLocation = null; if (min.getExpression() != null) {
494 * baseLocation = inferRelationsFromExpressionNode(md, nametable,
495 * min.getExpression(), new CompositeLocation(), constraint, false); } else {
497 * if (min.getMethod().isStatic()) { String globalLocId =
498 * ssjava.getMethodLattice(md).getGlobalLoc(); if (globalLocId == null) {
500 * Error("Method lattice does not define global variable location at " +
501 * generateErrorMessage(md.getClassDesc(), min)); } baseLocation = new
502 * CompositeLocation(new Location(md, globalLocId)); } else { String thisLocId
503 * = ssjava.getMethodLattice(md).getThisLoc(); baseLocation = new
504 * CompositeLocation(new Location(md, thisLocId)); } }
506 * checkCalleeConstraints(md, nametable, min, baseLocation, constraint);
508 * checkCallerArgumentLocationConstraints(md, nametable, min, baseLocation,
511 * if (!min.getMethod().getReturnType().isVoid()) { // If method has a return
512 * value, compute the highest possible return // location in the caller's
513 * perspective CompositeLocation ceilingLoc =
514 * computeCeilingLocationForCaller(md, nametable, min, baseLocation,
515 * constraint); return ceilingLoc; }
517 * return new CompositeLocation();
521 * private void checkCallerArgumentLocationConstraints(MethodDescriptor md,
522 * SymbolTable nametable, MethodInvokeNode min, CompositeLocation
523 * callerBaseLoc, CompositeLocation constraint) { // if parameter location
524 * consists of THIS and FIELD location, // caller should pass an argument that
525 * is comparable to the declared // parameter location // and is not lower
526 * than the declared parameter location in the field // lattice.
528 * MethodDescriptor calleemd = min.getMethod();
530 * List<CompositeLocation> callerArgList = new ArrayList<CompositeLocation>();
531 * List<CompositeLocation> calleeParamList = new
532 * ArrayList<CompositeLocation>();
534 * MethodLattice<String> calleeLattice = ssjava.getMethodLattice(calleemd);
535 * Location calleeThisLoc = new Location(calleemd,
536 * calleeLattice.getThisLoc());
538 * for (int i = 0; i < min.numArgs(); i++) { ExpressionNode en =
539 * min.getArg(i); CompositeLocation callerArgLoc =
540 * inferRelationsFromExpressionNode(md, nametable, en, new
541 * CompositeLocation(), constraint, false); callerArgList.add(callerArgLoc); }
543 * // setup callee params set for (int i = 0; i < calleemd.numParameters();
544 * i++) { VarDescriptor calleevd = (VarDescriptor) calleemd.getParameter(i);
545 * CompositeLocation calleeLoc = d2loc.get(calleevd);
546 * calleeParamList.add(calleeLoc); }
548 * String errorMsg = generateErrorMessage(md.getClassDesc(), min);
550 * System.out.println("checkCallerArgumentLocationConstraints=" +
551 * min.printNode(0)); System.out.println("base location=" + callerBaseLoc);
553 * for (int i = 0; i < calleeParamList.size(); i++) { CompositeLocation
554 * calleeParamLoc = calleeParamList.get(i); if
555 * (calleeParamLoc.get(0).equals(calleeThisLoc) && calleeParamLoc.getSize() >
558 * // callee parameter location has field information CompositeLocation
559 * callerArgLoc = callerArgList.get(i);
561 * CompositeLocation paramLocation = translateCalleeParamLocToCaller(md,
562 * calleeParamLoc, callerBaseLoc, errorMsg);
564 * Set<CompositeLocation> inputGLBSet = new HashSet<CompositeLocation>(); if
565 * (constraint != null) { inputGLBSet.add(callerArgLoc);
566 * inputGLBSet.add(constraint); callerArgLoc =
567 * CompositeLattice.calculateGLB(inputGLBSet,
568 * generateErrorMessage(md.getClassDesc(), min)); }
570 * if (!CompositeLattice.isGreaterThan(callerArgLoc, paramLocation, errorMsg))
571 * { throw new Error("Caller argument '" + min.getArg(i).printNode(0) + " : "
573 * "' should be higher than corresponding callee's parameter : " +
574 * paramLocation + " at " + errorMsg); }
580 * private CompositeLocation translateCalleeParamLocToCaller(MethodDescriptor
581 * md, CompositeLocation calleeParamLoc, CompositeLocation callerBaseLocation,
584 * CompositeLocation translate = new CompositeLocation();
586 * for (int i = 0; i < callerBaseLocation.getSize(); i++) {
587 * translate.addLocation(callerBaseLocation.get(i)); }
589 * for (int i = 1; i < calleeParamLoc.getSize(); i++) {
590 * translate.addLocation(calleeParamLoc.get(i)); }
592 * System.out.println("TRANSLATED=" + translate + " from calleeParamLoc=" +
595 * return translate; }
597 * private CompositeLocation computeCeilingLocationForCaller(MethodDescriptor
598 * md, SymbolTable nametable, MethodInvokeNode min, CompositeLocation
599 * baseLocation, CompositeLocation constraint) { List<CompositeLocation>
600 * argList = new ArrayList<CompositeLocation>();
602 * // by default, method has a THIS parameter argList.add(baseLocation);
604 * for (int i = 0; i < min.numArgs(); i++) { ExpressionNode en =
605 * min.getArg(i); CompositeLocation callerArg =
606 * inferRelationsFromExpressionNode(md, nametable, en, new
607 * CompositeLocation(), constraint, false); argList.add(callerArg); }
609 * System.out.println("\n## computeReturnLocation=" + min.getMethod() +
610 * " argList=" + argList); CompositeLocation compLoc =
611 * md2ReturnLocGen.get(min.getMethod()).computeReturnLocation(argList);
612 * DeltaLocation delta = new DeltaLocation(compLoc, 1);
613 * System.out.println("##computeReturnLocation=" + delta);
619 * private void checkCalleeConstraints(MethodDescriptor md, SymbolTable
620 * nametable, MethodInvokeNode min, CompositeLocation callerBaseLoc,
621 * CompositeLocation constraint) {
623 * System.out.println("checkCalleeConstraints="+min.printNode(0));
625 * MethodDescriptor calleemd = min.getMethod();
627 * MethodLattice<String> calleeLattice = ssjava.getMethodLattice(calleemd);
628 * CompositeLocation calleeThisLoc = new CompositeLocation(new
629 * Location(calleemd, calleeLattice.getThisLoc()));
631 * List<CompositeLocation> callerArgList = new ArrayList<CompositeLocation>();
632 * List<CompositeLocation> calleeParamList = new
633 * ArrayList<CompositeLocation>();
635 * if (min.numArgs() > 0) { // caller needs to guarantee that it passes
636 * arguments in regarding to // callee's hierarchy
638 * // setup caller args set // first, add caller's base(this) location
639 * callerArgList.add(callerBaseLoc); // second, add caller's arguments for
640 * (int i = 0; i < min.numArgs(); i++) { ExpressionNode en = min.getArg(i);
641 * CompositeLocation callerArgLoc = inferRelationsFromExpressionNode(md,
642 * nametable, en, new CompositeLocation(), constraint, false);
643 * callerArgList.add(callerArgLoc); }
645 * // setup callee params set // first, add callee's this location
646 * calleeParamList.add(calleeThisLoc); // second, add callee's parameters for
647 * (int i = 0; i < calleemd.numParameters(); i++) { VarDescriptor calleevd =
648 * (VarDescriptor) calleemd.getParameter(i); CompositeLocation calleeLoc =
649 * d2loc.get(calleevd);
650 * System.out.println("calleevd="+calleevd+" loc="+calleeLoc);
651 * calleeParamList.add(calleeLoc); }
653 * // here, check if ordering relations among caller's args respect //
654 * ordering relations in-between callee's args CHECK: for (int i = 0; i <
655 * calleeParamList.size(); i++) { CompositeLocation calleeLoc1 =
656 * calleeParamList.get(i); CompositeLocation callerLoc1 =
657 * callerArgList.get(i);
659 * for (int j = 0; j < calleeParamList.size(); j++) { if (i != j) {
660 * CompositeLocation calleeLoc2 = calleeParamList.get(j); CompositeLocation
661 * callerLoc2 = callerArgList.get(j);
663 * if (callerLoc1.get(callerLoc1.getSize() - 1).isTop() ||
664 * callerLoc2.get(callerLoc2.getSize() - 1).isTop()) { continue CHECK; }
666 * System.out.println("calleeLoc1="+calleeLoc1);
667 * System.out.println("calleeLoc2="
668 * +calleeLoc2+"calleeParamList="+calleeParamList);
670 * int callerResult = CompositeLattice.compare(callerLoc1, callerLoc2, true,
671 * generateErrorMessage(md.getClassDesc(), min)); int calleeResult =
672 * CompositeLattice.compare(calleeLoc1, calleeLoc2, true,
673 * generateErrorMessage(md.getClassDesc(), min));
675 * if (calleeResult == ComparisonResult.GREATER && callerResult !=
676 * ComparisonResult.GREATER) { // If calleeLoc1 is higher than calleeLoc2 //
677 * then, caller should have same ordering relation in-bet // callerLoc1 &
680 * String paramName1, paramName2;
682 * if (i == 0) { paramName1 = "'THIS'"; } else { paramName1 = "'parameter " +
683 * calleemd.getParamName(i - 1) + "'"; }
685 * if (j == 0) { paramName2 = "'THIS'"; } else { paramName2 = "'parameter " +
686 * calleemd.getParamName(j - 1) + "'"; }
689 * "Caller doesn't respect an ordering relation among method arguments: callee expects that "
690 * + paramName1 + " should be higher than " + paramName2 + " in " + calleemd +
691 * " at " + md.getClassDesc().getSourceFileName() + ":" + min.getNumLine()); }
700 * private CompositeLocation
701 * inferRelationsFromArrayAccessNode(MethodDescriptor md, SymbolTable
702 * nametable, ArrayAccessNode aan, CompositeLocation constraint, boolean
705 * ClassDescriptor cd = md.getClassDesc();
707 * CompositeLocation arrayLoc = inferRelationsFromExpressionNode(md,
708 * nametable, aan.getExpression(), new CompositeLocation(), constraint,
709 * isLHS); // addTypeLocation(aan.getExpression().getType(), arrayLoc);
710 * CompositeLocation indexLoc = inferRelationsFromExpressionNode(md,
711 * nametable, aan.getIndex(), new CompositeLocation(), constraint, isLHS); //
712 * addTypeLocation(aan.getIndex().getType(), indexLoc);
714 * if (isLHS) { if (!CompositeLattice.isGreaterThan(indexLoc, arrayLoc,
715 * generateErrorMessage(cd, aan))) { throw new
716 * Error("Array index value is not higher than array location at " +
717 * generateErrorMessage(cd, aan)); } return arrayLoc; } else {
718 * Set<CompositeLocation> inputGLB = new HashSet<CompositeLocation>();
719 * inputGLB.add(arrayLoc); inputGLB.add(indexLoc); return
720 * CompositeLattice.calculateGLB(inputGLB, generateErrorMessage(cd, aan)); }
724 * private CompositeLocation
725 * inferRelationsFromCreateObjectNode(MethodDescriptor md, SymbolTable
726 * nametable, CreateObjectNode con) {
728 * ClassDescriptor cd = md.getClassDesc();
730 * CompositeLocation compLoc = new CompositeLocation();
731 * compLoc.addLocation(Location.createTopLocation(md)); return compLoc;
735 private VarID inferRelationsFromOpNode(MethodDescriptor md, SymbolTable nametable, OpNode on,
736 VarID flowTo, BlockStatementNode implicitTag) {
738 ClassDescriptor cd = md.getClassDesc();
740 inferRelationsFromExpressionNode(md, nametable, on.getLeft(), flowTo, implicitTag, false);
742 CompositeLocation rightLoc = new CompositeLocation();
743 if (on.getRight() != null) {
744 inferRelationsFromExpressionNode(md, nametable, on.getRight(), flowTo, implicitTag, false);
747 Operation op = on.getOp();
749 switch (op.getOp()) {
751 case Operation.UNARYPLUS:
752 case Operation.UNARYMINUS:
753 case Operation.LOGIC_NOT:
757 case Operation.LOGIC_OR:
758 case Operation.LOGIC_AND:
760 case Operation.BIT_OR:
761 case Operation.BIT_XOR:
762 case Operation.BIT_AND:
763 case Operation.ISAVAILABLE:
764 case Operation.EQUAL:
765 case Operation.NOTEQUAL:
775 case Operation.LEFTSHIFT:
776 case Operation.RIGHTSHIFT:
777 case Operation.URIGHTSHIFT:
782 throw new Error(op.toString());
787 private VarID inferRelationsFromLiteralNode(MethodDescriptor md, SymbolTable nametable,
789 // literal data flow does not matter
794 private VarID inferRelationsFromNameNode(MethodDescriptor md, SymbolTable nametable, NameNode nn,
795 VarID flowTo, BlockStatementNode implicitTag) {
797 NameDescriptor nd = nn.getName();
798 if (nd.getBase() != null) {
800 inferRelationsFromExpressionNode(md, nametable, nn.getExpression(), flowTo, implicitTag,
803 String varname = nd.toString();
804 if (varname.equals("this")) {
806 if (flowTo != null) {
807 rSet.addRelation(new BinaryRelation(var, flowTo));
809 if (implicitTag != null) {
810 implicitFlowSet.add(new ImplicitTuple(var, implicitTag));
816 Descriptor d = (Descriptor) nametable.get(varname);
818 if (d instanceof VarDescriptor) {
820 if (flowTo != null) {
821 rSet.addRelation(new BinaryRelation(var, flowTo));
823 if (implicitTag != null) {
824 implicitFlowSet.add(new ImplicitTuple(var, implicitTag));
826 } else if (d instanceof FieldDescriptor) {
827 FieldDescriptor fd = (FieldDescriptor) d;
831 if (flowTo != null) {
832 rSet.addRelation(new BinaryRelation(var, flowTo));
834 if (implicitTag != null) {
835 implicitFlowSet.add(new ImplicitTuple(var, implicitTag));
841 if (flowTo != null) {
842 rSet.addRelation(new BinaryRelation(var, flowTo));
844 if (implicitTag != null) {
845 implicitFlowSet.add(new ImplicitTuple(var, implicitTag));
851 if (flowTo != null) {
852 rSet.addRelation(new BinaryRelation(var, flowTo));
854 if (implicitTag != null) {
855 implicitFlowSet.add(new ImplicitTuple(var, implicitTag));
859 } else if (d == null) {
861 if (flowTo != null) {
862 rSet.addRelation(new BinaryRelation(var, flowTo));
864 if (implicitTag != null) {
865 implicitFlowSet.add(new ImplicitTuple(var, implicitTag));
875 * private CompositeLocation
876 * inferRelationsFromFieldAccessNode(MethodDescriptor md, SymbolTable
877 * nametable, FieldAccessNode fan, CompositeLocation loc, CompositeLocation
880 * ExpressionNode left = fan.getExpression(); TypeDescriptor ltd =
883 * FieldDescriptor fd = fan.getField();
885 * String varName = null; if (left.kind() == Kind.NameNode) { NameDescriptor
886 * nd = ((NameNode) left).getName(); varName = nd.toString(); }
888 * if (ltd.isClassNameRef() || (varName != null && varName.equals("this"))) {
889 * // using a class name directly or access using this if (fd.isStatic() &&
890 * fd.isFinal()) { loc.addLocation(Location.createTopLocation(md)); return
893 * loc = inferRelationsFromExpressionNode(md, nametable, left, loc,
894 * constraint, false);
895 * System.out.println("### inferRelationsFromFieldAccessNode=" +
896 * fan.printNode(0)); System.out.println("### left=" + left.printNode(0)); if
897 * (!left.getType().isPrimitive()) { Location fieldLoc = getFieldLocation(fd);
898 * loc.addLocation(fieldLoc); }
902 * private Location getFieldLocation(FieldDescriptor fd) {
904 * System.out.println("### getFieldLocation=" + fd);
905 * System.out.println("### fd.getType().getExtension()=" +
906 * fd.getType().getExtension());
908 * Location fieldLoc = (Location) fd.getType().getExtension();
910 * // handle the case that method annotation checking skips checking field //
911 * declaration if (fieldLoc == null) { fieldLoc =
912 * checkFieldDeclaration(fd.getClassDescriptor(), fd); }
919 private VarID inferRelationsFromAssignmentNode(MethodDescriptor md, SymbolTable nametable,
920 AssignmentNode an, VarID flowTo, BlockStatementNode implicitTag) {
921 ClassDescriptor cd = md.getClassDesc();
922 boolean postinc = true;
924 if (an.getOperation().getBaseOp() == null
925 || (an.getOperation().getBaseOp().getOp() != Operation.POSTINC && an.getOperation()
926 .getBaseOp().getOp() != Operation.POSTDEC))
928 // get ID for leftside
930 inferRelationsFromExpressionNode(md, nametable, an.getDest(), flowTo, implicitTag, true);
933 // recursively add relations from RHS to LHS
934 inferRelationsFromExpressionNode(md, nametable, an.getSrc(), destID, null, false);
937 // add relation to self
938 destID = inferRelationsFromExpressionNode(md, nametable, an.getDest(), destID, null, false);
941 // checks if flow to anythin and adds relation
942 if (flowTo != null) {
943 rSet.addRelation(new BinaryRelation(destID, flowTo));
946 // add relations for implicit flow
947 for (ImplicitTuple it : implicitFlowSet) {
948 rSet.addRelation(new BinaryRelation(it.getVar(), destID));