@@ -541,7 +541,8 @@ private BoundExpression BindSimpleBinaryOperator(BinaryExpressionSyntax node, Bi
541541 && left is BoundUnconvertedInterpolatedString or BoundBinaryOperator { IsUnconvertedInterpolatedStringAddition : true }
542542 && right is BoundUnconvertedInterpolatedString )
543543 {
544- var stringConstant = FoldBinaryOperator ( node , BinaryOperatorKind . StringConcatenation , left , right , SpecialType . System_String , diagnostics ) ;
544+ Debug . Assert ( right . Type . SpecialType == SpecialType . System_String ) ;
545+ var stringConstant = FoldBinaryOperator ( node , BinaryOperatorKind . StringConcatenation , left , right , right . Type , diagnostics ) ;
545546 return new BoundBinaryOperator ( node , BinaryOperatorKind . StringConcatenation , BoundBinaryOperator . UncommonData . UnconvertedInterpolatedStringAddition ( stringConstant ) , LookupResultKind . Empty , left , right , right . Type ) ;
546547 }
547548
@@ -621,7 +622,7 @@ private BoundExpression BindSimpleBinaryOperator(BinaryExpressionSyntax node, Bi
621622
622623 resultLeft = CreateConversion ( left , best . LeftConversion , signature . LeftType , diagnostics ) ;
623624 resultRight = CreateConversion ( right , best . RightConversion , signature . RightType , diagnostics ) ;
624- resultConstant = FoldBinaryOperator ( node , resultOperatorKind , resultLeft , resultRight , resultType . SpecialType , diagnostics ) ;
625+ resultConstant = FoldBinaryOperator ( node , resultOperatorKind , resultLeft , resultRight , resultType , diagnostics ) ;
625626 }
626627 else
627628 {
@@ -856,7 +857,7 @@ private BoundExpression BindConditionalLogicalOperator(BinaryExpressionSyntax no
856857 if ( ( object ) left . Type != null && left . Type . SpecialType == SpecialType . System_Boolean &&
857858 ( object ) right . Type != null && right . Type . SpecialType == SpecialType . System_Boolean )
858859 {
859- var constantValue = FoldBinaryOperator ( node , kind | BinaryOperatorKind . Bool , left , right , SpecialType . System_Boolean , diagnostics ) ;
860+ var constantValue = FoldBinaryOperator ( node , kind | BinaryOperatorKind . Bool , left , right , left . Type , diagnostics ) ;
860861
861862 // NOTE: no candidate user-defined operators.
862863 return new BoundBinaryOperator ( node , kind | BinaryOperatorKind . Bool , constantValue , methodOpt : null , constrainedToTypeOpt : null ,
@@ -1596,6 +1597,7 @@ internal static SpecialType GetEnumPromotedType(SpecialType underlyingType)
15961597 BinaryOperatorKind kind ,
15971598 BoundExpression left ,
15981599 BoundExpression right ,
1600+ TypeSymbol resultTypeSymbol ,
15991601 BindingDiagnosticBag diagnostics )
16001602 {
16011603 Debug . Assert ( left != null ) ;
@@ -1628,16 +1630,14 @@ internal static SpecialType GetEnumPromotedType(SpecialType underlyingType)
16281630
16291631 BinaryOperatorKind newKind = kind . Operator ( ) . WithType ( newLeftOperand . Type ! . SpecialType ) ;
16301632
1631- SpecialType operatorType = SpecialType . None ;
1632-
16331633 switch ( newKind . Operator ( ) )
16341634 {
16351635 case BinaryOperatorKind . Addition :
16361636 case BinaryOperatorKind . Subtraction :
16371637 case BinaryOperatorKind . And :
16381638 case BinaryOperatorKind . Or :
16391639 case BinaryOperatorKind . Xor :
1640- operatorType = operandType . SpecialType ;
1640+ resultTypeSymbol = operandType ;
16411641 break ;
16421642
16431643 case BinaryOperatorKind . LessThan :
@@ -1646,16 +1646,16 @@ internal static SpecialType GetEnumPromotedType(SpecialType underlyingType)
16461646 case BinaryOperatorKind . GreaterThanOrEqual :
16471647 case BinaryOperatorKind . Equal :
16481648 case BinaryOperatorKind . NotEqual :
1649- operatorType = SpecialType . System_Boolean ;
1649+ Debug . Assert ( resultTypeSymbol . SpecialType == SpecialType . System_Boolean ) ;
16501650 break ;
16511651
16521652 default :
16531653 throw ExceptionUtilities . UnexpectedValue ( newKind . Operator ( ) ) ;
16541654 }
16551655
1656- var constantValue = FoldBinaryOperator ( syntax , newKind , newLeftOperand , newRightOperand , operatorType , diagnostics ) ;
1656+ var constantValue = FoldBinaryOperator ( syntax , newKind , newLeftOperand , newRightOperand , resultTypeSymbol , diagnostics ) ;
16571657
1658- if ( operatorType != SpecialType . System_Boolean && constantValue != null && ! constantValue . IsBad )
1658+ if ( resultTypeSymbol . SpecialType != SpecialType . System_Boolean && constantValue != null && ! constantValue . IsBad )
16591659 {
16601660 TypeSymbol resultType = kind == BinaryOperatorKind . EnumSubtraction ? underlyingType : enumType ;
16611661
@@ -1672,7 +1672,7 @@ internal static SpecialType GetEnumPromotedType(SpecialType underlyingType)
16721672 BinaryOperatorKind kind ,
16731673 BoundExpression left ,
16741674 BoundExpression right ,
1675- SpecialType resultType ,
1675+ TypeSymbol resultTypeSymbol ,
16761676 BindingDiagnosticBag diagnostics )
16771677 {
16781678 Debug . Assert ( left != null ) ;
@@ -1704,7 +1704,7 @@ internal static SpecialType GetEnumPromotedType(SpecialType underlyingType)
17041704
17051705 if ( kind . IsEnum ( ) && ! kind . IsLifted ( ) )
17061706 {
1707- return FoldEnumBinaryOperator ( syntax , kind , left , right , diagnostics ) ;
1707+ return FoldEnumBinaryOperator ( syntax , kind , left , right , resultTypeSymbol , diagnostics ) ;
17081708 }
17091709
17101710 // Divisions by zero on integral types and decimal always fail even in an unchecked context.
@@ -1715,6 +1715,7 @@ internal static SpecialType GetEnumPromotedType(SpecialType underlyingType)
17151715 }
17161716
17171717 object ? newValue = null ;
1718+ SpecialType resultType = resultTypeSymbol . SpecialType ;
17181719
17191720 // Certain binary operations never fail; bool & bool, for example. If we are in one of those
17201721 // cases, simply fold the operation and return.
@@ -1765,13 +1766,10 @@ internal static SpecialType GetEnumPromotedType(SpecialType underlyingType)
17651766 {
17661767 if ( CheckOverflowAtCompileTime )
17671768 {
1768- Error ( diagnostics , ErrorCode . ERR_CheckedOverflow , syntax ) ;
1769- return ConstantValue . Bad ;
1770- }
1771- else
1772- {
1773- return null ;
1769+ Error ( diagnostics , ErrorCode . WRN_CompileTimeCheckedOverflow , syntax , resultTypeSymbol ) ;
17741770 }
1771+
1772+ return null ;
17751773 }
17761774
17771775 if ( newValue != null )
@@ -2616,7 +2614,7 @@ private BoundExpression BindUnaryOperatorCore(CSharpSyntaxNode node, string oper
26162614 var resultOperand = CreateConversion ( operand . Syntax , operand , best . Conversion , isCast : false , conversionGroupOpt : null , signature . OperandType , diagnostics ) ;
26172615 var resultType = signature . ReturnType ;
26182616 UnaryOperatorKind resultOperatorKind = signature . Kind ;
2619- var resultConstant = FoldUnaryOperator ( node , resultOperatorKind , resultOperand , resultType . SpecialType , diagnostics ) ;
2617+ var resultConstant = FoldUnaryOperator ( node , resultOperatorKind , resultOperand , resultType , diagnostics ) ;
26202618
26212619 CheckNativeIntegerFeatureAvailability ( resultOperatorKind , node , diagnostics ) ;
26222620 CheckConstraintLanguageVersionAndRuntimeSupportForOperator ( node , signature . Method , signature . ConstrainedToTypeOpt , diagnostics ) ;
@@ -2653,7 +2651,7 @@ private BoundExpression BindUnaryOperatorCore(CSharpSyntaxNode node, string oper
26532651
26542652 UnaryOperatorKind newKind = kind . Operator ( ) . WithType ( upconvertSpecialType ) ;
26552653
2656- var constantValue = FoldUnaryOperator ( syntax , newKind , operand , upconvertType . SpecialType , diagnostics ) ;
2654+ var constantValue = FoldUnaryOperator ( syntax , newKind , operand , upconvertType , diagnostics ) ;
26572655
26582656 // Convert back to the underlying type
26592657 if ( constantValue != null && ! constantValue . IsBad )
@@ -2671,7 +2669,7 @@ private BoundExpression BindUnaryOperatorCore(CSharpSyntaxNode node, string oper
26712669 CSharpSyntaxNode syntax ,
26722670 UnaryOperatorKind kind ,
26732671 BoundExpression operand ,
2674- SpecialType resultType ,
2672+ TypeSymbol resultTypeSymbol ,
26752673 BindingDiagnosticBag diagnostics )
26762674 {
26772675 Debug . Assert ( operand != null ) ;
@@ -2693,6 +2691,7 @@ private BoundExpression BindUnaryOperatorCore(CSharpSyntaxNode node, string oper
26932691 return FoldEnumUnaryOperator ( syntax , kind , operand , diagnostics ) ;
26942692 }
26952693
2694+ SpecialType resultType = resultTypeSymbol . SpecialType ;
26962695 var newValue = FoldNeverOverflowUnaryOperator ( kind , value ) ;
26972696 if ( newValue != null )
26982697 {
@@ -2707,13 +2706,10 @@ private BoundExpression BindUnaryOperatorCore(CSharpSyntaxNode node, string oper
27072706 {
27082707 if ( CheckOverflowAtCompileTime )
27092708 {
2710- Error ( diagnostics , ErrorCode . ERR_CheckedOverflow , syntax ) ;
2711- return ConstantValue . Bad ;
2712- }
2713- else
2714- {
2715- return null ;
2709+ Error ( diagnostics , ErrorCode . WRN_CompileTimeCheckedOverflow , syntax , resultTypeSymbol ) ;
27162710 }
2711+
2712+ return null ;
27172713 }
27182714
27192715 if ( newValue != null )
0 commit comments