1 package Analysis.SSJava;
3 import java.util.HashSet;
4 import java.util.Iterator;
6 import java.util.StringTokenizer;
7 import java.util.Vector;
9 import IR.AnnotationDescriptor;
10 import IR.ClassDescriptor;
11 import IR.FieldDescriptor;
12 import IR.MethodDescriptor;
15 import IR.SymbolTable;
16 import IR.TypeDescriptor;
17 import IR.VarDescriptor;
18 import IR.Tree.AssignmentNode;
19 import IR.Tree.BlockExpressionNode;
20 import IR.Tree.BlockNode;
21 import IR.Tree.BlockStatementNode;
22 import IR.Tree.DeclarationNode;
23 import IR.Tree.ExpressionNode;
25 import IR.Tree.OpNode;
28 public class FlowDownCheck {
33 public FlowDownCheck(State state) {
35 this.toanalyze = new HashSet();
38 public void flowDownCheck() {
40 SymbolTable classtable = state.getClassSymbolTable();
41 toanalyze.addAll(classtable.getValueSet());
42 toanalyze.addAll(state.getTaskSymbolTable().getValueSet());
45 while (!toanalyze.isEmpty()) {
46 Object obj = toanalyze.iterator().next();
47 ClassDescriptor cd = (ClassDescriptor) obj;
49 if (cd.isClassLibrary()) {
50 // doesn't care about class libraries now
56 for (Iterator method_it = cd.getMethods(); method_it.hasNext();) {
57 MethodDescriptor md = (MethodDescriptor) method_it.next();
59 checkMethodBody(cd, md);
61 System.out.println("Error in " + md);
68 public void checkMethodBody(ClassDescriptor cd, MethodDescriptor md) {
69 ClassDescriptor superdesc = cd.getSuperDesc();
70 if (superdesc != null) {
71 Set possiblematches = superdesc.getMethodTable().getSet(md.getSymbol());
72 for (Iterator methodit = possiblematches.iterator(); methodit.hasNext();) {
73 MethodDescriptor matchmd = (MethodDescriptor) methodit.next();
74 if (md.matches(matchmd)) {
75 if (matchmd.getModifiers().isFinal()) {
76 throw new Error("Try to override final method in method:" + md + " declared in " + cd);
81 BlockNode bn = state.getMethodBody(md);
82 checkBlockNode(md, md.getParameterTable(), bn);
85 public void checkBlockNode(MethodDescriptor md, SymbolTable nametable, BlockNode bn) {
86 /* Link in the naming environment */
87 bn.getVarTable().setParent(nametable);
88 for (int i = 0; i < bn.size(); i++) {
89 BlockStatementNode bsn = bn.get(i);
90 checkBlockStatementNode(md, bn.getVarTable(), bsn);
94 public void checkBlockStatementNode(MethodDescriptor md, SymbolTable nametable,
95 BlockStatementNode bsn) {
98 case Kind.BlockExpressionNode:
99 checkBlockExpressionNode(md, nametable, (BlockExpressionNode) bsn);
102 case Kind.DeclarationNode:
103 checkDeclarationNode(md, (DeclarationNode) bsn);
107 * switch (bsn.kind()) { case Kind.BlockExpressionNode:
108 * checkBlockExpressionNode(md, nametable, (BlockExpressionNode) bsn);
111 * case Kind.DeclarationNode: checkDeclarationNode(md, nametable,
112 * (DeclarationNode) bsn); return;
114 * case Kind.TagDeclarationNode: checkTagDeclarationNode(md, nametable,
115 * (TagDeclarationNode) bsn); return;
117 * case Kind.IfStatementNode: checkIfStatementNode(md, nametable,
118 * (IfStatementNode) bsn); return;
120 * case Kind.SwitchStatementNode: checkSwitchStatementNode(md, nametable,
121 * (SwitchStatementNode) bsn); return;
123 * case Kind.LoopNode: checkLoopNode(md, nametable, (LoopNode) bsn); return;
125 * case Kind.ReturnNode: checkReturnNode(md, nametable, (ReturnNode) bsn);
128 * case Kind.TaskExitNode: checkTaskExitNode(md, nametable, (TaskExitNode)
131 * case Kind.SubBlockNode: checkSubBlockNode(md, nametable, (SubBlockNode)
134 * case Kind.AtomicNode: checkAtomicNode(md, nametable, (AtomicNode) bsn);
137 * case Kind.SynchronizedNode: checkSynchronizedNode(md, nametable,
138 * (SynchronizedNode) bsn); return;
140 * case Kind.ContinueBreakNode: checkContinueBreakNode(md, nametable,
141 * (ContinueBreakNode) bsn); return;
143 * case Kind.SESENode: case Kind.GenReachNode: // do nothing, no semantic
144 * check for SESEs return; }
146 // throw new Error();
149 void checkBlockExpressionNode(MethodDescriptor md, SymbolTable nametable, BlockExpressionNode ben) {
150 checkExpressionNode(md, nametable, ben.getExpression(), null);
153 void checkExpressionNode(MethodDescriptor md, SymbolTable nametable, ExpressionNode en,
157 case Kind.AssignmentNode:
158 checkAssignmentNode(md, nametable, (AssignmentNode) en, td);
162 checkOpNode(md, nametable, (OpNode) en, td);
166 * switch(en.kind()) { case Kind.AssignmentNode:
167 * checkAssignmentNode(md,nametable,(AssignmentNode)en,td); return;
169 * case Kind.CastNode: checkCastNode(md,nametable,(CastNode)en,td); return;
171 * case Kind.CreateObjectNode:
172 * checkCreateObjectNode(md,nametable,(CreateObjectNode)en,td); return;
174 * case Kind.FieldAccessNode:
175 * checkFieldAccessNode(md,nametable,(FieldAccessNode)en,td); return;
177 * case Kind.ArrayAccessNode:
178 * checkArrayAccessNode(md,nametable,(ArrayAccessNode)en,td); return;
180 * case Kind.LiteralNode: checkLiteralNode(md,nametable,(LiteralNode)en,td);
183 * case Kind.MethodInvokeNode:
184 * checkMethodInvokeNode(md,nametable,(MethodInvokeNode)en,td); return;
186 * case Kind.NameNode: checkNameNode(md,nametable,(NameNode)en,td); return;
188 * case Kind.OpNode: checkOpNode(md,nametable,(OpNode)en,td); return;
190 * case Kind.OffsetNode: checkOffsetNode(md, nametable, (OffsetNode)en, td);
193 * case Kind.TertiaryNode: checkTertiaryNode(md, nametable,
194 * (TertiaryNode)en, td); return;
196 * case Kind.InstanceOfNode: checkInstanceOfNode(md, nametable,
197 * (InstanceOfNode) en, td); return;
199 * case Kind.ArrayInitializerNode: checkArrayInitializerNode(md, nametable,
200 * (ArrayInitializerNode) en, td); return;
202 * case Kind.ClassTypeNode: checkClassTypeNode(md, nametable,
203 * (ClassTypeNode) en, td); return; }
207 void checkOpNode(MethodDescriptor md, SymbolTable nametable, OpNode on, TypeDescriptor td) {
209 Lattice<String> locOrder = (Lattice<String>) state.getCd2LocationOrder().get(md.getClassDesc());
211 checkExpressionNode(md, nametable, on.getLeft(), null);
212 if (on.getRight() != null)
213 checkExpressionNode(md, nametable, on.getRight(), null);
215 TypeDescriptor ltd = on.getLeft().getType();
216 TypeDescriptor rtd = on.getRight() != null ? on.getRight().getType() : null;
218 if (ltd.getAnnotationMarkers().size() == 0) {
221 // ltd.addAnnotationMarker(new AnnotationDescriptor(Lattice.TOP));
223 if (rtd != null && rtd.getAnnotationMarkers().size() == 0) {
226 // rtd.addAnnotationMarker(new AnnotationDescriptor(Lattice.TOP));
229 System.out.println("checking op node");
230 System.out.println("td=" + td);
231 System.out.println("ltd=" + ltd);
232 System.out.println("rtd=" + rtd);
234 Operation op = on.getOp();
236 switch (op.getOp()) {
238 case Operation.UNARYPLUS:
239 case Operation.UNARYMINUS:
240 case Operation.LOGIC_NOT:
242 on.setType(new TypeDescriptor(TypeDescriptor.BOOLEAN));
245 case Operation.LOGIC_OR:
246 case Operation.LOGIC_AND:
248 case Operation.BIT_OR:
249 case Operation.BIT_XOR:
250 case Operation.BIT_AND:
251 case Operation.ISAVAILABLE:
252 case Operation.EQUAL:
253 case Operation.NOTEQUAL:
263 case Operation.LEFTSHIFT:
264 case Operation.RIGHTSHIFT:
265 case Operation.URIGHTSHIFT:
267 Set<String> operandSet = new HashSet<String>();
268 String leftLoc = ltd.getAnnotationMarkers().get(0).getMarker();
269 String rightLoc = rtd.getAnnotationMarkers().get(0).getMarker();
271 operandSet.add(leftLoc);
272 operandSet.add(rightLoc);
275 // String glbLoc = locOrder.getGLB(operandSet);
276 // on.getType().addAnnotationMarker(new AnnotationDescriptor(glbLoc));
277 // System.out.println(glbLoc + "<-" + leftLoc + " " + rightLoc);
282 throw new Error(op.toString());
286 String lhsLoc = td.getAnnotationMarkers().get(0).getMarker();
287 if (locOrder.isGreaterThan(lhsLoc, on.getType().getAnnotationMarkers().get(0).getMarker())) {
288 throw new Error("The location of LHS is higher than RHS: " + on.printNode(0));
294 void checkAssignmentNode(MethodDescriptor md, SymbolTable nametable, AssignmentNode an,
297 boolean postinc = true;
298 if (an.getOperation().getBaseOp() == null
299 || (an.getOperation().getBaseOp().getOp() != Operation.POSTINC && an.getOperation()
300 .getBaseOp().getOp() != Operation.POSTDEC))
303 checkExpressionNode(md, nametable, an.getSrc(), td);
305 ClassDescriptor cd = md.getClassDesc();
306 Lattice<String> locOrder = (Lattice<String>) state.getCd2LocationOrder().get(cd);
308 System.out.println("an=" + an.printNode(0));
309 String destLocation = an.getDest().getType().getAnnotationMarkers().elementAt(0).getMarker();
310 String srcLocation = an.getSrc().getType().getAnnotationMarkers().elementAt(0).getMarker();
312 if (!locOrder.isGreaterThan(srcLocation, destLocation)) {
313 throw new Error("The value flow from " + srcLocation + " to " + destLocation
314 + " does not respect location hierarchy.");
319 void checkDeclarationNode(MethodDescriptor md, DeclarationNode dn) {
321 ClassDescriptor cd = md.getClassDesc();
322 VarDescriptor vd = dn.getVarDescriptor();
323 Vector<AnnotationDescriptor> annotationVec = vd.getType().getAnnotationMarkers();
325 // currently enforce every variable to have corresponding location
326 if (annotationVec.size() == 0) {
327 throw new Error("Location is not assigned to variable " + vd.getSymbol() + " in the method "
328 + md.getSymbol() + " of the class " + cd.getSymbol());
331 if (annotationVec.size() > 1) {
332 // variable can have at most one location
333 throw new Error(vd.getSymbol() + " has more than one location.");
336 AnnotationDescriptor ad = annotationVec.elementAt(0);
338 if (ad.getType() == AnnotationDescriptor.MARKER_ANNOTATION) {
340 // check if location is defined
341 String locationID = ad.getMarker();
342 Lattice<String> lattice = (Lattice<String>) state.getCd2LocationOrder().get(cd);
345 if (lattice == null || (!lattice.containsKey(locationID))) {
346 throw new Error("Location " + locationID
347 + " is not defined in the location hierarchy of class " + cd.getSymbol() + ".");
350 } else if (ad.getType() == AnnotationDescriptor.SINGLE_ANNOTATION) {
351 if (ad.getMarker().equals(SSJavaAnalysis.DELTA)) {
353 if (ad.getData().length() == 0) {
354 throw new Error("Delta function of " + vd.getSymbol() + " does not have any locations: "
355 + cd.getSymbol() + ".");
358 StringTokenizer token = new StringTokenizer(ad.getData(), ",");
359 while (token.hasMoreTokens()) {
360 String deltaOperand = token.nextToken();
369 private void checkClass(ClassDescriptor cd) {
370 // Check to see that fields are okay
371 for (Iterator field_it = cd.getFields(); field_it.hasNext();) {
372 FieldDescriptor fd = (FieldDescriptor) field_it.next();
373 checkFieldDeclaration(cd, fd);
376 // Check to see that methods respects ss property
377 for (Iterator method_it = cd.getMethods(); method_it.hasNext();) {
378 MethodDescriptor md = (MethodDescriptor) method_it.next();
379 checkMethodDeclaration(cd, md);
383 private void checkMethodDeclaration(ClassDescriptor cd, MethodDescriptor md) {
387 private void checkFieldDeclaration(ClassDescriptor cd, FieldDescriptor fd) {
389 Vector<AnnotationDescriptor> annotationVec = fd.getType().getAnnotationMarkers();
391 // currently enforce every variable to have corresponding location
392 if (annotationVec.size() == 0) {
393 throw new Error("Location is not assigned to the field " + fd.getSymbol() + " of the class "
397 if (annotationVec.size() > 1) {
398 // variable can have at most one location
399 throw new Error("Field " + fd.getSymbol() + " of class " + cd
400 + " has more than one location.");
403 // check if location is defined
404 AnnotationDescriptor ad = annotationVec.elementAt(0);
405 if (ad.getType() == AnnotationDescriptor.MARKER_ANNOTATION) {
406 String locationID = annotationVec.elementAt(0).getMarker();
407 Lattice<String> lattice = (Lattice<String>) state.getCd2LocationOrder().get(cd);
410 if (lattice == null || (!lattice.containsKey(locationID))) {
411 throw new Error("Location " + locationID
412 + " is not defined in the location hierarchy of class " + cd.getSymbol() + ".");
414 } else if (ad.getType() == AnnotationDescriptor.SINGLE_ANNOTATION) {
415 if (ad.getMarker().equals(SSJavaAnalysis.DELTA)) {
417 if (ad.getData().length() == 0) {
418 throw new Error("Delta function of " + fd.getSymbol() + " does not have any locations: "
419 + cd.getSymbol() + ".");
422 StringTokenizer token = new StringTokenizer(ad.getData(), ",");
423 while (token.hasMoreTokens()) {
424 String deltaOperand = token.nextToken();
425 // TODO: set delta operand to corresponding type descriptor