private bool bindImplicitConversionFromAgg(AggregateType aggTypeSrc) { // GENERICS: The case for constructed types is very similar to types with // no parameters. The parameters are irrelevant for most of the conversions // below. They could be relevant if we had user-defined conversions on // generic types. AggregateSymbol aggSrc = aggTypeSrc.getAggregate(); if (aggSrc.IsEnum()) { return(bindImplicitConversionFromEnum(aggTypeSrc)); } if (_typeDest.isEnumType()) { if (bindImplicitConversionToEnum(aggTypeSrc)) { return(true); } // Even though enum is sealed, a class can derive from enum in LAF scenarios -- // continue testing for derived to base conversions below. } else if (aggSrc.getThisType().isSimpleType() && _typeDest.isSimpleType()) { if (bindImplicitConversionBetweenSimpleTypes(aggTypeSrc)) { return(true); } // No simple conversion -- continue testing for derived to base conversions below. } return(bindImplicitConversionToBase(aggTypeSrc)); }
// 13.2.2 Explicit enumeration conversions // // The explicit enumeration conversions are: // // * From sbyte, byte, short, ushort, int, uint, long, ulong, char, float, double, or // decimal to any enum-type. // // * From any enum-type to sbyte, byte, short, ushort, int, uint, long, ulong, char, // float, double, or decimal. // // * From any enum-type to any other enum-type. // // * An explicit enumeration conversion between two types is processed by treating any // participating enum-type as the underlying type of that enum-type, and then performing // an implicit or explicit numeric conversion between the resulting types. private AggCastResult bindExplicitConversionFromEnumToAggregate(AggregateType aggTypeDest) { Debug.Assert(_typeSrc != null); Debug.Assert(aggTypeDest != null); if (!_typeSrc.isEnumType()) { return(AggCastResult.Failure); } AggregateSymbol aggDest = aggTypeDest.getAggregate(); if (aggDest.isPredefAgg(PredefinedType.PT_DECIMAL)) { return(bindExplicitConversionFromEnumToDecimal(aggTypeDest)); } if (!aggDest.getThisType().isNumericType() && !aggDest.IsEnum() && !(aggDest.IsPredefined() && aggDest.GetPredefType() == PredefinedType.PT_CHAR)) { return(AggCastResult.Failure); } if (_exprSrc.GetConst() != null) { ConstCastResult result = _binder.bindConstantCast(_exprSrc, _exprTypeDest, _needsExprDest, out _exprDest, true); if (result == ConstCastResult.Success) { return(AggCastResult.Success); } else if (result == ConstCastResult.CheckFailure) { return(AggCastResult.Abort); } } if (_needsExprDest) { _binder.bindSimpleCast(_exprSrc, _exprTypeDest, out _exprDest); } return(AggCastResult.Success); }
//////////////////////////////////////////////////////////////////////////////// // // Precondition: // // type - Non-null // // This returns a null for reference types and an EXPRZEROINIT for all others. public Expr CreateZeroInit(CType type) { Debug.Assert(type != null); if (type.isEnumType()) { // For enum types, we create a constant that has the default value // as an object pointer. return(CreateConstant(type, ConstVal.Get(Activator.CreateInstance(type.AssociatedSystemType)))); } Debug.Assert(type.fundType() > FUNDTYPE.FT_NONE); Debug.Assert(type.fundType() < FUNDTYPE.FT_COUNT); switch (type.fundType()) { case FUNDTYPE.FT_PTR: { // Just allocate a new node and fill it in. return(CreateCast(0, type, CreateNull())); } case FUNDTYPE.FT_STRUCT: if (type.isPredefType(PredefinedType.PT_DECIMAL)) { goto default; } goto case FUNDTYPE.FT_VAR; case FUNDTYPE.FT_VAR: return(new ExprZeroInit(type)); default: return(CreateConstant(type, ConstVal.GetDefaultValue(type.constValKind()))); } }
private Expr GenerateBuiltInBinaryOperator(ExprBinOp expr) { Debug.Assert(expr != null); PREDEFMETH pdm; switch (expr.Kind) { case ExpressionKind.LeftShirt: pdm = PREDEFMETH.PM_EXPRESSION_LEFTSHIFT; break; case ExpressionKind.RightShift: pdm = PREDEFMETH.PM_EXPRESSION_RIGHTSHIFT; break; case ExpressionKind.BitwiseExclusiveOr: pdm = PREDEFMETH.PM_EXPRESSION_EXCLUSIVEOR; break; case ExpressionKind.BitwiseOr: pdm = PREDEFMETH.PM_EXPRESSION_OR; break; case ExpressionKind.BitwiseAnd: pdm = PREDEFMETH.PM_EXPRESSION_AND; break; case ExpressionKind.LogicalAnd: pdm = PREDEFMETH.PM_EXPRESSION_ANDALSO; break; case ExpressionKind.LogicalOr: pdm = PREDEFMETH.PM_EXPRESSION_ORELSE; break; case ExpressionKind.StringEq: pdm = PREDEFMETH.PM_EXPRESSION_EQUAL; break; case ExpressionKind.Eq: pdm = PREDEFMETH.PM_EXPRESSION_EQUAL; break; case ExpressionKind.StringNotEq: pdm = PREDEFMETH.PM_EXPRESSION_NOTEQUAL; break; case ExpressionKind.NotEq: pdm = PREDEFMETH.PM_EXPRESSION_NOTEQUAL; break; case ExpressionKind.GreaterThanOrEqual: pdm = PREDEFMETH.PM_EXPRESSION_GREATERTHANOREQUAL; break; case ExpressionKind.LessThanOrEqual: pdm = PREDEFMETH.PM_EXPRESSION_LESSTHANOREQUAL; break; case ExpressionKind.LessThan: pdm = PREDEFMETH.PM_EXPRESSION_LESSTHAN; break; case ExpressionKind.GreaterThan: pdm = PREDEFMETH.PM_EXPRESSION_GREATERTHAN; break; case ExpressionKind.Modulo: pdm = PREDEFMETH.PM_EXPRESSION_MODULO; break; case ExpressionKind.Divide: pdm = PREDEFMETH.PM_EXPRESSION_DIVIDE; break; case ExpressionKind.Multiply: pdm = expr.isChecked() ? PREDEFMETH.PM_EXPRESSION_MULTIPLYCHECKED : PREDEFMETH.PM_EXPRESSION_MULTIPLY; break; case ExpressionKind.Subtract: pdm = expr.isChecked() ? PREDEFMETH.PM_EXPRESSION_SUBTRACTCHECKED : PREDEFMETH.PM_EXPRESSION_SUBTRACT; break; case ExpressionKind.Add: pdm = expr.isChecked() ? PREDEFMETH.PM_EXPRESSION_ADDCHECKED : PREDEFMETH.PM_EXPRESSION_ADD; break; default: throw Error.InternalCompilerError(); } Expr origL = expr.OptionalLeftChild; Expr origR = expr.OptionalRightChild; Debug.Assert(origL != null); Debug.Assert(origR != null); CType typeL = origL.Type; CType typeR = origR.Type; Expr newL = Visit(origL); Expr newR = Visit(origR); bool didEnumConversion = false; CType convertL = null; CType convertR = null; if (typeL.isEnumType()) { // We have already inserted casts if not lifted, so we should never see an enum. Debug.Assert(expr.IsLifted); convertL = GetSymbolLoader().GetTypeManager().GetNullable(typeL.underlyingEnumType()); typeL = convertL; didEnumConversion = true; } else if (typeL is NullableType nubL && nubL.UnderlyingType.isEnumType()) { Debug.Assert(expr.IsLifted); convertL = GetSymbolLoader().GetTypeManager().GetNullable(nubL.UnderlyingType.underlyingEnumType()); typeL = convertL; didEnumConversion = true; } if (typeR.isEnumType()) { Debug.Assert(expr.IsLifted); convertR = GetSymbolLoader().GetTypeManager().GetNullable(typeR.underlyingEnumType()); typeR = convertR; didEnumConversion = true; } else if (typeR is NullableType nubR && nubR.UnderlyingType.isEnumType()) { Debug.Assert(expr.IsLifted); convertR = GetSymbolLoader().GetTypeManager().GetNullable(nubR.UnderlyingType.underlyingEnumType()); typeR = convertR; didEnumConversion = true; } if (typeL is NullableType nubL2 && nubL2.UnderlyingType == typeR) { convertR = typeL; } if (typeR is NullableType nubR2 && nubR2.UnderlyingType == typeL) { convertL = typeR; } if (convertL != null) { newL = GenerateCall(PREDEFMETH.PM_EXPRESSION_CONVERT, newL, CreateTypeOf(convertL)); } if (convertR != null) { newR = GenerateCall(PREDEFMETH.PM_EXPRESSION_CONVERT, newR, CreateTypeOf(convertR)); } Expr call = GenerateCall(pdm, newL, newR); if (didEnumConversion && expr.Type.StripNubs().isEnumType()) { call = GenerateCall(PREDEFMETH.PM_EXPRESSION_CONVERT, call, CreateTypeOf(expr.Type)); } return(call); }
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); }
private Expr CreateZeroInit(ExprClass typeExpr, Expr originalConstructorCall, bool isConstructor) { Debug.Assert(typeExpr != null); CType type = typeExpr.Type; bool isError = false; if (type.isEnumType()) { // For enum types, we create a constant that has the default value // as an object pointer. return(CreateConstant(type, ConstVal.Get(Activator.CreateInstance(type.AssociatedSystemType)))); } switch (type.fundType()) { case FUNDTYPE.FT_PTR: { CType nullType = Types.GetNullType(); // It looks like this if is always false ... if (nullType.fundType() == type.fundType()) { // Create a constant here. return(CreateConstant(type, ConstVal.GetDefaultValue(ConstValKind.IntPtr))); } // Just allocate a new node and fill it in. return(CreateCast(0, typeExpr, CreateNull())); } 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: return(CreateConstant(type, ConstVal.GetDefaultValue(type.constValKind()))); case FUNDTYPE.FT_STRUCT: if (type.isPredefType(PredefinedType.PT_DECIMAL)) { goto case FUNDTYPE.FT_R8; } break; case FUNDTYPE.FT_VAR: break; default: isError = true; break; } return(new ExprZeroInit(type, originalConstructorCall, isConstructor, isError)); }
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. ExprConstant expr = CreateConstant(pType, ConstVal.Get(Activator.CreateInstance(pType.AssociatedSystemType))); return(expr); } switch (pType.fundType()) { default: bIsError = true; break; case FUNDTYPE.FT_PTR: { CType nullType = GetTypes().GetNullType(); // It looks like this if is always false ... if (nullType.fundType() == pType.fundType()) { // Create a constant here. ExprConstant expr = CreateConstant(pType, ConstVal.GetDefaultValue(ConstValKind.IntPtr)); return(expr); } // Just allocate a new node and fill it in. ExprCast cast = CreateCast(0, pTypeExpr, CreateNull()); 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, ConstVal.GetDefaultValue(pType.constValKind())); ExprConstant exprInOriginal = CreateConstant(pType, ConstVal.GetDefaultValue(pType.constValKind())); exprInOriginal.OptionalConstructorCall = pOptionalOriginalConstructorCall; return(expr); } case FUNDTYPE.FT_STRUCT: if (pType.isPredefType(PredefinedType.PT_DECIMAL)) { ExprConstant expr = CreateConstant(pType, ConstVal.GetDefaultValue(pType.constValKind())); ExprConstant exprOriginal = CreateConstant(pType, ConstVal.GetDefaultValue(pType.constValKind())); exprOriginal.OptionalConstructorCall = 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); }
private AggregateType GetEnumBinOpType(ExpressionKind ek, CType argType1, CType argType2, out AggregateType ppEnumType) { Debug.Assert(argType1.isEnumType() || argType2.isEnumType()); AggregateType type1 = argType1.AsAggregateType(); AggregateType type2 = argType2.AsAggregateType(); AggregateType typeEnum = type1.isEnumType() ? type1 : type2; Debug.Assert(type1 == typeEnum || type1 == typeEnum.underlyingEnumType()); Debug.Assert(type2 == typeEnum || type2 == typeEnum.underlyingEnumType()); AggregateType typeDst = typeEnum; switch (ek) { case ExpressionKind.EK_BITAND: case ExpressionKind.EK_BITOR: case ExpressionKind.EK_BITXOR: Debug.Assert(type1 == type2); break; case ExpressionKind.EK_ADD: Debug.Assert(type1 != type2); break; case ExpressionKind.EK_SUB: if (type1 == type2) typeDst = typeEnum.underlyingEnumType(); break; default: Debug.Assert(ek.isRelational()); typeDst = GetReqPDT(PredefinedType.PT_BOOL); break; } ppEnumType = typeEnum; return typeDst; }
private EXPR BindIncOpCore(ExpressionKind ek, EXPRFLAG flags, EXPR exprVal, CType type) { Debug.Assert(ek == ExpressionKind.EK_ADD || ek == ExpressionKind.EK_SUB); CONSTVAL cv = new CONSTVAL(); EXPR pExprResult = null; if (type.isEnumType() && type.fundType() > FUNDTYPE.FT_LASTINTEGRAL) { // This is an error case when enum derives from an illegal type. Just treat it as an int. type = GetReqPDT(PredefinedType.PT_INT); } FUNDTYPE ft = type.fundType(); CType typeTmp = type; switch (ft) { default: { Debug.Assert(type.isPredefType(PredefinedType.PT_DECIMAL)); ek = ek == ExpressionKind.EK_ADD ? ExpressionKind.EK_DECIMALINC : ExpressionKind.EK_DECIMALDEC; PREDEFMETH predefMeth = ek == ExpressionKind.EK_DECIMALINC ? PREDEFMETH.PM_DECIMAL_OPINCREMENT : PREDEFMETH.PM_DECIMAL_OPDECREMENT; pExprResult = CreateUnaryOpForPredefMethodCall(ek, predefMeth, type, exprVal); } break; case FUNDTYPE.FT_PTR: cv.iVal = 1; pExprResult = BindPtrBinOp(ek, flags, exprVal, GetExprFactory().CreateConstant(GetReqPDT(PredefinedType.PT_INT), cv)); break; case FUNDTYPE.FT_I1: case FUNDTYPE.FT_I2: case FUNDTYPE.FT_U1: case FUNDTYPE.FT_U2: typeTmp = GetReqPDT(PredefinedType.PT_INT); cv.iVal = 1; pExprResult = LScalar(ek, flags, exprVal, type, cv, pExprResult, typeTmp); break; case FUNDTYPE.FT_I4: case FUNDTYPE.FT_U4: cv.iVal = 1; pExprResult = LScalar(ek, flags, exprVal, type, cv, pExprResult, typeTmp); break; case FUNDTYPE.FT_I8: case FUNDTYPE.FT_U8: cv = GetExprConstants().Create((long)1); pExprResult = LScalar(ek, flags, exprVal, type, cv, pExprResult, typeTmp); break; case FUNDTYPE.FT_R4: case FUNDTYPE.FT_R8: cv = GetExprConstants().Create(1.0); pExprResult = LScalar(ek, flags, exprVal, type, cv, pExprResult, typeTmp); break; } Debug.Assert(pExprResult != null); Debug.Assert(!pExprResult.type.IsNullableType()); return pExprResult; }