Пример #1
0
        private EXPRMULTI BindLiftedIncOp(ExpressionKind ek, EXPRFLAG flags, EXPR arg, UnaOpFullSig uofs)
        {
            Debug.Assert(ek == ExpressionKind.EK_ADD || ek == ExpressionKind.EK_SUB);
            Debug.Assert(uofs.isLifted());

            NullableType type = uofs.GetType().AsNullableType();
            Debug.Assert(arg != null);
            EXPR exprVal;

#if ! CSEE
            EXPRMULTIGET exprGet = GetExprFactory().CreateMultiGet(EXPRFLAG.EXF_ASSGOP, arg.type, null);
            exprVal = exprGet;
#else
            exprVal = arg;
#endif

            EXPR nonLiftedResult = null;
            EXPR nonLiftedArg = exprVal;

            // We want to give the lifted argument as the binop, but use the non-lifted argument as the 
            // argument of the call.
            //Debug.Assert(uofs.LiftArg() || type.IsValType());
            nonLiftedArg = mustCast(nonLiftedArg, type.GetUnderlyingType());
            nonLiftedResult = BindIncOpCore(ek, flags, nonLiftedArg, type.GetUnderlyingType());
            exprVal = mustCast(exprVal, type);
            EXPRUNARYOP exprRes = GetExprFactory().CreateUnaryOp((ek == ExpressionKind.EK_ADD) ? ExpressionKind.EK_INC : ExpressionKind.EK_DEC, arg.type/* type */, exprVal);
            mustCast(mustCast(nonLiftedResult, type), arg.type);
            exprRes.flags |= flags;

            EXPRMULTI exprMulti = GetExprFactory().CreateMulti(EXPRFLAG.EXF_ASSGOP | flags, arg.type, arg, exprRes);

#if ! CSEE
            exprGet.SetOptionalMulti(exprMulti);
#endif
            return exprMulti;
        }
Пример #2
0
        private EXPRMULTI BindNonliftedIncOp(ExpressionKind ek, EXPRFLAG flags, EXPR arg, UnaOpFullSig uofs)
        {
            Debug.Assert(ek == ExpressionKind.EK_ADD || ek == ExpressionKind.EK_SUB);
            Debug.Assert(!uofs.isLifted());

            Debug.Assert(arg != null);
            EXPR exprVal;
#if ! CSEE
            EXPRMULTIGET exprGet = GetExprFactory().CreateMultiGet(EXPRFLAG.EXF_ASSGOP, arg.type, null);
            exprVal = exprGet;
#else
            exprVal = arg;
#endif

            CType type = uofs.GetType();
            Debug.Assert(!type.IsNullableType());

            // These used to be converts, but we're making them casts now - this is because
            // we need to remove the ability to call inc(sbyte) etc for all types smaller than int. 
            // Note however, that this will give us different error messages on compile time versus runtime
            // for checked increments.
            //
            // Also, we changed it so that we now generate the cast to and from enum for enum increments.
            exprVal = mustCast(exprVal, type);
            exprVal = BindIncOpCore(ek, flags, exprVal, type);
            EXPR op = mustCast(exprVal, arg.type, CONVERTTYPE.NOUDC);

            EXPRMULTI exprMulti = GetExprFactory().CreateMulti(EXPRFLAG.EXF_ASSGOP | flags, arg.type, arg, op);

#if ! CSEE
            exprGet.SetOptionalMulti(exprMulti);
#endif
            return exprMulti;
        }
Пример #3
0
        /*
            Handles standard increment and decrement operators.
        */
        private EXPR BindIncOp(ExpressionKind ek, EXPRFLAG flags, EXPR arg, UnaOpFullSig uofs)
        {
            Debug.Assert(ek == ExpressionKind.EK_ADD || ek == ExpressionKind.EK_SUB);
            if (!checkLvalue(arg, CheckLvalueKind.Increment))
            {
                EXPR rval = GetExprFactory().CreateBinop(ek, arg.type, arg, null);
                rval.SetError();
                return rval;
            }

            CType typeRaw = uofs.GetType().StripNubs();

            FUNDTYPE ft = typeRaw.fundType();
            if (ft == FUNDTYPE.FT_R8 || ft == FUNDTYPE.FT_R4)
            {
                flags = ~EXPRFLAG.EXF_CHECKOVERFLOW;
            }

            if (uofs.isLifted())
            {
                return BindLiftedIncOp(ek, flags, arg, uofs);
            }
            else
            {
                return BindNonliftedIncOp(ek, flags, arg, uofs);
            }
        }
Пример #4
0
        /*
            Determine which UnaOpSig is better for overload resolution.
            Returns negative if iuos1 is better, positive if iuos2 is better, 0 if neither.
        */
        private int WhichUofsIsBetter(UnaOpFullSig uofs1, UnaOpFullSig uofs2, CType typeArg)
        {
            BetterType bt;

            if (uofs1.FPreDef() && uofs2.FPreDef())
            {
                // Faster to compare predefs.
                bt = WhichTypeIsBetter(uofs1.pt, uofs2.pt, typeArg);
            }
            else
            {
                bt = WhichTypeIsBetter(uofs1.GetType(), uofs2.GetType(), typeArg);
            }

            switch (bt)
            {
                default:
                    VSFAIL("Shouldn't happen");
                    return 0;
                case BetterType.Same:
                case BetterType.Neither:
                    return 0;
                case BetterType.Left:
                    return -1;
                case BetterType.Right:
                    return +1;
            }
        }
Пример #5
0
        private EXPR BindLiftedStandardUnop(ExpressionKind ek, EXPRFLAG flags, EXPR arg, UnaOpFullSig uofs)
        {
            NullableType type = uofs.GetType().AsNullableType();
            Debug.Assert(arg != null && arg.type != null);
            if (arg.type.IsNullType())
            {
                return BadOperatorTypesError(ek, arg, null, type);
            }

            EXPR pArgument = null;
            EXPR nonLiftedArg = null;

            LiftArgument(arg, uofs.GetType(), uofs.Convert(), out pArgument, out nonLiftedArg);

            // Now call the function with the non lifted arguments to report errors.
            EXPR nonLiftedResult = uofs.pfn(ek, flags, nonLiftedArg);
            EXPRUNARYOP exprRes = GetExprFactory().CreateUnaryOp(ek, type, pArgument);
            mustCast(nonLiftedResult, type, 0);
            exprRes.flags |= flags;

            Debug.Assert((exprRes.flags & EXPRFLAG.EXF_LVALUE) == 0);
            return exprRes;
        }
Пример #6
0
        /////////////////////////////////////////////////////////////////////////////////

        private bool FindApplicableSignatures(
                EXPR pArgument,
                UnaOpMask unaryOpMask,
                List<UnaOpFullSig> pSignatures)
        {
            // All callers should already assert this to be the case.
            Debug.Assert(pArgument != null);
            Debug.Assert(pArgument.type != null);

            long iuosMinLift = GetSymbolLoader().FCanLift() ? 0 : g_rguos.Length;

            CType pArgumentType = pArgument.type;
            CType pRawType = pArgumentType.StripNubs();
            PredefinedType pt = pArgumentType.isPredefined() ? pArgumentType.getPredefType() : PredefinedType.PT_COUNT;
            PredefinedType ptRaw = pRawType.isPredefined() ? pRawType.getPredefType() : PredefinedType.PT_COUNT;

            for (int index = 0; index < g_rguos.Length; index++)
            {
                UnaOpSig uos = g_rguos[index];
                if ((uos.grfuom & unaryOpMask) == 0)
                {
                    continue;
                }

                ConvKind cv = GetConvKind(pt, g_rguos[index].pt);
                CType typeSig = null;

                switch (cv)
                {
                    default:
                        VSFAIL("Shouldn't happen!");
                        continue;

                    case ConvKind.None:
                        continue;

                    case ConvKind.Explicit:
                        if (!pArgument.isCONSTANT_OK())
                        {
                            continue;
                        }
                        if (canConvert(pArgument, typeSig = GetOptPDT(uos.pt)))
                        {
                            break;
                        }
                        if (index < iuosMinLift)
                        {
                            continue;
                        }
                        typeSig = GetSymbolLoader().GetTypeManager().GetNullable(typeSig);
                        if (!canConvert(pArgument, typeSig))
                        {
                            continue;
                        }
                        break;

                    case ConvKind.Unknown:
                        if (canConvert(pArgument, typeSig = GetOptPDT(uos.pt)))
                        {
                            break;
                        }
                        if (index < iuosMinLift)
                        {
                            continue;
                        }
                        typeSig = GetSymbolLoader().GetTypeManager().GetNullable(typeSig);
                        if (!canConvert(pArgument, typeSig))
                        {
                            continue;
                        }
                        break;

                    case ConvKind.Implicit:
                        break;

                    case ConvKind.Identity:
                        {
                            UnaOpFullSig result = new UnaOpFullSig(this, uos);
                            if (result.GetType() != null)
                            {
                                pSignatures.Add(result);
                                return true;
                            }
                        }
                        break;
                }

                if (typeSig != null && typeSig.IsNullableType())
                {
                    // Need to use a lifted signature.
                    LiftFlags grflt = LiftFlags.None;

                    switch (GetConvKind(ptRaw, uos.pt))
                    {
                        default:
                            grflt = grflt | LiftFlags.Convert1;
                            break;
                        case ConvKind.Implicit:
                        case ConvKind.Identity:
                            grflt = grflt | LiftFlags.Lift1;
                            break;
                    }

                    pSignatures.Add(new UnaOpFullSig(typeSig, uos.pfn, grflt, uos.fnkind));

                    // NOTE: Can't skip any if we use the lifted signature because the
                    // type might convert to int? and to long (but not to int) in which
                    // case we should get an ambiguity. But we can skip the lifted ones....
                    iuosMinLift = index + uos.cuosSkip + 1;
                }
                else
                {
                    // Record it as applicable and skip accordingly.
                    UnaOpFullSig newResult = new UnaOpFullSig(this, uos);
                    if (newResult.GetType() != null)
                    {
                        pSignatures.Add(newResult);
                    }
                    index += uos.cuosSkip;
                }
            }
            return false;
        }