1 package Analysis.SSJava;
3 import java.util.HashSet;
4 import java.util.Hashtable;
5 import java.util.Iterator;
8 import IR.ClassDescriptor;
9 import IR.MethodDescriptor;
12 import IR.SymbolTable;
14 import IR.Tree.ArrayAccessNode;
15 import IR.Tree.ArrayInitializerNode;
16 import IR.Tree.AssignmentNode;
17 import IR.Tree.BlockExpressionNode;
18 import IR.Tree.BlockNode;
19 import IR.Tree.BlockStatementNode;
20 import IR.Tree.CastNode;
21 import IR.Tree.CreateObjectNode;
22 import IR.Tree.DeclarationNode;
23 import IR.Tree.ExpressionNode;
24 import IR.Tree.FieldAccessNode;
25 import IR.Tree.IfStatementNode;
26 import IR.Tree.InstanceOfNode;
28 import IR.Tree.LoopNode;
29 import IR.Tree.MethodInvokeNode;
30 import IR.Tree.OpNode;
31 import IR.Tree.ReturnNode;
32 import IR.Tree.SubBlockNode;
33 import IR.Tree.SwitchBlockNode;
34 import IR.Tree.SwitchStatementNode;
35 import IR.Tree.TertiaryNode;
38 public class MethodAnnotationCheck {
41 SSJavaAnalysis ssjava;
44 Set<MethodDescriptor> annotatedMDSet;
45 Hashtable<MethodDescriptor, Set<MethodDescriptor>> caller2calleeSet;
47 public MethodAnnotationCheck(SSJavaAnalysis ssjava, State state, TypeUtil tu) {
51 caller2calleeSet = new Hashtable<MethodDescriptor, Set<MethodDescriptor>>();
52 annotatedMDSet = new HashSet<MethodDescriptor>();
55 public void methodAnnoatationCheck() {
56 SymbolTable classtable = state.getClassSymbolTable();
57 HashSet toanalyze = new HashSet();
58 toanalyze.addAll(classtable.getValueSet());
59 toanalyze.addAll(state.getTaskSymbolTable().getValueSet());
60 while (!toanalyze.isEmpty()) {
61 Object obj = toanalyze.iterator().next();
62 ClassDescriptor cd = (ClassDescriptor) obj;
65 if (!cd.isInterface()) {
66 for (Iterator method_it = cd.getMethods(); method_it.hasNext();) {
67 MethodDescriptor md = (MethodDescriptor) method_it.next();
68 checkMethodBody(cd, md);
74 for (Iterator iterator = annotatedMDSet.iterator(); iterator.hasNext();) {
75 MethodDescriptor md = (MethodDescriptor) iterator.next();
76 ssjava.addAnnotationRequire(md);
79 Set<Pair> visited = new HashSet<Pair>();
80 Set<MethodDescriptor> tovisit = new HashSet<MethodDescriptor>();
81 tovisit.addAll(annotatedMDSet);
83 while (!tovisit.isEmpty()) {
84 MethodDescriptor callerMD = tovisit.iterator().next();
85 tovisit.remove(callerMD);
87 Set<MethodDescriptor> calleeSet = caller2calleeSet.get(callerMD);
88 if (calleeSet != null) {
89 for (Iterator iterator = calleeSet.iterator(); iterator.hasNext();) {
90 MethodDescriptor calleeMD = (MethodDescriptor) iterator.next();
91 Pair p = new Pair(callerMD, calleeMD);
92 if (!visited.contains(p)) {
95 tovisit.add(calleeMD);
97 Set<MethodDescriptor> possibleCalleeSet =
98 (Set<MethodDescriptor>) ssjava.getCallGraph().getMethods(calleeMD);
100 for (Iterator iterator2 = possibleCalleeSet.iterator(); iterator2.hasNext();) {
101 MethodDescriptor possibleCallee = (MethodDescriptor) iterator2.next();
103 if (!possibleCallee.isAbstract()) {
104 ssjava.addAnnotationRequire(possibleCallee);
105 tovisit.add(possibleCallee);
117 public void methodAnnoataionInheritanceCheck() {
118 // check If a method is annotated, any method that overrides it should
121 Set<MethodDescriptor> tovisit = new HashSet<MethodDescriptor>();
122 tovisit.addAll(ssjava.getAnnotationRequireSet());
124 while (!tovisit.isEmpty()) {
125 MethodDescriptor md = tovisit.iterator().next();
128 ClassDescriptor cd = md.getClassDesc();
130 Set subClassSet = tu.getSubClasses(cd);
131 if (subClassSet != null) {
132 for (Iterator iterator2 = subClassSet.iterator(); iterator2.hasNext();) {
133 ClassDescriptor subCD = (ClassDescriptor) iterator2.next();
134 Set possiblematches = subCD.getMethodTable().getSet(md.getSymbol());
135 for (Iterator methodit = possiblematches.iterator(); methodit.hasNext();) {
136 MethodDescriptor matchmd = (MethodDescriptor) methodit.next();
137 if (md.matches(matchmd)) {
138 if (matchmd.getClassDesc().equals(subCD)) {
139 ssjava.addAnnotationRequire(matchmd);
146 // need to check super classess if the current method is inherited from
147 // them, all of ancestor method should be annoated
148 ClassDescriptor currentCd = cd;
149 ClassDescriptor superCd = tu.getSuper(currentCd);
150 while (!superCd.getSymbol().equals("Object")) {
151 Set possiblematches = superCd.getMethodTable().getSet(md.getSymbol());
152 for (Iterator methodit = possiblematches.iterator(); methodit.hasNext();) {
153 MethodDescriptor matchmd = (MethodDescriptor) methodit.next();
154 if (md.matches(matchmd)) {
155 ssjava.addAnnotationRequire(matchmd);
159 superCd = tu.getSuper(currentCd);
162 Set<ClassDescriptor> superIFSet = tu.getSuperIFs(cd);
163 for (Iterator iterator = superIFSet.iterator(); iterator.hasNext();) {
164 ClassDescriptor parentInterface = (ClassDescriptor) iterator.next();
165 Set possiblematches = parentInterface.getMethodTable().getSet(md.getSymbol());
166 for (Iterator methodit = possiblematches.iterator(); methodit.hasNext();) {
167 MethodDescriptor matchmd = (MethodDescriptor) methodit.next();
168 if (md.matches(matchmd)) {
169 ssjava.addAnnotationRequire(matchmd);
178 private void checkMethodBody(ClassDescriptor cd, MethodDescriptor md) {
179 BlockNode bn = state.getMethodBody(md);
180 checkBlockNode(md, md.getParameterTable(), bn, false);
183 private void checkBlockNode(MethodDescriptor md, SymbolTable nametable, BlockNode bn, boolean flag) {
184 bn.getVarTable().setParent(nametable);
185 String label = bn.getLabel();
186 boolean isSSJavaLoop = flag;
187 if (label != null && label.equals(ssjava.SSJAVA)) {
189 throw new Error("Only outermost loop can be the self-stabilizing loop.");
191 annotatedMDSet.add(md);
196 for (int i = 0; i < bn.size(); i++) {
197 BlockStatementNode bsn = bn.get(i);
198 checkBlockStatementNode(md, bn.getVarTable(), bsn, isSSJavaLoop);
203 private void checkBlockStatementNode(MethodDescriptor md, SymbolTable nametable,
204 BlockStatementNode bsn, boolean flag) {
206 switch (bsn.kind()) {
207 case Kind.SubBlockNode:
208 checkSubBlockNode(md, nametable, (SubBlockNode) bsn, flag);
211 case Kind.BlockExpressionNode:
212 checkBlockExpressionNode(md, nametable, (BlockExpressionNode) bsn, flag);
215 case Kind.DeclarationNode:
216 checkDeclarationNode(md, nametable, (DeclarationNode) bsn, flag);
219 case Kind.IfStatementNode:
220 checkIfStatementNode(md, nametable, (IfStatementNode) bsn, flag);
224 checkLoopNode(md, nametable, (LoopNode) bsn, flag);
227 case Kind.ReturnNode:
228 checkReturnNode(md, nametable, (ReturnNode) bsn, flag);
231 case Kind.SwitchStatementNode:
232 checkSwitchStatementNode(md, nametable, (SwitchStatementNode) bsn, flag);
238 private void checkSwitchStatementNode(MethodDescriptor md, SymbolTable nametable,
239 SwitchStatementNode ssn, boolean flag) {
241 checkExpressionNode(md, nametable, ssn.getCondition(), flag);
243 BlockNode sbn = ssn.getSwitchBody();
244 for (int i = 0; i < sbn.size(); i++) {
245 checkBlockNode(md, nametable, ((SwitchBlockNode) sbn.get(i)).getSwitchBlockStatement(), flag);
250 private void checkDeclarationNode(MethodDescriptor md, SymbolTable nametable, DeclarationNode dn,
252 if (dn.getExpression() != null) {
253 checkExpressionNode(md, nametable, dn.getExpression(), flag);
257 private void checkReturnNode(MethodDescriptor md, SymbolTable nametable, ReturnNode rn,
259 if (rn.getReturnExpression() != null) {
260 if (md.getReturnType() != null) {
261 checkExpressionNode(md, nametable, rn.getReturnExpression(), flag);
266 private void checkLoopNode(MethodDescriptor md, SymbolTable nametable, LoopNode ln, boolean flag) {
267 if (ln.getType() == LoopNode.WHILELOOP || ln.getType() == LoopNode.DOWHILELOOP) {
268 checkExpressionNode(md, nametable, ln.getCondition(), flag);
269 checkBlockNode(md, nametable, ln.getBody(), flag);
272 /* Link in the initializer naming environment */
273 BlockNode bn = ln.getInitializer();
274 bn.getVarTable().setParent(nametable);
275 for (int i = 0; i < bn.size(); i++) {
276 BlockStatementNode bsn = bn.get(i);
277 checkBlockStatementNode(md, bn.getVarTable(), bsn, flag);
279 // check the condition
280 checkExpressionNode(md, bn.getVarTable(), ln.getCondition(), flag);
281 checkBlockNode(md, bn.getVarTable(), ln.getBody(), flag);
282 checkBlockNode(md, bn.getVarTable(), ln.getUpdate(), flag);
286 private void checkIfStatementNode(MethodDescriptor md, SymbolTable nametable,
287 IfStatementNode isn, boolean flag) {
288 checkExpressionNode(md, nametable, isn.getCondition(), flag);
289 checkBlockNode(md, nametable, isn.getTrueBlock(), flag);
290 if (isn.getFalseBlock() != null) {
291 checkBlockNode(md, nametable, isn.getFalseBlock(), flag);
295 private void checkSubBlockNode(MethodDescriptor md, SymbolTable nametable, SubBlockNode sbn,
297 checkBlockNode(md, nametable.getParent(), sbn.getBlockNode(), flag);
300 private void checkBlockExpressionNode(MethodDescriptor md, SymbolTable nametable,
301 BlockExpressionNode ben, boolean flag) {
302 checkExpressionNode(md, nametable, ben.getExpression(), flag);
305 private void checkExpressionNode(MethodDescriptor md, SymbolTable nametable, ExpressionNode en,
308 case Kind.AssignmentNode:
309 checkAssignmentNode(md, nametable, (AssignmentNode) en, flag);
313 checkCastNode(md, nametable, (CastNode) en, flag);
316 case Kind.CreateObjectNode:
317 checkCreateObjectNode(md, nametable, (CreateObjectNode) en, flag);
320 case Kind.FieldAccessNode:
321 checkFieldAccessNode(md, nametable, (FieldAccessNode) en, flag);
324 case Kind.ArrayAccessNode:
325 checkArrayAccessNode(md, nametable, (ArrayAccessNode) en, flag);
328 // case Kind.LiteralNode:
329 // checkLiteralNode(md, nametable, (LiteralNode) en, flag);
332 case Kind.MethodInvokeNode:
333 checkMethodInvokeNode(md, nametable, (MethodInvokeNode) en, flag);
336 // case Kind.NameNode:
337 // checkNameNode(md, nametable, (NameNode) en, flag);
341 checkOpNode(md, nametable, (OpNode) en, flag);
344 // case Kind.OffsetNode:
345 // checkOffsetNode(md, nametable, (OffsetNode) en, flag);
348 case Kind.TertiaryNode:
349 checkTertiaryNode(md, nametable, (TertiaryNode) en, flag);
352 case Kind.InstanceOfNode:
353 checkInstanceOfNode(md, nametable, (InstanceOfNode) en, flag);
356 case Kind.ArrayInitializerNode:
357 checkArrayInitializerNode(md, nametable, (ArrayInitializerNode) en, flag);
360 // case Kind.ClassTypeNode:
361 // checkClassTypeNode(md, nametable, (ClassTypeNode) en, flag);
366 private void checkArrayInitializerNode(MethodDescriptor md, SymbolTable nametable,
367 ArrayInitializerNode ain, boolean flag) {
369 for (int i = 0; i < ain.numVarInitializers(); ++i) {
370 checkExpressionNode(md, nametable, ain.getVarInitializer(i), flag);
375 private void checkInstanceOfNode(MethodDescriptor md, SymbolTable nametable, InstanceOfNode tn,
377 checkExpressionNode(md, nametable, tn.getExpr(), flag);
380 private void checkTertiaryNode(MethodDescriptor md, SymbolTable nametable, TertiaryNode tn,
382 checkExpressionNode(md, nametable, tn.getCond(), flag);
383 checkExpressionNode(md, nametable, tn.getTrueExpr(), flag);
384 checkExpressionNode(md, nametable, tn.getFalseExpr(), flag);
387 private void checkOpNode(MethodDescriptor md, SymbolTable nametable, OpNode on, boolean flag) {
389 checkExpressionNode(md, nametable, on.getLeft(), flag);
390 if (on.getRight() != null) {
391 checkExpressionNode(md, nametable, on.getRight(), flag);
396 private void checkMethodInvokeNode(MethodDescriptor md, SymbolTable nametable,
397 MethodInvokeNode min, boolean flag) {
398 for (int i = 0; i < min.numArgs(); i++) {
399 ExpressionNode en = min.getArg(i);
400 checkExpressionNode(md, nametable, en, flag);
403 if (min.getExpression() != null) {
404 checkExpressionNode(md, nametable, min.getExpression(), flag);
408 annotatedMDSet.add(min.getMethod());
411 Set<MethodDescriptor> mdSet = caller2calleeSet.get(md);
413 mdSet = new HashSet<MethodDescriptor>();
414 caller2calleeSet.put(md, mdSet);
416 mdSet.add(min.getMethod());
420 private void checkArrayAccessNode(MethodDescriptor md, SymbolTable nametable,
421 ArrayAccessNode aan, boolean flag) {
423 ExpressionNode left = aan.getExpression();
424 checkExpressionNode(md, nametable, left, flag);
425 checkExpressionNode(md, nametable, aan.getIndex(), flag);
429 private void checkFieldAccessNode(MethodDescriptor md, SymbolTable nametable,
430 FieldAccessNode fan, boolean flag) {
431 ExpressionNode left = fan.getExpression();
432 checkExpressionNode(md, nametable, left, flag);
435 private void checkCreateObjectNode(MethodDescriptor md, SymbolTable nametable,
436 CreateObjectNode con, boolean flag) {
438 for (int i = 0; i < con.numArgs(); i++) {
439 ExpressionNode en = con.getArg(i);
440 checkExpressionNode(md, nametable, en, flag);
445 private void checkCastNode(MethodDescriptor md, SymbolTable nametable, CastNode cn, boolean flag) {
446 ExpressionNode en = cn.getExpression();
447 checkExpressionNode(md, nametable, en, flag);
450 private void checkAssignmentNode(MethodDescriptor md, SymbolTable nametable, AssignmentNode an,
452 boolean postinc = true;
454 if (an.getOperation().getBaseOp() == null
455 || (an.getOperation().getBaseOp().getOp() != Operation.POSTINC && an.getOperation()
456 .getBaseOp().getOp() != Operation.POSTDEC))
460 checkExpressionNode(md, nametable, an.getSrc(), flag);
463 checkExpressionNode(md, nametable, an.getDest(), flag);