From 3bc59f4d7bebb45295b11d40de88ce73f1172b7f Mon Sep 17 00:00:00 2001 From: jzhou Date: Fri, 11 Nov 2011 00:18:09 +0000 Subject: [PATCH] Fix inner class implementation. Now code like inner.this.X/outer.this.X work correctly. And the inner class can correctly refer to the fields/methods defined in the surrounding class. --- Robust/src/IR/Flat/BuildCode.java | 17 ++++- Robust/src/IR/SymbolTable.java | 24 ------- Robust/src/IR/Tree/BuildIR.java | 8 +-- Robust/src/IR/Tree/FieldAccessNode.java | 4 ++ Robust/src/IR/Tree/SemanticCheck.java | 94 ++++++++++++++++++++++--- 5 files changed, 107 insertions(+), 40 deletions(-) diff --git a/Robust/src/IR/Flat/BuildCode.java b/Robust/src/IR/Flat/BuildCode.java index 9482735f..59ee3e07 100644 --- a/Robust/src/IR/Flat/BuildCode.java +++ b/Robust/src/IR/Flat/BuildCode.java @@ -2805,7 +2805,22 @@ fldloop: output.println("}else{"); output.println(generateTemp(fm, ffn.getDst())+"="+ generateTemp(fm,ffn.getSrc())+"->"+ ffn.getField().getSafeSymbol()+";"); output.println("}"); - }else { + }else if (ffn.getField().getSymbol().equals("this")) { + // an inner class refers to itself + if( state.CAPTURE_NULL_DEREFERENCES ) { + output.println("#ifdef CAPTURE_NULL_DEREFERENCES"); + output.println("if (" + generateTemp(fm,ffn.getSrc()) + " == NULL) {"); + output.println("printf(\" NULL ptr error: %s, %s, %d \\n\", __FILE__, __func__, __LINE__);"); + if(state.MULTICOREGC||state.PMC) { + output.println("failednullptr(&___locals___);"); + } else { + output.println("failednullptr(NULL);"); + } + output.println("}"); + output.println("#endif //CAPTURE_NULL_DEREFERENCES"); + } + output.println(generateTemp(fm, ffn.getDst())+"="+ generateTemp(fm,ffn.getSrc())+";"); + } else { if( state.CAPTURE_NULL_DEREFERENCES ) { output.println("#ifdef CAPTURE_NULL_DEREFERENCES"); output.println("if (" + generateTemp(fm,ffn.getSrc()) + " == NULL) {"); diff --git a/Robust/src/IR/SymbolTable.java b/Robust/src/IR/SymbolTable.java index 3ada4029..057e93be 100644 --- a/Robust/src/IR/SymbolTable.java +++ b/Robust/src/IR/SymbolTable.java @@ -9,15 +9,12 @@ public class SymbolTable { private HashSet valueset; private Vector parentIFs; - private SymbolTable surrounding; - public SymbolTable() { table = new Hashtable(); valueset = new HashSet(); parent = null; parentIFs = null; - this.surrounding = null; } public SymbolTable(SymbolTable parent) { @@ -49,9 +46,6 @@ public class SymbolTable { hs.addAll(parentIFs.elementAt(i).getPSet(name)); } } - if(this.surrounding != null) { - hs.addAll(this.surrounding.getPSet(name)); - } if (table.containsKey(name)) { hs.addAll((HashSet)table.get(name)); } @@ -90,13 +84,6 @@ public class SymbolTable { } } - if(this.surrounding != null) { - d = this.surrounding.get(name); - if(d != null) { - return d; - } - } - return null; } @@ -136,9 +123,6 @@ public class SymbolTable { hs.addAll(parentIFs.elementAt(i).getAllValueSet()); } } - if(this.surrounding != null) { - hs.addAll(this.surrounding.getAllValueSet()); - } hs.addAll(valueset); return hs; @@ -160,14 +144,6 @@ public class SymbolTable { this.parent = parent; } - public SymbolTable getSurrounding() { - return this.surrounding; - } - - public void setSurrounding(SymbolTable surrounding) { - this.surrounding = surrounding; - } - public Vector getParentIFs() { return parentIFs; } diff --git a/Robust/src/IR/Tree/BuildIR.java b/Robust/src/IR/Tree/BuildIR.java index 31f062e9..a6005bd3 100644 --- a/Robust/src/IR/Tree/BuildIR.java +++ b/Robust/src/IR/Tree/BuildIR.java @@ -1202,13 +1202,13 @@ private void addOuterClassReferences( ClassDescriptor cn, int depth ) nn.setNumLine(pn.getLine()); return nn; } else if (isNode(pn,"parentclass")) { - NameDescriptor nd=new NameDescriptor("this"); + NameDescriptor nd=new NameDescriptor(pn.getChild("name").getFirstChild().getFirstChild().getTerminal()); NameNode nn=new NameNode(nd); nn.setNumLine(pn.getLine()); //because inner classes pass right thru...... - /* FieldAccessNode fan=new FieldAccessNode(nn,"this$0"); - fan.setNumLine(pn.getLine());*/ - return nn; + FieldAccessNode fan=new FieldAccessNode(nn,"this"); + fan.setNumLine(pn.getLine()); + return fan; } else if (isNode(pn,"isavailable")) { NameDescriptor nd=new NameDescriptor(pn.getTerminal()); NameNode nn=new NameNode(nd); diff --git a/Robust/src/IR/Tree/FieldAccessNode.java b/Robust/src/IR/Tree/FieldAccessNode.java index d7c28bda..e764bb0d 100644 --- a/Robust/src/IR/Tree/FieldAccessNode.java +++ b/Robust/src/IR/Tree/FieldAccessNode.java @@ -19,6 +19,10 @@ public class FieldAccessNode extends ExpressionNode { public String getFieldName() { return fieldname; } + + public void setFieldName(String fieldname) { + this.fieldname = fieldname; + } public FieldDescriptor getField() { return field; diff --git a/Robust/src/IR/Tree/SemanticCheck.java b/Robust/src/IR/Tree/SemanticCheck.java index b461accb..76443900 100644 --- a/Robust/src/IR/Tree/SemanticCheck.java +++ b/Robust/src/IR/Tree/SemanticCheck.java @@ -75,13 +75,6 @@ public class SemanticCheck { cd.getFieldTable().setParent(cd.getSuperDesc().getFieldTable()); cd.getMethodTable().setParent(cd.getSuperDesc().getMethodTable()); cd.getFlagTable().setParent(cd.getSuperDesc().getFlagTable()); - // if this is an inner class, link together Field, Method and Flag - // tables from its surrounding class - if(cd.isInnerClass()) { - cd.getFieldTable().setSurrounding(cd.getSurroundingDesc().getFieldTable()); - cd.getMethodTable().setSurrounding(cd.getSurroundingDesc().getMethodTable()); - cd.getFlagTable().setSurrounding(cd.getSurroundingDesc().getFlagTable()); - } } } } @@ -677,6 +670,26 @@ public class SemanticCheck { if(ltd.isClassNameRef()) { // the field access is using a class name directly if (fd==null) { + // check if it is to access a surrounding class in an inner class + if(fieldname.equals("this")) { + ClassDescriptor icd = ((VarDescriptor)nametable.get("this")).getType().getClassDesc(); + if(icd.isInnerClass()) { + NameNode nn = new NameNode(new NameDescriptor("this")); + nn.setVar((VarDescriptor)nametable.get("this")); + fan.setExpression(nn); + if(icd.getSurroundingDesc()==ltd.getClassDesc()) { + // this is a surrounding class access inside an inner class + fan.setExpression(nn); + fan.setFieldName("this$0"); + fd = (FieldDescriptor)icd.getFieldTable().get("this$0"); + } else if(icd==ltd.getClassDesc()) { + // this is an inner class this operation + fd = new FieldDescriptor(new Modifiers(),new TypeDescriptor(icd),"this",null,false); + } + fan.setField(fd); + return; + } + } ClassDescriptor surroundingCls=ltd.getClassDesc().getSurroundingDesc(); while(surroundingCls!=null) { @@ -833,9 +846,23 @@ public class SemanticCheck { } } + FieldDescriptor recurseSurroundingClasses( ClassDescriptor icd, String varname ) { + if( null == icd || false == icd.isInnerClass() ) + return null; + + ClassDescriptor surroundingDesc = icd.getSurroundingDesc(); + if( null == surroundingDesc ) + return null; + + SymbolTable fieldTable = surroundingDesc.getFieldTable(); + FieldDescriptor fd = ( FieldDescriptor ) fieldTable.get( varname ); + if( null != fd ) + return fd; + return recurseSurroundingClasses( surroundingDesc, varname ); + } + FieldAccessNode fieldAccessExpression( ClassDescriptor icd, String varname, int linenum ) { - // first check if the field is belong to the icd or its parent class - FieldDescriptor fd = (FieldDescriptor)icd.getFieldTable().get(varname); + FieldDescriptor fd = recurseSurroundingClasses( icd, varname ); if( null == fd ) return null; @@ -1291,6 +1318,41 @@ NextMethod: for (Iterator methodit = methoddescriptorset.iterator(); methodit.ha } } + MethodDescriptor recurseSurroundingClassesM( ClassDescriptor icd, String varname ) { + if( null == icd || false == icd.isInnerClass() ) + return null; + + ClassDescriptor surroundingDesc = icd.getSurroundingDesc(); + if( null == surroundingDesc ) + return null; + + SymbolTable methodTable = surroundingDesc.getMethodTable(); + MethodDescriptor md = ( MethodDescriptor ) methodTable.get( varname ); + if( null != md ) + return md; + return recurseSurroundingClassesM( surroundingDesc, varname ); + } + + ExpressionNode methodInvocationExpression( ClassDescriptor icd, MethodDescriptor md, int linenum ) { + ClassDescriptor cd = md.getClassDesc(); + int depth = 1; + int startingDepth = icd.getInnerDepth(); + + if( true == cd.isInnerClass() ) + depth = cd.getInnerDepth(); + + String composed = "this"; + NameDescriptor runningDesc = new NameDescriptor( "this" );; + + for ( int index = startingDepth; index > depth; --index ) { + composed = "this$" + String.valueOf( index - 1 ); + runningDesc = new NameDescriptor( runningDesc, composed ); + } + if( false == cd.isInnerClass() ) + runningDesc = new NameDescriptor( runningDesc, "this$" + String.valueOf(0) ); //all the way up. + + return new NameNode(runningDesc); +} void checkMethodInvokeNode(Descriptor md, SymbolTable nametable, MethodInvokeNode min, TypeDescriptor td) { /*Typecheck subexpressions @@ -1393,8 +1455,18 @@ NextMethod: /* Is this more specific than bestmd */ } } - if (bestmd==null) - throw new Error("No method found for :"+min.printNode(0)+" in class: " + classtolookin+" in "+md); + if (bestmd==null) { + // if this is an inner class, need to check the method table for the surrounding class + bestmd = recurseSurroundingClassesM(classtolookin, min.getMethodName()); + if(bestmd == null) + throw new Error("No method found for :"+min.printNode(0)+" in class: " + classtolookin+" in "+md); + else { + // set the correct "this" expression here + ExpressionNode en=methodInvocationExpression(classtolookin, bestmd, min.getNumLine()); + min.setExpression(en); + checkExpressionNode(md, nametable, min.getExpression(), null); + } + } min.setMethod(bestmd); if ((td!=null)&&(min.getType()!=null)&&!typeutil.isSuperorType(td, min.getType())) -- 2.34.1