changes.
[IRC.git] / Robust / src / Analysis / SSJava / LinearTypeCheck.java
1 package Analysis.SSJava;
2
3 import java.util.ArrayList;
4 import java.util.Collections;
5 import java.util.Comparator;
6 import java.util.HashSet;
7 import java.util.Hashtable;
8 import java.util.Iterator;
9 import java.util.List;
10 import java.util.Set;
11 import java.util.Vector;
12
13 import Analysis.Liveness;
14 import IR.AnnotationDescriptor;
15 import IR.ClassDescriptor;
16 import IR.MethodDescriptor;
17 import IR.Operation;
18 import IR.State;
19 import IR.SymbolTable;
20 import IR.TypeDescriptor;
21 import IR.VarDescriptor;
22 import IR.Flat.FKind;
23 import IR.Flat.FlatMethod;
24 import IR.Flat.FlatNode;
25 import IR.Flat.FlatOpNode;
26 import IR.Flat.TempDescriptor;
27 import IR.Tree.ArrayAccessNode;
28 import IR.Tree.ArrayInitializerNode;
29 import IR.Tree.AssignmentNode;
30 import IR.Tree.BlockExpressionNode;
31 import IR.Tree.BlockNode;
32 import IR.Tree.BlockStatementNode;
33 import IR.Tree.CastNode;
34 import IR.Tree.CreateObjectNode;
35 import IR.Tree.DeclarationNode;
36 import IR.Tree.ExpressionNode;
37 import IR.Tree.FieldAccessNode;
38 import IR.Tree.IfStatementNode;
39 import IR.Tree.Kind;
40 import IR.Tree.LoopNode;
41 import IR.Tree.MethodInvokeNode;
42 import IR.Tree.NameNode;
43 import IR.Tree.OffsetNode;
44 import IR.Tree.OpNode;
45 import IR.Tree.ReturnNode;
46 import IR.Tree.SubBlockNode;
47 import IR.Tree.SwitchBlockNode;
48 import IR.Tree.SwitchStatementNode;
49 import IR.Tree.SynchronizedNode;
50 import IR.Tree.TertiaryNode;
51 import IR.Tree.TreeNode;
52
53 public class LinearTypeCheck {
54
55   State state;
56   SSJavaAnalysis ssjava;
57   String needToNullify = null;
58   AssignmentNode prevAssignNode;
59
60   Set<TreeNode> linearTypeCheckSet;
61
62   Hashtable<TreeNode, FlatMethod> mapTreeNode2FlatMethod;
63
64   Set<MethodDescriptor> delegateThisMethodSet;
65
66   Liveness liveness;
67
68   boolean deterministic = true;
69
70   public LinearTypeCheck(SSJavaAnalysis ssjava, State state) {
71     this.ssjava = ssjava;
72     this.state = state;
73     this.linearTypeCheckSet = new HashSet<TreeNode>();
74     this.mapTreeNode2FlatMethod = new Hashtable<TreeNode, FlatMethod>();
75     this.delegateThisMethodSet = new HashSet<MethodDescriptor>();
76     this.liveness = new Liveness();
77   }
78
79   public void linearTypeCheck() {
80
81     // first, parsing DELEGATE annotation from method declarations
82     Iterator it = state.getClassSymbolTable().getDescriptorsIterator();
83     while (it.hasNext()) {
84       ClassDescriptor cd = (ClassDescriptor) it.next();
85       for (Iterator method_it = cd.getMethods(); method_it.hasNext();) {
86         MethodDescriptor md = (MethodDescriptor) method_it.next();
87         parseAnnotations(md);
88       }
89     }
90
91     // second, check the linear type
92     if (deterministic) {
93
94       SymbolTable classtable = state.getClassSymbolTable();
95
96       List<ClassDescriptor> toanalyzeList = new ArrayList<ClassDescriptor>();
97       List<MethodDescriptor> toanalyzeMethodList = new ArrayList<MethodDescriptor>();
98
99       toanalyzeList.addAll(classtable.getValueSet());
100       Collections.sort(toanalyzeList, new Comparator<ClassDescriptor>() {
101         public int compare(ClassDescriptor o1, ClassDescriptor o2) {
102           return o1.getClassName().compareTo(o2.getClassName());
103         }
104       });
105
106       for (int i = 0; i < toanalyzeList.size(); i++) {
107         ClassDescriptor cd = toanalyzeList.get(i);
108
109         SymbolTable methodtable = cd.getMethodTable();
110         toanalyzeMethodList.clear();
111         toanalyzeMethodList.addAll(methodtable.getValueSet());
112         Collections.sort(toanalyzeMethodList, new Comparator<MethodDescriptor>() {
113           public int compare(MethodDescriptor o1, MethodDescriptor o2) {
114             return o1.getSymbol().compareTo(o2.getSymbol());
115           }
116         });
117
118         for (int mdIdx = 0; mdIdx < toanalyzeMethodList.size(); mdIdx++) {
119           MethodDescriptor md = toanalyzeMethodList.get(mdIdx);
120           checkMethodBody(cd, md);
121         }
122
123       }
124
125     } else {
126       it = state.getClassSymbolTable().getDescriptorsIterator();
127       while (it.hasNext()) {
128         ClassDescriptor cd = (ClassDescriptor) it.next();
129         for (Iterator method_it = cd.getMethods(); method_it.hasNext();) {
130           MethodDescriptor md = (MethodDescriptor) method_it.next();
131           checkMethodBody(cd, md);
132         }
133       }
134     }
135
136     // third, check if original references are destroyed after creating new
137     // alias
138
139     for (Iterator<TreeNode> iterator = linearTypeCheckSet.iterator(); iterator.hasNext();) {
140       TreeNode tn = iterator.next();
141       Set<FlatNode> fnSet = ssjava.getBuildFlat().getFlatNodeSet(tn);
142       if (fnSet != null) {
143         for (Iterator iterator2 = fnSet.iterator(); iterator2.hasNext();) {
144           FlatNode fn = (FlatNode) iterator2.next();
145           if (isLiveOut(tn, fn)) {
146             throw new Error(
147                 "Local variable '"
148                     + tn.printNode(0)
149                     + "', which is read by a method, should be destroyed after introducing new alias at "
150                     + mapTreeNode2FlatMethod.get(tn).getMethod().getClassDesc().getSourceFileName()
151                     + "::" + tn.getNumLine());
152           }
153
154         }
155       }
156
157     }
158
159   }
160
161   private boolean isLiveOut(TreeNode tn, FlatNode fn) {
162     Set<TempDescriptor> liveOutTemp = liveness.getLiveOutTemps(mapTreeNode2FlatMethod.get(tn), fn);
163     if (fn.kind() == FKind.FlatOpNode) {
164       FlatOpNode fon = (FlatOpNode) fn;
165       return liveOutTemp.contains(fon.getLeft());
166     }
167     return false;
168   }
169
170   private void parseAnnotations(MethodDescriptor md) {
171
172     // method annotation parsing
173     Vector<AnnotationDescriptor> methodAnnotations = md.getModifiers().getAnnotations();
174     if (methodAnnotations != null) {
175       for (int i = 0; i < methodAnnotations.size(); i++) {
176         AnnotationDescriptor an = methodAnnotations.elementAt(i);
177         if (an.getMarker().equals(ssjava.DELEGATETHIS)) {
178           delegateThisMethodSet.add(md);
179           md.getThis().getType().setExtension(new SSJavaType(true));
180         }
181       }
182     }
183
184     // paramter annotation parsing
185     for (int i = 0; i < md.numParameters(); i++) {
186       // process annotations on method parameters
187       VarDescriptor vd = (VarDescriptor) md.getParameter(i);
188
189       Vector<AnnotationDescriptor> annotationVec = vd.getType().getAnnotationMarkers();
190
191       for (int anIdx = 0; anIdx < annotationVec.size(); anIdx++) {
192         AnnotationDescriptor ad = annotationVec.elementAt(anIdx);
193         if (ad.getMarker().equals(SSJavaAnalysis.DELEGATE)) {
194           SSJavaType locationType = new SSJavaType(true);
195           vd.getType().setExtension(locationType);
196         }
197       }
198     }
199   }
200
201   private void checkMethodBody(ClassDescriptor cd, MethodDescriptor md) {
202     BlockNode bn = state.getMethodBody(md);
203     checkBlockNode(md, md.getParameterTable(), bn);
204   }
205
206   private void checkBlockNode(MethodDescriptor md, SymbolTable nametable, BlockNode bn) {
207     for (int i = 0; i < bn.size(); i++) {
208       BlockStatementNode bsn = bn.get(i);
209       checkBlockStatementNode(md, bn.getVarTable(), bsn);
210     }
211   }
212
213   private void checkBlockStatementNode(MethodDescriptor md, SymbolTable nametable,
214       BlockStatementNode bsn) {
215
216     if (needToNullify != null) {
217       if (!checkNullifying(bsn)) {
218         throw new Error(
219             "Reference field '"
220                 + needToNullify
221                 + "', which is read by a method, should be assigned to null before executing any following statement of the reference copy statement at "
222                 + md.getClassDesc().getSourceFileName() + "::" + prevAssignNode.getNumLine());
223       }
224     }
225
226     switch (bsn.kind()) {
227
228     case Kind.BlockExpressionNode:
229       checkBlockExpressionNode(md, nametable, (BlockExpressionNode) bsn);
230       return;
231
232     case Kind.DeclarationNode:
233       checkDeclarationNode(md, nametable, (DeclarationNode) bsn);
234       return;
235
236     case Kind.IfStatementNode:
237       checkIfStatementNode(md, nametable, (IfStatementNode) bsn);
238       return;
239
240     case Kind.SwitchStatementNode:
241       checkSwitchStatementNode(md, nametable, (SwitchStatementNode) bsn);
242       return;
243
244     case Kind.LoopNode:
245       checkLoopNode(md, nametable, (LoopNode) bsn);
246       return;
247
248     case Kind.ReturnNode:
249       checkReturnNode(md, nametable, (ReturnNode) bsn);
250       return;
251
252     case Kind.SubBlockNode:
253       checkSubBlockNode(md, nametable, (SubBlockNode) bsn);
254       return;
255
256     case Kind.SynchronizedNode:
257       checkSynchronizedNode(md, nametable, (SynchronizedNode) bsn);
258       return;
259     }
260
261   }
262
263   private void checkSynchronizedNode(MethodDescriptor md, SymbolTable nametable,
264       SynchronizedNode sbn) {
265     checkBlockNode(md, nametable, sbn.getBlockNode());
266     // todo this could be Object
267     checkExpressionNode(md, nametable, sbn.getExpr());
268   }
269
270   private void checkReturnNode(MethodDescriptor md, SymbolTable nametable, ReturnNode rn) {
271     if (rn.getReturnExpression() != null) {
272       checkExpressionNode(md, nametable, rn.getReturnExpression());
273     }
274   }
275
276   private void checkSubBlockNode(MethodDescriptor md, SymbolTable nametable, SubBlockNode sbn) {
277     checkBlockNode(md, nametable, sbn.getBlockNode());
278   }
279
280   private void checkIfStatementNode(MethodDescriptor md, SymbolTable nametable, IfStatementNode isn) {
281     checkExpressionNode(md, nametable, isn.getCondition());
282     checkBlockNode(md, nametable, isn.getTrueBlock());
283     if (isn.getFalseBlock() != null)
284       checkBlockNode(md, nametable, isn.getFalseBlock());
285   }
286
287   private void checkSwitchStatementNode(MethodDescriptor md, SymbolTable nametable,
288       SwitchStatementNode ssn) {
289
290     checkExpressionNode(md, nametable, ssn.getCondition());
291
292     BlockNode sbn = ssn.getSwitchBody();
293     for (int i = 0; i < sbn.size(); i++) {
294       checkSwitchBlockNode(md, nametable, (SwitchBlockNode) sbn.get(i));
295     }
296   }
297
298   private void checkSwitchBlockNode(MethodDescriptor md, SymbolTable nametable, SwitchBlockNode sbn) {
299     checkBlockNode(md, nametable, sbn.getSwitchBlockStatement());
300   }
301
302   private void checkBlockExpressionNode(MethodDescriptor md, SymbolTable nametable,
303       BlockExpressionNode ben) {
304     checkExpressionNode(md, nametable, ben.getExpression());
305   }
306
307   private void checkExpressionNode(MethodDescriptor md, SymbolTable nametable, ExpressionNode en) {
308     switch (en.kind()) {
309     case Kind.AssignmentNode:
310       checkAssignmentNode(md, nametable, (AssignmentNode) en);
311       return;
312
313     case Kind.CastNode:
314       checkCastNode(md, nametable, (CastNode) en);
315       return;
316
317     case Kind.CreateObjectNode:
318       checkCreateObjectNode(md, nametable, (CreateObjectNode) en);
319       return;
320
321     case Kind.FieldAccessNode:
322       checkFieldAccessNode(md, nametable, (FieldAccessNode) en);
323       return;
324
325     case Kind.ArrayAccessNode:
326       checkArrayAccessNode(md, nametable, (ArrayAccessNode) en);
327       return;
328
329       // case Kind.LiteralNode:
330       // checkLiteralNode(md, nametable, (LiteralNode) en);
331       // return;
332
333     case Kind.MethodInvokeNode:
334       checkMethodInvokeNode(md, nametable, (MethodInvokeNode) en);
335       return;
336
337     case Kind.NameNode:
338       checkNameNode(md, nametable, (NameNode) en);
339       return;
340
341     case Kind.OpNode:
342       checkOpNode(md, nametable, (OpNode) en);
343       return;
344
345     case Kind.OffsetNode:
346       checkOffsetNode(md, nametable, (OffsetNode) en);
347       return;
348
349     case Kind.TertiaryNode:
350       checkTertiaryNode(md, nametable, (TertiaryNode) en);
351       return;
352
353       // case Kind.InstanceOfNode:
354       // checkInstanceOfNode(md, nametable, (InstanceOfNode) en);
355       // return;
356
357       // case Kind.ArrayInitializerNode:
358       // checkArrayInitializerNode(md, nametable, (ArrayInitializerNode) en);
359       // return;
360
361       // case Kind.ClassTypeNode:
362       // checkClassTypeNode(md, nametable, (ClassTypeNode) ens);
363       // return;
364     }
365   }
366
367   private void checkTertiaryNode(MethodDescriptor md, SymbolTable nametable, TertiaryNode en) {
368     // TODO Auto-generated method stub
369
370   }
371
372   private void checkOffsetNode(MethodDescriptor md, SymbolTable nametable, OffsetNode en) {
373     // TODO Auto-generated method stub
374
375   }
376
377   private void checkOpNode(MethodDescriptor md, SymbolTable nametable, OpNode en) {
378     // TODO Auto-generated method stub
379
380   }
381
382   private void checkNameNode(MethodDescriptor md, SymbolTable nametable, NameNode en) {
383     // TODO Auto-generated method stub
384
385   }
386
387   private boolean isOwned(VarDescriptor varDesc) {
388     if (varDesc.getType().getExtension() != null) {
389       SSJavaType locationType = (SSJavaType) varDesc.getType().getExtension();
390       return locationType.isOwned();
391     }
392     return false;
393   }
394
395   private void checkMethodInvokeNode(MethodDescriptor md, SymbolTable nametable,
396       MethodInvokeNode min) {
397
398     MethodDescriptor calleeMethodDesc = min.getMethod();
399
400     // check delegate_this annotation
401     // only method that owns itself 'THIS' can call method with delegate_this
402     // annotation
403
404     if (delegateThisMethodSet.contains(calleeMethodDesc)) {
405
406       if (min.getBaseName() == null) {
407         if (!delegateThisMethodSet.contains(md)) {
408           throw new Error("Caller does not own the 'THIS' argument at " + md.getClassDesc() + "::"
409               + min.getNumLine());
410         }
411       } else {
412         VarDescriptor baseVar = (VarDescriptor) nametable.get(min.getBaseName().getIdentifier());
413         if (!isOwned(baseVar)) {
414           throw new Error("Caller does not own the 'THIS' argument at " + md.getClassDesc() + "::"
415               + min.getNumLine());
416         }
417       }
418     }
419
420     // check delegate parameter annotation
421     for (int i = 0; i < min.numArgs(); i++) {
422       ExpressionNode argNode = min.getArg(i);
423
424       TypeDescriptor paramType = calleeMethodDesc.getParamType(i);
425
426       if (isReference(argNode.getType())) {
427
428         boolean isParamOwnedByCallee = false;
429         if (paramType.getExtension() != null) {
430           SSJavaType locationType = (SSJavaType) paramType.getExtension();
431           isParamOwnedByCallee = locationType.isOwned();
432         }
433
434         TypeDescriptor argType = getTypeDescriptor(argNode);
435
436         if (isParamOwnedByCallee) {
437
438           // cannot pass field reference through ownership transition
439           if (isField(argNode)) {
440             throw new Error("Caller cannot transfer its ownership of the field reference at "
441                 + md.getClassDesc() + "::" + min.getNumLine());
442           }
443
444           // method expects that argument is owned by caller
445           SSJavaType locationType = (SSJavaType) argType.getExtension();
446
447           if (locationType == null || !locationType.isOwned()) {
448             throw new Error("Caller passes an argument not owned by itself at " + md.getClassDesc()
449                 + "::" + min.getNumLine());
450           }
451
452         }
453
454       }
455     }
456
457   }
458
459   private void checkArrayAccessNode(MethodDescriptor md, SymbolTable nametable, ArrayAccessNode en) {
460     // TODO Auto-generated method stub
461
462   }
463
464   private void checkFieldAccessNode(MethodDescriptor md, SymbolTable nametable, FieldAccessNode fan) {
465
466   }
467
468   private void checkCreateObjectNode(MethodDescriptor md, SymbolTable nametable,
469       CreateObjectNode con) {
470
471     TypeDescriptor[] tdarray = new TypeDescriptor[con.numArgs()];
472     for (int i = 0; i < con.numArgs(); i++) {
473       ExpressionNode en = con.getArg(i);
474       checkExpressionNode(md, nametable, en);
475       tdarray[i] = en.getType();
476     }
477
478     if ((con.getArrayInitializer() != null)) {
479       checkArrayInitializerNode(md, nametable, con.getArrayInitializer());
480     }
481
482     // the current method owns a instance that it makes inside
483     SSJavaType locationType = new SSJavaType(true);
484     con.getType().setExtension(locationType);
485
486   }
487
488   private void checkArrayInitializerNode(MethodDescriptor md, SymbolTable nametable,
489       ArrayInitializerNode arrayInitializer) {
490     // TODO Auto-generated method stub
491
492   }
493
494   private void checkCastNode(MethodDescriptor md, SymbolTable nametable, CastNode cn) {
495     ExpressionNode en = cn.getExpression();
496     checkExpressionNode(md, nametable, en);
497   }
498
499   private boolean checkNullifying(BlockStatementNode bsn) {
500
501     if (bsn.kind() == Kind.BlockExpressionNode) {
502       ExpressionNode en = ((BlockExpressionNode) bsn).getExpression();
503       if (en.kind() == Kind.AssignmentNode) {
504         AssignmentNode an = (AssignmentNode) en;
505
506         String destName = an.getDest().printNode(0);
507         if (destName.startsWith("this.")) {
508           destName = destName.substring(5);
509         }
510
511         if (an.getSrc().getType().isNull() && destName.equals(needToNullify)) {
512           needToNullify = null;
513           return true;
514         }
515       }
516     }
517
518     return false;
519   }
520
521   private void checkLoopNode(MethodDescriptor md, SymbolTable nametable, LoopNode ln) {
522     if (ln.getType() == LoopNode.WHILELOOP || ln.getType() == LoopNode.DOWHILELOOP) {
523       checkExpressionNode(md, nametable, ln.getCondition());
524       checkBlockNode(md, nametable, ln.getBody());
525     } else {
526       // For loop case
527       /* Link in the initializer naming environment */
528       BlockNode bn = ln.getInitializer();
529       for (int i = 0; i < bn.size(); i++) {
530         BlockStatementNode bsn = bn.get(i);
531         checkBlockStatementNode(md, bn.getVarTable(), bsn);
532       }
533       // check the condition
534       checkExpressionNode(md, bn.getVarTable(), ln.getCondition());
535       checkBlockNode(md, bn.getVarTable(), ln.getBody());
536       checkBlockNode(md, bn.getVarTable(), ln.getUpdate());
537     }
538   }
539
540   private void checkAssignmentNode(MethodDescriptor md, SymbolTable nametable, AssignmentNode an) {
541
542     boolean postinc = true;
543     if (an.getOperation().getBaseOp() == null
544         || (an.getOperation().getBaseOp().getOp() != Operation.POSTINC && an.getOperation()
545             .getBaseOp().getOp() != Operation.POSTDEC))
546       postinc = false;
547
548     if (!postinc) {
549
550       checkExpressionNode(md, nametable, an.getSrc());
551
552       if (isReference(an.getSrc().getType()) && isReference(an.getDest().getType())) {
553
554         if (an.getSrc().kind() == Kind.NameNode) {
555
556           NameNode nn = (NameNode) an.getSrc();
557
558           if (nn.getField() != null) {
559             needToNullify = nn.getField().getSymbol();
560             prevAssignNode = an;
561           } else if (nn.getExpression() != null) {
562             if (nn.getExpression() instanceof FieldAccessNode) {
563               FieldAccessNode fan = (FieldAccessNode) nn.getExpression();
564               needToNullify = fan.printNode(0);
565               prevAssignNode = an;
566
567             }
568
569           } else {
570             // local variable case
571             linearTypeCheckSet.add(an.getSrc());
572             mapTreeNode2FlatMethod.put(an.getSrc(), state.getMethodFlat(md));
573           }
574         } else if (an.getSrc().kind() == Kind.FieldAccessNode) {
575           FieldAccessNode fan = (FieldAccessNode) an.getSrc();
576           needToNullify = fan.printNode(0);
577           if (needToNullify.startsWith("this.")) {
578             needToNullify = needToNullify.substring(5);
579           }
580           prevAssignNode = an;
581         } else if (an.getSrc().kind() == Kind.ArrayAccessNode) {
582           if (an.getSrc().getType().isPtr()) {
583             throw new Error(
584                 "Not allowed to create an alias to the middle of the multidimensional array at "
585                     + md.getClassDesc().getSourceFileName() + "::" + an.getNumLine());
586           }
587         }
588
589         if (isCreatingAlias(an.getSrc())) {
590
591           TypeDescriptor srcType = getTypeDescriptor(an.getSrc());
592           boolean isSourceOwned = false;
593
594           if (srcType.getExtension() != null) {
595             SSJavaType srcLocationType = (SSJavaType) srcType.getExtension();
596             isSourceOwned = srcLocationType.isOwned();
597           }
598
599           if (!isField(an.getDest()) && isSourceOwned) {
600             // here, transfer ownership from LHS to RHS when it creates alias
601             TypeDescriptor destType = getTypeDescriptor(an.getDest());
602             destType.setExtension(new SSJavaType(isSourceOwned));
603           } else {
604             // if instance is not owned by the method, not able to store
605             // instance into field
606             if (!isSourceOwned) {
607               throw new Error(
608                   "Method is not allowed to store an instance not owned by itself into a field at "
609                       + md.getClassDesc().getSourceFileName() + "::" + an.getNumLine());
610             }
611           }
612
613         }
614
615       }
616
617     }
618
619   }
620
621   private boolean isCreatingAlias(ExpressionNode en) {
622
623     int kind = en.kind();
624     if (kind == Kind.NameNode || kind == Kind.ArrayAccessNode || kind == Kind.FieldAccessNode) {
625       return true;
626     }
627     return false;
628
629   }
630
631   private TypeDescriptor getTypeDescriptor(ExpressionNode en) {
632
633     if (en.kind() == Kind.NameNode) {
634       NameNode nn = (NameNode) en;
635       if (nn.getField() != null) {
636         return nn.getVar().getType();
637       } else if (nn.getVar() != null) {
638         return nn.getVar().getType();
639       } else {
640         return getTypeDescriptor(nn.getExpression());
641       }
642     } else if (en.kind() == Kind.FieldAccessNode) {
643       FieldAccessNode fan = (FieldAccessNode) en;
644       return getTypeDescriptor(fan.getExpression());
645     } else if (en.kind() == Kind.CreateObjectNode) {
646       CreateObjectNode con = (CreateObjectNode) en;
647       return con.getType();
648     }
649
650     return null;
651   }
652
653   private boolean isField(ExpressionNode en) {
654
655     if (en.kind() == Kind.NameNode) {
656       NameNode nn = (NameNode) en;
657       if (nn.getField() != null) {
658         return true;
659       }
660
661       if (nn.getName() != null && nn.getName().getBase() != null) {
662         return true;
663       }
664
665     } else if (en.kind() == Kind.FieldAccessNode) {
666       return true;
667     }
668     return false;
669   }
670
671   private void checkDeclarationNode(MethodDescriptor md, SymbolTable nametable, DeclarationNode dn) {
672     if (dn.getExpression() != null) {
673       checkExpressionNode(md, nametable, dn.getExpression());
674       if (dn.getExpression().kind() == Kind.CreateObjectNode) {
675         dn.getVarDescriptor().getType().setExtension(new SSJavaType(true));
676       }
677
678     }
679
680   }
681
682   private boolean isReference(TypeDescriptor td) {
683     if (td.isPtr()) {
684       return true;
685     }
686     return false;
687   }
688
689 }