adding more annotations for mp3decoder
[IRC.git] / Robust / src / Analysis / SSJava / MethodAnnotationCheck.java
1 package Analysis.SSJava;
2
3 import java.util.HashSet;
4 import java.util.Hashtable;
5 import java.util.Iterator;
6 import java.util.Set;
7
8 import IR.ClassDescriptor;
9 import IR.MethodDescriptor;
10 import IR.Operation;
11 import IR.State;
12 import IR.SymbolTable;
13 import IR.TypeUtil;
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;
27 import IR.Tree.Kind;
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;
34 import Util.Pair;
35
36 public class MethodAnnotationCheck {
37
38   State state;
39   SSJavaAnalysis ssjava;
40   TypeUtil tu;
41
42   Set<MethodDescriptor> annotatedMDSet;
43   Hashtable<MethodDescriptor, Set<MethodDescriptor>> caller2calleeSet;
44
45   public MethodAnnotationCheck(SSJavaAnalysis ssjava, State state, TypeUtil tu) {
46     this.ssjava = ssjava;
47     this.state = state;
48     this.tu = tu;
49     caller2calleeSet = new Hashtable<MethodDescriptor, Set<MethodDescriptor>>();
50     annotatedMDSet = new HashSet<MethodDescriptor>();
51   }
52
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;
61       toanalyze.remove(cd);
62
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);
67         }
68       }
69
70     }
71
72     for (Iterator iterator = annotatedMDSet.iterator(); iterator.hasNext();) {
73       MethodDescriptor md = (MethodDescriptor) iterator.next();
74       ssjava.addAnnotationRequire(md);
75     }
76
77     Set<Pair> visited = new HashSet<Pair>();
78     Set<MethodDescriptor> tovisit = new HashSet<MethodDescriptor>();
79     tovisit.addAll(annotatedMDSet);
80
81     while (!tovisit.isEmpty()) {
82       MethodDescriptor callerMD = tovisit.iterator().next();
83       tovisit.remove(callerMD);
84       Set<MethodDescriptor> calleeSet = caller2calleeSet.get(callerMD);
85       if (calleeSet != null) {
86         for (Iterator iterator = calleeSet.iterator(); iterator.hasNext();) {
87           MethodDescriptor calleeMD = (MethodDescriptor) iterator.next();
88           Pair p = new Pair(callerMD, calleeMD);
89           if (!visited.contains(p)) {
90             visited.add(p);
91             tovisit.add(calleeMD);
92             ssjava.addAnnotationRequire(calleeMD);
93           }
94         }
95       }
96     }
97
98   }
99
100   public void methodAnnoataionInheritanceCheck() {
101     // check If a method is annotated, any method that overrides it should
102     // be annotated.
103
104     Set<MethodDescriptor> tovisit = new HashSet<MethodDescriptor>();
105     tovisit.addAll(ssjava.getAnnotationRequireSet());
106
107     while (!tovisit.isEmpty()) {
108       MethodDescriptor md = tovisit.iterator().next();
109       tovisit.remove(md);
110
111       ClassDescriptor cd = md.getClassDesc();
112
113       Set subClassSet = tu.getSubClasses(cd);
114       if (subClassSet != null) {
115         for (Iterator iterator2 = subClassSet.iterator(); iterator2.hasNext();) {
116           ClassDescriptor subCD = (ClassDescriptor) iterator2.next();
117           Set possiblematches = subCD.getMethodTable().getSet(md.getSymbol());
118           for (Iterator methodit = possiblematches.iterator(); methodit.hasNext();) {
119             MethodDescriptor matchmd = (MethodDescriptor) methodit.next();
120             if (md.matches(matchmd)) {
121               if (matchmd.getClassDesc().equals(subCD)) {
122                 ssjava.addAnnotationRequire(matchmd);
123               }
124             }
125           }
126         }
127       }
128     }
129
130   }
131
132   private void checkMethodBody(ClassDescriptor cd, MethodDescriptor md) {
133     BlockNode bn = state.getMethodBody(md);
134     checkBlockNode(md, md.getParameterTable(), bn, false);
135   }
136
137   private void checkBlockNode(MethodDescriptor md, SymbolTable nametable, BlockNode bn, boolean flag) {
138     bn.getVarTable().setParent(nametable);
139     String label = bn.getLabel();
140     boolean isSSJavaLoop = flag;
141     if (label != null && label.equals(ssjava.SSJAVA)) {
142       if (isSSJavaLoop) {
143         throw new Error("Only outermost loop can be the self-stabilizing loop.");
144       } else {
145         annotatedMDSet.add(md);
146         isSSJavaLoop = true;
147       }
148     }
149
150     for (int i = 0; i < bn.size(); i++) {
151       BlockStatementNode bsn = bn.get(i);
152       checkBlockStatementNode(md, bn.getVarTable(), bsn, isSSJavaLoop);
153     }
154
155   }
156
157   private void checkBlockStatementNode(MethodDescriptor md, SymbolTable nametable,
158       BlockStatementNode bsn, boolean flag) {
159
160     switch (bsn.kind()) {
161     case Kind.SubBlockNode:
162       checkSubBlockNode(md, nametable, (SubBlockNode) bsn, flag);
163       return;
164
165     case Kind.BlockExpressionNode:
166       checkBlockExpressionNode(md, nametable, (BlockExpressionNode) bsn, flag);
167       break;
168
169     case Kind.DeclarationNode:
170       checkDeclarationNode(md, nametable, (DeclarationNode) bsn, flag);
171       break;
172
173     case Kind.IfStatementNode:
174       checkIfStatementNode(md, nametable, (IfStatementNode) bsn, flag);
175       break;
176
177     case Kind.LoopNode:
178       checkLoopNode(md, nametable, (LoopNode) bsn, flag);
179       break;
180
181     case Kind.ReturnNode:
182       checkReturnNode(md, nametable, (ReturnNode) bsn, flag);
183       break;
184
185     }
186   }
187
188   private void checkDeclarationNode(MethodDescriptor md, SymbolTable nametable, DeclarationNode dn,
189       boolean flag) {
190     if (dn.getExpression() != null) {
191       checkExpressionNode(md, nametable, dn.getExpression(), flag);
192     }
193   }
194
195   private void checkReturnNode(MethodDescriptor md, SymbolTable nametable, ReturnNode rn,
196       boolean flag) {
197     if (rn.getReturnExpression() != null) {
198       if (md.getReturnType() != null) {
199         checkExpressionNode(md, nametable, rn.getReturnExpression(), flag);
200       }
201     }
202   }
203
204   private void checkLoopNode(MethodDescriptor md, SymbolTable nametable, LoopNode ln, boolean flag) {
205     if (ln.getType() == LoopNode.WHILELOOP || ln.getType() == LoopNode.DOWHILELOOP) {
206       checkExpressionNode(md, nametable, ln.getCondition(), flag);
207       checkBlockNode(md, nametable, ln.getBody(), flag);
208     } else {
209       // For loop case
210       /* Link in the initializer naming environment */
211       BlockNode bn = ln.getInitializer();
212       bn.getVarTable().setParent(nametable);
213       for (int i = 0; i < bn.size(); i++) {
214         BlockStatementNode bsn = bn.get(i);
215         checkBlockStatementNode(md, bn.getVarTable(), bsn, flag);
216       }
217       // check the condition
218       checkExpressionNode(md, bn.getVarTable(), ln.getCondition(), flag);
219       checkBlockNode(md, bn.getVarTable(), ln.getBody(), flag);
220       checkBlockNode(md, bn.getVarTable(), ln.getUpdate(), flag);
221     }
222   }
223
224   private void checkIfStatementNode(MethodDescriptor md, SymbolTable nametable,
225       IfStatementNode isn, boolean flag) {
226     checkExpressionNode(md, nametable, isn.getCondition(), flag);
227     checkBlockNode(md, nametable, isn.getTrueBlock(), flag);
228     if (isn.getFalseBlock() != null) {
229       checkBlockNode(md, nametable, isn.getFalseBlock(), flag);
230     }
231   }
232
233   private void checkSubBlockNode(MethodDescriptor md, SymbolTable nametable, SubBlockNode sbn,
234       boolean flag) {
235     checkBlockNode(md, nametable.getParent(), sbn.getBlockNode(), flag);
236   }
237
238   private void checkBlockExpressionNode(MethodDescriptor md, SymbolTable nametable,
239       BlockExpressionNode ben, boolean flag) {
240     checkExpressionNode(md, nametable, ben.getExpression(), flag);
241   }
242
243   private void checkExpressionNode(MethodDescriptor md, SymbolTable nametable, ExpressionNode en,
244       boolean flag) {
245     switch (en.kind()) {
246     case Kind.AssignmentNode:
247       checkAssignmentNode(md, nametable, (AssignmentNode) en, flag);
248       return;
249
250     case Kind.CastNode:
251       checkCastNode(md, nametable, (CastNode) en, flag);
252       return;
253
254     case Kind.CreateObjectNode:
255       checkCreateObjectNode(md, nametable, (CreateObjectNode) en, flag);
256       return;
257
258     case Kind.FieldAccessNode:
259       checkFieldAccessNode(md, nametable, (FieldAccessNode) en, flag);
260       return;
261
262     case Kind.ArrayAccessNode:
263       checkArrayAccessNode(md, nametable, (ArrayAccessNode) en, flag);
264       return;
265
266       // case Kind.LiteralNode:
267       // checkLiteralNode(md, nametable, (LiteralNode) en, flag);
268       // return;
269
270     case Kind.MethodInvokeNode:
271       checkMethodInvokeNode(md, nametable, (MethodInvokeNode) en, flag);
272       return;
273
274       // case Kind.NameNode:
275       // checkNameNode(md, nametable, (NameNode) en, flag);
276       // return;
277
278     case Kind.OpNode:
279       checkOpNode(md, nametable, (OpNode) en, flag);
280       return;
281
282       // case Kind.OffsetNode:
283       // checkOffsetNode(md, nametable, (OffsetNode) en, flag);
284       // return;
285
286     case Kind.TertiaryNode:
287       checkTertiaryNode(md, nametable, (TertiaryNode) en, flag);
288       return;
289
290     case Kind.InstanceOfNode:
291       checkInstanceOfNode(md, nametable, (InstanceOfNode) en, flag);
292       return;
293
294     case Kind.ArrayInitializerNode:
295       checkArrayInitializerNode(md, nametable, (ArrayInitializerNode) en, flag);
296       return;
297
298       // case Kind.ClassTypeNode:
299       // checkClassTypeNode(md, nametable, (ClassTypeNode) en, flag);
300       // return;
301     }
302   }
303
304   private void checkArrayInitializerNode(MethodDescriptor md, SymbolTable nametable,
305       ArrayInitializerNode ain, boolean flag) {
306
307     for (int i = 0; i < ain.numVarInitializers(); ++i) {
308       checkExpressionNode(md, nametable, ain.getVarInitializer(i), flag);
309     }
310
311   }
312
313   private void checkInstanceOfNode(MethodDescriptor md, SymbolTable nametable, InstanceOfNode tn,
314       boolean flag) {
315     checkExpressionNode(md, nametable, tn.getExpr(), flag);
316   }
317
318   private void checkTertiaryNode(MethodDescriptor md, SymbolTable nametable, TertiaryNode tn,
319       boolean flag) {
320     checkExpressionNode(md, nametable, tn.getCond(), flag);
321     checkExpressionNode(md, nametable, tn.getTrueExpr(), flag);
322     checkExpressionNode(md, nametable, tn.getFalseExpr(), flag);
323   }
324
325   private void checkOpNode(MethodDescriptor md, SymbolTable nametable, OpNode on, boolean flag) {
326
327     checkExpressionNode(md, nametable, on.getLeft(), flag);
328     if (on.getRight() != null) {
329       checkExpressionNode(md, nametable, on.getRight(), flag);
330     }
331
332   }
333
334   private void checkMethodInvokeNode(MethodDescriptor md, SymbolTable nametable,
335       MethodInvokeNode min, boolean flag) {
336     for (int i = 0; i < min.numArgs(); i++) {
337       ExpressionNode en = min.getArg(i);
338       checkExpressionNode(md, nametable, en, flag);
339     }
340
341     if (min.getExpression() != null) {
342       checkExpressionNode(md, nametable, min.getExpression(), flag);
343     }
344
345     if (flag) {
346       annotatedMDSet.add(min.getMethod());
347     }
348
349     Set<MethodDescriptor> mdSet = caller2calleeSet.get(md);
350     if (mdSet == null) {
351       mdSet = new HashSet<MethodDescriptor>();
352       caller2calleeSet.put(md, mdSet);
353     }
354     mdSet.add(min.getMethod());
355
356   }
357
358   private void checkArrayAccessNode(MethodDescriptor md, SymbolTable nametable,
359       ArrayAccessNode aan, boolean flag) {
360
361     ExpressionNode left = aan.getExpression();
362     checkExpressionNode(md, nametable, left, flag);
363     checkExpressionNode(md, nametable, aan.getIndex(), flag);
364
365   }
366
367   private void checkFieldAccessNode(MethodDescriptor md, SymbolTable nametable,
368       FieldAccessNode fan, boolean flag) {
369     ExpressionNode left = fan.getExpression();
370     checkExpressionNode(md, nametable, left, flag);
371   }
372
373   private void checkCreateObjectNode(MethodDescriptor md, SymbolTable nametable,
374       CreateObjectNode con, boolean flag) {
375
376     for (int i = 0; i < con.numArgs(); i++) {
377       ExpressionNode en = con.getArg(i);
378       checkExpressionNode(md, nametable, en, flag);
379     }
380
381   }
382
383   private void checkCastNode(MethodDescriptor md, SymbolTable nametable, CastNode cn, boolean flag) {
384     ExpressionNode en = cn.getExpression();
385     checkExpressionNode(md, nametable, en, flag);
386   }
387
388   private void checkAssignmentNode(MethodDescriptor md, SymbolTable nametable, AssignmentNode an,
389       boolean flag) {
390     boolean postinc = true;
391
392     if (an.getOperation().getBaseOp() == null
393         || (an.getOperation().getBaseOp().getOp() != Operation.POSTINC && an.getOperation()
394             .getBaseOp().getOp() != Operation.POSTDEC))
395       postinc = false;
396
397     if (!postinc) {
398       checkExpressionNode(md, nametable, an.getSrc(), flag);
399     }
400
401     checkExpressionNode(md, nametable, an.getDest(), flag);
402
403   }
404
405 }