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;
12 import IR.MethodDescriptor;
14 import IR.SymbolTable;
15 import IR.TaskDescriptor;
16 import IR.TypeDescriptor;
17 import IR.VarDescriptor;
18 import IR.Tree.ArrayAccessNode;
19 import IR.Tree.ArrayInitializerNode;
20 import IR.Tree.AssignmentNode;
21 import IR.Tree.AtomicNode;
22 import IR.Tree.BlockExpressionNode;
23 import IR.Tree.BlockNode;
24 import IR.Tree.BlockStatementNode;
25 import IR.Tree.CastNode;
26 import IR.Tree.ClassTypeNode;
27 import IR.Tree.ContinueBreakNode;
28 import IR.Tree.CreateObjectNode;
29 import IR.Tree.DeclarationNode;
30 import IR.Tree.ExpressionNode;
31 import IR.Tree.FieldAccessNode;
32 import IR.Tree.IfStatementNode;
33 import IR.Tree.InstanceOfNode;
35 import IR.Tree.LiteralNode;
36 import IR.Tree.LoopNode;
37 import IR.Tree.MethodInvokeNode;
38 import IR.Tree.NameNode;
39 import IR.Tree.OffsetNode;
40 import IR.Tree.OpNode;
41 import IR.Tree.ReturnNode;
42 import IR.Tree.SubBlockNode;
43 import IR.Tree.SwitchBlockNode;
44 import IR.Tree.SwitchLabelNode;
45 import IR.Tree.SwitchStatementNode;
46 import IR.Tree.SynchronizedNode;
47 import IR.Tree.TagDeclarationNode;
48 import IR.Tree.TaskExitNode;
49 import IR.Tree.TertiaryNode;
51 public class LinearTypeCheck {
54 SSJavaAnalysis ssjava;
55 String needToNullify = null;
57 Hashtable<MethodDescriptor, Set<VarDescriptor>> md2DelegateParamSet;
59 public LinearTypeCheck(SSJavaAnalysis ssjava, State state) {
62 md2DelegateParamSet = new Hashtable<MethodDescriptor, Set<VarDescriptor>>();
65 public void linearTypeCheck() {
67 // first, parsing DELEGATE annotation from method declarations
68 Iterator it = state.getClassSymbolTable().getDescriptorsIterator();
69 while (it.hasNext()) {
70 ClassDescriptor cd = (ClassDescriptor) it.next();
71 for (Iterator method_it = cd.getMethods(); method_it.hasNext();) {
72 MethodDescriptor md = (MethodDescriptor) method_it.next();
76 System.out.println("###");
77 System.out.println("md2DelegateParamSet=" + md2DelegateParamSet);
79 // second, check the linear type
80 it = state.getClassSymbolTable().getDescriptorsIterator();
81 while (it.hasNext()) {
82 ClassDescriptor cd = (ClassDescriptor) it.next();
83 for (Iterator method_it = cd.getMethods(); method_it.hasNext();) {
84 MethodDescriptor md = (MethodDescriptor) method_it.next();
85 if (ssjava.needTobeAnnotated(md)) {
86 checkMethodBody(cd, md);
93 private void parseAnnotations(MethodDescriptor md) {
95 for (int i = 0; i < md.numParameters(); i++) {
96 // process annotations on method parameters
97 VarDescriptor vd = (VarDescriptor) md.getParameter(i);
99 Vector<AnnotationDescriptor> annotationVec = vd.getType().getAnnotationMarkers();
101 for (int anIdx = 0; anIdx < annotationVec.size(); anIdx++) {
102 AnnotationDescriptor ad = annotationVec.elementAt(anIdx);
103 if (ad.getMarker().equals(SSJavaAnalysis.DELEGATE)) {
105 Set<VarDescriptor> delegateSet = md2DelegateParamSet.get(md);
106 if (delegateSet == null) {
107 delegateSet = new HashSet<VarDescriptor>();
108 md2DelegateParamSet.put(md, delegateSet);
118 private void checkMethodBody(ClassDescriptor cd, MethodDescriptor md) {
119 BlockNode bn = state.getMethodBody(md);
120 checkBlockNode(md, md.getParameterTable(), bn);
123 private void checkBlockNode(MethodDescriptor md, SymbolTable nametable, BlockNode bn) {
124 for (int i = 0; i < bn.size(); i++) {
125 BlockStatementNode bsn = bn.get(i);
126 checkBlockStatementNode(md, bn.getVarTable(), bsn);
130 private void checkBlockStatementNode(MethodDescriptor md, SymbolTable nametable,
131 BlockStatementNode bsn) {
133 if (needToNullify != null) {
134 if (!checkNullifying(bsn)) {
136 "Reference field, which is read by a method, should be assigned to null before executing any following statement of the reference copy statement at "
137 + md.getClassDesc().getSourceFileName() + "::" + bsn.getNumLine());
141 switch (bsn.kind()) {
143 case Kind.BlockExpressionNode:
144 checkBlockExpressionNode(md, nametable, (BlockExpressionNode) bsn);
147 case Kind.DeclarationNode:
148 checkDeclarationNode(md, nametable, (DeclarationNode) bsn);
151 case Kind.IfStatementNode:
152 checkIfStatementNode(md, nametable, (IfStatementNode) bsn);
155 case Kind.SwitchStatementNode:
156 checkSwitchStatementNode(md, nametable, (SwitchStatementNode) bsn);
160 checkLoopNode(md, nametable, (LoopNode) bsn);
163 case Kind.ReturnNode:
164 checkReturnNode(md, nametable, (ReturnNode) bsn);
167 case Kind.SubBlockNode:
168 checkSubBlockNode(md, nametable, (SubBlockNode) bsn);
171 case Kind.SynchronizedNode:
172 checkSynchronizedNode(md, nametable, (SynchronizedNode) bsn);
179 private void checkSynchronizedNode(MethodDescriptor md, SymbolTable nametable,
180 SynchronizedNode sbn) {
181 checkBlockNode(md, nametable, sbn.getBlockNode());
182 // todo this could be Object
183 checkExpressionNode(md, nametable, sbn.getExpr());
186 private void checkReturnNode(MethodDescriptor md, SymbolTable nametable, ReturnNode rn) {
187 if (rn.getReturnExpression() != null) {
188 checkExpressionNode(md, nametable, rn.getReturnExpression());
192 private void checkSubBlockNode(MethodDescriptor md, SymbolTable nametable, SubBlockNode sbn) {
193 checkBlockNode(md, nametable, sbn.getBlockNode());
196 private void checkIfStatementNode(MethodDescriptor md, SymbolTable nametable, IfStatementNode isn) {
197 checkExpressionNode(md, nametable, isn.getCondition());
198 checkBlockNode(md, nametable, isn.getTrueBlock());
199 if (isn.getFalseBlock() != null)
200 checkBlockNode(md, nametable, isn.getFalseBlock());
203 private void checkSwitchStatementNode(MethodDescriptor md, SymbolTable nametable,
204 SwitchStatementNode ssn) {
206 checkExpressionNode(md, nametable, ssn.getCondition());
208 BlockNode sbn = ssn.getSwitchBody();
209 for (int i = 0; i < sbn.size(); i++) {
210 checkSwitchBlockNode(md, nametable, (SwitchBlockNode) sbn.get(i));
214 private void checkSwitchBlockNode(MethodDescriptor md, SymbolTable nametable, SwitchBlockNode sbn) {
215 checkBlockNode(md, nametable, sbn.getSwitchBlockStatement());
218 private void checkBlockExpressionNode(MethodDescriptor md, SymbolTable nametable,
219 BlockExpressionNode ben) {
220 checkExpressionNode(md, nametable, ben.getExpression());
223 private void checkExpressionNode(MethodDescriptor md, SymbolTable nametable, ExpressionNode en) {
225 case Kind.AssignmentNode:
226 checkAssignmentNode(md, nametable, (AssignmentNode) en);
230 checkCastNode(md, nametable, (CastNode) en);
233 case Kind.CreateObjectNode:
234 checkCreateObjectNode(md, nametable, (CreateObjectNode) en);
237 case Kind.FieldAccessNode:
238 checkFieldAccessNode(md, nametable, (FieldAccessNode) en);
241 case Kind.ArrayAccessNode:
242 checkArrayAccessNode(md, nametable, (ArrayAccessNode) en);
245 // case Kind.LiteralNode:
246 // checkLiteralNode(md, nametable, (LiteralNode) en);
249 case Kind.MethodInvokeNode:
250 checkMethodInvokeNode(md, nametable, (MethodInvokeNode) en);
254 checkNameNode(md, nametable, (NameNode) en);
258 checkOpNode(md, nametable, (OpNode) en);
261 case Kind.OffsetNode:
262 checkOffsetNode(md, nametable, (OffsetNode) en);
265 case Kind.TertiaryNode:
266 checkTertiaryNode(md, nametable, (TertiaryNode) en);
269 // case Kind.InstanceOfNode:
270 // checkInstanceOfNode(md, nametable, (InstanceOfNode) en);
273 // case Kind.ArrayInitializerNode:
274 // checkArrayInitializerNode(md, nametable, (ArrayInitializerNode) en);
277 // case Kind.ClassTypeNode:
278 // checkClassTypeNode(md, nametable, (ClassTypeNode) ens);
284 private void checkTertiaryNode(MethodDescriptor md, SymbolTable nametable, TertiaryNode en) {
285 // TODO Auto-generated method stub
289 private void checkOffsetNode(MethodDescriptor md, SymbolTable nametable, OffsetNode en) {
290 // TODO Auto-generated method stub
294 private void checkOpNode(MethodDescriptor md, SymbolTable nametable, OpNode en) {
295 // TODO Auto-generated method stub
299 private void checkNameNode(MethodDescriptor md, SymbolTable nametable, NameNode en) {
300 // TODO Auto-generated method stub
304 private void checkMethodInvokeNode(MethodDescriptor md, SymbolTable nametable, MethodInvokeNode en) {
305 // TODO Auto-generated method stub
309 private void checkArrayAccessNode(MethodDescriptor md, SymbolTable nametable, ArrayAccessNode en) {
310 // TODO Auto-generated method stub
314 private void checkFieldAccessNode(MethodDescriptor md, SymbolTable nametable, FieldAccessNode fan) {
318 private void checkCreateObjectNode(MethodDescriptor md, SymbolTable nametable,
319 CreateObjectNode con) {
320 TypeDescriptor[] tdarray = new TypeDescriptor[con.numArgs()];
321 for (int i = 0; i < con.numArgs(); i++) {
322 ExpressionNode en = con.getArg(i);
323 checkExpressionNode(md, nametable, en);
324 tdarray[i] = en.getType();
327 if ((con.getArrayInitializer() != null)) {
328 checkArrayInitializerNode(md, nametable, con.getArrayInitializer());
333 private void checkArrayInitializerNode(MethodDescriptor md, SymbolTable nametable,
334 ArrayInitializerNode arrayInitializer) {
335 // TODO Auto-generated method stub
339 private void checkCastNode(MethodDescriptor md, SymbolTable nametable, CastNode cn) {
340 ExpressionNode en = cn.getExpression();
341 checkExpressionNode(md, nametable, en);
344 private boolean checkNullifying(BlockStatementNode bsn) {
346 if (bsn.kind() == Kind.BlockExpressionNode) {
347 ExpressionNode en = ((BlockExpressionNode) bsn).getExpression();
348 if (en.kind() == Kind.AssignmentNode) {
349 AssignmentNode an = (AssignmentNode) en;
351 if (an.getSrc().getType().isNull() && an.getDest().printNode(0).equals(needToNullify)) {
352 needToNullify = null;
361 private void checkLoopNode(MethodDescriptor md, SymbolTable nametable, LoopNode ln) {
362 if (ln.getType() == LoopNode.WHILELOOP || ln.getType() == LoopNode.DOWHILELOOP) {
363 checkExpressionNode(md, nametable, ln.getCondition());
364 checkBlockNode(md, nametable, ln.getBody());
367 /* Link in the initializer naming environment */
368 BlockNode bn = ln.getInitializer();
369 for (int i = 0; i < bn.size(); i++) {
370 BlockStatementNode bsn = bn.get(i);
371 checkBlockStatementNode(md, bn.getVarTable(), bsn);
373 // check the condition
374 checkExpressionNode(md, bn.getVarTable(), ln.getCondition());
375 checkBlockNode(md, bn.getVarTable(), ln.getBody());
376 checkBlockNode(md, bn.getVarTable(), ln.getUpdate());
380 private void checkAssignmentNode(Descriptor md, SymbolTable nametable, AssignmentNode an) {
381 needToNullify(an.getSrc());
384 private void checkDeclarationNode(Descriptor md, SymbolTable nametable, DeclarationNode dn) {
385 needToNullify(dn.getExpression());
388 private void needToNullify(ExpressionNode en) {
390 if (en != null && en.getType().isPtr() && !en.getType().isString()) {
391 if (en.kind() != Kind.CreateObjectNode && en.kind() != Kind.LiteralNode) {
392 if (en.kind() == Kind.CastNode) {
393 needToNullify = ((CastNode) en).getExpression().printNode(0);
395 needToNullify = en.printNode(0);