示例#1
0
        public ExprClass CreateClass(CType pType, ExprTypeArguments pOptionalTypeArguments)
        {
            Debug.Assert(pType != null);
            ExprClass rval = new ExprClass(pType);

            return(rval);
        }
示例#2
0
        private ExprTypeOf CreateTypeOf(ExprClass pSourceType)
        {
            ExprTypeOf rval = new ExprTypeOf(GetTypes().GetReqPredefAgg(PredefinedType.PT_TYPE).getThisType());

            rval.Flags      = EXPRFLAG.EXF_CANTBENULL;
            rval.SourceType = pSourceType;
            return(rval);
        }
示例#3
0
文件: Cast.cs 项目: stantoxt/corefx
 public ExprCast(EXPRFLAG flags, ExprClass destinationType, Expr argument)
     : base(ExpressionKind.Cast)
 {
     Debug.Assert(argument != null);
     Debug.Assert(destinationType != null);
     Debug.Assert((flags & ~(EXPRFLAG.EXF_CAST_ALL | EXPRFLAG.EXF_MASK_ANY)) == 0);
     Argument        = argument;
     Flags           = flags;
     DestinationType = destinationType;
 }
示例#4
0
        public ExprClass CreateClass(CType pType, Expr pOptionalLHS, ExprTypeArguments pOptionalTypeArguments)
        {
            Debug.Assert(pType != null);
            ExprClass rval = new ExprClass();

            rval.Kind            = ExpressionKind.EK_CLASS;
            rval.Type            = pType;
            rval.TypeOrNamespace = pType;
            Debug.Assert(rval != null);
            return(rval);
        }
示例#5
0
 public ImplicitConversion(ExpressionBinder binder, Expr exprSrc, CType typeSrc, ExprClass typeDest, bool needsExprDest, CONVERTTYPE flags)
 {
     _binder        = binder;
     _exprSrc       = exprSrc;
     _typeSrc       = typeSrc;
     _typeDest      = typeDest.Type;
     _exprTypeDest  = typeDest;
     _needsExprDest = needsExprDest;
     _flags         = flags;
     _exprDest      = null;
 }
示例#6
0
            // ----------------------------------------------------------------------------
            // BindExplicitConversion
            // ----------------------------------------------------------------------------

            public ExplicitConversion(ExpressionBinder binder, Expr exprSrc, CType typeSrc, ExprClass typeDest, CType pDestinationTypeForLambdaErrorReporting, bool needsExprDest, CONVERTTYPE flags)
            {
                _binder   = binder;
                _exprSrc  = exprSrc;
                _typeSrc  = typeSrc;
                _typeDest = typeDest.Type;
                _pDestinationTypeForLambdaErrorReporting = pDestinationTypeForLambdaErrorReporting;
                _exprTypeDest  = typeDest;
                _needsExprDest = needsExprDest;
                _flags         = flags;
                _exprDest      = null;
            }
示例#7
0
        public ExprCast CreateCast(EXPRFLAG nFlags, ExprClass pType, Expr pArg)
        {
            Debug.Assert(pArg != null);
            Debug.Assert(pType != null);
            Debug.Assert(0 == (nFlags & ~(EXPRFLAG.EXF_CAST_ALL | EXPRFLAG.EXF_MASK_ANY)));
            ExprCast rval = new ExprCast();

            rval.Argument        = pArg;
            rval.Flags           = nFlags;
            rval.DestinationType = pType;
            return(rval);
        }
示例#8
0
            private AggCastResult bindExplicitConversionFromEnumToDecimal(AggregateType aggTypeDest)
            {
                Debug.Assert(_typeSrc != null);
                Debug.Assert(aggTypeDest != null);
                Debug.Assert(aggTypeDest.isPredefType(PredefinedType.PT_DECIMAL));

                AggregateType underlyingType = _typeSrc.underlyingType() as AggregateType;

                // Need to first cast the source expr to its underlying type.

                Expr exprCast;

                if (_exprSrc == null)
                {
                    exprCast = null;
                }
                else
                {
                    ExprClass underlyingExpr = GetExprFactory().CreateClass(underlyingType);
                    _binder.bindSimpleCast(_exprSrc, underlyingExpr, out exprCast);
                }

                // There is always an implicit conversion from any integral type to decimal.

                if (exprCast.GetConst() != null)
                {
                    // Fold the constant cast if possible.
                    ConstCastResult result = _binder.bindConstantCast(exprCast, _exprTypeDest, _needsExprDest, out _exprDest, true);
                    if (result == ConstCastResult.Success)
                    {
                        return(AggCastResult.Success);  // else, don't fold and use a regular cast, below.
                    }
                    if (result == ConstCastResult.CheckFailure && 0 == (_flags & CONVERTTYPE.CHECKOVERFLOW))
                    {
                        return(AggCastResult.Abort);
                    }
                }

                // Conversions from integral types to decimal are always bound as a user-defined conversion.

                if (_needsExprDest)
                {
                    // According the language, this is a standard conversion, but it is implemented
                    // through a user-defined conversion. Because it's a standard conversion, we don't
                    // test the CONVERTTYPE.NOUDC flag here.

                    bool ok = _binder.bindUserDefinedConversion(exprCast, underlyingType, aggTypeDest, _needsExprDest, out _exprDest, false);
                    Debug.Assert(ok);
                }

                return(AggCastResult.Success);
            }
示例#9
0
            private bool bindExplicitConversionToTypeVar()
            {
                // 13.2.3 Explicit reference conversions
                //
                // For a type-parameter T that is known to be a reference type (25.7), the following
                // explicit reference conversions exist:
                //
                // * From the effective base class C of T to T and from any base class of C to T.
                // * From any interface-type to T.
                // * From a type-parameter U to T provided that T depends on U (25.7).

                Debug.Assert(_typeSrc != null);
                Debug.Assert(_typeDest != null);

                // NOTE: for the flags, we have to use EXPRFLAG.EXF_FORCE_UNBOX (not EXPRFLAG.EXF_REFCHECK) even when
                // we know that the type is a reference type. The verifier expects all code for
                // type parameters to behave as if the type parameter is a value type.
                // The jitter should be smart about it....
                if (_typeSrc.isInterfaceType() || _binder.canConvert(_typeDest, _typeSrc, CONVERTTYPE.NOUDC))
                {
                    if (!_needsExprDest)
                    {
                        return(true);
                    }

                    // There is an explicit, possibly unboxing, conversion from Object or any interface to
                    // a type variable. This will involve a type check and possibly an unbox.
                    // There is an explicit conversion from non-interface X to the type var iff there is an
                    // implicit conversion from the type var to X.
                    if (_typeSrc is TypeParameterType)
                    {
                        // Need to box first before unboxing.
                        Expr      exprT;
                        ExprClass exprObj = GetExprFactory().CreateClass(_binder.GetPredefindType(PredefinedType.PT_OBJECT));
                        _binder.bindSimpleCast(_exprSrc, exprObj, out exprT, EXPRFLAG.EXF_FORCE_BOX);
                        _exprSrc = exprT;
                    }
                    if (_needsExprDest)
                    {
                        _binder.bindSimpleCast(_exprSrc, _exprTypeDest, out _exprDest, EXPRFLAG.EXF_FORCE_UNBOX);
                    }
                    return(true);
                }
                return(false);
            }
示例#10
0
 protected virtual Expr VisitCLASS(ExprClass pExpr)
 {
     return(VisitEXPR(pExpr));
 }
示例#11
0
 private ExprTypeOf CreateTypeOf(ExprClass sourceType) =>
 new ExprTypeOf(Types.GetPredefAgg(PredefinedType.PT_TYPE).getThisType(), sourceType);
示例#12
0
 public ExprCast CreateCast(EXPRFLAG flags, ExprClass type, Expr argument) => new ExprCast(flags, type, argument);
示例#13
0
        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));
        }
示例#14
0
            /***************************************************************************************************
            *   Called by BindImplicitConversion when the destination type is Nullable<T>. The following
            *   conversions are handled by this method:
            *
            * For S in { object, ValueType, interfaces implemented by underlying type} there is an explicit
            *     unboxing conversion S => T?
            * System.Enum => T? there is an unboxing conversion if T is an enum type
            * null => T? implemented as default(T?)
            *
            * Implicit T?* => T?+ implemented by either wrapping or calling GetValueOrDefault the
            *     appropriate number of times.
            * If imp/exp S => T then imp/exp S => T?+ implemented by converting to T then wrapping the
            *     appropriate number of times.
            * If imp/exp S => T then imp/exp S?+ => T?+ implemented by calling GetValueOrDefault (m-1) times
            *     then calling HasValue, producing a null if it returns false, otherwise calling Value,
            *     converting to T then wrapping the appropriate number of times.
            *
            *   The 3 rules above can be summarized with the following recursive rules:
            *
            * If imp/exp S => T? then imp/exp S? => T? implemented as
            *     qs.HasValue ? (T?)(qs.Value) : default(T?)
            * If imp/exp S => T then imp/exp S => T? implemented as new T?((T)s)
            *
            *   This method also handles calling bindUserDefinedConverion. This method does NOT handle
            *   the following conversions:
            *
            * Implicit boxing conversion from S? to { object, ValueType, Enum, ifaces implemented by S }. (Handled by BindImplicitConversion.)
            * If imp/exp S => T then explicit S?+ => T implemented by calling Value the appropriate number
            *     of times. (Handled by BindExplicitConversion.)
            *
            *   The recursive equivalent is:
            *
            * If imp/exp S => T and T is not nullable then explicit S? => T implemented as qs.Value
            *
            *   Some nullable conversion are NOT standard conversions. In particular, if S => T is implicit
            *   then S? => T is not standard. Similarly if S => T is not implicit then S => T? is not standard.
            ***************************************************************************************************/
            private bool BindNubConversion(NullableType nubDst)
            {
                // This code assumes that STANDARD and ISEXPLICIT are never both set.
                // bindUserDefinedConversion should ensure this!
                Debug.Assert(0 != (~_flags & (CONVERTTYPE.STANDARD | CONVERTTYPE.ISEXPLICIT)));
                Debug.Assert(_exprSrc == null || _exprSrc.Type == _typeSrc);
                Debug.Assert(!_needsExprDest || _exprSrc != null);
                Debug.Assert(_typeSrc != nubDst); // BindImplicitConversion should have taken care of this already.
                AggregateType atsDst = nubDst.GetAts();

                // Check for the unboxing conversion. This takes precedence over the wrapping conversions.
                if (GetSymbolLoader().HasBaseConversion(nubDst.GetUnderlyingType(), _typeSrc) && !CConversions.FWrappingConv(_typeSrc, nubDst))
                {
                    // These should be different! Fix the caller if typeSrc is an AggregateType of Nullable.
                    Debug.Assert(atsDst != _typeSrc);

                    // typeSrc is a base type of the destination nullable type so there is an explicit
                    // unboxing conversion.
                    if (0 == (_flags & CONVERTTYPE.ISEXPLICIT))
                    {
                        return(false);
                    }

                    if (_needsExprDest)
                    {
                        _binder.bindSimpleCast(_exprSrc, _exprTypeDest, out _exprDest, EXPRFLAG.EXF_UNBOX);
                    }
                    return(true);
                }

                bool           dstWasNullable;
                bool           srcWasNullable;
                CType          typeDstBase     = nubDst.StripNubs(out dstWasNullable);
                ExprClass      exprTypeDstBase = GetExprFactory().CreateClass(typeDstBase);
                CType          typeSrcBase     = _typeSrc.StripNubs(out srcWasNullable);
                ConversionFunc pfn             = (_flags & CONVERTTYPE.ISEXPLICIT) != 0 ?
                                                 (ConversionFunc)_binder.BindExplicitConversion :
                                                 (ConversionFunc)_binder.BindImplicitConversion;

                if (!srcWasNullable)
                {
                    Debug.Assert(_typeSrc == typeSrcBase);

                    // The null type can be implicitly converted to T? as the default value.
                    if (_typeSrc is NullType)
                    {
                        // If we have the constant null, generate it as a default value of T?.  If we have
                        // some crazy expression which has been determined to be always null, like (null??null)
                        // keep it in its expression form and transform it in the nullable rewrite pass.
                        if (_needsExprDest)
                        {
                            if (_exprSrc.isCONSTANT_OK())
                            {
                                _exprDest = GetExprFactory().CreateZeroInit(nubDst);
                            }
                            else
                            {
                                _exprDest = GetExprFactory().CreateCast(_typeDest, _exprSrc);
                            }
                        }
                        return(true);
                    }

                    Expr exprTmp = _exprSrc;

                    // If there is an implicit/explicit S => T then there is an implicit/explicit S => T?
                    if (_typeSrc == typeDstBase || pfn(_exprSrc, _typeSrc, exprTypeDstBase, nubDst, _needsExprDest, out exprTmp, _flags | CONVERTTYPE.NOUDC))
                    {
                        if (_needsExprDest)
                        {
                            ExprUserDefinedConversion exprUDC = exprTmp as ExprUserDefinedConversion;
                            if (exprUDC != null)
                            {
                                exprTmp = exprUDC.UserDefinedCall;
                            }

                            if (dstWasNullable)
                            {
                                ExprCall call = _binder.BindNubNew(exprTmp);
                                exprTmp = call;
                                call.NullableCallLiftKind = NullableCallLiftKind.NullableConversionConstructor;
                            }

                            if (exprUDC != null)
                            {
                                exprUDC.UserDefinedCall = exprTmp;
                                exprTmp = exprUDC;
                            }

                            Debug.Assert(exprTmp.Type == nubDst);
                            _exprDest = exprTmp;
                        }
                        return(true);
                    }

                    // No builtin conversion. Maybe there is a user defined conversion....
                    return(0 == (_flags & CONVERTTYPE.NOUDC) && _binder.bindUserDefinedConversion(_exprSrc, _typeSrc, nubDst, _needsExprDest, out _exprDest, 0 == (_flags & CONVERTTYPE.ISEXPLICIT)));
                }

                // Both are Nullable so there is only a conversion if there is a conversion between the base types.
                // That is, if there is an implicit/explicit S => T then there is an implicit/explicit S?+ => T?+.
                if (typeSrcBase != typeDstBase && !pfn(null, typeSrcBase, exprTypeDstBase, nubDst, false, out _exprDest, _flags | CONVERTTYPE.NOUDC))
                {
                    // No builtin conversion. Maybe there is a user defined conversion....
                    return(0 == (_flags & CONVERTTYPE.NOUDC) && _binder.bindUserDefinedConversion(_exprSrc, _typeSrc, nubDst, _needsExprDest, out _exprDest, 0 == (_flags & CONVERTTYPE.ISEXPLICIT)));
                }

                if (_needsExprDest)
                {
                    MethWithInst    mwi       = new MethWithInst(null, null);
                    ExprMemberGroup pMemGroup = GetExprFactory().CreateMemGroup(null, mwi);
                    ExprCall        exprDst   = GetExprFactory().CreateCall(0, nubDst, _exprSrc, pMemGroup, null);

                    // Here we want to first check whether or not the conversions work on the base types.

                    Expr      arg1 = _binder.mustCast(_exprSrc, typeSrcBase);
                    ExprClass arg2 = GetExprFactory().CreateClass(typeDstBase);

                    bool convertible = (_flags & CONVERTTYPE.ISEXPLICIT) != 0
                        ? _binder.BindExplicitConversion(
                        arg1, arg1.Type, arg2, typeDstBase, out arg1, _flags | CONVERTTYPE.NOUDC)
                        : _binder.BindImplicitConversion(
                        arg1, arg1.Type, arg2, typeDstBase, out arg1, _flags | CONVERTTYPE.NOUDC);

                    if (!convertible)
                    {
                        Debug.Fail("bind(Im|Ex)plicitConversion failed unexpectedly");
                        return(false);
                    }

                    exprDst.CastOfNonLiftedResultToLiftedType = _binder.mustCast(arg1, nubDst, 0);
                    exprDst.NullableCallLiftKind = NullableCallLiftKind.NullableConversion;
                    exprDst.PConversions         = exprDst.CastOfNonLiftedResultToLiftedType;
                    _exprDest = exprDst;
                }

                return(true);
            }
示例#15
0
 protected virtual Expr VisitCLASS(ExprClass pExpr)
 {
     return(VisitTYPEORNAMESPACE(pExpr));
 }
示例#16
0
        ////////////////////////////////////////////////////////////////////////////////
        //
        // Precondition:
        //
        // pType - Non-null
        //
        // This returns a null for reference types and an EXPRZEROINIT for all others.

        public Expr CreateZeroInit(CType pType)
        {
            ExprClass exprClass = MakeClass(pType);

            return(CreateZeroInit(exprClass));
        }
示例#17
0
            private bool bindImplicitConversionFromTypeVar(TypeParameterType tyVarSrc)
            {
                // 13.1.4
                //
                // For a type-parameter T that is known to be a reference type (25.7), the following implicit
                // reference conversions exist:
                //
                // *   From T to its effective base class C, from T to any base class of C, and from T to any
                //     interface implemented by C.
                // *   From T to an interface-type I in T's effective interface set and from T to any base
                //     interface of I.
                // *   From T to a type parameter U provided that T depends on U (25.7). [Note: Since T is known
                //     to be a reference type, within the scope of T, the run-time type of U will always be a
                //     reference type, even if U is not known to be a reference type at compile-time.]
                // *   From the null type (11.2.7) to T.
                //
                // 13.1.5
                //
                // For a type-parameter T that is not known to be a reference type (25.7), the following conversions
                // involving T are considered to be boxing conversions at compile-time. At run-time, if T is a value
                // type, the conversion is executed as a boxing conversion. At run-time, if T is a reference type,
                // the conversion is executed as an implicit reference conversion or identity conversion.
                //
                // *   From T to its effective base class C, from T to any base class of C, and from T to any
                //     interface implemented by C. [Note: C will be one of the types System.Object, System.ValueType,
                //     or System.Enum (otherwise T would be known to be a reference type and 13.1.4 would apply
                //     instead of this clause).]
                // *   From T to an interface-type I in T's effective interface set and from T to any base
                //     interface of I.
                //
                // 13.1.6 Implicit type parameter conversions
                //
                // This clause details implicit conversions involving type parameters that are not classified as
                // implicit reference conversions or implicit boxing conversions.
                //
                // For a type-parameter T that is not known to be a reference type, there is an implicit conversion
                // from T to a type parameter U provided T depends on U. At run-time, if T is a value type and U is
                // a reference type, the conversion is executed as a boxing conversion. At run-time, if both T and U
                // are value types, then T and U are necessarily the same type and no conversion is performed. At
                // run-time, if T is a reference type, then U is necessarily also a reference type and the conversion
                // is executed as an implicit reference conversion or identity conversion (25.7).

                CType     typeTmp = tyVarSrc.GetEffectiveBaseClass();
                TypeArray bnds    = tyVarSrc.GetBounds();
                int       itype   = -1;

                for (; ;)
                {
                    if (_binder.canConvert(typeTmp, _typeDest, _flags | CONVERTTYPE.NOUDC))
                    {
                        if (!_needsExprDest)
                        {
                            return(true);
                        }
                        if (_typeDest.IsTypeParameterType())
                        {
                            // For a type var destination we need to cast to object then to the other type var.
                            Expr      exprT;
                            ExprClass exprObj = GetExprFactory().MakeClass(_binder.GetReqPDT(PredefinedType.PT_OBJECT));
                            _binder.bindSimpleCast(_exprSrc, exprObj, out exprT, EXPRFLAG.EXF_FORCE_BOX);
                            _binder.bindSimpleCast(exprT, _exprTypeDest, out _exprDest, EXPRFLAG.EXF_FORCE_UNBOX);
                        }
                        else
                        {
                            _binder.bindSimpleCast(_exprSrc, _exprTypeDest, out _exprDest, EXPRFLAG.EXF_FORCE_BOX);
                        }
                        return(true);
                    }
                    do
                    {
                        if (++itype >= bnds.Count)
                        {
                            return(false);
                        }
                        typeTmp = bnds[itype];
                    }while (!typeTmp.isInterfaceType() && !typeTmp.IsTypeParameterType());
                }
            }
示例#18
0
        private Expr CreateZeroInit(ExprClass pTypeExpr, Expr pOptionalOriginalConstructorCall, bool isConstructor)
        {
            Debug.Assert(pTypeExpr != null);
            CType pType    = pTypeExpr.Type;
            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(pType);

            rval.OptionalConstructorCall = pOptionalOriginalConstructorCall;
            rval.IsConstructor           = isConstructor;

            if (bIsError)
            {
                rval.SetError();
            }

            return(rval);
        }
示例#19
0
 private Expr CreateZeroInit(ExprClass pTypeExpr)
 {
     return(CreateZeroInit(pTypeExpr, null, false));
 }