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); }
private EXPR CreateZeroInit(EXPRTYPEORNAMESPACE pTypeExpr, EXPR pOptionalOriginalConstructorCall, bool isConstructor) { Debug.Assert(pTypeExpr != null); CType pType = pTypeExpr.TypeOrNamespace.AsType(); bool bIsError = false; if (pType.isEnumType()) { // For enum types, we create a constant that has the default value // as an object pointer. ConstValFactory factory = new ConstValFactory(); EXPRCONSTANT expr = CreateConstant(pType, factory.Create(Activator.CreateInstance(pType.AssociatedSystemType))); return(expr); } switch (pType.fundType()) { default: bIsError = true; break; case FUNDTYPE.FT_PTR: { CType nullType = GetTypes().GetNullType(); // UNDONE: I think this if is always false ... if (nullType.fundType() == pType.fundType()) { // Create a constant here. EXPRCONSTANT expr = CreateConstant(pType, ConstValFactory.GetDefaultValue(ConstValKind.IntPtr)); return(expr); } // Just allocate a new node and fill it in. EXPRCAST cast = CreateCast(0, pTypeExpr, CreateNull()); // UNDONE: should pTree be passed in here? return(cast); } case FUNDTYPE.FT_REF: case FUNDTYPE.FT_I1: case FUNDTYPE.FT_U1: case FUNDTYPE.FT_I2: case FUNDTYPE.FT_U2: case FUNDTYPE.FT_I4: case FUNDTYPE.FT_U4: case FUNDTYPE.FT_I8: case FUNDTYPE.FT_U8: case FUNDTYPE.FT_R4: case FUNDTYPE.FT_R8: { EXPRCONSTANT expr = CreateConstant(pType, ConstValFactory.GetDefaultValue(pType.constValKind())); EXPRCONSTANT exprInOriginal = CreateConstant(pType, ConstValFactory.GetDefaultValue(pType.constValKind())); exprInOriginal.SetOptionalConstructorCall(pOptionalOriginalConstructorCall); return(expr); // UNDONE: Check other bogus casts } case FUNDTYPE.FT_STRUCT: if (pType.isPredefType(PredefinedType.PT_DECIMAL)) { EXPRCONSTANT expr = CreateConstant(pType, ConstValFactory.GetDefaultValue(pType.constValKind())); EXPRCONSTANT exprOriginal = CreateConstant(pType, ConstValFactory.GetDefaultValue(pType.constValKind())); exprOriginal.SetOptionalConstructorCall(pOptionalOriginalConstructorCall); return(expr); } break; case FUNDTYPE.FT_VAR: break; } EXPRZEROINIT rval = new EXPRZEROINIT(); rval.kind = ExpressionKind.EK_ZEROINIT; rval.type = pType; rval.flags = 0; rval.OptionalConstructorCall = pOptionalOriginalConstructorCall; rval.IsConstructor = isConstructor; if (bIsError) { rval.SetError(); } Debug.Assert(rval != null); return(rval); }