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.ArrayAccessNode;
25 import IR.Tree.AssignmentNode;
26 import IR.Tree.BlockExpressionNode;
27 import IR.Tree.BlockNode;
28 import IR.Tree.BlockStatementNode;
29 import IR.Tree.CastNode;
30 import IR.Tree.DeclarationNode;
31 import IR.Tree.ExpressionNode;
32 import IR.Tree.IfStatementNode;
34 import IR.Tree.LiteralNode;
35 import IR.Tree.LoopNode;
36 import IR.Tree.NameNode;
37 import IR.Tree.OpNode;
38 import IR.Tree.ReturnNode;
39 import IR.Tree.SubBlockNode;
40 import IR.Tree.SwitchStatementNode;
41 import IR.Tree.SwitchBlockNode;
43 public class SSJavaInferenceEngine {
46 static SSJavaAnalysis ssjava;
48 Set<ClassDescriptor> toanalyze;
49 List<ClassDescriptor> toanalyzeList;
51 Set<MethodDescriptor> toanalyzeMethod;
52 List<MethodDescriptor> toanalyzeMethodList;
54 // mapping from 'descriptor' to 'composite location'
55 Hashtable<Descriptor, CompositeLocation> d2loc;
57 Hashtable<MethodDescriptor, CompositeLocation> md2ReturnLoc;
58 Hashtable<MethodDescriptor, ReturnLocGenerator> md2ReturnLocGen;
60 // mapping from 'locID' to 'class descriptor'
61 Hashtable<String, ClassDescriptor> fieldLocName2cd;
63 private Set<ImplicitTuple> implicitFlowSet; /*
65 * hashtable<ExpressionNode
68 private RelationSet rSet;
70 boolean deterministic = true;
72 public SSJavaInferenceEngine(SSJavaAnalysis ssjava, State state) {
76 this.toanalyzeList = new ArrayList<ClassDescriptor>();
78 this.toanalyze = new HashSet<ClassDescriptor>();
81 this.toanalyzeMethodList = new ArrayList<MethodDescriptor>();
83 this.toanalyzeMethod = new HashSet<MethodDescriptor>();
85 this.d2loc = new Hashtable<Descriptor, CompositeLocation>();
86 this.fieldLocName2cd = new Hashtable<String, ClassDescriptor>();
87 this.md2ReturnLoc = new Hashtable<MethodDescriptor, CompositeLocation>();
88 this.md2ReturnLocGen = new Hashtable<MethodDescriptor, ReturnLocGenerator>();
89 this.implicitFlowSet = new HashSet<ImplicitTuple>();
90 this.rSet = new RelationSet();
95 // construct mapping from the location name to the class descriptor
96 // assume that the location name is unique through the whole program
98 Set<ClassDescriptor> cdSet = ssjava.getCd2lattice().keySet();
99 for (Iterator iterator = cdSet.iterator(); iterator.hasNext();) {
100 ClassDescriptor cd = (ClassDescriptor) iterator.next();
101 SSJavaLattice<String> lattice = ssjava.getCd2lattice().get(cd);
102 Set<String> fieldLocNameSet = lattice.getKeySet();
104 for (Iterator iterator2 = fieldLocNameSet.iterator(); iterator2.hasNext();) {
105 String fieldLocName = (String) iterator2.next();
106 fieldLocName2cd.put(fieldLocName, cd);
113 public boolean toAnalyzeIsEmpty() {
115 return toanalyzeList.isEmpty();
117 return toanalyze.isEmpty();
121 public ClassDescriptor toAnalyzeNext() {
123 return toanalyzeList.remove(0);
125 ClassDescriptor cd = toanalyze.iterator().next();
126 toanalyze.remove(cd);
131 public void setupToAnalyze() {
132 SymbolTable classtable = state.getClassSymbolTable();
134 toanalyzeList.clear();
135 toanalyzeList.addAll(classtable.getValueSet());
136 Collections.sort(toanalyzeList, new Comparator<ClassDescriptor>() {
137 public int compare(ClassDescriptor o1, ClassDescriptor o2) {
138 return o1.getClassName().compareTo(o2.getClassName());
143 toanalyze.addAll(classtable.getValueSet());
147 public void setupToAnalazeMethod(ClassDescriptor cd) {
149 SymbolTable methodtable = cd.getMethodTable();
151 toanalyzeMethodList.clear();
152 toanalyzeMethodList.addAll(methodtable.getValueSet());
153 Collections.sort(toanalyzeMethodList, new Comparator<MethodDescriptor>() {
154 public int compare(MethodDescriptor o1, MethodDescriptor o2) {
155 return o1.getSymbol().compareTo(o2.getSymbol());
159 toanalyzeMethod.clear();
160 toanalyzeMethod.addAll(methodtable.getValueSet());
164 public boolean toAnalyzeMethodIsEmpty() {
166 return toanalyzeMethodList.isEmpty();
168 return toanalyzeMethod.isEmpty();
172 public MethodDescriptor toAnalyzeMethodNext() {
174 return toanalyzeMethodList.remove(0);
176 MethodDescriptor md = toanalyzeMethod.iterator().next();
177 toanalyzeMethod.remove(md);
182 public void inference() {
183 FileWriter latticeFile;
184 PrintWriter latticeOut;
187 while (!toAnalyzeIsEmpty()) {
188 ClassDescriptor cd = toAnalyzeNext();
190 latticeFile = new FileWriter(cd.getClassName() + ".lat");
191 } catch (IOException e) {
192 System.out.println("File Fail");
195 latticeOut = new PrintWriter(latticeFile);
196 if (ssjava.needToBeAnnoated(cd)) {
197 setupToAnalazeMethod(cd);
198 while (!toAnalyzeMethodIsEmpty()) {
199 MethodDescriptor md = toAnalyzeMethodNext();
200 if (ssjava.needTobeAnnotated(md)) {
201 inferRelationsFromBlockNode(md, md.getParameterTable(), state.getMethodBody(md));
202 latticeOut.println(md.getClassMethodName() + "\n");
203 latticeOut.println(rSet.toString());
204 rSet = new RelationSet();
213 private void inferRelationsFromBlockNode(MethodDescriptor md, SymbolTable nametable, BlockNode bn) {
215 bn.getVarTable().setParent(nametable);
216 for (int i = 0; i < bn.size(); i++) {
217 BlockStatementNode bsn = bn.get(i);
218 inferRelationsFromBlockStatementNode(md, bn.getVarTable(), bsn);
223 private void inferRelationsFromBlockStatementNode(MethodDescriptor md, SymbolTable nametable,
224 BlockStatementNode bsn) {
226 switch (bsn.kind()) {
227 case Kind.BlockExpressionNode:
228 inferRelationsFromBlockExpressionNode(md, nametable, (BlockExpressionNode) bsn);
231 case Kind.DeclarationNode:
232 inferRelationsFromDeclarationNode(md, nametable, (DeclarationNode) bsn);
235 case Kind.IfStatementNode:
236 inferRelationsFromIfStatementNode(md, nametable, (IfStatementNode) bsn);
240 inferRelationsFromLoopNode(md, nametable, (LoopNode) bsn);
243 case Kind.ReturnNode:
244 inferRelationsFromReturnNode(md, nametable, (ReturnNode) bsn);
247 case Kind.SubBlockNode:
248 inferRelationsFromSubBlockNode(md, nametable, (SubBlockNode) bsn);
251 case Kind.SwitchStatementNode:
252 inferRelationsFromSwitchStatementNode(md, nametable, (SwitchStatementNode) bsn);
256 System.out.println(bsn.kind() + " not handled...");
261 private void inferRelationsFromSwitchStatementNode(MethodDescriptor md,
262 SymbolTable nametable, SwitchStatementNode ssn) {
264 ClassDescriptor cd = md.getClassDesc();
266 inferRelationsFromExpressionNode(md, nametable, ssn.getCondition(), null, (BlockStatementNode) ssn, false);
267 BlockNode sbn = ssn.getSwitchBody();
269 for (int i = 0; i < sbn.size(); i++) {
270 inferRelationsFromSwitchBlockNode(md, nametable, (SwitchBlockNode) sbn.get(i));
273 for(ImplicitTuple tuple: implicitFlowSet){
274 if(tuple.isFromBranch((BlockStatementNode) ssn)){
275 implicitFlowSet.remove(tuple);
280 private void inferRelationsFromSwitchBlockNode(MethodDescriptor md,
281 SymbolTable nametable, SwitchBlockNode sbn) {
282 inferRelationsFromBlockNode(md, nametable, sbn.getSwitchBlockStatement());
285 private void inferRelationsFromReturnNode(MethodDescriptor md, SymbolTable nametable,
288 ExpressionNode returnExp = rn.getReturnExpression();
291 VarID returnID = new VarID(md);
292 returnID.setReturn();
293 if (returnExp != null) {
294 inferRelationsFromExpressionNode(md, nametable, returnExp, returnID, null, false);
298 private void inferRelationsFromLoopNode(MethodDescriptor md, SymbolTable nametable, LoopNode ln) {
300 ClassDescriptor cd = md.getClassDesc();
301 if (ln.getType() == LoopNode.WHILELOOP || ln.getType() == LoopNode.DOWHILELOOP) {
303 inferRelationsFromExpressionNode(md, nametable, ln.getCondition(), null, ln, false);
305 inferRelationsFromBlockNode(md, nametable, ln.getBody());
307 for (ImplicitTuple tuple : implicitFlowSet) {
308 if (tuple.isFromBranch(ln)) {
309 implicitFlowSet.remove(tuple);
314 // check 'for loop' case
315 BlockNode bn = ln.getInitializer();
316 bn.getVarTable().setParent(nametable);
318 inferRelationsFromBlockNode(md, nametable, bn);
319 inferRelationsFromExpressionNode(md, bn.getVarTable(), ln.getCondition(), null, ln, false);
321 inferRelationsFromBlockNode(md, bn.getVarTable(), ln.getUpdate());
322 inferRelationsFromBlockNode(md, bn.getVarTable(), ln.getBody());
324 for (ImplicitTuple tuple : implicitFlowSet) {
325 if (tuple.isFromBranch(ln)) {
326 implicitFlowSet.remove(tuple);
334 private void inferRelationsFromSubBlockNode(MethodDescriptor md,
335 SymbolTable nametable, SubBlockNode sbn) {
336 inferRelationsFromBlockNode(md, nametable.getParent(), sbn.getBlockNode());
339 private void inferRelationsFromIfStatementNode(MethodDescriptor md, SymbolTable nametable,
340 IfStatementNode isn) {
342 inferRelationsFromExpressionNode(md, nametable, isn.getCondition(), null, isn, false);
344 inferRelationsFromBlockNode(md, nametable, isn.getTrueBlock());
346 if (isn.getFalseBlock() != null) {
347 inferRelationsFromBlockNode(md, nametable, isn.getFalseBlock());
350 for (ImplicitTuple tuple : implicitFlowSet) {
351 if (tuple.isFromBranch(isn)) {
352 implicitFlowSet.remove(tuple);
357 private void inferRelationsFromDeclarationNode(MethodDescriptor md, SymbolTable nametable,
358 DeclarationNode dn) {
361 private void inferRelationsFromBlockExpressionNode(MethodDescriptor md,
362 SymbolTable nametable, BlockExpressionNode ben) {
363 inferRelationsFromExpressionNode(md, nametable, ben.getExpression(), null, null, false);
366 private VarID inferRelationsFromExpressionNode(MethodDescriptor md, SymbolTable nametable,
367 ExpressionNode en, VarID flowTo, BlockStatementNode implicitTag, boolean isLHS) {
372 case Kind.AssignmentNode:
374 inferRelationsFromAssignmentNode(md, nametable, (AssignmentNode) en, flowTo, implicitTag);
377 // case Kind.FieldAccessNode:
379 // inferRelationsFromFieldAccessNode(md, nametable, (FieldAccessNode) en,
384 var = inferRelationsFromNameNode(md, nametable, (NameNode) en, flowTo, implicitTag);
388 var = inferRelationsFromOpNode(md, nametable, (OpNode) en, flowTo, implicitTag);
391 * case Kind.CreateObjectNode: var = inferRelationsFromCreateObjectNode(md,
392 * nametable, (CreateObjectNode) en); break;
394 case Kind.ArrayAccessNode:
395 var = inferRelationsFromArrayAccessNode(md, nametable, (ArrayAccessNode) en, flowTo, implicitTag, isLHS);
398 case Kind.LiteralNode:
399 var = inferRelationsFromLiteralNode(md, nametable, (LiteralNode) en);
402 * case Kind.MethodInvokeNode: var = inferRelationsFromMethodInvokeNode(md,
403 * nametable, (MethodInvokeNode) en, flowTo); break;
405 * case Kind.TertiaryNode: var = inferRelationsFromTertiaryNode(md,
406 * nametable, (TertiaryNode) en); break;
409 var = inferRelationsFromCastNode(md, nametable, (CastNode) en, flowTo, implicitTag);
413 System.out.println("expressionnode not handled...");
417 // addTypeLocation(en.getType(), compLoc);
423 private VarID inferRelationsFromCastNode(MethodDescriptor md,
424 SymbolTable nametable, CastNode cn, VarID flowTo, BlockStatementNode implicitTag) {
426 ExpressionNode en = cn.getExpression();
427 return inferRelationsFromExpressionNode(md, nametable, en, flowTo, implicitTag, false);
431 * private CompositeLocation inferRelationsFromTertiaryNode(MethodDescriptor
432 * md, SymbolTable nametable, TertiaryNode tn, CompositeLocation constraint) {
433 * ClassDescriptor cd = md.getClassDesc();
435 * CompositeLocation condLoc = inferRelationsFromExpressionNode(md, nametable,
436 * tn.getCond(), new CompositeLocation(), constraint, false); //
437 * addLocationType(tn.getCond().getType(), condLoc); CompositeLocation trueLoc
438 * = inferRelationsFromExpressionNode(md, nametable, tn.getTrueExpr(), new
439 * CompositeLocation(), constraint, false); //
440 * addLocationType(tn.getTrueExpr().getType(), trueLoc); CompositeLocation
441 * falseLoc = inferRelationsFromExpressionNode(md, nametable,
442 * tn.getFalseExpr(), new CompositeLocation(), constraint, false); //
443 * addLocationType(tn.getFalseExpr().getType(), falseLoc);
445 * // locations from true/false branches can be TOP when there are only
446 * literal // values // in this case, we don't need to check flow down rule!
448 * // check if condLoc is higher than trueLoc & falseLoc if
449 * (!trueLoc.get(0).isTop() && !CompositeLattice.isGreaterThan(condLoc,
450 * trueLoc, generateErrorMessage(cd, tn))) { throw new Error(
451 * "The location of the condition expression is lower than the true expression at "
452 * + cd.getSourceFileName() + ":" + tn.getCond().getNumLine()); }
454 * if (!falseLoc.get(0).isTop() && !CompositeLattice.isGreaterThan(condLoc,
455 * falseLoc, generateErrorMessage(cd, tn.getCond()))) { throw new Error(
456 * "The location of the condition expression is lower than the true expression at "
457 * + cd.getSourceFileName() + ":" + tn.getCond().getNumLine()); }
459 * // then, return glb of trueLoc & falseLoc Set<CompositeLocation>
460 * glbInputSet = new HashSet<CompositeLocation>(); glbInputSet.add(trueLoc);
461 * glbInputSet.add(falseLoc);
463 * return CompositeLattice.calculateGLB(glbInputSet, generateErrorMessage(cd,
466 * private CompositeLocation
467 * inferRelationsFromMethodInvokeNode(MethodDescriptor md, SymbolTable
468 * nametable, MethodInvokeNode min, CompositeLocation loc, CompositeLocation
471 * CompositeLocation baseLocation = null; if (min.getExpression() != null) {
472 * baseLocation = inferRelationsFromExpressionNode(md, nametable,
473 * min.getExpression(), new CompositeLocation(), constraint, false); } else {
475 * if (min.getMethod().isStatic()) { String globalLocId =
476 * ssjava.getMethodLattice(md).getGlobalLoc(); if (globalLocId == null) {
478 * Error("Method lattice does not define global variable location at " +
479 * generateErrorMessage(md.getClassDesc(), min)); } baseLocation = new
480 * CompositeLocation(new Location(md, globalLocId)); } else { String thisLocId
481 * = ssjava.getMethodLattice(md).getThisLoc(); baseLocation = new
482 * CompositeLocation(new Location(md, thisLocId)); } }
484 * checkCalleeConstraints(md, nametable, min, baseLocation, constraint);
486 * checkCallerArgumentLocationConstraints(md, nametable, min, baseLocation,
489 * if (!min.getMethod().getReturnType().isVoid()) { // If method has a return
490 * value, compute the highest possible return // location in the caller's
491 * perspective CompositeLocation ceilingLoc =
492 * computeCeilingLocationForCaller(md, nametable, min, baseLocation,
493 * constraint); return ceilingLoc; }
495 * return new CompositeLocation();
499 * private void checkCallerArgumentLocationConstraints(MethodDescriptor md,
500 * SymbolTable nametable, MethodInvokeNode min, CompositeLocation
501 * callerBaseLoc, CompositeLocation constraint) { // if parameter location
502 * consists of THIS and FIELD location, // caller should pass an argument that
503 * is comparable to the declared // parameter location // and is not lower
504 * than the declared parameter location in the field // lattice.
506 * MethodDescriptor calleemd = min.getMethod();
508 * List<CompositeLocation> callerArgList = new ArrayList<CompositeLocation>();
509 * List<CompositeLocation> calleeParamList = new
510 * ArrayList<CompositeLocation>();
512 * MethodLattice<String> calleeLattice = ssjava.getMethodLattice(calleemd);
513 * Location calleeThisLoc = new Location(calleemd,
514 * calleeLattice.getThisLoc());
516 * for (int i = 0; i < min.numArgs(); i++) { ExpressionNode en =
517 * min.getArg(i); CompositeLocation callerArgLoc =
518 * inferRelationsFromExpressionNode(md, nametable, en, new
519 * CompositeLocation(), constraint, false); callerArgList.add(callerArgLoc); }
521 * // setup callee params set for (int i = 0; i < calleemd.numParameters();
522 * i++) { VarDescriptor calleevd = (VarDescriptor) calleemd.getParameter(i);
523 * CompositeLocation calleeLoc = d2loc.get(calleevd);
524 * calleeParamList.add(calleeLoc); }
526 * String errorMsg = generateErrorMessage(md.getClassDesc(), min);
528 * System.out.println("checkCallerArgumentLocationConstraints=" +
529 * min.printNode(0)); System.out.println("base location=" + callerBaseLoc);
531 * for (int i = 0; i < calleeParamList.size(); i++) { CompositeLocation
532 * calleeParamLoc = calleeParamList.get(i); if
533 * (calleeParamLoc.get(0).equals(calleeThisLoc) && calleeParamLoc.getSize() >
536 * // callee parameter location has field information CompositeLocation
537 * callerArgLoc = callerArgList.get(i);
539 * CompositeLocation paramLocation = translateCalleeParamLocToCaller(md,
540 * calleeParamLoc, callerBaseLoc, errorMsg);
542 * Set<CompositeLocation> inputGLBSet = new HashSet<CompositeLocation>(); if
543 * (constraint != null) { inputGLBSet.add(callerArgLoc);
544 * inputGLBSet.add(constraint); callerArgLoc =
545 * CompositeLattice.calculateGLB(inputGLBSet,
546 * generateErrorMessage(md.getClassDesc(), min)); }
548 * if (!CompositeLattice.isGreaterThan(callerArgLoc, paramLocation, errorMsg))
549 * { throw new Error("Caller argument '" + min.getArg(i).printNode(0) + " : "
551 * "' should be higher than corresponding callee's parameter : " +
552 * paramLocation + " at " + errorMsg); }
558 * private CompositeLocation translateCalleeParamLocToCaller(MethodDescriptor
559 * md, CompositeLocation calleeParamLoc, CompositeLocation callerBaseLocation,
562 * CompositeLocation translate = new CompositeLocation();
564 * for (int i = 0; i < callerBaseLocation.getSize(); i++) {
565 * translate.addLocation(callerBaseLocation.get(i)); }
567 * for (int i = 1; i < calleeParamLoc.getSize(); i++) {
568 * translate.addLocation(calleeParamLoc.get(i)); }
570 * System.out.println("TRANSLATED=" + translate + " from calleeParamLoc=" +
573 * return translate; }
575 * private CompositeLocation computeCeilingLocationForCaller(MethodDescriptor
576 * md, SymbolTable nametable, MethodInvokeNode min, CompositeLocation
577 * baseLocation, CompositeLocation constraint) { List<CompositeLocation>
578 * argList = new ArrayList<CompositeLocation>();
580 * // by default, method has a THIS parameter argList.add(baseLocation);
582 * for (int i = 0; i < min.numArgs(); i++) { ExpressionNode en =
583 * min.getArg(i); CompositeLocation callerArg =
584 * inferRelationsFromExpressionNode(md, nametable, en, new
585 * CompositeLocation(), constraint, false); argList.add(callerArg); }
587 * System.out.println("\n## computeReturnLocation=" + min.getMethod() +
588 * " argList=" + argList); CompositeLocation compLoc =
589 * md2ReturnLocGen.get(min.getMethod()).computeReturnLocation(argList);
590 * DeltaLocation delta = new DeltaLocation(compLoc, 1);
591 * System.out.println("##computeReturnLocation=" + delta);
597 * private void checkCalleeConstraints(MethodDescriptor md, SymbolTable
598 * nametable, MethodInvokeNode min, CompositeLocation callerBaseLoc,
599 * CompositeLocation constraint) {
601 * System.out.println("checkCalleeConstraints="+min.printNode(0));
603 * MethodDescriptor calleemd = min.getMethod();
605 * MethodLattice<String> calleeLattice = ssjava.getMethodLattice(calleemd);
606 * CompositeLocation calleeThisLoc = new CompositeLocation(new
607 * Location(calleemd, calleeLattice.getThisLoc()));
609 * List<CompositeLocation> callerArgList = new ArrayList<CompositeLocation>();
610 * List<CompositeLocation> calleeParamList = new
611 * ArrayList<CompositeLocation>();
613 * if (min.numArgs() > 0) { // caller needs to guarantee that it passes
614 * arguments in regarding to // callee's hierarchy
616 * // setup caller args set // first, add caller's base(this) location
617 * callerArgList.add(callerBaseLoc); // second, add caller's arguments for
618 * (int i = 0; i < min.numArgs(); i++) { ExpressionNode en = min.getArg(i);
619 * CompositeLocation callerArgLoc = inferRelationsFromExpressionNode(md,
620 * nametable, en, new CompositeLocation(), constraint, false);
621 * callerArgList.add(callerArgLoc); }
623 * // setup callee params set // first, add callee's this location
624 * calleeParamList.add(calleeThisLoc); // second, add callee's parameters for
625 * (int i = 0; i < calleemd.numParameters(); i++) { VarDescriptor calleevd =
626 * (VarDescriptor) calleemd.getParameter(i); CompositeLocation calleeLoc =
627 * d2loc.get(calleevd);
628 * System.out.println("calleevd="+calleevd+" loc="+calleeLoc);
629 * calleeParamList.add(calleeLoc); }
631 * // here, check if ordering relations among caller's args respect //
632 * ordering relations in-between callee's args CHECK: for (int i = 0; i <
633 * calleeParamList.size(); i++) { CompositeLocation calleeLoc1 =
634 * calleeParamList.get(i); CompositeLocation callerLoc1 =
635 * callerArgList.get(i);
637 * for (int j = 0; j < calleeParamList.size(); j++) { if (i != j) {
638 * CompositeLocation calleeLoc2 = calleeParamList.get(j); CompositeLocation
639 * callerLoc2 = callerArgList.get(j);
641 * if (callerLoc1.get(callerLoc1.getSize() - 1).isTop() ||
642 * callerLoc2.get(callerLoc2.getSize() - 1).isTop()) { continue CHECK; }
644 * System.out.println("calleeLoc1="+calleeLoc1);
645 * System.out.println("calleeLoc2="
646 * +calleeLoc2+"calleeParamList="+calleeParamList);
648 * int callerResult = CompositeLattice.compare(callerLoc1, callerLoc2, true,
649 * generateErrorMessage(md.getClassDesc(), min)); int calleeResult =
650 * CompositeLattice.compare(calleeLoc1, calleeLoc2, true,
651 * generateErrorMessage(md.getClassDesc(), min));
653 * if (calleeResult == ComparisonResult.GREATER && callerResult !=
654 * ComparisonResult.GREATER) { // If calleeLoc1 is higher than calleeLoc2 //
655 * then, caller should have same ordering relation in-bet // callerLoc1 &
658 * String paramName1, paramName2;
660 * if (i == 0) { paramName1 = "'THIS'"; } else { paramName1 = "'parameter " +
661 * calleemd.getParamName(i - 1) + "'"; }
663 * if (j == 0) { paramName2 = "'THIS'"; } else { paramName2 = "'parameter " +
664 * calleemd.getParamName(j - 1) + "'"; }
667 * "Caller doesn't respect an ordering relation among method arguments: callee expects that "
668 * + paramName1 + " should be higher than " + paramName2 + " in " + calleemd +
669 * " at " + md.getClassDesc().getSourceFileName() + ":" + min.getNumLine()); }
678 private VarID inferRelationsFromArrayAccessNode(MethodDescriptor md, SymbolTable
679 nametable, ArrayAccessNode aan, VarID flowTo, BlockStatementNode implicitTag, boolean isLHS) {
682 VarID arrayID = inferRelationsFromExpressionNode(md, nametable, aan.getExpression(), flowTo, implicitTag, isLHS);
685 VarID indexID = inferRelationsFromExpressionNode(md, nametable, aan.getIndex(), arrayID, implicitTag, isLHS);
688 VarID indexID = inferRelationsFromExpressionNode(md, nametable, aan.getIndex(), flowTo, implicitTag, isLHS);
694 private CompositeLocation
695 inferRelationsFromCreateObjectNode(MethodDescriptor md, SymbolTable
696 nametable, CreateObjectNode con) {
698 ClassDescriptor cd = md.getClassDesc();
700 CompositeLocation compLoc = new CompositeLocation();
701 compLoc.addLocation(Location.createTopLocation(md)); return compLoc;
705 private VarID inferRelationsFromOpNode(MethodDescriptor md, SymbolTable nametable, OpNode on,
706 VarID flowTo, BlockStatementNode implicitTag) {
709 inferRelationsFromExpressionNode(md, nametable, on.getLeft(), flowTo, implicitTag, false);
711 if (on.getRight() != null) {
712 inferRelationsFromExpressionNode(md, nametable, on.getRight(), flowTo, implicitTag, false);
715 Operation op = on.getOp();
717 switch (op.getOp()) {
719 case Operation.UNARYPLUS:
720 case Operation.UNARYMINUS:
721 case Operation.LOGIC_NOT:
725 case Operation.LOGIC_OR:
726 case Operation.LOGIC_AND:
728 case Operation.BIT_OR:
729 case Operation.BIT_XOR:
730 case Operation.BIT_AND:
731 case Operation.ISAVAILABLE:
732 case Operation.EQUAL:
733 case Operation.NOTEQUAL:
743 case Operation.LEFTSHIFT:
744 case Operation.RIGHTSHIFT:
745 case Operation.URIGHTSHIFT:
750 throw new Error(op.toString());
755 private VarID inferRelationsFromLiteralNode(MethodDescriptor md, SymbolTable nametable,
757 // literal data flow does not matter
762 private VarID inferRelationsFromNameNode(MethodDescriptor md, SymbolTable nametable, NameNode nn,
763 VarID flowTo, BlockStatementNode implicitTag) {
765 NameDescriptor nd = nn.getName();
766 if (nd.getBase() != null) {
768 inferRelationsFromExpressionNode(md, nametable, nn.getExpression(), flowTo, implicitTag,
771 String varname = nd.toString();
772 if (varname.equals("this")) {
774 if (flowTo != null) {
775 rSet.addRelation(new BinaryRelation(var, flowTo));
777 if (implicitTag != null) {
778 implicitFlowSet.add(new ImplicitTuple(var, implicitTag));
784 Descriptor d = (Descriptor) nametable.get(varname);
786 if (d instanceof VarDescriptor) {
788 if (flowTo != null) {
789 rSet.addRelation(new BinaryRelation(var, flowTo));
791 if (implicitTag != null) {
792 implicitFlowSet.add(new ImplicitTuple(var, implicitTag));
794 } else if (d instanceof FieldDescriptor) {
795 FieldDescriptor fd = (FieldDescriptor) d;
799 if (flowTo != null) {
800 rSet.addRelation(new BinaryRelation(var, flowTo));
802 if (implicitTag != null) {
803 implicitFlowSet.add(new ImplicitTuple(var, implicitTag));
809 if (flowTo != null) {
810 rSet.addRelation(new BinaryRelation(var, flowTo));
812 if (implicitTag != null) {
813 implicitFlowSet.add(new ImplicitTuple(var, implicitTag));
819 if (flowTo != null) {
820 rSet.addRelation(new BinaryRelation(var, flowTo));
822 if (implicitTag != null) {
823 implicitFlowSet.add(new ImplicitTuple(var, implicitTag));
827 } else if (d == null) {
829 if (flowTo != null) {
830 rSet.addRelation(new BinaryRelation(var, flowTo));
832 if (implicitTag != null) {
833 implicitFlowSet.add(new ImplicitTuple(var, implicitTag));
843 * private CompositeLocation
844 * inferRelationsFromFieldAccessNode(MethodDescriptor md, SymbolTable
845 * nametable, FieldAccessNode fan, CompositeLocation loc, CompositeLocation
848 * ExpressionNode left = fan.getExpression(); TypeDescriptor ltd =
851 * FieldDescriptor fd = fan.getField();
853 * String varName = null; if (left.kind() == Kind.NameNode) { NameDescriptor
854 * nd = ((NameNode) left).getName(); varName = nd.toString(); }
856 * if (ltd.isClassNameRef() || (varName != null && varName.equals("this"))) {
857 * // using a class name directly or access using this if (fd.isStatic() &&
858 * fd.isFinal()) { loc.addLocation(Location.createTopLocation(md)); return
861 * loc = inferRelationsFromExpressionNode(md, nametable, left, loc,
862 * constraint, false);
863 * System.out.println("### inferRelationsFromFieldAccessNode=" +
864 * fan.printNode(0)); System.out.println("### left=" + left.printNode(0)); if
865 * (!left.getType().isPrimitive()) { Location fieldLoc = getFieldLocation(fd);
866 * loc.addLocation(fieldLoc); }
870 * private Location getFieldLocation(FieldDescriptor fd) {
872 * System.out.println("### getFieldLocation=" + fd);
873 * System.out.println("### fd.getType().getExtension()=" +
874 * fd.getType().getExtension());
876 * Location fieldLoc = (Location) fd.getType().getExtension();
878 * // handle the case that method annotation checking skips checking field //
879 * declaration if (fieldLoc == null) { fieldLoc =
880 * checkFieldDeclaration(fd.getClassDescriptor(), fd); }
887 private VarID inferRelationsFromAssignmentNode(MethodDescriptor md, SymbolTable nametable,
888 AssignmentNode an, VarID flowTo, BlockStatementNode implicitTag) {
889 ClassDescriptor cd = md.getClassDesc();
890 boolean postinc = true;
892 if (an.getOperation().getBaseOp() == null
893 || (an.getOperation().getBaseOp().getOp() != Operation.POSTINC && an.getOperation()
894 .getBaseOp().getOp() != Operation.POSTDEC))
896 // get ID for leftside
898 inferRelationsFromExpressionNode(md, nametable, an.getDest(), flowTo, implicitTag, true);
901 // recursively add relations from RHS to LHS
902 inferRelationsFromExpressionNode(md, nametable, an.getSrc(), destID, null, false);
905 // add relation to self
906 destID = inferRelationsFromExpressionNode(md, nametable, an.getDest(), destID, null, false);
909 // checks if flow to anythin and adds relation
910 if (flowTo != null) {
911 rSet.addRelation(new BinaryRelation(destID, flowTo));
914 // add relations for implicit flow
915 for (ImplicitTuple it : implicitFlowSet) {
916 rSet.addRelation(new BinaryRelation(it.getVar(), destID));