Пример #1
0
 /** Check that the assignment to a field is correct. */
 protected void checkFieldAssign(
     FlowGraph graph, FieldAssign a, DataFlowItem dfIn, DataFlowItem dfOut)
     throws SemanticException {
   Field f = (Field) a.left();
   FieldInstance fi = f.fieldInstance();
   if (fi.flags().isFinal()) {
     if ((currCBI.currCodeDecl instanceof ConstructorDecl
             || currCBI.currCodeDecl instanceof Initializer)
         && isFieldsTargetAppropriate(f)) {
       // we are in a constructor or initializer block and
       // if the field is static then the target is the class
       // at hand, and if it is not static then the
       // target of the field is this.
       // So a final field in this situation can be
       // assigned to at most once.
       MinMaxInitCount initCount = (MinMaxInitCount) dfOut.initStatus.get(fi);
       if (InitCount.MANY.equals(initCount.getMax())) {
         throw new SemanticException(
             "field \"" + fi.name() + "\" might already have been assigned to", a.position());
       }
     } else {
       // not in a constructor or intializer, or the target is
       // not appropriate. So we cannot assign
       // to a final field at all.
       throw new SemanticException(
           "Cannot assign a value " + "to final field \"" + fi.name() + "\"", a.position());
     }
   }
 }
Пример #2
0
 /**
  * Determine if we are interested in this field on the basis of the target of the field. To wit,
  * if the field is static, then the target of the field must be the current class; if the field is
  * not static then the target must be "this".
  */
 protected boolean isFieldsTargetAppropriate(Field f) {
   if (f.fieldInstance().flags().isStatic()) {
     ClassType containingClass = (ClassType) currCBI.currCodeDecl.codeInstance().container();
     return containingClass.equals(f.fieldInstance().container());
   } else {
     return (f.target() instanceof Special && Special.THIS.equals(((Special) f.target()).kind()));
   }
 }
Пример #3
0
  /** Perform the appropriate flow operations for assignment to a field */
  protected Map flowFieldAssign(
      DataFlowItem inItem, FlowGraph graph, FieldAssign a, Set succEdgeKeys) {
    Field f = (Field) a.left();
    FieldInstance fi = f.fieldInstance();

    if (fi.flags().isFinal() && isFieldsTargetAppropriate(f)) {
      // this field is final and the target for this field is
      // appropriate for what we are interested in.
      Map m = new HashMap(inItem.initStatus);
      MinMaxInitCount initCount = (MinMaxInitCount) m.get(fi);
      // initCount may be null if the field is defined in an
      // outer class.
      if (initCount != null) {
        initCount =
            new MinMaxInitCount(initCount.getMin().increment(), initCount.getMax().increment());
        m.put(fi, initCount);
        return itemToMap(new DataFlowItem(m), succEdgeKeys);
      }
    }
    return null;
  }
  protected NodeVisitor enterCall(Node n) throws SemanticException {
    if (n instanceof FieldDecl) {
      FieldDecl fd = (FieldDecl) n;

      FwdReferenceChecker frc = (FwdReferenceChecker) this.copy();
      frc.inInitialization = true;
      frc.inStaticInit = fd.flags().flags().isStatic();

      frc.declaredFields = new HashSet<FieldDef>(declaredFields);
      declaredFields.add(fd.fieldDef());
      return frc;
    } else if (n instanceof Initializer) {
      FwdReferenceChecker frc = (FwdReferenceChecker) this.copy();
      frc.inInitialization = true;
      frc.inStaticInit = ((Initializer) n).flags().flags().isStatic();
      return frc;
    } else if (n instanceof FieldAssign) {
      FwdReferenceChecker frc = (FwdReferenceChecker) this.copy();
      return frc;
    } else if (n instanceof Field) {
      if (inInitialization) {
        // we need to check if this is an illegal fwd reference.
        Field f = (Field) n;

        // an illegal fwd reference if a usage of an instance
        // (resp. static) field occurs in an instance (resp. static)
        // initialization, and the innermost enclosing class or
        // interface of the usage is the same as the container of
        // the field, and we have not yet seen the field declaration.
        //
        // In addition, if a field is not accessed as a simple name,
        // then all is ok

        ClassType currentClass = context().currentClass();
        StructType fContainer = f.fieldInstance().container();

        if (inStaticInit == f.fieldInstance().flags().isStatic()
            && currentClass.typeEquals(fContainer, context)
            && !declaredFields.contains(f.fieldInstance().def())
            && f.isTargetImplicit()) {
          throw new SemanticException("Illegal forward reference", f.position());
        }
      }
    }
    return this;
  }
Пример #5
0
  private Node translateExtForArray(ExtendedFor n, List<String> labels) throws SemanticException {
    Position pos = Position.compilerGenerated();
    Type iteratedType = n.decl().type().type();
    // translate "L1,...,Ln: for (C x: e) b" to
    // "{ C[] arr = e; int iter = 0;  L1,...,Ln: while (iter < arr.length)  { C x = arr[iter]; b ;
    // iter = iter + 1; }"
    List<Stmt> stmts = new ArrayList<Stmt>();

    // add the declaration of arr: "C[] arr = e"
    Id arrID = freshName("arr");
    LocalInstance arrLI = ts.localInstance(pos, Flags.NONE, n.expr().type(), arrID.id());
    {
      LocalDecl ld =
          nodeFactory()
              .LocalDecl(
                  pos, Flags.NONE, nodeFactory().CanonicalTypeNode(pos, arrLI.type()), arrID);
      ld = ld.localInstance(arrLI);
      ld = ld.init(n.expr());
      stmts.add(ld);
    }

    // add the declaration of iterator: "int iter = 0"
    Id iterID = freshName("iter");
    LocalInstance iterLI = ts.localInstance(pos, Flags.NONE, ts.Int(), iterID.id());
    {
      LocalDecl ld =
          nodeFactory()
              .LocalDecl(
                  pos, Flags.NONE, nodeFactory().CanonicalTypeNode(pos, iterLI.type()), iterID);
      ld = ld.localInstance(iterLI);
      ld = ld.init(nodeFactory().IntLit(pos, IntLit.INT, 0).type(ts.Int()));
      stmts.add(ld);
    }

    // build the conditional "iter < arr.length"
    Expr cond;
    {
      Local iterLocal =
          (Local) nodeFactory().Local(pos, iterID).localInstance(iterLI).type(ts.Int());
      Local arrLocal =
          (Local) nodeFactory().Local(pos, arrID).localInstance(arrLI).type(arrLI.type());
      Id id = nodeFactory().Id(pos, "length");
      Field field = (Field) nodeFactory().Field(pos, arrLocal, id).type(ts.Int());
      field = field.fieldInstance(ts.findField(arrLI.type().toReference(), "length"));

      cond = nodeFactory().Binary(pos, iterLocal, Binary.LT, field).type(ts.Boolean());
    }

    // build the initlizer for the local decl: arr[iter]
    Expr init;
    {
      Local iterLocal =
          (Local) nodeFactory().Local(pos, iterID).localInstance(iterLI).type(ts.Int());
      Local arrLocal =
          (Local) nodeFactory().Local(pos, arrID).localInstance(arrLI).type(arrLI.type());
      init = nodeFactory().ArrayAccess(pos, arrLocal, iterLocal);
      init = init.type(iteratedType);
    }

    // build the increment for iter (iter = iter + 1;)
    Stmt inc;
    {
      Local iterLocal =
          (Local) nodeFactory().Local(pos, iterID).localInstance(iterLI).type(ts.Int());
      Expr incExpr =
          nodeFactory()
              .Binary(
                  pos,
                  iterLocal.type(ts.Int()),
                  Binary.ADD,
                  nodeFactory().IntLit(pos, IntLit.INT, 1).type(ts.Int()))
              .type(ts.Int());
      Assign incStore =
          (Assign) nodeFactory().Assign(pos, iterLocal, Assign.ASSIGN, incExpr).type(ts.Int());
      inc = nodeFactory().Eval(pos, incStore);
    }

    // build the while loop
    {
      // Create a new loop body from the old body followed by the increment
      Block loopBody = nodeFactory().Block(pos, n.decl().init(init), n.body(), inc);
      While loop = nodeFactory().While(pos, cond, loopBody);
      stmts.add(labelStmt(loop, labels));
    }
    return nodeFactory().Block(pos, stmts);
  }
Пример #6
0
 private boolean isBoxed(Field field) {
   if (isBoxedType(field.fieldInstance().def().type().get())) return true;
   return false;
 }