having a new check that verifies the single reference constraint: only allows a singl...
[IRC.git] / Robust / src / Analysis / SSJava / SingleReferenceCheck.java
1 package Analysis.SSJava;
2
3 import java.util.Iterator;
4
5 import IR.ClassDescriptor;
6 import IR.MethodDescriptor;
7 import IR.State;
8 import IR.Tree.AssignmentNode;
9 import IR.Tree.BlockExpressionNode;
10 import IR.Tree.BlockNode;
11 import IR.Tree.BlockStatementNode;
12 import IR.Tree.CastNode;
13 import IR.Tree.CreateObjectNode;
14 import IR.Tree.DeclarationNode;
15 import IR.Tree.ExpressionNode;
16 import IR.Tree.Kind;
17 import IR.Tree.LoopNode;
18 import IR.Tree.SubBlockNode;
19
20 public class SingleReferenceCheck {
21
22   static State state;
23   String needToNullify = null;
24
25   public SingleReferenceCheck(State state) {
26     this.state = state;
27   }
28
29   public void singleReferenceCheck() {
30     Iterator it = state.getClassSymbolTable().getDescriptorsIterator();
31     while (it.hasNext()) {
32       ClassDescriptor cd = (ClassDescriptor) it.next();
33       for (Iterator method_it = cd.getMethods(); method_it.hasNext();) {
34         MethodDescriptor md = (MethodDescriptor) method_it.next();
35         checkMethodBody(cd, md);
36       }
37     }
38   }
39
40   private void checkMethodBody(ClassDescriptor cd, MethodDescriptor fm) {
41     BlockNode bn = state.getMethodBody(fm);
42     for (int i = 0; i < bn.size(); i++) {
43       checkBlockStatementNode(cd, bn.get(i));
44     }
45
46   }
47
48   private boolean checkNullifying(BlockStatementNode bsn) {
49
50     if (bsn.kind() == Kind.BlockExpressionNode) {
51       ExpressionNode en = ((BlockExpressionNode) bsn).getExpression();
52       if (en.kind() == Kind.AssignmentNode) {
53         AssignmentNode an = (AssignmentNode) en;
54
55         if (an.getSrc().getType().isNull() && an.getDest().printNode(0).equals(needToNullify)) {
56           needToNullify = null;
57           return true;
58         }
59       }
60     }
61
62     return false;
63   }
64
65   private void checkBlockStatementNode(ClassDescriptor cd, BlockStatementNode bsn) {
66
67     if (needToNullify != null) {
68       if (!checkNullifying(bsn)) {
69         throw new Error(
70             "Reference field, which is read by a method, should be assigned to null before executing any following statement of the reference copy statement at "
71                 + cd.getSourceFileName() + "::" + bsn.getNumLine());
72       }
73     }
74
75     switch (bsn.kind()) {
76     case Kind.BlockExpressionNode:
77       checkExpressionNode(((BlockExpressionNode) bsn).getExpression());
78       break;
79
80     case Kind.DeclarationNode:
81       checkDeclarationNode((DeclarationNode) bsn);
82       break;
83
84     case Kind.SubBlockNode:
85       checkSubBlockNode(cd, (SubBlockNode) bsn);
86       return;
87
88     case Kind.LoopNode:
89       checkLoopNode(cd, (LoopNode) bsn);
90       break;
91     }
92
93   }
94
95   private void checkLoopNode(ClassDescriptor cd, LoopNode ln) {
96     if (ln.getType() == LoopNode.FORLOOP) {
97       checkBlockNode(cd, ln.getInitializer());
98     }
99     checkBlockNode(cd, ln.getBody());
100   }
101
102   private void checkSubBlockNode(ClassDescriptor cd, SubBlockNode sbn) {
103     checkBlockNode(cd, sbn.getBlockNode());
104   }
105
106   private void checkBlockNode(ClassDescriptor cd, BlockNode bn) {
107     for (int i = 0; i < bn.size(); i++) {
108       checkBlockStatementNode(cd, bn.get(i));
109     }
110   }
111
112   private void checkExpressionNode(ExpressionNode en) {
113
114     switch (en.kind()) {
115     case Kind.AssignmentNode:
116       checkAssignmentNode((AssignmentNode) en);
117       break;
118     }
119
120   }
121
122   private void checkAssignmentNode(AssignmentNode an) {
123
124     if (an.getSrc() != null) {
125       if (an.getSrc().getType().isPtr() && (!an.getSrc().getType().isNull())
126           && !(an.getSrc() instanceof CreateObjectNode)) {
127         if (an.getSrc() instanceof CastNode) {
128           needToNullify = ((CastNode) an.getSrc()).getExpression().printNode(0);
129         } else {
130           needToNullify = an.getSrc().printNode(0);
131         }
132       }
133
134     }
135   }
136
137   private void checkDeclarationNode(DeclarationNode dn) {
138
139     if (dn.getExpression() != null) {
140       if (dn.getExpression().getType().isPtr() && !(dn.getExpression() instanceof CreateObjectNode)) {
141
142         if (dn.getExpression() instanceof CastNode) {
143           needToNullify = ((CastNode) dn.getExpression()).getExpression().printNode(0);
144         } else {
145           needToNullify = dn.getExpression().printNode(0);
146         }
147
148       }
149     }
150   }
151
152 }