public FlowInfo analyseCode(BlockScope currentScope, FlowContext flowContext, FlowInfo flowInfo) { LocalVariableBinding local = this.expression.localVariableBinding(); if (local != null && (local.type.tagBits & TagBits.IsBaseType) == 0) { flowInfo = this.expression.analyseCode(currentScope, flowContext, flowInfo).unconditionalInits(); FlowInfo initsWhenTrue = flowInfo.copy(); initsWhenTrue.markAsComparedEqualToNonNull(local); if ((flowContext.tagBits & FlowContext.HIDE_NULL_COMPARISON_WARNING) != 0) { initsWhenTrue.markedAsNullOrNonNullInAssertExpression(local); } flowContext.recordUsingNullReference( currentScope, local, this.expression, FlowContext.CAN_ONLY_NULL | FlowContext.IN_INSTANCEOF, flowInfo); // no impact upon enclosing try context return FlowInfo.conditional(initsWhenTrue, flowInfo.copy()); } return this.expression.analyseCode(currentScope, flowContext, flowInfo).unconditionalInits(); }
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; }