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