introduce new flag -ssjava for enabling SSJava feature and start working on the imple...
[IRC.git] / Robust / src / Analysis / SSJava / FlowDownCheck.java
1 package Analysis.SSJava;
2
3 import java.util.HashSet;
4 import java.util.Iterator;
5 import java.util.Set;
6 import java.util.Vector;
7
8 import IR.AnnotationDescriptor;
9 import IR.ClassDescriptor;
10 import IR.FieldDescriptor;
11 import IR.MethodDescriptor;
12 import IR.State;
13 import IR.SymbolTable;
14 import IR.TypeDescriptor;
15 import IR.VarDescriptor;
16 import IR.Tree.AssignmentNode;
17 import IR.Tree.BlockExpressionNode;
18 import IR.Tree.BlockNode;
19 import IR.Tree.BlockStatementNode;
20 import IR.Tree.DeclarationNode;
21 import IR.Tree.ExpressionNode;
22 import IR.Tree.Kind;
23 import Util.Lattice;
24
25 public class FlowDownCheck {
26
27   State state;
28   HashSet toanalyze;
29
30   public FlowDownCheck(State state) {
31     this.state = state;
32     this.toanalyze = new HashSet();
33   }
34
35   public void flowDownCheck() {
36
37     SymbolTable classtable = state.getClassSymbolTable();
38     toanalyze.addAll(classtable.getValueSet());
39     toanalyze.addAll(state.getTaskSymbolTable().getValueSet());
40
41     // Do methods next
42     while (!toanalyze.isEmpty()) {
43       Object obj = toanalyze.iterator().next();
44       ClassDescriptor cd = (ClassDescriptor) obj;
45       toanalyze.remove(cd);
46       if (cd.isClassLibrary()) {
47         // doesn't care about class libraries now
48         continue;
49       }
50
51       checkClass(cd);
52
53       for (Iterator method_it = cd.getMethods(); method_it.hasNext();) {
54         MethodDescriptor md = (MethodDescriptor) method_it.next();
55         try {
56           checkMethodBody(cd, md);
57         } catch (Error e) {
58           System.out.println("Error in " + md);
59           throw e;
60         }
61       }
62     }
63   }
64
65   public void checkMethodBody(ClassDescriptor cd, MethodDescriptor md) {
66     ClassDescriptor superdesc = cd.getSuperDesc();
67     if (superdesc != null) {
68       Set possiblematches = superdesc.getMethodTable().getSet(md.getSymbol());
69       for (Iterator methodit = possiblematches.iterator(); methodit.hasNext();) {
70         MethodDescriptor matchmd = (MethodDescriptor) methodit.next();
71         if (md.matches(matchmd)) {
72           if (matchmd.getModifiers().isFinal()) {
73             throw new Error("Try to override final method in method:" + md + " declared in  " + cd);
74           }
75         }
76       }
77     }
78     BlockNode bn = state.getMethodBody(md);
79     checkBlockNode(md, md.getParameterTable(), bn);
80   }
81
82   public void checkBlockNode(MethodDescriptor md, SymbolTable nametable, BlockNode bn) {
83     /* Link in the naming environment */
84     bn.getVarTable().setParent(nametable);
85     for (int i = 0; i < bn.size(); i++) {
86       BlockStatementNode bsn = bn.get(i);
87       checkBlockStatementNode(md, bn.getVarTable(), bsn);
88     }
89   }
90
91   public void checkBlockStatementNode(MethodDescriptor md, SymbolTable nametable,
92       BlockStatementNode bsn) {
93
94     switch (bsn.kind()) {
95     case Kind.BlockExpressionNode:
96       checkBlockExpressionNode(md, nametable, (BlockExpressionNode) bsn);
97       return;
98
99     case Kind.DeclarationNode:
100       checkDeclarationNode(md, (DeclarationNode) bsn);
101       return;
102     }
103     /*
104      * switch (bsn.kind()) { case Kind.BlockExpressionNode:
105      * checkBlockExpressionNode(md, nametable, (BlockExpressionNode) bsn);
106      * return;
107      * 
108      * case Kind.DeclarationNode: checkDeclarationNode(md, nametable,
109      * (DeclarationNode) bsn); return;
110      * 
111      * case Kind.TagDeclarationNode: checkTagDeclarationNode(md, nametable,
112      * (TagDeclarationNode) bsn); return;
113      * 
114      * case Kind.IfStatementNode: checkIfStatementNode(md, nametable,
115      * (IfStatementNode) bsn); return;
116      * 
117      * case Kind.SwitchStatementNode: checkSwitchStatementNode(md, nametable,
118      * (SwitchStatementNode) bsn); return;
119      * 
120      * case Kind.LoopNode: checkLoopNode(md, nametable, (LoopNode) bsn); return;
121      * 
122      * case Kind.ReturnNode: checkReturnNode(md, nametable, (ReturnNode) bsn);
123      * return;
124      * 
125      * case Kind.TaskExitNode: checkTaskExitNode(md, nametable, (TaskExitNode)
126      * bsn); return;
127      * 
128      * case Kind.SubBlockNode: checkSubBlockNode(md, nametable, (SubBlockNode)
129      * bsn); return;
130      * 
131      * case Kind.AtomicNode: checkAtomicNode(md, nametable, (AtomicNode) bsn);
132      * return;
133      * 
134      * case Kind.SynchronizedNode: checkSynchronizedNode(md, nametable,
135      * (SynchronizedNode) bsn); return;
136      * 
137      * case Kind.ContinueBreakNode: checkContinueBreakNode(md, nametable,
138      * (ContinueBreakNode) bsn); return;
139      * 
140      * case Kind.SESENode: case Kind.GenReachNode: // do nothing, no semantic
141      * check for SESEs return; }
142      */
143     // throw new Error();
144   }
145
146   void checkBlockExpressionNode(MethodDescriptor md, SymbolTable nametable, BlockExpressionNode ben) {
147     checkExpressionNode(md, nametable, ben.getExpression(), null);
148   }
149
150   void checkExpressionNode(MethodDescriptor md, SymbolTable nametable, ExpressionNode en,
151       TypeDescriptor td) {
152
153     switch (en.kind()) {
154     case Kind.AssignmentNode:
155       checkAssignmentNode(md, nametable, (AssignmentNode) en, td);
156       return;
157     }
158     /*
159      * switch(en.kind()) { case Kind.AssignmentNode:
160      * checkAssignmentNode(md,nametable,(AssignmentNode)en,td); return;
161      * 
162      * case Kind.CastNode: checkCastNode(md,nametable,(CastNode)en,td); return;
163      * 
164      * case Kind.CreateObjectNode:
165      * checkCreateObjectNode(md,nametable,(CreateObjectNode)en,td); return;
166      * 
167      * case Kind.FieldAccessNode:
168      * checkFieldAccessNode(md,nametable,(FieldAccessNode)en,td); return;
169      * 
170      * case Kind.ArrayAccessNode:
171      * checkArrayAccessNode(md,nametable,(ArrayAccessNode)en,td); return;
172      * 
173      * case Kind.LiteralNode: checkLiteralNode(md,nametable,(LiteralNode)en,td);
174      * return;
175      * 
176      * case Kind.MethodInvokeNode:
177      * checkMethodInvokeNode(md,nametable,(MethodInvokeNode)en,td); return;
178      * 
179      * case Kind.NameNode: checkNameNode(md,nametable,(NameNode)en,td); return;
180      * 
181      * case Kind.OpNode: checkOpNode(md,nametable,(OpNode)en,td); return;
182      * 
183      * case Kind.OffsetNode: checkOffsetNode(md, nametable, (OffsetNode)en, td);
184      * return;
185      * 
186      * case Kind.TertiaryNode: checkTertiaryNode(md, nametable,
187      * (TertiaryNode)en, td); return;
188      * 
189      * case Kind.InstanceOfNode: checkInstanceOfNode(md, nametable,
190      * (InstanceOfNode) en, td); return;
191      * 
192      * case Kind.ArrayInitializerNode: checkArrayInitializerNode(md, nametable,
193      * (ArrayInitializerNode) en, td); return;
194      * 
195      * case Kind.ClassTypeNode: checkClassTypeNode(md, nametable,
196      * (ClassTypeNode) en, td); return; }
197      */
198   }
199
200   void checkAssignmentNode(MethodDescriptor md, SymbolTable nametable, AssignmentNode an,
201       TypeDescriptor td) {
202
203     ClassDescriptor cd = md.getClassDesc();
204     Lattice<String> locOrder = (Lattice<String>) state.getCd2LocationOrder().get(cd);
205
206     String destLocation = an.getDest().getType().getAnnotationMarkers().elementAt(0).getMarker();
207     String srcLocation = an.getSrc().getType().getAnnotationMarkers().elementAt(0).getMarker();
208
209     if (!locOrder.isGreaterThan(srcLocation, destLocation)) {
210       throw new Error("Value flow from " + srcLocation + " to " + destLocation
211           + "does not respect location hierarchy.");
212     }
213
214   }
215
216   void checkDeclarationNode(MethodDescriptor md, DeclarationNode dn) {
217
218     ClassDescriptor cd = md.getClassDesc();
219     VarDescriptor vd = dn.getVarDescriptor();
220     Vector<AnnotationDescriptor> annotationVec = vd.getType().getAnnotationMarkers();
221
222     // currently enforce every variable to have corresponding location
223     if (annotationVec.size() == 0) {
224       throw new Error("Location is not assigned to variable " + vd.getSymbol() + " in the method "
225           + md.getSymbol() + " of the class " + cd.getSymbol());
226     }
227
228     if (annotationVec.size() > 1) {
229       // variable can have at most one location
230       throw new Error(vd.getSymbol() + " has more than one location.");
231     }
232
233     // check if location is defined
234     String locationID = annotationVec.elementAt(0).getMarker();
235     Lattice<String> lattice = (Lattice<String>) state.getCd2LocationOrder().get(cd);
236
237     if (lattice == null || (!lattice.containsKey(locationID))) {
238       throw new Error("Location " + locationID
239           + " is not defined in the location hierarchy of class " + cd.getSymbol() + ".");
240     }
241
242   }
243
244   private void checkClass(ClassDescriptor cd) {
245     // Check to see that fields are okay
246     for (Iterator field_it = cd.getFields(); field_it.hasNext();) {
247       FieldDescriptor fd = (FieldDescriptor) field_it.next();
248       checkFieldDeclaration(cd, fd);
249     }
250
251     // Check to see that methods respects ss property
252     for (Iterator method_it = cd.getMethods(); method_it.hasNext();) {
253       MethodDescriptor md = (MethodDescriptor) method_it.next();
254       checkMethodDeclaration(cd, md);
255     }
256   }
257
258   private void checkMethodDeclaration(ClassDescriptor cd, MethodDescriptor md) {
259
260   }
261
262   private void checkFieldDeclaration(ClassDescriptor cd, FieldDescriptor fd) {
263
264     Vector<AnnotationDescriptor> annotationVec = fd.getType().getAnnotationMarkers();
265
266     // currently enforce every variable to have corresponding location
267     if (annotationVec.size() == 0) {
268       throw new Error("Location is not assigned to the field " + fd.getSymbol() + " of the class "
269           + cd.getSymbol());
270     }
271
272     if (annotationVec.size() > 1) {
273       // variable can have at most one location
274       throw new Error("Field " + fd.getSymbol() + " of class " + cd
275           + " has more than one location.");
276     }
277
278     // check if location is defined
279     String locationID = annotationVec.elementAt(0).getMarker();
280     Lattice<String> lattice = (Lattice<String>) state.getCd2LocationOrder().get(cd);
281
282     if (lattice == null || (!lattice.containsKey(locationID))) {
283       throw new Error("Location " + locationID
284           + " is not defined in the location hierarchy of class " + cd.getSymbol() + ".");
285     }
286
287   }
288 }