public FlowInfo analyseCode(BlockScope currentScope, FlowContext flowContext, FlowInfo flowInfo) {

    Constant cst = this.left.optimizedBooleanConstant();
    boolean isLeftOptimizedTrue = cst != Constant.NotAConstant && cst.booleanValue() == true;
    boolean isLeftOptimizedFalse = cst != Constant.NotAConstant && cst.booleanValue() == false;

    if (isLeftOptimizedFalse) {
      // FALSE || anything
      // need to be careful of scenario:
      //		(x || y) || !z, if passing the left info to the right, it would be swapped by the !
      FlowInfo mergedInfo =
          this.left.analyseCode(currentScope, flowContext, flowInfo).unconditionalInits();
      flowContext.expireNullCheckedFieldInfo();
      mergedInfo = this.right.analyseCode(currentScope, flowContext, mergedInfo);
      flowContext.expireNullCheckedFieldInfo();
      this.mergedInitStateIndex = currentScope.methodScope().recordInitializationStates(mergedInfo);
      return mergedInfo;
    }

    FlowInfo leftInfo = this.left.analyseCode(currentScope, flowContext, flowInfo);
    flowContext.expireNullCheckedFieldInfo();

    // need to be careful of scenario:
    //		(x || y) || !z, if passing the left info to the right, it would be swapped by the !
    FlowInfo rightInfo = leftInfo.initsWhenFalse().unconditionalCopy();
    this.rightInitStateIndex = currentScope.methodScope().recordInitializationStates(rightInfo);

    int previousMode = rightInfo.reachMode();
    if (isLeftOptimizedTrue) {
      if ((rightInfo.reachMode() & FlowInfo.UNREACHABLE) == 0) {
        currentScope.problemReporter().fakeReachable(this.right);
        rightInfo.setReachMode(FlowInfo.UNREACHABLE_OR_DEAD);
      }
    }
    rightInfo = this.right.analyseCode(currentScope, flowContext, rightInfo);
    flowContext.expireNullCheckedFieldInfo();
    if ((this.left.implicitConversion & TypeIds.UNBOXING) != 0) {
      this.left.checkNPE(currentScope, flowContext, flowInfo);
    }
    if ((this.right.implicitConversion & TypeIds.UNBOXING) != 0) {
      this.right.checkNPE(currentScope, flowContext, flowInfo);
    }
    // The definitely null variables in right info when true should not be missed out while merging
    // https://bugs.eclipse.org/bugs/show_bug.cgi?id=299900
    FlowInfo leftInfoWhenTrueForMerging =
        leftInfo
            .initsWhenTrue()
            .unconditionalCopy()
            .addPotentialInitializationsFrom(rightInfo.unconditionalInitsWithoutSideEffect());
    FlowInfo mergedInfo =
        FlowInfo.conditional(
            // merging two true initInfos for such a negative case: if ((t && (b = t)) || f) r = b;
            // // b may not have been initialized
            leftInfoWhenTrueForMerging
                .unconditionalInits()
                .mergedWith(
                    rightInfo.safeInitsWhenTrue().setReachMode(previousMode).unconditionalInits()),
            rightInfo.initsWhenFalse());
    this.mergedInitStateIndex = currentScope.methodScope().recordInitializationStates(mergedInfo);
    return mergedInfo;
  }