1 package Analysis.SSJava;
3 import java.util.HashSet;
4 import java.util.Iterator;
6 import java.util.Vector;
8 import IR.AnnotationDescriptor;
9 import IR.ClassDescriptor;
10 import IR.FieldDescriptor;
11 import IR.MethodDescriptor;
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;
25 public class FlowDownCheck {
30 public FlowDownCheck(State state) {
32 this.toanalyze = new HashSet();
35 public void flowDownCheck() {
37 SymbolTable classtable = state.getClassSymbolTable();
38 toanalyze.addAll(classtable.getValueSet());
39 toanalyze.addAll(state.getTaskSymbolTable().getValueSet());
42 while (!toanalyze.isEmpty()) {
43 Object obj = toanalyze.iterator().next();
44 ClassDescriptor cd = (ClassDescriptor) obj;
46 if (cd.isClassLibrary()) {
47 // doesn't care about class libraries now
53 for (Iterator method_it = cd.getMethods(); method_it.hasNext();) {
54 MethodDescriptor md = (MethodDescriptor) method_it.next();
56 checkMethodBody(cd, md);
58 System.out.println("Error in " + md);
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);
78 BlockNode bn = state.getMethodBody(md);
79 checkBlockNode(md, md.getParameterTable(), bn);
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);
91 public void checkBlockStatementNode(MethodDescriptor md, SymbolTable nametable,
92 BlockStatementNode bsn) {
95 case Kind.BlockExpressionNode:
96 checkBlockExpressionNode(md, nametable, (BlockExpressionNode) bsn);
99 case Kind.DeclarationNode:
100 checkDeclarationNode(md, (DeclarationNode) bsn);
104 * switch (bsn.kind()) { case Kind.BlockExpressionNode:
105 * checkBlockExpressionNode(md, nametable, (BlockExpressionNode) bsn);
108 * case Kind.DeclarationNode: checkDeclarationNode(md, nametable,
109 * (DeclarationNode) bsn); return;
111 * case Kind.TagDeclarationNode: checkTagDeclarationNode(md, nametable,
112 * (TagDeclarationNode) bsn); return;
114 * case Kind.IfStatementNode: checkIfStatementNode(md, nametable,
115 * (IfStatementNode) bsn); return;
117 * case Kind.SwitchStatementNode: checkSwitchStatementNode(md, nametable,
118 * (SwitchStatementNode) bsn); return;
120 * case Kind.LoopNode: checkLoopNode(md, nametable, (LoopNode) bsn); return;
122 * case Kind.ReturnNode: checkReturnNode(md, nametable, (ReturnNode) bsn);
125 * case Kind.TaskExitNode: checkTaskExitNode(md, nametable, (TaskExitNode)
128 * case Kind.SubBlockNode: checkSubBlockNode(md, nametable, (SubBlockNode)
131 * case Kind.AtomicNode: checkAtomicNode(md, nametable, (AtomicNode) bsn);
134 * case Kind.SynchronizedNode: checkSynchronizedNode(md, nametable,
135 * (SynchronizedNode) bsn); return;
137 * case Kind.ContinueBreakNode: checkContinueBreakNode(md, nametable,
138 * (ContinueBreakNode) bsn); return;
140 * case Kind.SESENode: case Kind.GenReachNode: // do nothing, no semantic
141 * check for SESEs return; }
143 // throw new Error();
146 void checkBlockExpressionNode(MethodDescriptor md, SymbolTable nametable, BlockExpressionNode ben) {
147 checkExpressionNode(md, nametable, ben.getExpression(), null);
150 void checkExpressionNode(MethodDescriptor md, SymbolTable nametable, ExpressionNode en,
154 case Kind.AssignmentNode:
155 checkAssignmentNode(md, nametable, (AssignmentNode) en, td);
159 * switch(en.kind()) { case Kind.AssignmentNode:
160 * checkAssignmentNode(md,nametable,(AssignmentNode)en,td); return;
162 * case Kind.CastNode: checkCastNode(md,nametable,(CastNode)en,td); return;
164 * case Kind.CreateObjectNode:
165 * checkCreateObjectNode(md,nametable,(CreateObjectNode)en,td); return;
167 * case Kind.FieldAccessNode:
168 * checkFieldAccessNode(md,nametable,(FieldAccessNode)en,td); return;
170 * case Kind.ArrayAccessNode:
171 * checkArrayAccessNode(md,nametable,(ArrayAccessNode)en,td); return;
173 * case Kind.LiteralNode: checkLiteralNode(md,nametable,(LiteralNode)en,td);
176 * case Kind.MethodInvokeNode:
177 * checkMethodInvokeNode(md,nametable,(MethodInvokeNode)en,td); return;
179 * case Kind.NameNode: checkNameNode(md,nametable,(NameNode)en,td); return;
181 * case Kind.OpNode: checkOpNode(md,nametable,(OpNode)en,td); return;
183 * case Kind.OffsetNode: checkOffsetNode(md, nametable, (OffsetNode)en, td);
186 * case Kind.TertiaryNode: checkTertiaryNode(md, nametable,
187 * (TertiaryNode)en, td); return;
189 * case Kind.InstanceOfNode: checkInstanceOfNode(md, nametable,
190 * (InstanceOfNode) en, td); return;
192 * case Kind.ArrayInitializerNode: checkArrayInitializerNode(md, nametable,
193 * (ArrayInitializerNode) en, td); return;
195 * case Kind.ClassTypeNode: checkClassTypeNode(md, nametable,
196 * (ClassTypeNode) en, td); return; }
200 void checkAssignmentNode(MethodDescriptor md, SymbolTable nametable, AssignmentNode an,
203 ClassDescriptor cd = md.getClassDesc();
204 Lattice<String> locOrder = (Lattice<String>) state.getCd2LocationOrder().get(cd);
206 String destLocation = an.getDest().getType().getAnnotationMarkers().elementAt(0).getMarker();
207 String srcLocation = an.getSrc().getType().getAnnotationMarkers().elementAt(0).getMarker();
209 if (!locOrder.isGreaterThan(srcLocation, destLocation)) {
210 throw new Error("Value flow from " + srcLocation + " to " + destLocation
211 + "does not respect location hierarchy.");
216 void checkDeclarationNode(MethodDescriptor md, DeclarationNode dn) {
218 ClassDescriptor cd = md.getClassDesc();
219 VarDescriptor vd = dn.getVarDescriptor();
220 Vector<AnnotationDescriptor> annotationVec = vd.getType().getAnnotationMarkers();
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());
228 if (annotationVec.size() > 1) {
229 // variable can have at most one location
230 throw new Error(vd.getSymbol() + " has more than one location.");
233 // check if location is defined
234 String locationID = annotationVec.elementAt(0).getMarker();
235 Lattice<String> lattice = (Lattice<String>) state.getCd2LocationOrder().get(cd);
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() + ".");
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);
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);
258 private void checkMethodDeclaration(ClassDescriptor cd, MethodDescriptor md) {
262 private void checkFieldDeclaration(ClassDescriptor cd, FieldDescriptor fd) {
264 Vector<AnnotationDescriptor> annotationVec = fd.getType().getAnnotationMarkers();
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 "
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.");
278 // check if location is defined
279 String locationID = annotationVec.elementAt(0).getMarker();
280 Lattice<String> lattice = (Lattice<String>) state.getCd2LocationOrder().get(cd);
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() + ".");