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.TertiaryNode;
36 public class MethodAnnotationCheck {
39 SSJavaAnalysis ssjava;
42 Set<MethodDescriptor> annotatedMDSet;
43 Hashtable<MethodDescriptor, Set<MethodDescriptor>> caller2calleeSet;
45 public MethodAnnotationCheck(SSJavaAnalysis ssjava, State state, TypeUtil tu) {
49 caller2calleeSet = new Hashtable<MethodDescriptor, Set<MethodDescriptor>>();
50 annotatedMDSet = new HashSet<MethodDescriptor>();
53 public void methodAnnoatationCheck() {
54 SymbolTable classtable = state.getClassSymbolTable();
55 HashSet toanalyze = new HashSet();
56 toanalyze.addAll(classtable.getValueSet());
57 toanalyze.addAll(state.getTaskSymbolTable().getValueSet());
58 while (!toanalyze.isEmpty()) {
59 Object obj = toanalyze.iterator().next();
60 ClassDescriptor cd = (ClassDescriptor) obj;
63 if (!cd.isInterface()) {
64 for (Iterator method_it = cd.getMethods(); method_it.hasNext();) {
65 MethodDescriptor md = (MethodDescriptor) method_it.next();
66 checkMethodBody(cd, md);
72 for (Iterator iterator = annotatedMDSet.iterator(); iterator.hasNext();) {
73 MethodDescriptor md = (MethodDescriptor) iterator.next();
74 ssjava.addAnnotationRequire(md);
77 Set<Pair> visited = new HashSet<Pair>();
78 Set<MethodDescriptor> tovisit = new HashSet<MethodDescriptor>();
79 tovisit.addAll(annotatedMDSet);
81 while (!tovisit.isEmpty()) {
82 MethodDescriptor callerMD = tovisit.iterator().next();
83 tovisit.remove(callerMD);
85 Set<MethodDescriptor> calleeSet = caller2calleeSet.get(callerMD);
86 if (calleeSet != null) {
87 for (Iterator iterator = calleeSet.iterator(); iterator.hasNext();) {
88 MethodDescriptor calleeMD = (MethodDescriptor) iterator.next();
89 Pair p = new Pair(callerMD, calleeMD);
90 if (!visited.contains(p)) {
93 if (calleeMD.getClassDesc().isInterface()) {
94 calleeMD.getClassDesc();
97 tovisit.add(calleeMD);
99 if (calleeMD.isAbstract()) {
100 Set<MethodDescriptor> possibleCalleeSet =
101 (Set<MethodDescriptor>) ssjava.getCallGraph().getMethods(calleeMD);
103 for (Iterator iterator2 = possibleCalleeSet.iterator(); iterator2.hasNext();) {
104 MethodDescriptor possibleCallee = (MethodDescriptor) iterator2.next();
106 if (!possibleCallee.isAbstract()) {
107 ssjava.addAnnotationRequire(possibleCallee);
108 tovisit.add(possibleCallee);
114 ssjava.addAnnotationRequire(calleeMD);
124 public void methodAnnoataionInheritanceCheck() {
125 // check If a method is annotated, any method that overrides it should
128 Set<MethodDescriptor> tovisit = new HashSet<MethodDescriptor>();
129 tovisit.addAll(ssjava.getAnnotationRequireSet());
131 while (!tovisit.isEmpty()) {
132 MethodDescriptor md = tovisit.iterator().next();
135 ClassDescriptor cd = md.getClassDesc();
137 Set subClassSet = tu.getSubClasses(cd);
138 if (subClassSet != null) {
139 for (Iterator iterator2 = subClassSet.iterator(); iterator2.hasNext();) {
140 ClassDescriptor subCD = (ClassDescriptor) iterator2.next();
141 Set possiblematches = subCD.getMethodTable().getSet(md.getSymbol());
142 for (Iterator methodit = possiblematches.iterator(); methodit.hasNext();) {
143 MethodDescriptor matchmd = (MethodDescriptor) methodit.next();
144 if (md.matches(matchmd)) {
145 if (matchmd.getClassDesc().equals(subCD)) {
146 ssjava.addAnnotationRequire(matchmd);
153 // need to check super classess if the current method is inherited from
154 // them, all of ancestor method should be annoated
155 ClassDescriptor currentCd = cd;
156 ClassDescriptor superCd = tu.getSuper(currentCd);
157 while (!superCd.getSymbol().equals("Object")) {
158 Set possiblematches = superCd.getMethodTable().getSet(md.getSymbol());
159 for (Iterator methodit = possiblematches.iterator(); methodit.hasNext();) {
160 MethodDescriptor matchmd = (MethodDescriptor) methodit.next();
161 if (md.matches(matchmd)) {
162 ssjava.addAnnotationRequire(matchmd);
166 superCd = tu.getSuper(currentCd);
169 Set<ClassDescriptor> superIFSet = tu.getSuperIFs(cd);
170 for (Iterator iterator = superIFSet.iterator(); iterator.hasNext();) {
171 ClassDescriptor parentInterface = (ClassDescriptor) iterator.next();
172 Set possiblematches = parentInterface.getMethodTable().getSet(md.getSymbol());
173 for (Iterator methodit = possiblematches.iterator(); methodit.hasNext();) {
174 MethodDescriptor matchmd = (MethodDescriptor) methodit.next();
175 if (md.matches(matchmd)) {
176 ssjava.addAnnotationRequire(matchmd);
185 private void checkMethodBody(ClassDescriptor cd, MethodDescriptor md) {
186 BlockNode bn = state.getMethodBody(md);
187 checkBlockNode(md, md.getParameterTable(), bn, false);
190 private void checkBlockNode(MethodDescriptor md, SymbolTable nametable, BlockNode bn, boolean flag) {
191 bn.getVarTable().setParent(nametable);
192 String label = bn.getLabel();
193 boolean isSSJavaLoop = flag;
194 if (label != null && label.equals(ssjava.SSJAVA)) {
196 throw new Error("Only outermost loop can be the self-stabilizing loop.");
198 annotatedMDSet.add(md);
203 for (int i = 0; i < bn.size(); i++) {
204 BlockStatementNode bsn = bn.get(i);
205 checkBlockStatementNode(md, bn.getVarTable(), bsn, isSSJavaLoop);
210 private void checkBlockStatementNode(MethodDescriptor md, SymbolTable nametable,
211 BlockStatementNode bsn, boolean flag) {
213 switch (bsn.kind()) {
214 case Kind.SubBlockNode:
215 checkSubBlockNode(md, nametable, (SubBlockNode) bsn, flag);
218 case Kind.BlockExpressionNode:
219 checkBlockExpressionNode(md, nametable, (BlockExpressionNode) bsn, flag);
222 case Kind.DeclarationNode:
223 checkDeclarationNode(md, nametable, (DeclarationNode) bsn, flag);
226 case Kind.IfStatementNode:
227 checkIfStatementNode(md, nametable, (IfStatementNode) bsn, flag);
231 checkLoopNode(md, nametable, (LoopNode) bsn, flag);
234 case Kind.ReturnNode:
235 checkReturnNode(md, nametable, (ReturnNode) bsn, flag);
241 private void checkDeclarationNode(MethodDescriptor md, SymbolTable nametable, DeclarationNode dn,
243 if (dn.getExpression() != null) {
244 checkExpressionNode(md, nametable, dn.getExpression(), flag);
248 private void checkReturnNode(MethodDescriptor md, SymbolTable nametable, ReturnNode rn,
250 if (rn.getReturnExpression() != null) {
251 if (md.getReturnType() != null) {
252 checkExpressionNode(md, nametable, rn.getReturnExpression(), flag);
257 private void checkLoopNode(MethodDescriptor md, SymbolTable nametable, LoopNode ln, boolean flag) {
258 if (ln.getType() == LoopNode.WHILELOOP || ln.getType() == LoopNode.DOWHILELOOP) {
259 checkExpressionNode(md, nametable, ln.getCondition(), flag);
260 checkBlockNode(md, nametable, ln.getBody(), flag);
263 /* Link in the initializer naming environment */
264 BlockNode bn = ln.getInitializer();
265 bn.getVarTable().setParent(nametable);
266 for (int i = 0; i < bn.size(); i++) {
267 BlockStatementNode bsn = bn.get(i);
268 checkBlockStatementNode(md, bn.getVarTable(), bsn, flag);
270 // check the condition
271 checkExpressionNode(md, bn.getVarTable(), ln.getCondition(), flag);
272 checkBlockNode(md, bn.getVarTable(), ln.getBody(), flag);
273 checkBlockNode(md, bn.getVarTable(), ln.getUpdate(), flag);
277 private void checkIfStatementNode(MethodDescriptor md, SymbolTable nametable,
278 IfStatementNode isn, boolean flag) {
279 checkExpressionNode(md, nametable, isn.getCondition(), flag);
280 checkBlockNode(md, nametable, isn.getTrueBlock(), flag);
281 if (isn.getFalseBlock() != null) {
282 checkBlockNode(md, nametable, isn.getFalseBlock(), flag);
286 private void checkSubBlockNode(MethodDescriptor md, SymbolTable nametable, SubBlockNode sbn,
288 checkBlockNode(md, nametable.getParent(), sbn.getBlockNode(), flag);
291 private void checkBlockExpressionNode(MethodDescriptor md, SymbolTable nametable,
292 BlockExpressionNode ben, boolean flag) {
293 checkExpressionNode(md, nametable, ben.getExpression(), flag);
296 private void checkExpressionNode(MethodDescriptor md, SymbolTable nametable, ExpressionNode en,
299 case Kind.AssignmentNode:
300 checkAssignmentNode(md, nametable, (AssignmentNode) en, flag);
304 checkCastNode(md, nametable, (CastNode) en, flag);
307 case Kind.CreateObjectNode:
308 checkCreateObjectNode(md, nametable, (CreateObjectNode) en, flag);
311 case Kind.FieldAccessNode:
312 checkFieldAccessNode(md, nametable, (FieldAccessNode) en, flag);
315 case Kind.ArrayAccessNode:
316 checkArrayAccessNode(md, nametable, (ArrayAccessNode) en, flag);
319 // case Kind.LiteralNode:
320 // checkLiteralNode(md, nametable, (LiteralNode) en, flag);
323 case Kind.MethodInvokeNode:
324 checkMethodInvokeNode(md, nametable, (MethodInvokeNode) en, flag);
327 // case Kind.NameNode:
328 // checkNameNode(md, nametable, (NameNode) en, flag);
332 checkOpNode(md, nametable, (OpNode) en, flag);
335 // case Kind.OffsetNode:
336 // checkOffsetNode(md, nametable, (OffsetNode) en, flag);
339 case Kind.TertiaryNode:
340 checkTertiaryNode(md, nametable, (TertiaryNode) en, flag);
343 case Kind.InstanceOfNode:
344 checkInstanceOfNode(md, nametable, (InstanceOfNode) en, flag);
347 case Kind.ArrayInitializerNode:
348 checkArrayInitializerNode(md, nametable, (ArrayInitializerNode) en, flag);
351 // case Kind.ClassTypeNode:
352 // checkClassTypeNode(md, nametable, (ClassTypeNode) en, flag);
357 private void checkArrayInitializerNode(MethodDescriptor md, SymbolTable nametable,
358 ArrayInitializerNode ain, boolean flag) {
360 for (int i = 0; i < ain.numVarInitializers(); ++i) {
361 checkExpressionNode(md, nametable, ain.getVarInitializer(i), flag);
366 private void checkInstanceOfNode(MethodDescriptor md, SymbolTable nametable, InstanceOfNode tn,
368 checkExpressionNode(md, nametable, tn.getExpr(), flag);
371 private void checkTertiaryNode(MethodDescriptor md, SymbolTable nametable, TertiaryNode tn,
373 checkExpressionNode(md, nametable, tn.getCond(), flag);
374 checkExpressionNode(md, nametable, tn.getTrueExpr(), flag);
375 checkExpressionNode(md, nametable, tn.getFalseExpr(), flag);
378 private void checkOpNode(MethodDescriptor md, SymbolTable nametable, OpNode on, boolean flag) {
380 checkExpressionNode(md, nametable, on.getLeft(), flag);
381 if (on.getRight() != null) {
382 checkExpressionNode(md, nametable, on.getRight(), flag);
387 private void checkMethodInvokeNode(MethodDescriptor md, SymbolTable nametable,
388 MethodInvokeNode min, boolean flag) {
389 for (int i = 0; i < min.numArgs(); i++) {
390 ExpressionNode en = min.getArg(i);
391 checkExpressionNode(md, nametable, en, flag);
394 if (min.getExpression() != null) {
395 checkExpressionNode(md, nametable, min.getExpression(), flag);
399 annotatedMDSet.add(min.getMethod());
402 Set<MethodDescriptor> mdSet = caller2calleeSet.get(md);
404 mdSet = new HashSet<MethodDescriptor>();
405 caller2calleeSet.put(md, mdSet);
407 mdSet.add(min.getMethod());
411 private void checkArrayAccessNode(MethodDescriptor md, SymbolTable nametable,
412 ArrayAccessNode aan, boolean flag) {
414 ExpressionNode left = aan.getExpression();
415 checkExpressionNode(md, nametable, left, flag);
416 checkExpressionNode(md, nametable, aan.getIndex(), flag);
420 private void checkFieldAccessNode(MethodDescriptor md, SymbolTable nametable,
421 FieldAccessNode fan, boolean flag) {
422 ExpressionNode left = fan.getExpression();
423 checkExpressionNode(md, nametable, left, flag);
426 private void checkCreateObjectNode(MethodDescriptor md, SymbolTable nametable,
427 CreateObjectNode con, boolean flag) {
429 for (int i = 0; i < con.numArgs(); i++) {
430 ExpressionNode en = con.getArg(i);
431 checkExpressionNode(md, nametable, en, flag);
436 private void checkCastNode(MethodDescriptor md, SymbolTable nametable, CastNode cn, boolean flag) {
437 ExpressionNode en = cn.getExpression();
438 checkExpressionNode(md, nametable, en, flag);
441 private void checkAssignmentNode(MethodDescriptor md, SymbolTable nametable, AssignmentNode an,
443 boolean postinc = true;
445 if (an.getOperation().getBaseOp() == null
446 || (an.getOperation().getBaseOp().getOp() != Operation.POSTINC && an.getOperation()
447 .getBaseOp().getOp() != Operation.POSTDEC))
451 checkExpressionNode(md, nametable, an.getSrc(), flag);
454 checkExpressionNode(md, nametable, an.getDest(), flag);