Example #1
0
            private bool bindImplicitConversionToEnum(AggregateType aggTypeSrc)
            {
                // The spec states:
                // *****************
                // 13.1.3 Implicit enumeration conversions
                //
                // An implicit enumeration conversion permits the decimal-integer-literal 0 to be converted to any
                // enum-type.
                // *****************
                // However, we actually allow any constant zero, not just the integer literal zero, to be converted
                // to enum.  The reason for this is for backwards compatibility with a premature optimization
                // that used to be in the binding layer.  We would optimize away expressions such as 0 | blah to be
                // just 0, but not erase the "is literal" bit.  This meant that expression such as 0 | 0 | E.X
                // would succeed rather than correctly producing an error pointing out that 0 | 0 is not a literal
                // zero and therefore does not convert to any enum.
                //
                // We have removed the premature optimization but want old code to continue to compile. Rather than
                // try to emulate the somewhat complex behaviour of the previous optimizer, it is easier to simply
                // say that any compile time constant zero is convertible to any enum.  This means unfortunately
                // expressions such as (7-7) * 12 are convertible to enum, but frankly, that's better than having
                // some terribly complex rule about what constitutes a legal zero and what doesn't.

                // Note: Don't use GetConst here since the conversion only applies to bona-fide compile time constants.
                if (
                    aggTypeSrc.getAggregate().GetPredefType() != PredefinedType.PT_BOOL &&
                    exprSrc != null &&
                    exprSrc.isZero() &&
                    exprSrc.type.isNumericType() &&
                    /*(exprSrc.flags & EXF_LITERALCONST) &&*/
                    0 == (flags & CONVERTTYPE.STANDARD))
                {
                    // NOTE: This allows conversions from uint, long, ulong, float, double, and hexadecimal int
                    // NOTE: This is for backwards compatibility with Everett

                    // REVIEW: : This is another place where we lose EXPR fidelity. We shouldn't fold this
                    // into a constant here - we should move this to a later pass.
                    if (needsExprDest)
                    {
                        exprDest = GetExprFactory().CreateConstant(typeDest, ConstValFactory.GetDefaultValue(typeDest.constValKind()));
                    }
                    return(true);
                }
                return(false);
            }