1 package Analysis.SSJava;
3 import java.util.HashSet;
4 import java.util.Hashtable;
5 import java.util.Iterator;
7 import java.util.Vector;
9 import IR.AnnotationDescriptor;
10 import IR.ClassDescriptor;
11 import IR.MethodDescriptor;
14 import IR.SymbolTable;
16 import IR.Tree.ArrayAccessNode;
17 import IR.Tree.ArrayInitializerNode;
18 import IR.Tree.AssignmentNode;
19 import IR.Tree.BlockExpressionNode;
20 import IR.Tree.BlockNode;
21 import IR.Tree.BlockStatementNode;
22 import IR.Tree.CastNode;
23 import IR.Tree.CreateObjectNode;
24 import IR.Tree.DeclarationNode;
25 import IR.Tree.ExpressionNode;
26 import IR.Tree.FieldAccessNode;
27 import IR.Tree.IfStatementNode;
28 import IR.Tree.InstanceOfNode;
30 import IR.Tree.LoopNode;
31 import IR.Tree.MethodInvokeNode;
32 import IR.Tree.OpNode;
33 import IR.Tree.ReturnNode;
34 import IR.Tree.SubBlockNode;
35 import IR.Tree.SwitchBlockNode;
36 import IR.Tree.SwitchStatementNode;
37 import IR.Tree.TertiaryNode;
40 public class MethodAnnotationCheck {
43 SSJavaAnalysis ssjava;
46 Set<MethodDescriptor> annotatedMDSet;
47 Hashtable<MethodDescriptor, Set<MethodDescriptor>> caller2calleeSet;
49 public MethodAnnotationCheck(SSJavaAnalysis ssjava, State state, TypeUtil tu) {
53 caller2calleeSet = new Hashtable<MethodDescriptor, Set<MethodDescriptor>>();
54 annotatedMDSet = new HashSet<MethodDescriptor>();
57 public void methodAnnoatationCheck() {
58 SymbolTable classtable = state.getClassSymbolTable();
59 HashSet toanalyze = new HashSet();
60 toanalyze.addAll(classtable.getValueSet());
61 toanalyze.addAll(state.getTaskSymbolTable().getValueSet());
62 while (!toanalyze.isEmpty()) {
63 Object obj = toanalyze.iterator().next();
64 ClassDescriptor cd = (ClassDescriptor) obj;
67 if (!ssjava.isSSJavaUtil(cd) && !cd.isInterface()) {
68 for (Iterator method_it = cd.getMethods(); method_it.hasNext();) {
69 MethodDescriptor md = (MethodDescriptor) method_it.next();
70 checkTrustworthyMethodAnnotation(md);
71 checkMethodBody(cd, md);
77 for (Iterator iterator = annotatedMDSet.iterator(); iterator.hasNext();) {
78 MethodDescriptor md = (MethodDescriptor) iterator.next();
79 if (!ssjava.isTrustMethod(md)) {
80 ssjava.addAnnotationRequire(md);
84 Set<Pair> visited = new HashSet<Pair>();
85 Set<MethodDescriptor> tovisit = new HashSet<MethodDescriptor>();
86 tovisit.addAll(annotatedMDSet);
88 while (!tovisit.isEmpty()) {
89 MethodDescriptor callerMD = tovisit.iterator().next();
90 tovisit.remove(callerMD);
92 Set<MethodDescriptor> calleeSet = caller2calleeSet.get(callerMD);
93 if (calleeSet != null) {
94 for (Iterator iterator = calleeSet.iterator(); iterator.hasNext();) {
95 MethodDescriptor calleeMD = (MethodDescriptor) iterator.next();
96 Pair p = new Pair(callerMD, calleeMD);
97 if (!visited.contains(p)) {
100 if (!ssjava.isTrustMethod(callerMD) && !ssjava.isTrustMethod(calleeMD)) {
101 // if method is annotated as "TRUST", do not need to check for
102 // linear type & flow-down rule
103 tovisit.add(calleeMD);
105 Set<MethodDescriptor> possibleCalleeSet =
106 (Set<MethodDescriptor>) ssjava.getCallGraph().getMethods(calleeMD);
108 for (Iterator iterator2 = possibleCalleeSet.iterator(); iterator2.hasNext();) {
109 MethodDescriptor possibleCallee = (MethodDescriptor) iterator2.next();
111 if (!possibleCallee.isAbstract() && !possibleCallee.getModifiers().isNative()) {
112 ssjava.addAnnotationRequire(possibleCallee);
113 tovisit.add(possibleCallee);
125 private void checkTrustworthyMethodAnnotation(MethodDescriptor md) {
126 // method annotation parsing
127 Vector<AnnotationDescriptor> methodAnnotations = md.getModifiers().getAnnotations();
128 if (methodAnnotations != null) {
129 for (int i = 0; i < methodAnnotations.size(); i++) {
130 AnnotationDescriptor an = methodAnnotations.elementAt(i);
131 if (an.getMarker().equals(ssjava.TRUST)) {
132 ssjava.addTrustMethod(md);
138 public void methodAnnoataionInheritanceCheck() {
139 // check If a method is annotated, any method that overrides it should
142 Set<MethodDescriptor> tovisit = new HashSet<MethodDescriptor>();
143 tovisit.addAll(ssjava.getAnnotationRequireSet());
145 while (!tovisit.isEmpty()) {
146 MethodDescriptor md = tovisit.iterator().next();
149 ClassDescriptor cd = md.getClassDesc();
151 Set subClassSet = tu.getSubClasses(cd);
152 if (subClassSet != null) {
153 for (Iterator iterator2 = subClassSet.iterator(); iterator2.hasNext();) {
154 ClassDescriptor subCD = (ClassDescriptor) iterator2.next();
155 Set possiblematches = subCD.getMethodTable().getSet(md.getSymbol());
156 for (Iterator methodit = possiblematches.iterator(); methodit.hasNext();) {
157 MethodDescriptor matchmd = (MethodDescriptor) methodit.next();
158 if (md.matches(matchmd)) {
159 if (matchmd.getClassDesc().equals(subCD)) {
160 ssjava.addAnnotationRequire(matchmd);
167 // need to check super classess if the current method is inherited from
168 // them, all of ancestor method should be annotated.
170 ClassDescriptor curClassDesc;
171 ClassDescriptor parentClassDesc = cd;
173 while (!parentClassDesc.getSymbol().equals("Object")) {
174 curClassDesc = parentClassDesc;
175 parentClassDesc = tu.getSuper(curClassDesc);
176 Set possiblematches = parentClassDesc.getMethodTable().getSet(md.getSymbol());
177 for (Iterator methodit = possiblematches.iterator(); methodit.hasNext();) {
178 MethodDescriptor matchmd = (MethodDescriptor) methodit.next();
179 if (md.matches(matchmd)) {
180 ssjava.addAnnotationRequire(matchmd);
185 Set<ClassDescriptor> superIFSet = tu.getSuperIFs(cd);
186 for (Iterator iterator = superIFSet.iterator(); iterator.hasNext();) {
187 ClassDescriptor parentInterface = (ClassDescriptor) iterator.next();
188 Set possiblematches = parentInterface.getMethodTable().getSet(md.getSymbol());
189 for (Iterator methodit = possiblematches.iterator(); methodit.hasNext();) {
190 MethodDescriptor matchmd = (MethodDescriptor) methodit.next();
191 if (md.matches(matchmd)) {
192 ssjava.addAnnotationRequire(matchmd);
201 private void checkMethodBody(ClassDescriptor cd, MethodDescriptor md) {
202 BlockNode bn = state.getMethodBody(md);
203 checkBlockNode(md, md.getParameterTable(), bn, false);
206 private void checkBlockNode(MethodDescriptor md, SymbolTable nametable, BlockNode bn, boolean flag) {
207 bn.getVarTable().setParent(nametable);
209 for (int i = 0; i < bn.size(); i++) {
210 BlockStatementNode bsn = bn.get(i);
211 checkBlockStatementNode(md, bn.getVarTable(), bsn, flag);
216 private void checkBlockStatementNode(MethodDescriptor md, SymbolTable nametable,
217 BlockStatementNode bsn, boolean flag) {
219 switch (bsn.kind()) {
220 case Kind.SubBlockNode:
221 checkSubBlockNode(md, nametable, (SubBlockNode) bsn, flag);
224 case Kind.BlockExpressionNode:
225 checkBlockExpressionNode(md, nametable, (BlockExpressionNode) bsn, flag);
228 case Kind.DeclarationNode:
229 checkDeclarationNode(md, nametable, (DeclarationNode) bsn, flag);
232 case Kind.IfStatementNode:
233 checkIfStatementNode(md, nametable, (IfStatementNode) bsn, flag);
237 checkLoopNode(md, nametable, (LoopNode) bsn, flag);
240 case Kind.ReturnNode:
241 checkReturnNode(md, nametable, (ReturnNode) bsn, flag);
244 case Kind.SwitchStatementNode:
245 checkSwitchStatementNode(md, nametable, (SwitchStatementNode) bsn, flag);
251 private void checkSwitchStatementNode(MethodDescriptor md, SymbolTable nametable,
252 SwitchStatementNode ssn, boolean flag) {
254 checkExpressionNode(md, nametable, ssn.getCondition(), flag);
256 BlockNode sbn = ssn.getSwitchBody();
257 for (int i = 0; i < sbn.size(); i++) {
258 checkBlockNode(md, nametable, ((SwitchBlockNode) sbn.get(i)).getSwitchBlockStatement(), flag);
263 private void checkDeclarationNode(MethodDescriptor md, SymbolTable nametable, DeclarationNode dn,
265 if (dn.getExpression() != null) {
266 checkExpressionNode(md, nametable, dn.getExpression(), flag);
270 private void checkReturnNode(MethodDescriptor md, SymbolTable nametable, ReturnNode rn,
272 if (rn.getReturnExpression() != null) {
273 if (md.getReturnType() != null) {
274 checkExpressionNode(md, nametable, rn.getReturnExpression(), flag);
279 private void checkLoopNode(MethodDescriptor md, SymbolTable nametable, LoopNode ln, boolean flag) {
281 String label = ln.getLabel();
282 boolean isSSJavaLoop = flag;
283 if (label != null && label.equals(ssjava.SSJAVA)) {
285 throw new Error("Only outermost loop can be the self-stabilizing loop.");
287 ssjava.setMethodContainingSSJavaLoop(md);
288 annotatedMDSet.add(md);
293 if (ln.getType() == LoopNode.WHILELOOP || ln.getType() == LoopNode.DOWHILELOOP) {
294 checkExpressionNode(md, nametable, ln.getCondition(), isSSJavaLoop);
295 checkBlockNode(md, nametable, ln.getBody(), isSSJavaLoop);
298 /* Link in the initializer naming environment */
299 BlockNode bn = ln.getInitializer();
300 bn.getVarTable().setParent(nametable);
301 for (int i = 0; i < bn.size(); i++) {
302 BlockStatementNode bsn = bn.get(i);
303 checkBlockStatementNode(md, bn.getVarTable(), bsn, isSSJavaLoop);
305 // check the condition
306 checkExpressionNode(md, bn.getVarTable(), ln.getCondition(), isSSJavaLoop);
307 checkBlockNode(md, bn.getVarTable(), ln.getBody(), isSSJavaLoop);
308 checkBlockNode(md, bn.getVarTable(), ln.getUpdate(), isSSJavaLoop);
312 private void checkIfStatementNode(MethodDescriptor md, SymbolTable nametable,
313 IfStatementNode isn, boolean flag) {
314 checkExpressionNode(md, nametable, isn.getCondition(), flag);
315 checkBlockNode(md, nametable, isn.getTrueBlock(), flag);
316 if (isn.getFalseBlock() != null) {
317 checkBlockNode(md, nametable, isn.getFalseBlock(), flag);
321 private void checkSubBlockNode(MethodDescriptor md, SymbolTable nametable, SubBlockNode sbn,
323 checkBlockNode(md, nametable.getParent(), sbn.getBlockNode(), flag);
326 private void checkBlockExpressionNode(MethodDescriptor md, SymbolTable nametable,
327 BlockExpressionNode ben, boolean flag) {
328 checkExpressionNode(md, nametable, ben.getExpression(), flag);
331 private void checkExpressionNode(MethodDescriptor md, SymbolTable nametable, ExpressionNode en,
334 case Kind.AssignmentNode:
335 checkAssignmentNode(md, nametable, (AssignmentNode) en, flag);
339 checkCastNode(md, nametable, (CastNode) en, flag);
342 case Kind.CreateObjectNode:
343 checkCreateObjectNode(md, nametable, (CreateObjectNode) en, flag);
346 case Kind.FieldAccessNode:
347 checkFieldAccessNode(md, nametable, (FieldAccessNode) en, flag);
350 case Kind.ArrayAccessNode:
351 checkArrayAccessNode(md, nametable, (ArrayAccessNode) en, flag);
354 // case Kind.LiteralNode:
355 // checkLiteralNode(md, nametable, (LiteralNode) en, flag);
358 case Kind.MethodInvokeNode:
359 checkMethodInvokeNode(md, nametable, (MethodInvokeNode) en, flag);
362 // case Kind.NameNode:
363 // checkNameNode(md, nametable, (NameNode) en, flag);
367 checkOpNode(md, nametable, (OpNode) en, flag);
370 // case Kind.OffsetNode:
371 // checkOffsetNode(md, nametable, (OffsetNode) en, flag);
374 case Kind.TertiaryNode:
375 checkTertiaryNode(md, nametable, (TertiaryNode) en, flag);
378 case Kind.InstanceOfNode:
379 checkInstanceOfNode(md, nametable, (InstanceOfNode) en, flag);
382 case Kind.ArrayInitializerNode:
383 checkArrayInitializerNode(md, nametable, (ArrayInitializerNode) en, flag);
386 // case Kind.ClassTypeNode:
387 // checkClassTypeNode(md, nametable, (ClassTypeNode) en, flag);
392 private void checkArrayInitializerNode(MethodDescriptor md, SymbolTable nametable,
393 ArrayInitializerNode ain, boolean flag) {
395 for (int i = 0; i < ain.numVarInitializers(); ++i) {
396 checkExpressionNode(md, nametable, ain.getVarInitializer(i), flag);
401 private void checkInstanceOfNode(MethodDescriptor md, SymbolTable nametable, InstanceOfNode tn,
403 checkExpressionNode(md, nametable, tn.getExpr(), flag);
406 private void checkTertiaryNode(MethodDescriptor md, SymbolTable nametable, TertiaryNode tn,
408 checkExpressionNode(md, nametable, tn.getCond(), flag);
409 checkExpressionNode(md, nametable, tn.getTrueExpr(), flag);
410 checkExpressionNode(md, nametable, tn.getFalseExpr(), flag);
413 private void checkOpNode(MethodDescriptor md, SymbolTable nametable, OpNode on, boolean flag) {
415 checkExpressionNode(md, nametable, on.getLeft(), flag);
416 if (on.getRight() != null) {
417 checkExpressionNode(md, nametable, on.getRight(), flag);
422 private void checkMethodInvokeNode(MethodDescriptor md, SymbolTable nametable,
423 MethodInvokeNode min, boolean flag) {
424 for (int i = 0; i < min.numArgs(); i++) {
425 ExpressionNode en = min.getArg(i);
426 checkExpressionNode(md, nametable, en, flag);
429 if (min.getExpression() != null) {
430 checkExpressionNode(md, nametable, min.getExpression(), flag);
434 annotatedMDSet.add(min.getMethod());
437 Set<MethodDescriptor> mdSet = caller2calleeSet.get(md);
439 mdSet = new HashSet<MethodDescriptor>();
440 caller2calleeSet.put(md, mdSet);
442 mdSet.add(min.getMethod());
446 private void checkArrayAccessNode(MethodDescriptor md, SymbolTable nametable,
447 ArrayAccessNode aan, boolean flag) {
449 ExpressionNode left = aan.getExpression();
450 checkExpressionNode(md, nametable, left, flag);
451 checkExpressionNode(md, nametable, aan.getIndex(), flag);
455 private void checkFieldAccessNode(MethodDescriptor md, SymbolTable nametable,
456 FieldAccessNode fan, boolean flag) {
457 ExpressionNode left = fan.getExpression();
458 checkExpressionNode(md, nametable, left, flag);
461 private void checkCreateObjectNode(MethodDescriptor md, SymbolTable nametable,
462 CreateObjectNode con, boolean flag) {
464 for (int i = 0; i < con.numArgs(); i++) {
465 ExpressionNode en = con.getArg(i);
466 checkExpressionNode(md, nametable, en, flag);
471 private void checkCastNode(MethodDescriptor md, SymbolTable nametable, CastNode cn, boolean flag) {
472 ExpressionNode en = cn.getExpression();
473 checkExpressionNode(md, nametable, en, flag);
476 private void checkAssignmentNode(MethodDescriptor md, SymbolTable nametable, AssignmentNode an,
478 boolean postinc = true;
480 if (an.getOperation().getBaseOp() == null
481 || (an.getOperation().getBaseOp().getOp() != Operation.POSTINC && an.getOperation()
482 .getBaseOp().getOp() != Operation.POSTDEC))
486 checkExpressionNode(md, nametable, an.getSrc(), flag);
489 checkExpressionNode(md, nametable, an.getDest(), flag);