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;
  }