Esempio n. 1
0
 public static EXPR StripNullableConstructor(EXPR pExpr)
 {
     while (IsNullableConstructor(pExpr))
     {
         Debug.Assert(pExpr.isCALL());
         pExpr = pExpr.asCALL().GetOptionalArguments();
         Debug.Assert(pExpr != null && !pExpr.isLIST());
     }
     return pExpr;
 }
Esempio n. 2
0
        protected override EXPR Dispatch(EXPR expr)
        {
            Debug.Assert(expr != null);

            EXPR result = base.Dispatch(expr);
            if (result == expr)
            {
                throw Error.InternalCompilerError();
            }
            return result;
        }
Esempio n. 3
0
 public ImplicitConversion(ExpressionBinder binder, EXPR exprSrc, CType typeSrc, EXPRTYPEORNAMESPACE typeDest, bool needsExprDest, CONVERTTYPE flags)
 {
     _binder = binder;
     _exprSrc = exprSrc;
     _typeSrc = typeSrc;
     _typeDest = typeDest.TypeOrNamespace.AsType();
     _exprTypeDest = typeDest;
     _needsExprDest = needsExprDest;
     _flags = flags;
     _exprDest = null;
 }
Esempio n. 4
0
            // ----------------------------------------------------------------------------
            // BindExplicitConversion
            // ----------------------------------------------------------------------------

            public ExplicitConversion(ExpressionBinder binder, EXPR exprSrc, CType typeSrc, EXPRTYPEORNAMESPACE typeDest, CType pDestinationTypeForLambdaErrorReporting, bool needsExprDest, CONVERTTYPE flags)
            {
                _binder = binder;
                _exprSrc = exprSrc;
                _typeSrc = typeSrc;
                _typeDest = typeDest.TypeOrNamespace.AsType();
                _pDestinationTypeForLambdaErrorReporting = pDestinationTypeForLambdaErrorReporting;
                _exprTypeDest = typeDest;
                _needsExprDest = needsExprDest;
                _flags = flags;
                _exprDest = null;
            }
Esempio n. 5
0
 public EXPRFUNCPTR CreateFunctionPointer(EXPRFLAG nFlags, CType pType, EXPR pObject, MethWithInst MWI)
 {
     Debug.Assert(0 == (nFlags & ~(EXPRFLAG.EXF_BASECALL)));
     EXPRFUNCPTR rval = new EXPRFUNCPTR();
     rval.kind = ExpressionKind.EK_FUNCPTR;
     rval.type = pType;
     rval.flags = nFlags;
     rval.OptionalObject = pObject;
     rval.mwi = new MethWithInst(MWI);
     Debug.Assert(rval != null);
     return (rval);
 }
Esempio n. 6
0
 public EXPRFIELD CreateField(EXPRFLAG nFlags, CType pType, EXPR pOptionalObject, uint nOffset, FieldWithType FWT, EXPR pOptionalLHS)
 {
     Debug.Assert(0 == (nFlags & ~(EXPRFLAG.EXF_MEMBERSET | EXPRFLAG.EXF_MASK_ANY)));
     EXPRFIELD rval = new EXPRFIELD();
     rval.kind = ExpressionKind.EK_FIELD;
     rval.type = pType;
     rval.flags = nFlags;
     rval.SetOptionalObject(pOptionalObject);
     if (FWT != null)
     {
         rval.fwt = FWT;
     }
     Debug.Assert(rval != null);
     return (rval);
 }
Esempio n. 7
0
        public EXPRCAST CreateCast(EXPRFLAG nFlags, EXPRTYPEORNAMESPACE 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.type            = pType.TypeOrNamespace as CType;
            rval.kind            = ExpressionKind.EK_CAST;
            rval.Argument        = pArg;
            rval.flags           = nFlags;
            rval.DestinationType = pType;
            Debug.Assert(rval != null);
            return(rval);
        }
Esempio n. 8
0
 public BinOpArgInfo(EXPR op1, EXPR op2)
 {
     Debug.Assert(op1 != null);
     Debug.Assert(op2 != null);
     arg1 = op1;
     arg2 = op2;
     type1 = arg1.type;
     type2 = arg2.type;
     typeRaw1 = type1.StripNubs();
     typeRaw2 = type2.StripNubs();
     pt1 = type1.isPredefined() ? type1.getPredefType() : PredefinedType.PT_COUNT;
     pt2 = type2.isPredefined() ? type2.getPredefType() : PredefinedType.PT_COUNT;
     ptRaw1 = typeRaw1.isPredefined() ? typeRaw1.getPredefType() : PredefinedType.PT_COUNT;
     ptRaw2 = typeRaw2.isPredefined() ? typeRaw2.getPredefType() : PredefinedType.PT_COUNT;
 }
Esempio n. 9
0
        public EXPRARRINIT CreateArrayInit(EXPRFLAG nFlags, CType pType, EXPR pOptionalArguments, EXPR pOptionalArgumentDimensions, int[] pDimSizes)
        {
            Debug.Assert(0 == (nFlags &
                               ~(EXPRFLAG.EXF_MASK_ANY | EXPRFLAG.EXF_ARRAYCONST | EXPRFLAG.EXF_ARRAYALLCONST)));
            EXPRARRINIT rval = new EXPRARRINIT();

            rval.kind = ExpressionKind.EK_ARRINIT;
            rval.type = pType;
            rval.SetOptionalArguments(pOptionalArguments);
            rval.SetOptionalArgumentDimensions(pOptionalArgumentDimensions);
            rval.dimSizes = pDimSizes;
            rval.dimSize  = pDimSizes != null ? pDimSizes.Length : 0;
            Debug.Assert(rval != null);
            return(rval);
        }
Esempio n. 10
0
        public EXPRUNARYOP CreateUnaryOp(ExpressionKind exprKind, CType pType, EXPR pOperand)
        {
            Debug.Assert(exprKind.isUnaryOperator());
            Debug.Assert(pOperand != null);
            EXPRUNARYOP rval = new EXPRUNARYOP();

            rval.kind  = exprKind;
            rval.type  = pType;
            rval.flags = 0;
            rval.Child = pOperand;
            rval.OptionalUserDefinedCall = null;
            rval.UserDefinedCallMethod   = null;
            Debug.Assert(rval != null);
            return(rval);
        }
Esempio n. 11
0
        public EXPREVENT CreateEvent(CType pType, EXPR pOptionalObject, EventWithType EWT)
        {
            EXPREVENT rval = new EXPREVENT();

            rval.kind           = ExpressionKind.EK_EVENT;
            rval.type           = pType;
            rval.flags          = 0;
            rval.OptionalObject = pOptionalObject;
            if (EWT != null)
            {
                rval.ewt = EWT;
            }
            Debug.Assert(rval != null);
            return(rval);
        }
Esempio n. 12
0
        /////////////////////////////////////////////////////////////////////////////////

        protected EXPRSTMT DispatchStatementList(EXPRSTMT expr)
        {
            Debug.Assert(expr != null);

            EXPRSTMT first = expr;
            EXPRSTMT pexpr = first;

            while (pexpr != null)
            {
                // If the processor replaces the statement -- potentially with
                // null, another statement, or a list of statements -- then we
                // make sure that the statement list is hooked together correctly.

                EXPRSTMT next = pexpr.GetOptionalNextStatement();
                EXPRSTMT old  = pexpr;

                // Unhook the next one.
                pexpr.SetOptionalNextStatement(null);

                EXPR result = Dispatch(pexpr);
                Debug.Assert(result == null || result.isSTMT());

                if (pexpr == first)
                {
                    first = (result == null) ? null : result.asSTMT();
                }
                else
                {
                    pexpr.SetOptionalNextStatement((result == null) ? null : result.asSTMT());
                }

                // A transformation may return back a list of statements (or
                // if the statements have been determined to be unnecessary,
                // perhaps it has simply returned null.)
                //
                // Skip visiting the new list, then hook the tail of the old list
                // up to the end of the new list.

                while (pexpr.GetOptionalNextStatement() != null)
                {
                    pexpr = pexpr.GetOptionalNextStatement();
                }

                // Re-hook the next pointer.
                pexpr.SetOptionalNextStatement(next);
            }
            return(first);
        }
Esempio n. 13
0
            private bool bindImplicitConversionFromNullable(NullableType nubSrc)
            {
                // We can convert T? using a boxing conversion, we can convert it to ValueType, and
                // we can convert it to any interface implemented by T.
                //
                // 13.1.5 Boxing Conversions
                //
                // A nullable-type has a boxing conversion to the same set of types to which the nullable-type's
                // underlying type has boxing conversions. A boxing conversion applied to a value of a nullable-type
                // proceeds as follows:
                //
                // *   If the HasValue property of the nullable value evaluates to false, then the result of the
                //     boxing conversion is the null reference of the appropriate type.
                //
                // Otherwise, the result is obtained by boxing the result of evaluating the Value property on
                // the nullable value.

                AggregateType atsNub = nubSrc.GetAts(GetErrorContext());

                if (atsNub == null)
                {
                    return(false);
                }
                if (atsNub == _typeDest)
                {
                    if (_needsExprDest)
                    {
                        _exprDest = _exprSrc;
                    }
                    return(true);
                }
                if (GetSymbolLoader().HasBaseConversion(nubSrc.GetUnderlyingType(), _typeDest) && !CConversions.FUnwrappingConv(nubSrc, _typeDest))
                {
                    if (_needsExprDest)
                    {
                        _binder.bindSimpleCast(_exprSrc, _exprTypeDest, out _exprDest, EXPRFLAG.EXF_BOX);
                        if (!_typeDest.isPredefType(PredefinedType.PT_OBJECT))
                        {
                            // The base type of a nullable is always a non-nullable value type,
                            // therefore so is typeDest unless typeDest is PT_OBJECT. In this case the conversion
                            // needs to be unboxed. We only need this if we actually will use the result.
                            _binder.bindSimpleCast(_exprDest, _exprTypeDest, out _exprDest, EXPRFLAG.EXF_FORCE_UNBOX);
                        }
                    }
                    return(true);
                }
                return(0 == (_flags & CONVERTTYPE.NOUDC) && _binder.bindUserDefinedConversion(_exprSrc, nubSrc, _typeDest, _needsExprDest, out _exprDest, true));
            }
        public EXPRFIELD CreateField(EXPRFLAG nFlags, CType pType, EXPR pOptionalObject, uint nOffset, FieldWithType FWT, EXPR pOptionalLHS)
        {
            Debug.Assert(0 == (nFlags & ~(EXPRFLAG.EXF_MEMBERSET | EXPRFLAG.EXF_MASK_ANY)));
            EXPRFIELD rval = new EXPRFIELD();

            rval.kind  = ExpressionKind.EK_FIELD;
            rval.type  = pType;
            rval.flags = nFlags;
            rval.SetOptionalObject(pOptionalObject);
            if (FWT != null)
            {
                rval.fwt = FWT;
            }
            Debug.Assert(rval != null);
            return(rval);
        }
        public EXPRBINOP CreateBinop(ExpressionKind exprKind, CType pType, EXPR p1, EXPR p2)
        {
            //Debug.Assert(exprKind.isBinaryOperator());
            EXPRBINOP rval = new EXPRBINOP();

            rval.kind  = exprKind;
            rval.type  = pType;
            rval.flags = EXPRFLAG.EXF_BINOP;
            rval.SetOptionalLeftChild(p1);
            rval.SetOptionalRightChild(p2);
            rval.isLifted = false;
            rval.SetOptionalUserDefinedCall(null);
            rval.SetUserDefinedCallMethod(null);
            Debug.Assert(rval != null);
            return(rval);
        }
        public EXPRMEMGRP CreateMemGroup(
            EXPR pObject,
            MethPropWithInst mwi)
        {
            Name pName = mwi.Sym != null ? mwi.Sym.name : null;
            MethodOrPropertySymbol methProp = mwi.MethProp();

            CType pType = mwi.GetType();

            if (pType == null)
            {
                pType = GetTypes().GetErrorSym();
            }

            return(CreateMemGroup(0, pName, mwi.TypeArgs, methProp != null ? methProp.getKind() : SYMKIND.SK_MethodSymbol, mwi.GetType(), methProp, pObject, new CMemberLookupResults(GetGlobalSymbols().AllocParams(1, new CType[] { pType }), pName)));
        }
        public EXPRRETURN CreateReturn(EXPRFLAG nFlags, Scope pCurrentScope, EXPR pOptionalObject, EXPR pOptionalOriginalObject)
        {
            Debug.Assert(0 == (nFlags &
                               ~(EXPRFLAG.EXF_ASLEAVE | EXPRFLAG.EXF_FINALLYBLOCKED | EXPRFLAG.EXF_RETURNISYIELD |
                                 EXPRFLAG.EXF_ASFINALLYLEAVE | EXPRFLAG.EXF_GENERATEDSTMT | EXPRFLAG.EXF_MARKING |
                                 EXPRFLAG.EXF_MASK_ANY
                                 )
                               ));
            EXPRRETURN rval = new EXPRRETURN();

            rval.kind  = ExpressionKind.EK_RETURN;
            rval.type  = null;
            rval.flags = nFlags;
            rval.SetOptionalObject(pOptionalObject);
            Debug.Assert(rval != null);
            return(rval);
        }
        public EXPR CreateOperator(ExpressionKind exprKind, CType pType, EXPR pArg1, EXPR pOptionalArg2)
        {
            Debug.Assert(pArg1 != null);
            EXPR rval = null;

            if (exprKind.isUnaryOperator())
            {
                Debug.Assert(pOptionalArg2 == null);
                rval = CreateUnaryOp(exprKind, pType, pArg1);
            }
            else
            {
                rval = CreateBinop(exprKind, pType, pArg1, pOptionalArg2);
            }
            Debug.Assert(rval != null);
            return(rval);
        }
Esempio n. 19
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.IsTypeParameterType())
                    {
                        // Need to box first before unboxing.
                        EXPR      exprT;
                        EXPRCLASS exprObj = GetExprFactory().MakeClass(_binder.GetReqPDT(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);
            }
Esempio n. 20
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);
            }
Esempio n. 21
0
        // Value
        public EXPR BindValue(EXPR exprSrc)
        {
            Debug.Assert(exprSrc != null && exprSrc.type.IsNullableType());

            // For new T?(x), the answer is x.
            if (CNullable.IsNullableConstructor(exprSrc))
            {
                Debug.Assert(exprSrc.asCALL().GetOptionalArguments() != null && !exprSrc.asCALL().GetOptionalArguments().isLIST());
                return(exprSrc.asCALL().GetOptionalArguments());
            }

            CType         typeBase = exprSrc.type.AsNullableType().GetUnderlyingType();
            AggregateType ats      = exprSrc.type.AsNullableType().GetAts(GetErrorContext());

            if (ats == null)
            {
                EXPRPROP rval = GetExprFactory().CreateProperty(typeBase, exprSrc);
                rval.SetError();
                return(rval);
            }

            // UNDONE: move this to transform pass ...
            PropertySymbol prop = GetSymbolLoader().getBSymmgr().propNubValue;

            if (prop == null)
            {
                prop = GetSymbolLoader().getPredefinedMembers().GetProperty(PREDEFPROP.PP_G_OPTIONAL_VALUE);
                GetSymbolLoader().getBSymmgr().propNubValue = prop;
            }

            PropWithType     pwt       = new PropWithType(prop, ats);
            MethWithType     mwt       = new MethWithType(prop != null ? prop.methGet : null, ats);
            MethPropWithInst mpwi      = new MethPropWithInst(prop, ats);
            EXPRMEMGRP       pMemGroup = GetExprFactory().CreateMemGroup(exprSrc, mpwi);
            EXPRPROP         exprRes   = GetExprFactory().CreateProperty(typeBase, null, null, pMemGroup, pwt, mwt, null);

            if (prop == null)
            {
                exprRes.SetError();
            }

            return(exprRes);
        }
        public EXPRUSERDEFINEDCONVERSION CreateUserDefinedConversion(EXPR arg, EXPR call, MethWithInst mwi)
        {
            Debug.Assert(arg != null);
            Debug.Assert(call != null);
            EXPRUSERDEFINEDCONVERSION rval = new EXPRUSERDEFINEDCONVERSION();

            rval.kind                  = ExpressionKind.EK_USERDEFINEDCONVERSION;
            rval.type                  = call.type;
            rval.flags                 = 0;
            rval.Argument              = arg;
            rval.UserDefinedCall       = call;
            rval.UserDefinedCallMethod = mwi;
            if (call.HasError())
            {
                rval.SetError();
            }
            Debug.Assert(rval != null);
            return(rval);
        }
Esempio n. 23
0
        public static IEnumerable <EXPR> ToEnumerable(this EXPR expr)
        {
            EXPR exprCur = expr;

            while (exprCur != null)
            {
                if (exprCur.isLIST())
                {
                    yield return(exprCur.asLIST().GetOptionalElement());

                    exprCur = exprCur.asLIST().GetOptionalNextListNode();
                }
                else
                {
                    yield return(exprCur);

                    yield break;
                }
            }
        }
Esempio n. 24
0
        public static EXPR Map(this EXPR expr, ExprFactory factory, Func <EXPR, EXPR> f)
        {
            Debug.Assert(f != null);
            Debug.Assert(factory != null);

            if (expr == null)
            {
                return(f(expr));
            }

            EXPR result = null;
            EXPR tail   = null;

            foreach (EXPR item in expr.ToEnumerable())
            {
                EXPR mappedItem = f(item);
                factory.AppendItemToList(mappedItem, ref result, ref tail);
            }
            return(result);
        }
Esempio n. 25
0
        public EXPR Visit(EXPR pExpr)
        {
            if (pExpr == null)
            {
                return null;
            }

            EXPR pResult;
            if (IsCachedExpr(pExpr, out pResult))
            {
                return pResult;
            }

            if (pExpr.isSTMT())
            {
                return CacheExprMapping(pExpr, DispatchStatementList(pExpr.asSTMT()));
            }

            return CacheExprMapping(pExpr, Dispatch(pExpr));
        }
        public EXPRWRAP CreateWrap(
            Scope pCurrentScope,
            EXPR pOptionalExpression
            )
        {
            EXPRWRAP rval = new EXPRWRAP();

            rval.kind  = ExpressionKind.EK_WRAP;
            rval.type  = null;
            rval.flags = 0;
            rval.SetOptionalExpression(pOptionalExpression);
            if (pOptionalExpression != null)
            {
                rval.setType(pOptionalExpression.type);
            }
            rval.flags |= EXPRFLAG.EXF_LVALUE;

            Debug.Assert(rval != null);
            return(rval);
        }
        public EXPRARRAYINDEX CreateArrayIndex(EXPR pArray, EXPR pIndex)
        {
            CType pType = pArray.type;

            if (pType != null && pType.IsArrayType())
            {
                pType = pType.AsArrayType().GetElementType();
            }
            else if (pType == null)
            {
                pType = GetTypes().GetReqPredefAgg(PredefinedType.PT_INT).getThisType();
            }
            EXPRARRAYINDEX pResult = new EXPRARRAYINDEX();

            pResult.kind  = ExpressionKind.EK_ARRAYINDEX;
            pResult.type  = pType;
            pResult.flags = 0;
            pResult.SetArray(pArray);
            pResult.SetIndex(pIndex);
            return(pResult);
        }
Esempio n. 28
0
        public EXPR Visit(EXPR pExpr)
        {
            if (pExpr == null)
            {
                return(null);
            }

            EXPR pResult;

            if (IsCachedExpr(pExpr, out pResult))
            {
                return(pResult);
            }

            if (pExpr.isSTMT())
            {
                return(CacheExprMapping(pExpr, DispatchStatementList(pExpr.asSTMT())));
            }

            return(CacheExprMapping(pExpr, Dispatch(pExpr)));
        }
Esempio n. 29
0
        // Value
        public EXPR BindValue(EXPR exprSrc)
        {
            Debug.Assert(exprSrc != null && exprSrc.type.IsNullableType());

            // For new T?(x), the answer is x.
            if (CNullable.IsNullableConstructor(exprSrc))
            {
                Debug.Assert(exprSrc.asCALL().GetOptionalArguments() != null && !exprSrc.asCALL().GetOptionalArguments().isLIST());
                return exprSrc.asCALL().GetOptionalArguments();
            }

            CType typeBase = exprSrc.type.AsNullableType().GetUnderlyingType();
            AggregateType ats = exprSrc.type.AsNullableType().GetAts(GetErrorContext());
            if (ats == null)
            {
                EXPRPROP rval = GetExprFactory().CreateProperty(typeBase, exprSrc);
                rval.SetError();
                return rval;
            }

            PropertySymbol prop = GetSymbolLoader().getBSymmgr().propNubValue;
            if (prop == null)
            {
                prop = GetSymbolLoader().getPredefinedMembers().GetProperty(PREDEFPROP.PP_G_OPTIONAL_VALUE);
                GetSymbolLoader().getBSymmgr().propNubValue = prop;
            }

            PropWithType pwt = new PropWithType(prop, ats);
            MethWithType mwt = new MethWithType(prop != null ? prop.methGet : null, ats);
            MethPropWithInst mpwi = new MethPropWithInst(prop, ats);
            EXPRMEMGRP pMemGroup = GetExprFactory().CreateMemGroup(exprSrc, mpwi);
            EXPRPROP exprRes = GetExprFactory().CreateProperty(typeBase, null, null, pMemGroup, pwt, mwt, null);

            if (prop == null)
            {
                exprRes.SetError();
            }

            return exprRes;
        }
Esempio n. 30
0
        public static bool IsNullableConstructor(EXPR expr)
        {
            Debug.Assert(expr != null);

            if (!expr.isCALL())
            {
                return false;
            }

            EXPRCALL pCall = expr.asCALL();
            if (pCall.GetMemberGroup().GetOptionalObject() != null)
            {
                return false;
            }

            MethodSymbol meth = pCall.mwi.Meth();
            if (meth == null)
            {
                return false;
            }
            return meth.IsNullableConstructor();
        }
        public EXPRPROP CreateProperty(CType pType, EXPR pOptionalObjectThrough, EXPR pOptionalArguments, EXPRMEMGRP pMemberGroup, PropWithType pwtSlot, MethWithType mwtGet, MethWithType mwtSet)
        {
            EXPRPROP rval = new EXPRPROP();

            rval.kind  = ExpressionKind.EK_PROP;
            rval.type  = pType;
            rval.flags = 0;
            rval.SetOptionalObjectThrough(pOptionalObjectThrough);
            rval.SetOptionalArguments(pOptionalArguments);
            rval.SetMemberGroup(pMemberGroup);

            if (pwtSlot != null)
            {
                rval.pwtSlot = pwtSlot;
            }
            if (mwtSet != null)
            {
                rval.mwtSet = mwtSet;
            }
            Debug.Assert(rval != null);
            return(rval);
        }
Esempio n. 32
0
            private bool bindExplicitConversionFromNub()
            {
                Debug.Assert(_typeSrc != null);
                Debug.Assert(_typeDest != null);

                // If S and T are value types and there is a builtin conversion from S => T then there is an
                // explicit conversion from S? => T that throws on null.
                if (_typeDest.IsValType() && _binder.BindExplicitConversion(null, _typeSrc.StripNubs(), _exprTypeDest, _pDestinationTypeForLambdaErrorReporting, _flags | CONVERTTYPE.NOUDC))
                {
                    if (_needsExprDest)
                    {
                        EXPR valueSrc = _exprSrc;
                        // This is a holdover from the days when you could have nullable of nullable.
                        // Can we remove this loop?
                        while (valueSrc.type.IsNullableType())
                        {
                            valueSrc = _binder.BindNubValue(valueSrc);
                        }
                        Debug.Assert(valueSrc.type == _typeSrc.StripNubs());
                        if (!_binder.BindExplicitConversion(valueSrc, valueSrc.type, _exprTypeDest, _pDestinationTypeForLambdaErrorReporting, _needsExprDest, out _exprDest, _flags | CONVERTTYPE.NOUDC))
                        {
                            VSFAIL("BindExplicitConversion failed unexpectedly");
                            return(false);
                        }
                        if (_exprDest.kind == ExpressionKind.EK_USERDEFINEDCONVERSION)
                        {
                            _exprDest.asUSERDEFINEDCONVERSION().Argument = _exprSrc;
                        }
                    }
                    return(true);
                }

                if ((_flags & CONVERTTYPE.NOUDC) == 0)
                {
                    return(_binder.bindUserDefinedConversion(_exprSrc, _typeSrc, _typeDest, _needsExprDest, out _exprDest, false));
                }
                return(false);
            }
        public EXPRQUESTIONMARK CreateQuestionMark(EXPR pTestExpression, EXPRBINOP pConsequence)
        {
            Debug.Assert(pTestExpression != null);
            Debug.Assert(pConsequence != null);

            CType pType = pConsequence.type;

            if (pType == null)
            {
                Debug.Assert(pConsequence.GetOptionalLeftChild() != null);
                pType = pConsequence.GetOptionalLeftChild().type;
                Debug.Assert(pType != null);
            }
            EXPRQUESTIONMARK pResult = new EXPRQUESTIONMARK();

            pResult.kind  = ExpressionKind.EK_QUESTIONMARK;
            pResult.type  = pType;
            pResult.flags = 0;
            pResult.SetTestExpression(pTestExpression);
            pResult.SetConsequence(pConsequence);
            Debug.Assert(pResult != null);
            return(pResult);
        }
Esempio n. 34
0
        public EXPRCALL CreateCall(EXPRFLAG nFlags, CType pType, EXPR pOptionalArguments, EXPRMEMGRP pMemberGroup, MethWithInst MWI)
        {
            Debug.Assert(0 == (nFlags &
               ~(
                   EXPRFLAG.EXF_NEWOBJCALL | EXPRFLAG.EXF_CONSTRAINED | EXPRFLAG.EXF_BASECALL |
                   EXPRFLAG.EXF_NEWSTRUCTASSG |
                   EXPRFLAG.EXF_IMPLICITSTRUCTASSG | EXPRFLAG.EXF_MASK_ANY
               )
              ));

            EXPRCALL rval = new EXPRCALL();
            rval.kind = ExpressionKind.EK_CALL;
            rval.type = pType;
            rval.flags = nFlags;
            rval.SetOptionalArguments(pOptionalArguments);
            rval.SetMemberGroup(pMemberGroup);
            rval.nubLiftKind = NullableCallLiftKind.NotLifted;
            rval.castOfNonLiftedResultToLiftedType = null;

            rval.mwi = MWI;
            Debug.Assert(rval != null);
            return (rval);
        }
Esempio n. 35
0
        public EXPRCALL BindNew(EXPR pExprSrc)
        {
            Debug.Assert(pExprSrc != null);

            NullableType pNubSourceType = GetSymbolLoader().GetTypeManager().GetNullable(pExprSrc.type);

            AggregateType pSourceType = pNubSourceType.GetAts(GetErrorContext());

            if (pSourceType == null)
            {
                MethWithInst mwi       = new MethWithInst(null, null);
                EXPRMEMGRP   pMemGroup = GetExprFactory().CreateMemGroup(pExprSrc, mwi);
                EXPRCALL     rval      = GetExprFactory().CreateCall(0, pNubSourceType, null, pMemGroup, null);
                rval.SetError();
                return(rval);
            }

            // UNDONE: move this to transform pass
            MethodSymbol meth = GetSymbolLoader().getBSymmgr().methNubCtor;

            if (meth == null)
            {
                meth = GetSymbolLoader().getPredefinedMembers().GetMethod(PREDEFMETH.PM_G_OPTIONAL_CTOR);
                GetSymbolLoader().getBSymmgr().methNubCtor = meth;
            }

            MethWithInst methwithinst = new MethWithInst(meth, pSourceType, BSYMMGR.EmptyTypeArray());
            EXPRMEMGRP   memgroup     = GetExprFactory().CreateMemGroup(null, methwithinst);
            EXPRCALL     pExprRes     = GetExprFactory().CreateCall(EXPRFLAG.EXF_NEWOBJCALL | EXPRFLAG.EXF_CANTBENULL, pNubSourceType, pExprSrc, memgroup, methwithinst);

            if (meth == null)
            {
                pExprRes.SetError();
            }

            return(pExprRes);
        }
Esempio n. 36
0
        public static bool IsNullableConstructor(EXPR expr)
        {
            Debug.Assert(expr != null);

            if (!expr.isCALL())
            {
                return(false);
            }

            EXPRCALL pCall = expr.asCALL();

            if (pCall.GetMemberGroup().GetOptionalObject() != null)
            {
                return(false);
            }

            MethodSymbol meth = pCall.mwi.Meth();

            if (meth == null)
            {
                return(false);
            }
            return(meth.IsNullableConstructor());
        }
Esempio n. 37
0
        /////////////////////////////////////////////////////////////////////////////////

        public static Expression Rewrite(TypeManager typeManager, EXPR pExpr, IEnumerable<Expression> listOfParameters)
        {
            ExpressionTreeCallRewriter rewriter = new ExpressionTreeCallRewriter(typeManager, listOfParameters);

            // We should have a EXPRBINOP thats an EK_SEQUENCE. The RHS of our sequence
            // should be a call to PM_EXPRESSION_LAMBDA. The LHS of our sequence is the 
            // set of declarations for the parameters that we'll need.
            // Assert all of these first, and then unwrap them.

            Debug.Assert(pExpr != null);
            Debug.Assert(pExpr.isBIN());
            Debug.Assert(pExpr.kind == ExpressionKind.EK_SEQUENCE);
            Debug.Assert(pExpr.asBIN().GetOptionalRightChild() != null);
            Debug.Assert(pExpr.asBIN().GetOptionalRightChild().isCALL());
            Debug.Assert(pExpr.asBIN().GetOptionalRightChild().asCALL().PredefinedMethod == PREDEFMETH.PM_EXPRESSION_LAMBDA);
            Debug.Assert(pExpr.asBIN().GetOptionalLeftChild() != null);

            // Visit the left to generate the parameter construction.
            rewriter.Visit(pExpr.asBIN().GetOptionalLeftChild());
            EXPRCALL call = pExpr.asBIN().GetOptionalRightChild().asCALL();

            ExpressionEXPR e = rewriter.Visit(call) as ExpressionEXPR;
            return e.Expression;
        }
        public EXPRCALL CreateCall(EXPRFLAG nFlags, CType pType, EXPR pOptionalArguments, EXPRMEMGRP pMemberGroup, MethWithInst MWI)
        {
            Debug.Assert(0 == (nFlags &
                               ~(
                                   EXPRFLAG.EXF_NEWOBJCALL | EXPRFLAG.EXF_CONSTRAINED | EXPRFLAG.EXF_BASECALL |
                                   EXPRFLAG.EXF_NEWSTRUCTASSG |
                                   EXPRFLAG.EXF_IMPLICITSTRUCTASSG | EXPRFLAG.EXF_MASK_ANY
                                   )
                               ));

            EXPRCALL rval = new EXPRCALL();

            rval.kind  = ExpressionKind.EK_CALL;
            rval.type  = pType;
            rval.flags = nFlags;
            rval.SetOptionalArguments(pOptionalArguments);
            rval.SetMemberGroup(pMemberGroup);
            rval.nubLiftKind = NullableCallLiftKind.NotLifted;
            rval.castOfNonLiftedResultToLiftedType = null;

            rval.mwi = MWI;
            Debug.Assert(rval != null);
            return(rval);
        }
        public void setArgs(EXPR args)
        {
            RETAILVERIFY(this.isCALL() || this.isPROP() || this.isFIELD() || this.isARRAYINDEX());
            if (this.isFIELD())
            {
                Debug.Assert(false, "Setting arguments on a field.");
                return;
            }
            switch (kind)
            {
            case ExpressionKind.EK_CALL:
                this.asCALL().SetOptionalArguments(args);
                return;

            case ExpressionKind.EK_PROP:
                this.asPROP().SetOptionalArguments(args);
                return;

            case ExpressionKind.EK_ARRAYINDEX:
                this.asARRAYINDEX().SetIndex(args);
                return;
            }
            Debug.Assert(false, "Shouldn't get here without a CALL, PROP, FIELD or ARRINDEX");
        }
Esempio n. 40
0
 protected virtual EXPR GenerateConversionWithSource(EXPR pTarget, CType pType, bool bChecked)
 {
     PREDEFMETH pdm = bChecked ? PREDEFMETH.PM_EXPRESSION_CONVERTCHECKED : PREDEFMETH.PM_EXPRESSION_CONVERT;
     EXPR pTypeOf = CreateTypeOf(pType);
     return GenerateCall(pdm, pTarget, pTypeOf);
 }
Esempio n. 41
0
 protected virtual EXPR GenerateValueAccessConversion(EXPR pArgument)
 {
     Debug.Assert(pArgument != null);
     CType pStrippedTypeOfArgument = pArgument.type.StripNubs();
     EXPR pStrippedTypeExpr = CreateTypeOf(pStrippedTypeOfArgument);
     return GenerateCall(PREDEFMETH.PM_EXPRESSION_CONVERT, Visit(pArgument), pStrippedTypeExpr);
 }
Esempio n. 42
0
        protected virtual EXPR GenerateBuiltInUnaryOperator(PREDEFMETH pdm, EXPR pOriginalOperator, EXPR pOperator)
        {
            EXPR op = Visit(pOriginalOperator);
            if (pOriginalOperator.type.IsNullableType() && pOriginalOperator.type.StripNubs().isEnumType())
            {
                Debug.Assert(pOperator.kind == ExpressionKind.EK_BITNOT); // The only built-in unary operator defined on nullable enum.
                CType underlyingType = pOriginalOperator.type.StripNubs().underlyingEnumType();
                CType nullableType = GetSymbolLoader().GetTypeManager().GetNullable(underlyingType);
                op = GenerateCall(PREDEFMETH.PM_EXPRESSION_CONVERT, op, CreateTypeOf(nullableType));
            }
            EXPR call = GenerateCall(pdm, op);
            if (pOriginalOperator.type.IsNullableType() && pOriginalOperator.type.StripNubs().isEnumType())
            {
                call = GenerateCall(PREDEFMETH.PM_EXPRESSION_CONVERT, call, CreateTypeOf(pOperator.type));
            }

            return call;
        }
Esempio n. 43
0
 protected virtual EXPR GenerateConversion(EXPR arg, CType CType, bool bChecked)
 {
     return GenerateConversionWithSource(Visit(arg), CType, bChecked || arg.isChecked());
 }
Esempio n. 44
0
        /***************************************************************************************************
        *   Lookup must be called before anything else can be called.
        *
        *   typeSrc - Must be an AggregateType or TypeParameterType.
        *   obj - the expression through which the member is being accessed. This is used for accessibility
        *       of protected members and for constructing a MEMGRP from the results of the lookup.
        *       It is legal for obj to be an EK_CLASS, in which case it may be used for accessibility, but
        *       will not be used for MEMGRP construction.
        *   symWhere - the symbol from with the name is being accessed (for checking accessibility).
        *   name - the name to look for.
        *   arity - the number of type args specified. Only members that support this arity are found.
        *       Note that when arity is zero, all methods are considered since we do type argument
        *       inferencing.
        *
        *   flags - See MemLookFlags.
        *       TypeVarsAllowed only applies to the most derived type (not base types).
        ***************************************************************************************************/
        public bool Lookup(CSemanticChecker checker, CType typeSrc, EXPR obj, ParentSymbol symWhere, Name name, int arity, MemLookFlags flags)
        {
            Debug.Assert((flags & ~MemLookFlags.All) == 0);
            Debug.Assert(obj == null || obj.type != null);
            Debug.Assert(typeSrc.IsAggregateType() || typeSrc.IsTypeParameterType());
            Debug.Assert(checker != null);

            _prgtype = _rgtypeStart;

            // Save the inputs for error handling, etc.
            _pSemanticChecker = checker;
            _pSymbolLoader    = checker.GetSymbolLoader();
            _typeSrc          = typeSrc;
            _obj      = (obj != null && !obj.isCLASS()) ? obj : null;
            _symWhere = symWhere;
            _name     = name;
            _arity    = arity;
            _flags    = flags;

            if ((_flags & MemLookFlags.BaseCall) != 0)
            {
                _typeQual = null;
            }
            else if ((_flags & MemLookFlags.Ctor) != 0)
            {
                _typeQual = _typeSrc;
            }
            else if (obj != null)
            {
                _typeQual = (CType)obj.type;
            }
            else
            {
                _typeQual = null;
            }

            // Determine what to search.
            AggregateType typeCls1  = null;
            AggregateType typeIface = null;
            TypeArray     ifaces    = BSYMMGR.EmptyTypeArray();
            AggregateType typeCls2  = null;

            if (typeSrc.IsTypeParameterType())
            {
                Debug.Assert((_flags & (MemLookFlags.Ctor | MemLookFlags.NewObj | MemLookFlags.Operator | MemLookFlags.BaseCall | MemLookFlags.TypeVarsAllowed)) == 0);
                _flags  &= ~MemLookFlags.TypeVarsAllowed;
                ifaces   = typeSrc.AsTypeParameterType().GetInterfaceBounds();
                typeCls1 = typeSrc.AsTypeParameterType().GetEffectiveBaseClass();
                if (ifaces.size > 0 && typeCls1.isPredefType(PredefinedType.PT_OBJECT))
                {
                    typeCls1 = null;
                }
            }
            else if (!typeSrc.isInterfaceType())
            {
                typeCls1 = typeSrc.AsAggregateType();

                if (typeCls1.IsWindowsRuntimeType())
                {
                    ifaces = typeCls1.GetWinRTCollectionIfacesAll(GetSymbolLoader());
                }
            }
            else
            {
                Debug.Assert(typeSrc.isInterfaceType());
                Debug.Assert((_flags & (MemLookFlags.Ctor | MemLookFlags.NewObj | MemLookFlags.Operator | MemLookFlags.BaseCall)) == 0);
                typeIface = typeSrc.AsAggregateType();
                ifaces    = typeIface.GetIfacesAll();
            }

            if (typeIface != null || ifaces.size > 0)
            {
                typeCls2 = GetSymbolLoader().GetReqPredefType(PredefinedType.PT_OBJECT);
            }

            // Search the class first (except possibly object).
            if (typeCls1 == null || LookupInClass(typeCls1, ref typeCls2))
            {
                // Search the interfaces.
                if ((typeIface != null || ifaces.size > 0) && LookupInInterfaces(typeIface, ifaces) && typeCls2 != null)
                {
                    // Search object last.
                    Debug.Assert(typeCls2 != null && typeCls2.isPredefType(PredefinedType.PT_OBJECT));

                    AggregateType result = null;
                    LookupInClass(typeCls2, ref result);
                }
            }

            // if we are requested with extension methods
            _results = new CMemberLookupResults(GetAllTypes(), _name);

            return(!FError());
        }
Esempio n. 45
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(GetErrorContext());

                if (atsDst == null)
                {
                    return(false);
                }

                // 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);
                }

                int       cnubDst;
                int       cnubSrc;
                CType     typeDstBase     = nubDst.StripNubs(out cnubDst);
                EXPRCLASS exprTypeDstBase = GetExprFactory().MakeClass(typeDstBase);
                CType     typeSrcBase     = typeSrc.StripNubs(out cnubSrc);

                ConversionFunc pfn = (flags & CONVERTTYPE.ISEXPLICIT) != 0 ?
                                     (ConversionFunc)binder.BindExplicitConversion :
                                     (ConversionFunc)binder.BindImplicitConversion;

                if (cnubSrc == 0)
                {
                    Debug.Assert(typeSrc == typeSrcBase);

                    // The null type can be implicitly converted to T? as the default value.
                    if (typeSrc.IsNullType())
                    {
                        // 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(0x00, 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)
                        {
                            // UNDONE: This is a premature realization of the nullable conversion as
                            // UNDONE: a constructor.  Rather than flagging this, can we simply emit it
                            // UNDONE: as a cast node and have the operator rewrite pass turn it into
                            // UNDONE: a constructor call?
                            EXPRUSERDEFINEDCONVERSION exprUDC = exprTmp.kind == ExpressionKind.EK_USERDEFINEDCONVERSION ? exprTmp.asUSERDEFINEDCONVERSION() : null;
                            if (exprUDC != null)
                            {
                                exprTmp = exprUDC.UserDefinedCall;
                            }

                            // This logic is left over from the days when T?? was legal. However there are error/LAF cases that necessitates the loop.
                            // typeSrc is not nullable so just wrap the required number of times. For legal code (cnubDst <= 0).

                            for (int i = 0; i < cnubDst; i++)
                            {
                                exprTmp = binder.BindNubNew(exprTmp);
                                exprTmp.asCALL().nubLiftKind = NullableCallLiftKind.NullableConversionConstructor;
                            }
                            if (exprUDC != null)
                            {
                                exprUDC.UserDefinedCall = exprTmp;
                                exprUDC.setType((CType)exprTmp.type);
                                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);
                    EXPRMEMGRP   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().MakeClass(typeDstBase);

                    bool convertible;
                    if (0 != (flags & CONVERTTYPE.ISEXPLICIT))
                    {
                        convertible = binder.BindExplicitConversion(arg1, arg1.type, arg2, typeDstBase, out arg1, flags | CONVERTTYPE.NOUDC);
                    }
                    else
                    {
                        convertible = binder.BindImplicitConversion(arg1, arg1.type, arg2, typeDstBase, out arg1, flags | CONVERTTYPE.NOUDC);
                    }
                    if (!convertible)
                    {
                        VSFAIL("bind(Im|Ex)plicitConversion failed unexpectedly");
                        return(false);
                    }

                    exprDst.castOfNonLiftedResultToLiftedType = binder.mustCast(arg1, nubDst, 0);
                    exprDst.nubLiftKind  = NullableCallLiftKind.NullableConversion;
                    exprDst.pConversions = exprDst.castOfNonLiftedResultToLiftedType;
                    exprDest             = exprDst;
                }

                return(true);
            }
Esempio n. 46
0
        protected void FixLiftedUserDefinedBinaryOperators(EXPRBINOP expr, ref EXPR pp1, ref EXPR pp2)
        {
            // If we have lifted T1 op T2 to T1? op T2?, and we have an expression T1 op T2? or T1? op T2 then
            // we need to ensure that the unlifted actual arguments are promoted to their nullable CType.
            Debug.Assert(expr != null);
            Debug.Assert(pp1 != null);
            Debug.Assert(pp1 != null);
            Debug.Assert(pp2 != null);
            Debug.Assert(pp2 != null);
            MethodSymbol method = expr.GetUserDefinedCallMethod().Meth();
            EXPR orig1 = expr.GetOptionalLeftChild();
            EXPR orig2 = expr.GetOptionalRightChild();
            Debug.Assert(orig1 != null && orig2 != null);
            EXPR new1 = pp1;
            EXPR new2 = pp2;
            CType fptype1 = method.Params.Item(0);
            CType fptype2 = method.Params.Item(1);
            CType aatype1 = orig1.type;
            CType aatype2 = orig2.type;
            // Is the operator even a candidate for lifting?
            if (fptype1.IsNullableType() || fptype2.IsNullableType() ||
                !fptype1.IsAggregateType() || !fptype2.IsAggregateType() ||
                !fptype1.AsAggregateType().getAggregate().IsValueType() ||
                !fptype2.AsAggregateType().getAggregate().IsValueType())
            {
                return;
            }
            CType nubfptype1 = GetSymbolLoader().GetTypeManager().GetNullable(fptype1);
            CType nubfptype2 = GetSymbolLoader().GetTypeManager().GetNullable(fptype2);
            // If we have null op X, or T1 op T2?, or T1 op null, lift first arg to T1?
            if (aatype1.IsNullType() || aatype1 == fptype1 && (aatype2 == nubfptype2 || aatype2.IsNullType()))
            {
                new1 = GenerateCall(PREDEFMETH.PM_EXPRESSION_CONVERT, new1, CreateTypeOf(nubfptype1));
            }

            // If we have X op null, or T1? op T2, or null op T2, lift second arg to T2?
            if (aatype2.IsNullType() || aatype2 == fptype2 && (aatype1 == nubfptype1 || aatype1.IsNullType()))
            {
                new2 = GenerateCall(PREDEFMETH.PM_EXPRESSION_CONVERT, new2, CreateTypeOf(nubfptype2));
            }
            pp1 = new1;
            pp2 = new2;
        }
Esempio n. 47
0
        protected virtual EXPR GenerateUserDefinedConversion(EXPRUSERDEFINEDCONVERSION pExpr, EXPR pArgument)
        {
            EXPR pCastCall = pExpr.UserDefinedCall;
            EXPR pCastArgument = pExpr.Argument;
            EXPR pConversionSource = null;

            if (!isEnumToDecimalConversion(pArgument.type, pExpr.type) && IsNullableValueAccess(pCastArgument, pArgument))
            {
                // We have an implicit conversion of nullable CType to the value CType, generate a convert node for it.
                pConversionSource = GenerateValueAccessConversion(pArgument);
            }
            else if (pCastCall.isCALL() && pCastCall.asCALL().pConversions != null)
            {
                EXPR pUDConversion = pCastCall.asCALL().pConversions;
                if (pUDConversion.isCALL())
                {
                    EXPR pUDConversionArgument = pUDConversion.asCALL().GetOptionalArguments();
                    if (IsNullableValueAccess(pUDConversionArgument, pArgument))
                    {
                        pConversionSource = GenerateValueAccessConversion(pArgument);
                    }
                    else
                    {
                        pConversionSource = Visit(pUDConversionArgument);
                    }
                    return GenerateConversionWithSource(pConversionSource, pCastCall.type, pCastCall.asCALL().isChecked());
                }
                else
                {
                    // This can happen if we have a UD conversion from C to, say, int, 
                    // and we have an explicit cast to decimal?. The conversion should
                    // then be bound as two chained user-defined conversions.
                    Debug.Assert(pUDConversion.isUSERDEFINEDCONVERSION());
                    // Just recurse.
                    return GenerateUserDefinedConversion(pUDConversion.asUSERDEFINEDCONVERSION(), pArgument);
                }
            }
            else
            {
                pConversionSource = Visit(pCastArgument);
            }
            return GenerateUserDefinedConversion(pCastArgument, pExpr.type, pConversionSource, pExpr.UserDefinedCallMethod);
        }
Esempio n. 48
0
 protected EXPRCALL GenerateCall(PREDEFMETH pdm, EXPR arg1, EXPR arg2, EXPR arg3, EXPR arg4)
 {
     MethodSymbol method = GetPreDefMethod(pdm);
     if (method == null)
         return null;
     AggregateType expressionType = GetSymbolLoader().GetOptPredefTypeErr(PredefinedType.PT_EXPRESSION, true);
     EXPR args = GetExprFactory().CreateList(arg1, arg2, arg3, arg4);
     MethWithInst mwi = new MethWithInst(method, expressionType);
     EXPRMEMGRP pMemGroup = GetExprFactory().CreateMemGroup(null, mwi);
     EXPRCALL call = GetExprFactory().CreateCall(0, mwi.Meth().RetType, args, pMemGroup, mwi);
     call.PredefinedMethod = pdm;
     return call;
 }
Esempio n. 49
0
 protected virtual EXPRARRINIT GenerateParamsArray(EXPR args, PredefinedType pt)
 {
     int parameterCount = ExpressionIterator.Count(args);
     AggregateType paramsArrayElementType = GetSymbolLoader().GetOptPredefTypeErr(pt, true);
     ArrayType paramsArrayType = GetSymbolLoader().GetTypeManager().GetArray(paramsArrayElementType, 1);
     EXPRCONSTANT paramsArrayArg = GetExprFactory().CreateIntegerConstant(parameterCount);
     EXPRARRINIT arrayInit = GetExprFactory().CreateArrayInit(EXPRFLAG.EXF_CANTBENULL, paramsArrayType, args, paramsArrayArg, null);
     arrayInit.dimSize = parameterCount;
     arrayInit.dimSizes = new int[] { arrayInit.dimSize }; // CLEANUP: Why isn't this done by the factory?
     return arrayInit;
 }
Esempio n. 50
0
 protected EXPRCALL GenerateCall(PREDEFMETH pdm, EXPR arg1)
 {
     MethodSymbol method = GetPreDefMethod(pdm);
     // this should be enforced in an earlier pass and the tranform pass should not 
     // be handeling this error
     if (method == null)
         return null;
     AggregateType expressionType = GetSymbolLoader().GetOptPredefTypeErr(PredefinedType.PT_EXPRESSION, true);
     MethWithInst mwi = new MethWithInst(method, expressionType);
     EXPRMEMGRP pMemGroup = GetExprFactory().CreateMemGroup(null, mwi);
     EXPRCALL call = GetExprFactory().CreateCall(0, mwi.Meth().RetType, arg1, pMemGroup, mwi);
     call.PredefinedMethod = pdm;
     return call;
 }
Esempio n. 51
0
        protected virtual EXPR GenerateConstant(EXPR expr)
        {
            EXPRFLAG flags = 0;

            AggregateType pObject = GetSymbolLoader().GetReqPredefType(PredefinedType.PT_OBJECT, true);

            if (expr.type.IsNullType())
            {
                EXPRTYPEOF pTypeOf = CreateTypeOf(pObject);
                return GenerateCall(PREDEFMETH.PM_EXPRESSION_CONSTANT_OBJECT_TYPE, expr, pTypeOf);
            }

            AggregateType stringType = GetSymbolLoader().GetReqPredefType(PredefinedType.PT_STRING, true);
            if (expr.type != stringType)
            {
                flags = EXPRFLAG.EXF_BOX;
            }

            EXPRCLASS objectType = GetExprFactory().MakeClass(pObject);
            EXPRCAST cast = GetExprFactory().CreateCast(flags, objectType, expr);
            EXPRTYPEOF pTypeOf2 = CreateTypeOf(expr.type);

            return GenerateCall(PREDEFMETH.PM_EXPRESSION_CONSTANT_OBJECT_TYPE, cast, pTypeOf2);
        }
Esempio n. 52
0
        protected virtual EXPR GenerateIndexList(EXPR oldIndices)
        {
            CType intType = symbolLoader.GetReqPredefType(PredefinedType.PT_INT, true);

            EXPR newIndices = null;
            EXPR newIndicesTail = newIndices;
            for (ExpressionIterator it = new ExpressionIterator(oldIndices); !it.AtEnd(); it.MoveNext())
            {
                EXPR newIndex = it.Current();
                if (newIndex.type != intType)
                {
                    EXPRCLASS exprType = expressionFactory.CreateClass(intType, null, null);
                    newIndex = expressionFactory.CreateCast(EXPRFLAG.EXF_INDEXEXPR, exprType, newIndex);
                    newIndex.flags |= EXPRFLAG.EXF_CHECKOVERFLOW;
                }
                EXPR rewrittenIndex = Visit(newIndex);
                expressionFactory.AppendItemToList(rewrittenIndex, ref newIndices, ref newIndicesTail);
            }
            return newIndices;
        }
Esempio n. 53
0
 protected virtual EXPR GenerateUserDefinedConversion(EXPR arg, CType type, MethWithInst method)
 {
     EXPR target = Visit(arg);
     return GenerateUserDefinedConversion(arg, type, target, method);
 }
Esempio n. 54
0
 protected bool IsNullableValueAccess(EXPR pExpr, EXPR pObject)
 {
     Debug.Assert(pExpr != null);
     return pExpr.isPROP() && (pExpr.asPROP().GetMemberGroup().GetOptionalObject() == pObject) && pObject.type.IsNullableType();
 }
Esempio n. 55
0
        protected virtual EXPR GenerateUserDefinedConversion(EXPR arg, CType CType, EXPR target, MethWithInst method)
        {
            // The user-defined explicit conversion from enum? to decimal or decimal? requires
            // that we convert the enum? to its nullable underlying CType.
            if (isEnumToDecimalConversion(arg.type, CType))
            {
                // Special case: If we have enum? to decimal? then we need to emit 
                // a conversion from enum? to its nullable underlying CType first.
                // This is unfortunate; we ought to reorganize how conversions are 
                // represented in the EXPR tree so that this is more transparent.

                // converting an enum to its underlying CType never fails, so no need to check it.
                CType underlyingType = arg.type.StripNubs().underlyingEnumType();
                CType nullableType = GetSymbolLoader().GetTypeManager().GetNullable(underlyingType);
                EXPR typeofNubEnum = CreateTypeOf(nullableType);
                target = GenerateCall(PREDEFMETH.PM_EXPRESSION_CONVERT, target, typeofNubEnum);
            }

            // If the methodinfo does not return the target CType AND this is not a lifted conversion
            // from one value CType to another, then we need to wrap the whole thing in another conversion,
            // e.g. if we have a user-defined conversion from int to S? and we have (S)myint, then we need to generate 
            // Convert(Convert(myint, typeof(S?), op_implicit), typeof(S))

            CType pMethodReturnType = GetSymbolLoader().GetTypeManager().SubstType(method.Meth().RetType,
                method.GetType(), method.TypeArgs);
            bool fDontLiftReturnType = (pMethodReturnType == CType || (IsNullableValueType(arg.type) && IsNullableValueType(CType)));

            EXPR typeofInner = CreateTypeOf(fDontLiftReturnType ? CType : pMethodReturnType);
            EXPR methodInfo = GetExprFactory().CreateMethodInfo(method);
            PREDEFMETH pdmInner = arg.isChecked() ? PREDEFMETH.PM_EXPRESSION_CONVERTCHECKED_USER_DEFINED : PREDEFMETH.PM_EXPRESSION_CONVERT_USER_DEFINED;
            EXPR callUserDefinedConversion = GenerateCall(pdmInner, target, typeofInner, methodInfo);

            if (fDontLiftReturnType)
            {
                return callUserDefinedConversion;
            }

            PREDEFMETH pdmOuter = arg.isChecked() ? PREDEFMETH.PM_EXPRESSION_CONVERTCHECKED : PREDEFMETH.PM_EXPRESSION_CONVERT;
            EXPR typeofOuter = CreateTypeOf(CType);
            return GenerateCall(pdmOuter, callUserDefinedConversion, typeofOuter);
        }
Esempio n. 56
0
 protected bool IsDelegateConstructorCall(EXPR pExpr)
 {
     Debug.Assert(pExpr != null);
     if (!pExpr.isCALL())
     {
         return false;
     }
     EXPRCALL pCall = pExpr.asCALL();
     return pCall.mwi.Meth() != null &&
         pCall.mwi.Meth().IsConstructor() &&
         pCall.type.isDelegateType() &&
         pCall.GetOptionalArguments() != null &&
         pCall.GetOptionalArguments().isLIST() &&
         pCall.GetOptionalArguments().asLIST().GetOptionalNextListNode().kind == ExpressionKind.EK_FUNCPTR;
 }
Esempio n. 57
0
 protected EXPR DestroyWraps(EXPRBOUNDLAMBDA anonmeth, EXPR sequence)
 {
     for (Symbol sym = anonmeth.ArgumentScope(); sym != null; sym = sym.nextChild)
     {
         if (!sym.IsLocalVariableSymbol())
         {
             continue;
         }
         LocalVariableSymbol local = sym.AsLocalVariableSymbol();
         if (local.isThis)
         {
             continue;
         }
         Debug.Assert(local.wrap != null);
         Debug.Assert(anonmeth.OptionalBody != null);
         EXPR freeWrap = GetExprFactory().CreateWrap(anonmeth.OptionalBody.OptionalScopeSymbol, local.wrap);
         sequence = GetExprFactory().CreateReverseSequence(sequence, freeWrap);
     }
     return sequence;
 }
Esempio n. 58
0
 protected virtual EXPR GenerateQuestionMarkOperand(EXPR pExpr)
 {
     Debug.Assert(pExpr != null);
     // We must not optimize away compiler-generated reference casts because
     // the expression tree API insists that the CType of both sides be identical.
     if (pExpr.isCAST())
     {
         return GenerateConversion(pExpr.asCAST().GetArgument(), pExpr.type, pExpr.isChecked());
     }
     return Visit(pExpr);
 }
Esempio n. 59
0
        /////////////////////////////////////////////////////////////////////////////////

        internal SymWithType LookupMember(
            string name,
            EXPR callingObject,
            ParentSymbol context,
            int arity,
            MemberLookup mem,
            bool allowSpecialNames,
            bool requireInvocable)
        {
            CType type = callingObject.type;

            if (type.IsArrayType())
            {
                type = _semanticChecker.GetSymbolLoader().GetReqPredefType(PredefinedType.PT_ARRAY);
            }
            if (type.IsNullableType())
            {
                type = type.AsNullableType().GetAts(_semanticChecker.GetSymbolLoader().GetErrorContext());
            }

            if (!mem.Lookup(
                _semanticChecker,
                type,
                callingObject,
                context,
                GetName(name),
                arity,
                MemLookFlags.TypeVarsAllowed |
                    (allowSpecialNames ? 0 : MemLookFlags.UserCallable) |
                    (name == SpecialNames.Indexer ? MemLookFlags.Indexer : 0) |
                    (name == SpecialNames.Constructor ? MemLookFlags.Ctor : 0) |
                    (requireInvocable ? MemLookFlags.MustBeInvocable : 0)))
            {
                return null;
            }
            return mem.SwtFirst();
        }
Esempio n. 60
0
            /*
             * BindImplicitConversion
             *
             * This is a complex routine with complex parameters. Generally, this should
             * be called through one of the helper methods that insulates you
             * from the complexity of the interface. This routine handles all the logic
             * associated with implicit conversions.
             *
             * exprSrc - the expression being converted. Can be null if only type conversion
             *           info is being supplied.
             * typeSrc - type of the source
             * typeDest - type of the destination
             * exprDest - returns an expression of the src converted to the dest. If null, we
             *            only care about whether the conversion can be attempted, not the
             *            expression tree.
             * flags    - flags possibly customizing the conversions allowed. E.g., can suppress
             *            user-defined conversions.
             *
             * returns true if the conversion can be made, false if not.
             */
            public bool Bind()
            {
                // 13.1 Implicit conversions
                //
                // The following conversions are classified as implicit conversions:
                //
                // *   Identity conversions
                // *   Implicit numeric conversions
                // *   Implicit enumeration conversions
                // *   Implicit reference conversions
                // *   Boxing conversions
                // *   Implicit type parameter conversions
                // *   Implicit constant expression conversions
                // *   User-defined implicit conversions
                // *   Implicit conversions from an anonymous method expression to a compatible delegate type
                // *   Implicit conversion from a method group to a compatible delegate type
                // *   Conversions from the null type (11.2.7) to any nullable type
                // *   Implicit nullable conversions
                // *   Lifted user-defined implicit conversions
                //
                // Implicit conversions can occur in a variety of situations, including function member invocations
                // (14.4.3), cast expressions (14.6.6), and assignments (14.14).

                // Can't convert to or from the error type.
                if (typeSrc == null || typeDest == null || typeDest.IsNeverSameType())
                {
                    return(false);
                }

                Debug.Assert(typeSrc != null && typeDest != null);         // types must be supplied.
                Debug.Assert(exprSrc == null || typeSrc == exprSrc.type);  // type of source should be correct if source supplied
                Debug.Assert(!needsExprDest || exprSrc != null);           // need source expr to create dest expr

                switch (typeDest.GetTypeKind())
                {
                case TypeKind.TK_ErrorType:
                    Debug.Assert(typeDest.AsErrorType().HasTypeParent() || typeDest.AsErrorType().HasNSParent());
                    if (typeSrc != typeDest)
                    {
                        return(false);
                    }
                    if (needsExprDest)
                    {
                        exprDest = exprSrc;
                    }
                    return(true);

                case TypeKind.TK_NullType:
                    // Can only convert to the null type if src is null.
                    if (!typeSrc.IsNullType())
                    {
                        return(false);
                    }
                    if (needsExprDest)
                    {
                        exprDest = exprSrc;
                    }
                    return(true);

                case TypeKind.TK_MethodGroupType:
                    VSFAIL("Something is wrong with Type.IsNeverSameType()");
                    return(false);

                case TypeKind.TK_NaturalIntegerType:
                case TypeKind.TK_ArgumentListType:
                    return(typeSrc == typeDest);

                case TypeKind.TK_VoidType:
                    return(false);

                default:
                    break;
                }

                if (typeSrc.IsErrorType())
                {
                    Debug.Assert(!typeDest.IsErrorType());
                    return(false);
                }

                // 13.1.1 Identity conversion
                //
                // An identity conversion converts from any type to the same type. This conversion exists only
                // such that an entity that already has a required type can be said to be convertible to that type.

                if (typeSrc == typeDest &&
                    ((flags & CONVERTTYPE.ISEXPLICIT) == 0 || (!typeSrc.isPredefType(PredefinedType.PT_FLOAT) && !typeSrc.isPredefType(PredefinedType.PT_DOUBLE))))
                {
                    if (needsExprDest)
                    {
                        exprDest = exprSrc;
                    }
                    return(true);
                }

                if (typeDest.IsNullableType())
                {
                    return(BindNubConversion(typeDest.AsNullableType()));
                }

                if (typeSrc.IsNullableType())
                {
                    return(bindImplicitConversionFromNullable(typeSrc.AsNullableType()));
                }

                if ((flags & CONVERTTYPE.ISEXPLICIT) != 0)
                {
                    flags |= CONVERTTYPE.NOUDC;
                }

                // Get the fundamental types of destination.
                FUNDTYPE ftDest = typeDest.fundType();

                Debug.Assert(ftDest != FUNDTYPE.FT_NONE || typeDest.IsParameterModifierType());

                switch (typeSrc.GetTypeKind())
                {
                default:
                    VSFAIL("Bad type symbol kind");
                    break;

                case TypeKind.TK_MethodGroupType:
                    if (exprSrc.isMEMGRP())
                    {
                        EXPRCALL outExpr;
                        bool     retVal = binder.BindGrpConversion(exprSrc.asMEMGRP(), typeDest, needsExprDest, out outExpr, false);
                        exprDest = outExpr;
                        return(retVal);
                    }
                    return(false);

                case TypeKind.TK_VoidType:
                case TypeKind.TK_ErrorType:
                case TypeKind.TK_ParameterModifierType:
                case TypeKind.TK_ArgumentListType:
                    return(false);

                case TypeKind.TK_NullType:
                    if (bindImplicitConversionFromNull())
                    {
                        return(true);
                    }
                    // If not, try user defined implicit conversions.
                    break;

                case TypeKind.TK_ArrayType:
                    if (bindImplicitConversionFromArray())
                    {
                        return(true);
                    }
                    // If not, try user defined implicit conversions.
                    break;

                case TypeKind.TK_PointerType:
                    if (bindImplicitConversionFromPointer())
                    {
                        return(true);
                    }
                    // If not, try user defined implicit conversions.
                    break;

                case TypeKind.TK_TypeParameterType:
                    if (bindImplicitConversionFromTypeVar(typeSrc.AsTypeParameterType()))
                    {
                        return(true);
                    }
                    // If not, try user defined implicit conversions.
                    break;

                case TypeKind.TK_AggregateType:
                    // TypeReference and ArgIterator can't be boxed (or converted to anything else)
                    if (typeSrc.isSpecialByRefType())
                    {
                        return(false);
                    }
                    if (bindImplicitConversionFromAgg(typeSrc.AsAggregateType()))
                    {
                        return(true);
                    }
                    // If not, try user defined implicit conversions.
                    break;
                }

                // !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
                // RUNTIME BINDER ONLY CHANGE
                // !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
                //
                // Every incoming dynamic operand should be implicitly convertible
                // to any type that it is an instance of.

                if (exprSrc != null &&
                    exprSrc.RuntimeObject != null &&
                    typeDest.AssociatedSystemType.IsInstanceOfType(exprSrc.RuntimeObject) &&
                    binder.GetSemanticChecker().CheckTypeAccess(typeDest, binder.Context.ContextForMemberLookup()))
                {
                    if (needsExprDest)
                    {
                        binder.bindSimpleCast(exprSrc, exprTypeDest, out exprDest, exprSrc.flags & EXPRFLAG.EXF_CANTBENULL);
                    }
                    return(true);
                }

                // !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
                // END RUNTIME BINDER ONLY CHANGE
                // !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!

                // 13.1.8 User-defined implicit conversions
                //
                // A user-defined implicit conversion consists of an optional standard implicit conversion,
                // followed by execution of a user-defined implicit conversion operator, followed by another
                // optional standard implicit conversion. The exact rules for evaluating user-defined
                // conversions are described in 13.4.3.

                if (0 == (flags & CONVERTTYPE.NOUDC))
                {
                    return(binder.bindUserDefinedConversion(exprSrc, typeSrc, typeDest, needsExprDest, out exprDest, true));
                }

                // No conversion was found.

                return(false);
            }